MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_thermal_emission.t
Go to the documentation of this file.
1! module mod_thermal_emission -- synthesize emission flux of some
2! thermal lines
3! EUV lines database:
4! 'He_II_304' 'Fe_IX_171' 'Fe_XXIV_193' 'Fe_XIV_211' 'Fe_XVI_335'
5! 'Fe_XVIII_94' 'Fe_XXI_131'
6! subroutines:
7! get_EUV: get local EUV emission intensity (for 1d, 2d and 3d)
8! get_SXR: get local Soft X-ray emission intensity (for 1d, 2d and 3d)
9
12 use mod_geometry
13 use mod_physics
14 use mod_comm_lib, only: mpistop
15
16 implicit none
17
18 integer :: n_aia
19 double precision :: t_aia(1:101)
20 double precision :: f_94(1:101),f_131(1:101),f_171(1:101)
21 double precision :: f_193(1:101),f_211(1:101),f_304(1:101)
22 double precision :: f_335(1:101)
23 integer :: n_iris
24 double precision :: t_iris(1:41)
25 double precision :: f_1354(1:41)
26 integer :: n_eis
27 double precision :: t_eis1(1:60),t_eis2(1:60)
28 double precision :: f_263(1:60),f_264(1:60),f_192(1:60),f_255(1:60)
29
30
31 double precision :: vec_xi1(1:3),vec_xi2(1:3),vec_los(1:3)
32
33 data n_aia / 101 /
34
35 data t_aia / 4. , 4.05, 4.1, 4.15, 4.2, 4.25, 4.3, 4.35, &
36 4.4, 4.45, 4.5, 4.55, 4.6, 4.65, 4.7, 4.75, &
37 4.8, 4.85, 4.9, 4.95, 5. , 5.05, 5.1, 5.15, &
38 5.2, 5.25, 5.3, 5.35, 5.4, 5.45, 5.5, 5.55, &
39 5.6, 5.65, 5.7, 5.75, 5.8, 5.85, 5.9, 5.95, &
40 6. , 6.05, 6.1, 6.15, 6.2, 6.25, 6.3, 6.35, &
41 6.4, 6.45, 6.5, 6.55, 6.6, 6.65, 6.7, 6.75, &
42 6.8, 6.85, 6.9, 6.95, 7. , 7.05, 7.1, 7.15, &
43 7.2, 7.25, 7.3, 7.35, 7.4, 7.45, 7.5, 7.55, &
44 7.6, 7.65, 7.7, 7.75, 7.8, 7.85, 7.9, 7.95, &
45 8. , 8.05, 8.1, 8.15, 8.2, 8.25, 8.3, 8.35, &
46 8.4, 8.45, 8.5, 8.55, 8.6, 8.65, 8.7, 8.75, &
47 8.8, 8.85, 8.9, 8.95, 9. /
48
49 data f_94 / 4.25022959d-37, 4.35880298d-36, 3.57054296d-35, 2.18175426d-34, &
50 8.97592571d-34, 2.68512961d-33, 7.49559346d-33, 2.11603751d-32, &
51 5.39752853d-32, 1.02935904d-31, 1.33822307d-31, 1.40884290d-31, &
52 1.54933156d-31, 2.07543102d-31, 3.42026227d-31, 6.31171444d-31, &
53 1.16559416d-30, 1.95360497d-30, 2.77818735d-30, 3.43552578d-30, &
54 4.04061803d-30, 4.75470982d-30, 5.65553769d-30, 6.70595782d-30, &
55 7.80680354d-30, 8.93247715d-30, 1.02618156d-29, 1.25979030d-29, &
56 1.88526483d-29, 3.62448572d-29, 7.50553279d-29, 1.42337571d-28, &
57 2.37912813d-28, 3.55232305d-28, 4.84985757d-28, 6.20662827d-28, &
58 7.66193687d-28, 9.30403645d-28, 1.10519802d-27, 1.25786927d-27, &
59 1.34362634d-27, 1.33185242d-27, 1.22302081d-27, 1.05677973d-27, &
60 9.23064720d-28, 8.78570994d-28, 8.02397416d-28, 5.87681142d-28, &
61 3.82272695d-28, 3.11492649d-28, 3.85736090d-28, 5.98893519d-28, &
62 9.57553548d-28, 1.46650267d-27, 2.10365847d-27, 2.79406671d-27, &
63 3.39420087d-27, 3.71077520d-27, 3.57296767d-27, 2.95114380d-27, &
64 2.02913103d-27, 1.13361825d-27, 5.13405629d-28, 2.01305089d-28, &
65 8.15781482d-29, 4.28366817d-29, 3.08701543d-29, 2.68693906d-29, &
66 2.51764203d-29, 2.41773103d-29, 2.33996083d-29, 2.26997246d-29, &
67 2.20316143d-29, 2.13810001d-29, 2.07424438d-29, 2.01149189d-29, &
68 1.94980213d-29, 1.88917920d-29, 1.82963583d-29, 1.77116920d-29, &
69 1.71374392d-29, 1.65740593d-29, 1.60214447d-29, 1.54803205d-29, &
70 1.49510777d-29, 1.44346818d-29, 1.39322305d-29, 1.34441897d-29, &
71 1.29713709d-29, 1.25132618d-29, 1.20686068d-29, 1.14226584d-29, &
72 1.09866413d-29, 1.05635524d-29, 1.01532444d-29, 9.75577134d-30, &
73 9.37102736d-30, 8.99873335d-30, 8.63860172d-30, 8.29051944d-30, &
74 7.95414793d-30 /
75
76 data f_131 / 3.18403601d-37, 3.22254703d-36, 2.61657920d-35, &
77 1.59575286d-34, 6.65779556d-34, 2.07015132d-33, &
78 6.05768615d-33, 1.76074833d-32, 4.52633001d-32, &
79 8.57121883d-32, 1.09184271d-31, 1.10207963d-31, &
80 1.11371658d-31, 1.29105226d-31, 1.80385897d-31, &
81 3.27295431d-31, 8.92002136d-31, 3.15214579d-30, &
82 9.73440787d-30, 2.22709702d-29, 4.01788984d-29, &
83 6.27471832d-29, 8.91764995d-29, 1.18725647d-28, &
84 1.52888040d-28, 2.05082946d-28, 3.47651873d-28, &
85 8.80482184d-28, 2.66533063d-27, 7.05805149d-27, &
86 1.46072515d-26, 2.45282476d-26, 3.55303726d-26, &
87 4.59075911d-26, 5.36503515d-26, 5.68444094d-26, &
88 5.47222296d-26, 4.81119761d-26, 3.85959059d-26, &
89 2.80383406d-26, 1.83977650d-26, 1.11182849d-26, &
90 6.50748885d-27, 3.96843481d-27, 2.61876319d-27, &
91 1.85525324d-27, 1.39717024d-27, 1.11504283d-27, &
92 9.38169611d-28, 8.24801234d-28, 7.43331919d-28, &
93 6.74537063d-28, 6.14495760d-28, 5.70805277d-28, &
94 5.61219786d-28, 6.31981777d-28, 9.19747307d-28, &
95 1.76795732d-27, 3.77985446d-27, 7.43166191d-27, &
96 1.19785603d-26, 1.48234676d-26, 1.36673114d-26, &
97 9.61047146d-27, 5.61209353d-27, 3.04779780d-27, &
98 1.69378976d-27, 1.02113491d-27, 6.82223774d-28, &
99 5.02099099d-28, 3.99377760d-28, 3.36279037d-28, &
100 2.94767378d-28, 2.65740865d-28, 2.44396277d-28, &
101 2.28003967d-28, 2.14941419d-28, 2.04178995d-28, &
102 1.95031045d-28, 1.87011994d-28, 1.79777869d-28, &
103 1.73093957d-28, 1.66795789d-28, 1.60785455d-28, &
104 1.55002399d-28, 1.49418229d-28, 1.44022426d-28, &
105 1.38807103d-28, 1.33772767d-28, 1.28908404d-28, &
106 1.24196208d-28, 1.17437501d-28, 1.12854330d-28, &
107 1.08410498d-28, 1.04112003d-28, 9.99529904d-29, &
108 9.59358806d-29, 9.20512291d-29, 8.83009123d-29, &
109 8.46817043d-29, 8.11921928d-29 /
110
111 data f_171 / 2.98015581d-42, 1.24696230d-40, 3.37614652d-39, 5.64103034d-38, &
112 5.20550266d-37, 2.77785939d-36, 1.16283616d-35, 6.50007689d-35, &
113 9.96177399d-34, 1.89586076d-32, 2.10982799d-31, 1.36946479d-30, &
114 6.27396553d-30, 2.29955134d-29, 7.13430211d-29, 1.91024282d-28, &
115 4.35358848d-28, 7.94807808d-28, 1.07431875d-27, 1.08399488d-27, &
116 9.16212938d-28, 7.34715770d-28, 6.59246382d-28, 9.13541375d-28, &
117 2.05939035d-27, 5.08206555d-27, 1.10148083d-26, 2.01884662d-26, &
118 3.13578384d-26, 4.14367719d-26, 5.36067711d-26, 8.74170213d-26, &
119 1.64161233d-25, 2.94587860d-25, 4.76298332d-25, 6.91765639d-25, &
120 9.08825111d-25, 1.08496183d-24, 1.17440114d-24, 1.13943939d-24, &
121 9.71696981d-25, 7.09593688d-25, 4.31376399d-25, 2.12708486d-25, &
122 8.47429567d-26, 3.17608104d-26, 1.95898842d-26, 1.98064242d-26, &
123 1.67706555d-26, 8.99126003d-27, 3.29773878d-27, 1.28896127d-27, &
124 8.51169698d-28, 7.53520167d-28, 6.18268143d-28, 4.30034650d-28, &
125 2.78152409d-28, 1.95437088d-28, 1.65896278d-28, 1.68740181d-28, &
126 1.76054383d-28, 1.63978419d-28, 1.32880591d-28, 1.00833205d-28, &
127 7.82252806d-29, 6.36181741d-29, 5.34633869d-29, 4.58013864d-29, &
128 3.97833422d-29, 3.49414760d-29, 3.09790940d-29, 2.76786227d-29, &
129 2.48806269d-29, 2.24823367d-29, 2.04016653d-29, 1.85977413d-29, &
130 1.70367499d-29, 1.56966125d-29, 1.45570643d-29, 1.35964565d-29, &
131 1.27879263d-29, 1.21016980d-29, 1.15132499d-29, 1.09959628d-29, &
132 1.05307482d-29, 1.01040261d-29, 9.70657096d-30, 9.33214234d-30, &
133 8.97689427d-30, 8.63761192d-30, 8.31149879d-30, 7.85162401d-30, &
134 7.53828281d-30, 7.23559452d-30, 6.94341530d-30, 6.66137038d-30, &
135 6.38929156d-30, 6.12669083d-30, 5.87346434d-30, 5.62943622d-30, &
136 5.39435202d-30 /
137
138 data f_193 / 6.40066486d-32, 4.92737300d-31, 2.95342934d-30, 1.28061594d-29, &
139 3.47747667d-29, 5.88554792d-29, 7.72171179d-29, 9.75609282d-29, &
140 1.34318963d-28, 1.96252638d-28, 2.70163878d-28, 3.63192965d-28, &
141 5.28087341d-28, 8.37821446d-28, 1.39089159d-27, 2.31749718d-27, &
142 3.77510689d-27, 5.85198594d-27, 8.26021568d-27, 1.04870405d-26, &
143 1.25209374d-26, 1.47406787d-26, 1.77174067d-26, 2.24098537d-26, &
144 3.05926105d-26, 4.50018853d-26, 6.84720216d-26, 1.00595861d-25, &
145 1.30759222d-25, 1.36481773d-25, 1.15943558d-25, 1.01467304d-25, &
146 1.04092532d-25, 1.15071251d-25, 1.27416033d-25, 1.38463476d-25, &
147 1.47882726d-25, 1.57041238d-25, 1.69786224d-25, 1.94970397d-25, &
148 2.50332918d-25, 3.58321431d-25, 5.18061550d-25, 6.60405549d-25, &
149 6.64085365d-25, 4.83825816d-25, 2.40545020d-25, 8.59534098d-26, &
150 2.90920638d-26, 1.33204845d-26, 9.03933926d-27, 7.78910836d-27, &
151 7.29342321d-27, 7.40267022d-27, 8.05279981d-27, 8.13829291d-27, &
152 6.92634262d-27, 5.12521880d-27, 3.59527615d-27, 2.69617560d-27, &
153 2.84432713d-27, 5.06697306d-27, 1.01281903d-26, 1.63526978d-26, &
154 2.06759342d-26, 2.19482312d-26, 2.10050611d-26, 1.89837248d-26, &
155 1.66347131d-26, 1.43071097d-26, 1.21518419d-26, 1.02078343d-26, &
156 8.46936184d-27, 6.93015742d-27, 5.56973237d-27, 4.38951754d-27, &
157 3.38456457d-27, 2.55309556d-27, 1.88904224d-27, 1.38057546d-27, &
158 1.00718330d-27, 7.43581116d-28, 5.63562931d-28, 4.43359435d-28, &
159 3.63923535d-28, 3.11248143d-28, 2.75586846d-28, 2.50672237d-28, &
160 2.32419348d-28, 2.18325682d-28, 2.06834486d-28, 1.93497044d-28, &
161 1.84540751d-28, 1.76356504d-28, 1.68741425d-28, 1.61566157d-28, &
162 1.54754523d-28, 1.48249410d-28, 1.42020176d-28, 1.36045230d-28, &
163 1.30307965d-28 /
164
165 data f_211 / 4.74439912d-42, 1.95251522d-40, 5.19700194d-39, 8.53120166d-38, &
166 7.72745727d-37, 4.04158559d-36, 1.64853511d-35, 8.56295439d-35, &
167 1.17529722d-33, 2.16867729d-32, 2.40472264d-31, 1.56418133d-30, &
168 7.20032889d-30, 2.65838271d-29, 8.33196904d-29, 2.26128236d-28, &
169 5.24295811d-28, 9.77791121d-28, 1.35913489d-27, 1.43957785d-27, &
170 1.37591544d-27, 1.49029886d-27, 2.06183401d-27, 3.31440622d-27, &
171 5.42497318d-27, 8.41100374d-27, 1.17941366d-26, 1.49269794d-26, &
172 1.71506074d-26, 1.71266353d-26, 1.51434781d-26, 1.36766622d-26, &
173 1.33483562d-26, 1.36834518d-26, 1.45829002d-26, 1.62575306d-26, &
174 1.88773347d-26, 2.22026986d-26, 2.54930499d-26, 2.80758138d-26, &
175 3.06176409d-26, 3.62799792d-26, 5.13226109d-26, 8.46260744d-26, &
176 1.38486586d-25, 1.86192535d-25, 1.78007934d-25, 1.16548409d-25, &
177 5.89293257d-26, 2.69952884d-26, 1.24891081d-26, 6.41273176d-27, &
178 4.08282914d-27, 3.26463328d-27, 2.76230280d-27, 2.08986882d-27, &
179 1.37658470d-27, 8.48489381d-28, 5.19304217d-28, 3.19312514d-28, &
180 2.02968197d-28, 1.50171666d-28, 1.39164218d-28, 1.42448821d-28, &
181 1.41714519d-28, 1.33341059d-28, 1.20759270d-28, 1.07259692d-28, &
182 9.44895400d-29, 8.29030041d-29, 7.25440631d-29, 6.33479483d-29, &
183 5.51563757d-29, 4.79002469d-29, 4.14990482d-29, 3.59384972d-29, &
184 3.12010860d-29, 2.72624742d-29, 2.40734791d-29, 2.15543565d-29, &
185 1.95921688d-29, 1.80682882d-29, 1.68695662d-29, 1.59020936d-29, &
186 1.50940886d-29, 1.43956179d-29, 1.37731622d-29, 1.32049043d-29, &
187 1.26771875d-29, 1.21803879d-29, 1.17074716d-29, 1.10507836d-29, &
188 1.06022834d-29, 1.01703080d-29, 9.75436986d-30, 9.35349257d-30, &
189 8.96744546d-30, 8.59527489d-30, 8.23678940d-30, 7.89144480d-30, &
190 7.55891138d-30 /
191
192 data f_304 / 3.62695850d-32, 2.79969087d-31, 1.68340584d-30, 7.32681440d-30, &
193 1.99967770d-29, 3.41296785d-29, 4.55409104d-29, 5.94994635d-29, &
194 8.59864963d-29, 1.39787633d-28, 3.17701965d-28, 1.14474920d-27, &
195 4.44845958d-27, 1.54785841d-26, 4.70265345d-26, 1.24524365d-25, &
196 2.81535352d-25, 5.10093666d-25, 6.83545307d-25, 6.82110329d-25, &
197 5.66886188d-25, 4.36205513d-25, 3.29265688d-25, 2.49802368d-25, &
198 1.92527113d-25, 1.51058572d-25, 1.20596047d-25, 9.76884267d-26, &
199 7.89979266d-26, 6.18224289d-26, 4.67298332d-26, 3.57934505d-26, &
200 2.84535785d-26, 2.32853022d-26, 1.95228514d-26, 1.67880071d-26, &
201 1.47608785d-26, 1.32199691d-26, 1.20070960d-26, 1.09378177d-26, &
202 1.00031730d-26, 9.62434001d-27, 1.05063954d-26, 1.27267143d-26, &
203 1.45923057d-26, 1.36746707d-26, 1.03466970d-26, 6.97647829d-27, &
204 4.63141039d-27, 3.19031994d-27, 2.33373613d-27, 1.81589079d-27, &
205 1.48446917d-27, 1.26611478d-27, 1.12617468d-27, 1.03625148d-27, &
206 9.61400595d-28, 8.79016231d-28, 7.82612130d-28, 6.73762960d-28, &
207 5.59717956d-28, 4.53010243d-28, 3.65712196d-28, 3.00958686d-28, &
208 2.54011502d-28, 2.18102277d-28, 1.88736437d-28, 1.63817539d-28, &
209 1.42283147d-28, 1.23631916d-28, 1.07526003d-28, 9.36797928d-29, &
210 8.18565660d-29, 7.18152734d-29, 6.32523238d-29, 5.59513985d-29, &
211 4.96614048d-29, 4.42518826d-29, 3.95487628d-29, 3.54690294d-29, &
212 3.18953930d-29, 2.87720933d-29, 2.60186750d-29, 2.36011522d-29, &
213 2.14717806d-29, 1.95905217d-29, 1.79287981d-29, 1.64562262d-29, &
214 1.51489425d-29, 1.39876064d-29, 1.29496850d-29, 1.18665438d-29, &
215 1.10240474d-29, 1.02643099d-29, 9.57780996d-30, 8.95465151d-30, &
216 8.38950190d-30, 7.87283711d-30, 7.40136507d-30, 6.96804279d-30, &
217 6.56945323d-30 /
218
219 data f_335 / 2.46882661d-32, 1.89476632d-31, 1.13216502d-30, 4.89532008d-30, &
220 1.32745970d-29, 2.25390335d-29, 3.00511672d-29, 3.96035934d-29, &
221 5.77977656d-29, 8.58600736d-29, 1.14083000d-28, 1.48644411d-28, &
222 2.15788823d-28, 3.51628877d-28, 6.12200698d-28, 1.08184987d-27, &
223 1.85590697d-27, 2.91679107d-27, 3.94405396d-27, 4.63610680d-27, &
224 5.13824456d-27, 5.66602209d-27, 6.30009232d-27, 7.03422868d-27, &
225 7.77973918d-27, 8.32371831d-27, 8.56724316d-27, 8.62601374d-27, &
226 8.13308844d-27, 6.53188216d-27, 4.55197029d-27, 3.57590087d-27, &
227 3.59571707d-27, 4.03502770d-27, 4.54366411d-27, 4.96914990d-27, &
228 5.24601170d-27, 5.39979250d-27, 5.43023669d-27, 5.26235042d-27, &
229 4.91585495d-27, 4.52628362d-27, 4.13385020d-27, 3.67538967d-27, &
230 3.39939742d-27, 3.81284533d-27, 5.02332701d-27, 6.19438602d-27, &
231 6.49613071d-27, 6.04010475d-27, 5.24664275d-27, 4.37225997d-27, &
232 3.52957182d-27, 2.76212276d-27, 2.08473158d-27, 1.50850518d-27, &
233 1.04602472d-27, 7.13091243d-28, 5.34289645d-28, 5.21079581d-28, &
234 6.22246365d-28, 6.99555864d-28, 6.29665489d-28, 4.45077026d-28, &
235 2.67046793d-28, 1.52774686d-28, 9.18061770d-29, 6.09116074d-29, &
236 4.48562572d-29, 3.59463696d-29, 3.05820218d-29, 2.70766652d-29, &
237 2.46144034d-29, 2.27758450d-29, 2.13331183d-29, 2.01537836d-29, &
238 1.91566180d-29, 1.82893912d-29, 1.75167748d-29, 1.68136168d-29, &
239 1.61615595d-29, 1.55481846d-29, 1.49643236d-29, 1.44046656d-29, &
240 1.38657085d-29, 1.33459068d-29, 1.28447380d-29, 1.23615682d-29, &
241 1.18963296d-29, 1.14478976d-29, 1.10146637d-29, 1.04039479d-29, &
242 9.98611410d-30, 9.58205147d-30, 9.19202009d-30, 8.81551313d-30, &
243 8.45252127d-30, 8.10224764d-30, 7.76469090d-30, 7.43954323d-30, &
244 7.12653873d-30 /
245
246
247 data n_iris / 41 /
248
249 data t_iris / 4. , 4.1 , 4.2 , 4.3 , 4.40000001, &
250 4.50000001, 4.60000001, 4.70000001, 4.80000001, 4.90000001, &
251 5.00000001, 5.10000002, 5.20000002, 5.30000002, 5.40000002, &
252 5.50000002, 5.60000002, 5.70000003, 5.80000003, 5.90000003, &
253 6.00000003, 6.10000003, 6.20000003, 6.30000003, 6.40000004, &
254 6.50000004, 6.60000004, 6.70000004, 6.80000004, 6.90000004, &
255 7.00000004, 7.10000005, 7.20000005, 7.30000005, 7.40000005, &
256 7.50000005, 7.60000005, 7.70000006, 7.80000006, 7.90000006, &
257 8.00000006 /
258
259 data f_1354 / 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, &
260 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, &
261 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, &
262 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, &
263 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, &
264 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 1.09503647d-39, &
265 5.47214550d-36, 2.42433983d-33, 2.75295034d-31, 1.21929718d-29, &
266 2.48392125d-28, 2.33268145d-27, 8.68623633d-27, 1.00166284d-26, &
267 3.63126633d-27, 7.45174807d-28, 1.38224064d-28, 2.69270994d-29, &
268 5.53314977d-30, 1.15313092d-30, 2.34195788d-31, 4.48242942d-32, &
269 7.94976380d-33 /
270
271
272 data n_eis / 60 /
273
274 data t_eis1 / 1.99526231d+05, 2.23872114d+05, 2.51188643d+05, 2.81838293d+05, &
275 3.16227766d+05, 3.54813389d+05, 3.98107171d+05, 4.46683592d+05, &
276 5.01187234d+05, 5.62341325d+05, 6.30957344d+05, 7.07945784d+05, &
277 7.94328235d+05, 8.91250938d+05, 1.00000000d+06, 1.12201845d+06, &
278 1.25892541d+06, 1.41253754d+06, 1.58489319d+06, 1.77827941d+06, &
279 1.99526231d+06, 2.23872114d+06, 2.51188643d+06, 2.81838293d+06, &
280 3.16227766d+06, 3.54813389d+06, 3.98107171d+06, 4.46683592d+06, &
281 5.01187234d+06, 5.62341325d+06, 6.30957344d+06, 7.07945784d+06, &
282 7.94328235d+06, 8.91250938d+06, 1.00000000d+07, 1.12201845d+07, &
283 1.25892541d+07, 1.41253754d+07, 1.58489319d+07, 1.77827941d+07, &
284 1.99526231d+07, 2.23872114d+07, 2.51188643d+07, 2.81838293d+07, &
285 3.16227766d+07, 3.54813389d+07, 3.98107171d+07, 4.46683592d+07, &
286 5.01187234d+07, 5.62341325d+07, 6.30957344d+07, 7.07945784d+07, &
287 7.94328235d+07, 8.91250938d+07, 1.00000000d+08, 1.12201845d+08, &
288 1.25892541d+08, 1.41253754d+08, 1.58489319d+08, 1.77827941d+08 /
289
290 data t_eis2 / 1.99526231d+06, 2.23872114d+06, 2.51188643d+06, 2.81838293d+06, &
291 3.16227766d+06, 3.54813389d+06, 3.98107171d+06, 4.46683592d+06, &
292 5.01187234d+06, 5.62341325d+06, 6.30957344d+06, 7.07945784d+06, &
293 7.94328235d+06, 8.91250938d+06, 1.00000000d+07, 1.12201845d+07, &
294 1.25892541d+07, 1.41253754d+07, 1.58489319d+07, 1.77827941d+07, &
295 1.99526231d+07, 2.23872114d+07, 2.51188643d+07, 2.81838293d+07, &
296 3.16227766d+07, 3.54813389d+07, 3.98107171d+07, 4.46683592d+07, &
297 5.01187234d+07, 5.62341325d+07, 6.30957344d+07, 7.07945784d+07, &
298 7.94328235d+07, 8.91250938d+07, 1.00000000d+08, 1.12201845d+08, &
299 1.25892541d+08, 1.41253754d+08, 1.58489319d+08, 1.77827941d+08, &
300 1.99526231d+08, 2.23872114d+08, 2.51188643d+08, 2.81838293d+08, &
301 3.16227766d+08, 3.54813389d+08, 3.98107171d+08, 4.46683592d+08, &
302 5.01187234d+08, 5.62341325d+08, 6.30957344d+08, 7.07945784d+08, &
303 7.94328235d+08, 8.91250938d+08, 1.00000000d+09, 1.12201845d+09, &
304 1.25892541d+09, 1.41253754d+09, 1.58489319d+09, 1.77827941d+09 /
305
306 data f_263 / 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, &
307 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, &
308 0.00000000d+00, 4.46454917d-45, 3.26774829d-42, 1.25292566d-39, &
309 2.66922338d-37, 3.28497742d-35, 2.38677554d-33, 1.03937729d-31, &
310 2.75075687d-30, 4.47961733d-29, 4.46729177d-28, 2.64862689d-27, &
311 8.90863800d-27, 1.72437548d-26, 2.22217752d-26, 2.27999477d-26, &
312 2.08264363d-26, 1.78226687d-26, 1.45821699d-26, 1.14675379d-26, &
313 8.63082492d-27, 6.15925429d-27, 4.11252514d-27, 2.51530564d-27, &
314 1.37090986d-27, 6.42443134d-28, 2.48392636d-28, 7.59187874d-29, &
315 1.77852938d-29, 3.23945221d-30, 4.90533903d-31, 6.75458158d-32, &
316 9.06878868d-33, 1.23927474d-33, 1.75769395d-34, 2.60710914d-35, &
317 4.04318030d-36, 6.53500581d-37, 1.09365022d-37, 1.88383322d-38, &
318 3.31425233d-39, 5.90964084d-40, 1.06147549d-40, 1.90706170d-41, &
319 3.41331584d-42, 6.07310718d-43, 1.07364738d-43, 1.89085498d-44, &
320 3.32598922d-45, 5.87125640d-46, 0.00000000d+00, 0.00000000d+00 /
321
322 data f_264 / 0.00000000d+00, 2.81670057d-46, 1.28007268d-43, 2.54586603d-41, &
323 2.67887256d-39, 1.68413285d-37, 6.85702304d-36, 1.91797284d-34, &
324 3.84675839d-33, 5.69939170d-32, 6.36224608d-31, 5.39176489d-30, &
325 3.45478458d-29, 1.64848693d-28, 5.71476364d-28, 1.39909997d-27, &
326 2.37743056d-27, 2.86712530d-27, 2.65206348d-27, 2.07175767d-27, &
327 1.47866767d-27, 1.01087374d-27, 6.79605811d-28, 4.54746770d-28, &
328 3.04351751d-28, 2.03639149d-28, 1.35940991d-28, 9.01451939d-29, &
329 5.91289972d-29, 3.81821178d-29, 2.41434696d-29, 1.48871220d-29, &
330 8.93362094d-30, 5.21097445d-30, 2.95964719d-30, 1.64278748d-30, &
331 8.95571660d-31, 4.82096011d-31, 2.57390991d-31, 1.36821781d-31, &
332 7.27136350d-32, 3.87019426d-32, 2.06883430d-32, 1.11228884d-32, &
333 6.01883313d-33, 3.27790676d-33, 1.79805012d-33, 9.93085346d-34, &
334 5.52139556d-34, 3.08881387d-34, 1.73890315d-34, 9.84434964d-35, &
335 5.60603378d-35, 3.20626492d-35, 1.84111068d-35, 0.00000000d+00, &
336 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00 /
337
338 data f_192 / 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 4.35772105d-44, &
339 1.26162319d-41, 1.97471205d-39, 1.83409019d-37, 1.08206288d-35, &
340 4.27914363d-34, 1.17943846d-32, 2.32565755d-31, 3.33087991d-30, &
341 3.47013260d-29, 2.60375866d-28, 1.37737127d-27, 5.01053913d-27, &
342 1.23479810d-26, 2.11310542d-26, 2.71831513d-26, 2.89851163d-26, &
343 2.77312376d-26, 2.50025229d-26, 2.18323661d-26, 1.86980322d-26, &
344 1.58035034d-26, 1.31985651d-26, 1.08733133d-26, 8.81804906d-27, &
345 7.00417973d-27, 5.43356567d-27, 4.09857884d-27, 2.99651764d-27, &
346 2.11902962d-27, 1.45014127d-27, 9.62291023d-28, 6.21548647d-28, &
347 3.92807578d-28, 2.44230375d-28, 1.50167782d-28, 9.17611405d-29, &
348 5.58707641d-29, 3.40570915d-29, 2.08030862d-29, 1.27588676d-29, &
349 7.86535588d-30, 4.87646151d-30, 3.03888897d-30, 1.90578649d-30, &
350 1.20195947d-30, 7.61955060d-31, 4.85602199d-31, 3.11049969d-31, &
351 2.00087065d-31, 1.29223740d-31, 8.37422008d-32, 0.00000000d+00, &
352 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00 /
353
354 data f_255 / 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 1.76014287d-44, &
355 5.07057938d-42, 7.90473970d-40, 7.31852999d-38, 4.30709255d-36, &
356 1.70009061d-34, 4.67925160d-33, 9.21703546d-32, 1.31918676d-30, &
357 1.37393161d-29, 1.03102379d-28, 5.45694018d-28, 1.98699648d-27, &
358 4.90346776d-27, 8.40524725d-27, 1.08321456d-26, 1.15714525d-26, &
359 1.10905152d-26, 1.00155023d-26, 8.75799161d-27, 7.50935839d-27, &
360 6.35253533d-27, 5.30919268d-27, 4.37669455d-27, 3.55185164d-27, &
361 2.82347055d-27, 2.19257595d-27, 1.65589541d-27, 1.21224987d-27, &
362 8.58395132d-28, 5.88163935d-28, 3.90721447d-28, 2.52593407d-28, &
363 1.59739995d-28, 9.93802874d-29, 6.11343388d-29, 3.73711135d-29, &
364 2.27618743d-29, 1.38793199d-29, 8.48060787d-30, 5.20305940d-30, &
365 3.20867365d-30, 1.99011277d-30, 1.24064551d-30, 7.78310544d-31, &
366 4.91013681d-31, 3.11338381d-31, 1.98451675d-31, 1.27135460d-31, &
367 8.17917486d-32, 5.28280497d-32, 3.42357159d-32, 0.00000000d+00, &
368 0.00000000d+00, 0.00000000d+00, 0.00000000d+00, 0.00000000d+00 /
369
370 abstract interface
371 subroutine get_subr1(w,x,ixI^L,ixO^L,res)
373 integer, intent(in) :: ixI^L, ixO^L
374 double precision, intent(in) :: w(ixI^S,nw)
375 double precision, intent(in) :: x(ixI^S,1:ndim)
376 double precision, intent(out):: res(ixI^S)
377 end subroutine get_subr1
378
379 end interface
380
381 abstract interface
382 subroutine get_2var_subr_te(ixI^L, ixO^L, w, val1, val2)
384 integer, intent(in) :: ixI^L, ixO^L
385 double precision, intent(in) :: w(ixI^S, nw)
386 double precision, intent(out):: val1(ixI^S), val2(ixI^S)
387 end subroutine get_2var_subr_te
388 end interface
389
391
392 procedure(get_subr1), pointer, nopass :: get_rho => null()
393 procedure(get_subr1), pointer, nopass :: get_pthermal => null()
394 procedure(get_subr1), pointer, nopass :: get_var_rfactor => null()
395 procedure(get_2var_subr_te), pointer, nopass :: get_ne_nh => null()
396
397 end type te_fluid
398
400 integer :: igrid=0
401 integer :: level=0
402 integer :: rft=1
403 integer :: los_min=0
404 integer :: los_max=0
405 double precision, allocatable :: source(:^d&)
406 double precision, allocatable :: opacity(:^d&)
407 double precision, allocatable :: sourcev(:^d&)
408 double precision, allocatable :: xface1(:),xface2(:),xface3(:)
409 double precision, allocatable :: rface(:),thetaface(:),phiface(:)
410 double precision, allocatable :: rface2(:),theta_cos(:),phi_sin(:),phi_cos(:)
411 double precision :: box_min(1:3)=0.d0
412 double precision :: box_max(1:3)=0.d0
413 integer :: ixpmin1=1
414 integer :: ixpmax1=0
415 integer :: ixpmin2=1
416 integer :: ixpmax2=0
417 logical :: has_pixels=.false.
418 end type radsyn_euv_cache
419
420 character(len=std_len) :: ray_method_active='legacy'
421 logical :: sph_use_dda=.false.
422
423
424 contains
425
428
429 character(len=*), intent(in) :: datatype
430
431 if (trim(radiation_transfer) /= 'thin' .and. trim(radiation_transfer) /= 'thick') then
432 call mpistop("bad radiation_transfer")
433 endif
434
435 sph_use_dda=.false.
436 select case(trim(ray_method))
437 case('auto','')
438 if (datatype=='image_euv' .and. coordinate==spherical) then
439 ray_method_active='spherical'
440 sph_use_dda=.true.
441 else if (datatype=='image_euv' .and. coordinate==cartesian .and. dat_resolution .and. slab) then
442 ray_method_active='cart'
443 else
444 ray_method_active='legacy'
445 endif
446 case('legacy')
447 ray_method_active='legacy'
448 case('cart','cart_dda')
449 ray_method_active='cart'
450 case('spherical','sph_intersection')
451 ray_method_active='spherical'
452 case('sph_dda','spherical_dda')
453 ray_method_active='spherical'
454 sph_use_dda=.true.
455 case default
456 call mpistop("bad ray_method")
457 end select
458
459 if (trim(emission_model) /= 'auto' .and. trim(emission_model) /= 'euv_aia' .and. &
460 trim(emission_model) /= 'white_light' .and. trim(emission_model) /= 'radio_ff' .and. &
461 trim(emission_model) /= 'pseudo_current') then
462 call mpistop("bad emission_model")
463 endif
464
465 if ((output_tau .or. output_absorption_fraction) .and. trim(radiation_transfer) /= 'thick') then
466 call mpistop("tau and absorption-fraction output need thick transfer")
467 endif
468
469 if (radsyn_pixel_batch<1) then
470 call mpistop("radsyn_pixel_batch must be positive")
471 endif
473 call mpistop("radsyn_segment_batch_factor must be non-negative")
474 endif
475 if (radsyn_segment_memory_mb<=zero) then
476 call mpistop("radsyn_segment_memory_mb must be positive")
477 endif
479 call mpistop("radsyn_segment_comm_factor must be positive")
480 endif
481
482 if (instrument_postprocess) then
483 if (datatype /= 'image_euv' .or. .not. dat_resolution) then
484 call mpistop("instrument_postprocess currently needs dat-resolution EUV images")
485 endif
486 if (trim(ray_method_active) == 'spherical') then
487 call mpistop("instrument_postprocess is not yet supported for spherical rays")
488 endif
489 if (trim(emission_model) == 'pseudo_current') then
490 call mpistop("instrument_postprocess currently supports only EUV AIA or radio_ff images")
491 endif
492 if (trim(emission_model) == 'radio_ff' .and. radio_beam_fwhm<=zero) then
493 call mpistop("radio_ff instrument_postprocess needs radio_beam_fwhm > 0 arcsec")
494 endif
495 endif
496
497 select case(trim(emission_model))
498 case('auto')
499 continue
500 case('euv_aia')
501 if (datatype /= 'image_euv' .and. datatype /= 'spectrum_euv') then
502 call mpistop("emission_model=euv_aia is only valid for EUV synthesis")
503 endif
504 case('white_light')
505 if (datatype /= 'image_whitelight') then
506 call mpistop("emission_model=white_light is only valid for white-light synthesis")
507 endif
508 case('radio_ff')
509 if (datatype /= 'image_euv') then
510 call mpistop("emission_model=radio_ff currently reuses EUV-image convert types")
511 endif
512 if (radio_frequency<=zero) then
513 call mpistop("emission_model=radio_ff needs radio_frequency > 0")
514 endif
515 case('pseudo_current')
516 if (datatype /= 'image_euv') then
517 call mpistop("emission_model=pseudo_current is only valid for EUV-image convert types")
518 endif
519 if (trim(radiation_transfer) /= 'thin') then
520 call mpistop("emission_model=pseudo_current currently supports only thin transfer")
521 endif
522 end select
523
524 if (trim(ray_method_active) == 'cart') then
525 if (datatype /= 'image_euv' .or. coordinate /= cartesian .or. .not. slab) then
526 call mpistop("ray_method=cart needs Cartesian EUV slab images")
527 endif
528 endif
529 if (trim(ray_method_active) == 'spherical') then
530 {^ifoned
531 call mpistop("ray_method=spherical currently needs 3D spherical grids")
532 }
533 {^iftwod
534 call mpistop("ray_method=spherical currently needs 3D spherical grids")
535 }
536 {^ifthreed
537 if (datatype /= 'image_euv' .or. coordinate /= spherical .or. &
538 (trim(radiation_transfer) /= 'thin' .and. trim(radiation_transfer) /= 'thick')) then
539 call mpistop("bad ray_method=spherical mode")
540 endif
541 if (trim(emission_model) /= 'auto' .and. trim(emission_model) /= 'euv_aia') then
542 call mpistop("ray_method=spherical currently supports only EUV AIA emission")
543 endif
544 if (xprobmin2<=1.d-10 .or. xprobmax2>=dpi-1.d-10) then
545 call mpistop("ray_method=spherical does not support polar-axis crossing domains")
546 endif
547 if (xprobmax3<=xprobmin3 .or. xprobmax3-xprobmin3>=2.d0*dpi-1.d-10) then
548 call mpistop("ray_method=spherical does not support phi-wrapping domains")
549 endif
550 }
551 endif
552 if (trim(radiation_transfer) == 'thick') then
553 if (datatype /= 'image_euv') then
554 call mpistop("thick transfer is only defined for EUV images")
555 endif
556 if (trim(ray_method_active) == 'spherical') then
557 continue
558 else if (trim(ray_method_active) == 'cart') then
559 if (.not. slab) call mpistop("cartesian thick EUV currently needs slab output")
560 else if (.not. slab .or. .not. dat_resolution) then
561 call mpistop("thick EUV currently needs Cartesian dat_resolution output")
562 endif
563 if (trim(ray_method_active) /= 'cart' .and. &
564 trim(ray_method_active) /= 'spherical' .and. &
565 .not. ((los_phi==0 .and. los_theta==90) .or. &
566 (los_phi==90 .and. los_theta==90) .or. los_theta==0)) then
567 call mpistop("thick EUV currently needs x/y/z-aligned LOS")
568 endif
569 endif
571
572 subroutine integrate_transfer_step_first_order(emissivity,opacity,path_length,intensity,tau)
573 ! First-order formal-solution step used by the planned ordered LOS transfer.
574 double precision, intent(in) :: emissivity,opacity,path_length
575 double precision, intent(inout) :: intensity,tau
576
577 double precision :: dtau
578
579 if (path_length<=zero) return
580 intensity=intensity+transfer_attenuation(tau)*max(zero,emissivity)*path_length
581 dtau=max(zero,opacity)*path_length
582 tau=tau+dtau
584
586 radsyn_euv_has_doppler_output=trim(emission_model)/='pseudo_current' .and. &
587 trim(emission_model)/='radio_ff' .and. &
588 .not. (coordinate==spherical .and. trim(ray_method_active)=='spherical')
590
591 integer function radsyn_euv_num_outputs(has_doppler,has_thick) result(num_outputs)
592 logical, intent(in) :: has_doppler,has_thick
593
594 num_outputs=1
595 if (has_doppler) num_outputs=num_outputs+1
596 if (has_thick .and. output_tau) num_outputs=num_outputs+1
597 if (has_thick .and. output_absorption_fraction) num_outputs=num_outputs+1
598 end function radsyn_euv_num_outputs
599
600 subroutine normalize_euv_doppler(nI1,nI2,EUV,Dpl,unitv)
601 integer, intent(in) :: nI1,nI2
602 double precision, intent(in) :: EUV(nI1,nI2),unitv
603 double precision, intent(inout) :: Dpl(nI1,nI2)
604
605 integer :: ix1,ix2
606
607 do ix1=1,ni1
608 do ix2=1,ni2
609 if (euv(ix1,ix2)/=zero) then
610 dpl(ix1,ix2)=(dpl(ix1,ix2)/euv(ix1,ix2))*unitv
611 else
612 dpl(ix1,ix2)=zero
613 endif
614 if (abs(dpl(ix1,ix2))<smalldouble) dpl(ix1,ix2)=zero
615 enddo
616 enddo
617 end subroutine normalize_euv_doppler
618
619 subroutine fill_euv_absorption_fraction(nI1,nI2,EUV,EUVthin,smallflux,Absorption,cap_to_one)
620 integer, intent(in) :: nI1,nI2
621 double precision, intent(in) :: EUV(nI1,nI2),EUVthin(nI1,nI2),smallflux
622 double precision, intent(out) :: Absorption(nI1,nI2)
623 logical, intent(in), optional :: cap_to_one
624
625 integer :: ix1,ix2
626 logical :: cap_absorption
627
628 absorption=zero
629 cap_absorption=.false.
630 if (present(cap_to_one)) cap_absorption=cap_to_one
631 do ix1=1,ni1
632 do ix2=1,ni2
633 if (euvthin(ix1,ix2)>smallflux) then
634 absorption(ix1,ix2)=max(zero,(euvthin(ix1,ix2)-euv(ix1,ix2))/euvthin(ix1,ix2))
635 if (cap_absorption) absorption(ix1,ix2)=min(one,absorption(ix1,ix2))
636 endif
637 enddo
638 enddo
639 end subroutine fill_euv_absorption_fraction
640
641 subroutine pack_euv_image_outputs(nI1,nI2,EUV,wI,smallflux,has_doppler,has_thick,Dpl,Tau,EUVthin,&
642 cap_absorption)
643 integer, intent(in) :: nI1,nI2
644 double precision, intent(in) :: EUV(nI1,nI2),smallflux
645 double precision, intent(inout) :: wI(:,:,:)
646 logical, intent(in) :: has_doppler,has_thick
647 double precision, intent(in), optional :: Dpl(nI1,nI2),Tau(nI1,nI2),EUVthin(nI1,nI2)
648 logical, intent(in), optional :: cap_absorption
649
650 integer :: iw
651 double precision, allocatable :: Absorption(:,:)
652
653 wi=zero
654 wi(:,:,1)=euv(:,:)
655 iw=1
656 if (has_doppler) then
657 if (.not. present(dpl)) call mpistop("Doppler output requested without Doppler image")
658 iw=iw+1
659 wi(:,:,iw)=dpl(:,:)
660 endif
661 if (has_thick .and. output_tau) then
662 if (.not. present(tau)) call mpistop("tau output requested without tau image")
663 iw=iw+1
664 wi(:,:,iw)=tau(:,:)
665 endif
666 if (has_thick .and. output_absorption_fraction) then
667 if (.not. present(euvthin)) call mpistop("absorption output requested without thin image")
668 allocate(absorption(ni1,ni2))
669 call fill_euv_absorption_fraction(ni1,ni2,euv,euvthin,smallflux,absorption,cap_absorption)
670 iw=iw+1
671 wi(:,:,iw)=absorption(:,:)
672 deallocate(absorption)
673 endif
674 end subroutine pack_euv_image_outputs
675
676 subroutine radsyn_get_segment_batch_limits(pixel_batch_target,segment_batch_target,segment_comm_target)
677 integer, intent(out) :: pixel_batch_target,segment_batch_target,segment_comm_target
678
679 pixel_batch_target=max(1,radsyn_pixel_batch)
680 if (radsyn_segment_batch_factor>0) then
681 segment_batch_target=max(128,radsyn_segment_batch_factor*pixel_batch_target)
682 else
683 segment_batch_target=max(128,int(min(dble(huge(segment_batch_target)),&
684 max(128.d0,radsyn_segment_memory_mb*1048576.d0/256.d0))))
685 endif
686 segment_comm_target=max(128,radsyn_segment_comm_factor*pixel_batch_target)
688
689 double precision function transfer_attenuation(tau)
690 double precision, intent(in) :: tau
691
692 if (tau<=zero) then
694 else
696 endif
697 end function transfer_attenuation
698
699 double precision function exp_clamped(argument)
700 double precision, intent(in) :: argument
701
702 if (argument<-700.d0) then
703 exp_clamped=zero
704 else if (argument>700.d0) then
705 exp_clamped=huge(one)
706 else
707 exp_clamped=exp(argument)
708 endif
709 end function exp_clamped
710
711 double precision function pow10_clamped(exponent)
712 double precision, intent(in) :: exponent
713
714 if (exponent>300.d0) then
715 pow10_clamped=1.d300
716 else if (exponent<-300.d0) then
717 pow10_clamped=zero
718 else
719 pow10_clamped=10.d0**exponent
720 endif
721 end function pow10_clamped
722
723 double precision function interpolate_response_value(temperature,t_table,f_table,n_table,log_temperature,log_response)
724 double precision, intent(in) :: temperature
725 integer, intent(in) :: n_table
726 double precision, intent(in) :: t_table(n_table),f_table(n_table)
727 logical, intent(in) :: log_temperature,log_response
728
729 integer :: ilo,ihi,imid
730 double precision :: temp_lookup,response_lookup,flo,fhi
731
733 if (temperature<=zero) return
734 if (log_temperature) then
735 temp_lookup=log10(temperature)
736 else
737 temp_lookup=temperature
738 endif
739 if (temp_lookup<t_table(1) .or. temp_lookup>t_table(n_table)) return
740 if (temp_lookup==t_table(n_table)) then
741 if (log_response) then
742 response_lookup=log10(max(f_table(n_table),1.d-99))
743 else
744 response_lookup=f_table(n_table)
745 endif
746 else
747 ilo=1
748 ihi=n_table
749 do while (ihi-ilo>1)
750 imid=(ilo+ihi)/2
751 if (temp_lookup>=t_table(imid)) then
752 ilo=imid
753 else
754 ihi=imid
755 endif
756 enddo
757 if (log_response) then
758 flo=log10(max(f_table(ilo),1.d-99))
759 fhi=log10(max(f_table(ilo+1),1.d-99))
760 else
761 flo=f_table(ilo)
762 fhi=f_table(ilo+1)
763 endif
764 response_lookup=flo*(temp_lookup-t_table(ilo+1))/(t_table(ilo)-t_table(ilo+1))+&
765 fhi*(temp_lookup-t_table(ilo))/(t_table(ilo+1)-t_table(ilo))
766 endif
767
768 if (log_response) then
769 if (response_lookup>-99.d0) interpolate_response_value=10.d0**response_lookup
770 else
771 interpolate_response_value=response_lookup
772 endif
774 end function interpolate_response_value
775
776 subroutine apply_temperature_response(ixI^L,ixO^L,Te,flux,t_table,f_table,n_table,log_temperature,log_response)
777 integer, intent(in) :: ixI^L, ixO^L, n_table
778 double precision, intent(in) :: Te(ixI^S),t_table(n_table),f_table(n_table)
779 double precision, intent(inout) :: flux(ixI^S)
780 logical, intent(in) :: log_temperature,log_response
781
782 integer :: ix^D
783 double precision :: GT
784
785 {do ix^db=ixomin^db,ixomax^db\}
786 gt=interpolate_response_value(te(ix^d),t_table,f_table,n_table,log_temperature,log_response)
787 flux(ix^d)=flux(ix^d)*gt
788 if (flux(ix^d)<zero) flux(ix^d)=zero
789 {enddo\}
790 end subroutine apply_temperature_response
791
792 subroutine get_euv_hhe_opacity(wl,ixI^L,ixO^L,w,x,fl,kappa)
793 ! H I + He I + He II photoionization opacity in cm^-1.
794 use mod_constants, only: kb_cgs
795 use mod_eos, only: eos
796
797 integer, intent(in) :: wl
798 integer, intent(in) :: ixI^L, ixO^L
799 double precision, intent(in) :: x(ixI^S,1:ndim)
800 double precision, intent(in) :: w(ixI^S,1:nw)
801 type(te_fluid), intent(in) :: fl
802 double precision, intent(out) :: kappa(ixI^S)
803
804 integer :: ix^D
805 double precision :: pth(ixI^S),Te(ixI^S),Ne(ixI^S)
806 double precision :: wave_ratio,s_H1,s_He1,s_He2,Pe
807 double precision :: log_H21,log_He21,log_He32,log_He321,logScaleHe,w_H21
808 double precision :: term0,term1,term2,denHe,i0,j1,j2,be
809 double precision :: N_H,N_H1,N_He1,N_He2
810 double precision, parameter :: Xe_H21=13.6d0, xe_he21=24.587d0, xe_he32=54.416d0
811 double precision, parameter :: rHe=0.1d0
812 double precision, parameter :: sigma_H1=5.16d-20, sigma_he1=9.25d-19, sigma_he2=7.17d-19
813
814 call fl%get_pthermal(w,x,ixi^l,ixo^l,pth)
815 call fl%get_rho(w,x,ixi^l,ixo^l,ne)
816 call fl%get_var_Rfactor(w,x,ixi^l,ixo^l,te)
817 te(ixo^s)=pth(ixo^s)/(ne(ixo^s)*te(ixo^s))*unit_temperature
818 block
819 double precision :: nH_dummy(ixI^S)
820 call eos%get_ne_nH(ixi^l, ixo^l, w, ne, nh_dummy)
821 end block
822 if (si_unit) then
823 ne(ixo^s)=ne(ixo^s)*unit_numberdensity/1.d6
824 else
825 ne(ixo^s)=ne(ixo^s)*unit_numberdensity
826 endif
827
828 wave_ratio=dble(wl)/171.d0
829 s_h1=zero
830 s_he1=zero
831 s_he2=zero
832 if (wl<=912) s_h1=wave_ratio**3*sigma_h1
833 if (wl<=504) s_he1=wave_ratio**2*sigma_he1
834 if (wl<=228) s_he2=wave_ratio**2.75d0*sigma_he2
835 kappa(ixo^s)=zero
836
837 {do ix^db=ixomin^db,ixomax^db\}
838 if (te(ix^d)>zero .and. ne(ix^d)>zero) then
839 pe=ne(ix^d)*kb_cgs*te(ix^d)
840 if (pe>zero) then
841 log_h21=2.5d0*log10(te(ix^d))-5040.d0*xe_h21/te(ix^d)-log10(pe)-0.48d0
842 log_he21=log10(4.d0)+2.5d0*log10(te(ix^d))-5040.d0*xe_he21/te(ix^d)-log10(pe)-0.48d0
843 log_he32=2.5d0*log10(te(ix^d))-5040.d0*xe_he32/te(ix^d)-log10(pe)-0.48d0
844 w_h21=pow10_clamped(log_h21)
845 i0=w_h21/(1.d0+w_h21)
846 log_he321=log_he21+log_he32
847 logscalehe=max(zero,log_he21,log_he321)
848 term0=pow10_clamped(-logscalehe)
849 term1=pow10_clamped(log_he21-logscalehe)
850 term2=pow10_clamped(log_he321-logscalehe)
851 denhe=term0+term1+term2
852 if (denhe>zero) then
853 j1=term1/denhe
854 j2=term2/denhe
855 else
856 j1=zero
857 j2=zero
858 endif
859 be=i0+rhe*(j1+2.d0*j2)
860 if (be>smalldouble) then
861 n_h=ne(ix^d)/be
862 n_h1=n_h*(1.d0-i0)
863 n_he1=(1.d0-j1-j2)*rhe*n_h
864 n_he2=j1*rhe*n_h
865 kappa(ix^d)=max(zero,n_h1*s_h1+n_he1*s_he1+n_he2*s_he2)
866 endif
867 endif
868 endif
869 {enddo\}
870 end subroutine get_euv_hhe_opacity
871
872 subroutine get_pseudo_current(igrid,ixI^L,ixO^L,w,source)
873 integer, intent(in) :: igrid
874 integer, intent(in) :: ixI^L, ixO^L
875 double precision, intent(in) :: w(ixI^S,1:nw)
876 double precision, intent(out) :: source(ixI^S)
877
878 integer :: ix^D,idir,idirmin,idirmin0
879 double precision :: current(ixI^S,7-2*ndir:3)
880
881 if (.not. allocated(iw_mag)) then
882 call mpistop("emission_model=pseudo_current needs magnetic-field variables")
883 endif
884
885 idirmin0=7-2*ndir
886 current=zero
887 call curlvector(w(ixi^s,iw_mag(1:ndir)),ixi^l,ixo^l,current,idirmin,idirmin0,ndir)
888 if (b0field) then
889 current(ixo^s,idirmin0:3)=current(ixo^s,idirmin0:3)+ps(igrid)%J0(ixo^s,idirmin0:3)
890 endif
891
892 source(ixi^s)=zero
893 {do ix^db=ixomin^db,ixomax^db\}
894 do idir=idirmin0,3
895 source(ix^d)=source(ix^d)+current(ix^d,idir)**2
896 enddo
897 {enddo\}
898 end subroutine get_pseudo_current
899
900 subroutine get_radio_ff_source_opacity(ixI^L,ixO^L,w,x,fl,source,kappa)
901 use mod_eos, only: eos
902
903 integer, intent(in) :: ixI^L, ixO^L
904 double precision, intent(in) :: x(ixI^S,1:ndim)
905 double precision, intent(in) :: w(ixI^S,1:nw)
906 type(te_fluid), intent(in) :: fl
907 double precision, intent(out) :: source(ixI^S),kappa(ixI^S)
908
909 integer :: ix^D
910 double precision :: pth(ixI^S),Te(ixI^S),Ne(ixI^S)
911 double precision :: nH_dummy(ixI^S),gff
912
913 call fl%get_pthermal(w,x,ixi^l,ixo^l,pth)
914 call fl%get_rho(w,x,ixi^l,ixo^l,ne)
915 call fl%get_var_Rfactor(w,x,ixi^l,ixo^l,te)
916 te(ixo^s)=pth(ixo^s)/(ne(ixo^s)*te(ixo^s))*unit_temperature
917 call eos%get_ne_nH(ixi^l,ixo^l,w,ne,nh_dummy)
918 if (si_unit) then
919 ne(ixo^s)=ne(ixo^s)*unit_numberdensity/1.d6
920 else
921 ne(ixo^s)=ne(ixo^s)*unit_numberdensity
922 endif
923
924 source(ixi^s)=zero
925 kappa(ixi^s)=zero
926 {do ix^db=ixomin^db,ixomax^db\}
927 if (te(ix^d)>zero .and. ne(ix^d)>zero) then
928 if (te(ix^d)<2.d5) then
929 gff=18.2d0+1.5d0*log(te(ix^d))-log(radio_frequency)
930 else
931 gff=24.5d0+log(te(ix^d))-log(radio_frequency)
932 endif
933 gff=max(one,gff)
934 kappa(ix^d)=9.78d-3*ne(ix^d)**2*gff/(radio_frequency**2*te(ix^d)**1.5d0)
935 source(ix^d)=te(ix^d)*kappa(ix^d)
936 endif
937 {enddo\}
938 end subroutine get_radio_ff_source_opacity
939
940 subroutine get_line_info(wl,ion,mass,logTe,line_center,spatial_px,spectral_px,sigma_PSF,width_slit)
941 ! get information of the spectral line
942 ! wl: wavelength
943 ! mass: ion mass, unit -- proton mass
944 ! logTe: peak temperature of emission line in logarithm
945 ! line_center: center wavelength of emission line, unit -- Angstrom (0.1 nm)
946 ! spatial_px: pixel size in space of instrument (for image), unit -- arcsec
947 ! spectral_px: pixel size in wagelength of instrument (for spectrum), unit -- Angstrom
948 ! sigma_PSF: width of point spread function core (for instrument), unit -- pixel
949 ! width_slit: width of slit for spectrograph, unit -- arcsec
951
952 integer, intent(in) :: wl
953 integer, intent(out) :: mass
954 character(len=30), intent(out) :: ion
955 double precision, intent(out) :: logTe,line_center,spatial_px,spectral_px
956 double precision, intent(out) :: sigma_PSF,width_slit
957
958 select case(wl)
959 case(304)
960 ion='He II'
961 mass=4
962 logte=4.7d0
963 line_center=303.8d0
964 spatial_px=0.6d0
965 spectral_px=0.02d0
966 sigma_psf=0.895d0
967 width_slit=0.6d0
968 case(171)
969 ion='Fe IX'
970 mass=56
971 logte=5.8d0
972 line_center=171.1d0
973 spatial_px=0.6d0
974 spectral_px=0.02d0
975 sigma_psf=1.019d0
976 width_slit=0.6d0
977 case(193)
978 ion='Fe XXIV'
979 mass=56
980 logte=7.3d0
981 line_center=193.5d0
982 spatial_px=0.6d0
983 spectral_px=0.02d0
984 sigma_psf=0.813d0
985 width_slit=0.6d0
986 case(211)
987 ion='Fe XIV'
988 mass=56
989 logte=6.3d0
990 line_center=211.3d0
991 spatial_px=0.6d0
992 spectral_px=0.02d0
993 sigma_psf=0.913d0
994 width_slit=0.6d0
995 case(335)
996 ion='Fe XVI'
997 mass=56
998 logte=6.4d0
999 line_center=335.4d0
1000 spatial_px=0.6d0
1001 spectral_px=0.02d0
1002 sigma_psf=1.019d0
1003 width_slit=0.6d0
1004 case(94)
1005 ion='Fe XVIII'
1006 mass=56
1007 logte=6.8d0
1008 line_center=93.9d0
1009 spatial_px=0.6d0
1010 spectral_px=0.02d0
1011 sigma_psf=1.025d0
1012 width_slit=0.6d0
1013 case(131)
1014 ion='Fe XXI'
1015 mass=56
1016 logte=7.0d0
1017 line_center=131.0d0
1018 spatial_px=0.6d0
1019 spectral_px=0.02d0
1020 sigma_psf=0.984d0
1021 width_slit=0.6d0
1022 case(1354)
1023 ion='Fe XXI'
1024 mass=56
1025 logte=7.0d0
1026 line_center=1354.1d0
1027 spatial_px=0.1663d0
1028 spectral_px=12.98d-3
1029 sigma_psf=1.d0
1030 width_slit=0.33d0
1031 case(263)
1032 ion='Fe XVI'
1033 mass=56
1034 logte=6.4d0
1035 line_center=262.976d0
1036 spatial_px=1.d0
1037 spectral_px=22.d-3
1038 sigma_psf=1.d0
1039 width_slit=2.d0
1040 case(264)
1041 ion='Fe XXIII'
1042 mass=56
1043 logte=7.1d0
1044 line_center=263.765d0
1045 spatial_px=1.d0
1046 spectral_px=22.d-3
1047 sigma_psf=1.d0
1048 width_slit=2.d0
1049 case(192)
1050 ion='Fe XXIV'
1051 mass=56
1052 logte=7.2d0
1053 line_center=192.028d0
1054 spatial_px=1.d0
1055 spectral_px=22.d-3
1056 sigma_psf=1.d0
1057 width_slit=2.d0
1058 case(255)
1059 ion='Fe XXIV'
1060 mass=56
1061 logte=7.2d0
1062 line_center=255.113d0
1063 spatial_px=1.d0
1064 spectral_px=22.d-3
1065 sigma_psf=1.d0
1066 width_slit=2.d0
1067 case default
1068 call mpistop("No information about this line")
1069 end select
1070
1071 spatial_px=spatial_px/instrument_resolution_factor
1072 end subroutine get_line_info
1073
1074 subroutine get_euv(wl,ixI^L,ixO^L,w,x,fl,flux)
1075 ! calculate the local emission intensity of given EUV line (optically thin)
1076 ! wavelength is the wave length of the emission line
1077 ! unit [DN cm^-1 s^-1 pixel^-1]
1078 ! ingrate flux along line of sight: DN s^-1 pixel^-1
1080 use mod_eos, only: eos
1081
1082 integer, intent(in) :: wl
1083 integer, intent(in) :: ixI^L, ixO^L
1084 double precision, intent(in) :: x(ixI^S,1:ndim)
1085 double precision, intent(in) :: w(ixI^S,1:nw)
1086 type(te_fluid), intent(in) :: fl
1087 double precision, intent(out) :: flux(ixI^S)
1088
1089 integer :: ix^D
1090 double precision :: pth(ixI^S),Te(ixI^S),Ne(ixI^S)
1091
1092 call fl%get_pthermal(w,x,ixi^l,ixo^l,pth)
1093 call fl%get_rho(w,x,ixi^l,ixo^l,ne)
1094 call fl%get_var_Rfactor(w,x,ixi^l,ixo^l,te)
1095 te(ixo^s)=pth(ixo^s)/(ne(ixo^s)*te(ixo^s))*unit_temperature
1096 ! get actual electron density from EoS (replaces rho with ne)
1097 block
1098 double precision :: nH_dummy(ixI^S)
1099 call eos%get_ne_nH(ixi^l, ixo^l, w, ne, nh_dummy)
1100 end block
1101 if (si_unit) then
1102 ne(ixo^s)=ne(ixo^s)*unit_numberdensity/1.d6 ! m^-3 -> cm-3
1103 flux(ixo^s)=ne(ixo^s)**2
1104 else
1105 ne(ixo^s)=ne(ixo^s)*unit_numberdensity
1106 flux(ixo^s)=ne(ixo^s)**2
1107 endif
1108
1109 select case(wl)
1110 case(94)
1111 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_aia,f_94,n_aia,.true.,.true.)
1112 case(131)
1113 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_aia,f_131,n_aia,.true.,.true.)
1114 case(171)
1115 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_aia,f_171,n_aia,.true.,.true.)
1116 case(193)
1117 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_aia,f_193,n_aia,.true.,.true.)
1118 case(211)
1119 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_aia,f_211,n_aia,.true.,.true.)
1120 case(304)
1121 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_aia,f_304,n_aia,.true.,.true.)
1122 case(335)
1123 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_aia,f_335,n_aia,.true.,.true.)
1124 case(1354)
1125 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_iris,f_1354,n_iris,.true.,.true.)
1126 case(263)
1127 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_eis1,f_263,n_eis,.false.,.false.)
1128 case(264)
1129 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_eis2,f_264,n_eis,.false.,.false.)
1130 case(192)
1131 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_eis2,f_192,n_eis,.false.,.false.)
1132 case(255)
1133 call apply_temperature_response(ixi^l,ixo^l,te,flux,t_eis2,f_255,n_eis,.false.,.false.)
1134 case default
1135 call mpistop("Unknown wavelength")
1136 end select
1137 end subroutine get_euv
1138
1139 subroutine get_sxr(ixI^L,ixO^L,w,x,fl,flux,El,Eu)
1140 !synthesize thermal SXR from El keV to Eu keV released by cm^-3/m^-3
1141 ! volume of plasma in 1 s
1142 !flux (cgs): photons cm^-3 s^-1
1143 !flux (SI): photons m^-3 s^-1
1145 use mod_eos, only: eos
1146
1147 integer, intent(in) :: ixI^L,ixO^L
1148 integer, intent(in) :: El,Eu
1149 double precision, intent(in) :: x(ixI^S,1:ndim)
1150 double precision, intent(in) :: w(ixI^S,nw)
1151 type(te_fluid), intent(in) :: fl
1152 double precision, intent(out) :: flux(ixI^S)
1153
1154 integer :: ix^D,ixO^D
1155 integer :: iE,numE
1156 double precision :: I0,kb,keV,dE,Ei
1157 double precision :: pth(ixI^S),Te(ixI^S),kbT(ixI^S)
1158 double precision :: Ne(ixI^S),gff(ixI^S),fi(ixI^S)
1159 double precision :: EM(ixI^S)
1160
1161 i0=3.01d-15 ! I0*4*pi*AU**2, I0 from Pinto (2015)
1162 kb=const_kb
1163 kev=1.0d3*const_ev
1164 de=0.1
1165 nume=floor((eu-el)/de)
1166 call fl%get_pthermal(w,x,ixi^l,ixo^l,pth)
1167 call fl%get_rho(w,x,ixi^l,ixo^l,ne)
1168 call fl%get_var_Rfactor(w,x,ixi^l,ixo^l,te)
1169 te(ixo^s)=pth(ixo^s)/(ne(ixo^s)*te(ixo^s))*unit_temperature
1170 ! get actual electron density from EoS (replaces rho with ne)
1171 block
1172 double precision :: nH_dummy(ixI^S)
1173 call eos%get_ne_nH(ixi^l, ixo^l, w, ne, nh_dummy)
1174 end block
1175 if (si_unit) then
1176 ne(ixo^s)=ne(ixo^s)*unit_numberdensity/1.d6 ! m^-3 -> cm-3
1177 em(ixo^s)=(ne(ixo^s))**2*1.d6 ! cm^-3 m^-3
1178 else
1179 ne(ixo^s)=ne(ixo^s)*unit_numberdensity
1180 em(ixo^s)=(ne(ixo^s))**2
1181 endif
1182 kbt(ixo^s)=kb*te(ixo^s)/kev
1183 flux(ixo^s)=0.0d0
1184 do ie=0,nume-1
1185 ei=de*ie+el*1.d0
1186 gff(ixo^s)=1.d0
1187 {do ix^db=ixomin^db,ixomax^db\}
1188 if (kbt(ix^d)>0.01*ei) then
1189 if(kbt(ix^d)<ei) gff(ix^d)=(kbt(ix^d)/ei)**0.4
1190 fi(ix^d)=(em(ix^d)*gff(ix^d))*exp_clamped(-ei/(kbt(ix^d)))/(ei*dsqrt(kbt(ix^d)))
1191 else
1192 fi(ix^d)=zero
1193 endif
1194 {enddo\}
1195 flux(ixo^s)=flux(ixo^s)+fi(ixo^s)*de
1196 enddo
1197 flux(ixo^s)=flux(ixo^s)*i0
1198 end subroutine get_sxr
1199
1200 subroutine get_goes_sxr_flux(xbox^L,fl,eflux)
1201 !get GOES SXR 1-8A flux observing at 1AU from given box [w/m^2]
1203
1204 double precision, intent(in) :: xbox^L
1205 type(te_fluid), intent(in) :: fl
1206 double precision, intent(out) :: eflux
1207
1208 double precision :: dxb^D,xb^L
1209 integer :: iigrid,igrid,j
1210 integer :: ixO^L,ixI^L,ix^D
1211 double precision :: eflux_grid,eflux_pe
1212
1213 ^d&iximin^d=ixglo^d;
1214 ^d&iximax^d=ixghi^d;
1215 ^d&ixomin^d=ixmlo^d;
1216 ^d&ixomax^d=ixmhi^d;
1217 eflux_pe=zero
1218 do iigrid=1,igridstail; igrid=igrids(iigrid);
1219 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
1220 ^d&xbmin^d=rnode(rpxmin^d_,igrid);
1221 ^d&xbmax^d=rnode(rpxmax^d_,igrid);
1222 call get_goes_flux_grid(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,ps(igrid)%dvolume(ixi^s),xbox^l,xb^l,fl,eflux_grid)
1223 eflux_pe=eflux_pe+eflux_grid
1224 enddo
1225 call mpi_allreduce(eflux_pe,eflux,1,mpi_double_precision,mpi_sum,icomm,ierrmpi)
1226 end subroutine get_goes_sxr_flux
1227
1228 subroutine get_goes_flux_grid(ixI^L,ixO^L,w,x,dV,xbox^L,xb^L,fl,eflux_grid)
1230 use mod_eos, only: eos
1231
1232 integer, intent(in) :: ixI^L,ixO^L
1233 double precision, intent(in) :: x(ixI^S,1:ndim),dV(ixI^S)
1234 double precision, intent(in) :: w(ixI^S,nw)
1235 double precision, intent(in) :: xbox^L,xb^L
1236 type(te_fluid), intent(in) :: fl
1237 double precision, intent(out) :: eflux_grid
1238
1239 integer :: ix^D,ixO^D,ixb^L
1240 integer :: iE,numE,j,inbox
1241 double precision :: I0,kb,keV,dE,Ei,El,Eu,A_cgs
1242 double precision :: pth(ixI^S),Te(ixI^S),kbT(ixI^S)
1243 double precision :: Ne(ixI^S),EM(ixI^S)
1244 double precision :: gff,fi,erg_SI
1245
1246 ! check whether the grid is inside given box
1247 inbox=0
1248 {if (xbmin^d<xboxmax^d .and. xbmax^d>xboxmin^d) inbox=inbox+1\}
1249
1250 if (inbox==ndim) then
1251 ! indexes for cells inside given box
1252 ^d&ixbmin^d=ixomin^d;
1253 ^d&ixbmax^d=ixomax^d;
1254 {if (xbmax^d>xboxmax^d) ixbmax^d=ixomax^d-ceiling((xbmax^d-xboxmax^d)/dxlevel(^d))\}
1255 {if (xbmin^d<xboxmin^d) ixbmin^d=ceiling((xboxmin^d-xbmin^d)/dxlevel(^d))+ixomin^d\}
1256
1257 i0=1.07d-38 ! photon flux index for observed at 1AU [photon cm^3 m^-2 s^-1 keV^-1]
1258 kb=const_kb
1259 kev=1.0d3*const_ev
1260 erg_si=1.d-7
1261 a_cgs=1.d-8 ! Angstrom
1262 el=const_h*const_c/(8.d0*a_cgs)/kev ! 8 A
1263 eu=const_h*const_c/(1.d0*a_cgs)/kev ! 1 A
1264 de=0.1 ! keV
1265 nume=floor((eu-el)/de)
1266 call fl%get_pthermal(w,x,ixi^l,ixb^l,pth)
1267 call fl%get_rho(w,x,ixi^l,ixb^l,ne)
1268 call fl%get_var_Rfactor(w,x,ixi^l,ixb^l,te)
1269 te(ixb^s)=pth(ixb^s)/(ne(ixb^s)*te(ixb^s))*unit_temperature
1270 ! get actual electron density from EoS (replaces rho with ne)
1271 block
1272 double precision :: nH_dummy(ixI^S)
1273 call eos%get_ne_nH(ixi^l, ixb^l, w, ne, nh_dummy)
1274 end block
1275 if (si_unit) then
1276 ne(ixo^s)=ne(ixo^s)*unit_numberdensity/1.d6 ! m^-3 -> cm-3
1277 em(ixb^s)=(i0*(ne(ixb^s))**2)*dv(ixb^s)*(unit_length*1.d2)**3 ! cm^-3
1278 else
1279 ne(ixo^s)=ne(ixo^s)*unit_numberdensity
1280 em(ixb^s)=(i0*(ne(ixb^s))**2)*dv(ixb^s)*unit_length**3
1281 endif
1282 kbt(ixb^s)=kb*te(ixb^s)/kev
1283 eflux_grid=0.0d0
1284
1285 do ie=0,nume-1
1286 ei=de*ie+el
1287 {do ix^db=ixbmin^db,ixbmax^db\}
1288 if (kbt(ix^d)>1.d-2*ei) then
1289 if(kbt(ix^d)<ei) then
1290 gff=(kbt(ix^d)/ei)**0.4
1291 else
1292 gff=1.d0
1293 endif
1294 fi=(em(ix^d)*gff)*exp_clamped(-ei/(kbt(ix^d)))/(ei*dsqrt(kbt(ix^d)))
1295 eflux_grid=eflux_grid+fi*de*ei
1296 endif
1297 {enddo\}
1298 enddo
1299 eflux_grid=eflux_grid*kev*erg_si
1300 endif
1301
1302 end subroutine get_goes_flux_grid
1303
1304 {^ifthreed
1305 subroutine get_euv_spectrum(qunit,fl)
1307
1308 integer, intent(in) :: qunit
1309 type(te_fluid), intent(in) :: fl
1310 character(20) :: datatype
1311
1312 integer :: mass
1313 character (30) :: ion
1314 double precision :: logTe,lineCent,sigma_PSF,spaceRsl,wlRsl,wslit
1315 double precision :: xslit,arcsec
1316
1317 datatype='spectrum_euv'
1319 arcsec=7.25d7/unit_length
1320 call get_line_info(spectrum_wl,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
1321
1322 if (mype==0) print *, '###################################################'
1323 select case(spectrum_wl)
1324 case (1354)
1325 if (mype==0) print *, 'Systhesizing EUV spectrum (observed by IRIS).'
1326 case (263,264,192,255)
1327 if (mype==0) print *, 'Systhesizing EUV spectrum (observed by Hinode/EIS).'
1328 case default
1329 call mpistop('Wrong wavelength!')
1330 end select
1331
1333 call mpistop('Wrong spectrum window!')
1334 endif
1335
1336 if (mype==0) write(*,'(a,f8.3,a)') ' Wavelength: ',linecent,' Angstrom'
1337 if (mype==0) print *, 'Unit of EUV flux: DN s^-1 pixel^-1'
1338
1339 if (dat_resolution) then
1340 if (mype==0) then
1341 write(*,'(a,f5.3,a,f5.1,a)') ' Supposed pixel: ',wlrsl,' Angstrom x ',spacersl*725.0, ' km'
1342 print *, 'Unit of wavelength: Angstrom (0.1 nm) '
1343 if (si_unit) then
1344 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d6,' Mm'
1345 else
1346 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d8,' Mm'
1347 endif
1348 write(*,'(a,f8.1,a)') ' Supposed width of slit: ',wslit*725.0,' km'
1349 endif
1350 call get_spectrum_datresol(qunit,datatype,fl)
1351 else
1352 if (mype==0) then
1353 print *, 'Unit of wavelength: Angstrom (0.1 nm) '
1354 if (activate_unit_arcsec) then
1355 write(*,'(a,f5.3,a,f5.1,a)') ' Pixel: ',wlrsl,' Angstrom x ',spacersl*725.0, ' km'
1356 print *, 'Unit of length: arcsec (~725 km)'
1357 write(*,'(a,f8.1,a)') ' Location of slit: xI1 = ',location_slit,' arcsec'
1358 write(*,'(a,f8.1,a)') ' Width of slit: ',wslit,' arcsec'
1359 else
1360 if (si_unit) then
1361 if (mype==0) write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d6,' Mm'
1362 else
1363 if (mype==0) write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d8,' Mm'
1364 endif
1365 write(*,'(a,f8.1,a)') ' Location of slit: xI1 = ',location_slit,' Unit_length'
1366 write(*,'(a,f8.1,a)') ' Width of slit: ',wslit*725.d0,' km'
1367 endif
1368 endif
1369 if (mype==0) print *, 'Direction of the slit: parallel to xI2 vector'
1370 if (coordinate==cartesian .or. coordinate==spherical) then
1371 call get_spectrum(qunit,datatype,fl)
1372 else
1373 call mpistop("EUV spectrum synthesis: support for sperical coordinates is to be added!")
1374 endif
1375 endif
1376
1377 if (mype==0) print *, '###################################################'
1378
1379 end subroutine get_euv_spectrum
1380
1381 subroutine get_spectrum_datresol(qunit,datatype,fl)
1382
1383 integer, intent(in) :: qunit
1384 character(20), intent(in) :: datatype
1385 type(te_fluid), intent(in) :: fl
1386
1387 integer :: numWL,numXS,iwL,ixS,numWI,numS
1388 double precision :: dwLg,xSmin,xSmax,wLmin,wLmax
1389 double precision, allocatable :: wL(:),xS(:),dwL(:),dxS(:)
1390 double precision, allocatable :: wI(:,:,:),spectra(:,:),spectra_rc(:,:)
1391 integer :: strtype,nstrb,nbb,nuni,nstr,bnx
1392 double precision :: qs,dxfirst,dxmid,lenstr
1393
1394 integer :: iigrid,igrid,j,dir_loc
1395 double precision :: xbmin(1:ndim),xbmax(1:ndim)
1396
1397 dwlg=1.d-3
1398 numwl=4*int((spectrum_window_max-spectrum_window_min)/(4.d0*dwlg))
1399 wlmin=(spectrum_window_max+spectrum_window_min)/2.d0-dwlg*numwl/2
1400 wlmax=(spectrum_window_max+spectrum_window_min)/2.d0+dwlg*numwl/2
1401 allocate(wl(numwl),dwl(numwl))
1402 dwl(:)=dwlg
1403 do iwl=1,numwl
1404 wl(iwl)=wlmin+iwl*dwlg-half*dwlg
1405 enddo
1406
1407 select case(direction_slit)
1408 case (1)
1409 numxs=domain_nx1*2**(refine_max_level-1)
1410 xsmin=xprobmin1
1411 xsmax=xprobmax1
1412 bnx=block_nx1
1413 nbb=domain_nx1
1414 strtype=stretch_type(1)
1415 nstrb=nstretchedblocks_baselevel(1)
1416 qs=qstretch_baselevel(1)
1417 if (mype==0) print *, 'Direction of the slit: x'
1418 case (2)
1419 numxs=domain_nx2*2**(refine_max_level-1)
1420 xsmin=xprobmin2
1421 xsmax=xprobmax2
1422 bnx=block_nx2
1423 nbb=domain_nx2
1424 strtype=stretch_type(2)
1425 nstrb=nstretchedblocks_baselevel(2)
1426 qs=qstretch_baselevel(2)
1427 if (mype==0) print *, 'Direction of the slit: y'
1428 case (3)
1429 numxs=domain_nx3*2**(refine_max_level-1)
1430 xsmin=xprobmin3
1431 xsmax=xprobmax3
1432 bnx=block_nx3
1433 nbb=domain_nx3
1434 strtype=stretch_type(3)
1435 nstrb=nstretchedblocks_baselevel(3)
1436 qs=qstretch_baselevel(3)
1437 if (mype==0) print *, 'Direction of the slit: z'
1438 case default
1439 call mpistop('Wrong direction_slit')
1440 end select
1441
1442 allocate(xs(numxs),dxs(numxs),spectra(numwl,numxs),spectra_rc(numwl,numxs))
1443 numwi=1
1444 allocate(wi(numwl,numxs,numwi))
1445
1446 select case(strtype)
1447 case(0) ! uniform
1448 dxs(:)=(xsmax-xsmin)/numxs
1449 do ixs=1,numxs
1450 xs(ixs)=xsmin+dxs(ixs)*(ixs-half)
1451 enddo
1452 case(1) ! uni stretch
1453 qs=qs**(one/2**(refine_max_level-1))
1454 dxfirst=(xsmax-xsmin)*(one-qs)/(one-qs**numxs)
1455 dxs(1)=dxfirst
1456 do ixs=2,numxs
1457 dxs(ixs)=dxfirst*qs**(ixs-1)
1458 xs(ixs)=dxs(1)/(one-qs)*(one-qs**(ixs-1))+half*dxs(ixs)
1459 enddo
1460 case(2) ! symm stretch
1461 ! base level, nbb = nstr + nuni + nstr
1462 nstr=nstrb*bnx/2
1463 nuni=nbb-nstrb*bnx
1464 lenstr=(xsmax-xsmin)/(2.d0+nuni*(one-qs)/(one-qs**nstr))
1465 dxfirst=(xsmax-xsmin)/(dble(nuni)+2.d0/(one-qs)*(one-qs**nstr))
1466 dxmid=dxfirst
1467 ! refine_max level, numXI = nstr + nuni + nstr
1468 nstr=nstr*2**(refine_max_level-1)
1469 nuni=nuni*2**(refine_max_level-1)
1470 qs=qs**(one/2**(refine_max_level-1))
1471 dxfirst=lenstr*(one-qs)/(one-qs**nstr)
1472 dxmid=dxmid/2**(refine_max_level-1)
1473 ! uniform center
1474 if(nuni .gt. 0) then
1475 do ixs=nstr+1,nstr+nuni
1476 dxs(ixs)=dxmid
1477 xs(ixs)=lenstr+(dble(ixs)-0.5d0-nstr)*dxs(ixs)+xsmin
1478 enddo
1479 endif
1480 ! left half
1481 do ixs=nstr,1,-1
1482 dxs(ixs)=dxfirst*qs**(nstr-ixs)
1483 xs(ixs)=xsmin+lenstr-dxs(ixs)*half-dxfirst*(one-qs**(nstr-ixs))/(one-qs)
1484 enddo
1485 ! right half
1486 do ixs=nstr+nuni+1,numxs
1487 dxs(ixs)=dxfirst*qs**(ixs-nstr-nuni-1)
1488 xs(ixs)=xsmax-lenstr+dxs(ixs)*half+dxfirst*(one-qs**(ixs-nstr-nuni-1))/(one-qs)
1489 enddo
1490 case default
1491 call mpistop("unknown stretch type")
1492 end select
1493
1494 if (los_phi==0 .and. los_theta==90 .and. direction_slit==2) then
1495 ! LOS->x slit->y
1496 dir_loc=3
1497 else if (los_phi==0 .and. los_theta==90 .and. direction_slit==3) then
1498 ! LOS->x slit->z
1499 dir_loc=2
1500 else if (los_phi==90 .and. los_theta==90 .and. direction_slit==1) then
1501 ! LOS->y slit->x
1502 dir_loc=3
1503 else if (los_phi==90 .and. los_theta==90 .and. direction_slit==3) then
1504 ! LOS->y slit->z
1505 dir_loc=1
1506 else if (los_theta==0 .and. direction_slit==1) then
1507 ! LOS->z slit->x
1508 dir_loc=2
1509 else if (los_theta==0 .and. direction_slit==2) then
1510 ! LOS->z slit->y
1511 dir_loc=1
1512 else
1513 call mpistop('Wrong combination of LOS and slit direction!')
1514 endif
1515
1516 if (dir_loc==1) then
1517 if (location_slit>xprobmax1 .or. location_slit<xprobmin1) then
1518 call mpistop('Wrong value for location_slit!')
1519 endif
1520 if(mype==0) write(*,'(a,f8.1,a)') ' Location of slit: x = ',location_slit,' Unit_length'
1521 else if (dir_loc==2) then
1522 if (location_slit>xprobmax2 .or. location_slit<xprobmin2) then
1523 call mpistop('Wrong value for location_slit!')
1524 endif
1525 if(mype==0) write(*,'(a,f8.1,a)') ' Location of slit: y = ',location_slit,' Unit_length'
1526 else
1527 if (location_slit>xprobmax3 .or. location_slit<xprobmin3) then
1528 call mpistop('Wrong value for location_slit!')
1529 endif
1530 if(mype==0) write(*,'(a,f8.1,a)') ' Location of slit: z = ',location_slit,' Unit_length'
1531 endif
1532
1533 ! find slit and do integration
1534 spectra=zero
1535 do iigrid=1,igridstail; igrid=igrids(iigrid);
1536 ^d&xbmin(^d)=rnode(rpxmin^d_,igrid);
1537 ^d&xbmax(^d)=rnode(rpxmax^d_,igrid);
1538 if (location_slit>=xbmin(dir_loc) .and. location_slit<xbmax(dir_loc)) then
1539 call integrate_spectra_datresol(igrid,wl,dwl,spectra,numwl,numxs,dir_loc,fl)
1540 endif
1541 enddo
1542
1543 nums=numwl*numxs
1544 call mpi_allreduce(spectra,spectra_rc,nums,mpi_double_precision, &
1545 mpi_sum,icomm,ierrmpi)
1546 do iwl=1,numwl
1547 do ixs=1,numxs
1548 if (spectra_rc(iwl,ixs)>smalldouble) then
1549 wi(iwl,ixs,1)=spectra_rc(iwl,ixs)
1550 else
1551 wi(iwl,ixs,1)=zero
1552 endif
1553 enddo
1554 enddo
1555
1556 call output_data(qunit,wl,xs,dwl,dxs,wi,numwl,numxs,numwi,datatype)
1557
1558 deallocate(wl,xs,dwl,dxs,spectra,spectra_rc,wi)
1559
1560 end subroutine get_spectrum_datresol
1561
1562 subroutine integrate_spectra_datresol(igrid,wL,dwL,spectra,numWL,numXS,dir_loc,fl)
1563 use mod_constants
1564
1565 integer, intent(in) :: igrid,numWL,numXS,dir_loc
1566 type(te_fluid), intent(in) :: fl
1567 double precision, intent(in) :: wL(numWL),dwL(numWL)
1568 double precision, intent(inout) :: spectra(numWL,numXS)
1569
1570 integer :: direction_LOS
1571 integer :: ixO^L,ixI^L,ix^D,ixOnew
1572 double precision, allocatable :: flux(:^D&),v(:^D&),pth(:^D&),Te(:^D&),rho(:^D&)
1573 double precision :: wlc,wlwd
1574
1575 integer :: mass
1576 double precision :: logTe,lineCent
1577 character (30) :: ion
1578 double precision :: spaceRsl,wlRsl,sigma_PSF,wslit
1579
1580 integer :: levelg,rft,ixSmin,ixSmax,iwL
1581 double precision :: flux_pix,dL
1582
1583 call get_line_info(spectrum_wl,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
1584
1585 if (los_phi==0 .and. los_theta==90) then
1586 direction_los=1
1587 else if (los_phi==90 .and. los_theta==90) then
1588 direction_los=2
1589 else
1590 direction_los=3
1591 endif
1592
1593 ^d&ixomin^d=ixmlo^d\
1594 ^d&ixomax^d=ixmhi^d\
1595 ^d&iximin^d=ixglo^d\
1596 ^d&iximax^d=ixghi^d\
1597 allocate(flux(ixi^s),v(ixi^s),pth(ixi^s),te(ixi^s),rho(ixi^s))
1598
1599 ^d&ix^d=ixomin^d;
1600 if (dir_loc==1) then
1601 do ix1=ixomin1,ixomax1
1602 if (location_slit>=(ps(igrid)%x(ix^d,1)-half*ps(igrid)%dx(ix^d,1)) .and. &
1603 location_slit<(ps(igrid)%x(ix^d,1)+half*ps(igrid)%dx(ix^d,1))) then
1604 ixonew=ix1
1605 endif
1606 enddo
1607 ixomin1=ixonew
1608 ixomax1=ixonew
1609 else if (dir_loc==2) then
1610 do ix2=ixomin2,ixomax2
1611 if (location_slit>=(ps(igrid)%x(ix^d,2)-half*ps(igrid)%dx(ix^d,2)) .and. &
1612 location_slit<(ps(igrid)%x(ix^d,2)+half*ps(igrid)%dx(ix^d,2))) then
1613 ixonew=ix2
1614 endif
1615 enddo
1616 ixomin2=ixonew
1617 ixomax2=ixonew
1618 else
1619 do ix3=ixomin3,ixomax3
1620 if (location_slit>=(ps(igrid)%x(ix^d,3)-half*ps(igrid)%dx(ix^d,3)) .and. &
1621 location_slit<(ps(igrid)%x(ix^d,3)+half*ps(igrid)%dx(ix^d,3))) then
1622 ixonew=ix3
1623 endif
1624 enddo
1625 ixomin3=ixonew
1626 ixomax3=ixonew
1627 endif
1628
1629 call get_euv(spectrum_wl,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux)
1630 flux(ixo^s)=flux(ixo^s)/instrument_resolution_factor**2 ! adjust flux due to artifical change of resolution
1631 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,rho)
1632 v(ixo^s)=-ps(igrid)%w(ixo^s,iw_mom(direction_los))/rho(ixo^s)
1633 call fl%get_pthermal(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,pth)
1634 call fl%get_var_Rfactor(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,te)
1635 te(ixo^s)=pth(ixo^s)/(te(ixo^s)*rho(ixo^s))
1636
1637 ! grid parameters
1638 levelg=ps(igrid)%level
1639 rft=2**(refine_max_level-levelg)
1640
1641 {do ix^d=ixomin^d,ixomax^d\}
1642 if (flux(ix^d)>smalldouble) then
1643 if (si_unit) then
1644 wlc=linecent*(1.d0+v(ix^d)*unit_velocity*1.d2/const_c)
1645 else
1646 wlc=linecent*(1.d0+v(ix^d)*unit_velocity/const_c)
1647 endif
1648 wlwd=sqrt(kb_cgs*te(ix^d)*unit_temperature/(mass*mp_cgs))
1649 wlwd=wlwd*linecent/const_c
1650 ! involved pixel
1651 select case(direction_slit)
1652 case(1)
1653 ixsmin=(block_nx1*(node(pig1_,igrid)-1)+(ix1-ixomin1))*rft+1
1654 ixsmax=(block_nx1*(node(pig1_,igrid)-1)+(ix1-ixomin1+1))*rft
1655 case(2)
1656 ixsmin=(block_nx2*(node(pig2_,igrid)-1)+(ix2-ixomin2))*rft+1
1657 ixsmax=(block_nx2*(node(pig2_,igrid)-1)+(ix2-ixomin2+1))*rft
1658 case(3)
1659 ixsmin=(block_nx3*(node(pig3_,igrid)-1)+(ix3-ixomin3))*rft+1
1660 ixsmax=(block_nx3*(node(pig3_,igrid)-1)+(ix3-ixomin3+1))*rft
1661 end select
1662 ! LOS depth
1663 select case(direction_los)
1664 case(1)
1665 dl=ps(igrid)%dx(ix^d,1)*unit_length
1666 case(2)
1667 dl=ps(igrid)%dx(ix^d,2)*unit_length
1668 case default
1669 dl=ps(igrid)%dx(ix^d,3)*unit_length
1670 end select
1671 if (si_unit) dl=dl*1.d2
1672 ! integral pixel flux
1673 do iwl=1,numwl
1674 flux_pix=flux(ix^d)*wlrsl*dl*exp_clamped(-(wl(iwl)-wlc)**2/(2*wlwd**2))/(sqrt(2*dpi)*wlwd)
1675 if (flux_pix>smalldouble) then
1676 flux_pix=flux_pix*wslit/spacersl
1677 spectra(iwl,ixsmin:ixsmax)=spectra(iwl,ixsmin:ixsmax)+flux_pix
1678 endif
1679 enddo
1680 endif
1681 {enddo\}
1682
1683 deallocate(flux,v,pth,te,rho)
1684
1685 end subroutine integrate_spectra_datresol
1686
1687 subroutine get_spectrum(qunit,datatype,fl)
1688
1689 integer, intent(in) :: qunit
1690 character(20), intent(in) :: datatype
1691 type(te_fluid), intent(in) :: fl
1692
1693 integer :: numWL,numXS,iwL,ixS,numWI,ix^D
1694 double precision :: dwLg,dxSg,xSmin,xSmax,xScent,wLmin,wLmax
1695 double precision, allocatable :: wL(:),xS(:),dwL(:),dxS(:)
1696 double precision, allocatable :: wI(:,:,:),spectra(:,:),spectra_rc(:,:)
1697 double precision :: vec_cor(1:3),xI_cor(1:2)
1698 double precision :: res,r_loc,r_max
1699
1700 integer :: mass
1701 character (30) :: ion
1702 double precision :: logTe,lineCent,sigma_PSF,spaceRsl,wlRsl,wslit
1703 double precision :: unitv,arcsec,RHESSI_rsl,pixel
1704 integer :: iigrid,igrid,i,j,numS
1705 double precision :: xLmin,xLmax,xslit
1706
1707 if (coordinate==spherical) then
1709 else
1710 ! cartesian
1712 endif
1713
1714 ! calculate domain in space
1715 if (coordinate==spherical) then
1716 xsmin=-abs(xprobmax1)
1717 xsmax=abs(xprobmax1)
1718 else
1719 do ix1=1,2
1720 if (ix1==1) vec_cor(1)=xprobmin1
1721 if (ix1==2) vec_cor(1)=xprobmax1
1722 do ix2=1,2
1723 if (ix2==1) vec_cor(2)=xprobmin2
1724 if (ix2==2) vec_cor(2)=xprobmax2
1725 do ix3=1,2
1726 if (ix3==1) vec_cor(3)=xprobmin3
1727 if (ix3==2) vec_cor(3)=xprobmax3
1728 if (big_image) then
1729 r_loc=(vec_cor(1)-x_origin(1))**2
1730 r_loc=r_loc+(vec_cor(2)-x_origin(2))**2
1731 r_loc=r_loc+(vec_cor(3)-x_origin(3))**2
1732 r_loc=sqrt(r_loc)
1733 if (ix1==1 .and. ix2==1 .and. ix3==1) then
1734 r_max=r_loc
1735 else
1736 r_max=max(r_max,r_loc)
1737 endif
1738 else
1739 call get_cor_image(vec_cor,xi_cor)
1740 if (ix1==1 .and. ix2==1 .and. ix3==1) then
1741 xsmin=xi_cor(2)
1742 xsmax=xi_cor(2)
1743 else
1744 xsmin=min(xsmin,xi_cor(2))
1745 xsmax=max(xsmax,xi_cor(2))
1746 endif
1747 endif
1748 enddo
1749 enddo
1750 enddo
1751 if (big_image) then
1752 xsmin=-r_max
1753 xsmax=r_max
1754 endif
1755 endif
1756 xscent=(xsmin+xsmax)/2.d0
1757
1758 ! tables for storing spectra data
1759 if (si_unit) then
1760 arcsec=7.25d5/unit_length
1761 else
1762 arcsec=7.25d7/unit_length
1763 endif
1764 call get_line_info(spectrum_wl,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
1765 dxsg=spacersl*arcsec
1766 numxs=ceiling((xsmax-xscent)/dxsg)
1767 xsmin=xscent-numxs*dxsg
1768 xsmax=xscent+numxs*dxsg
1769 numxs=numxs*2
1770 dwlg=wlrsl
1771 numwl=2*int((spectrum_window_max-spectrum_window_min)/(2.d0*dwlg))
1772 wlmin=(spectrum_window_max+spectrum_window_min)/2.d0-dwlg*numwl/2
1773 wlmax=(spectrum_window_max+spectrum_window_min)/2.d0+dwlg*numwl/2
1774 allocate(wl(numwl),dwl(numwl),xs(numxs),dxs(numxs))
1775 numwi=1
1776 allocate(wi(numwl,numxs,numwi),spectra(numwl,numxs),spectra_rc(numwl,numxs))
1777 do iwl=1,numwl
1778 wl(iwl)=wlmin+iwl*dwlg-half*dwlg
1779 dwl=dwlg
1780 enddo
1781 do ixs=1,numxs
1782 xs(ixs)=xsmin+dxsg*(ixs-half)
1783 dxs(ixs)=dxsg
1784 enddo
1785
1786 ! find slit and do integration
1787 spectra=zero
1788 do iigrid=1,igridstail; igrid=igrids(iigrid);
1789 do ix1=1,2
1790 if (ix1==1) vec_cor(1)=rnode(rpxmin1_,igrid)
1791 if (ix1==2) vec_cor(1)=rnode(rpxmax1_,igrid)
1792 do ix2=1,2
1793 if (ix2==1) vec_cor(2)=rnode(rpxmin2_,igrid)
1794 if (ix2==2) vec_cor(2)=rnode(rpxmax2_,igrid)
1795 do ix3=1,2
1796 if (ix3==1) vec_cor(3)=rnode(rpxmin3_,igrid)
1797 if (ix3==2) vec_cor(3)=rnode(rpxmax3_,igrid)
1798 call get_cor_image(vec_cor,xi_cor)
1799 if (ix1==1 .and. ix2==1 .and. ix3==1) then
1800 xlmin=xi_cor(1)
1801 xlmax=xi_cor(1)
1802 else
1803 xlmin=min(xlmin,xi_cor(1))
1804 xlmax=max(xlmax,xi_cor(1))
1805 endif
1806 enddo
1807 enddo
1808 enddo
1809
1810 if (activate_unit_arcsec) then
1811 xslit=location_slit*arcsec
1812 else
1813 xslit=location_slit
1814 endif
1815 if (xslit>=xlmin-wslit*arcsec .and. xslit<=xlmax+wslit*arcsec) then
1816 call integrate_spectra_cartesian(igrid,wl,dwlg,xs,dxsg,spectra,numwl,numxs,fl)
1817 endif
1818 enddo
1819
1820 nums=numwl*numxs
1821 call mpi_allreduce(spectra,spectra_rc,nums,mpi_double_precision, &
1822 mpi_sum,icomm,ierrmpi)
1823 do iwl=1,numwl
1824 do ixs=1,numxs
1825 if (spectra_rc(iwl,ixs)>smalldouble) then
1826 wi(iwl,ixs,1)=spectra_rc(iwl,ixs)
1827 else
1828 wi(iwl,ixs,1)=zero
1829 endif
1830 enddo
1831 enddo
1832
1833 if (activate_unit_arcsec) then
1834 xs=xs/arcsec
1835 dxs=dxs/arcsec
1836 endif
1837
1838 call output_data(qunit,wl,xs,dwl,dxs,wi,numwl,numxs,numwi,datatype)
1839
1840 deallocate(wl,xs,dwl,dxs,spectra,spectra_rc,wi)
1841
1842 end subroutine get_spectrum
1843
1844 subroutine integrate_spectra_cartesian(igrid,wL,dwLg,xS,dxSg,spectra,numWL,numXS,fl)
1845
1846 integer, intent(in) :: igrid,numWL,numXS
1847 double precision, intent(in) :: wL(numWL),xS(numXS)
1848 double precision, intent(in) :: dwLg,dxSg
1849 double precision, intent(inout) :: spectra(numWL,numXS)
1850 type(te_fluid), intent(in) :: fl
1851
1852 integer :: ixO^L,ixI^L,ix^D,ixOnew,j
1853 double precision, allocatable :: flux(:^D&),v(:^D&),pth(:^D&),Te(:^D&),rho(:^D&)
1854 double precision :: wlc,wlwd,res,dst_slit,xslit,arcsec
1855 double precision :: vloc(1:3),xloc(1:3),dxloc(1:3),xIloc(1:2),dxIloc(1:2)
1856 integer :: nSubC^D,iSubC^D,iwL,ixS,ixSmin,ixSmax,iwLmin,iwLmax,nwL
1857 double precision :: slit_width,dxSubC^D,xerf^L,fluxSubC
1858 double precision :: xSubC(1:3),xCent(1:2)
1859
1860 integer :: mass
1861 double precision :: logTe,lineCent
1862 character (30) :: ion
1863 double precision :: spaceRsl,wlRsl,sigma_PSF,wslit
1864 double precision :: sigma_wl,sigma_xs,factor
1865
1866 if (si_unit) then
1867 arcsec=7.25d5/unit_length
1868 else
1869 arcsec=7.25d7/unit_length
1870 endif
1871 if (activate_unit_arcsec) then
1872 xslit=location_slit*arcsec
1873 else
1874 xslit=location_slit
1875 endif
1876
1877 call get_line_info(spectrum_wl,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
1878
1879 ^d&ixomin^d=ixmlo^d\
1880 ^d&ixomax^d=ixmhi^d\
1881 ^d&iximin^d=ixglo^d\
1882 ^d&iximax^d=ixghi^d\
1883 allocate(flux(ixi^s),v(ixi^s),pth(ixi^s),te(ixi^s),rho(ixi^s))
1884 ! get local EUV flux and velocity
1885 call get_euv(spectrum_wl,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux)
1886 flux(ixo^s)=flux(ixo^s)/instrument_resolution_factor**2 ! adjust flux due to artifical change of resolution
1887 call fl%get_pthermal(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,pth)
1888 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,rho)
1889 call fl%get_var_Rfactor(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,te)
1890 te(ixo^s)=pth(ixo^s)/(te(ixo^s)*rho(ixo^s))
1891 {do ix^d=ixomin^d,ixomax^d\}
1892 do j=1,3
1893 vloc(j)=ps(igrid)%w(ix^d,iw_mom(j))/rho(ix^d)
1894 enddo
1895 call dot_product_loc(vloc,vec_los,res)
1896 v(ix^d)=res
1897 {enddo\}
1898
1899 deallocate(rho)
1900
1901 slit_width=wslit*arcsec
1902 sigma_wl=sigma_psf*dwlg
1903 sigma_xs=sigma_psf*dxsg
1904 {do ix^d=ixomin^d,ixomax^d\}
1905 if (flux(ix^d)>smalldouble) then
1906 xloc(1:3)=ps(igrid)%x(ix^d,1:3)
1907 dxloc(1:3)=ps(igrid)%dx(ix^d,1:3)
1908 call get_cor_image(xloc,xiloc)
1909 call dot_product_loc(dxloc,vec_xi1,res)
1910 dxiloc(1)=abs(res)
1911 if (xiloc(1)>=xslit-half*(slit_width+dxiloc(1)) .and. &
1912 xiloc(1)<=xslit+half*(slit_width+dxiloc(1))) then
1913 ^d&nsubc^d=1;
1914 ^d&nsubc^d=max(nsubc^d,ceiling(ps(igrid)%dx(ix^dd,^d)*abs(vec_xi1(^d))/(slit_width/16.d0)));
1915 ^d&nsubc^d=max(nsubc^d,ceiling(ps(igrid)%dx(ix^dd,^d)*abs(vec_xi2(^d))/(dxsg/4.d0)));
1916 ^d&dxsubc^d=ps(igrid)%dx(ix^dd,^d)/nsubc^d;
1917 ! local line center and line width
1918 if (si_unit) then
1919 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length*1.d2/dxsg/dxsg ! DN s^-1
1920 wlc=linecent*(1.d0+v(ix^d)*unit_velocity*1.d2/const_c)
1921 else
1922 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length/dxsg/dxsg ! DN s^-1
1923 wlc=linecent*(1.d0+v(ix^d)*unit_velocity/const_c)
1924 endif
1925 wlwd=sqrt(kb_cgs*te(ix^d)*unit_temperature/(mass*mp_cgs))
1926 wlwd=wlwd*linecent/const_c
1927 ! dividing a cell to several parts to get more accurate integrating values
1928 {do isubc^d=1,nsubc^d\}
1929 ^d&xsubc(^d)=xloc(^d)-half*dxloc(^d)+(isubc^d-half)*dxsubc^d;
1930 call get_cor_image(xsubc,xcent)
1931 dst_slit=abs(xcent(1)-xslit) ! space distance to slit center
1932 if (dst_slit<=half*slit_width) then
1933 ixs=floor((xcent(2)-(xs(1)-half*dxsg))/dxsg)+1
1934 ixsmin=max(1,ixs-3)
1935 ixsmax=min(ixs+3,numxs)
1936 iwl=floor((wlc-(wl(1)-half*dwlg))/dwlg)+1
1937 nwl=3*ceiling(wlwd/dwlg+1)
1938 iwlmin=max(1,iwl-nwl)
1939 iwlmax=min(iwl+nwl,numwl)
1940 ! calculate the contribution to nearby pixels
1941 do iwl=iwlmin,iwlmax
1942 do ixs=ixsmin,ixsmax
1943 xerfmin1=(wl(iwl)-half*dwlg-wlc)/sqrt(2.d0*(sigma_wl**2+wlwd**2))
1944 xerfmax1=(wl(iwl)+half*dwlg-wlc)/sqrt(2.d0*(sigma_wl**2+wlwd**2))
1945 xerfmin2=(xs(ixs)-half*dxsg-xcent(2))/(sqrt(2.d0)*sigma_xs)
1946 xerfmax2=(xs(ixs)+half*dxsg-xcent(2))/(sqrt(2.d0)*sigma_xs)
1947 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
1948 spectra(iwl,ixs)=spectra(iwl,ixs)+fluxsubc*factor
1949 enddo
1950 enddo
1951 ! nearby pixels
1952 endif
1953 {enddo\}
1954 endif
1955 endif
1956 {enddo\}
1957
1958 deallocate(flux,v,pth,te)
1959 end subroutine integrate_spectra_cartesian
1960 }
1961
1962 {^ifthreed
1963 subroutine get_euv_image(qunit,fl)
1965
1966 integer, intent(in) :: qunit
1967 type(te_fluid), intent(in) :: fl
1968 character(20) :: datatype
1969
1970 integer :: mass
1971 character (30) :: ion
1972 double precision :: logTe,lineCent,sigma_PSF,spaceRsl,wlRsl,wslit
1973 double precision :: t0,t1
1974
1975 t0=mpi_wtime()
1976 datatype='image_euv'
1978 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
1979
1980 if (mype==0) then
1981 print *, '###################################################'
1982 print *, 'Systhesizing EUV image'
1983 write(*,'(a,f8.3,a)') ' Wavelength: ',linecent,' Angstrom'
1984 print *, 'Unit of EUV flux: DN s^-1 pixel^-1'
1985 endif
1986
1987 if (dat_resolution) then
1988 if (.not. slab .and. .not. (coordinate==spherical .and. trim(ray_method_active)=='spherical')) &
1989 call mpistop('EUV dat-resolution needs Cartesian or spherical native rays')
1990 if (mype==0) then
1991 write(*,'(a,f7.1,a,f7.1,a,f5.1,a,f5.1,a)') ' Supposed Pixel: ',spacersl*725.0,' km x ',spacersl*725.0, &
1992 ' km (', spacersl, ' arcsec x ', spacersl, ' arcsec)'
1993 if (si_unit) then
1994 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d6,' Mm'
1995 else
1996 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d8,' Mm'
1997 endif
1998 endif
1999 if (coordinate==spherical .and. trim(ray_method_active)=='spherical') then
2000 call get_image_datresol(qunit,datatype,fl)
2001 else if (trim(ray_method_active)=='cart') then
2002 call get_image_datresol(qunit,datatype,fl)
2003 else if (los_phi==0 .and. los_theta==90) then
2004 call get_image_datresol(qunit,datatype,fl)
2005 else if (los_phi==90 .and. los_theta==90) then
2006 call get_image_datresol(qunit,datatype,fl)
2007 else if (los_theta==0) then
2008 call get_image_datresol(qunit,datatype,fl)
2009 else
2010 call mpistop('ERROR: Wrong LOS for synthesizing emission!')
2011 endif
2012 else
2013 if (mype==0) then
2014 write(*,'(a,f7.1,a,f7.1,a,f5.1,a,f5.1,a)') ' Pixel: ',spacersl*725.0,' km x ',spacersl*725.0, ' km (', &
2015 spacersl, ' arcsec x ', spacersl, ' arcsec)'
2016 if (activate_unit_arcsec) then
2017 print *, 'Unit of length: arcsec (~725 km)'
2018 else
2019 if (si_unit) then
2020 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d6,' Mm'
2021 else
2022 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d8,' Mm'
2023 endif
2024 endif
2025 endif
2026 if (coordinate==cartesian) then
2027 if (mype==0) write(*,'(a,f8.3,f8.3,f8.3,a)') ' Mapping: [',x_origin(1),x_origin(2),x_origin(3), &
2028 '] of the simulation box is located at [X=0,Y=0] of the image'
2029 call get_image(qunit,datatype,fl)
2030 else if (coordinate==spherical) then
2031 if (mype==0) write(*,'(a,f6.3,f8.3,f8.3,a)') ' Mapping: R=0 of the simulation box is located at [X=0,Y=0] of the image'
2032 call get_image(qunit,datatype,fl)
2033 else
2034 call mpistop("EUV synthesis: this coordinate is not supported!")
2035 endif
2036 endif
2037
2038 t1=mpi_wtime()
2039 if (mype==0) print *, 'time comsuming: ',t1-t0,' s'
2040 if (mype==0) print *, '###################################################'
2041
2042 end subroutine get_euv_image
2043
2044 subroutine get_sxr_image(qunit,fl)
2046
2047 integer, intent(in) :: qunit
2048 type(te_fluid), intent(in) :: fl
2049 character(20) :: datatype
2050 double precision :: RHESSI_rsl
2051 double precision :: t0,t1
2052
2053 t0=mpi_wtime()
2054 datatype='image_sxr'
2056 rhessi_rsl=2.3/instrument_resolution_factor
2057
2058 if (mype==0) then
2059 print *, '###################################################'
2060 print *, 'Systhesizing SXR image (observed at 1 AU).'
2061 write(*,'(a,i2,a,i2,a)') ' Passband: ',emin_sxr,' - ',emax_sxr,' keV'
2062 endif
2063
2064 if (dat_resolution) then
2065 if (coordinate/=cartesian) call mpistop('SXR synthesis: only cartesian is supported for .dat resolution!')
2066 if (mype==0) then
2067 print *, 'Unit of SXR flux: photons cm^-2 s^-1 pixel^-1'
2068 write(*,'(a,f5.1,a,f5.1,a,f5.1,a,f5.1,a)') ' Supposed Pixel: ',rhessi_rsl*0.725, ' Mm x ',rhessi_rsl*0.725, &
2069 ' Mm (', rhessi_rsl, ' arcsec x ', rhessi_rsl, ' arcsec)'
2070 if (si_unit) then
2071 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d6,' Mm'
2072 else
2073 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d8,' Mm'
2074 endif
2075 endif
2076 if (los_phi==0 .and. los_theta==90) then
2077 call get_image_datresol(qunit,datatype,fl)
2078 else if (los_phi==90 .and. los_theta==90) then
2079 call get_image_datresol(qunit,datatype,fl)
2080 else if (los_theta==0) then
2081 call get_image_datresol(qunit,datatype,fl)
2082 else
2083 call mpistop('ERROR: Wrong LOS for synthesizing emission!')
2084 endif
2085 else
2086 if (mype==0) then
2087 print *, 'Unit of SXR flux: photons cm^-2 s^-1 pixel^-1'
2088 write(*,'(a,f5.1,a,f5.1,a,f5.1,a,f5.1,a)') ' Pixel: ',rhessi_rsl*0.725, ' Mm x ',rhessi_rsl*0.725, &
2089 ' Mm (', rhessi_rsl, ' arcsec x ', rhessi_rsl, ' arcsec)'
2090 if (activate_unit_arcsec) then
2091 print *, 'Unit of length: arcsec (~725 km)'
2092 else
2093 if (si_unit) then
2094 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d6,' Mm'
2095 else
2096 write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d8,' Mm'
2097 endif
2098 endif
2099 endif
2100 if (coordinate==cartesian) then
2101 if (mype==0) write(*,'(a,f8.3,f8.3,f8.3,a)') ' Mapping: [',x_origin(1),x_origin(2),x_origin(3), &
2102 '] of the simulation box is located at [X=0,Y=0] of the image'
2103 call get_image(qunit,datatype,fl)
2104 else if (coordinate==spherical) then
2105 if (mype==0) write(*,'(a,f6.3,f8.3,f8.3,a)') ' Mapping: R=0 of the simulation box is located at [X=0,Y=0] of the image'
2106 call get_image(qunit,datatype,fl)
2107 else
2108 call mpistop("SXR synthesis: this coordinate is not supported!")
2109 endif
2110 endif
2111
2112 t1=mpi_wtime()
2113 if (mype==0) print *, 'time comsuming:',t1-t0
2114 if (mype==0) print *, '###################################################'
2115
2116 end subroutine get_sxr_image
2117
2118 subroutine get_whitelight_image(qunit,fl)
2120
2121 integer, intent(in) :: qunit
2122 type(te_fluid), intent(in) :: fl
2123 character(20) :: datatype
2124 double precision :: LASCO_rsl
2125
2126 if (mype==0) print *, '###################################################'
2127
2128 if (whitelight_instrument=='LASCO/C1') then
2129 lasco_rsl=5.6d0/instrument_resolution_factor
2130 if (mype==0) print *, 'Systhesizing white light image (observed by LASCO/C1).'
2131 else if (whitelight_instrument=='LASCO/C2') then
2132 lasco_rsl=11.4d0/instrument_resolution_factor
2133 if (mype==0) print *, 'Systhesizing white light image (observed by LASCO/C2).'
2134 else if (whitelight_instrument=='LASCO/C3') then
2135 lasco_rsl=56.d0/instrument_resolution_factor
2136 if (mype==0) print *, 'Systhesizing white light image (observed by LASCO/C3).'
2137 else
2138 call mpistop('Whitelight synthesis: instrument is not supported!')
2139 endif
2140
2141 if (mype==0) write(*,'(a,f5.1,a,f5.1,a,f5.1,a,f5.1,a)') ' Pixel: ',lasco_rsl*0.725,' Mm x ',lasco_rsl*0.725, ' Mm (', &
2142 lasco_rsl, ' arcsec x ', lasco_rsl, ' arcsec) '
2143 if (mype==0) print *, 'Unit of white light flux: average Sun brightness'
2144
2145 datatype='image_whitelight'
2147
2148 if (mype==0) then
2149 if (activate_unit_arcsec) then
2150 print *, 'Unit of length: arcsec (~725 km)'
2151 else
2152 if (si_unit) then
2153 if (mype==0) write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d6,' Mm'
2154 else
2155 if (mype==0) write(*,'(a,f8.1,a)') ' Unit of length: ',unit_length/1.d8,' Mm'
2156 endif
2157 endif
2158 endif
2159
2160 if (coordinate==spherical) then
2161 if (mype==0) write(*,'(a,f6.3,f8.3,f8.3,a)') ' Mapping: R=0 of the simulation box is located at [X=0,Y=0] of the image'
2162 call get_image(qunit,datatype,fl)
2163 else
2164 call mpistop("Whitelight synthesis: this coordinate is not supported!")
2165 endif
2166
2167 if (mype==0) print *, '###################################################'
2168
2169 end subroutine get_whitelight_image
2170
2171 subroutine postprocess_euv_instrument_image(nSrc1,nSrc2,xSrc1,xSrc2,dxSrc1,dxSrc2,&
2172 EUV,Dpl,nOut1,nOut2,xOut1,xOut2,&
2173 dxOut1,dxOut2,wOut,numWOut,Tau,EUVthin)
2175 use mod_constants
2176
2177 integer, intent(in) :: nSrc1,nSrc2
2178 double precision, intent(in) :: xSrc1(nSrc1),xSrc2(nSrc2)
2179 double precision, intent(in) :: dxSrc1(nSrc1),dxSrc2(nSrc2)
2180 double precision, intent(in) :: EUV(nSrc1,nSrc2),Dpl(nSrc1,nSrc2)
2181 integer, intent(out) :: nOut1,nOut2,numWOut
2182 double precision, allocatable, intent(out) :: xOut1(:),xOut2(:),dxOut1(:),dxOut2(:)
2183 double precision, allocatable, intent(out) :: wOut(:,:,:)
2184 double precision, intent(in), optional :: Tau(nSrc1,nSrc2),EUVthin(nSrc1,nSrc2)
2185
2186 integer :: mass,ixS1,ixS2,ixP1,ixP2,ixC1,ixC2,iw
2187 integer :: ixPmin1,ixPmax1,ixPmin2,ixPmax2
2188 character(30) :: ion
2189 double precision :: logTe,lineCent,spaceRsl,wlRsl,sigma_PSF,wslit
2190 double precision :: arcsec,dxInst,xMin1,xMax1,xMin2,xMax2,xCent1,xCent2
2191 double precision :: sigma0,xerfmin1,xerfmax1,xerfmin2,xerfmax2
2192 double precision :: factor,weightSum,weightNorm,thinVal,tauVal
2193 double precision, allocatable :: dplNum(:,:),thinOut(:,:),tauOut(:,:),tauWeight(:,:)
2194
2195 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
2196 if (si_unit) then
2197 arcsec=7.25d5/unit_length
2198 else
2199 arcsec=7.25d7/unit_length
2200 endif
2201 dxinst=spacersl*arcsec
2202 if (dxinst<=zero) call mpistop("instrument_postprocess has non-positive pixel size")
2203
2204 xmin1=minval(xsrc1-half*dxsrc1)
2205 xmax1=maxval(xsrc1+half*dxsrc1)
2206 xmin2=minval(xsrc2-half*dxsrc2)
2207 xmax2=maxval(xsrc2+half*dxsrc2)
2208 xcent1=half*(xmin1+xmax1)
2209 xcent2=half*(xmin2+xmax2)
2210 nout1=16*max(1,ceiling((xmax1-xmin1)/(16.d0*dxinst)))
2211 nout2=16*max(1,ceiling((xmax2-xmin2)/(16.d0*dxinst)))
2212 xmin1=xcent1-half*dble(nout1)*dxinst
2213 xmin2=xcent2-half*dble(nout2)*dxinst
2214
2215 allocate(xout1(nout1),xout2(nout2),dxout1(nout1),dxout2(nout2))
2216 do ixp1=1,nout1
2217 xout1(ixp1)=xmin1+dxinst*(dble(ixp1)-half)
2218 dxout1(ixp1)=dxinst
2219 enddo
2220 do ixp2=1,nout2
2221 xout2(ixp2)=xmin2+dxinst*(dble(ixp2)-half)
2222 dxout2(ixp2)=dxinst
2223 enddo
2224
2225 numwout=2
2226 if (present(tau) .and. output_tau) numwout=numwout+1
2227 if (present(euvthin) .and. output_absorption_fraction) numwout=numwout+1
2228 allocate(wout(nout1,nout2,numwout),dplnum(nout1,nout2))
2229 wout=zero
2230 dplnum=zero
2231 if (present(euvthin)) then
2232 allocate(thinout(nout1,nout2))
2233 thinout=zero
2234 endif
2235 if (present(tau) .and. output_tau) then
2236 allocate(tauout(nout1,nout2),tauweight(nout1,nout2))
2237 tauout=zero
2238 tauweight=zero
2239 endif
2240
2241 sigma0=sigma_psf*dxinst
2242 do ixs1=1,nsrc1
2243 do ixs2=1,nsrc2
2244 thinval=zero
2245 tauval=zero
2246 if (present(euvthin)) thinval=euvthin(ixs1,ixs2)
2247 if (present(tau)) tauval=tau(ixs1,ixs2)
2248 if (abs(euv(ixs1,ixs2))<=smalldouble .and. abs(thinval)<=smalldouble .and. &
2249 abs(tauval)<=smalldouble) cycle
2250
2251 ixc1=floor((xsrc1(ixs1)-(xout1(1)-half*dxinst))/dxinst)+1
2252 ixc2=floor((xsrc2(ixs2)-(xout2(1)-half*dxinst))/dxinst)+1
2253 ixpmin1=max(1,ixc1-3)
2254 ixpmax1=min(nout1,ixc1+3)
2255 ixpmin2=max(1,ixc2-3)
2256 ixpmax2=min(nout2,ixc2+3)
2257
2258 weightsum=zero
2259 do ixp1=ixpmin1,ixpmax1
2260 do ixp2=ixpmin2,ixpmax2
2261 xerfmin1=((xout1(ixp1)-half*dxinst)-xsrc1(ixs1))/(sqrt(2.d0)*sigma0)
2262 xerfmax1=((xout1(ixp1)+half*dxinst)-xsrc1(ixs1))/(sqrt(2.d0)*sigma0)
2263 xerfmin2=((xout2(ixp2)-half*dxinst)-xsrc2(ixs2))/(sqrt(2.d0)*sigma0)
2264 xerfmax2=((xout2(ixp2)+half*dxinst)-xsrc2(ixs2))/(sqrt(2.d0)*sigma0)
2265 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
2266 weightsum=weightsum+factor
2267 enddo
2268 enddo
2269 if (weightsum<=zero) cycle
2270
2271 do ixp1=ixpmin1,ixpmax1
2272 do ixp2=ixpmin2,ixpmax2
2273 xerfmin1=((xout1(ixp1)-half*dxinst)-xsrc1(ixs1))/(sqrt(2.d0)*sigma0)
2274 xerfmax1=((xout1(ixp1)+half*dxinst)-xsrc1(ixs1))/(sqrt(2.d0)*sigma0)
2275 xerfmin2=((xout2(ixp2)-half*dxinst)-xsrc2(ixs2))/(sqrt(2.d0)*sigma0)
2276 xerfmax2=((xout2(ixp2)+half*dxinst)-xsrc2(ixs2))/(sqrt(2.d0)*sigma0)
2277 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
2278 weightnorm=factor/weightsum
2279 wout(ixp1,ixp2,1)=wout(ixp1,ixp2,1)+euv(ixs1,ixs2)*weightnorm
2280 dplnum(ixp1,ixp2)=dplnum(ixp1,ixp2)+euv(ixs1,ixs2)*dpl(ixs1,ixs2)*weightnorm
2281 if (present(euvthin)) thinout(ixp1,ixp2)=thinout(ixp1,ixp2)+thinval*weightnorm
2282 if (present(tau) .and. output_tau) then
2283 tauout(ixp1,ixp2)=tauout(ixp1,ixp2)+tauval*weightnorm
2284 tauweight(ixp1,ixp2)=tauweight(ixp1,ixp2)+weightnorm
2285 endif
2286 enddo
2287 enddo
2288 enddo
2289 enddo
2290
2291 do ixp1=1,nout1
2292 do ixp2=1,nout2
2293 if (wout(ixp1,ixp2,1)>smalldouble) then
2294 wout(ixp1,ixp2,2)=dplnum(ixp1,ixp2)/wout(ixp1,ixp2,1)
2295 else
2296 wout(ixp1,ixp2,2)=zero
2297 endif
2298 enddo
2299 enddo
2300 iw=2
2301 if (present(tau) .and. output_tau) then
2302 iw=iw+1
2303 do ixp1=1,nout1
2304 do ixp2=1,nout2
2305 if (tauweight(ixp1,ixp2)>zero) then
2306 wout(ixp1,ixp2,iw)=tauout(ixp1,ixp2)/tauweight(ixp1,ixp2)
2307 else
2308 wout(ixp1,ixp2,iw)=zero
2309 endif
2310 enddo
2311 enddo
2312 endif
2313 if (present(euvthin) .and. output_absorption_fraction) then
2314 iw=iw+1
2315 do ixp1=1,nout1
2316 do ixp2=1,nout2
2317 if (thinout(ixp1,ixp2)>smalldouble) then
2318 wout(ixp1,ixp2,iw)=min(one,max(zero,(thinout(ixp1,ixp2)-wout(ixp1,ixp2,1))/thinout(ixp1,ixp2)))
2319 else
2320 wout(ixp1,ixp2,iw)=zero
2321 endif
2322 enddo
2323 enddo
2324 endif
2325
2326 if (mype==0) then
2327 write(*,'(a,2(i8,1x),a,2(i8,1x),a,1pe12.5)') &
2328 ' instrument_postprocess EUV grid src/out: ',nsrc1,nsrc2,' -> ',nout1,nout2,' dx=',dxinst
2329 endif
2330
2331 deallocate(dplnum)
2332 if (allocated(thinout)) deallocate(thinout)
2333 if (allocated(tauout)) deallocate(tauout,tauweight)
2335
2336 subroutine postprocess_radio_beam_image(nSrc1,nSrc2,xSrc1,xSrc2,dxSrc1,dxSrc2,&
2337 Bright,nOut1,nOut2,xOut1,xOut2,&
2338 dxOut1,dxOut2,wOut,numWOut,Tau,BrightThin)
2340
2341 integer, intent(in) :: nSrc1,nSrc2
2342 double precision, intent(in) :: xSrc1(nSrc1),xSrc2(nSrc2)
2343 double precision, intent(in) :: dxSrc1(nSrc1),dxSrc2(nSrc2)
2344 double precision, intent(in) :: Bright(nSrc1,nSrc2)
2345 integer, intent(out) :: nOut1,nOut2,numWOut
2346 double precision, allocatable, intent(out) :: xOut1(:),xOut2(:),dxOut1(:),dxOut2(:)
2347 double precision, allocatable, intent(out) :: wOut(:,:,:)
2348 double precision, intent(in), optional :: Tau(nSrc1,nSrc2),BrightThin(nSrc1,nSrc2)
2349
2350 integer :: ixS1,ixS2,ixP1,ixP2,ixC1,ixC2,iw,nStencil
2351 integer :: ixPmin1,ixPmax1,ixPmin2,ixPmax2
2352 double precision :: arcsec,beamPixel,beamSigma,xMin1,xMax1,xMin2,xMax2,xCent1,xCent2
2353 double precision :: distance1,distance2,weight,cellArea,thinVal,tauVal
2354 double precision, allocatable :: norm(:,:),thinOut(:,:),tauOut(:,:),tauNorm(:,:)
2355
2356 if (si_unit) then
2357 arcsec=7.25d5/unit_length
2358 else
2359 arcsec=7.25d7/unit_length
2360 endif
2361 beamsigma=radio_beam_fwhm*arcsec/sqrt(8.d0*log(2.d0))
2362 if (radio_beam_pixel_size>zero) then
2363 beampixel=radio_beam_pixel_size*arcsec
2364 else
2365 beampixel=radio_beam_fwhm*arcsec/3.d0
2366 endif
2367 if (beamsigma<=zero .or. beampixel<=zero) then
2368 call mpistop("radio beam postprocess has non-positive beam or pixel size")
2369 endif
2370
2371 xmin1=minval(xsrc1-half*dxsrc1)
2372 xmax1=maxval(xsrc1+half*dxsrc1)
2373 xmin2=minval(xsrc2-half*dxsrc2)
2374 xmax2=maxval(xsrc2+half*dxsrc2)
2375 xcent1=half*(xmin1+xmax1)
2376 xcent2=half*(xmin2+xmax2)
2377 nout1=16*max(1,ceiling((xmax1-xmin1)/(16.d0*beampixel)))
2378 nout2=16*max(1,ceiling((xmax2-xmin2)/(16.d0*beampixel)))
2379 xmin1=xcent1-half*dble(nout1)*beampixel
2380 xmin2=xcent2-half*dble(nout2)*beampixel
2381
2382 allocate(xout1(nout1),xout2(nout2),dxout1(nout1),dxout2(nout2))
2383 do ixp1=1,nout1
2384 xout1(ixp1)=xmin1+beampixel*(dble(ixp1)-half)
2385 dxout1(ixp1)=beampixel
2386 enddo
2387 do ixp2=1,nout2
2388 xout2(ixp2)=xmin2+beampixel*(dble(ixp2)-half)
2389 dxout2(ixp2)=beampixel
2390 enddo
2391
2392 numwout=1
2393 if (present(tau) .and. output_tau) numwout=numwout+1
2394 if (present(brightthin) .and. output_absorption_fraction) numwout=numwout+1
2395 allocate(wout(nout1,nout2,numwout),norm(nout1,nout2))
2396 wout=zero
2397 norm=zero
2398 if (present(brightthin)) then
2399 allocate(thinout(nout1,nout2))
2400 thinout=zero
2401 endif
2402 if (present(tau) .and. output_tau) then
2403 allocate(tauout(nout1,nout2),taunorm(nout1,nout2))
2404 tauout=zero
2405 taunorm=zero
2406 endif
2407
2408 nstencil=max(3,ceiling(4.d0*beamsigma/beampixel)+1)
2409 do ixs1=1,nsrc1
2410 do ixs2=1,nsrc2
2411 thinval=zero
2412 tauval=zero
2413 if (present(brightthin)) thinval=brightthin(ixs1,ixs2)
2414 if (present(tau)) tauval=tau(ixs1,ixs2)
2415 if (abs(bright(ixs1,ixs2))<=smalldouble .and. abs(thinval)<=smalldouble .and. &
2416 abs(tauval)<=smalldouble) cycle
2417
2418 ixc1=floor((xsrc1(ixs1)-(xout1(1)-half*beampixel))/beampixel)+1
2419 ixc2=floor((xsrc2(ixs2)-(xout2(1)-half*beampixel))/beampixel)+1
2420 ixpmin1=max(1,ixc1-nstencil)
2421 ixpmax1=min(nout1,ixc1+nstencil)
2422 ixpmin2=max(1,ixc2-nstencil)
2423 ixpmax2=min(nout2,ixc2+nstencil)
2424 cellarea=max(smalldouble,dxsrc1(ixs1)*dxsrc2(ixs2))
2425
2426 do ixp1=ixpmin1,ixpmax1
2427 distance1=xout1(ixp1)-xsrc1(ixs1)
2428 do ixp2=ixpmin2,ixpmax2
2429 distance2=xout2(ixp2)-xsrc2(ixs2)
2430 weight=exp_clamped(-half*(distance1**2+distance2**2)/beamsigma**2)*cellarea
2431 wout(ixp1,ixp2,1)=wout(ixp1,ixp2,1)+bright(ixs1,ixs2)*weight
2432 norm(ixp1,ixp2)=norm(ixp1,ixp2)+weight
2433 if (present(brightthin)) thinout(ixp1,ixp2)=thinout(ixp1,ixp2)+thinval*weight
2434 if (present(tau) .and. output_tau) then
2435 tauout(ixp1,ixp2)=tauout(ixp1,ixp2)+tauval*weight
2436 taunorm(ixp1,ixp2)=taunorm(ixp1,ixp2)+weight
2437 endif
2438 enddo
2439 enddo
2440 enddo
2441 enddo
2442
2443 do ixp1=1,nout1
2444 do ixp2=1,nout2
2445 if (norm(ixp1,ixp2)>zero) then
2446 wout(ixp1,ixp2,1)=wout(ixp1,ixp2,1)/norm(ixp1,ixp2)
2447 if (present(brightthin)) thinout(ixp1,ixp2)=thinout(ixp1,ixp2)/norm(ixp1,ixp2)
2448 else
2449 wout(ixp1,ixp2,1)=zero
2450 if (present(brightthin)) thinout(ixp1,ixp2)=zero
2451 endif
2452 enddo
2453 enddo
2454
2455 iw=1
2456 if (present(tau) .and. output_tau) then
2457 iw=iw+1
2458 do ixp1=1,nout1
2459 do ixp2=1,nout2
2460 if (taunorm(ixp1,ixp2)>zero) then
2461 wout(ixp1,ixp2,iw)=tauout(ixp1,ixp2)/taunorm(ixp1,ixp2)
2462 else
2463 wout(ixp1,ixp2,iw)=zero
2464 endif
2465 enddo
2466 enddo
2467 endif
2468 if (present(brightthin) .and. output_absorption_fraction) then
2469 iw=iw+1
2470 do ixp1=1,nout1
2471 do ixp2=1,nout2
2472 if (thinout(ixp1,ixp2)>smalldouble) then
2473 wout(ixp1,ixp2,iw)=min(one,max(zero,(thinout(ixp1,ixp2)-wout(ixp1,ixp2,1))/thinout(ixp1,ixp2)))
2474 else
2475 wout(ixp1,ixp2,iw)=zero
2476 endif
2477 enddo
2478 enddo
2479 endif
2480
2481 if (mype==0) then
2482 write(*,'(a,2(i8,1x),a,2(i8,1x),a,2(1pe12.5,1x))') &
2483 ' radio_beam_postprocess grid src/out: ',nsrc1,nsrc2,' -> ',nout1,nout2,&
2484 ' fwhm/pixel=',radio_beam_fwhm,beampixel/arcsec
2485 endif
2486
2487 deallocate(norm)
2488 if (allocated(thinout)) deallocate(thinout)
2489 if (allocated(tauout)) deallocate(tauout,taunorm)
2490 end subroutine postprocess_radio_beam_image
2491
2492 subroutine get_image_datresol(qunit,datatype,fl)
2493 ! integrate emission flux along line of sight (LOS)
2494 ! in a 3D simulation box and get a 2D EUV image
2496 use mod_constants
2497
2498 integer, intent(in) :: qunit
2499 character(20), intent(in) :: datatype
2500 type(te_fluid), intent(in) :: fl
2501
2502 double precision :: dx^D
2503 integer :: numX^D,ix^D
2504 double precision, allocatable :: EUV(:,:),EUVs(:,:),Dpl(:,:),Dpls(:,:)
2505 double precision, allocatable :: EUVthin(:,:),Tau(:,:)
2506 double precision, allocatable :: SXR(:,:),SXRs(:,:),wI(:,:,:)
2507 double precision, allocatable :: xI1(:),xI2(:),dxI1(:),dxI2(:),dxIi
2508 integer :: numXI1,numXI2,numSI,numWI,iw
2509 double precision :: xI^L
2510 integer :: iigrid,igrid,i,j
2511 double precision, allocatable :: xIF1(:),xIF2(:),dxIF1(:),dxIF2(:)
2512 double precision, allocatable :: xIP1(:),xIP2(:),dxIP1(:),dxIP2(:),wIP(:,:,:)
2513 integer :: nXIF1,nXIF2
2514 integer :: nXIP1,nXIP2,numWIP
2515 double precision :: xIF^L
2516 double precision :: vec_cor(1:3),xI_cor(1:2),dxDDA,xIcent1,xIcent2
2517
2518 double precision :: unitv,arcsec,RHESSI_rsl
2519 integer :: strtype^D,nstrb^D,nbb^D,nuni^D,nstr^D,bnx^D
2520 double precision :: qs^D,dxfirst^D,dxmid^D,lenstr^D
2521 logical :: has_doppler_output,has_thick_output
2522
2523 numx1=domain_nx1*2**(refine_max_level-1)
2524 numx2=domain_nx2*2**(refine_max_level-1)
2525 numx3=domain_nx3*2**(refine_max_level-1)
2526
2527 if (trim(ray_method_active)=='cart') call init_vectors_cartesian()
2528 if (coordinate==spherical .and. trim(ray_method_active)=='spherical') call init_vectors_spherical()
2529
2530 ! parameters for creating table
2531 if (coordinate==spherical .and. trim(ray_method_active)=='spherical') then
2532 call get_sph_intersection_image_bounds(xifmin1,xifmax1,xifmin2,xifmax2)
2534 xicent1=half*(xifmin1+xifmax1)
2535 xicent2=half*(xifmin2+xifmax2)
2536 nxif1=max(1,ceiling((xifmax1-xifmin1)/dxdda))
2537 nxif2=max(1,ceiling((xifmax2-xifmin2)/dxdda))
2538 xifmin1=xicent1-half*dble(nxif1)*dxdda
2539 xifmax1=xicent1+half*dble(nxif1)*dxdda
2540 xifmin2=xicent2-half*dble(nxif2)*dxdda
2541 xifmax2=xicent2+half*dble(nxif2)*dxdda
2542 bnx1=1
2543 bnx2=1
2544 nbb1=nxif1
2545 nbb2=nxif2
2546 strtype1=0
2547 strtype2=0
2548 nstrb1=0
2549 nstrb2=0
2550 qs1=one
2551 qs2=one
2552 if (mype==0) write(*,'(a,1pe12.5,a,2(i8,1x))') &
2553 ' spherical native dat-resolution image-plane dx: ',dxdda,' n=',nxif1,nxif2
2554 else if (trim(ray_method_active)=='cart' .and. .not. &
2555 ((los_phi==0 .and. los_theta==90) .or. &
2556 (los_phi==90 .and. los_theta==90) .or. los_theta==0)) then
2557 do ix1=1,2
2558 if (ix1==1) vec_cor(1)=xprobmin1
2559 if (ix1==2) vec_cor(1)=xprobmax1
2560 do ix2=1,2
2561 if (ix2==1) vec_cor(2)=xprobmin2
2562 if (ix2==2) vec_cor(2)=xprobmax2
2563 do ix3=1,2
2564 if (ix3==1) vec_cor(3)=xprobmin3
2565 if (ix3==2) vec_cor(3)=xprobmax3
2566 call get_cor_image(vec_cor,xi_cor)
2567 if (ix1==1 .and. ix2==1 .and. ix3==1) then
2568 xifmin1=xi_cor(1)
2569 xifmax1=xi_cor(1)
2570 xifmin2=xi_cor(2)
2571 xifmax2=xi_cor(2)
2572 else
2573 xifmin1=min(xifmin1,xi_cor(1))
2574 xifmax1=max(xifmax1,xi_cor(1))
2575 xifmin2=min(xifmin2,xi_cor(2))
2576 xifmax2=max(xifmax2,xi_cor(2))
2577 endif
2578 enddo
2579 enddo
2580 enddo
2581 dxdda=min((xprobmax1-xprobmin1)/dble(numx1),&
2582 (xprobmax2-xprobmin2)/dble(numx2),&
2583 (xprobmax3-xprobmin3)/dble(numx3))
2584 xicent1=half*(xifmin1+xifmax1)
2585 xicent2=half*(xifmin2+xifmax2)
2586 nxif1=max(1,ceiling((xifmax1-xifmin1)/dxdda))
2587 nxif2=max(1,ceiling((xifmax2-xifmin2)/dxdda))
2588 xifmin1=xicent1-half*dble(nxif1)*dxdda
2589 xifmax1=xicent1+half*dble(nxif1)*dxdda
2590 xifmin2=xicent2-half*dble(nxif2)*dxdda
2591 xifmax2=xicent2+half*dble(nxif2)*dxdda
2592 bnx1=1
2593 bnx2=1
2594 nbb1=nxif1
2595 nbb2=nxif2
2596 strtype1=0
2597 strtype2=0
2598 nstrb1=0
2599 nstrb2=0
2600 qs1=one
2601 qs2=one
2602 else if (los_phi==0 .and. los_theta==90) then
2603 nxif1=domain_nx2*2**(refine_max_level-1)
2604 nxif2=domain_nx3*2**(refine_max_level-1)
2605 xifmin1=xprobmin2
2606 xifmax1=xprobmax2
2607 xifmin2=xprobmin3
2608 xifmax2=xprobmax3
2609 bnx1=block_nx2
2610 bnx2=block_nx3
2611 nbb1=domain_nx2
2612 nbb2=domain_nx3
2613 strtype1=stretch_type(2)
2614 strtype2=stretch_type(3)
2617 qs1=qstretch_baselevel(2)
2618 qs2=qstretch_baselevel(3)
2619 if (mype==0) write(*,'(a)') ' LOS vector: [-1.00 0.00 0.00]'
2620 if (mype==0) write(*,'(a)') ' xI1 vector: [ 0.00 1.00 0.00]'
2621 if (mype==0) write(*,'(a)') ' xI2 vector: [ 0.00 0.00 1.00]'
2622 else if (los_phi==90 .and. los_theta==90) then
2623 nxif1=domain_nx3*2**(refine_max_level-1)
2624 nxif2=domain_nx1*2**(refine_max_level-1)
2625 xifmin1=xprobmin3
2626 xifmax1=xprobmax3
2627 xifmin2=xprobmin1
2628 xifmax2=xprobmax1
2629 bnx1=block_nx3
2630 bnx2=block_nx1
2631 nbb1=domain_nx3
2632 nbb2=domain_nx1
2633 strtype1=stretch_type(3)
2634 strtype2=stretch_type(1)
2637 qs1=qstretch_baselevel(3)
2638 qs2=qstretch_baselevel(1)
2639 if (mype==0) write(*,'(a)') ' LOS vector: [ 0.00 -1.00 0.00]'
2640 if (mype==0) write(*,'(a)') ' xI1 vector: [-1.00 0.00 0.00]'
2641 if (mype==0) write(*,'(a)') ' xI2 vector: [ 0.00 0.00 1.00]'
2642 else
2643 nxif1=domain_nx1*2**(refine_max_level-1)
2644 nxif2=domain_nx2*2**(refine_max_level-1)
2645 xifmin1=xprobmin1
2646 xifmax1=xprobmax1
2647 xifmin2=xprobmin2
2648 xifmax2=xprobmax2
2649 bnx1=block_nx1
2650 bnx2=block_nx2
2651 nbb1=domain_nx1
2652 nbb2=domain_nx2
2653 strtype1=stretch_type(1)
2654 strtype2=stretch_type(2)
2657 qs1=qstretch_baselevel(1)
2658 qs2=qstretch_baselevel(2)
2659 if (mype==0) write(*,'(a)') ' LOS vector: [ 0.00 0.00 -1.00]'
2660 if (mype==0) write(*,'(a)') ' xI1 vector: [ 1.00 0.00 0.00]'
2661 if (mype==0) write(*,'(a)') ' xI2 vector: [ 0.00 1.00 0.00]'
2662 endif
2663 allocate(xif1(nxif1),xif2(nxif2),dxif1(nxif1),dxif2(nxif2))
2664
2665 ! initialize image coordinate
2666 select case(strtype1)
2667 case(0) ! uniform
2668 dxif1(:)=(xifmax1-xifmin1)/nxif1
2669 do ix1=1,nxif1
2670 xif1(ix1)=xifmin1+dxif1(ix1)*(ix1-half)
2671 enddo
2672 case(1) ! uni stretch
2673 qs1=qs1**(one/2**(refine_max_level-1))
2674 dxfirst1=(xifmax1-xifmin1)*(one-qs1)/(one-qs1**nxif1)
2675 dxif1(1)=dxfirst1
2676 do ix1=2,nxif1
2677 dxif1(ix1)=dxfirst1*qs1**(ix1-1)
2678 xif1(ix1)=dxif1(1)/(one-qs1)*(one-qs1**(ix1-1))+half*dxif1(ix1)
2679 enddo
2680 case(2) ! symm stretch
2681 ! base level, nbb = nstr + nuni + nstr
2682 nstr1=nstrb1*bnx1/2
2683 nuni1=nbb1-nstrb1*bnx1
2684 lenstr1=(xifmax1-xifmin1)/(2.d0+nuni1*(one-qs1)/(one-qs1**nstr1))
2685 dxfirst1=(xifmax1-xifmin1)/(dble(nuni1)+2.d0/(one-qs1)*(one-qs1**nstr1))
2686 dxmid1=dxfirst1
2687 ! refine_max level, numXI = nstr + nuni + nstr
2688 nstr1=nstr1*2**(refine_max_level-1)
2689 nuni1=nuni1*2**(refine_max_level-1)
2690 qs1=qs1**(one/2**(refine_max_level-1))
2691 dxfirst1=lenstr1*(one-qs1)/(one-qs1**nstr1)
2692 dxmid1=dxmid1/2**(refine_max_level-1)
2693 ! uniform center
2694 if(nuni1 .gt. 0) then
2695 do ix1=nstr1+1,nstr1+nuni1
2696 dxif1(ix1)=dxmid1
2697 xif1(ix1)=lenstr1+(dble(ix1)-0.5d0-nstr1)*dxif1(ix1)+xifmin1
2698 enddo
2699 endif
2700 ! left half
2701 do ix1=nstr1,1,-1
2702 dxif1(ix1)=dxfirst1*qs1**(nstr1-ix1)
2703 xif1(ix1)=xifmin1+lenstr1-dxif1(ix1)*half-dxfirst1*(one-qs1**(nstr1-ix1))/(one-qs1)
2704 enddo
2705 ! right half
2706 do ix1=nstr1+nuni1+1,nxif1
2707 dxif1(ix1)=dxfirst1*qs1**(ix1-nstr1-nuni1-1)
2708 xif1(ix1)=xifmax1-lenstr1+dxif1(ix1)*half+dxfirst1*(one-qs1**(ix1-nstr1-nuni1-1))/(one-qs1)
2709 enddo
2710 case default
2711 call mpistop("unknown stretch type")
2712 end select
2713
2714 select case(strtype2)
2715 case(0) ! uniform
2716 dxif2(:)=(xifmax2-xifmin2)/nxif2
2717 do ix2=1,nxif2
2718 xif2(ix2)=xifmin2+dxif2(ix2)*(ix2-half)
2719 enddo
2720 case(1) ! uni stretch
2721 qs2=qs2**(one/2**(refine_max_level-1))
2722 dxfirst2=(xifmax2-xifmin2)*(one-qs2)/(one-qs2**nxif2)
2723 dxif2(1)=dxfirst2
2724 do ix2=2,nxif1
2725 dxif2(ix2)=dxfirst2*qs2**(ix2-1)
2726 xif2(ix2)=dxif2(1)/(one-qs2)*(one-qs2**(ix2-1))+half*dxif2(ix2)
2727 enddo
2728 case(2) ! symm stretch
2729 ! base level, nbb = nstr + nuni + nstr
2730 nstr2=nstrb2*bnx2/2
2731 nuni2=nbb2-nstrb2*bnx2
2732 lenstr2=(xifmax2-xifmin2)/(2.d0+nuni2*(one-qs2)/(one-qs2**nstr2))
2733 dxfirst2=(xifmax2-xifmin2)/(dble(nuni2)+2.d0/(one-qs2)*(one-qs2**nstr2))
2734 dxmid2=dxfirst2
2735 ! refine_max level, numXI = nstr + nuni + nstr
2736 nstr2=nstr2*2**(refine_max_level-1)
2737 nuni2=nuni2*2**(refine_max_level-1)
2738 qs2=qs2**(one/2**(refine_max_level-1))
2739 dxfirst2=lenstr2*(one-qs2)/(one-qs2**nstr2)
2740 dxmid2=dxmid2/2**(refine_max_level-1)
2741 ! uniform center
2742 if(nuni2 .gt. 0) then
2743 do ix2=nstr2+1,nstr2+nuni2
2744 dxif2(ix2)=dxmid2
2745 xif2(ix2)=lenstr2+(dble(ix2)-0.5d0-nstr2)*dxif2(ix2)+xifmin2
2746 enddo
2747 endif
2748 ! left half
2749 do ix2=nstr2,1,-1
2750 dxif2(ix2)=dxfirst2*qs2**(nstr2-ix2)
2751 xif2(ix2)=xifmin2+lenstr2-dxif2(ix2)*half-dxfirst2*(one-qs2**(nstr2-ix2))/(one-qs2)
2752 enddo
2753 ! right half
2754 do ix2=nstr2+nuni2+1,nxif2
2755 dxif2(ix2)=dxfirst2*qs2**(ix2-nstr2-nuni2-1)
2756 xif2(ix2)=xifmax2-lenstr2+dxif2(ix2)*half+dxfirst2*(one-qs2**(ix2-nstr2-nuni2-1))/(one-qs2)
2757 enddo
2758 case default
2759 call mpistop("unknown stretch type")
2760 end select
2761
2762 ! integrate EUV flux and get cell average flux for image
2763 if (datatype=='image_euv') then
2764 if (si_unit) then
2765 unitv=unit_velocity/1.0e3 ! km/s
2766 else
2767 unitv=unit_velocity/1.0e5 ! km/s
2768 endif
2769 has_thick_output=trim(radiation_transfer)=='thick'
2770 has_doppler_output=radsyn_euv_has_doppler_output()
2771 numwi=radsyn_euv_num_outputs(has_doppler_output,has_thick_output)
2772 allocate(wi(nxif1,nxif2,numwi))
2773 allocate(euv(nxif1,nxif2),dpl(nxif1,nxif2))
2774 if (trim(radiation_transfer)=='thick') then
2775 allocate(euvthin(nxif1,nxif2),tau(nxif1,nxif2))
2776 if (coordinate==spherical .and. trim(ray_method_active)=='spherical') then
2777 call integrate_euv_sph_intersection_thick(nxif1,nxif2,xif1,xif2,dxif1(1),fl,euv,tau,euvthin)
2778 dpl=zero
2779 else if (trim(ray_method_active)=='cart') then
2780 call integrate_euv_cart_dda_thick_datresol(nxif1,nxif2,xif1,xif2,fl,euv,dpl,tau,euvthin)
2781 else
2782 call integrate_euv_thick_datresol(nxif1,nxif2,fl,euv,dpl,tau,euvthin)
2783 endif
2784 if (has_doppler_output) then
2785 where(euv<smalldouble) euv=zero
2786 call normalize_euv_doppler(nxif1,nxif2,euv,dpl,unitv)
2787 endif
2788 else
2789 allocate(euvs(nxif1,nxif2),dpls(nxif1,nxif2))
2790 euvs=0.0d0
2791 euv=0.0d0
2792 dpl=0.d0
2793 dpls=0.d0
2794 if (coordinate==spherical .and. trim(ray_method_active)=='spherical') then
2795 call integrate_euv_sph_intersection_thin(nxif1,nxif2,xif1,xif2,dxif1(1),fl,euv)
2796 euvs=euv
2797 numsi=nxif1*nxif2
2798 call mpi_allreduce(euvs,euv,numsi,mpi_double_precision, &
2799 mpi_sum,icomm,ierrmpi)
2800 else if (trim(ray_method_active)=='cart') then
2801 call integrate_euv_cart_dda_datresol(nxif1,nxif2,xif1,xif2,fl,euv,dpl)
2802 else
2803 do iigrid=1,igridstail; igrid=igrids(iigrid);
2804 call integrate_euv_datresol(igrid,nxif1,nxif2,xif1,xif2,dxif1,dxif2,fl,euvs,dpls)
2805 enddo
2806 numsi=nxif1*nxif2
2807 call mpi_allreduce(euvs,euv,numsi,mpi_double_precision, &
2808 mpi_sum,icomm,ierrmpi)
2809 call mpi_allreduce(dpls,dpl,numsi,mpi_double_precision, &
2810 mpi_sum,icomm,ierrmpi)
2811 endif
2812 if (has_doppler_output) then
2813 where(euv<smalldouble) euv=zero
2814 call normalize_euv_doppler(nxif1,nxif2,euv,dpl,unitv)
2815 endif
2816 deallocate(euvs,dpls)
2817 endif
2818 if (has_thick_output) then
2819 if (has_doppler_output) then
2820 call pack_euv_image_outputs(nxif1,nxif2,euv,wi,smalldouble,has_doppler_output,&
2821 has_thick_output,dpl=dpl,tau=tau,euvthin=euvthin)
2822 else
2823 call pack_euv_image_outputs(nxif1,nxif2,euv,wi,smalldouble,has_doppler_output,&
2824 has_thick_output,tau=tau,euvthin=euvthin)
2825 endif
2826 else if (has_doppler_output) then
2827 call pack_euv_image_outputs(nxif1,nxif2,euv,wi,smalldouble,has_doppler_output,&
2828 has_thick_output,dpl=dpl)
2829 else
2830 call pack_euv_image_outputs(nxif1,nxif2,euv,wi,smalldouble,has_doppler_output,&
2831 has_thick_output)
2832 endif
2833
2834 if (instrument_postprocess) then
2835 if (trim(emission_model)=='radio_ff') then
2836 if (trim(radiation_transfer)=='thick') then
2837 call postprocess_radio_beam_image(nxif1,nxif2,xif1,xif2,dxif1,dxif2,&
2838 euv,nxip1,nxip2,xip1,xip2,&
2839 dxip1,dxip2,wip,numwip,tau=tau,brightthin=euvthin)
2840 else
2841 call postprocess_radio_beam_image(nxif1,nxif2,xif1,xif2,dxif1,dxif2,&
2842 euv,nxip1,nxip2,xip1,xip2,&
2843 dxip1,dxip2,wip,numwip)
2844 endif
2845 else if (trim(radiation_transfer)=='thick') then
2846 call postprocess_euv_instrument_image(nxif1,nxif2,xif1,xif2,dxif1,dxif2,&
2847 euv,dpl,nxip1,nxip2,xip1,xip2,&
2848 dxip1,dxip2,wip,numwip,tau=tau,euvthin=euvthin)
2849 else
2850 call postprocess_euv_instrument_image(nxif1,nxif2,xif1,xif2,dxif1,dxif2,&
2851 euv,dpl,nxip1,nxip2,xip1,xip2,&
2852 dxip1,dxip2,wip,numwip)
2853 endif
2854 call output_data(qunit,xip1,xip2,dxip1,dxip2,wip,nxip1,nxip2,numwip,datatype)
2855 deallocate(xip1,xip2,dxip1,dxip2,wip)
2856 else
2857 call output_data(qunit,xif1,xif2,dxif1,dxif2,wi,nxif1,nxif2,numwi,datatype)
2858 endif
2859 if (trim(radiation_transfer)=='thick') then
2860 deallocate(wi,euv,dpl,euvthin,tau)
2861 else
2862 deallocate(wi,euv,dpl)
2863 endif
2864 endif
2865
2866 ! integrate SXR flux and get cell average flux for image
2867 if (datatype=='image_sxr') then
2868 if (si_unit) then
2869 arcsec=7.25d5
2870 else
2871 arcsec=7.25d7
2872 endif
2873 rhessi_rsl=2.3d0/instrument_resolution_factor
2874 numwi=1
2875 allocate(wi(nxif1,nxif2,numwi))
2876 allocate(sxrs(nxif1,nxif2),sxr(nxif1,nxif2))
2877 sxrs=0.0d0
2878 sxr=0.0d0
2879 do iigrid=1,igridstail; igrid=igrids(iigrid);
2880 call integrate_sxr_datresol(igrid,nxif1,nxif2,xif1,xif2,dxif1,dxif2,fl,sxrs)
2881 enddo
2882 numsi=nxif1*nxif2
2883 call mpi_allreduce(sxrs,sxr,numsi,mpi_double_precision, &
2884 mpi_sum,icomm,ierrmpi)
2885
2886 sxr=sxr*(rhessi_rsl*arcsec)**2 ! photons cm^-2 s^-1 pixel^-1
2887 do ix1=1,nxif1
2888 do ix2=1,nxif2
2889 if (sxr(ix1,ix2)<smalldouble) sxr(ix1,ix2)=zero
2890 enddo
2891 enddo
2892 wi(:,:,1)=sxr(:,:)
2893
2894 call output_data(qunit,xif1,xif2,dxif1,dxif2,wi,nxif1,nxif2,numwi,datatype)
2895 deallocate(wi,sxr,sxrs)
2896 endif
2897
2898 deallocate(xif1,xif2,dxif1,dxif2)
2899
2900 end subroutine get_image_datresol
2901
2902 subroutine integrate_sxr_datresol(igrid,nXIF1,nXIF2,xIF1,xIF2,dxIF1,dxIF2,fl,SXR)
2904
2905 integer, intent(in) :: igrid,nXIF1,nXIF2
2906 double precision, intent(in) :: xIF1(nXIF1),xIF2(nXIF2)
2907 double precision, intent(in) :: dxIF1(nXIF1),dxIF2(nXIF2)
2908 type(te_fluid), intent(in) :: fl
2909 double precision, intent(out) :: SXR(nXIF1,nXIF2)
2910
2911 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
2912 double precision :: xb^L,xd^D
2913 double precision, allocatable :: flux(:^D&),opacity(:^D&)
2914 double precision, allocatable :: dxb1(:^D&),dxb2(:^D&),dxb3(:^D&)
2915 double precision, allocatable :: SXRg(:,:),xg1(:),xg2(:),dxg1(:),dxg2(:)
2916 integer :: levelg,nXg1,nXg2,iXgmin1,iXgmax1,iXgmin2,iXgmax2,rft,iXg^D
2917 double precision :: SXRt,xc^L,xg^L,r2,area_1AU
2918 integer :: ixP^L,ixP^D
2919 integer :: direction_LOS
2920
2921 if (los_phi==0 .and. los_theta==90) then
2922 direction_los=1
2923 else if (los_phi==90 .and. los_theta==90) then
2924 direction_los=2
2925 else
2926 direction_los=3
2927 endif
2928
2929 ^d&ixomin^d=ixmlo^d\
2930 ^d&ixomax^d=ixmhi^d\
2931 ^d&iximin^d=ixglo^d\
2932 ^d&iximax^d=ixghi^d\
2933 ^d&xbmin^d=rnode(rpxmin^d_,igrid)\
2934 ^d&xbmax^d=rnode(rpxmax^d_,igrid)\
2935
2936 allocate(flux(ixi^s))
2937 allocate(dxb1(ixi^s),dxb2(ixi^s),dxb3(ixi^s))
2938 dxb1(ixo^s)=ps(igrid)%dx(ixo^s,1)
2939 dxb2(ixo^s)=ps(igrid)%dx(ixo^s,2)
2940 dxb3(ixo^s)=ps(igrid)%dx(ixo^s,3)
2941 ! get local SXR flux
2942 call get_sxr(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,emin_sxr,emax_sxr)
2943
2944 ! grid parameters
2945 levelg=ps(igrid)%level
2946 rft=2**(refine_max_level-levelg)
2947
2948 ! fine table for storing EUV flux of current grid
2949 select case(direction_los)
2950 case(1)
2951 nxg1=iximax2*rft
2952 nxg2=iximax3*rft
2953 case(2)
2954 nxg1=iximax3*rft
2955 nxg2=iximax1*rft
2956 case(3)
2957 nxg1=iximax1*rft
2958 nxg2=iximax2*rft
2959 end select
2960 allocate(sxrg(nxg1,nxg2),xg1(nxg1),xg2(nxg2),dxg1(nxg1),dxg2(nxg2))
2961 sxrg=zero
2962 xg1=zero
2963 xg2=zero
2964
2965 ! integrate for different direction
2966 select case(direction_los)
2967 case(1)
2968 do ix2=ixomin2,ixomax2
2969 ixgmin1=(ix2-1)*rft+1
2970 ixgmax1=ix2*rft
2971 do ix3=ixomin3,ixomax3
2972 ixgmin2=(ix3-1)*rft+1
2973 ixgmax2=ix3*rft
2974 sxrt=0.d0
2975 do ix1=ixomin1,ixomax1
2976 sxrt=sxrt+flux(ix^d)*dxb1(ix^d)*unit_length
2977 enddo
2978 sxrg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=sxrt
2979 enddo
2980 enddo
2981 case(2)
2982 do ix3=ixomin3,ixomax3
2983 ixgmin1=(ix3-1)*rft+1
2984 ixgmax1=ix3*rft
2985 do ix1=ixomin1,ixomax1
2986 ixgmin2=(ix1-1)*rft+1
2987 ixgmax2=ix1*rft
2988 sxrt=0.d0
2989 do ix2=ixomin2,ixomax2
2990 sxrt=sxrt+flux(ix^d)*dxb2(ix^d)*unit_length
2991 enddo
2992 sxrg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=sxrt
2993 enddo
2994 enddo
2995 case(3)
2996 do ix1=ixomin1,ixomax1
2997 ixgmin1=(ix1-1)*rft+1
2998 ixgmax1=ix1*rft
2999 do ix2=ixomin2,ixomax2
3000 ixgmin2=(ix2-1)*rft+1
3001 ixgmax2=ix2*rft
3002 sxrt=0.d0
3003 do ix3=ixomin3,ixomax3
3004 sxrt=sxrt+flux(ix^d)*dxb3(ix^d)*unit_length
3005 enddo
3006 sxrg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=sxrt
3007 enddo
3008 enddo
3009 end select
3010
3011 area_1au=2.81d27
3012 sxrg=sxrg/area_1au
3013
3014 ! mapping grid data to global table
3015 ! index ranges in local table
3016 select case(direction_los)
3017 case(1)
3018 ixgmin1=(ixomin2-1)*rft+1
3019 ixgmax1=ixomax2*rft
3020 ixgmin2=(ixomin3-1)*rft+1
3021 ixgmax2=ixomax3*rft
3022 case(2)
3023 ixgmin1=(ixomin3-1)*rft+1
3024 ixgmax1=ixomax3*rft
3025 ixgmin2=(ixomin1-1)*rft+1
3026 ixgmax2=ixomax1*rft
3027 case(3)
3028 ixgmin1=(ixomin1-1)*rft+1
3029 ixgmax1=ixomax1*rft
3030 ixgmin2=(ixomin2-1)*rft+1
3031 ixgmax2=ixomax2*rft
3032 end select
3033 ! index ranges in global table & mapping
3034 select case(direction_los)
3035 case(1)
3036 ixpmin1=(node(pig2_,igrid)-1)*rft*block_nx2+1
3037 ixpmax1=node(pig2_,igrid)*rft*block_nx2
3038 ixpmin2=(node(pig3_,igrid)-1)*rft*block_nx3+1
3039 ixpmax2=node(pig3_,igrid)*rft*block_nx3
3040 case(2)
3041 ixpmin1=(node(pig3_,igrid)-1)*rft*block_nx3+1
3042 ixpmax1=node(pig3_,igrid)*rft*block_nx3
3043 ixpmin2=(node(pig1_,igrid)-1)*rft*block_nx1+1
3044 ixpmax2=node(pig1_,igrid)*rft*block_nx1
3045 case(3)
3046 ixpmin1=(node(pig1_,igrid)-1)*rft*block_nx1+1
3047 ixpmax1=node(pig1_,igrid)*rft*block_nx1
3048 ixpmin2=(node(pig2_,igrid)-1)*rft*block_nx2+1
3049 ixpmax2=node(pig2_,igrid)*rft*block_nx2
3050 end select
3051 xg1(ixgmin1:ixgmax1)=xif1(ixpmin1:ixpmax1)
3052 xg2(ixgmin2:ixgmax2)=xif2(ixpmin2:ixpmax2)
3053 dxg1(ixgmin1:ixgmax1)=dxif1(ixpmin1:ixpmax1)
3054 dxg2(ixgmin2:ixgmax2)=dxif2(ixpmin2:ixpmax2)
3055 sxr(ixpmin1:ixpmax1,ixpmin2:ixpmax2)=sxr(ixpmin1:ixpmax1,ixpmin2:ixpmax2)+&
3056 sxrg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)
3057
3058 deallocate(flux,dxb1,dxb2,dxb3,sxrg,xg1,xg2,dxg1,dxg2)
3059
3060 end subroutine integrate_sxr_datresol
3061
3062 subroutine integrate_euv_datresol(igrid,nXIF1,nXIF2,xIF1,xIF2,dxIF1,dxIF2,fl,EUV,Dpl)
3064
3065 integer, intent(in) :: igrid,nXIF1,nXIF2
3066 double precision, intent(in) :: xIF1(nXIF1),xIF2(nXIF2)
3067 double precision, intent(in) :: dxIF1(nXIF1),dxIF2(nXIF2)
3068 type(te_fluid), intent(in) :: fl
3069 double precision, intent(out) :: EUV(nXIF1,nXIF2),Dpl(nXIF1,nXIF2)
3070
3071 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
3072 double precision :: xb^L,xd^D
3073 double precision, allocatable :: flux(:^D&),v(:^D&),rho(:^D&),opacity(:^D&)
3074 double precision, allocatable :: dxb1(:^D&),dxb2(:^D&),dxb3(:^D&)
3075 double precision, allocatable :: EUVg(:,:),Fvg(:,:),xg1(:),xg2(:),dxg1(:),dxg2(:)
3076 integer :: levelg,nXg1,nXg2,iXgmin1,iXgmax1,iXgmin2,iXgmax2,rft,iXg^D
3077 double precision :: EUVt,Fvt,xc^L,xg^L,r2
3078 integer :: ixP^L,ixP^D
3079 integer :: direction_LOS
3080
3081 if (los_phi==0 .and. los_theta==90) then
3082 direction_los=1
3083 else if (los_phi==90 .and. los_theta==90) then
3084 direction_los=2
3085 else
3086 direction_los=3
3087 endif
3088
3089 ^d&ixomin^d=ixmlo^d\
3090 ^d&ixomax^d=ixmhi^d\
3091 ^d&iximin^d=ixglo^d\
3092 ^d&iximax^d=ixghi^d\
3093 ^d&xbmin^d=rnode(rpxmin^d_,igrid)\
3094 ^d&xbmax^d=rnode(rpxmax^d_,igrid)\
3095
3096 allocate(flux(ixi^s),v(ixi^s),rho(ixi^s),opacity(ixi^s))
3097 allocate(dxb1(ixi^s),dxb2(ixi^s),dxb3(ixi^s))
3098 dxb1(ixo^s)=ps(igrid)%dx(ixo^s,1)
3099 dxb2(ixo^s)=ps(igrid)%dx(ixo^s,2)
3100 dxb3(ixo^s)=ps(igrid)%dx(ixo^s,3)
3101 if (trim(emission_model)=='pseudo_current') then
3102 call get_pseudo_current(igrid,ixi^l,ixo^l,ps(igrid)%w,flux)
3103 v(ixo^s)=zero
3104 deallocate(rho)
3105 else if (trim(emission_model)=='radio_ff') then
3106 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,opacity)
3107 v(ixo^s)=zero
3108 deallocate(rho)
3109 else
3110 ! get local EUV flux and velocity
3111 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux)
3112 flux(ixo^s)=flux(ixo^s)/instrument_resolution_factor**2 ! adjust flux due to artifical change of resolution
3113 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,rho)
3114 v(ixo^s)=-ps(igrid)%w(ixo^s,iw_mom(direction_los))/rho(ixo^s)
3115 deallocate(rho)
3116 endif
3117
3118 ! grid parameters
3119 levelg=ps(igrid)%level
3120 rft=2**(refine_max_level-levelg)
3121
3122 ! fine table for storing EUV flux of current grid
3123 select case(direction_los)
3124 case(1)
3125 nxg1=iximax2*rft
3126 nxg2=iximax3*rft
3127 case(2)
3128 nxg1=iximax3*rft
3129 nxg2=iximax1*rft
3130 case(3)
3131 nxg1=iximax1*rft
3132 nxg2=iximax2*rft
3133 end select
3134 allocate(euvg(nxg1,nxg2),fvg(nxg1,nxg2),xg1(nxg1),xg2(nxg2),dxg1(nxg1),dxg2(nxg2))
3135 euvg=zero
3136 fvg=zero
3137 xg1=zero
3138 xg2=zero
3139
3140 ! integrate for different direction
3141 select case(direction_los)
3142 case(1)
3143 do ix2=ixomin2,ixomax2
3144 ixgmin1=(ix2-1)*rft+1
3145 ixgmax1=ix2*rft
3146 do ix3=ixomin3,ixomax3
3147 ixgmin2=(ix3-1)*rft+1
3148 ixgmax2=ix3*rft
3149 euvt=0.d0
3150 fvt=0.d0
3151 do ix1=ixomin1,ixomax1
3152 euvt=euvt+flux(ix^d)*dxb1(ix^d)*unit_length
3153 fvt=fvt+flux(ix^d)*dxb1(ix^d)*unit_length*v(ix^d)
3154 enddo
3155 euvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=euvt
3156 fvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=fvt
3157 enddo
3158 enddo
3159 case(2)
3160 do ix3=ixomin3,ixomax3
3161 ixgmin1=(ix3-1)*rft+1
3162 ixgmax1=ix3*rft
3163 do ix1=ixomin1,ixomax1
3164 ixgmin2=(ix1-1)*rft+1
3165 ixgmax2=ix1*rft
3166 euvt=0.d0
3167 fvt=0.d0
3168 do ix2=ixomin2,ixomax2
3169 euvt=euvt+flux(ix^d)*dxb2(ix^d)*unit_length
3170 fvt=fvt+flux(ix^d)*dxb2(ix^d)*unit_length*v(ix^d)
3171 enddo
3172 euvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=euvt
3173 fvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=fvt
3174 enddo
3175 enddo
3176 case(3)
3177 do ix1=ixomin1,ixomax1
3178 ixgmin1=(ix1-1)*rft+1
3179 ixgmax1=ix1*rft
3180 do ix2=ixomin2,ixomax2
3181 ixgmin2=(ix2-1)*rft+1
3182 ixgmax2=ix2*rft
3183 euvt=0.d0
3184 fvt=0.d0
3185 do ix3=ixomin3,ixomax3
3186 euvt=euvt+flux(ix^d)*dxb3(ix^d)*unit_length
3187 fvt=fvt+flux(ix^d)*dxb3(ix^d)*unit_length*v(ix^d)
3188 enddo
3189 euvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=euvt
3190 fvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)=fvt
3191 enddo
3192 enddo
3193 end select
3194 if (si_unit) then
3195 euvg=euvg*1.d2
3196 fvg=fvg*1.d2
3197 endif
3198
3199 ! mapping grid data to global table
3200 ! index ranges in local table
3201 select case(direction_los)
3202 case(1)
3203 ixgmin1=(ixomin2-1)*rft+1
3204 ixgmax1=ixomax2*rft
3205 ixgmin2=(ixomin3-1)*rft+1
3206 ixgmax2=ixomax3*rft
3207 case(2)
3208 ixgmin1=(ixomin3-1)*rft+1
3209 ixgmax1=ixomax3*rft
3210 ixgmin2=(ixomin1-1)*rft+1
3211 ixgmax2=ixomax1*rft
3212 case(3)
3213 ixgmin1=(ixomin1-1)*rft+1
3214 ixgmax1=ixomax1*rft
3215 ixgmin2=(ixomin2-1)*rft+1
3216 ixgmax2=ixomax2*rft
3217 end select
3218 ! index ranges in global table & mapping
3219 select case(direction_los)
3220 case(1)
3221 ixpmin1=(node(pig2_,igrid)-1)*rft*block_nx2+1
3222 ixpmax1=node(pig2_,igrid)*rft*block_nx2
3223 ixpmin2=(node(pig3_,igrid)-1)*rft*block_nx3+1
3224 ixpmax2=node(pig3_,igrid)*rft*block_nx3
3225 case(2)
3226 ixpmin1=(node(pig3_,igrid)-1)*rft*block_nx3+1
3227 ixpmax1=node(pig3_,igrid)*rft*block_nx3
3228 ixpmin2=(node(pig1_,igrid)-1)*rft*block_nx1+1
3229 ixpmax2=node(pig1_,igrid)*rft*block_nx1
3230 case(3)
3231 ixpmin1=(node(pig1_,igrid)-1)*rft*block_nx1+1
3232 ixpmax1=node(pig1_,igrid)*rft*block_nx1
3233 ixpmin2=(node(pig2_,igrid)-1)*rft*block_nx2+1
3234 ixpmax2=node(pig2_,igrid)*rft*block_nx2
3235 end select
3236 xg1(ixgmin1:ixgmax1)=xif1(ixpmin1:ixpmax1)
3237 xg2(ixgmin2:ixgmax2)=xif2(ixpmin2:ixpmax2)
3238 dxg1(ixgmin1:ixgmax1)=dxif1(ixpmin1:ixpmax1)
3239 dxg2(ixgmin2:ixgmax2)=dxif2(ixpmin2:ixpmax2)
3240 euv(ixpmin1:ixpmax1,ixpmin2:ixpmax2)=euv(ixpmin1:ixpmax1,ixpmin2:ixpmax2)+&
3241 euvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)
3242 dpl(ixpmin1:ixpmax1,ixpmin2:ixpmax2)=dpl(ixpmin1:ixpmax1,ixpmin2:ixpmax2)+&
3243 fvg(ixgmin1:ixgmax1,ixgmin2:ixgmax2)
3244
3245 deallocate(flux,v,opacity,dxb1,dxb2,dxb3,euvg,fvg,xg1,xg2,dxg1,dxg2)
3246
3247 end subroutine integrate_euv_datresol
3248
3249 }
3250
3251 {^ifthreed
3252
3253 subroutine ray_box_intersection_cart(ray_origin,ray_dir,box_min,box_max,hit,t_enter,t_exit)
3254 double precision, intent(in) :: ray_origin(1:3),ray_dir(1:3),box_min(1:3),box_max(1:3)
3255 logical, intent(out) :: hit
3256 double precision, intent(out) :: t_enter,t_exit
3257
3258 integer :: idir
3259 double precision :: t1,t2,td
3260
3261 hit=.true.
3262 t_enter=-huge(one)
3263 t_exit=huge(one)
3264 do idir=1,3
3265 if (abs(ray_dir(idir))<=smalldouble) then
3266 if (ray_origin(idir)<box_min(idir) .or. ray_origin(idir)>box_max(idir)) then
3267 hit=.false.
3268 return
3269 endif
3270 else
3271 t1=(box_min(idir)-ray_origin(idir))/ray_dir(idir)
3272 t2=(box_max(idir)-ray_origin(idir))/ray_dir(idir)
3273 if (t1>t2) then
3274 td=t1
3275 t1=t2
3276 t2=td
3277 endif
3278 t_enter=max(t_enter,t1)
3279 t_exit=min(t_exit,t2)
3280 if (t_enter>=t_exit) then
3281 hit=.false.
3282 return
3283 endif
3284 endif
3285 enddo
3286 end subroutine ray_box_intersection_cart
3287
3288 subroutine build_cart_dda_faces(ixI^L,ixO^L,x,dx,xface1,xface2,xface3)
3289 integer, intent(in) :: ixI^L, ixO^L
3290 double precision, intent(in) :: x(ixI^S,1:ndim),dx(ixI^S,1:ndim)
3291 double precision, allocatable, intent(out) :: xface1(:),xface2(:),xface3(:)
3292
3293 integer :: ix^D
3294
3295 allocate(xface1(ixomin1:ixomax1+1),xface2(ixomin2:ixomax2+1),xface3(ixomin3:ixomax3+1))
3296
3297 ix2=ixomin2
3298 ix3=ixomin3
3299 do ix1=ixomin1,ixomax1
3300 xface1(ix1)=x(ix^d,1)-half*dx(ix^d,1)
3301 enddo
3302 xface1(ixomax1+1)=x(ixomax1,ixomin2,ixomin3,1)+half*dx(ixomax1,ixomin2,ixomin3,1)
3303
3304 ix1=ixomin1
3305 ix3=ixomin3
3306 do ix2=ixomin2,ixomax2
3307 xface2(ix2)=x(ix^d,2)-half*dx(ix^d,2)
3308 enddo
3309 xface2(ixomax2+1)=x(ixomin1,ixomax2,ixomin3,2)+half*dx(ixomin1,ixomax2,ixomin3,2)
3310
3311 ix1=ixomin1
3312 ix2=ixomin2
3313 do ix3=ixomin3,ixomax3
3314 xface3(ix3)=x(ix^d,3)-half*dx(ix^d,3)
3315 enddo
3316 xface3(ixomax3+1)=x(ixomin1,ixomin2,ixomax3,3)+half*dx(ixomin1,ixomin2,ixomax3,3)
3317 end subroutine build_cart_dda_faces
3318
3319 integer function cart_dda_locate_index(pos,faces,imin,imax) result(idx)
3320 integer, intent(in) :: imin,imax
3321 double precision, intent(in) :: pos,faces(imin:imax+1)
3322
3323 integer :: ilo,ihi,imid
3324
3325 if (pos<=faces(imin)) then
3326 idx=imin
3327 return
3328 endif
3329 if (pos>=faces(imax+1)) then
3330 idx=imax
3331 return
3332 endif
3333
3334 ilo=imin
3335 ihi=imax+1
3336 do while (ihi-ilo>1)
3337 imid=(ilo+ihi)/2
3338 if (pos>=faces(imid)) then
3339 ilo=imid
3340 else
3341 ihi=imid
3342 endif
3343 enddo
3344 idx=min(imax,max(imin,ilo))
3345 end function cart_dda_locate_index
3346
3347 subroutine cart_dda_init_axis(ray_origin_axis,ray_dir_axis,faces,imin,imax,idx,step,tMax)
3348 integer, intent(in) :: imin,imax,idx
3349 double precision, intent(in) :: ray_origin_axis,ray_dir_axis,faces(imin:imax+1)
3350 integer, intent(out) :: step
3351 double precision, intent(out) :: tMax
3352
3353 if (ray_dir_axis>zero) then
3354 step=1
3355 tmax=(faces(idx+1)-ray_origin_axis)/ray_dir_axis
3356 else if (ray_dir_axis<zero) then
3357 step=-1
3358 tmax=(faces(idx)-ray_origin_axis)/ray_dir_axis
3359 else
3360 step=0
3361 tmax=huge(one)
3362 endif
3363 end subroutine cart_dda_init_axis
3364
3365 subroutine cart_dda_advance_axis(ray_origin_axis,ray_dir_axis,faces,imin,imax,idx,step,tMax,done)
3366 integer, intent(in) :: imin,imax,step
3367 double precision, intent(in) :: ray_origin_axis,ray_dir_axis,faces(imin:imax+1)
3368 integer, intent(inout) :: idx
3369 double precision, intent(inout) :: tMax
3370 logical, intent(out) :: done
3371
3372 done=.false.
3373 idx=idx+step
3374 if (idx<imin .or. idx>imax) then
3375 done=.true.
3376 return
3377 endif
3378 if (step>0) then
3379 tmax=(faces(idx+1)-ray_origin_axis)/ray_dir_axis
3380 else if (step<0) then
3381 tmax=(faces(idx)-ray_origin_axis)/ray_dir_axis
3382 else
3383 tmax=huge(one)
3384 endif
3385 end subroutine cart_dda_advance_axis
3386
3387 subroutine acc_euv_cart_dda(ixI^L,ixO^L,source,sourcev,&
3388 ray_origin,xface1,xface2,xface3,t_enter,t_exit,EUVp,Dplp)
3389 integer, intent(in) :: ixI^L, ixO^L
3390 double precision, intent(in) :: source(ixI^S),sourcev(ixI^S)
3391 double precision, intent(in) :: ray_origin(1:3)
3392 double precision, intent(in) :: xface1(ixOmin1:ixOmax1+1),xface2(ixOmin2:ixOmax2+1),&
3393 xface3(ixOmin3:ixOmax3+1)
3394 double precision, intent(in) :: t_enter,t_exit
3395 double precision, intent(inout) :: EUVp,Dplp
3396
3397 integer :: ix^D,step(1:3)
3398 double precision :: pos(1:3),tMax(1:3),tNow,tNext,ds_cm,epsRay
3399 logical :: done
3400
3401 if (t_exit<=t_enter) return
3402 epsray=max(1.d-12,1.d-10*abs(t_exit-t_enter))
3403 pos=ray_origin+(t_enter+epsray)*vec_los
3404 ix1=cart_dda_locate_index(pos(1),xface1,ixomin1,ixomax1)
3405 ix2=cart_dda_locate_index(pos(2),xface2,ixomin2,ixomax2)
3406 ix3=cart_dda_locate_index(pos(3),xface3,ixomin3,ixomax3)
3407
3408 call cart_dda_init_axis(ray_origin(1),vec_los(1),xface1,ixomin1,ixomax1,ix1,step(1),tmax(1))
3409 call cart_dda_init_axis(ray_origin(2),vec_los(2),xface2,ixomin2,ixomax2,ix2,step(2),tmax(2))
3410 call cart_dda_init_axis(ray_origin(3),vec_los(3),xface3,ixomin3,ixomax3,ix3,step(3),tmax(3))
3411
3412 tnow=t_enter
3413 do
3414 tnext=min(t_exit,tmax(1),tmax(2),tmax(3))
3415 if (tnext>tnow) then
3416 ds_cm=(tnext-tnow)*unit_length
3417 if (si_unit) ds_cm=ds_cm*1.d2
3418 euvp=euvp+source(ix^d)*ds_cm
3419 dplp=dplp+sourcev(ix^d)*ds_cm
3420 endif
3421 tnow=tnext
3422 if (tnow>=t_exit-epsray) exit
3423
3424 if (tmax(1)<=tnow+epsray) then
3425 call cart_dda_advance_axis(ray_origin(1),vec_los(1),xface1,ixomin1,ixomax1,ix1,step(1),tmax(1),done)
3426 if (done) exit
3427 endif
3428 if (tmax(2)<=tnow+epsray) then
3429 call cart_dda_advance_axis(ray_origin(2),vec_los(2),xface2,ixomin2,ixomax2,ix2,step(2),tmax(2),done)
3430 if (done) exit
3431 endif
3432 if (tmax(3)<=tnow+epsray) then
3433 call cart_dda_advance_axis(ray_origin(3),vec_los(3),xface3,ixomin3,ixomax3,ix3,step(3),tmax(3),done)
3434 if (done) exit
3435 endif
3436 enddo
3437 end subroutine acc_euv_cart_dda
3438
3439 subroutine append_cart_dda_segment(segments,nseg,capacity,pixel_id,tseg,jds,kds,jvds)
3440 double precision, allocatable, intent(inout) :: segments(:,:)
3441 integer, intent(inout) :: nseg,capacity
3442 integer, intent(in) :: pixel_id
3443 double precision, intent(in) :: tseg,jds,kds,jvds
3444
3445 double precision, allocatable :: tmp(:,:)
3446 integer :: new_capacity
3447
3448 if (capacity<=0) then
3449 capacity=1024
3450 allocate(segments(5,capacity))
3451 else if (nseg>=capacity) then
3452 new_capacity=2*capacity
3453 allocate(tmp(5,new_capacity))
3454 tmp(:,1:capacity)=segments(:,1:capacity)
3455 call move_alloc(tmp,segments)
3456 capacity=new_capacity
3457 endif
3458
3459 nseg=nseg+1
3460 segments(1,nseg)=dble(pixel_id)
3461 segments(2,nseg)=tseg
3462 segments(3,nseg)=jds
3463 segments(4,nseg)=kds
3464 segments(5,nseg)=jvds
3465 end subroutine append_cart_dda_segment
3466
3467 subroutine collect_euv_cart_dda_segments(ixI^L,ixO^L,source,opacity,sourcev,&
3468 pixel_id,ray_origin,xface1,xface2,xface3,t_enter,t_exit,&
3469 segments,nseg,capacity)
3470 integer, intent(in) :: ixI^L, ixO^L
3471 double precision, intent(in) :: source(ixI^S),opacity(ixI^S),sourcev(ixI^S)
3472 integer, intent(in) :: pixel_id
3473 double precision, intent(in) :: ray_origin(1:3)
3474 double precision, intent(in) :: xface1(ixOmin1:ixOmax1+1),xface2(ixOmin2:ixOmax2+1),&
3475 xface3(ixOmin3:ixOmax3+1)
3476 double precision, intent(in) :: t_enter,t_exit
3477 double precision, allocatable, intent(inout) :: segments(:,:)
3478 integer, intent(inout) :: nseg,capacity
3479
3480 integer :: ix^D,step(1:3)
3481 double precision :: pos(1:3),tMax(1:3),tNow,tNext,ds_cm,epsRay,tseg
3482 double precision :: jds,kds,jvds
3483 logical :: done
3484
3485 if (t_exit<=t_enter) return
3486 epsray=max(1.d-12,1.d-10*abs(t_exit-t_enter))
3487 pos=ray_origin+(t_enter+epsray)*vec_los
3488 ix1=cart_dda_locate_index(pos(1),xface1,ixomin1,ixomax1)
3489 ix2=cart_dda_locate_index(pos(2),xface2,ixomin2,ixomax2)
3490 ix3=cart_dda_locate_index(pos(3),xface3,ixomin3,ixomax3)
3491
3492 call cart_dda_init_axis(ray_origin(1),vec_los(1),xface1,ixomin1,ixomax1,ix1,step(1),tmax(1))
3493 call cart_dda_init_axis(ray_origin(2),vec_los(2),xface2,ixomin2,ixomax2,ix2,step(2),tmax(2))
3494 call cart_dda_init_axis(ray_origin(3),vec_los(3),xface3,ixomin3,ixomax3,ix3,step(3),tmax(3))
3495
3496 tnow=t_enter
3497 do
3498 tnext=min(t_exit,tmax(1),tmax(2),tmax(3))
3499 if (tnext>tnow) then
3500 ds_cm=(tnext-tnow)*unit_length
3501 if (si_unit) ds_cm=ds_cm*1.d2
3502 jds=source(ix^d)*ds_cm
3503 kds=opacity(ix^d)*ds_cm
3504 jvds=sourcev(ix^d)*ds_cm
3505 if (jds/=zero .or. kds/=zero .or. jvds/=zero) then
3506 tseg=half*(tnow+tnext)
3507 call append_cart_dda_segment(segments,nseg,capacity,pixel_id,tseg,jds,kds,jvds)
3508 endif
3509 endif
3510 tnow=tnext
3511 if (tnow>=t_exit-epsray) exit
3512
3513 if (tmax(1)<=tnow+epsray) then
3514 call cart_dda_advance_axis(ray_origin(1),vec_los(1),xface1,ixomin1,ixomax1,ix1,step(1),tmax(1),done)
3515 if (done) exit
3516 endif
3517 if (tmax(2)<=tnow+epsray) then
3518 call cart_dda_advance_axis(ray_origin(2),vec_los(2),xface2,ixomin2,ixomax2,ix2,step(2),tmax(2),done)
3519 if (done) exit
3520 endif
3521 if (tmax(3)<=tnow+epsray) then
3522 call cart_dda_advance_axis(ray_origin(3),vec_los(3),xface3,ixomin3,ixomax3,ix3,step(3),tmax(3),done)
3523 if (done) exit
3524 endif
3525 enddo
3526 end subroutine collect_euv_cart_dda_segments
3527
3528 subroutine sort_segment_indices_near_to_far(segments,idx,nidx)
3529 double precision, intent(in) :: segments(:,:)
3530 integer, intent(inout) :: idx(:)
3531 integer, intent(in) :: nidx
3532
3533 if (nidx<=1) return
3534 if (nidx<=32) then
3535 call insertion_sort_segment_indices(segments,idx,1,nidx)
3536 else
3537 call quicksort_segment_indices(segments,idx,1,nidx)
3538 endif
3540
3541 subroutine insertion_sort_segment_indices(segments,idx,ilo,ihi)
3542 double precision, intent(in) :: segments(:,:)
3543 integer, intent(inout) :: idx(:)
3544 integer, intent(in) :: ilo,ihi
3545
3546 integer :: i,j,key
3547
3548 do i=ilo+1,ihi
3549 key=idx(i)
3550 j=i-1
3551 do while (j>=ilo .and. segments(2,idx(j))>segments(2,key))
3552 idx(j+1)=idx(j)
3553 j=j-1
3554 enddo
3555 idx(j+1)=key
3556 enddo
3557 end subroutine insertion_sort_segment_indices
3558
3559 recursive subroutine quicksort_segment_indices(segments,idx,ilo,ihi)
3560 double precision, intent(in) :: segments(:,:)
3561 integer, intent(inout) :: idx(:)
3562 integer, intent(in) :: ilo,ihi
3563
3564 integer :: i,j,tmp
3565 double precision :: pivot
3566
3567 if (ihi-ilo<=32) then
3568 call insertion_sort_segment_indices(segments,idx,ilo,ihi)
3569 return
3570 endif
3571
3572 i=ilo
3573 j=ihi
3574 pivot=segments(2,idx((ilo+ihi)/2))
3575 do
3576 do while (segments(2,idx(i))<pivot)
3577 i=i+1
3578 enddo
3579 do while (segments(2,idx(j))>pivot)
3580 j=j-1
3581 enddo
3582 if (i<=j) then
3583 tmp=idx(i)
3584 idx(i)=idx(j)
3585 idx(j)=tmp
3586 i=i+1
3587 j=j-1
3588 endif
3589 if (i>j) exit
3590 enddo
3591
3592 if (ilo<j) call quicksort_segment_indices(segments,idx,ilo,j)
3593 if (i<ihi) call quicksort_segment_indices(segments,idx,i,ihi)
3594 end subroutine quicksort_segment_indices
3595
3596 integer function segment_pixel_owner(pixel_id) result(owner)
3597 integer, intent(in) :: pixel_id
3598
3599 owner=mod(pixel_id-1,npe)
3600 end function segment_pixel_owner
3601
3602 logical function segment_is_valid(segments,is,nvars) result(valid)
3603 double precision, intent(in) :: segments(:,:)
3604 integer, intent(in) :: is,nvars
3605
3606 integer :: iv
3607
3608 valid=.true.
3609 do iv=1,nvars
3610 if (segments(iv,is)/=segments(iv,is) .or. abs(segments(iv,is))>=1.d90) then
3611 valid=.false.
3612 return
3613 endif
3614 enddo
3615 end function segment_is_valid
3616
3617 subroutine cart_dda_block_pixel_range(box_min,box_max,nXIF1,nXIF2,xIF1,xIF2,ixPmin1,ixPmax1,ixPmin2,ixPmax2,has_pixels)
3618 double precision, intent(in) :: box_min(1:3),box_max(1:3)
3619 integer, intent(in) :: nXIF1,nXIF2
3620 double precision, intent(in) :: xIF1(nXIF1),xIF2(nXIF2)
3621 integer, intent(out) :: ixPmin1,ixPmax1,ixPmin2,ixPmax2
3622 logical, intent(out) :: has_pixels
3623
3624 integer :: i1,i2,i3
3625 double precision :: vec_cor(1:3),xI_cor(1:2)
3626 double precision :: xmin1,xmax1,xmin2,xmax2,dx1,dx2
3627
3628 do i1=1,2
3629 if (i1==1) vec_cor(1)=box_min(1)
3630 if (i1==2) vec_cor(1)=box_max(1)
3631 do i2=1,2
3632 if (i2==1) vec_cor(2)=box_min(2)
3633 if (i2==2) vec_cor(2)=box_max(2)
3634 do i3=1,2
3635 if (i3==1) vec_cor(3)=box_min(3)
3636 if (i3==2) vec_cor(3)=box_max(3)
3637 call get_cor_image(vec_cor,xi_cor)
3638 if (i1==1 .and. i2==1 .and. i3==1) then
3639 xmin1=xi_cor(1)
3640 xmax1=xi_cor(1)
3641 xmin2=xi_cor(2)
3642 xmax2=xi_cor(2)
3643 else
3644 xmin1=min(xmin1,xi_cor(1))
3645 xmax1=max(xmax1,xi_cor(1))
3646 xmin2=min(xmin2,xi_cor(2))
3647 xmax2=max(xmax2,xi_cor(2))
3648 endif
3649 enddo
3650 enddo
3651 enddo
3652
3653 if (nxif1>1) then
3654 dx1=abs(xif1(2)-xif1(1))
3655 else
3656 dx1=max(one,abs(xmax1-xmin1))
3657 endif
3658 if (nxif2>1) then
3659 dx2=abs(xif2(2)-xif2(1))
3660 else
3661 dx2=max(one,abs(xmax2-xmin2))
3662 endif
3663
3664 ixpmin1=max(1,floor((xmin1-xif1(1))/dx1)+1-1)
3665 ixpmax1=min(nxif1,ceiling((xmax1-xif1(1))/dx1)+1+1)
3666 ixpmin2=max(1,floor((xmin2-xif2(1))/dx2)+1-1)
3667 ixpmax2=min(nxif2,ceiling((xmax2-xif2(1))/dx2)+1+1)
3668 has_pixels=ixpmin1<=ixpmax1 .and. ixpmin2<=ixpmax2
3669 end subroutine cart_dda_block_pixel_range
3670
3671 subroutine integrate_euv_cart_dda_datresol(nXIF1,nXIF2,xIF1,xIF2,fl,EUV,Dpl)
3673
3674 integer, intent(in) :: nXIF1,nXIF2
3675 double precision, intent(in) :: xIF1(nXIF1),xIF2(nXIF2)
3676 type(te_fluid), intent(in) :: fl
3677 double precision, intent(out) :: EUV(nXIF1,nXIF2),Dpl(nXIF1,nXIF2)
3678
3679 integer :: ixO^L,ixO^D,ixI^L,ix^D
3680 integer :: iigrid,igrid,ixP1,ixP2,numSI,ixPmin1,ixPmax1,ixPmin2,ixPmax2
3681 double precision :: box_min(1:3),box_max(1:3),ray_origin(1:3)
3682 double precision :: t_enter,t_exit,vlos
3683 double precision :: profile_local(2),profile_global(2)
3684 logical :: hit,has_pixels
3685 double precision, allocatable :: source(:^D&),sourcev(:^D&),rho(:^D&),opacity(:^D&)
3686 double precision, allocatable :: xface1(:),xface2(:),xface3(:)
3687 double precision, allocatable :: EUVs(:,:),Dpls(:,:)
3688
3689 allocate(euvs(nxif1,nxif2),dpls(nxif1,nxif2))
3690 euvs=zero
3691 dpls=zero
3692 profile_local=zero
3693
3694 do iigrid=1,igridstail; igrid=igrids(iigrid);
3695 ^d&ixomin^d=ixmlo^d\
3696 ^d&ixomax^d=ixmhi^d\
3697 ^d&iximin^d=ixglo^d\
3698 ^d&iximax^d=ixghi^d\
3699
3700 box_min(1)=rnode(rpxmin1_,igrid)
3701 box_min(2)=rnode(rpxmin2_,igrid)
3702 box_min(3)=rnode(rpxmin3_,igrid)
3703 box_max(1)=rnode(rpxmax1_,igrid)
3704 box_max(2)=rnode(rpxmax2_,igrid)
3705 box_max(3)=rnode(rpxmax3_,igrid)
3706 call build_cart_dda_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,xface1,xface2,xface3)
3707 call cart_dda_block_pixel_range(box_min,box_max,nxif1,nxif2,xif1,xif2,&
3708 ixpmin1,ixpmax1,ixpmin2,ixpmax2,has_pixels)
3709 if (.not. has_pixels) then
3710 deallocate(xface1,xface2,xface3)
3711 cycle
3712 endif
3713
3714 allocate(source(ixi^s),sourcev(ixi^s),rho(ixi^s),opacity(ixi^s))
3715 source=zero
3716 sourcev=zero
3717 if (trim(emission_model)=='pseudo_current') then
3718 call get_pseudo_current(igrid,ixi^l,ixo^l,ps(igrid)%w,source)
3719 else if (trim(emission_model)=='radio_ff') then
3720 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,source,opacity)
3721 else
3722 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,source)
3723 source(ixo^s)=source(ixo^s)/instrument_resolution_factor**2
3724 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,rho)
3725 do ix1=ixomin1,ixomax1
3726 do ix2=ixomin2,ixomax2
3727 do ix3=ixomin3,ixomax3
3728 if (rho(ix^d)>smalldouble) then
3729 vlos=(ps(igrid)%w(ix^d,iw_mom(1))*vec_los(1)+&
3730 ps(igrid)%w(ix^d,iw_mom(2))*vec_los(2)+&
3731 ps(igrid)%w(ix^d,iw_mom(3))*vec_los(3))/rho(ix^d)
3732 sourcev(ix^d)=source(ix^d)*vlos
3733 endif
3734 enddo
3735 enddo
3736 enddo
3737 endif
3738 deallocate(rho,opacity)
3739
3740 do ixp1=ixpmin1,ixpmax1
3741 do ixp2=ixpmin2,ixpmax2
3742 ray_origin=x_origin+xif1(ixp1)*vec_xi1+xif2(ixp2)*vec_xi2
3743 profile_local(1)=profile_local(1)+one
3744 call ray_box_intersection_cart(ray_origin,vec_los,box_min,box_max,hit,t_enter,t_exit)
3745 if (hit) then
3746 profile_local(2)=profile_local(2)+one
3747 call acc_euv_cart_dda(ixi^l,ixo^l,source,sourcev,&
3748 ray_origin,xface1,xface2,xface3,t_enter,t_exit,euvs(ixp1,ixp2),dpls(ixp1,ixp2))
3749 endif
3750 enddo
3751 enddo
3752
3753 deallocate(source,sourcev,xface1,xface2,xface3)
3754 enddo
3755
3756 numsi=nxif1*nxif2
3757 call mpi_allreduce(euvs,euv,numsi,mpi_double_precision,mpi_sum,icomm,ierrmpi)
3758 call mpi_allreduce(dpls,dpl,numsi,mpi_double_precision,mpi_sum,icomm,ierrmpi)
3759 call mpi_allreduce(profile_local,profile_global,2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
3760 if (radsyn_verbose .and. mype==0) then
3761 write(*,'(a,2(es12.5,1x))') ' cart_dda thin profile ray_tests ray_hits: ',profile_global
3762 endif
3763 deallocate(euvs,dpls)
3764 end subroutine integrate_euv_cart_dda_datresol
3765
3766 subroutine integrate_euv_cart_dda_thick_datresol(nXIF1,nXIF2,xIF1,xIF2,fl,EUV,Dpl,Tau,EUVthin)
3768
3769 integer, intent(in) :: nXIF1,nXIF2
3770 double precision, intent(in) :: xIF1(nXIF1),xIF2(nXIF2)
3771 type(te_fluid), intent(in) :: fl
3772 double precision, intent(out) :: EUV(nXIF1,nXIF2),Dpl(nXIF1,nXIF2)
3773 double precision, intent(out) :: Tau(nXIF1,nXIF2),EUVthin(nXIF1,nXIF2)
3774
3775 integer, parameter :: nSegVars=5
3776 integer :: ixO^L,ixO^D,ixI^L,ix^D
3777 integer :: iigrid,igrid,ixP1,ixP2,ipix,ipixStart,ipixEnd,nPixBatch,pixel_id
3778 integer :: nseg,capacity,totalCount,totalSeg,ipe,is,iseg,nidx,owner,isegDest,nsegBefore
3779 integer :: ixGlobal,iyGlobal,ixPmin1,ixPmax1,ixPmin2,ixPmax2,iFirst,iLast,iLocal
3780 integer :: nPixBatchTarget
3781 integer :: maxSegBatchTarget,maxSegCommTarget,maxNsegBatch,nPixTotal
3782 integer :: maxOwnerSegCount,maxOwnerSegCountLocal,segOffset,recvFill,totalRoundCount,totalRoundSeg
3783 integer, allocatable :: sendCounts(:),recvCounts(:),sendDispls(:),recvDispls(:)
3784 integer, allocatable :: roundSendCounts(:),roundRecvCounts(:)
3785 integer, allocatable :: roundSendDispls(:),roundRecvDispls(:)
3786 integer, allocatable :: ownerSegCounts(:),ownerOffsets(:),idx(:)
3787 integer, allocatable :: bucketCounts(:),bucketOffsets(:),bucketFill(:)
3788 double precision :: ray_origin(1:3)
3789 double precision :: t_enter,t_exit,vlos,atten
3790 double precision :: profile_local(5),profile_global(5),profile_batch(5)
3791 logical :: hit,has_pixels,batchAccepted,batchReduced
3792 double precision, allocatable :: rho(:^D&)
3793 double precision, allocatable :: segments(:,:),segments_send(:,:),segments_recv(:,:)
3794 double precision, allocatable :: segments_recv_round(:,:)
3795 double precision, allocatable :: image_reduce(:,:)
3796 type(radsyn_euv_cache), allocatable :: cache(:)
3797
3798 euv=zero
3799 dpl=zero
3800 tau=zero
3801 euvthin=zero
3802 profile_local=zero
3803 allocate(sendcounts(0:npe-1),recvcounts(0:npe-1),senddispls(0:npe-1),recvdispls(0:npe-1))
3804 allocate(roundsendcounts(0:npe-1),roundrecvcounts(0:npe-1))
3805 allocate(roundsenddispls(0:npe-1),roundrecvdispls(0:npe-1))
3806 allocate(ownersegcounts(0:npe-1),owneroffsets(0:npe-1))
3807 allocate(cache(igridstail))
3808 call radsyn_get_segment_batch_limits(npixbatchtarget,maxsegbatchtarget,maxsegcommtarget)
3809 allocate(bucketcounts(npixbatchtarget),bucketoffsets(npixbatchtarget+1),&
3810 bucketfill(npixbatchtarget))
3811
3812 do iigrid=1,igridstail; igrid=igrids(iigrid);
3813 ^d&ixomin^d=ixmlo^d\
3814 ^d&ixomax^d=ixmhi^d\
3815 ^d&iximin^d=ixglo^d\
3816 ^d&iximax^d=ixghi^d\
3817
3818 cache(iigrid)%igrid=igrid
3819 allocate(cache(iigrid)%source(ixi^s),cache(iigrid)%opacity(ixi^s),&
3820 cache(iigrid)%sourcev(ixi^s),rho(ixi^s))
3821 cache(iigrid)%source=zero
3822 cache(iigrid)%opacity=zero
3823 cache(iigrid)%sourcev=zero
3824 if (trim(emission_model)=='radio_ff') then
3825 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,&
3826 cache(iigrid)%source,cache(iigrid)%opacity)
3827 else
3828 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%source)
3829 cache(iigrid)%source(ixo^s)=cache(iigrid)%source(ixo^s)/instrument_resolution_factor**2
3830 call get_euv_hhe_opacity(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%opacity)
3831 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,rho)
3832 do ix1=ixomin1,ixomax1
3833 do ix2=ixomin2,ixomax2
3834 do ix3=ixomin3,ixomax3
3835 if (rho(ix^d)>smalldouble) then
3836 vlos=(ps(igrid)%w(ix^d,iw_mom(1))*vec_los(1)+&
3837 ps(igrid)%w(ix^d,iw_mom(2))*vec_los(2)+&
3838 ps(igrid)%w(ix^d,iw_mom(3))*vec_los(3))/rho(ix^d)
3839 cache(iigrid)%sourcev(ix^d)=cache(iigrid)%source(ix^d)*vlos
3840 endif
3841 enddo
3842 enddo
3843 enddo
3844 endif
3845 deallocate(rho)
3846 cache(iigrid)%box_min(1)=rnode(rpxmin1_,igrid)
3847 cache(iigrid)%box_min(2)=rnode(rpxmin2_,igrid)
3848 cache(iigrid)%box_min(3)=rnode(rpxmin3_,igrid)
3849 cache(iigrid)%box_max(1)=rnode(rpxmax1_,igrid)
3850 cache(iigrid)%box_max(2)=rnode(rpxmax2_,igrid)
3851 cache(iigrid)%box_max(3)=rnode(rpxmax3_,igrid)
3852 call build_cart_dda_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,&
3853 cache(iigrid)%xface1,cache(iigrid)%xface2,&
3854 cache(iigrid)%xface3)
3855 call cart_dda_block_pixel_range(cache(iigrid)%box_min,cache(iigrid)%box_max,&
3856 nxif1,nxif2,xif1,xif2,cache(iigrid)%ixPmin1,cache(iigrid)%ixPmax1,&
3857 cache(iigrid)%ixPmin2,cache(iigrid)%ixPmax2,cache(iigrid)%has_pixels)
3858 enddo
3859
3860 npixtotal=nxif1*nxif2
3861 ipixstart=1
3862 do while (ipixstart<=npixtotal)
3863 ipixend=min(nxif1*nxif2,ipixstart+npixbatchtarget-1)
3864 npixbatch=ipixend-ipixstart+1
3865 batchaccepted=.false.
3866 batchreduced=.false.
3867
3868 do while (.not. batchaccepted)
3869 nseg=0
3870 capacity=0
3871 profile_batch=zero
3872
3873 do iigrid=1,igridstail; igrid=igrids(iigrid);
3874 ^d&ixomin^d=ixmlo^d\
3875 ^d&ixomax^d=ixmhi^d\
3876 ^d&iximin^d=ixglo^d\
3877 ^d&iximax^d=ixghi^d\
3878
3879 ixpmin1=cache(iigrid)%ixPmin1
3880 ixpmax1=cache(iigrid)%ixPmax1
3881 ixpmin2=cache(iigrid)%ixPmin2
3882 ixpmax2=cache(iigrid)%ixPmax2
3883 has_pixels=cache(iigrid)%has_pixels
3884 if (.not. has_pixels) cycle
3885
3886 do ixp2=ixpmin2,ixpmax2
3887 ifirst=max(ipixstart,(ixp2-1)*nxif1+ixpmin1)
3888 ilast=min(ipixend,(ixp2-1)*nxif1+ixpmax1)
3889 if (ifirst>ilast) cycle
3890 do ipix=ifirst,ilast
3891 ixp1=1+mod(ipix-1,nxif1)
3892 ray_origin=x_origin+xif1(ixp1)*vec_xi1+xif2(ixp2)*vec_xi2
3893 profile_batch(1)=profile_batch(1)+one
3894 call ray_box_intersection_cart(ray_origin,vec_los,cache(iigrid)%box_min,&
3895 cache(iigrid)%box_max,hit,t_enter,t_exit)
3896 if (hit) then
3897 profile_batch(2)=profile_batch(2)+one
3898 nsegbefore=nseg
3899 call collect_euv_cart_dda_segments(ixi^l,ixo^l,cache(iigrid)%source,&
3900 cache(iigrid)%opacity,cache(iigrid)%sourcev,&
3901 ipix,ray_origin,cache(iigrid)%xface1,&
3902 cache(iigrid)%xface2,cache(iigrid)%xface3,&
3903 t_enter,t_exit,&
3904 segments,nseg,capacity)
3905 profile_batch(3)=profile_batch(3)+dble(nseg-nsegbefore)
3906 endif
3907 enddo
3908 enddo
3909 enddo
3910
3911 call mpi_allreduce(nseg,maxnsegbatch,1,mpi_integer,mpi_max,icomm,ierrmpi)
3912 if (maxnsegbatch>maxsegbatchtarget .and. npixbatch>1) then
3913 npixbatch=max(1,npixbatch/2)
3914 ipixend=ipixstart+npixbatch-1
3915 if (allocated(segments)) deallocate(segments)
3916 batchreduced=.true.
3917 else
3918 batchaccepted=.true.
3919 endif
3920 enddo
3921
3922 profile_local=profile_local+profile_batch
3923 if (radsyn_verbose .and. mype==0 .and. batchreduced) then
3924 write(*,'(a,3(i0,1x))') ' cart_dda thick adaptive batch: ',&
3925 ipixstart,ipixend,maxnsegbatch
3926 endif
3927
3928 if (.not. allocated(segments)) then
3929 capacity=1
3930 allocate(segments(nsegvars,capacity))
3931 endif
3932 ownersegcounts=0
3933 do is=1,nseg
3934 owner=segment_pixel_owner(nint(segments(1,is)))
3935 ownersegcounts(owner)=ownersegcounts(owner)+1
3936 enddo
3937 sendcounts=nsegvars*ownersegcounts
3938 senddispls(0)=0
3939 do ipe=1,npe-1
3940 senddispls(ipe)=senddispls(ipe-1)+sendcounts(ipe-1)
3941 enddo
3942
3943 allocate(segments_send(nsegvars,max(1,nseg)))
3944 owneroffsets=0
3945 do is=1,nseg
3946 owner=segment_pixel_owner(nint(segments(1,is)))
3947 isegdest=senddispls(owner)/nsegvars+owneroffsets(owner)+1
3948 segments_send(:,isegdest)=segments(:,is)
3949 owneroffsets(owner)=owneroffsets(owner)+1
3950 enddo
3951
3952 call mpi_alltoall(sendcounts,1,mpi_integer,recvcounts,1,mpi_integer,icomm,ierrmpi)
3953 recvdispls(0)=0
3954 do ipe=1,npe-1
3955 recvdispls(ipe)=recvdispls(ipe-1)+recvcounts(ipe-1)
3956 enddo
3957 totalcount=sum(recvcounts)
3958 totalseg=totalcount/nsegvars
3959 profile_local(4)=profile_local(4)+dble(totalcount)
3960 allocate(segments_recv(nsegvars,max(1,totalseg)))
3961
3962 recvfill=0
3963 maxownersegcountlocal=maxval(ownersegcounts)
3964 call mpi_allreduce(maxownersegcountlocal,maxownersegcount,1,mpi_integer,mpi_max,icomm,ierrmpi)
3965 do segoffset=0,maxownersegcount-1,maxsegcommtarget
3966 roundsendcounts=0
3967 roundsenddispls=senddispls
3968 do ipe=0,npe-1
3969 if (ownersegcounts(ipe)>segoffset) then
3970 roundsendcounts(ipe)=nsegvars*min(maxsegcommtarget,ownersegcounts(ipe)-segoffset)
3971 roundsenddispls(ipe)=senddispls(ipe)+nsegvars*segoffset
3972 endif
3973 enddo
3974
3975 call mpi_alltoall(roundsendcounts,1,mpi_integer,roundrecvcounts,1,mpi_integer,icomm,ierrmpi)
3976 roundrecvdispls(0)=0
3977 do ipe=1,npe-1
3978 roundrecvdispls(ipe)=roundrecvdispls(ipe-1)+roundrecvcounts(ipe-1)
3979 enddo
3980 totalroundcount=sum(roundrecvcounts)
3981 totalroundseg=totalroundcount/nsegvars
3982 allocate(segments_recv_round(nsegvars,max(1,totalroundseg)))
3983
3984 call mpi_alltoallv(segments_send,roundsendcounts,roundsenddispls,mpi_double_precision,&
3985 segments_recv_round,roundrecvcounts,roundrecvdispls,&
3986 mpi_double_precision,icomm,ierrmpi)
3987
3988 if (totalroundseg>0) then
3989 segments_recv(:,recvfill+1:recvfill+totalroundseg)=segments_recv_round(:,1:totalroundseg)
3990 recvfill=recvfill+totalroundseg
3991 endif
3992 deallocate(segments_recv_round)
3993 enddo
3994
3995 if (recvfill/=totalseg) call mpistop("cart_dda thick segmented receive mismatch")
3996
3997 if (totalseg>0) then
3998 allocate(idx(totalseg))
3999 bucketcounts(1:npixbatch)=0
4000 do is=1,totalseg
4001 if (segment_is_valid(segments_recv,is,nsegvars)) then
4002 ipix=nint(segments_recv(1,is))
4003 if (ipix>=ipixstart .and. ipix<=ipixend .and. segment_pixel_owner(ipix)==mype) then
4004 ilocal=ipix-ipixstart+1
4005 bucketcounts(ilocal)=bucketcounts(ilocal)+1
4006 endif
4007 endif
4008 enddo
4009
4010 bucketoffsets(1)=1
4011 do ilocal=1,npixbatch
4012 bucketoffsets(ilocal+1)=bucketoffsets(ilocal)+bucketcounts(ilocal)
4013 enddo
4014 bucketfill(1:npixbatch)=bucketoffsets(1:npixbatch)
4015 do is=1,totalseg
4016 if (segment_is_valid(segments_recv,is,nsegvars)) then
4017 ipix=nint(segments_recv(1,is))
4018 if (ipix>=ipixstart .and. ipix<=ipixend .and. segment_pixel_owner(ipix)==mype) then
4019 ilocal=ipix-ipixstart+1
4020 idx(bucketfill(ilocal))=is
4021 bucketfill(ilocal)=bucketfill(ilocal)+1
4022 endif
4023 endif
4024 enddo
4025
4026 do ipix=ipixstart,ipixend
4027 if (segment_pixel_owner(ipix)/=mype) cycle
4028 ilocal=ipix-ipixstart+1
4029 nidx=bucketcounts(ilocal)
4030 if (nidx>0) then
4031 profile_local(5)=profile_local(5)+dble(nidx)*dble(nidx)
4032 call sort_segment_indices_near_to_far(segments_recv,idx(bucketoffsets(ilocal):bucketoffsets(ilocal+1)-1),nidx)
4033 ixglobal=1+mod(ipix-1,nxif1)
4034 iyglobal=1+(ipix-1)/nxif1
4035 do iseg=bucketoffsets(ilocal),bucketoffsets(ilocal+1)-1
4036 is=idx(iseg)
4037 euvthin(ixglobal,iyglobal)=euvthin(ixglobal,iyglobal)+segments_recv(3,is)
4038 atten=transfer_attenuation(tau(ixglobal,iyglobal))
4039 euv(ixglobal,iyglobal)=euv(ixglobal,iyglobal)+atten*segments_recv(3,is)
4040 dpl(ixglobal,iyglobal)=dpl(ixglobal,iyglobal)+atten*segments_recv(5,is)
4041 tau(ixglobal,iyglobal)=tau(ixglobal,iyglobal)+max(zero,segments_recv(4,is))
4042 enddo
4043 endif
4044 enddo
4045 deallocate(idx)
4046 endif
4047
4048 deallocate(segments_send,segments_recv)
4049 if (allocated(segments)) deallocate(segments)
4050 ipixstart=ipixend+1
4051 enddo
4052
4053 do iigrid=1,igridstail
4054 if (allocated(cache(iigrid)%source)) deallocate(cache(iigrid)%source)
4055 if (allocated(cache(iigrid)%opacity)) deallocate(cache(iigrid)%opacity)
4056 if (allocated(cache(iigrid)%sourcev)) deallocate(cache(iigrid)%sourcev)
4057 if (allocated(cache(iigrid)%xface1)) deallocate(cache(iigrid)%xface1)
4058 if (allocated(cache(iigrid)%xface2)) deallocate(cache(iigrid)%xface2)
4059 if (allocated(cache(iigrid)%xface3)) deallocate(cache(iigrid)%xface3)
4060 enddo
4061 deallocate(cache)
4062 deallocate(sendcounts,recvcounts,senddispls,recvdispls,roundsendcounts,roundrecvcounts,&
4063 roundsenddispls,roundrecvdispls,ownersegcounts,owneroffsets,bucketcounts,&
4064 bucketoffsets,bucketfill)
4065 allocate(image_reduce(nxif1,nxif2))
4066 call mpi_allreduce(euv,image_reduce,nxif1*nxif2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
4067 euv=image_reduce
4068 call mpi_allreduce(dpl,image_reduce,nxif1*nxif2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
4069 dpl=image_reduce
4070 call mpi_allreduce(tau,image_reduce,nxif1*nxif2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
4071 tau=image_reduce
4072 call mpi_allreduce(euvthin,image_reduce,nxif1*nxif2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
4073 euvthin=image_reduce
4074 deallocate(image_reduce)
4075 call mpi_allreduce(profile_local,profile_global,5,mpi_double_precision,mpi_sum,icomm,ierrmpi)
4076 if (radsyn_verbose .and. mype==0) then
4077 write(*,'(a,5(es12.5,1x))') &
4078 ' cart_dda thick profile: ',profile_global
4079 endif
4081
4082 subroutine integrate_euv_thick_datresol(nXIF1,nXIF2,fl,EUV,Dpl,Tau,EUVthin)
4084
4085 integer, intent(in) :: nXIF1,nXIF2
4086 type(te_fluid), intent(in) :: fl
4087 double precision, intent(out) :: EUV(nXIF1,nXIF2),Dpl(nXIF1,nXIF2)
4088 double precision, intent(out) :: Tau(nXIF1,nXIF2),EUVthin(nXIF1,nXIF2)
4089
4090 integer :: ixO^L,ixO^D,ixI^L,ix^D
4091 integer :: iigrid,igrid,levelg,rft,direction_LOS,nLOS,numSeg,nLayerVars,nLayerSeg
4092 integer :: ixP1,ixP2,ixL,iSub1,iSub2,relL
4093 integer :: nLosBatch,nBatch,iBatch,ixLstart,ixLend,ixLgridStart,ixLgridEnd
4094 integer :: ixPmin1,ixPmin2
4095 double precision :: ds_cm,jds,kds,jvds,atten,layerBytes,targetBytes
4096 double precision, allocatable :: rho(:^D&)
4097 double precision, allocatable :: layer_ds(:,:,:,:),layer_all(:,:,:,:)
4098 type(radsyn_euv_cache), allocatable :: cache(:)
4099
4100 if (los_phi==0 .and. los_theta==90) then
4101 direction_los=1
4102 nlos=domain_nx1*2**(refine_max_level-1)
4103 else if (los_phi==90 .and. los_theta==90) then
4104 direction_los=2
4105 nlos=domain_nx2*2**(refine_max_level-1)
4106 else
4107 direction_los=3
4108 nlos=domain_nx3*2**(refine_max_level-1)
4109 endif
4110
4111 nlayervars=3
4112 if (nxif1>huge(numseg)/max(1,nxif2) .or. nxif1*nxif2>huge(numseg)/nlayervars) then
4113 call mpistop("thick EUV layer buffer is too large for one MPI reduction")
4114 endif
4115 nlayerseg=nxif1*nxif2*nlayervars
4116 targetbytes=256.d0*1024.d0*1024.d0
4117 layerbytes=dble(nlayerseg)*8.d0*2.d0
4118 nlosbatch=max(1,min(16,int(targetbytes/max(one,layerbytes))))
4119 if (nlayerseg>huge(numseg)/nlosbatch) then
4120 call mpistop("thick EUV batched layer buffer is too large for one MPI reduction")
4121 endif
4122
4123 allocate(cache(igridstail))
4124 do iigrid=1,igridstail; igrid=igrids(iigrid);
4125 ^d&ixomin^d=ixmlo^d\
4126 ^d&ixomax^d=ixmhi^d\
4127 ^d&iximin^d=ixglo^d\
4128 ^d&iximax^d=ixghi^d\
4129
4130 cache(iigrid)%igrid=igrid
4131 levelg=ps(igrid)%level
4132 rft=2**(refine_max_level-levelg)
4133 cache(iigrid)%level=levelg
4134 cache(iigrid)%rft=rft
4135
4136 select case(direction_los)
4137 case(1)
4138 cache(iigrid)%los_min=(node(pig1_,igrid)-1)*rft*block_nx1+1
4139 cache(iigrid)%los_max=node(pig1_,igrid)*rft*block_nx1
4140 case(2)
4141 cache(iigrid)%los_min=(node(pig2_,igrid)-1)*rft*block_nx2+1
4142 cache(iigrid)%los_max=node(pig2_,igrid)*rft*block_nx2
4143 case(3)
4144 cache(iigrid)%los_min=(node(pig3_,igrid)-1)*rft*block_nx3+1
4145 cache(iigrid)%los_max=node(pig3_,igrid)*rft*block_nx3
4146 end select
4147
4148 allocate(cache(iigrid)%source(ixi^s),cache(iigrid)%opacity(ixi^s),&
4149 cache(iigrid)%sourcev(ixi^s),rho(ixi^s))
4150 cache(iigrid)%source=zero
4151 cache(iigrid)%opacity=zero
4152 cache(iigrid)%sourcev=zero
4153 if (trim(emission_model)=='radio_ff') then
4154 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,&
4155 cache(iigrid)%source,cache(iigrid)%opacity)
4156 else
4157 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%source)
4158 cache(iigrid)%source(ixo^s)=cache(iigrid)%source(ixo^s)/instrument_resolution_factor**2
4159 call get_euv_hhe_opacity(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%opacity)
4160 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,rho)
4161 cache(iigrid)%sourcev(ixo^s)=cache(iigrid)%source(ixo^s)*&
4162 (-ps(igrid)%w(ixo^s,iw_mom(direction_los))/rho(ixo^s))
4163 endif
4164 deallocate(rho)
4165 enddo
4166
4167 ! Stream a small batch of finest LOS layers; this avoids a full Npix*Nlos column buffer.
4168 allocate(layer_ds(nxif1,nxif2,nlayervars,nlosbatch),layer_all(nxif1,nxif2,nlayervars,nlosbatch))
4169 euv=zero
4170 dpl=zero
4171 tau=zero
4172 euvthin=zero
4173
4174 do ixlstart=1,nlos,nlosbatch
4175 ixlend=min(nlos,ixlstart+nlosbatch-1)
4176 nbatch=ixlend-ixlstart+1
4177 layer_ds(:,:,:,1:nbatch)=zero
4178
4179 do iigrid=1,igridstail
4180 ixlgridstart=max(ixlstart,cache(iigrid)%los_min)
4181 ixlgridend=min(ixlend,cache(iigrid)%los_max)
4182 if (ixlgridstart>ixlgridend) cycle
4183 igrid=cache(iigrid)%igrid
4184 rft=cache(iigrid)%rft
4185 ^d&ixomin^d=ixmlo^d\
4186 ^d&ixomax^d=ixmhi^d\
4187 ^d&iximin^d=ixglo^d\
4188 ^d&iximax^d=ixghi^d\
4189
4190 do ixl=ixlgridstart,ixlgridend
4191 ibatch=ixl-ixlstart+1
4192 rell=ixl-cache(iigrid)%los_min
4193
4194 select case(direction_los)
4195 case(1)
4196 ix1=ixomin1+rell/rft
4197 do ix2=ixomin2,ixomax2
4198 ixpmin1=(node(pig2_,igrid)-1)*rft*block_nx2+(ix2-ixomin2)*rft+1
4199 do ix3=ixomin3,ixomax3
4200 ixpmin2=(node(pig3_,igrid)-1)*rft*block_nx3+(ix3-ixomin3)*rft+1
4201 ds_cm=ps(igrid)%dx(ix^d,1)*unit_length/dble(rft)
4202 if (si_unit) ds_cm=ds_cm*1.d2
4203 jds=cache(iigrid)%source(ix^d)*ds_cm
4204 kds=cache(iigrid)%opacity(ix^d)*ds_cm
4205 jvds=cache(iigrid)%sourcev(ix^d)*ds_cm
4206 do isub1=0,rft-1
4207 ixp1=ixpmin1+isub1
4208 do isub2=0,rft-1
4209 ixp2=ixpmin2+isub2
4210 layer_ds(ixp1,ixp2,1,ibatch)=layer_ds(ixp1,ixp2,1,ibatch)+jds
4211 layer_ds(ixp1,ixp2,2,ibatch)=layer_ds(ixp1,ixp2,2,ibatch)+kds
4212 layer_ds(ixp1,ixp2,3,ibatch)=layer_ds(ixp1,ixp2,3,ibatch)+jvds
4213 enddo
4214 enddo
4215 enddo
4216 enddo
4217 case(2)
4218 ix2=ixomin2+rell/rft
4219 do ix3=ixomin3,ixomax3
4220 ixpmin1=(node(pig3_,igrid)-1)*rft*block_nx3+(ix3-ixomin3)*rft+1
4221 do ix1=ixomin1,ixomax1
4222 ixpmin2=(node(pig1_,igrid)-1)*rft*block_nx1+(ix1-ixomin1)*rft+1
4223 ds_cm=ps(igrid)%dx(ix^d,2)*unit_length/dble(rft)
4224 if (si_unit) ds_cm=ds_cm*1.d2
4225 jds=cache(iigrid)%source(ix^d)*ds_cm
4226 kds=cache(iigrid)%opacity(ix^d)*ds_cm
4227 jvds=cache(iigrid)%sourcev(ix^d)*ds_cm
4228 do isub1=0,rft-1
4229 ixp1=ixpmin1+isub1
4230 do isub2=0,rft-1
4231 ixp2=ixpmin2+isub2
4232 layer_ds(ixp1,ixp2,1,ibatch)=layer_ds(ixp1,ixp2,1,ibatch)+jds
4233 layer_ds(ixp1,ixp2,2,ibatch)=layer_ds(ixp1,ixp2,2,ibatch)+kds
4234 layer_ds(ixp1,ixp2,3,ibatch)=layer_ds(ixp1,ixp2,3,ibatch)+jvds
4235 enddo
4236 enddo
4237 enddo
4238 enddo
4239 case(3)
4240 ix3=ixomin3+rell/rft
4241 do ix1=ixomin1,ixomax1
4242 ixpmin1=(node(pig1_,igrid)-1)*rft*block_nx1+(ix1-ixomin1)*rft+1
4243 do ix2=ixomin2,ixomax2
4244 ixpmin2=(node(pig2_,igrid)-1)*rft*block_nx2+(ix2-ixomin2)*rft+1
4245 ds_cm=ps(igrid)%dx(ix^d,3)*unit_length/dble(rft)
4246 if (si_unit) ds_cm=ds_cm*1.d2
4247 jds=cache(iigrid)%source(ix^d)*ds_cm
4248 kds=cache(iigrid)%opacity(ix^d)*ds_cm
4249 jvds=cache(iigrid)%sourcev(ix^d)*ds_cm
4250 do isub1=0,rft-1
4251 ixp1=ixpmin1+isub1
4252 do isub2=0,rft-1
4253 ixp2=ixpmin2+isub2
4254 layer_ds(ixp1,ixp2,1,ibatch)=layer_ds(ixp1,ixp2,1,ibatch)+jds
4255 layer_ds(ixp1,ixp2,2,ibatch)=layer_ds(ixp1,ixp2,2,ibatch)+kds
4256 layer_ds(ixp1,ixp2,3,ibatch)=layer_ds(ixp1,ixp2,3,ibatch)+jvds
4257 enddo
4258 enddo
4259 enddo
4260 enddo
4261 end select
4262 enddo
4263 enddo
4264
4265 numseg=nlayerseg*nbatch
4266 call mpi_allreduce(layer_ds,layer_all,numseg,mpi_double_precision,mpi_sum,icomm,ierrmpi)
4267
4268 do ibatch=1,nbatch
4269 !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(atten) SCHEDULE(static)
4270 do ixp1=1,nxif1
4271 do ixp2=1,nxif2
4272 euvthin(ixp1,ixp2)=euvthin(ixp1,ixp2)+layer_all(ixp1,ixp2,1,ibatch)
4273 atten=transfer_attenuation(tau(ixp1,ixp2))
4274 euv(ixp1,ixp2)=euv(ixp1,ixp2)+atten*layer_all(ixp1,ixp2,1,ibatch)
4275 dpl(ixp1,ixp2)=dpl(ixp1,ixp2)+atten*layer_all(ixp1,ixp2,3,ibatch)
4276 tau(ixp1,ixp2)=tau(ixp1,ixp2)+layer_all(ixp1,ixp2,2,ibatch)
4277 enddo
4278 enddo
4279 !$OMP END PARALLEL DO
4280 enddo
4281 enddo
4282
4283 do iigrid=1,igridstail
4284 if (allocated(cache(iigrid)%source)) deallocate(cache(iigrid)%source)
4285 if (allocated(cache(iigrid)%opacity)) deallocate(cache(iigrid)%opacity)
4286 if (allocated(cache(iigrid)%sourcev)) deallocate(cache(iigrid)%sourcev)
4287 enddo
4288 deallocate(cache,layer_ds,layer_all)
4289
4290 end subroutine integrate_euv_thick_datresol
4291
4292 }
4293
4294 {^ifthreed
4295
4296 subroutine build_sph_intersection_faces(ixI^L,ixO^L,x,dx,rface,thetaface,phiface)
4297 integer, intent(in) :: ixI^L, ixO^L
4298 double precision, intent(in) :: x(ixI^S,1:ndim),dx(ixI^S,1:ndim)
4299 double precision, allocatable, intent(out) :: rface(:),thetaface(:),phiface(:)
4300 integer :: ix1,ix2,ix3
4301
4302 allocate(rface(ixomin1:ixomax1+1),thetaface(ixomin2:ixomax2+1),phiface(ixomin3:ixomax3+1))
4303 do ix1=ixomin1,ixomax1
4304 rface(ix1)=x(ix1,ixomin2,ixomin3,1)-half*dx(ix1,ixomin2,ixomin3,1)
4305 enddo
4306 rface(ixomax1+1)=x(ixomax1,ixomin2,ixomin3,1)+half*dx(ixomax1,ixomin2,ixomin3,1)
4307 do ix2=ixomin2,ixomax2
4308 thetaface(ix2)=x(ixomin1,ix2,ixomin3,2)-half*dx(ixomin1,ix2,ixomin3,2)
4309 enddo
4310 thetaface(ixomax2+1)=x(ixomin1,ixomax2,ixomin3,2)+half*dx(ixomin1,ixomax2,ixomin3,2)
4311 do ix3=ixomin3,ixomax3
4312 phiface(ix3)=x(ixomin1,ixomin2,ix3,3)-half*dx(ixomin1,ixomin2,ix3,3)
4313 enddo
4314 phiface(ixomax3+1)=x(ixomin1,ixomin2,ixomax3,3)+half*dx(ixomin1,ixomin2,ixomax3,3)
4315 end subroutine build_sph_intersection_faces
4316
4317 subroutine sph_add_t(tvals,nt,capacity,t)
4318 double precision, allocatable, intent(inout) :: tvals(:)
4319 integer, intent(inout) :: nt,capacity
4320 double precision, intent(in) :: t
4321
4322 double precision, allocatable :: tmp(:)
4323
4324 if (t /= t .or. abs(t)>1.d90) return
4325 if (.not. allocated(tvals)) then
4326 capacity=64
4327 allocate(tvals(capacity))
4328 else if (nt>=capacity) then
4329 allocate(tmp(capacity))
4330 tmp=tvals
4331 deallocate(tvals)
4332 allocate(tvals(2*capacity))
4333 tvals(1:capacity)=tmp
4334 deallocate(tmp)
4335 capacity=2*capacity
4336 endif
4337 nt=nt+1
4338 tvals(nt)=t
4339 end subroutine sph_add_t
4340
4341 subroutine sph_add_t_fixed(tvals,nt,t)
4342 double precision, intent(inout) :: tvals(:)
4343 integer, intent(inout) :: nt
4344 double precision, intent(in) :: t
4345
4346 if (t /= t .or. abs(t)>1.d90) return
4347 if (nt>=size(tvals)) return
4348 nt=nt+1
4349 tvals(nt)=t
4350 end subroutine sph_add_t_fixed
4351
4352 subroutine sph_sort_unique_t(tvals,nt)
4353 double precision, intent(inout) :: tvals(:)
4354 integer, intent(inout) :: nt
4355
4356 integer :: i,j,nout
4357 double precision :: key,epsT
4358
4359 if (nt<=1) return
4360 do i=2,nt
4361 key=tvals(i)
4362 j=i-1
4363 do while (j>=1 .and. tvals(j)>key)
4364 tvals(j+1)=tvals(j)
4365 j=j-1
4366 enddo
4367 tvals(j+1)=key
4368 enddo
4369 epst=max(1.d-12,1.d-10*max(one,abs(tvals(nt)-tvals(1))))
4370 nout=1
4371 do i=2,nt
4372 if (abs(tvals(i)-tvals(nout))>epst) then
4373 nout=nout+1
4374 tvals(nout)=tvals(i)
4375 endif
4376 enddo
4377 nt=nout
4378 end subroutine sph_sort_unique_t
4379
4380 subroutine sph_add_sphere_intersections(ray_origin,ray_dir,rface,tvals,nt,capacity)
4381 double precision, intent(in) :: ray_origin(1:3),ray_dir(1:3),rface
4382 double precision, allocatable, intent(inout) :: tvals(:)
4383 integer, intent(inout) :: nt,capacity
4384
4385 double precision :: aa,bb,cc,disc,root
4386
4387 aa=sum(ray_dir**2)
4388 bb=2.d0*sum(ray_origin*ray_dir)
4389 cc=sum(ray_origin**2)-rface**2
4390 disc=bb**2-4.d0*aa*cc
4391 if (disc<zero) return
4392 root=sqrt(max(zero,disc))
4393 call sph_add_t(tvals,nt,capacity,(-bb-root)/(2.d0*aa))
4394 call sph_add_t(tvals,nt,capacity,(-bb+root)/(2.d0*aa))
4395 end subroutine sph_add_sphere_intersections
4396
4397 subroutine sph_add_theta_intersections(ray_origin,ray_dir,thetaface,tvals,nt,capacity)
4398 double precision, intent(in) :: ray_origin(1:3),ray_dir(1:3),thetaface
4399 double precision, allocatable, intent(inout) :: tvals(:)
4400 integer, intent(inout) :: nt,capacity
4401
4402 double precision :: cth,aa,bb,cc,disc,root
4403
4404 cth=cos(thetaface)
4405 aa=ray_dir(3)**2-cth**2*sum(ray_dir**2)
4406 bb=2.d0*(ray_origin(3)*ray_dir(3)-cth**2*sum(ray_origin*ray_dir))
4407 cc=ray_origin(3)**2-cth**2*sum(ray_origin**2)
4408 if (abs(aa)<1.d-14) then
4409 if (abs(bb)>1.d-14) call sph_add_t(tvals,nt,capacity,-cc/bb)
4410 return
4411 endif
4412 disc=bb**2-4.d0*aa*cc
4413 if (disc<zero) return
4414 root=sqrt(max(zero,disc))
4415 call sph_add_t(tvals,nt,capacity,(-bb-root)/(2.d0*aa))
4416 call sph_add_t(tvals,nt,capacity,(-bb+root)/(2.d0*aa))
4417 end subroutine sph_add_theta_intersections
4418
4419 subroutine sph_add_phi_intersection(ray_origin,ray_dir,phiface,tvals,nt,capacity)
4420 double precision, intent(in) :: ray_origin(1:3),ray_dir(1:3),phiface
4421 double precision, allocatable, intent(inout) :: tvals(:)
4422 integer, intent(inout) :: nt,capacity
4423
4424 double precision :: normal(1:3),denom,numer
4425
4426 normal(1)=-sin(phiface)
4427 normal(2)=cos(phiface)
4428 normal(3)=zero
4429 denom=sum(normal*ray_dir)
4430 if (abs(denom)<1.d-14) return
4431 numer=sum(normal*ray_origin)
4432 call sph_add_t(tvals,nt,capacity,-numer/denom)
4433 end subroutine sph_add_phi_intersection
4434
4435 subroutine sph_cart_to_coord(pos,sph)
4436 double precision, intent(in) :: pos(1:3)
4437 double precision, intent(out) :: sph(1:3)
4438
4439 sph(1)=sqrt(sum(pos**2))
4440 if (sph(1)>zero) then
4441 sph(2)=acos(max(-one,min(one,pos(3)/sph(1))))
4442 else
4443 sph(2)=zero
4444 endif
4445 sph(3)=atan2(pos(2),pos(1))
4446 end subroutine sph_cart_to_coord
4447
4448 integer function sph_locate_index(value,faces,imin,imax) result(idx)
4449 integer, intent(in) :: imin,imax
4450 double precision, intent(in) :: value,faces(imin:imax+1)
4451
4452 integer :: ilo,ihi,imid
4453
4454 idx=0
4455 if (value<faces(imin)-1.d-12 .or. value>faces(imax+1)+1.d-12) return
4456 if (value<=faces(imin)) then
4457 idx=imin
4458 return
4459 endif
4460 if (value>=faces(imax+1)) then
4461 idx=imax
4462 return
4463 endif
4464
4465 ilo=imin
4466 ihi=imax+1
4467 do while (ihi-ilo>1)
4468 imid=(ilo+ihi)/2
4469 if (value>=faces(imid)) then
4470 ilo=imid
4471 else
4472 ihi=imid
4473 endif
4474 enddo
4475 idx=min(imax,max(imin,ilo))
4476 end function sph_locate_index
4477
4478 integer function sph_locate_index_desc(value,faces,imin,imax) result(idx)
4479 integer, intent(in) :: imin,imax
4480 double precision, intent(in) :: value,faces(imin:imax+1)
4481
4482 integer :: ilo,ihi,imid
4483
4484 idx=0
4485 if (value>faces(imin)+1.d-12 .or. value<faces(imax+1)-1.d-12) return
4486 if (value>=faces(imin)) then
4487 idx=imin
4488 return
4489 endif
4490 if (value<=faces(imax+1)) then
4491 idx=imax
4492 return
4493 endif
4494
4495 ilo=imin
4496 ihi=imax+1
4497 do while (ihi-ilo>1)
4498 imid=(ilo+ihi)/2
4499 if (value<=faces(imid)) then
4500 ilo=imid
4501 else
4502 ihi=imid
4503 endif
4504 enddo
4505 idx=min(imax,max(imin,ilo))
4506 end function sph_locate_index_desc
4507
4508 subroutine sph_locate_cell(pos,rface,thetaface,phiface,ixO^L,ix1,ix2,ix3,inside)
4509 double precision, intent(in) :: pos(1:3)
4510 double precision, intent(in) :: rface(ixOmin1:ixOmax1+1),thetaface(ixOmin2:ixOmax2+1),&
4511 phiface(ixOmin3:ixOmax3+1)
4512 integer, intent(in) :: ixO^L
4513 integer, intent(out) :: ix1,ix2,ix3
4514 logical, intent(out) :: inside
4515
4516 double precision :: sph(1:3),phi
4517
4518 call sph_cart_to_coord(pos,sph)
4519 phi=sph(3)
4520 if (phi<phiface(ixomin3)-1.d-12) phi=phi+2.d0*dpi
4521 if (phi>phiface(ixomax3+1)+1.d-12) phi=phi-2.d0*dpi
4522 ix1=sph_locate_index(sph(1),rface,ixomin1,ixomax1)
4523 ix2=sph_locate_index(sph(2),thetaface,ixomin2,ixomax2)
4524 ix3=sph_locate_index(phi,phiface,ixomin3,ixomax3)
4525 inside=ix1>0 .and. ix2>0 .and. ix3>0
4526 end subroutine sph_locate_cell
4527
4528 logical function sph_segment_visible(pos,ximg1,ximg2) result(visible)
4529 use mod_constants
4530 double precision, intent(in) :: pos(1:3),ximg1,ximg2
4531
4532 double precision :: dotp,rc,rthick,rloc
4533
4534 rthick=r_opt_thick*const_rsun/unit_length
4535 rc=sqrt(ximg1**2+ximg2**2)
4536 rloc=sqrt(sum(pos**2))
4537 call dot_product_loc(vec_los,pos,dotp)
4538 visible=.true.
4539 if (dotp>=zero) then
4540 if (rc<=rthick) visible=.false.
4541 else
4542 if (rloc<=rthick) visible=.false.
4543 endif
4544 end function sph_segment_visible
4545
4546 subroutine sph_block_pixel_range(rface,thetaface,phiface,ixO^L,nXI1,nXI2,xI1,xI2,dxI,&
4547 ixPmin1,ixPmax1,ixPmin2,ixPmax2,has_pixels)
4548 double precision, intent(in) :: rface(ixOmin1:ixOmax1+1),thetaface(ixOmin2:ixOmax2+1),&
4549 phiface(ixOmin3:ixOmax3+1)
4550 integer, intent(in) :: ixO^L,nXI1,nXI2
4551 double precision, intent(in) :: xI1(nXI1),xI2(nXI2),dxI
4552 integer, intent(out) :: ixPmin1,ixPmax1,ixPmin2,ixPmax2
4553 logical, intent(out) :: has_pixels
4554
4555 integer, parameter :: nsample=5
4556 integer :: ir,it,ip
4557 double precision :: sph(1:3),xcent(1:2)
4558 double precision :: xmin1,xmax1,xmin2,xmax2
4559 double precision :: wr,wt,wp,pad
4560
4561 has_pixels=.false.
4562 xmin1=huge(one)
4563 xmax1=-huge(one)
4564 xmin2=huge(one)
4565 xmax2=-huge(one)
4566 do ir=0,nsample-1
4567 wr=dble(ir)/dble(nsample-1)
4568 sph(1)=(one-wr)*rface(ixomin1)+wr*rface(ixomax1+1)
4569 do it=0,nsample-1
4570 wt=dble(it)/dble(nsample-1)
4571 sph(2)=(one-wt)*thetaface(ixomin2)+wt*thetaface(ixomax2+1)
4572 do ip=0,nsample-1
4573 wp=dble(ip)/dble(nsample-1)
4574 if (ir/=0 .and. ir/=nsample-1 .and. it/=0 .and. it/=nsample-1 .and. &
4575 ip/=0 .and. ip/=nsample-1) cycle
4576 sph(3)=(one-wp)*phiface(ixomin3)+wp*phiface(ixomax3+1)
4577 call get_cor_image_spherical(sph,xcent)
4578 xmin1=min(xmin1,xcent(1))
4579 xmax1=max(xmax1,xcent(1))
4580 xmin2=min(xmin2,xcent(2))
4581 xmax2=max(xmax2,xcent(2))
4582 enddo
4583 enddo
4584 enddo
4585 pad=2.d0*dxi
4586 xmin1=xmin1-pad
4587 xmax1=xmax1+pad
4588 xmin2=xmin2-pad
4589 xmax2=xmax2+pad
4590 ixpmin1=max(1,floor((xmin1-(xi1(1)-half*dxi))/dxi)+1)
4591 ixpmax1=min(nxi1,ceiling((xmax1-(xi1(1)-half*dxi))/dxi))
4592 ixpmin2=max(1,floor((xmin2-(xi2(1)-half*dxi))/dxi)+1)
4593 ixpmax2=min(nxi2,ceiling((xmax2-(xi2(1)-half*dxi))/dxi))
4594 has_pixels=ixpmin1<=ixpmax1 .and. ixpmin2<=ixpmax2
4595 end subroutine sph_block_pixel_range
4596
4597 subroutine acc_euv_sph_intersection(ixI^L,ixO^L,source,ray_origin,ximg1,ximg2,&
4598 rface,thetaface,phiface,EUVp)
4599 integer, intent(in) :: ixI^L,ixO^L
4600 double precision, intent(in) :: source(ixI^S),ray_origin(1:3),ximg1,ximg2
4601 double precision, intent(in) :: rface(ixOmin1:ixOmax1+1),thetaface(ixOmin2:ixOmax2+1),&
4602 phiface(ixOmin3:ixOmax3+1)
4603 double precision, intent(inout) :: EUVp
4604
4605 integer :: nt,capacity,i,ix^D
4606 double precision, allocatable :: tvals(:)
4607 double precision :: posMid(1:3),ds_cm,tMid,t0,t1
4608 logical :: inside
4609
4610 nt=0
4611 capacity=0
4612 do ix1=ixomin1,ixomax1+1
4613 call sph_add_sphere_intersections(ray_origin,vec_los,rface(ix1),tvals,nt,capacity)
4614 enddo
4615 do ix2=ixomin2,ixomax2+1
4616 call sph_add_theta_intersections(ray_origin,vec_los,thetaface(ix2),tvals,nt,capacity)
4617 enddo
4618 do ix3=ixomin3,ixomax3+1
4619 call sph_add_phi_intersection(ray_origin,vec_los,phiface(ix3),tvals,nt,capacity)
4620 enddo
4621 if (nt<2) then
4622 if (allocated(tvals)) deallocate(tvals)
4623 return
4624 endif
4625 call sph_sort_unique_t(tvals,nt)
4626
4627 do i=1,nt-1
4628 t0=tvals(i)
4629 t1=tvals(i+1)
4630 if (t1<=t0) cycle
4631 tmid=half*(t0+t1)
4632 posmid=ray_origin+tmid*vec_los
4633 if (.not. sph_segment_visible(posmid,ximg1,ximg2)) cycle
4634 call sph_locate_cell(posmid,rface,thetaface,phiface,ixo^l,ix1,ix2,ix3,inside)
4635 if (.not. inside) cycle
4636 ds_cm=(t1-t0)*unit_length
4637 if (si_unit) ds_cm=ds_cm*1.d2
4638 euvp=euvp+source(ix^d)*ds_cm
4639 enddo
4640 deallocate(tvals)
4641 end subroutine acc_euv_sph_intersection
4642
4643 subroutine collect_euv_sph_intersection_segments(ixI^L,ixO^L,source,opacity,&
4644 pixel_id,ray_origin,ximg1,ximg2,&
4645 rface,thetaface,phiface,rface2,&
4646 theta_cos,phi_sin,phi_cos,&
4647 segments,nseg,capacity)
4648 use mod_constants, only: const_rsun
4649
4650 integer, intent(in) :: ixI^L,ixO^L,pixel_id
4651 double precision, intent(in) :: source(ixI^S),opacity(ixI^S)
4652 double precision, intent(in) :: ray_origin(1:3),ximg1,ximg2
4653 double precision, intent(in) :: rface(ixOmin1:ixOmax1+1),thetaface(ixOmin2:ixOmax2+1),&
4654 phiface(ixOmin3:ixOmax3+1)
4655 double precision, intent(in) :: rface2(ixOmin1:ixOmax1+1),theta_cos(ixOmin2:ixOmax2+1),&
4656 phi_sin(ixOmin3:ixOmax3+1),phi_cos(ixOmin3:ixOmax3+1)
4657 double precision, allocatable, intent(inout) :: segments(:,:)
4658 integer, intent(inout) :: nseg,capacity
4659
4660 integer :: nt,i,ix^D
4661 double precision :: tvals(2*(ixOmax1-ixOmin1+2)+2*(ixOmax2-ixOmin2+2)+&
4662 (ixOmax3-ixOmin3+2))
4663 double precision :: posMid(1:3),ds_cm,tMid,t0,t1,jds,kds
4664 double precision :: dir2,origin2,odotd,aa,bb,cc,disc,root,cth2
4665 double precision :: denom,numer,r2,mu,phi,dotp,rthick2,rc2
4666 logical :: inside
4667
4668 nt=0
4669 dir2=sum(vec_los**2)
4670 origin2=sum(ray_origin**2)
4671 odotd=sum(ray_origin*vec_los)
4672 rthick2=(r_opt_thick*const_rsun/unit_length)**2
4673 rc2=ximg1**2+ximg2**2
4674
4675 do ix1=ixomin1,ixomax1+1
4676 aa=dir2
4677 bb=2.d0*odotd
4678 cc=origin2-rface2(ix1)
4679 disc=bb**2-4.d0*aa*cc
4680 if (disc>=zero) then
4681 root=sqrt(max(zero,disc))
4682 call sph_add_t_fixed(tvals,nt,(-bb-root)/(2.d0*aa))
4683 call sph_add_t_fixed(tvals,nt,(-bb+root)/(2.d0*aa))
4684 endif
4685 enddo
4686 do ix2=ixomin2,ixomax2+1
4687 cth2=theta_cos(ix2)**2
4688 aa=vec_los(3)**2-cth2*dir2
4689 bb=2.d0*(ray_origin(3)*vec_los(3)-cth2*odotd)
4690 cc=ray_origin(3)**2-cth2*origin2
4691 if (abs(aa)<1.d-14) then
4692 if (abs(bb)>1.d-14) call sph_add_t_fixed(tvals,nt,-cc/bb)
4693 else
4694 disc=bb**2-4.d0*aa*cc
4695 if (disc>=zero) then
4696 root=sqrt(max(zero,disc))
4697 call sph_add_t_fixed(tvals,nt,(-bb-root)/(2.d0*aa))
4698 call sph_add_t_fixed(tvals,nt,(-bb+root)/(2.d0*aa))
4699 endif
4700 endif
4701 enddo
4702 do ix3=ixomin3,ixomax3+1
4703 denom=-phi_sin(ix3)*vec_los(1)+phi_cos(ix3)*vec_los(2)
4704 if (abs(denom)>=1.d-14) then
4705 numer=-phi_sin(ix3)*ray_origin(1)+phi_cos(ix3)*ray_origin(2)
4706 call sph_add_t_fixed(tvals,nt,-numer/denom)
4707 endif
4708 enddo
4709 if (nt<2) return
4710 call sph_sort_unique_t(tvals,nt)
4711
4712 do i=1,nt-1
4713 t0=tvals(i)
4714 t1=tvals(i+1)
4715 if (t1<=t0) cycle
4716 tmid=half*(t0+t1)
4717 posmid=ray_origin+tmid*vec_los
4718 r2=sum(posmid**2)
4719 dotp=sum(vec_los*posmid)
4720 if (dotp>=zero) then
4721 if (rc2<=rthick2) cycle
4722 else
4723 if (r2<=rthick2) cycle
4724 endif
4725
4726 ix1=sph_locate_index(r2,rface2,ixomin1,ixomax1)
4727 if (r2>zero) then
4728 mu=posmid(3)/sqrt(r2)
4729 else
4730 mu=one
4731 endif
4732 ix2=sph_locate_index_desc(mu,theta_cos,ixomin2,ixomax2)
4733 phi=atan2(posmid(2),posmid(1))
4734 if (phi<phiface(ixomin3)-1.d-12) phi=phi+2.d0*dpi
4735 if (phi>phiface(ixomax3+1)+1.d-12) phi=phi-2.d0*dpi
4736 ix3=sph_locate_index(phi,phiface,ixomin3,ixomax3)
4737 inside=ix1>0 .and. ix2>0 .and. ix3>0
4738 if (.not. inside) cycle
4739 ds_cm=(t1-t0)*unit_length
4740 if (si_unit) ds_cm=ds_cm*1.d2
4741 jds=max(zero,source(ix^d))*ds_cm
4742 kds=max(zero,opacity(ix^d))*ds_cm
4743 call append_cart_dda_segment(segments,nseg,capacity,pixel_id,tmid,jds,kds,zero)
4744 enddo
4746
4747 subroutine sph_locate_cell_fast(pos,rface2,theta_cos,phiface,ixO^L,ix1,ix2,ix3,inside)
4748 double precision, intent(in) :: pos(1:3)
4749 double precision, intent(in) :: rface2(ixOmin1:ixOmax1+1),theta_cos(ixOmin2:ixOmax2+1),&
4750 phiface(ixOmin3:ixOmax3+1)
4751 integer, intent(in) :: ixO^L
4752 integer, intent(out) :: ix1,ix2,ix3
4753 logical, intent(out) :: inside
4754
4755 double precision :: r2,mu,phi
4756
4757 r2=sum(pos**2)
4758 ix1=sph_locate_index(r2,rface2,ixomin1,ixomax1)
4759 if (r2>zero) then
4760 mu=pos(3)/sqrt(r2)
4761 else
4762 mu=one
4763 endif
4764 ix2=sph_locate_index_desc(mu,theta_cos,ixomin2,ixomax2)
4765 phi=atan2(pos(2),pos(1))
4766 if (phi<phiface(ixomin3)-1.d-12) phi=phi+2.d0*dpi
4767 if (phi>phiface(ixomax3+1)+1.d-12) phi=phi-2.d0*dpi
4768 ix3=sph_locate_index(phi,phiface,ixomin3,ixomax3)
4769 inside=ix1>0 .and. ix2>0 .and. ix3>0
4770 end subroutine sph_locate_cell_fast
4771
4772 subroutine sph_try_exit_candidate(t,tNow,tExit,epsRay,tNext,found)
4773 double precision, intent(in) :: t,tNow,tExit,epsRay
4774 double precision, intent(inout) :: tNext
4775 logical, intent(inout) :: found
4776
4777 if (t>tnow+epsray .and. t<=texit+epsray .and. t<tnext) then
4778 tnext=t
4779 found=.true.
4780 endif
4781 end subroutine sph_try_exit_candidate
4782
4783 subroutine sph_try_theta_exit_candidate(t,theta_face_cos,ray_origin,tNow,tExit,epsRay,tNext,found)
4784 double precision, intent(in) :: t,theta_face_cos,ray_origin(1:3),tNow,tExit,epsRay
4785 double precision, intent(inout) :: tNext
4786 logical, intent(inout) :: found
4787
4788 double precision :: pos(1:3),r2
4789
4790 if (t<=tnow+epsray .or. t>texit+epsray .or. t>=tnext) return
4791 pos=ray_origin+t*vec_los
4792 r2=sum(pos**2)
4793 if (r2<=zero) return
4794 if (theta_face_cos>1.d-12 .and. pos(3)<-1.d-10) return
4795 if (theta_face_cos<-1.d-12 .and. pos(3)>1.d-10) return
4796 if (abs(pos(3)**2-theta_face_cos**2*r2)>1.d-6*max(one,r2)) return
4797 tnext=t
4798 found=.true.
4799 end subroutine sph_try_theta_exit_candidate
4800
4801 subroutine sph_try_phi_exit_candidate(t,phi_face_sin,phi_face_cos,ray_origin,tNow,tExit,epsRay,tNext,found)
4802 double precision, intent(in) :: t,phi_face_sin,phi_face_cos,ray_origin(1:3),tNow,tExit,epsRay
4803 double precision, intent(inout) :: tNext
4804 logical, intent(inout) :: found
4805
4806 double precision :: pos(1:3),radialDot
4807
4808 if (t<=tnow+epsray .or. t>texit+epsray .or. t>=tnext) return
4809 pos=ray_origin+t*vec_los
4810 radialdot=phi_face_cos*pos(1)+phi_face_sin*pos(2)
4811 if (radialdot<-1.d-10) return
4812 tnext=t
4813 found=.true.
4814 end subroutine sph_try_phi_exit_candidate
4815
4816 subroutine sph_next_cell_exit(ray_origin,rface2,theta_cos,phiface,phi_sin,phi_cos,ixO^L,&
4817 ix1,ix2,ix3,tNow,tExit,epsRay,tNext,found)
4818 double precision, intent(in) :: ray_origin(1:3)
4819 double precision, intent(in) :: rface2(ixOmin1:ixOmax1+1),theta_cos(ixOmin2:ixOmax2+1),&
4820 phiface(ixOmin3:ixOmax3+1)
4821 double precision, intent(in) :: phi_sin(ixOmin3:ixOmax3+1),phi_cos(ixOmin3:ixOmax3+1)
4822 integer, intent(in) :: ixO^L,ix1,ix2,ix3
4823 double precision, intent(in) :: tNow,tExit,epsRay
4824 double precision, intent(out) :: tNext
4825 logical, intent(out) :: found
4826
4827 integer :: iface
4828 double precision :: dir2,origin2,odotd,aa,bb,cc,disc,root,cth2,denom,numer
4829
4830 found=.false.
4831 tnext=huge(one)
4832 dir2=sum(vec_los**2)
4833 origin2=sum(ray_origin**2)
4834 odotd=sum(ray_origin*vec_los)
4835
4836 do iface=ix1,ix1+1
4837 aa=dir2
4838 bb=2.d0*odotd
4839 cc=origin2-rface2(iface)
4840 disc=bb**2-4.d0*aa*cc
4841 if (disc>=zero) then
4842 root=sqrt(max(zero,disc))
4843 call sph_try_exit_candidate((-bb-root)/(2.d0*aa),tnow,texit,epsray,tnext,found)
4844 call sph_try_exit_candidate((-bb+root)/(2.d0*aa),tnow,texit,epsray,tnext,found)
4845 endif
4846 enddo
4847
4848 do iface=ix2,ix2+1
4849 cth2=theta_cos(iface)**2
4850 aa=vec_los(3)**2-cth2*dir2
4851 bb=2.d0*(ray_origin(3)*vec_los(3)-cth2*odotd)
4852 cc=ray_origin(3)**2-cth2*origin2
4853 if (abs(aa)<1.d-14) then
4854 if (abs(bb)>1.d-14) call sph_try_theta_exit_candidate(-cc/bb,theta_cos(iface),&
4855 ray_origin,tnow,texit,epsray,tnext,found)
4856 else
4857 disc=bb**2-4.d0*aa*cc
4858 if (disc>=zero) then
4859 root=sqrt(max(zero,disc))
4860 call sph_try_theta_exit_candidate((-bb-root)/(2.d0*aa),theta_cos(iface),&
4861 ray_origin,tnow,texit,epsray,tnext,found)
4862 call sph_try_theta_exit_candidate((-bb+root)/(2.d0*aa),theta_cos(iface),&
4863 ray_origin,tnow,texit,epsray,tnext,found)
4864 endif
4865 endif
4866 enddo
4867
4868 do iface=ix3,ix3+1
4869 denom=-phi_sin(iface)*vec_los(1)+phi_cos(iface)*vec_los(2)
4870 if (abs(denom)>=1.d-14) then
4871 numer=-phi_sin(iface)*ray_origin(1)+phi_cos(iface)*ray_origin(2)
4872 call sph_try_phi_exit_candidate(-numer/denom,phi_sin(iface),phi_cos(iface),ray_origin,&
4873 tnow,texit,epsray,tnext,found)
4874 endif
4875 enddo
4876 end subroutine sph_next_cell_exit
4877
4878 subroutine collect_euv_sph_dda_interval(ixI^L,ixO^L,source,opacity,pixel_id,&
4879 ray_origin,ximg1,ximg2,rface2,theta_cos,phiface,&
4880 phi_sin,phi_cos,&
4881 t_enter,t_exit,segments,nseg,capacity,ok)
4882 use mod_constants, only: const_rsun
4883
4884 integer, intent(in) :: ixI^L,ixO^L,pixel_id
4885 double precision, intent(in) :: source(ixI^S),opacity(ixI^S)
4886 double precision, intent(in) :: ray_origin(1:3),ximg1,ximg2
4887 double precision, intent(in) :: rface2(ixOmin1:ixOmax1+1),theta_cos(ixOmin2:ixOmax2+1),&
4888 phiface(ixOmin3:ixOmax3+1)
4889 double precision, intent(in) :: phi_sin(ixOmin3:ixOmax3+1),phi_cos(ixOmin3:ixOmax3+1)
4890 double precision, intent(in) :: t_enter,t_exit
4891 double precision, allocatable, intent(inout) :: segments(:,:)
4892 integer, intent(inout) :: nseg,capacity
4893 logical, intent(out) :: ok
4894
4895 integer :: ix^D,nstep,maxSteps
4896 double precision :: tNow,tNext,tEnd,tMid,epsRay,ds_cm,jds,kds
4897 double precision :: pos(1:3),r2,dotp,rthick2,rc2
4898 logical :: inside,found
4899
4900 ok=.true.
4901 if (t_exit<=t_enter) return
4902 epsray=max(1.d-12,1.d-10*max(one,abs(t_exit-t_enter)))
4903 pos=ray_origin+(t_enter+epsray)*vec_los
4904 call sph_locate_cell_fast(pos,rface2,theta_cos,phiface,ixo^l,ix1,ix2,ix3,inside)
4905 if (.not. inside) then
4906 ok=.false.
4907 return
4908 endif
4909
4910 rthick2=(r_opt_thick*const_rsun/unit_length)**2
4911 rc2=ximg1**2+ximg2**2
4912 tnow=t_enter
4913 nstep=0
4914 maxsteps=8*((ixomax1-ixomin1+1)+(ixomax2-ixomin2+1)+(ixomax3-ixomin3+1)+3)
4915
4916 do while (tnow<t_exit-epsray)
4917 call sph_next_cell_exit(ray_origin,rface2,theta_cos,phiface,phi_sin,phi_cos,ixo^l,&
4918 ix1,ix2,ix3,tnow,t_exit,epsray,tnext,found)
4919 if (.not. found) then
4920 ok=.false.
4921 return
4922 endif
4923 tend=min(tnext,t_exit)
4924 if (tend>tnow) then
4925 tmid=half*(tnow+tend)
4926 pos=ray_origin+tmid*vec_los
4927 r2=sum(pos**2)
4928 dotp=sum(vec_los*pos)
4929 if (.not. ((dotp>=zero .and. rc2<=rthick2) .or. &
4930 (dotp<zero .and. r2<=rthick2))) then
4931 ds_cm=(tend-tnow)*unit_length
4932 if (si_unit) ds_cm=ds_cm*1.d2
4933 jds=max(zero,source(ix^d))*ds_cm
4934 kds=max(zero,opacity(ix^d))*ds_cm
4935 call append_cart_dda_segment(segments,nseg,capacity,pixel_id,tmid,jds,kds,zero)
4936 endif
4937 endif
4938 tnow=tend
4939 if (tnow>=t_exit-epsray) exit
4940 pos=ray_origin+(tnow+epsray)*vec_los
4941 call sph_locate_cell_fast(pos,rface2,theta_cos,phiface,ixo^l,ix1,ix2,ix3,inside)
4942 if (.not. inside) then
4943 ok=.false.
4944 return
4945 endif
4946 nstep=nstep+1
4947 if (nstep>maxsteps) then
4948 ok=.false.
4949 return
4950 endif
4951 enddo
4952 end subroutine collect_euv_sph_dda_interval
4953
4954 subroutine collect_euv_sph_dda_segments(ixI^L,ixO^L,source,opacity,&
4955 pixel_id,ray_origin,ximg1,ximg2,&
4956 rface,thetaface,phiface,rface2,&
4957 theta_cos,phi_sin,phi_cos,&
4958 segments,nseg,capacity,fallback)
4959 integer, intent(in) :: ixI^L,ixO^L,pixel_id
4960 double precision, intent(in) :: source(ixI^S),opacity(ixI^S)
4961 double precision, intent(in) :: ray_origin(1:3),ximg1,ximg2
4962 double precision, intent(in) :: rface(ixOmin1:ixOmax1+1),thetaface(ixOmin2:ixOmax2+1),&
4963 phiface(ixOmin3:ixOmax3+1)
4964 double precision, intent(in) :: rface2(ixOmin1:ixOmax1+1),theta_cos(ixOmin2:ixOmax2+1),&
4965 phi_sin(ixOmin3:ixOmax3+1),phi_cos(ixOmin3:ixOmax3+1)
4966 double precision, allocatable, intent(inout) :: segments(:,:)
4967 integer, intent(inout) :: nseg,capacity
4968 logical, intent(out) :: fallback
4969
4970 integer :: nt,i,nsegStart,ix^D
4971 double precision :: tvals(12),posMid(1:3),t0,t1,tMid
4972 double precision :: dir2,origin2,odotd,aa,bb,cc,disc,root,cth2,denom,numer
4973 logical :: inside,ok
4974
4975 fallback=.false.
4976 nsegstart=nseg
4977 nt=0
4978 dir2=sum(vec_los**2)
4979 origin2=sum(ray_origin**2)
4980 odotd=sum(ray_origin*vec_los)
4981
4982 do ix1=ixomin1,ixomax1+1,ixomax1-ixomin1+1
4983 aa=dir2
4984 bb=2.d0*odotd
4985 cc=origin2-rface2(ix1)
4986 disc=bb**2-4.d0*aa*cc
4987 if (disc>=zero) then
4988 root=sqrt(max(zero,disc))
4989 call sph_add_t_fixed(tvals,nt,(-bb-root)/(2.d0*aa))
4990 call sph_add_t_fixed(tvals,nt,(-bb+root)/(2.d0*aa))
4991 endif
4992 enddo
4993 do ix2=ixomin2,ixomax2+1,ixomax2-ixomin2+1
4994 cth2=theta_cos(ix2)**2
4995 aa=vec_los(3)**2-cth2*dir2
4996 bb=2.d0*(ray_origin(3)*vec_los(3)-cth2*odotd)
4997 cc=ray_origin(3)**2-cth2*origin2
4998 if (abs(aa)<1.d-14) then
4999 if (abs(bb)>1.d-14) call sph_add_t_fixed(tvals,nt,-cc/bb)
5000 else
5001 disc=bb**2-4.d0*aa*cc
5002 if (disc>=zero) then
5003 root=sqrt(max(zero,disc))
5004 call sph_add_t_fixed(tvals,nt,(-bb-root)/(2.d0*aa))
5005 call sph_add_t_fixed(tvals,nt,(-bb+root)/(2.d0*aa))
5006 endif
5007 endif
5008 enddo
5009 do ix3=ixomin3,ixomax3+1,ixomax3-ixomin3+1
5010 denom=-phi_sin(ix3)*vec_los(1)+phi_cos(ix3)*vec_los(2)
5011 if (abs(denom)>=1.d-14) then
5012 numer=-phi_sin(ix3)*ray_origin(1)+phi_cos(ix3)*ray_origin(2)
5013 call sph_add_t_fixed(tvals,nt,-numer/denom)
5014 endif
5015 enddo
5016
5017 if (nt<2) return
5018 call sph_sort_unique_t(tvals,nt)
5019
5020 do i=1,nt-1
5021 t0=tvals(i)
5022 t1=tvals(i+1)
5023 if (t1<=t0) cycle
5024 tmid=half*(t0+t1)
5025 posmid=ray_origin+tmid*vec_los
5026 call sph_locate_cell_fast(posmid,rface2,theta_cos,phiface,ixo^l,ix1,ix2,ix3,inside)
5027 if (.not. inside) cycle
5028 call collect_euv_sph_dda_interval(ixi^l,ixo^l,source,opacity,pixel_id,&
5029 ray_origin,ximg1,ximg2,rface2,theta_cos,phiface,phi_sin,phi_cos,&
5030 t0,t1,segments,nseg,capacity,ok)
5031 if (.not. ok) then
5032 nseg=nsegstart
5033 fallback=.true.
5034 call collect_euv_sph_intersection_segments(ixi^l,ixo^l,source,opacity,&
5035 pixel_id,ray_origin,ximg1,ximg2,rface,thetaface,phiface,rface2,&
5036 theta_cos,phi_sin,phi_cos,segments,nseg,capacity)
5037 return
5038 endif
5039 enddo
5040
5041 end subroutine collect_euv_sph_dda_segments
5042
5043 subroutine integrate_euv_sph_intersection_thin(numXI1,numXI2,xI1,xI2,dxI,fl,EM)
5045
5046 integer, intent(in) :: numXI1,numXI2
5047 double precision, intent(in) :: xI1(numXI1),xI2(numXI2),dxI
5048 type(te_fluid), intent(in) :: fl
5049 double precision, intent(inout) :: EM(numXI1,numXI2)
5050
5051 integer :: ixO^L,ixI^L,ix^D
5052 integer :: iigrid,igrid,ixP1,ixP2,ixPmin1,ixPmax1,ixPmin2,ixPmax2
5053 integer :: iseg,nseg,capacity,sphDdaFallbackLocal,sphDdaFallbackGlobal
5054 double precision :: ray_origin(1:3),profile_local(3),profile_global(3)
5055 double precision, allocatable :: source(:^D&)
5056 double precision, allocatable :: rface(:),thetaface(:),phiface(:)
5057 double precision, allocatable :: rface2(:),theta_cos(:),phi_sin(:),phi_cos(:)
5058 double precision, allocatable :: segments(:,:)
5059 logical :: has_pixels,ddaFallback
5060
5061 profile_local=zero
5062 sphddafallbacklocal=0
5063 do iigrid=1,igridstail; igrid=igrids(iigrid);
5064 ^d&ixomin^d=ixmlo^d\
5065 ^d&ixomax^d=ixmhi^d\
5066 ^d&iximin^d=ixglo^d\
5067 ^d&iximax^d=ixghi^d\
5068
5069 allocate(source(ixi^s))
5070 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,source)
5071 source(ixo^s)=source(ixo^s)/instrument_resolution_factor**2
5072 call build_sph_intersection_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,rface,thetaface,phiface)
5073 if (sph_use_dda) then
5074 allocate(rface2(ixomin1:ixomax1+1),theta_cos(ixomin2:ixomax2+1),&
5075 phi_sin(ixomin3:ixomax3+1),phi_cos(ixomin3:ixomax3+1))
5076 rface2=rface**2
5077 theta_cos=cos(thetaface)
5078 phi_sin=sin(phiface)
5079 phi_cos=cos(phiface)
5080 endif
5081 call sph_block_pixel_range(rface,thetaface,phiface,ixo^l,numxi1,numxi2,xi1,xi2,dxi,&
5082 ixpmin1,ixpmax1,ixpmin2,ixpmax2,has_pixels)
5083 if (has_pixels) then
5084 if (sph_use_dda) capacity=0
5085 do ixp1=ixpmin1,ixpmax1
5086 do ixp2=ixpmin2,ixpmax2
5087 ray_origin=xi1(ixp1)*vec_xi1+xi2(ixp2)*vec_xi2
5088 profile_local(1)=profile_local(1)+one
5089 if (sph_use_dda) then
5090 nseg=0
5091 call collect_euv_sph_dda_segments(ixi^l,ixo^l,source,source,&
5092 1,ray_origin,xi1(ixp1),xi2(ixp2),rface,thetaface,phiface,&
5093 rface2,theta_cos,phi_sin,phi_cos,segments,nseg,capacity,ddafallback)
5094 if (ddafallback) sphddafallbacklocal=sphddafallbacklocal+1
5095 do iseg=1,nseg
5096 em(ixp1,ixp2)=em(ixp1,ixp2)+segments(3,iseg)
5097 enddo
5098 else
5099 call acc_euv_sph_intersection(ixi^l,ixo^l,source,ray_origin,xi1(ixp1),xi2(ixp2),&
5100 rface,thetaface,phiface,em(ixp1,ixp2))
5101 endif
5102 enddo
5103 enddo
5104 profile_local(2)=profile_local(2)+dble((ixpmax1-ixpmin1+1)*(ixpmax2-ixpmin2+1))
5105 endif
5106 if (allocated(segments)) deallocate(segments)
5107 profile_local(3)=profile_local(3)+one
5108 if (allocated(rface2)) deallocate(rface2)
5109 if (allocated(theta_cos)) deallocate(theta_cos)
5110 if (allocated(phi_sin)) deallocate(phi_sin)
5111 if (allocated(phi_cos)) deallocate(phi_cos)
5112 deallocate(source,rface,thetaface,phiface)
5113 enddo
5114 call mpi_allreduce(profile_local,profile_global,3,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5115 call mpi_allreduce(sphddafallbacklocal,sphddafallbackglobal,1,mpi_integer,mpi_sum,icomm,ierrmpi)
5116 if (radsyn_verbose .and. mype==0) then
5117 if (sph_use_dda) then
5118 write(*,'(a,3(es12.5,1x))') ' sph_dda thin profile rays pixels blocks: ',profile_global
5119 write(*,'(a,i0)') ' sph_dda thin fallback rays: ',sphddafallbackglobal
5120 else
5121 write(*,'(a,3(es12.5,1x))') ' sph_intersection thin profile rays pixels blocks: ',profile_global
5122 endif
5123 endif
5125
5126 subroutine integrate_euv_sph_intersection_thick(numXI1,numXI2,xI1,xI2,dxI,fl,EUV,Tau,EUVthin)
5128
5129 integer, intent(in) :: numXI1,numXI2
5130 double precision, intent(in) :: xI1(numXI1),xI2(numXI2),dxI
5131 type(te_fluid), intent(in) :: fl
5132 double precision, intent(out) :: EUV(numXI1,numXI2),Tau(numXI1,numXI2),EUVthin(numXI1,numXI2)
5133
5134 integer, parameter :: nSegVars=5
5135 integer :: ixO^L,ixI^L,ix^D
5136 integer :: iigrid,igrid,ixP1,ixP2,ipix,ipixStart,ipixEnd,nPixBatch,pixel_id
5137 integer :: nseg,capacity,totalCount,totalSeg,ipe,is,iseg,nidx,owner,isegDest,nsegBefore
5138 integer :: ixGlobal,iyGlobal,ixPmin1,ixPmax1,ixPmin2,ixPmax2,iFirst,iLast,iLocal
5139 integer :: nPixBatchTarget
5140 integer :: maxSegBatchTarget,maxSegCommTarget,maxNsegBatch,nPixTotal
5141 integer :: maxOwnerSegCount,maxOwnerSegCountLocal,segOffset,recvFill,totalRoundCount,totalRoundSeg
5142 integer :: sphDdaFallbackLocal,sphDdaFallbackGlobal
5143 integer, allocatable :: sendCounts(:),recvCounts(:),sendDispls(:),recvDispls(:)
5144 integer, allocatable :: roundSendCounts(:),roundRecvCounts(:)
5145 integer, allocatable :: roundSendDispls(:),roundRecvDispls(:)
5146 integer, allocatable :: ownerSegCounts(:),ownerOffsets(:),idx(:)
5147 integer, allocatable :: bucketCounts(:),bucketOffsets(:),bucketFill(:)
5148 double precision :: ray_origin(1:3),atten
5149 double precision :: profile_local(5),profile_global(5),profile_batch(5)
5150 double precision :: phys_max_local(2),phys_max_global(2)
5151 double precision :: phys_sum_local(2),phys_sum_global(2),phys_sum_batch(2)
5152 double precision, allocatable :: segments(:,:),segments_send(:,:),segments_recv(:,:)
5153 double precision, allocatable :: segments_recv_round(:,:)
5154 double precision, allocatable :: image_reduce(:,:)
5155 logical :: has_pixels,batchAccepted,batchReduced,ddaFallback
5156 type(radsyn_euv_cache), allocatable :: cache(:)
5157
5158 euv=zero
5159 tau=zero
5160 euvthin=zero
5161 profile_local=zero
5162 phys_max_local=zero
5163 phys_sum_local=zero
5164 sphddafallbacklocal=0
5165 allocate(sendcounts(0:npe-1),recvcounts(0:npe-1),senddispls(0:npe-1),recvdispls(0:npe-1))
5166 allocate(roundsendcounts(0:npe-1),roundrecvcounts(0:npe-1))
5167 allocate(roundsenddispls(0:npe-1),roundrecvdispls(0:npe-1))
5168 allocate(ownersegcounts(0:npe-1),owneroffsets(0:npe-1))
5169 allocate(cache(igridstail))
5170 call radsyn_get_segment_batch_limits(npixbatchtarget,maxsegbatchtarget,maxsegcommtarget)
5171 allocate(bucketcounts(npixbatchtarget),bucketoffsets(npixbatchtarget+1),&
5172 bucketfill(npixbatchtarget))
5173
5174 do iigrid=1,igridstail; igrid=igrids(iigrid);
5175 ^d&ixomin^d=ixmlo^d\
5176 ^d&ixomax^d=ixmhi^d\
5177 ^d&iximin^d=ixglo^d\
5178 ^d&iximax^d=ixghi^d\
5179
5180 cache(iigrid)%igrid=igrid
5181 allocate(cache(iigrid)%source(ixi^s),cache(iigrid)%opacity(ixi^s))
5182 cache(iigrid)%source=zero
5183 cache(iigrid)%opacity=zero
5184 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%source)
5185 cache(iigrid)%source(ixo^s)=cache(iigrid)%source(ixo^s)/instrument_resolution_factor**2
5186 call get_euv_hhe_opacity(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%opacity)
5187 phys_max_local(1)=max(phys_max_local(1),maxval(cache(iigrid)%source(ixo^s)))
5188 phys_max_local(2)=max(phys_max_local(2),maxval(cache(iigrid)%opacity(ixo^s)))
5189 call build_sph_intersection_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,&
5190 cache(iigrid)%rface,cache(iigrid)%thetaface,&
5191 cache(iigrid)%phiface)
5192 allocate(cache(iigrid)%rface2(ixomin1:ixomax1+1),&
5193 cache(iigrid)%theta_cos(ixomin2:ixomax2+1),&
5194 cache(iigrid)%phi_sin(ixomin3:ixomax3+1),&
5195 cache(iigrid)%phi_cos(ixomin3:ixomax3+1))
5196 cache(iigrid)%rface2=cache(iigrid)%rface**2
5197 cache(iigrid)%theta_cos=cos(cache(iigrid)%thetaface)
5198 cache(iigrid)%phi_sin=sin(cache(iigrid)%phiface)
5199 cache(iigrid)%phi_cos=cos(cache(iigrid)%phiface)
5200 call sph_block_pixel_range(cache(iigrid)%rface,cache(iigrid)%thetaface,&
5201 cache(iigrid)%phiface,ixo^l,numxi1,numxi2,xi1,xi2,dxi,&
5202 cache(iigrid)%ixPmin1,cache(iigrid)%ixPmax1,&
5203 cache(iigrid)%ixPmin2,cache(iigrid)%ixPmax2,cache(iigrid)%has_pixels)
5204 enddo
5205
5206 npixtotal=numxi1*numxi2
5207 ipixstart=1
5208 do while (ipixstart<=npixtotal)
5209 ipixend=min(numxi1*numxi2,ipixstart+npixbatchtarget-1)
5210 npixbatch=ipixend-ipixstart+1
5211 batchaccepted=.false.
5212 batchreduced=.false.
5213
5214 do while (.not. batchaccepted)
5215 nseg=0
5216 capacity=0
5217 profile_batch=zero
5218 phys_sum_batch=zero
5219
5220 do iigrid=1,igridstail; igrid=igrids(iigrid);
5221 ^d&ixomin^d=ixmlo^d\
5222 ^d&ixomax^d=ixmhi^d\
5223 ^d&iximin^d=ixglo^d\
5224 ^d&iximax^d=ixghi^d\
5225
5226 ixpmin1=cache(iigrid)%ixPmin1
5227 ixpmax1=cache(iigrid)%ixPmax1
5228 ixpmin2=cache(iigrid)%ixPmin2
5229 ixpmax2=cache(iigrid)%ixPmax2
5230 has_pixels=cache(iigrid)%has_pixels
5231 if (.not. has_pixels) cycle
5232
5233 do ixp2=ixpmin2,ixpmax2
5234 ifirst=max(ipixstart,(ixp2-1)*numxi1+ixpmin1)
5235 ilast=min(ipixend,(ixp2-1)*numxi1+ixpmax1)
5236 if (ifirst>ilast) cycle
5237 do ipix=ifirst,ilast
5238 ixp1=1+mod(ipix-1,numxi1)
5239 pixel_id=ipix
5240 ray_origin=xi1(ixp1)*vec_xi1+xi2(ixp2)*vec_xi2
5241 profile_batch(1)=profile_batch(1)+one
5242 nsegbefore=nseg
5243 if (sph_use_dda) then
5244 call collect_euv_sph_dda_segments(ixi^l,ixo^l,cache(iigrid)%source,&
5245 cache(iigrid)%opacity,pixel_id,ray_origin,xi1(ixp1),xi2(ixp2),&
5246 cache(iigrid)%rface,cache(iigrid)%thetaface,cache(iigrid)%phiface,&
5247 cache(iigrid)%rface2,cache(iigrid)%theta_cos,&
5248 cache(iigrid)%phi_sin,cache(iigrid)%phi_cos,&
5249 segments,nseg,capacity,ddafallback)
5250 if (ddafallback) sphddafallbacklocal=sphddafallbacklocal+1
5251 else
5252 call collect_euv_sph_intersection_segments(ixi^l,ixo^l,cache(iigrid)%source,&
5253 cache(iigrid)%opacity,pixel_id,ray_origin,xi1(ixp1),xi2(ixp2),&
5254 cache(iigrid)%rface,cache(iigrid)%thetaface,cache(iigrid)%phiface,&
5255 cache(iigrid)%rface2,cache(iigrid)%theta_cos,&
5256 cache(iigrid)%phi_sin,cache(iigrid)%phi_cos,&
5257 segments,nseg,capacity)
5258 endif
5259 if (nseg>nsegbefore) profile_batch(2)=profile_batch(2)+one
5260 profile_batch(3)=profile_batch(3)+dble(nseg-nsegbefore)
5261 do iseg=nsegbefore+1,nseg
5262 phys_sum_batch(1)=phys_sum_batch(1)+segments(3,iseg)
5263 phys_sum_batch(2)=phys_sum_batch(2)+segments(4,iseg)
5264 enddo
5265 enddo
5266 enddo
5267 enddo
5268
5269 call mpi_allreduce(nseg,maxnsegbatch,1,mpi_integer,mpi_max,icomm,ierrmpi)
5270 if (maxnsegbatch>maxsegbatchtarget .and. npixbatch>1) then
5271 npixbatch=max(1,npixbatch/2)
5272 ipixend=ipixstart+npixbatch-1
5273 if (allocated(segments)) deallocate(segments)
5274 batchreduced=.true.
5275 else
5276 batchaccepted=.true.
5277 endif
5278 enddo
5279
5280 profile_local=profile_local+profile_batch
5281 phys_sum_local=phys_sum_local+phys_sum_batch
5282 if (radsyn_verbose .and. mype==0 .and. batchreduced) then
5283 if (sph_use_dda) then
5284 write(*,'(a,3(i0,1x))') ' sph_dda thick adaptive batch: ',&
5285 ipixstart,ipixend,maxnsegbatch
5286 else
5287 write(*,'(a,3(i0,1x))') ' sph_intersection thick adaptive batch: ',&
5288 ipixstart,ipixend,maxnsegbatch
5289 endif
5290 endif
5291
5292 if (.not. allocated(segments)) then
5293 capacity=1
5294 allocate(segments(nsegvars,capacity))
5295 endif
5296 ownersegcounts=0
5297 do is=1,nseg
5298 owner=segment_pixel_owner(nint(segments(1,is)))
5299 ownersegcounts(owner)=ownersegcounts(owner)+1
5300 enddo
5301 sendcounts=nsegvars*ownersegcounts
5302 senddispls(0)=0
5303 do ipe=1,npe-1
5304 senddispls(ipe)=senddispls(ipe-1)+sendcounts(ipe-1)
5305 enddo
5306
5307 allocate(segments_send(nsegvars,max(1,nseg)))
5308 owneroffsets=0
5309 do is=1,nseg
5310 owner=segment_pixel_owner(nint(segments(1,is)))
5311 isegdest=senddispls(owner)/nsegvars+owneroffsets(owner)+1
5312 segments_send(:,isegdest)=segments(:,is)
5313 owneroffsets(owner)=owneroffsets(owner)+1
5314 enddo
5315
5316 call mpi_alltoall(sendcounts,1,mpi_integer,recvcounts,1,mpi_integer,icomm,ierrmpi)
5317 recvdispls(0)=0
5318 do ipe=1,npe-1
5319 recvdispls(ipe)=recvdispls(ipe-1)+recvcounts(ipe-1)
5320 enddo
5321 totalcount=sum(recvcounts)
5322 totalseg=totalcount/nsegvars
5323 profile_local(4)=profile_local(4)+dble(totalcount)
5324 allocate(segments_recv(nsegvars,max(1,totalseg)))
5325
5326 recvfill=0
5327 maxownersegcountlocal=maxval(ownersegcounts)
5328 call mpi_allreduce(maxownersegcountlocal,maxownersegcount,1,mpi_integer,mpi_max,icomm,ierrmpi)
5329 do segoffset=0,maxownersegcount-1,maxsegcommtarget
5330 roundsendcounts=0
5331 roundsenddispls=senddispls
5332 do ipe=0,npe-1
5333 if (ownersegcounts(ipe)>segoffset) then
5334 roundsendcounts(ipe)=nsegvars*min(maxsegcommtarget,ownersegcounts(ipe)-segoffset)
5335 roundsenddispls(ipe)=senddispls(ipe)+nsegvars*segoffset
5336 endif
5337 enddo
5338
5339 call mpi_alltoall(roundsendcounts,1,mpi_integer,roundrecvcounts,1,mpi_integer,icomm,ierrmpi)
5340 roundrecvdispls(0)=0
5341 do ipe=1,npe-1
5342 roundrecvdispls(ipe)=roundrecvdispls(ipe-1)+roundrecvcounts(ipe-1)
5343 enddo
5344 totalroundcount=sum(roundrecvcounts)
5345 totalroundseg=totalroundcount/nsegvars
5346 allocate(segments_recv_round(nsegvars,max(1,totalroundseg)))
5347
5348 call mpi_alltoallv(segments_send,roundsendcounts,roundsenddispls,mpi_double_precision,&
5349 segments_recv_round,roundrecvcounts,roundrecvdispls,&
5350 mpi_double_precision,icomm,ierrmpi)
5351
5352 if (totalroundseg>0) then
5353 segments_recv(:,recvfill+1:recvfill+totalroundseg)=segments_recv_round(:,1:totalroundseg)
5354 recvfill=recvfill+totalroundseg
5355 endif
5356 deallocate(segments_recv_round)
5357 enddo
5358
5359 if (recvfill/=totalseg) call mpistop("ray-segment receive mismatch")
5360
5361 if (totalseg>0) then
5362 allocate(idx(totalseg))
5363 bucketcounts(1:npixbatch)=0
5364 do is=1,totalseg
5365 if (segment_is_valid(segments_recv,is,4)) then
5366 ipix=nint(segments_recv(1,is))
5367 if (ipix>=ipixstart .and. ipix<=ipixend .and. segment_pixel_owner(ipix)==mype) then
5368 ilocal=ipix-ipixstart+1
5369 bucketcounts(ilocal)=bucketcounts(ilocal)+1
5370 endif
5371 endif
5372 enddo
5373
5374 bucketoffsets(1)=1
5375 do ilocal=1,npixbatch
5376 bucketoffsets(ilocal+1)=bucketoffsets(ilocal)+bucketcounts(ilocal)
5377 enddo
5378 bucketfill(1:npixbatch)=bucketoffsets(1:npixbatch)
5379 do is=1,totalseg
5380 if (segment_is_valid(segments_recv,is,4)) then
5381 ipix=nint(segments_recv(1,is))
5382 if (ipix>=ipixstart .and. ipix<=ipixend .and. segment_pixel_owner(ipix)==mype) then
5383 ilocal=ipix-ipixstart+1
5384 idx(bucketfill(ilocal))=is
5385 bucketfill(ilocal)=bucketfill(ilocal)+1
5386 endif
5387 endif
5388 enddo
5389
5390 do ipix=ipixstart,ipixend
5391 if (segment_pixel_owner(ipix)/=mype) cycle
5392 ilocal=ipix-ipixstart+1
5393 nidx=bucketcounts(ilocal)
5394 if (nidx>0) then
5395 profile_local(5)=profile_local(5)+dble(nidx)*dble(nidx)
5396 call sort_segment_indices_near_to_far(segments_recv,&
5397 idx(bucketoffsets(ilocal):bucketoffsets(ilocal+1)-1),nidx)
5398 ixglobal=1+mod(ipix-1,numxi1)
5399 iyglobal=1+(ipix-1)/numxi1
5400 do iseg=bucketoffsets(ilocal),bucketoffsets(ilocal+1)-1
5401 is=idx(iseg)
5402 euvthin(ixglobal,iyglobal)=euvthin(ixglobal,iyglobal)+segments_recv(3,is)
5403 atten=transfer_attenuation(tau(ixglobal,iyglobal))
5404 euv(ixglobal,iyglobal)=euv(ixglobal,iyglobal)+atten*segments_recv(3,is)
5405 tau(ixglobal,iyglobal)=tau(ixglobal,iyglobal)+max(zero,segments_recv(4,is))
5406 enddo
5407 endif
5408 enddo
5409 deallocate(idx)
5410 endif
5411
5412 deallocate(segments_send,segments_recv)
5413 if (allocated(segments)) deallocate(segments)
5414 ipixstart=ipixend+1
5415 enddo
5416
5417 do iigrid=1,igridstail
5418 if (allocated(cache(iigrid)%source)) deallocate(cache(iigrid)%source)
5419 if (allocated(cache(iigrid)%opacity)) deallocate(cache(iigrid)%opacity)
5420 if (allocated(cache(iigrid)%rface)) deallocate(cache(iigrid)%rface)
5421 if (allocated(cache(iigrid)%thetaface)) deallocate(cache(iigrid)%thetaface)
5422 if (allocated(cache(iigrid)%phiface)) deallocate(cache(iigrid)%phiface)
5423 if (allocated(cache(iigrid)%rface2)) deallocate(cache(iigrid)%rface2)
5424 if (allocated(cache(iigrid)%theta_cos)) deallocate(cache(iigrid)%theta_cos)
5425 if (allocated(cache(iigrid)%phi_sin)) deallocate(cache(iigrid)%phi_sin)
5426 if (allocated(cache(iigrid)%phi_cos)) deallocate(cache(iigrid)%phi_cos)
5427 enddo
5428 deallocate(cache)
5429 deallocate(sendcounts,recvcounts,senddispls,recvdispls,roundsendcounts,roundrecvcounts,&
5430 roundsenddispls,roundrecvdispls,ownersegcounts,owneroffsets,bucketcounts,&
5431 bucketoffsets,bucketfill)
5432 allocate(image_reduce(numxi1,numxi2))
5433 call mpi_allreduce(euv,image_reduce,numxi1*numxi2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5434 euv=image_reduce
5435 call mpi_allreduce(tau,image_reduce,numxi1*numxi2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5436 tau=image_reduce
5437 call mpi_allreduce(euvthin,image_reduce,numxi1*numxi2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5438 euvthin=image_reduce
5439 deallocate(image_reduce)
5440 call mpi_allreduce(profile_local,profile_global,5,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5441 call mpi_allreduce(phys_max_local,phys_max_global,2,mpi_double_precision,mpi_max,icomm,ierrmpi)
5442 call mpi_allreduce(phys_sum_local,phys_sum_global,2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5443 call mpi_allreduce(sphddafallbacklocal,sphddafallbackglobal,1,mpi_integer,mpi_sum,icomm,ierrmpi)
5444 if (radsyn_verbose .and. mype==0) then
5445 if (sph_use_dda) then
5446 write(*,'(a,5(es12.5,1x))') ' sph_dda thick profile: ',profile_global
5447 write(*,'(a,i0)') ' sph_dda thick fallback rays: ',sphddafallbackglobal
5448 write(*,'(a,4(es12.5,1x))') ' sph_dda thick physics maxj maxk sumjds sumkds: ',&
5449 phys_max_global(1),phys_max_global(2),phys_sum_global(1),phys_sum_global(2)
5450 else
5451 write(*,'(a,5(es12.5,1x))') ' sph_intersection thick profile: ',profile_global
5452 write(*,'(a,4(es12.5,1x))') ' sph_intersection thick physics maxj maxk sumjds sumkds: ',&
5453 phys_max_global(1),phys_max_global(2),phys_sum_global(1),phys_sum_global(2)
5454 endif
5455 endif
5457
5458 }
5459
5460 {^ifthreed
5461
5462 subroutine get_sph_intersection_image_bounds(xImin1,xImax1,xImin2,xImax2)
5463 double precision, intent(out) :: xImin1,xImax1,xImin2,xImax2
5464
5465 integer, parameter :: nsample=5
5466 integer :: iigrid,igrid,ir,it,ip
5467 integer :: ixI^L,ixO^L
5468 double precision, allocatable :: rface(:),thetaface(:),phiface(:)
5469 double precision :: local_min1,local_max1,local_min2,local_max2
5470 double precision :: sph(1:3),xcent(1:2),wr,wt,wp
5471
5472 local_min1=huge(one)
5473 local_max1=-huge(one)
5474 local_min2=huge(one)
5475 local_max2=-huge(one)
5476
5477 do iigrid=1,igridstail
5478 igrid=igrids(iigrid)
5479 ^d&ixomin^d=ixmlo^d\
5480 ^d&ixomax^d=ixmhi^d\
5481 ^d&iximin^d=ixglo^d\
5482 ^d&iximax^d=ixghi^d\
5483
5484 call build_sph_intersection_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,&
5485 rface,thetaface,phiface)
5486 do ir=0,nsample-1
5487 wr=dble(ir)/dble(nsample-1)
5488 sph(1)=(one-wr)*rface(ixomin1)+wr*rface(ixomax1+1)
5489 do it=0,nsample-1
5490 wt=dble(it)/dble(nsample-1)
5491 sph(2)=(one-wt)*thetaface(ixomin2)+wt*thetaface(ixomax2+1)
5492 do ip=0,nsample-1
5493 wp=dble(ip)/dble(nsample-1)
5494 if (ir/=0 .and. ir/=nsample-1 .and. it/=0 .and. it/=nsample-1 .and. &
5495 ip/=0 .and. ip/=nsample-1) cycle
5496 sph(3)=(one-wp)*phiface(ixomin3)+wp*phiface(ixomax3+1)
5497 call get_cor_image_spherical(sph,xcent)
5498 local_min1=min(local_min1,xcent(1))
5499 local_max1=max(local_max1,xcent(1))
5500 local_min2=min(local_min2,xcent(2))
5501 local_max2=max(local_max2,xcent(2))
5502 enddo
5503 enddo
5504 enddo
5505 deallocate(rface,thetaface,phiface)
5506 enddo
5507
5508 call mpi_allreduce(local_min1,ximin1,1,mpi_double_precision,mpi_min,icomm,ierrmpi)
5509 call mpi_allreduce(local_max1,ximax1,1,mpi_double_precision,mpi_max,icomm,ierrmpi)
5510 call mpi_allreduce(local_min2,ximin2,1,mpi_double_precision,mpi_min,icomm,ierrmpi)
5511 call mpi_allreduce(local_max2,ximax2,1,mpi_double_precision,mpi_max,icomm,ierrmpi)
5512 if (ximin1>0.5d0*huge(one) .or. ximax1<-0.5d0*huge(one) .or. &
5513 ximin2>0.5d0*huge(one) .or. ximax2<-0.5d0*huge(one)) then
5514 call mpistop("sph_intersection could not determine image bounds")
5515 endif
5517
5519 double precision, intent(out) :: dxI
5520
5521 integer :: iigrid,igrid,ixI^L,ixO^L,ix^D
5522 double precision :: local_min,global_min,dr,ds_theta,ds_phi,rval,theta
5523
5524 local_min=huge(one)
5525 do iigrid=1,igridstail
5526 igrid=igrids(iigrid)
5527 ^d&ixomin^d=ixmlo^d\
5528 ^d&ixomax^d=ixmhi^d\
5529 ^d&iximin^d=ixglo^d\
5530 ^d&iximax^d=ixghi^d\
5531
5532 do ix1=ixomin1,ixomax1
5533 do ix2=ixomin2,ixomax2
5534 do ix3=ixomin3,ixomax3
5535 rval=max(smalldouble,ps(igrid)%x(ix^d,1))
5536 theta=ps(igrid)%x(ix^d,2)
5537 dr=ps(igrid)%dx(ix^d,1)
5538 ds_theta=rval*ps(igrid)%dx(ix^d,2)
5539 ds_phi=rval*max(smalldouble,sin(theta))*ps(igrid)%dx(ix^d,3)
5540 local_min=min(local_min,dr,ds_theta,ds_phi)
5541 enddo
5542 enddo
5543 enddo
5544 enddo
5545
5546 call mpi_allreduce(local_min,global_min,1,mpi_double_precision,mpi_min,icomm,ierrmpi)
5547 if (global_min<=zero .or. global_min>half*huge(one)) then
5548 call mpistop("sph_intersection could not determine dat-resolution image spacing")
5549 endif
5550 dxi=global_min
5552
5553 subroutine get_image(qunit,datatype,fl)
5554 ! integrate emission flux along line of sight (LOS)
5555 ! in a 3D simulation box and get a 2D EUV image
5557 use mod_constants
5558
5559 integer, intent(in) :: qunit
5560 type(te_fluid), intent(in) :: fl
5561 character(20), intent(in) :: datatype
5562
5563 integer :: ix^D,numXI1,numXI2,numWI
5564 double precision :: xImin1,xImax1,xImin2,xImax2,xIcent1,xIcent2,dxI
5565 double precision, allocatable :: xI1(:),xI2(:),dxI1(:),dxI2(:)
5566 double precision, allocatable :: wI(:,:,:),wIs(:,:,:),EM(:,:),Dpl(:,:),Tau(:,:),EMthin(:,:),WLB(:,:,:)
5567 double precision :: vec_temp1(1:3),vec_temp2(1:3)
5568 double precision :: vec_z(1:3),vec_cor(1:3),xI_cor(1:2)
5569 double precision :: res,LOS_psi,r_max,r_loc
5570
5571 integer :: mass
5572 character (30) :: ion
5573 double precision :: logTe,lineCent,sigma_PSF,spaceRsl,wlRsl,wslit
5574 double precision :: arcsec,RHESSI_rsl,LASCO_rsl,pixel,R_occult,smallflux
5575 integer :: iigrid,igrid,i,j,numSI,iw
5576 logical :: emit,ray_image_global,has_thick_output
5577
5578 if (coordinate==spherical) then
5580 else
5581 ! cartesian
5583 endif
5584
5585 ! calculate domain of the image
5586 if (coordinate==spherical) then
5587 if (trim(ray_method_active)=='spherical' .and. datatype=='image_euv') then
5588 call get_sph_intersection_image_bounds(ximin1,ximax1,ximin2,ximax2)
5589 else
5590 ximin1=-abs(xprobmax1)
5591 ximin2=-abs(xprobmax1)
5592 ximax1=abs(xprobmax1)
5593 ximax2=abs(xprobmax1)
5594 endif
5595 else
5596 ! calculate domain of the image
5597 do ix1=1,2
5598 if (ix1==1) vec_cor(1)=xprobmin1
5599 if (ix1==2) vec_cor(1)=xprobmax1
5600 do ix2=1,2
5601 if (ix2==1) vec_cor(2)=xprobmin2
5602 if (ix2==2) vec_cor(2)=xprobmax2
5603 do ix3=1,2
5604 if (ix3==1) vec_cor(3)=xprobmin3
5605 if (ix3==2) vec_cor(3)=xprobmax3
5606 if (big_image) then
5607 r_loc=(vec_cor(1)-x_origin(1))**2
5608 r_loc=r_loc+(vec_cor(2)-x_origin(2))**2
5609 r_loc=r_loc+(vec_cor(3)-x_origin(3))**2
5610 r_loc=sqrt(r_loc)
5611 if (ix1==1 .and. ix2==1 .and. ix3==1) then
5612 r_max=r_loc
5613 else
5614 r_max=max(r_max,r_loc)
5615 endif
5616 else
5617 call get_cor_image(vec_cor,xi_cor)
5618 if (ix1==1 .and. ix2==1 .and. ix3==1) then
5619 ximin1=xi_cor(1)
5620 ximax1=xi_cor(1)
5621 ximin2=xi_cor(2)
5622 ximax2=xi_cor(2)
5623 else
5624 ximin1=min(ximin1,xi_cor(1))
5625 ximax1=max(ximax1,xi_cor(1))
5626 ximin2=min(ximin2,xi_cor(2))
5627 ximax2=max(ximax2,xi_cor(2))
5628 endif
5629 endif
5630 enddo
5631 enddo
5632 enddo
5633 if (big_image) then
5634 ximin1=-r_max
5635 ximin2=-r_max
5636 ximax1=r_max
5637 ximax2=r_max
5638 endif
5639 endif
5640 xicent1=(ximin1+ximax1)/2.d0
5641 xicent2=(ximin2+ximax2)/2.d0
5642
5643 ! tables for image
5644 if (si_unit) then
5645 arcsec=7.25d5/unit_length
5646 else
5647 arcsec=7.25d7/unit_length
5648 endif
5649 if (datatype=='image_euv') then
5650 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
5651 dxi=spacersl*arcsec ! intrument resolution of image
5652 smallflux=smalldouble
5653 else if (datatype=='image_sxr') then
5654 rhessi_rsl=2.3d0/instrument_resolution_factor
5655 dxi=rhessi_rsl*arcsec
5656 smallflux=1.d-40
5657 else if (datatype=='image_whitelight') then
5658 if (whitelight_instrument=='LASCO/C1') then
5659 lasco_rsl=5.6d0/instrument_resolution_factor
5660 r_occult=1.1d0
5661 else if (whitelight_instrument=='LASCO/C2') then
5662 lasco_rsl=11.4d0/instrument_resolution_factor
5663 r_occult=2.d0
5664 else if (whitelight_instrument=='LASCO/C3') then
5665 lasco_rsl=56.d0/instrument_resolution_factor
5666 r_occult=3.7d0
5667 else
5668 call mpistop('Whitelight synthesis: instrument is not supported!')
5669 endif
5670 dxi=lasco_rsl*arcsec
5671 if (r_occultor>1.d0) r_occult=r_occultor
5672 r_occult=r_occult*const_rsun/unit_length
5673 smallflux=1.d-20
5674 endif
5675 numxi1=8*ceiling((ximax1-xicent1)/dxi/8.d0)
5676 ximin1=xicent1-numxi1*dxi
5677 ximax1=xicent1+numxi1*dxi
5678 numxi1=numxi1*2
5679 numxi2=8*ceiling((ximax2-xicent2)/dxi/8.d0)
5680 ximin2=xicent2-numxi2*dxi
5681 ximax2=xicent2+numxi2*dxi
5682 numxi2=numxi2*2
5683 allocate(xi1(numxi1),xi2(numxi2),dxi1(numxi1),dxi2(numxi2))
5684 do ix1=1,numxi1
5685 xi1(ix1)=ximin1+dxi*(ix1-half)
5686 dxi1(ix1)=dxi
5687 enddo
5688 do ix2=1,numxi2
5689 xi2(ix2)=ximin2+dxi*(ix2-half)
5690 dxi2(ix2)=dxi
5691 enddo
5692
5693 ! calculate emission
5694 if (datatype=='image_euv' .or. datatype=='image_sxr') then
5695 has_thick_output=datatype=='image_euv' .and. trim(radiation_transfer)=='thick' .and. &
5696 ((coordinate==spherical .and. trim(ray_method_active)=='spherical') .or. &
5697 (coordinate==cartesian .and. trim(ray_method_active)=='cart'))
5698 if (datatype=='image_euv') then
5699 numwi=radsyn_euv_num_outputs(.false.,has_thick_output)
5700 else
5701 numwi=1
5702 endif
5703 allocate(wi(numxi1,numxi2,numwi),wis(numxi1,numxi2,numwi),em(numxi1,numxi2))
5704 wi=zero
5705 wis=zero
5706 em=zero
5707 ray_image_global=.false.
5708 if (has_thick_output) then
5709 allocate(tau(numxi1,numxi2),emthin(numxi1,numxi2))
5710 tau=zero
5711 emthin=zero
5712 endif
5713 if (coordinate==cartesian .and. datatype=='image_euv' .and. &
5714 trim(ray_method_active)=='cart') then
5715 ray_image_global=.true.
5716 allocate(dpl(numxi1,numxi2))
5717 dpl=zero
5718 if (trim(radiation_transfer)=='thick') then
5719 call integrate_euv_cart_dda_thick_datresol(numxi1,numxi2,xi1,xi2,fl,em,dpl,tau,emthin)
5720 else
5721 call integrate_euv_cart_dda_datresol(numxi1,numxi2,xi1,xi2,fl,em,dpl)
5722 endif
5723 deallocate(dpl)
5724 else if (coordinate==cartesian) then
5725 do iigrid=1,igridstail; igrid=igrids(iigrid);
5726 call integrate_emission_cartesian(igrid,numxi1,numxi2,xi1,xi2,dxi,fl,datatype,em)
5727 enddo
5728 else if (trim(ray_method_active) == 'spherical' .and. datatype == 'image_euv') then
5729 if (trim(radiation_transfer) == 'thick') then
5730 ray_image_global=.true.
5731 call integrate_euv_sph_intersection_thick(numxi1,numxi2,xi1,xi2,dxi,fl,em,tau,emthin)
5732 else
5733 call integrate_euv_sph_intersection_thin(numxi1,numxi2,xi1,xi2,dxi,fl,em)
5734 endif
5735 else
5736 do iigrid=1,igridstail; igrid=igrids(iigrid);
5737 call integrate_emission_spherical(igrid,numxi1,numxi2,xi1,xi2,dxi,fl,datatype,em)
5738 enddo
5739 endif
5740 if (ray_image_global) then
5741 if (has_thick_output) then
5742 call pack_euv_image_outputs(numxi1,numxi2,em,wi,smallflux,.false.,&
5743 has_thick_output,tau=tau,euvthin=emthin,&
5744 cap_absorption=.true.)
5745 else
5746 call pack_euv_image_outputs(numxi1,numxi2,em,wi,smallflux,.false.,has_thick_output)
5747 endif
5748 else
5749 do ix1=1,numxi1
5750 do ix2=1,numxi2
5751 if (em(ix1,ix2)>smallflux) wis(ix1,ix2,1)=em(ix1,ix2)
5752 enddo
5753 enddo
5754 endif
5755 if (.not. ray_image_global) then
5756 numsi=numxi1*numxi2*numwi
5757 call mpi_allreduce(wis,wi,numsi,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5758 endif
5759 if (activate_unit_arcsec) then
5760 xi1=xi1/arcsec
5761 dxi1=dxi1/arcsec
5762 xi2=xi2/arcsec
5763 dxi2=dxi2/arcsec
5764 endif
5765 call output_data(qunit,xi1,xi2,dxi1,dxi2,wi,numxi1,numxi2,numwi,datatype)
5766 if (allocated(tau)) deallocate(tau)
5767 if (allocated(emthin)) deallocate(emthin)
5768 deallocate(wi,wis,em)
5769 else if (datatype=='image_whitelight') then
5770 numwi=2
5771 allocate(wi(numxi1,numxi2,numwi),wis(numxi1,numxi2,numwi),wlb(numxi1,numxi2,numwi))
5772 wi=zero
5773 wis=zero
5774 wlb=zero
5775 if (coordinate==spherical) then
5776 do iigrid=1,igridstail; igrid=igrids(iigrid);
5777 call integrate_whitelight_spherical(igrid,numxi1,numxi2,numwi,xi1,xi2,dxi,fl,datatype,wlb)
5778 enddo
5779 endif
5780 do ix1=1,numxi1
5781 do ix2=1,numxi2
5782 if (wlb(ix1,ix2,1)>smallflux) then
5783 wis(ix1,ix2,1)=wlb(ix1,ix2,1)
5784 wis(ix1,ix2,2)=wlb(ix1,ix2,2)
5785 endif
5786 enddo
5787 enddo
5788 numsi=numxi1*numxi2*numwi
5789 call mpi_allreduce(wis,wi,numsi,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5790 if (activate_unit_arcsec) then
5791 xi1=xi1/arcsec
5792 dxi1=dxi1/arcsec
5793 xi2=xi2/arcsec
5794 dxi2=dxi2/arcsec
5795 endif
5796 call output_data(qunit,xi1,xi2,dxi1,dxi2,wi,numxi1,numxi2,numwi,datatype)
5797 deallocate(wi,wis,wlb)
5798 endif
5799
5800 deallocate(xi1,xi2,dxi1,dxi2)
5801
5802 end subroutine get_image
5803
5804 subroutine integrate_emission_cartesian(igrid,numXI1,numXI2,xI1,xI2,dxI,fl,datatype,EM)
5805 integer, intent(in) :: igrid,numXI1,numXI2
5806 double precision, intent(in) :: xI1(numXI1),xI2(numXI2)
5807 double precision, intent(in) :: dxI
5808 type(te_fluid), intent(in) :: fl
5809 character(20), intent(in) :: datatype
5810 double precision, intent(inout) :: EM(numXI1,numXI2)
5811
5812 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
5813 double precision :: xb^L,xd^D
5814 double precision, allocatable :: flux(:^D&),opacity(:^D&)
5815 double precision :: res
5816 integer :: ixP^L,ixP^D,nSubC^D,iSubC^D
5817 double precision :: xSubP1,xSubP2,dxSubP,xerf^L,fluxsubC
5818 double precision :: xSubC(1:3),dxSubC^D,xCent(1:2)
5819
5820 integer :: mass
5821 double precision :: logTe
5822 character (30) :: ion
5823 double precision :: lineCent
5824 double precision :: sigma_PSF,spaceRsl,wlRsl,sigma0,factor,wslit
5825 double precision :: arcsec,pixel,RHESSI_rsl,area_1AU
5826 double precision :: aa,bb
5827
5828 ^d&ixomin^d=ixmlo^d\
5829 ^d&ixomax^d=ixmhi^d\
5830 ^d&iximin^d=ixglo^d\
5831 ^d&iximax^d=ixghi^d\
5832 ^d&xbmin^d=rnode(rpxmin^d_,igrid)\
5833 ^d&xbmax^d=rnode(rpxmax^d_,igrid)\
5834
5835 if (si_unit) then
5836 arcsec=7.25d5/unit_length
5837 else
5838 arcsec=7.25d7/unit_length
5839 endif
5840
5841 allocate(flux(ixi^s),opacity(ixi^s))
5842 if (datatype=='image_euv') then
5843 if (trim(emission_model)=='pseudo_current') then
5844 call get_pseudo_current(igrid,ixi^l,ixo^l,ps(igrid)%w,flux)
5845 else if (trim(emission_model)=='radio_ff') then
5846 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,opacity)
5847 else
5848 ! get local EUV flux and velocity
5849 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux)
5850 flux(ixo^s)=flux(ixo^s)/instrument_resolution_factor**2 ! adjust flux due to artifical change of resolution
5851 endif
5852 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
5853 pixel=spacersl*arcsec
5854 sigma0=sigma_psf*pixel
5855 else if (datatype=='image_sxr') then
5856 ! get local SXR flux photons cm^-3 s^-1 (cgs) or photons m^-3 s^-1 (SI)
5857 call get_sxr(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,emin_sxr,emax_sxr)
5858 rhessi_rsl=2.3d0/instrument_resolution_factor
5859 sigma_psf=1.d0
5860 pixel=rhessi_rsl*arcsec
5861 sigma0=sigma_psf*pixel
5862 area_1au=2.81d27
5863 endif
5864
5865 ! integrate emission
5866 {do ix^d=ixomin^d,ixomax^d\}
5867 ^d&nsubc^d=1;
5868 ^d&nsubc^d=max(nsubc^d,ceiling(ps(igrid)%dx(ix^dd,^d)*abs(vec_xi1(^d))/(dxi/2.d0)));
5869 ^d&nsubc^d=max(nsubc^d,ceiling(ps(igrid)%dx(ix^dd,^d)*abs(vec_xi2(^d))/(dxi/2.d0)));
5870 ^d&dxsubc^d=ps(igrid)%dx(ix^dd,^d)/nsubc^d;
5871 if (datatype=='image_euv') then
5872 if (si_unit) then
5873 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length*1.d2/dxi/dxi ! DN s^-1
5874 else
5875 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length/dxi/dxi ! DN s^-1
5876 endif
5877 else if (datatype=='image_sxr') then
5878 ! sub-cell SXR flux at 1 AU [photons s^-1 cm^-2]
5879 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length**3/area_1au
5880 endif
5881 if (fluxsubc>smalldouble) then
5882 ! dividing a cell to several parts to get more accurate integrating values
5883 {do isubc^d=1,nsubc^d\}
5884 ^d&xsubc(^d)=ps(igrid)%x(ix^dd,^d)-half*ps(igrid)%dx(ix^dd,^d)+(isubc^d-half)*dxsubc^d;
5885 ! mapping the 3D coordinate to location at the image
5886 call get_cor_image(xsubc,xcent)
5887 ! distribution at nearby pixels
5888 ixp1=floor((xcent(1)-(xi1(1)-half*dxi))/dxi)+1
5889 ixp2=floor((xcent(2)-(xi2(1)-half*dxi))/dxi)+1
5890 ixpmin1=max(1,ixp1-3)
5891 ixpmax1=min(ixp1+3,numxi1)
5892 ixpmin2=max(1,ixp2-3)
5893 ixpmax2=min(ixp2+3,numxi2)
5894 do ixp1=ixpmin1,ixpmax1
5895 do ixp2=ixpmin2,ixpmax2
5896 xerfmin1=((xi1(ixp1)-half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
5897 xerfmax1=((xi1(ixp1)+half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
5898 xerfmin2=((xi2(ixp2)-half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
5899 xerfmax2=((xi2(ixp2)+half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
5900 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
5901 em(ixp1,ixp2)=em(ixp1,ixp2)+fluxsubc*factor
5902 enddo !ixP2
5903 enddo !ixP1
5904 {enddo\} !iSubC
5905 endif
5906 {enddo\} !ix
5907
5908 deallocate(flux,opacity)
5909 end subroutine integrate_emission_cartesian
5910
5911 subroutine integrate_emission_spherical(igrid,numXI1,numXI2,xI1,xI2,dxI,fl,datatype,EM)
5912 integer, intent(in) :: igrid,numXI1,numXI2
5913 double precision, intent(in) :: xI1(numXI1),xI2(numXI2)
5914 double precision, intent(in) :: dxI
5915 type(te_fluid), intent(in) :: fl
5916 character(20), intent(in) :: datatype
5917 double precision, intent(inout) :: EM(numXI1,numXI2)
5918
5919 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
5920 double precision, allocatable :: flux(:^D&),Ne(:^D&),opacity(:^D&)
5921 integer :: ixP^L,ixP^D,nSubC^D,iSubC^D
5922 double precision :: xSubP1,xSubP2,dxSubP,xerf^L,fluxsubC,RsubC
5923 double precision :: TBsubC,PBsubC
5924 double precision :: xSubC(1:3),dxSubC^D,xCent(1:2),xSubC_car(1:3)
5925 double precision :: R_thick,dotp,dvolume,R_occult,Rc
5926 double precision :: dxl(1:3),x_sph(1:3),dx_sph(1:3)
5927 double precision :: unitv_r(1:3),unitv_theta(1:3),unitv_phi(1:3)
5928 logical :: sun_back_side,emit
5929
5930 integer :: mass
5931 double precision :: logTe
5932 character (30) :: ion
5933 double precision :: lineCent
5934 double precision :: sigma_PSF,spaceRsl,wlRsl,sigma0,factor,wslit
5935 double precision :: RHESSI_rsl,area_1AU,arcsec,pixel
5936
5937 ^d&ixomin^d=ixmlo^d;
5938 ^d&ixomax^d=ixmhi^d;
5939 ^d&iximin^d=ixglo^d;
5940 ^d&iximax^d=ixghi^d;
5941
5942 if (si_unit) then
5943 arcsec=7.25d5/unit_length
5944 else
5945 arcsec=7.25d7/unit_length
5946 endif
5947
5948 allocate(flux(ixi^s),opacity(ixi^s))
5949 if (datatype=='image_euv') then
5950 if (trim(emission_model)=='pseudo_current') then
5951 call get_pseudo_current(igrid,ixi^l,ixo^l,ps(igrid)%w,flux)
5952 else if (trim(emission_model)=='radio_ff') then
5953 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,opacity)
5954 else
5955 ! get local EUV flux and velocity
5956 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux)
5957 flux(ixo^s)=flux(ixo^s)/instrument_resolution_factor**2 ! adjust flux due to artifical change of resolution
5958 endif
5959 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
5960 pixel=spacersl*arcsec
5961 sigma0=sigma_psf*pixel
5962 else if (datatype=='image_sxr') then
5963 ! get local SXR flux photons cm^-3 s^-1 (cgs) or photons m^-3 s^-1 (SI)
5964 call get_sxr(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,emin_sxr,emax_sxr)
5965 rhessi_rsl=2.3d0/instrument_resolution_factor
5966 sigma_psf=1.d0
5967 pixel=rhessi_rsl*arcsec
5968 sigma0=sigma_psf*pixel
5969 area_1au=2.81d27
5970 endif
5971
5972 ! integrate emission
5973 r_thick=r_opt_thick*const_rsun/unit_length
5974 {do ix^d=ixomin^d,ixomax^d\}
5975 x_sph(1:3)=ps(igrid)%x(ix^d,1:3)
5976 dx_sph(1:3)=ps(igrid)%dx(ix^d,1:3)
5977 dxl(1)=dx_sph(1) ! cell size in length
5978 dxl(2)=x_sph(1)*dx_sph(2) ! cell size in length
5979 dxl(3)=x_sph(1)*dsin(x_sph(2))*dx_sph(3) ! cell size in length
5980 ! dividing a cell to several sub-cells to get more accurate integrating values
5981 ^d&nsubc^d=1;
5982 call get_unit_vector_spherical(x_sph,unitv_r,unitv_theta,unitv_phi)
5983 call dot_product_loc(unitv_r,vec_xi1,dotp)
5984 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
5985 call dot_product_loc(unitv_r,vec_xi2,dotp)
5986 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
5987 call dot_product_loc(unitv_theta,vec_xi1,dotp)
5988 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
5989 call dot_product_loc(unitv_theta,vec_xi2,dotp)
5990 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
5991 call dot_product_loc(unitv_phi,vec_xi1,dotp)
5992 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
5993 call dot_product_loc(unitv_phi,vec_xi2,dotp)
5994 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
5995
5996 ! integrate sub-cells
5997 do isubc1=1,nsubc1
5998 ! sub-cell center coordinate in spherical
5999 xsubc(1)=x_sph(1)-half*dx_sph(1)+(isubc1-half)*dx_sph(1)/nsubc1
6000 rsubc=xsubc(1)
6001 dxsubc1=dx_sph(1)/nsubc1 ! sub-cell size in length
6002 do isubc2=1,nsubc2
6003 ! sub-cell center coordinate in spherical
6004 xsubc(2)=x_sph(2)-half*dx_sph(2)+(isubc2-half)*dx_sph(2)/nsubc2
6005 dxsubc2=xsubc(1)*dx_sph(2)/nsubc2 ! sub-cell size in length
6006 dxsubc3=xsubc(1)*dsin(xsubc(2))*dx_sph(3)/nsubc3 ! sub-cell size in length
6007 dvolume=dxsubc1*dxsubc2*dxsubc3
6008 if (datatype=='image_euv') then
6009 if (si_unit) then
6010 fluxsubc=flux(ix^d)*dvolume*unit_length*1.d2/dxi/dxi ! DN s^-1
6011 else
6012 fluxsubc=flux(ix^d)*dvolume*unit_length/dxi/dxi ! DN s^-1
6013 endif
6014 else if (datatype=='image_sxr') then
6015 ! sub-cell SXR flux at 1 AU [photons s^-1 cm^-2]
6016 fluxsubc=flux(ix^d)*dvolume*unit_length**3/area_1au
6017 endif
6018 ! enter integration if flux large enough
6019 if (fluxsubc>smalldouble) then
6020 do isubc3=1,nsubc3
6021 ! sub-cell center coordinate in spherical
6022 xsubc(3)=x_sph(3)-half*dx_sph(3)+(isubc3-half)*dx_sph(3)/nsubc3
6023 call get_cor_image_spherical(xsubc,xcent)
6024 rc=dsqrt(xcent(1)**2+xcent(2)**2) ! distance to sun center (on the image plane)
6025 !
6026 ! whether the local emitted photons can arrive the telescope
6027 call spherical_to_cartesian(xsubc,xsubc_car)
6028 call dot_product_loc(vec_los,xsubc_car,dotp)
6029 sun_back_side=.true.
6030 if (dotp<0.d0) sun_back_side=.false.
6031 ! whether the local emission can reach the telescope
6032 if (sun_back_side) then
6033 emit=.false.
6034 if (rc>r_thick) emit=.true.
6035 else
6036 emit=.true.
6037 if (xsubc(1)<=r_thick) emit=.false.
6038 endif
6039 !
6040 if (emit) then
6041 ! mapping the 3D coordinate to location at the image
6042 ! distribution at nearby pixels
6043 ixp1=floor((xcent(1)-(xi1(1)-half*dxi))/dxi)+1
6044 ixp2=floor((xcent(2)-(xi2(1)-half*dxi))/dxi)+1
6045 ixpmin1=max(1,ixp1-3)
6046 ixpmax1=min(ixp1+3,numxi1)
6047 ixpmin2=max(1,ixp2-3)
6048 ixpmax2=min(ixp2+3,numxi2)
6049 do ixp1=ixpmin1,ixpmax1
6050 do ixp2=ixpmin2,ixpmax2
6051 xerfmin1=((xi1(ixp1)-half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6052 xerfmax1=((xi1(ixp1)+half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6053 xerfmin2=((xi2(ixp2)-half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6054 xerfmax2=((xi2(ixp2)+half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6055 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
6056 em(ixp1,ixp2)=em(ixp1,ixp2)+fluxsubc*factor
6057 enddo !ixP2
6058 enddo !ixP1
6059 endif !emit
6060 enddo !iSubC3
6061 endif !smallflux
6062 enddo !iSubC2
6063 enddo !iSubC1
6064 {enddo\} !ix
6065
6066 deallocate(flux,opacity)
6067
6068 end subroutine integrate_emission_spherical
6069
6070 subroutine integrate_whitelight_spherical(igrid,numXI1,numXI2,numWI,xI1,xI2,dxI,fl,datatype,WLB)
6071 use mod_eos, only: eos
6072
6073 integer, intent(in) :: igrid,numXI1,numXI2,numWI
6074 double precision, intent(in) :: xI1(numXI1),xI2(numXI2)
6075 double precision, intent(in) :: dxI
6076 type(te_fluid), intent(in) :: fl
6077 character(20), intent(in) :: datatype
6078 double precision, intent(inout) :: WLB(numXI1,numXI2,numWI)
6079
6080 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
6081 double precision, allocatable :: flux(:^D&),Ne(:^D&)
6082 integer :: ixP^L,ixP^D,nSubC^D,iSubC^D
6083 double precision :: xSubP1,xSubP2,dxSubP,xerf^L,fluxsubC,RsubC
6084 double precision :: sigma_PSF,sigma0,arcsec,pixel,LASCO_rsl
6085 double precision :: A,B,C,D,Rc,Ne0,TBsubC,PBsubC,factor
6086 double precision :: R_thick,dotp,dvolume,R_occult
6087 double precision :: xSubC(1:3),dxSubC^D,xCent(1:2),xSubC_car(1:3)
6088 double precision :: dxl(1:3),x_sph(1:3),dx_sph(1:3)
6089 double precision :: unitv_r(1:3),unitv_theta(1:3),unitv_phi(1:3)
6090 logical :: emit
6091
6092 ^d&ixomin^d=ixmlo^d;
6093 ^d&ixomax^d=ixmhi^d;
6094 ^d&iximin^d=ixglo^d;
6095 ^d&iximax^d=ixghi^d;
6096
6097 if (si_unit) then
6098 arcsec=7.25d5/unit_length
6099 else
6100 arcsec=7.25d7/unit_length
6101 endif
6102
6103 allocate(ne(ixi^s))
6104 if (whitelight_instrument=='LASCO/C1') then
6105 lasco_rsl=5.6d0/instrument_resolution_factor
6106 r_occult=1.1d0
6107 else if (whitelight_instrument=='LASCO/C2') then
6108 lasco_rsl=11.4d0/instrument_resolution_factor
6109 r_occult=2.d0
6110 else if (whitelight_instrument=='LASCO/C3') then
6111 lasco_rsl=56.d0/instrument_resolution_factor
6112 r_occult=3.7d0
6113 endif
6114 if (r_occultor>1.d0) r_occult=r_occultor
6115 r_occult=r_occult*const_rsun/unit_length
6116 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,ne)
6117 ! get actual electron density from EoS (replaces rho with ne)
6118 block
6119 double precision :: nH_dummy(ixI^S)
6120 call eos%get_ne_nH(ixi^l, ixo^l, ps(igrid)%w, ne, nh_dummy)
6121 end block
6122 sigma_psf=1.d0
6123 pixel=lasco_rsl*arcsec
6124 sigma0=sigma_psf*pixel
6125
6126 ! integrate emission
6127 r_thick=r_opt_thick*const_rsun/unit_length
6128 {do ix^d=ixomin^d,ixomax^d\}
6129 x_sph(1:3)=ps(igrid)%x(ix^d,1:3)
6130 dx_sph(1:3)=ps(igrid)%dx(ix^d,1:3)
6131 dxl(1)=dx_sph(1) ! cell size in length
6132 dxl(2)=x_sph(1)*dx_sph(2) ! cell size in length
6133 dxl(3)=x_sph(1)*dsin(x_sph(2))*dx_sph(3) ! cell size in length
6134 ne0=ne(ix^d)*unit_numberdensity
6135 ! dividing a cell to several sub-cells to get more accurate integrating values
6136 ^d&nsubc^d=1;
6137 call get_unit_vector_spherical(x_sph,unitv_r,unitv_theta,unitv_phi)
6138 call dot_product_loc(unitv_r,vec_xi1,dotp)
6139 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
6140 call dot_product_loc(unitv_r,vec_xi2,dotp)
6141 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
6142 call dot_product_loc(unitv_theta,vec_xi1,dotp)
6143 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
6144 call dot_product_loc(unitv_theta,vec_xi2,dotp)
6145 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
6146 call dot_product_loc(unitv_phi,vec_xi1,dotp)
6147 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
6148 call dot_product_loc(unitv_phi,vec_xi2,dotp)
6149 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
6150
6151 ! integrate sub-cells
6152 do isubc1=1,nsubc1
6153 ! sub-cell center coordinate in spherical
6154 xsubc(1)=x_sph(1)-half*dx_sph(1)+(isubc1-half)*dx_sph(1)/nsubc1
6155 rsubc=xsubc(1)
6156 dxsubc1=dx_sph(1)/nsubc1 ! sub-cell size in length
6157 call get_thomson_parameters(rsubc,a,b,c,d)
6158 do isubc2=1,nsubc2
6159 ! sub-cell center coordinate in spherical
6160 xsubc(2)=x_sph(2)-half*dx_sph(2)+(isubc2-half)*dx_sph(2)/nsubc2
6161 dxsubc2=xsubc(1)*dx_sph(2)/nsubc2 ! sub-cell size in length
6162 dxsubc3=xsubc(1)*dsin(xsubc(2))*dx_sph(3)/nsubc3 ! sub-cell size in length
6163 dvolume=dxsubc1*dxsubc2*dxsubc3
6164 do isubc3=1,nsubc3
6165 ! sub-cell center coordinate in spherical
6166 xsubc(3)=x_sph(3)-half*dx_sph(3)+(isubc3-half)*dx_sph(3)/nsubc3
6167 call get_cor_image_spherical(xsubc,xcent)
6168 rc=dsqrt(xcent(1)**2+xcent(2)**2) ! distance to sun center (on the image plane)
6169 ! whether the local emitted photons can arrive the telescope
6170 emit=.false.
6171 if (rc>r_occult) then
6172 emit=.true.
6173 ! scaterring flux from cm^-3 of plasma
6174 call get_whitelight_thomson(rsubc,rc,ne0,a,b,c,d,tbsubc,pbsubc)
6175 tbsubc=tbsubc*dvolume*unit_length/dxi/dxi
6176 pbsubc=pbsubc*dvolume*unit_length/dxi/dxi
6177 if (tbsubc<1.d-20) emit=.false.
6178 endif
6179 if (emit) then
6180 ! mapping the 3D coordinate to location at the image
6181 ! distribution at nearby pixels
6182 ixp1=floor((xcent(1)-(xi1(1)-half*dxi))/dxi)+1
6183 ixp2=floor((xcent(2)-(xi2(1)-half*dxi))/dxi)+1
6184 ixpmin1=max(1,ixp1-3)
6185 ixpmax1=min(ixp1+3,numxi1)
6186 ixpmin2=max(1,ixp2-3)
6187 ixpmax2=min(ixp2+3,numxi2)
6188 do ixp1=ixpmin1,ixpmax1
6189 do ixp2=ixpmin2,ixpmax2
6190 xerfmin1=((xi1(ixp1)-half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6191 xerfmax1=((xi1(ixp1)+half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6192 xerfmin2=((xi2(ixp2)-half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6193 xerfmax2=((xi2(ixp2)+half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6194 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
6195 wlb(ixp1,ixp2,1)=wlb(ixp1,ixp2,1)+tbsubc*factor
6196 wlb(ixp1,ixp2,2)=wlb(ixp1,ixp2,2)+pbsubc*factor
6197 enddo !ixP2
6198 enddo !ixP1
6199 endif
6200 enddo !iSubC3
6201 enddo !iSubC2
6202 enddo !iSubC1
6203 {enddo\} !ix
6204
6205 deallocate(ne)
6206
6207 end subroutine integrate_whitelight_spherical
6208
6209 subroutine get_thomson_parameters(Rl,A,B,C,D)
6210 ! parameters given in Billings 1968
6211 use mod_constants
6212 double precision, intent(in) :: Rl
6213 double precision, intent(inout) :: A,B,C,D
6214
6215 double precision :: sinO,cosO,sinO2,cosO2,tmp
6216
6217 sino=const_rsun/(rl*unit_length)
6218 sino2=sino**2
6219 coso2=1.d0-sino2
6220 coso=abs(dsqrt(coso2))
6221 tmp=log((1.d0+sino)/coso)
6222 a=coso*sino2
6223 b=-(1.d0-3.d0*sino2-(coso2/sino)*(1.d0+3.d0*sino2)*tmp)/8.d0
6224 c=4.d0/3.d0-coso-coso*coso2/3.d0
6225 d=(5.d0+sino2-(coso2/sino)*(5.d0-sino2)*tmp)/8.d0
6226
6227 end subroutine get_thomson_parameters
6228
6229 subroutine get_whitelight_thomson(Rl,Rin,Ne,A,B,C,D,fluxTB,fluxPB)
6230 ! use the method in SSW/eltheory
6231 double precision, intent(in) :: Rl,Rin,Ne,A,B,C,D
6232 double precision, intent(inout) :: fluxTB,fluxPB
6233
6234 double precision :: const,u,Bt,Br,PB,TB,sinchi2
6235
6236 u=0.63d0
6237 const=1.24878d-25/(1.d0-u/3.d0)
6238 sinchi2=(rin/rl)**2
6239 bt=const*(c+u*(d-c))
6240 pb=const*sinchi2*((a+u*(b-a)))
6241 br=bt-pb
6242 tb=bt+br
6243 fluxtb=tb*ne
6244 fluxpb=pb*ne
6245
6246 end subroutine get_whitelight_thomson
6247
6248 subroutine get_unit_vector_spherical(x_sph,unitv_r,unitv_theta,unitv_phi)
6249 double precision, intent(in) :: x_sph(1:3)
6250 double precision, intent(inout) :: unitv_r(1:3),unitv_theta(1:3),unitv_phi(1:3)
6251
6252 unitv_r(1)=dsin(x_sph(2))*dcos(x_sph(3))
6253 unitv_r(2)=dsin(x_sph(2))*dsin(x_sph(3))
6254 unitv_r(3)=dcos(x_sph(2))
6255 unitv_theta(1)=dcos(x_sph(2))*dcos(x_sph(3))
6256 unitv_theta(2)=dcos(x_sph(2))*dsin(x_sph(3))
6257 unitv_theta(3)=-dsin(x_sph(2))
6258 unitv_phi(1)=-dsin(x_sph(3))
6259 unitv_phi(2)=dcos(x_sph(3))
6260 unitv_phi(3)=zero
6261
6262 end subroutine get_unit_vector_spherical
6263
6264 subroutine output_data(qunit,xO1,xO2,dxO1,dxO2,wO,nXO1,nXO2,nWO,datatype)
6265 ! change the format of data and write data
6267
6268 integer, intent(in) :: qunit,nXO1,nXO2,nWO
6269 double precision, intent(in) :: dxO1(nxO1),dxO2(nxO2)
6270 double precision, intent(in) :: xO1(nXO1),xO2(nxO2)
6271 double precision, intent(inout) :: wO(nXO1,nXO2,nWO)
6272 character(20), intent(in) :: datatype
6273
6274 integer :: nPiece,nP1,nP2,nC1,nC2,nWC
6275 integer :: piece_nmax1,piece_nmax2,ix1,ix2,j,ipc,ixc1,ixc2
6276 double precision :: uniform_tol
6277 double precision, allocatable :: xC(:,:,:,:),wC(:,:,:,:),dxC(:,:,:,:)
6278
6279 ! clean small values
6280 uniform_tol=1.d-10
6281 do ix1=1,nxo1
6282 do ix2=1,nxo2
6283 do j=1,nwo
6284 if (abs(wo(ix1,ix2,j))<smalldouble) wo(ix1,ix2,j)=zero
6285 enddo
6286 enddo
6287 enddo
6288
6289 ! how many cells in each grid
6290 if (dat_resolution) then
6291 if (datatype=='image_euv' .or. datatype=='image_sxr') then
6292 if (los_phi==0 .and. los_theta==90) then
6293 piece_nmax1=block_nx2
6294 piece_nmax2=block_nx3
6295 else if (los_phi==90 .and. los_theta==90) then
6296 piece_nmax1=block_nx3
6297 piece_nmax2=block_nx1
6298 else
6299 piece_nmax1=block_nx1
6300 piece_nmax2=block_nx2
6301 endif
6302 else if (datatype=='spectrum_euv') then
6303 piece_nmax1=16
6304 if (direction_slit==1) then
6305 piece_nmax2=block_nx1
6306 else if (direction_slit==2) then
6307 piece_nmax2=block_nx2
6308 else
6309 piece_nmax2=block_nx3
6310 endif
6311 endif
6312 else
6313 piece_nmax1=20
6314 piece_nmax2=20
6315 endif
6316 loopn1: do j=piece_nmax1,1,-1
6317 if(mod(nxo1,j)==0) then
6318 nc1=j
6319 exit loopn1
6320 endif
6321 enddo loopn1
6322 loopn2: do j=piece_nmax2,1,-1
6323 if(mod(nxo2,j)==0) then
6324 nc2=j
6325 exit loopn2
6326 endif
6327 enddo loopn2
6328 ! how many grids
6329 np1=nxo1/nc1
6330 np2=nxo2/nc2
6331 npiece=np1*np2
6332 nwc=nwo
6333
6334 ! output images
6335 select case(convert_type)
6336 case('EIvtuCCmpi','ESvtuCCmpi','SIvtuCCmpi','WIvtuCCmpi')
6337 ! put data into grids
6338 allocate(xc(npiece,nc1,nc2,2))
6339 allocate(dxc(npiece,nc1,nc2,2))
6340 allocate(wc(npiece,nc1,nc2,nwo))
6341 do ipc=1,npiece
6342 do ixc1=1,nc1
6343 do ixc2=1,nc2
6344 ix1=mod(ipc-1,np1)*nc1+ixc1
6345 ix2=floor(1.0*(ipc-1)/np1)*nc2+ixc2
6346 xc(ipc,ixc1,ixc2,1)=xo1(ix1)
6347 xc(ipc,ixc1,ixc2,2)=xo2(ix2)
6348 dxc(ipc,ixc1,ixc2,1)=dxo1(ix1)
6349 dxc(ipc,ixc1,ixc2,2)=dxo2(ix2)
6350 do j=1,nwc
6351 wc(ipc,ixc1,ixc2,j)=wo(ix1,ix2,j)
6352 enddo
6353 enddo
6354 enddo
6355 enddo
6356 ! write data into vtu file
6357 call write_image_vtucc(qunit,xc,wc,dxc,npiece,nc1,nc2,nwc,datatype)
6358 deallocate(xc,dxc,wc)
6359 case('EIvtiCCmpi','ESvtiCCmpi','SIvtiCCmpi','WIvtiCCmpi')
6360 if (dat_resolution .and. &
6361 (maxval(abs(dxo1(:)-dxo1(1)))>uniform_tol*max(one,abs(dxo1(1))) .or. &
6362 maxval(abs(dxo2(:)-dxo2(1)))>uniform_tol*max(one,abs(dxo2(1))))) then
6363 call mpistop("vti needs uniform dat-resolution image grids")
6364 else
6365 call write_image_vticc(qunit,xo1,xo2,dxo1,dxo2,wo,nxo1,nxo2,nwo,nc1,nc2)
6366 endif
6367 case default
6368 call mpistop("Error in synthesize emission: Unknown convert_type")
6369 end select
6370
6371 end subroutine output_data
6372 }
6373
6374 subroutine write_image_vticc(qunit,xO1,xO2,dxO1,dxO2,wO,nXO1,nXO2,nWO,nC1,nC2)
6375 ! write image data to vti
6377
6378 integer, intent(in) :: qunit,nXO1,nXO2,nWO,nC1,nC2
6379 double precision, intent(in) :: xO1(nXO1),xO2(nxO2)
6380 double precision, intent(in) :: dxO1(nxO1),dxO2(nxO2)
6381 double precision, intent(in) :: wO(nXO1,nXO2,nWO)
6382
6383 double precision :: origin(1:3), spacing(1:3)
6384 integer :: wholeExtent(1:6)
6385 integer :: iw
6386 integer :: ixC1,ixC2
6387
6388 integer :: filenr
6389 logical :: fileopen
6390 character (70) :: subname,wname,vname,nameL,nameS
6391 character (len=std_len) :: filename
6392 logical :: sph_datres_no_doppler
6393
6394
6395 origin(1)=xo1(1)-0.5d0*dxo1(1)
6396 origin(2)=xo2(1)-0.5d0*dxo2(1)
6397 origin(3)=zero
6398 spacing(1)=dxo1(1)
6399 spacing(2)=dxo2(1)
6400 spacing(3)=one
6401 wholeextent=0
6402 wholeextent(2)=nxo1
6403 wholeextent(4)=nxo2
6404 sph_datres_no_doppler=dat_resolution .and. coordinate==spherical .and. trim(ray_method_active)=='spherical'
6405
6406 if (mype==0) then
6407 inquire(qunit,opened=fileopen)
6408 if(.not.fileopen)then
6409 ! generate filename
6410 filenr=snapshotini
6411 if (autoconvert) filenr=snapshotnext
6412 if (convert_type=='EIvtiCCmpi') then
6413 write(filename,'(a,i4.4,a)') trim(filename_euv),filenr,".vti"
6414 else if (convert_type=='SIvtiCCmpi') then
6415 write(filename,'(a,i4.4,a)') trim(filename_sxr),filenr,".vti"
6416 else if (convert_type=='WIvtiCCmpi') then
6417 write(filename,'(a,i4.4,a)') trim(filename_whitelight),filenr,".vti"
6418 else if (convert_type=='ESvtiCCmpi') then
6419 write(filename,'(a,i4.4,a)') trim(filename_spectrum),filenr,".vti"
6420 endif
6421 open(qunit,file=filename,status='unknown',form='formatted')
6422 endif
6423
6424 ! generate xml header
6425 write(qunit,'(a)')'<?xml version="1.0"?>'
6426 write(qunit,'(a)',advance='no') '<VTKFile type="ImageData"'
6427 write(qunit,'(a)')' version="0.1" byte_order="LittleEndian">'
6428 write(qunit,'(a,3(1pe14.6),a,6(i10),a,3(1pe14.6),a)')' <ImageData Origin="',&
6429 origin,'" WholeExtent="',wholeextent,'" Spacing="',spacing,'">'
6430 ! file info
6431 write(qunit,'(a)')'<FieldData>'
6432 write(qunit,'(2a)')'<DataArray type="Float32" Name="TIME" ',&
6433 'NumberOfTuples="1" format="ascii">'
6434 write(qunit,*) real(global_time*time_convert_factor)
6435 write(qunit,'(a)')'</DataArray>'
6436 write(qunit,'(a)')'</FieldData>'
6437 ! pixel/cell data
6438 write(qunit,'(a,6(i10),a)') '<Piece Extent="',wholeextent,'">'
6439 write(qunit,'(a)')'<CellData>'
6440 do iw=1,nwo
6441 ! variable name
6442 if (convert_type=='EIvtiCCmpi') then
6443 if (wavelength<100) then
6444 write(vname,'(a,i2)') "AIA",wavelength
6445 else if (wavelength<1000) then
6446 write(vname,'(a,i3)') "AIA",wavelength
6447 else
6448 write(vname,'(a,i4)') "IRIS",wavelength
6449 endif
6450 if (trim(emission_model)=='pseudo_current' .and. iw==1) vname='pseudo_current'
6451 if (trim(emission_model)=='radio_ff' .and. iw==1) vname='radio_brightness_temperature'
6452 if (trim(radiation_transfer)=='thick' .and. iw==1) vname=trim(vname)//'_thick'
6453 if (iw==2 .and. dat_resolution .and. (.not. sph_datres_no_doppler) .and. &
6454 trim(emission_model)/='radio_ff' .and. &
6455 trim(emission_model)/='pseudo_current') vname='Doppler_velocity'
6456 if (output_tau .and. trim(radiation_transfer)=='thick' .and. &
6457 ((trim(emission_model)=='radio_ff' .and. iw==2) .or. &
6458 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6459 ((dat_resolution .and. ((sph_datres_no_doppler .and. iw==2) .or. &
6460 ((.not. sph_datres_no_doppler) .and. iw==3))) .or. &
6461 ((.not. dat_resolution) .and. iw==2))))) then
6462 vname='tau'
6463 endif
6464 if (output_absorption_fraction .and. trim(radiation_transfer)=='thick' .and. &
6465 ((trim(emission_model)=='radio_ff' .and. ((output_tau .and. iw==3) .or. &
6466 ((.not. output_tau) .and. iw==2))) .or. &
6467 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6468 ((dat_resolution .and. sph_datres_no_doppler .and. output_tau .and. iw==3) .or. &
6469 (dat_resolution .and. sph_datres_no_doppler .and. (.not. output_tau) .and. iw==2) .or. &
6470 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. output_tau .and. iw==4) .or. &
6471 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. (.not. output_tau) .and. iw==3) .or. &
6472 ((.not. dat_resolution) .and. output_tau .and. iw==3) .or. &
6473 ((.not. dat_resolution) .and. (.not. output_tau) .and. iw==2))))) then
6474 vname='absorption_fraction'
6475 endif
6476 else if (convert_type=='SIvtiCCmpi') then
6477 if (emin_sxr<10 .and. emax_sxr<10) then
6478 write(vname,'(a,i1,a,i1,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6479 else if (emin_sxr<10 .and. emax_sxr>=10) then
6480 write(vname,'(a,i1,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6481 else
6482 write(vname,'(a,i2,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6483 endif
6484 else if (convert_type=='WIvtiCCmpi') then
6485 if (iw==1) write(vname,'(a)')'B'
6486 if (iw==2) write(vname,'(a)')'pB'
6487 else if (convert_type=='ESvtiCCmpi') then
6488 if (spectrum_wl==1354) then
6489 write(vname,'(a,i4)') "SG",spectrum_wl
6490 else
6491 write(vname,'(a,i3)') "EIS",spectrum_wl
6492 endif
6493 endif
6494 write(qunit,'(a,a,a)')&
6495 '<DataArray type="Float64" Name="',trim(vname),'" format="ascii">'
6496 write(qunit,'(200(1pe14.6))') ((wo(ixc1,ixc2,iw),ixc1=1,nxo1),ixc2=1,nxo2)
6497 write(qunit,'(a)')'</DataArray>'
6498 enddo
6499 write(qunit,'(a)')'</CellData>'
6500 write(qunit,'(a)')'</Piece>'
6501 ! end
6502 write(qunit,'(a)')'</ImageData>'
6503 write(qunit,'(a)')'</VTKFile>'
6504 close(qunit)
6505 endif
6506
6507 end subroutine write_image_vticc
6508
6509 subroutine write_image_vtucc(qunit,xC,wC,dxC,nPiece,nC1,nC2,nWC,datatype)
6510 ! write image data to vtu
6512
6513 integer, intent(in) :: qunit
6514 integer, intent(in) :: nPiece,nC1,nC2,nWC
6515 double precision, intent(in) :: xC(nPiece,nC1,nC2,2),dxC(nPiece,nc1,nc2,2)
6516 double precision, intent(in) :: wC(nPiece,nC1,nC2,nWC)
6517 character(20), intent(in) :: datatype
6518
6519 integer :: nP1,nP2
6520 double precision :: xP(nPiece,nC1+1,nC2+1,2)
6521 integer :: filenr
6522 logical :: fileopen
6523 character (70) :: subname,wname,vname,nameL,nameS
6524 character (len=std_len) :: filename
6525 integer :: ixC1,ixC2,ixP,ix1,ix2,j
6526 integer :: nc,np,icel,VTK_type
6527 logical :: sph_datres_no_doppler
6528
6529 np1=nc1+1
6530 np2=nc2+1
6531 np=np1*np2
6532 nc=nc1*nc2
6533 sph_datres_no_doppler=dat_resolution .and. coordinate==spherical .and. trim(ray_method_active)=='spherical'
6534 ! cell corner location
6535 do ixp=1,npiece
6536 do ix1=1,np1
6537 do ix2=1,np2
6538 if (ix1<np1) xp(ixp,ix1,ix2,1)=xc(ixp,ix1,1,1)-0.5d0*dxc(ixp,ix1,1,1)
6539 if (ix1==np1) xp(ixp,ix1,ix2,1)=xc(ixp,ix1-1,1,1)+0.5d0*dxc(ixp,ix1-1,1,1)
6540 if (ix2<np2) xp(ixp,ix1,ix2,2)=xc(ixp,1,ix2,2)-0.5d0*dxc(ixp,1,ix2,2)
6541 if (ix2==np2) xp(ixp,ix1,ix2,2)=xc(ixp,1,ix2-1,2)+0.5d0*dxc(ixp,1,ix2-1,2)
6542 enddo
6543 enddo
6544 enddo
6545 if (mype==0) then
6546 inquire(qunit,opened=fileopen)
6547 if(.not.fileopen)then
6548 ! generate filename
6549 filenr=snapshotini
6550 if (autoconvert) filenr=snapshotnext
6551 if (datatype=='image_euv') then
6552 write(filename,'(a,i4.4,a)') trim(filename_euv),filenr,".vtu"
6553 else if (datatype=='image_sxr') then
6554 write(filename,'(a,i4.4,a)') trim(filename_sxr),filenr,".vtu"
6555 else if (datatype=='image_whitelight') then
6556 write(filename,'(a,i4.4,a)') trim(filename_whitelight),filenr,".vtu"
6557 else if (datatype=='spectrum_euv') then
6558 write(filename,'(a,i4.4,a)') trim(filename_spectrum),filenr,".vtu"
6559 endif
6560 open(qunit,file=filename,status='unknown',form='formatted')
6561 endif
6562 ! generate xml header
6563 write(qunit,'(a)')'<?xml version="1.0"?>'
6564 write(qunit,'(a)',advance='no') '<VTKFile type="UnstructuredGrid"'
6565 write(qunit,'(a)')' version="0.1" byte_order="LittleEndian">'
6566 write(qunit,'(a)')'<UnstructuredGrid>'
6567 write(qunit,'(a)')'<FieldData>'
6568 write(qunit,'(2a)')'<DataArray type="Float32" Name="TIME" ',&
6569 'NumberOfTuples="1" format="ascii">'
6570 write(qunit,*) real(global_time*time_convert_factor)
6571 write(qunit,'(a)')'</DataArray>'
6572 write(qunit,'(a)')'</FieldData>'
6573 do ixp=1,npiece
6574 write(qunit,'(a,i7,a,i7,a)') &
6575 '<Piece NumberOfPoints="',np,'" NumberOfCells="',nc,'">'
6576 write(qunit,'(a)')'<CellData>'
6577 do j=1,nwc
6578 if (datatype=='image_euv') then
6579 if (j==1) then
6580 if (wavelength<100) then
6581 write(vname,'(a,i2)') "AIA",wavelength
6582 else if (wavelength<1000) then
6583 write(vname,'(a,i3)') "AIA",wavelength
6584 else
6585 write(vname,'(a,i4)') "IRIS",wavelength
6586 endif
6587 if (trim(emission_model)=='pseudo_current') vname='pseudo_current'
6588 if (trim(emission_model)=='radio_ff') vname='radio_brightness_temperature'
6589 if (trim(radiation_transfer)=='thick') vname=trim(vname)//'_thick'
6590 endif
6591 if (j==2 .and. dat_resolution .and. (.not. sph_datres_no_doppler) .and. &
6592 trim(emission_model)/='radio_ff' .and. &
6593 trim(emission_model)/='pseudo_current') vname='Doppler_velocity'
6594 if (output_tau .and. trim(radiation_transfer)=='thick' .and. &
6595 ((trim(emission_model)=='radio_ff' .and. j==2) .or. &
6596 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6597 ((dat_resolution .and. ((sph_datres_no_doppler .and. j==2) .or. &
6598 ((.not. sph_datres_no_doppler) .and. j==3))) .or. &
6599 ((.not. dat_resolution) .and. j==2))))) then
6600 vname='tau'
6601 endif
6602 if (output_absorption_fraction .and. trim(radiation_transfer)=='thick' .and. &
6603 ((trim(emission_model)=='radio_ff' .and. ((output_tau .and. j==3) .or. &
6604 ((.not. output_tau) .and. j==2))) .or. &
6605 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6606 ((dat_resolution .and. sph_datres_no_doppler .and. output_tau .and. j==3) .or. &
6607 (dat_resolution .and. sph_datres_no_doppler .and. (.not. output_tau) .and. j==2) .or. &
6608 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. output_tau .and. j==4) .or. &
6609 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. (.not. output_tau) .and. j==3) .or. &
6610 ((.not. dat_resolution) .and. output_tau .and. j==3) .or. &
6611 ((.not. dat_resolution) .and. (.not. output_tau) .and. j==2))))) then
6612 vname='absorption_fraction'
6613 endif
6614 else if (datatype=='image_sxr') then
6615 if (emin_sxr<10 .and. emax_sxr<10) then
6616 write(vname,'(a,i1,a,i1,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6617 else if (emin_sxr<10 .and. emax_sxr>=10) then
6618 write(vname,'(a,i1,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6619 else
6620 write(vname,'(a,i2,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6621 endif
6622 else if (datatype=='image_whitelight') then
6623 write(vname,'(a)')'whitelight'
6624 else if (datatype=='spectrum_euv') then
6625 if (spectrum_wl==1354) then
6626 write(vname,'(a,i4)') "SG",spectrum_wl
6627 else
6628 write(vname,'(a,i3)') "EIS",spectrum_wl
6629 endif
6630 endif
6631 write(qunit,'(a,a,a)')&
6632 '<DataArray type="Float64" Name="',trim(vname),'" format="ascii">'
6633 write(qunit,'(200(1pe14.6))') ((wc(ixp,ixc1,ixc2,j),ixc1=1,nc1),ixc2=1,nc2)
6634 write(qunit,'(a)')'</DataArray>'
6635 enddo
6636 write(qunit,'(a)')'</CellData>'
6637 write(qunit,'(a)')'<Points>'
6638 write(qunit,'(a)')'<DataArray type="Float32" NumberOfComponents="3" format="ascii">'
6639 do ix2=1,np2
6640 do ix1=1,np1
6641 if (datatype=='image_euv' .and. dat_resolution) then
6642 if (los_phi==0 .and. los_theta==90) then
6643 write(qunit,'(3(1pe14.6))') 0.d0,xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2)
6644 else if (los_phi==90 .and. los_theta==90) then
6645 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,2),0.d0,xp(ixp,ix1,ix2,1)
6646 else
6647 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2),0.d0
6648 endif
6649 else if (datatype=='image_sxr' .and. dat_resolution) then
6650 if (los_phi==0 .and. los_theta==90) then
6651 write(qunit,'(3(1pe14.6))') 0.d0,xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2)
6652 else if (los_phi==90 .and. los_theta==90) then
6653 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,2),0.d0,xp(ixp,ix1,ix2,1)
6654 else
6655 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2),0.d0
6656 endif
6657 else
6658 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2),0.d0
6659 endif
6660 enddo
6661 enddo
6662 write(qunit,'(a)')'</DataArray>'
6663 write(qunit,'(a)')'</Points>'
6664 ! connetivity part
6665 write(qunit,'(a)')'<Cells>'
6666 write(qunit,'(a)')'<DataArray type="Int32" Name="connectivity" format="ascii">'
6667 do ix2=1,nc2
6668 do ix1=1,nc1
6669 write(qunit,'(4(i7))') ix1-1+(ix2-1)*np1,ix1+(ix2-1)*np1,&
6670 ix1-1+ix2*np1,ix1+ix2*np1
6671 enddo
6672 enddo
6673 write(qunit,'(a)')'</DataArray>'
6674 ! offsets data array
6675 write(qunit,'(a)')'<DataArray type="Int32" Name="offsets" format="ascii">'
6676 do icel=1,nc
6677 write(qunit,'(i7)') icel*(2**2)
6678 enddo
6679 write(qunit,'(a)')'</DataArray>'
6680 ! VTK cell type data array
6681 write(qunit,'(a)')'<DataArray type="Int32" Name="types" format="ascii">'
6682 ! VTK_LINE=3; VTK_PIXEL=8; VTK_VOXEL=11 -> vtk-syntax
6683 vtk_type=8
6684 do icel=1,nc
6685 write(qunit,'(i2)') vtk_type
6686 enddo
6687 write(qunit,'(a)')'</DataArray>'
6688 write(qunit,'(a)')'</Cells>'
6689 write(qunit,'(a)')'</Piece>'
6690 enddo
6691 write(qunit,'(a)')'</UnstructuredGrid>'
6692 write(qunit,'(a)')'</VTKFile>'
6693 close(qunit)
6694 endif
6695 end subroutine write_image_vtucc
6696
6697 subroutine dot_product_loc(vec1,vec2,res)
6698 double precision, intent(in) :: vec1(1:3),vec2(1:3)
6699 double precision, intent(out) :: res
6700
6701 res=vec1(1)*vec2(1)+vec1(2)*vec2(2)+vec1(3)*vec2(3)
6702
6703 end subroutine dot_product_loc
6704
6705 subroutine cross_product_loc(vec_in1,vec_in2,vec_out)
6706 double precision, intent(in) :: vec_in1(1:3),vec_in2(1:3)
6707 double precision, intent(out) :: vec_out(1:3)
6708
6709 vec_out(1)=vec_in1(2)*vec_in2(3)-vec_in1(3)*vec_in2(2)
6710 vec_out(2)=vec_in1(3)*vec_in2(1)-vec_in1(1)*vec_in2(3)
6711 vec_out(3)=vec_in1(1)*vec_in2(2)-vec_in1(2)*vec_in2(1)
6712
6713 end subroutine cross_product_loc
6714
6716 integer :: j
6717 double precision :: LOS_psi
6718 double precision :: vec_car(1:3),vec_z(1:3),vec_temp1(1:3),vec_temp2(1:3)
6719 double precision :: vec_LOS_sph(1:3),vec_xI1_sph(1:3),vec_xI2_sph(1:3)
6720
6721 ! antiparallel to LOS in spherical
6722 vec_los(1)=1.d0
6723 vec_los(2)=dpi*los_theta/180.d0
6724 vec_los(3)=dpi*los_phi/180.d0
6725 ! LOS in cartesian
6726 call spherical_to_cartesian(vec_los,vec_car)
6727 vec_los=-vec_car
6728
6729 ! theta=0 in cartesian
6730 vec_z(:)=zero
6731 vec_z(3)=1.d0
6732
6733 ! x direction for image
6734 if (los_theta==zero) then
6735 vec_temp1(1)=1.d0
6736 vec_temp1(2)=dpi/2.d0
6737 vec_temp1(3)=dpi*los_phi/180.d0
6738 call spherical_to_cartesian(vec_temp1,vec_car)
6739 vec_temp1=-vec_car
6740 call cross_product_loc(vec_temp1,vec_z,vec_xi1)
6741 else
6743 endif
6744
6745 ! y direction for image
6747
6748 ! rotate the image
6749 vec_temp1=vec_xi1/sqrt(vec_xi1(1)**2+vec_xi1(2)**2+vec_xi1(3)**2)
6750 vec_temp2=vec_xi2/sqrt(vec_xi2(1)**2+vec_xi2(2)**2+vec_xi2(3)**2)
6751 los_psi=dpi*image_rotate/180.d0
6752 vec_xi1=vec_temp1*cos(los_psi)-vec_temp2*sin(los_psi)
6753 vec_xi2=vec_temp2*cos(los_psi)+vec_temp1*sin(los_psi)
6754
6755 do j=1,3
6756 if (abs(vec_los(j))<smalldouble) vec_los(j)=zero
6757 if (abs(vec_xi1(j))<smalldouble) vec_xi1(j)=zero
6758 if (abs(vec_xi2(j))<smalldouble) vec_xi2(j)=zero
6759 enddo
6760
6761 call cartesian_to_spherical(vec_los,vec_los_sph)
6762 call cartesian_to_spherical(vec_xi1,vec_xi1_sph)
6763 call cartesian_to_spherical(vec_xi2,vec_xi2_sph)
6764 vec_los_sph(2:3)=vec_los_sph(2:3)*180.d0/dpi
6765 vec_xi1_sph(2:3)=vec_xi1_sph(2:3)*180.d0/dpi
6766 vec_xi2_sph(2:3)=vec_xi2_sph(2:3)*180.d0/dpi
6767
6768 if (mype==0) write(*,'(a,f3.1,f6.1,f6.1,a)') ' ray direction (spherical): [',vec_los_sph(1),vec_los_sph(2),vec_los_sph(3),']'
6769 if (mype==0) write(*,'(a,f3.1,f6.1,f6.1,a)') ' xI1 direction (spherical): [',vec_xi1_sph(1),vec_xi1_sph(2),vec_xi1_sph(3),']'
6770 if (mype==0) write(*,'(a,f3.1,f6.1,f6.1,a)') ' xI2 direction (spherical): [',vec_xi2_sph(1),vec_xi2_sph(2),vec_xi2_sph(3),']'
6771
6772 end subroutine init_vectors_spherical
6773
6774 subroutine spherical_to_cartesian(vec_sph,vec_car)
6775 ! angles in rad
6776 double precision, intent(in) :: vec_sph(1:3)
6777 double precision, intent(inout) :: vec_car(1:3)
6778
6779 vec_car(1)=vec_sph(1)*dsin(vec_sph(2))*dcos(vec_sph(3))
6780 vec_car(2)=vec_sph(1)*dsin(vec_sph(2))*dsin(vec_sph(3))
6781 vec_car(3)=vec_sph(1)*dcos(vec_sph(2))
6782
6783 end subroutine spherical_to_cartesian
6784
6785 subroutine cartesian_to_spherical(vec_car,vec_sph)
6786 ! angles in rad
6787 double precision, intent(in) :: vec_car(1:3)
6788 double precision, intent(inout) :: vec_sph(1:3)
6789
6790 vec_sph(1)=dsqrt(vec_car(1)**2+vec_car(2)**2+vec_car(3)**2)
6791 vec_sph(2)=dacos(vec_car(3)/vec_sph(1))
6792 vec_sph(3)=atan2(vec_car(2),vec_car(1))
6793
6794 end subroutine cartesian_to_spherical
6795
6797 integer :: j
6798 double precision :: LOS_psi
6799 double precision :: vec_z(1:3),vec_temp1(1:3),vec_temp2(1:3)
6800
6801 ! vectors for image coordinate
6802 vec_los(1)=-cos(dpi*los_phi/180.d0)*sin(dpi*los_theta/180.d0)
6803 vec_los(2)=-sin(dpi*los_phi/180.d0)*sin(dpi*los_theta/180.d0)
6804 vec_los(3)=-cos(dpi*los_theta/180.d0)
6805 do j=1,3
6806 if (abs(vec_los(j))<=smalldouble) vec_los(j)=zero
6807 enddo
6808 vec_z(:)=zero
6809 vec_z(3)=1.d0
6810 if (los_theta==zero) then
6811 vec_xi1(1)=cos(dpi*los_phi/180.d0)
6812 vec_xi1(2)=sin(dpi*los_phi/180.d0)
6813 vec_xi1(3)=zero
6814 else
6816 endif
6818 vec_temp1=vec_xi1/sqrt(vec_xi1(1)**2+vec_xi1(2)**2+vec_xi1(3)**2)
6819 vec_temp2=vec_xi2/sqrt(vec_xi2(1)**2+vec_xi2(2)**2+vec_xi2(3)**2)
6820 los_psi=dpi*image_rotate/180.d0
6821 vec_xi1=vec_temp1*cos(los_psi)-vec_temp2*sin(los_psi)
6822 vec_xi2=vec_temp2*cos(los_psi)+vec_temp1*sin(los_psi)
6823
6824 do j=1,3
6825 if (abs(vec_xi1(j))<smalldouble) vec_xi1(j)=zero
6826 if (abs(vec_xi2(j))<smalldouble) vec_xi2(j)=zero
6827 enddo
6828
6829 if (mype==0) write(*,'(a,f5.2,f6.2,f6.2,a)') ' LOS vector: [',vec_los(1),vec_los(2),vec_los(3),']'
6830 if (mype==0) write(*,'(a,f5.2,f6.2,f6.2,a)') ' xI1 vector: [',vec_xi1(1),vec_xi1(2),vec_xi1(3),']'
6831 if (mype==0) write(*,'(a,f5.2,f6.2,f6.2,a)') ' xI2 vector: [',vec_xi2(1),vec_xi2(2),vec_xi2(3),']'
6832
6833 end subroutine init_vectors_cartesian
6834
6835 subroutine get_cor_image_spherical(x_3D_sph,x_image)
6836 double precision, intent(in) :: x_3D_sph(1:3)
6837 double precision, intent(inout) :: x_image(1:2)
6838 double precision :: res,res_origin
6839 double precision :: x_3D(1:3)
6840
6841 call spherical_to_cartesian(x_3d_sph,x_3d)
6842 call dot_product_loc(x_3d,vec_xi1,res)
6843 x_image(1)=res
6844 call dot_product_loc(x_3d,vec_xi2,res)
6845 x_image(2)=res
6846
6847 end subroutine get_cor_image_spherical
6848
6849 subroutine get_cor_image(x_3D,x_image)
6850 double precision, intent(in) :: x_3D(1:3)
6851 double precision, intent(inout) :: x_image(1:2)
6852 double precision :: res,res_origin
6853
6854 call dot_product_loc(x_3d,vec_xi1,res)
6855 call dot_product_loc(x_origin,vec_xi1,res_origin)
6856 x_image(1)=res-res_origin
6857 call dot_product_loc(x_3d,vec_xi2,res)
6858 call dot_product_loc(x_origin,vec_xi2,res_origin)
6859 x_image(2)=res-res_origin
6860
6861 end subroutine get_cor_image
6862
6863end module mod_thermal_emission
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module for physical and numeric constants.
double precision, parameter const_rsun
double precision, parameter kb_cgs
Boltzmann constant in cgs.
double precision, parameter half
double precision, parameter one
double precision, parameter dpi
Pi.
double precision, parameter zero
some frequently used numbers
double precision, parameter smalldouble
double precision, parameter mp_cgs
Proton mass in cgs.
double precision, parameter const_c
universal constants as specified in cgs units
Equation of state for AMRVAC, handled through a single eos_container object.
Definition mod_eos.t:30
Module with geometry-related routines (e.g., divergence, curl)
Definition mod_geometry.t:2
integer coordinate
Definition mod_geometry.t:7
integer, parameter spherical
integer, parameter cartesian
Definition mod_geometry.t:8
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
character(len=std_len) filename_sxr
Base file name for synthetic SXR emission output.
integer spectrum_wl
wave length for spectrum
integer ixghi
Upper index of grid block arrays.
logical activate_unit_arcsec
use arcsec as length unit of images/spectra
character(len=std_len) filename_spectrum
Base file name for synthetic EUV spectrum output.
double precision global_time
The global simulation time.
logical output_absorption_fraction
output absorption fraction for thick/thin EUV synthesis when available
double precision radio_beam_fwhm
Gaussian radio beam full width at half maximum in arcsec.
integer snapshotini
Resume from the snapshot with this index.
character(len=std_len) filename_euv
Base file name for synthetic EUV emission output.
logical instrument_postprocess
Post-process dat-resolution EUV images onto the instrument pixel grid.
character(len=std_len) filename_whitelight
Base file name for synthetic white light.
character(len=std_len) convert_type
Which format to use when converting.
double precision unit_length
Physical scaling factor for length.
double precision location_slit
location of the slit
double precision time_convert_factor
Conversion factor for time unit.
integer icomm
The MPI communicator.
character(len=std_len) whitelight_instrument
white light observation instrument
integer mype
The rank of the current MPI task.
double precision radio_frequency
Observing frequency for radio free-free synthesis in Hz.
integer ierrmpi
A global MPI error return code.
logical autoconvert
If true, already convert to output format during the run.
double precision, dimension(:), allocatable, parameter d
logical slab
Cartesian geometry or not.
double precision radio_beam_pixel_size
Output pixel size for radio beam post-processing in arcsec; <=0 uses FWHM/3.
integer snapshotnext
IO: snapshot and collapsed views output numbers/labels.
logical dat_resolution
resolution of the images
double precision r_occultor
the white light emission below it (unit=Rsun) is not visible
integer, dimension(ndim) nstretchedblocks_baselevel
(even) number of (symmetrically) stretched blocks at AMR level 1, per dimension
integer npe
The number of MPI tasks.
logical output_tau
output optical-depth map for synthetic emission when available
double precision, dimension(^nd) qstretch_baselevel
stretch factor between cells at AMR level 1, per dimension
double precision unit_velocity
Physical scaling factor for velocity.
integer radsyn_segment_batch_factor
Maximum ray segments per pixel batch, as a factor of radsyn_pixel_batch; <=0 uses memory budget....
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision unit_temperature
Physical scaling factor for temperature.
logical si_unit
Use SI units (.true.) or use cgs units (.false.)
double precision los_theta
direction of the line of sight (LOS)
character(len=std_len) radiation_transfer
Synthetic emission transfer mode: thin or thick.
double precision spectrum_window_max
integer wavelength
wavelength for output
integer, dimension(ndim) stretch_type
What kind of stretching is used per dimension.
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
integer radsyn_pixel_batch
Number of image pixels processed in one ray-segment MPI batch.
logical radsyn_verbose
Print synthetic-emission ray-tracing profiling counters.
double precision instrument_resolution_factor
times for enhancing spatial resolution for EUV image/spectra
double precision radsyn_segment_memory_mb
Approximate per-rank temporary memory budget, in MiB, for automatic ray-segment batch sizing.
double precision spectrum_window_min
spectral window
integer refine_max_level
Maximal number of AMR levels.
character(len=std_len) ray_method
Synthetic emission ray traversal method.
integer direction_slit
direction of the slit (for dat resolution only)
double precision, dimension(1:3) x_origin
where the is the origin (X=0,Y=0) of image
character(len=std_len) emission_model
Synthetic emission physical model selector.
integer, dimension(:,:), allocatable node
integer radsyn_segment_comm_factor
Maximum ray segments per segmented MPI all-to-all round, as a factor of radsyn_pixel_batch.
integer, parameter ixglo
Lower index of grid block arrays (always 1)
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
double precision, dimension(1:3) vec_los
subroutine get_goes_flux_grid(ixil, ixol, w, x, dv, xboxl, xbl, fl, eflux_grid)
subroutine integrate_spectra_cartesian(igrid, wl, dwlg, xs, dxsg, spectra, numwl, numxs, fl)
subroutine sph_cart_to_coord(pos, sph)
subroutine get_spectrum_datresol(qunit, datatype, fl)
double precision, dimension(1:101) f_304
subroutine get_sph_intersection_datresol_spacing(dxi)
double precision, dimension(1:101) f_193
double precision, dimension(1:60) f_264
subroutine normalize_euv_doppler(ni1, ni2, euv, dpl, unitv)
subroutine get_sph_intersection_image_bounds(ximin1, ximax1, ximin2, ximax2)
double precision, dimension(1:60) f_263
integer function sph_locate_index(value, faces, imin, imax)
subroutine get_euv_image(qunit, fl)
double precision, dimension(1:60) t_eis1
subroutine postprocess_radio_beam_image(nsrc1, nsrc2, xsrc1, xsrc2, dxsrc1, dxsrc2, bright, nout1, nout2, xout1, xout2, dxout1, dxout2, wout, numwout, tau, brightthin)
subroutine get_sxr(ixil, ixol, w, x, fl, flux, el, eu)
integer function radsyn_euv_num_outputs(has_doppler, has_thick)
subroutine collect_euv_cart_dda_segments(ixil, ixol, source, opacity, sourcev, pixel_id, ray_origin, xface1, xface2, xface3, t_enter, t_exit, segments, nseg, capacity)
subroutine get_unit_vector_spherical(x_sph, unitv_r, unitv_theta, unitv_phi)
subroutine collect_euv_sph_intersection_segments(ixil, ixol, source, opacity, pixel_id, ray_origin, ximg1, ximg2, rface, thetaface, phiface, rface2, theta_cos, phi_sin, phi_cos, segments, nseg, capacity)
double precision, dimension(1:101) f_131
recursive subroutine quicksort_segment_indices(segments, idx, ilo, ihi)
subroutine get_line_info(wl, ion, mass, logte, line_center, spatial_px, spectral_px, sigma_psf, width_slit)
double precision, dimension(1:60) f_255
subroutine sph_block_pixel_range(rface, thetaface, phiface, ixol, nxi1, nxi2, xi1, xi2, dxi, ixpmin1, ixpmax1, ixpmin2, ixpmax2, has_pixels)
subroutine cart_dda_advance_axis(ray_origin_axis, ray_dir_axis, faces, imin, imax, idx, step, tmax, done)
subroutine get_pseudo_current(igrid, ixil, ixol, w, source)
logical function segment_is_valid(segments, is, nvars)
double precision function transfer_attenuation(tau)
double precision, dimension(1:101) t_aia
double precision function exp_clamped(argument)
subroutine write_image_vtucc(qunit, xc, wc, dxc, npiece, nc1, nc2, nwc, datatype)
logical function sph_segment_visible(pos, ximg1, ximg2)
subroutine get_cor_image(x_3d, x_image)
subroutine get_thomson_parameters(rl, a, b, c, d)
subroutine integrate_euv_datresol(igrid, nxif1, nxif2, xif1, xif2, dxif1, dxif2, fl, euv, dpl)
subroutine cart_dda_block_pixel_range(box_min, box_max, nxif1, nxif2, xif1, xif2, ixpmin1, ixpmax1, ixpmin2, ixpmax2, has_pixels)
subroutine sph_add_t_fixed(tvals, nt, t)
double precision, dimension(1:60) t_eis2
subroutine sph_add_theta_intersections(ray_origin, ray_dir, thetaface, tvals, nt, capacity)
subroutine integrate_euv_cart_dda_thick_datresol(nxif1, nxif2, xif1, xif2, fl, euv, dpl, tau, euvthin)
double precision, dimension(1:101) f_171
double precision, dimension(1:101) f_94
subroutine integrate_spectra_datresol(igrid, wl, dwl, spectra, numwl, numxs, dir_loc, fl)
subroutine acc_euv_cart_dda(ixil, ixol, source, sourcev, ray_origin, xface1, xface2, xface3, t_enter, t_exit, euvp, dplp)
subroutine sph_add_phi_intersection(ray_origin, ray_dir, phiface, tvals, nt, capacity)
double precision, dimension(1:3) vec_xi1
subroutine append_cart_dda_segment(segments, nseg, capacity, pixel_id, tseg, jds, kds, jvds)
subroutine radsyn_get_segment_batch_limits(pixel_batch_target, segment_batch_target, segment_comm_target)
subroutine get_spectrum(qunit, datatype, fl)
subroutine ray_box_intersection_cart(ray_origin, ray_dir, box_min, box_max, hit, t_enter, t_exit)
subroutine cartesian_to_spherical(vec_car, vec_sph)
subroutine get_cor_image_spherical(x_3d_sph, x_image)
subroutine dot_product_loc(vec1, vec2, res)
subroutine integrate_emission_spherical(igrid, numxi1, numxi2, xi1, xi2, dxi, fl, datatype, em)
subroutine get_image(qunit, datatype, fl)
subroutine integrate_emission_cartesian(igrid, numxi1, numxi2, xi1, xi2, dxi, fl, datatype, em)
logical function radsyn_euv_has_doppler_output()
integer function sph_locate_index_desc(value, faces, imin, imax)
subroutine insertion_sort_segment_indices(segments, idx, ilo, ihi)
subroutine write_image_vticc(qunit, xo1, xo2, dxo1, dxo2, wo, nxo1, nxo2, nwo, nc1, nc2)
subroutine get_sxr_image(qunit, fl)
subroutine check_synthetic_emission_options(datatype)
subroutine fill_euv_absorption_fraction(ni1, ni2, euv, euvthin, smallflux, absorption, cap_to_one)
subroutine sph_sort_unique_t(tvals, nt)
double precision, dimension(1:60) f_192
subroutine sort_segment_indices_near_to_far(segments, idx, nidx)
integer function cart_dda_locate_index(pos, faces, imin, imax)
subroutine pack_euv_image_outputs(ni1, ni2, euv, wi, smallflux, has_doppler, has_thick, dpl, tau, euvthin, cap_absorption)
integer function segment_pixel_owner(pixel_id)
subroutine get_whitelight_thomson(rl, rin, ne, a, b, c, d, fluxtb, fluxpb)
subroutine get_image_datresol(qunit, datatype, fl)
subroutine collect_euv_sph_dda_interval(ixil, ixol, source, opacity, pixel_id, ray_origin, ximg1, ximg2, rface2, theta_cos, phiface, phi_sin, phi_cos, t_enter, t_exit, segments, nseg, capacity, ok)
subroutine get_goes_sxr_flux(xboxl, fl, eflux)
double precision function interpolate_response_value(temperature, t_table, f_table, n_table, log_temperature, log_response)
subroutine integrate_whitelight_spherical(igrid, numxi1, numxi2, numwi, xi1, xi2, dxi, fl, datatype, wlb)
double precision, dimension(1:3) vec_xi2
double precision, dimension(1:41) f_1354
subroutine cross_product_loc(vec_in1, vec_in2, vec_out)
character(len=std_len) ray_method_active
subroutine integrate_sxr_datresol(igrid, nxif1, nxif2, xif1, xif2, dxif1, dxif2, fl, sxr)
subroutine apply_temperature_response(ixil, ixol, te, flux, t_table, f_table, n_table, log_temperature, log_response)
double precision, dimension(1:101) f_335
subroutine sph_try_theta_exit_candidate(t, theta_face_cos, ray_origin, tnow, texit, epsray, tnext, found)
subroutine get_radio_ff_source_opacity(ixil, ixol, w, x, fl, source, kappa)
subroutine sph_next_cell_exit(ray_origin, rface2, theta_cos, phiface, phi_sin, phi_cos, ixol, ix1, ix2, ix3, tnow, texit, epsray, tnext, found)
subroutine integrate_euv_thick_datresol(nxif1, nxif2, fl, euv, dpl, tau, euvthin)
subroutine output_data(qunit, xo1, xo2, dxo1, dxo2, wo, nxo1, nxo2, nwo, datatype)
subroutine integrate_euv_sph_intersection_thick(numxi1, numxi2, xi1, xi2, dxi, fl, euv, tau, euvthin)
subroutine sph_try_phi_exit_candidate(t, phi_face_sin, phi_face_cos, ray_origin, tnow, texit, epsray, tnext, found)
double precision, dimension(1:41) t_iris
subroutine sph_locate_cell_fast(pos, rface2, theta_cos, phiface, ixol, ix1, ix2, ix3, inside)
subroutine get_euv_spectrum(qunit, fl)
double precision, dimension(1:101) f_211
subroutine build_sph_intersection_faces(ixil, ixol, x, dx, rface, thetaface, phiface)
subroutine collect_euv_sph_dda_segments(ixil, ixol, source, opacity, pixel_id, ray_origin, ximg1, ximg2, rface, thetaface, phiface, rface2, theta_cos, phi_sin, phi_cos, segments, nseg, capacity, fallback)
subroutine cart_dda_init_axis(ray_origin_axis, ray_dir_axis, faces, imin, imax, idx, step, tmax)
subroutine get_euv_hhe_opacity(wl, ixil, ixol, w, x, fl, kappa)
subroutine integrate_euv_sph_intersection_thin(numxi1, numxi2, xi1, xi2, dxi, fl, em)
subroutine integrate_euv_cart_dda_datresol(nxif1, nxif2, xif1, xif2, fl, euv, dpl)
subroutine get_whitelight_image(qunit, fl)
subroutine get_euv(wl, ixil, ixol, w, x, fl, flux)
subroutine sph_add_sphere_intersections(ray_origin, ray_dir, rface, tvals, nt, capacity)
subroutine build_cart_dda_faces(ixil, ixol, x, dx, xface1, xface2, xface3)
subroutine integrate_transfer_step_first_order(emissivity, opacity, path_length, intensity, tau)
double precision function pow10_clamped(exponent)
subroutine acc_euv_sph_intersection(ixil, ixol, source, ray_origin, ximg1, ximg2, rface, thetaface, phiface, euvp)
subroutine sph_locate_cell(pos, rface, thetaface, phiface, ixol, ix1, ix2, ix3, inside)
subroutine sph_try_exit_candidate(t, tnow, texit, epsray, tnext, found)
subroutine spherical_to_cartesian(vec_sph, vec_car)
subroutine sph_add_t(tvals, nt, capacity, t)
subroutine postprocess_euv_instrument_image(nsrc1, nsrc2, xsrc1, xsrc2, dxsrc1, dxsrc2, euv, dpl, nout1, nout2, xout1, xout2, dxout1, dxout2, wout, numwout, tau, euvthin)