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 double precision :: ray_origin(1:3),profile_local(3),profile_global(3)
5054 double precision, allocatable :: source(:^D&)
5055 double precision, allocatable :: rface(:),thetaface(:),phiface(:)
5056 logical :: has_pixels
5057
5058 profile_local=zero
5059 do iigrid=1,igridstail; igrid=igrids(iigrid);
5060 ^d&ixomin^d=ixmlo^d\
5061 ^d&ixomax^d=ixmhi^d\
5062 ^d&iximin^d=ixglo^d\
5063 ^d&iximax^d=ixghi^d\
5064
5065 allocate(source(ixi^s))
5066 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,source)
5067 source(ixo^s)=source(ixo^s)/instrument_resolution_factor**2
5068 call build_sph_intersection_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,rface,thetaface,phiface)
5069 call sph_block_pixel_range(rface,thetaface,phiface,ixo^l,numxi1,numxi2,xi1,xi2,dxi,&
5070 ixpmin1,ixpmax1,ixpmin2,ixpmax2,has_pixels)
5071 if (has_pixels) then
5072 do ixp1=ixpmin1,ixpmax1
5073 do ixp2=ixpmin2,ixpmax2
5074 ray_origin=xi1(ixp1)*vec_xi1+xi2(ixp2)*vec_xi2
5075 profile_local(1)=profile_local(1)+one
5076 call acc_euv_sph_intersection(ixi^l,ixo^l,source,ray_origin,xi1(ixp1),xi2(ixp2),&
5077 rface,thetaface,phiface,em(ixp1,ixp2))
5078 enddo
5079 enddo
5080 profile_local(2)=profile_local(2)+dble((ixpmax1-ixpmin1+1)*(ixpmax2-ixpmin2+1))
5081 endif
5082 profile_local(3)=profile_local(3)+one
5083 deallocate(source,rface,thetaface,phiface)
5084 enddo
5085 call mpi_allreduce(profile_local,profile_global,3,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5086 if (radsyn_verbose .and. mype==0) then
5087 write(*,'(a,3(es12.5,1x))') ' sph_intersection thin profile rays pixels blocks: ',profile_global
5088 endif
5090
5091 subroutine integrate_euv_sph_intersection_thick(numXI1,numXI2,xI1,xI2,dxI,fl,EUV,Tau,EUVthin)
5093
5094 integer, intent(in) :: numXI1,numXI2
5095 double precision, intent(in) :: xI1(numXI1),xI2(numXI2),dxI
5096 type(te_fluid), intent(in) :: fl
5097 double precision, intent(out) :: EUV(numXI1,numXI2),Tau(numXI1,numXI2),EUVthin(numXI1,numXI2)
5098
5099 integer, parameter :: nSegVars=5
5100 integer :: ixO^L,ixI^L,ix^D
5101 integer :: iigrid,igrid,ixP1,ixP2,ipix,ipixStart,ipixEnd,nPixBatch,pixel_id
5102 integer :: nseg,capacity,totalCount,totalSeg,ipe,is,iseg,nidx,owner,isegDest,nsegBefore
5103 integer :: ixGlobal,iyGlobal,ixPmin1,ixPmax1,ixPmin2,ixPmax2,iFirst,iLast,iLocal
5104 integer :: nPixBatchTarget
5105 integer :: maxSegBatchTarget,maxSegCommTarget,maxNsegBatch,nPixTotal
5106 integer :: maxOwnerSegCount,maxOwnerSegCountLocal,segOffset,recvFill,totalRoundCount,totalRoundSeg
5107 integer :: sphDdaFallbackLocal,sphDdaFallbackGlobal
5108 integer, allocatable :: sendCounts(:),recvCounts(:),sendDispls(:),recvDispls(:)
5109 integer, allocatable :: roundSendCounts(:),roundRecvCounts(:)
5110 integer, allocatable :: roundSendDispls(:),roundRecvDispls(:)
5111 integer, allocatable :: ownerSegCounts(:),ownerOffsets(:),idx(:)
5112 integer, allocatable :: bucketCounts(:),bucketOffsets(:),bucketFill(:)
5113 double precision :: ray_origin(1:3),atten
5114 double precision :: profile_local(5),profile_global(5),profile_batch(5)
5115 double precision :: phys_max_local(2),phys_max_global(2)
5116 double precision :: phys_sum_local(2),phys_sum_global(2),phys_sum_batch(2)
5117 double precision, allocatable :: segments(:,:),segments_send(:,:),segments_recv(:,:)
5118 double precision, allocatable :: segments_recv_round(:,:)
5119 double precision, allocatable :: image_reduce(:,:)
5120 logical :: has_pixels,batchAccepted,batchReduced,ddaFallback
5121 type(radsyn_euv_cache), allocatable :: cache(:)
5122
5123 euv=zero
5124 tau=zero
5125 euvthin=zero
5126 profile_local=zero
5127 phys_max_local=zero
5128 phys_sum_local=zero
5129 sphddafallbacklocal=0
5130 allocate(sendcounts(0:npe-1),recvcounts(0:npe-1),senddispls(0:npe-1),recvdispls(0:npe-1))
5131 allocate(roundsendcounts(0:npe-1),roundrecvcounts(0:npe-1))
5132 allocate(roundsenddispls(0:npe-1),roundrecvdispls(0:npe-1))
5133 allocate(ownersegcounts(0:npe-1),owneroffsets(0:npe-1))
5134 allocate(cache(igridstail))
5135 call radsyn_get_segment_batch_limits(npixbatchtarget,maxsegbatchtarget,maxsegcommtarget)
5136 allocate(bucketcounts(npixbatchtarget),bucketoffsets(npixbatchtarget+1),&
5137 bucketfill(npixbatchtarget))
5138
5139 do iigrid=1,igridstail; igrid=igrids(iigrid);
5140 ^d&ixomin^d=ixmlo^d\
5141 ^d&ixomax^d=ixmhi^d\
5142 ^d&iximin^d=ixglo^d\
5143 ^d&iximax^d=ixghi^d\
5144
5145 cache(iigrid)%igrid=igrid
5146 allocate(cache(iigrid)%source(ixi^s),cache(iigrid)%opacity(ixi^s))
5147 cache(iigrid)%source=zero
5148 cache(iigrid)%opacity=zero
5149 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%source)
5150 cache(iigrid)%source(ixo^s)=cache(iigrid)%source(ixo^s)/instrument_resolution_factor**2
5151 call get_euv_hhe_opacity(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,cache(iigrid)%opacity)
5152 phys_max_local(1)=max(phys_max_local(1),maxval(cache(iigrid)%source(ixo^s)))
5153 phys_max_local(2)=max(phys_max_local(2),maxval(cache(iigrid)%opacity(ixo^s)))
5154 call build_sph_intersection_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,&
5155 cache(iigrid)%rface,cache(iigrid)%thetaface,&
5156 cache(iigrid)%phiface)
5157 allocate(cache(iigrid)%rface2(ixomin1:ixomax1+1),&
5158 cache(iigrid)%theta_cos(ixomin2:ixomax2+1),&
5159 cache(iigrid)%phi_sin(ixomin3:ixomax3+1),&
5160 cache(iigrid)%phi_cos(ixomin3:ixomax3+1))
5161 cache(iigrid)%rface2=cache(iigrid)%rface**2
5162 cache(iigrid)%theta_cos=cos(cache(iigrid)%thetaface)
5163 cache(iigrid)%phi_sin=sin(cache(iigrid)%phiface)
5164 cache(iigrid)%phi_cos=cos(cache(iigrid)%phiface)
5165 call sph_block_pixel_range(cache(iigrid)%rface,cache(iigrid)%thetaface,&
5166 cache(iigrid)%phiface,ixo^l,numxi1,numxi2,xi1,xi2,dxi,&
5167 cache(iigrid)%ixPmin1,cache(iigrid)%ixPmax1,&
5168 cache(iigrid)%ixPmin2,cache(iigrid)%ixPmax2,cache(iigrid)%has_pixels)
5169 enddo
5170
5171 npixtotal=numxi1*numxi2
5172 ipixstart=1
5173 do while (ipixstart<=npixtotal)
5174 ipixend=min(numxi1*numxi2,ipixstart+npixbatchtarget-1)
5175 npixbatch=ipixend-ipixstart+1
5176 batchaccepted=.false.
5177 batchreduced=.false.
5178
5179 do while (.not. batchaccepted)
5180 nseg=0
5181 capacity=0
5182 profile_batch=zero
5183 phys_sum_batch=zero
5184
5185 do iigrid=1,igridstail; igrid=igrids(iigrid);
5186 ^d&ixomin^d=ixmlo^d\
5187 ^d&ixomax^d=ixmhi^d\
5188 ^d&iximin^d=ixglo^d\
5189 ^d&iximax^d=ixghi^d\
5190
5191 ixpmin1=cache(iigrid)%ixPmin1
5192 ixpmax1=cache(iigrid)%ixPmax1
5193 ixpmin2=cache(iigrid)%ixPmin2
5194 ixpmax2=cache(iigrid)%ixPmax2
5195 has_pixels=cache(iigrid)%has_pixels
5196 if (.not. has_pixels) cycle
5197
5198 do ixp2=ixpmin2,ixpmax2
5199 ifirst=max(ipixstart,(ixp2-1)*numxi1+ixpmin1)
5200 ilast=min(ipixend,(ixp2-1)*numxi1+ixpmax1)
5201 if (ifirst>ilast) cycle
5202 do ipix=ifirst,ilast
5203 ixp1=1+mod(ipix-1,numxi1)
5204 pixel_id=ipix
5205 ray_origin=xi1(ixp1)*vec_xi1+xi2(ixp2)*vec_xi2
5206 profile_batch(1)=profile_batch(1)+one
5207 nsegbefore=nseg
5208 if (sph_use_dda) then
5209 call collect_euv_sph_dda_segments(ixi^l,ixo^l,cache(iigrid)%source,&
5210 cache(iigrid)%opacity,pixel_id,ray_origin,xi1(ixp1),xi2(ixp2),&
5211 cache(iigrid)%rface,cache(iigrid)%thetaface,cache(iigrid)%phiface,&
5212 cache(iigrid)%rface2,cache(iigrid)%theta_cos,&
5213 cache(iigrid)%phi_sin,cache(iigrid)%phi_cos,&
5214 segments,nseg,capacity,ddafallback)
5215 if (ddafallback) sphddafallbacklocal=sphddafallbacklocal+1
5216 else
5217 call collect_euv_sph_intersection_segments(ixi^l,ixo^l,cache(iigrid)%source,&
5218 cache(iigrid)%opacity,pixel_id,ray_origin,xi1(ixp1),xi2(ixp2),&
5219 cache(iigrid)%rface,cache(iigrid)%thetaface,cache(iigrid)%phiface,&
5220 cache(iigrid)%rface2,cache(iigrid)%theta_cos,&
5221 cache(iigrid)%phi_sin,cache(iigrid)%phi_cos,&
5222 segments,nseg,capacity)
5223 endif
5224 if (nseg>nsegbefore) profile_batch(2)=profile_batch(2)+one
5225 profile_batch(3)=profile_batch(3)+dble(nseg-nsegbefore)
5226 do iseg=nsegbefore+1,nseg
5227 phys_sum_batch(1)=phys_sum_batch(1)+segments(3,iseg)
5228 phys_sum_batch(2)=phys_sum_batch(2)+segments(4,iseg)
5229 enddo
5230 enddo
5231 enddo
5232 enddo
5233
5234 call mpi_allreduce(nseg,maxnsegbatch,1,mpi_integer,mpi_max,icomm,ierrmpi)
5235 if (maxnsegbatch>maxsegbatchtarget .and. npixbatch>1) then
5236 npixbatch=max(1,npixbatch/2)
5237 ipixend=ipixstart+npixbatch-1
5238 if (allocated(segments)) deallocate(segments)
5239 batchreduced=.true.
5240 else
5241 batchaccepted=.true.
5242 endif
5243 enddo
5244
5245 profile_local=profile_local+profile_batch
5246 phys_sum_local=phys_sum_local+phys_sum_batch
5247 if (radsyn_verbose .and. mype==0 .and. batchreduced) then
5248 if (sph_use_dda) then
5249 write(*,'(a,3(i0,1x))') ' sph_dda thick adaptive batch: ',&
5250 ipixstart,ipixend,maxnsegbatch
5251 else
5252 write(*,'(a,3(i0,1x))') ' sph_intersection thick adaptive batch: ',&
5253 ipixstart,ipixend,maxnsegbatch
5254 endif
5255 endif
5256
5257 if (.not. allocated(segments)) then
5258 capacity=1
5259 allocate(segments(nsegvars,capacity))
5260 endif
5261 ownersegcounts=0
5262 do is=1,nseg
5263 owner=segment_pixel_owner(nint(segments(1,is)))
5264 ownersegcounts(owner)=ownersegcounts(owner)+1
5265 enddo
5266 sendcounts=nsegvars*ownersegcounts
5267 senddispls(0)=0
5268 do ipe=1,npe-1
5269 senddispls(ipe)=senddispls(ipe-1)+sendcounts(ipe-1)
5270 enddo
5271
5272 allocate(segments_send(nsegvars,max(1,nseg)))
5273 owneroffsets=0
5274 do is=1,nseg
5275 owner=segment_pixel_owner(nint(segments(1,is)))
5276 isegdest=senddispls(owner)/nsegvars+owneroffsets(owner)+1
5277 segments_send(:,isegdest)=segments(:,is)
5278 owneroffsets(owner)=owneroffsets(owner)+1
5279 enddo
5280
5281 call mpi_alltoall(sendcounts,1,mpi_integer,recvcounts,1,mpi_integer,icomm,ierrmpi)
5282 recvdispls(0)=0
5283 do ipe=1,npe-1
5284 recvdispls(ipe)=recvdispls(ipe-1)+recvcounts(ipe-1)
5285 enddo
5286 totalcount=sum(recvcounts)
5287 totalseg=totalcount/nsegvars
5288 profile_local(4)=profile_local(4)+dble(totalcount)
5289 allocate(segments_recv(nsegvars,max(1,totalseg)))
5290
5291 recvfill=0
5292 maxownersegcountlocal=maxval(ownersegcounts)
5293 call mpi_allreduce(maxownersegcountlocal,maxownersegcount,1,mpi_integer,mpi_max,icomm,ierrmpi)
5294 do segoffset=0,maxownersegcount-1,maxsegcommtarget
5295 roundsendcounts=0
5296 roundsenddispls=senddispls
5297 do ipe=0,npe-1
5298 if (ownersegcounts(ipe)>segoffset) then
5299 roundsendcounts(ipe)=nsegvars*min(maxsegcommtarget,ownersegcounts(ipe)-segoffset)
5300 roundsenddispls(ipe)=senddispls(ipe)+nsegvars*segoffset
5301 endif
5302 enddo
5303
5304 call mpi_alltoall(roundsendcounts,1,mpi_integer,roundrecvcounts,1,mpi_integer,icomm,ierrmpi)
5305 roundrecvdispls(0)=0
5306 do ipe=1,npe-1
5307 roundrecvdispls(ipe)=roundrecvdispls(ipe-1)+roundrecvcounts(ipe-1)
5308 enddo
5309 totalroundcount=sum(roundrecvcounts)
5310 totalroundseg=totalroundcount/nsegvars
5311 allocate(segments_recv_round(nsegvars,max(1,totalroundseg)))
5312
5313 call mpi_alltoallv(segments_send,roundsendcounts,roundsenddispls,mpi_double_precision,&
5314 segments_recv_round,roundrecvcounts,roundrecvdispls,&
5315 mpi_double_precision,icomm,ierrmpi)
5316
5317 if (totalroundseg>0) then
5318 segments_recv(:,recvfill+1:recvfill+totalroundseg)=segments_recv_round(:,1:totalroundseg)
5319 recvfill=recvfill+totalroundseg
5320 endif
5321 deallocate(segments_recv_round)
5322 enddo
5323
5324 if (recvfill/=totalseg) call mpistop("ray-segment receive mismatch")
5325
5326 if (totalseg>0) then
5327 allocate(idx(totalseg))
5328 bucketcounts(1:npixbatch)=0
5329 do is=1,totalseg
5330 if (segment_is_valid(segments_recv,is,4)) then
5331 ipix=nint(segments_recv(1,is))
5332 if (ipix>=ipixstart .and. ipix<=ipixend .and. segment_pixel_owner(ipix)==mype) then
5333 ilocal=ipix-ipixstart+1
5334 bucketcounts(ilocal)=bucketcounts(ilocal)+1
5335 endif
5336 endif
5337 enddo
5338
5339 bucketoffsets(1)=1
5340 do ilocal=1,npixbatch
5341 bucketoffsets(ilocal+1)=bucketoffsets(ilocal)+bucketcounts(ilocal)
5342 enddo
5343 bucketfill(1:npixbatch)=bucketoffsets(1:npixbatch)
5344 do is=1,totalseg
5345 if (segment_is_valid(segments_recv,is,4)) then
5346 ipix=nint(segments_recv(1,is))
5347 if (ipix>=ipixstart .and. ipix<=ipixend .and. segment_pixel_owner(ipix)==mype) then
5348 ilocal=ipix-ipixstart+1
5349 idx(bucketfill(ilocal))=is
5350 bucketfill(ilocal)=bucketfill(ilocal)+1
5351 endif
5352 endif
5353 enddo
5354
5355 do ipix=ipixstart,ipixend
5356 if (segment_pixel_owner(ipix)/=mype) cycle
5357 ilocal=ipix-ipixstart+1
5358 nidx=bucketcounts(ilocal)
5359 if (nidx>0) then
5360 profile_local(5)=profile_local(5)+dble(nidx)*dble(nidx)
5361 call sort_segment_indices_near_to_far(segments_recv,&
5362 idx(bucketoffsets(ilocal):bucketoffsets(ilocal+1)-1),nidx)
5363 ixglobal=1+mod(ipix-1,numxi1)
5364 iyglobal=1+(ipix-1)/numxi1
5365 do iseg=bucketoffsets(ilocal),bucketoffsets(ilocal+1)-1
5366 is=idx(iseg)
5367 euvthin(ixglobal,iyglobal)=euvthin(ixglobal,iyglobal)+segments_recv(3,is)
5368 atten=transfer_attenuation(tau(ixglobal,iyglobal))
5369 euv(ixglobal,iyglobal)=euv(ixglobal,iyglobal)+atten*segments_recv(3,is)
5370 tau(ixglobal,iyglobal)=tau(ixglobal,iyglobal)+max(zero,segments_recv(4,is))
5371 enddo
5372 endif
5373 enddo
5374 deallocate(idx)
5375 endif
5376
5377 deallocate(segments_send,segments_recv)
5378 if (allocated(segments)) deallocate(segments)
5379 ipixstart=ipixend+1
5380 enddo
5381
5382 do iigrid=1,igridstail
5383 if (allocated(cache(iigrid)%source)) deallocate(cache(iigrid)%source)
5384 if (allocated(cache(iigrid)%opacity)) deallocate(cache(iigrid)%opacity)
5385 if (allocated(cache(iigrid)%rface)) deallocate(cache(iigrid)%rface)
5386 if (allocated(cache(iigrid)%thetaface)) deallocate(cache(iigrid)%thetaface)
5387 if (allocated(cache(iigrid)%phiface)) deallocate(cache(iigrid)%phiface)
5388 if (allocated(cache(iigrid)%rface2)) deallocate(cache(iigrid)%rface2)
5389 if (allocated(cache(iigrid)%theta_cos)) deallocate(cache(iigrid)%theta_cos)
5390 if (allocated(cache(iigrid)%phi_sin)) deallocate(cache(iigrid)%phi_sin)
5391 if (allocated(cache(iigrid)%phi_cos)) deallocate(cache(iigrid)%phi_cos)
5392 enddo
5393 deallocate(cache)
5394 deallocate(sendcounts,recvcounts,senddispls,recvdispls,roundsendcounts,roundrecvcounts,&
5395 roundsenddispls,roundrecvdispls,ownersegcounts,owneroffsets,bucketcounts,&
5396 bucketoffsets,bucketfill)
5397 allocate(image_reduce(numxi1,numxi2))
5398 call mpi_allreduce(euv,image_reduce,numxi1*numxi2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5399 euv=image_reduce
5400 call mpi_allreduce(tau,image_reduce,numxi1*numxi2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5401 tau=image_reduce
5402 call mpi_allreduce(euvthin,image_reduce,numxi1*numxi2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5403 euvthin=image_reduce
5404 deallocate(image_reduce)
5405 call mpi_allreduce(profile_local,profile_global,5,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5406 call mpi_allreduce(phys_max_local,phys_max_global,2,mpi_double_precision,mpi_max,icomm,ierrmpi)
5407 call mpi_allreduce(phys_sum_local,phys_sum_global,2,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5408 call mpi_allreduce(sphddafallbacklocal,sphddafallbackglobal,1,mpi_integer,mpi_sum,icomm,ierrmpi)
5409 if (radsyn_verbose .and. mype==0) then
5410 if (sph_use_dda) then
5411 write(*,'(a,5(es12.5,1x))') ' sph_dda thick profile: ',profile_global
5412 write(*,'(a,i0)') ' sph_dda thick fallback rays: ',sphddafallbackglobal
5413 write(*,'(a,4(es12.5,1x))') ' sph_dda thick physics maxj maxk sumjds sumkds: ',&
5414 phys_max_global(1),phys_max_global(2),phys_sum_global(1),phys_sum_global(2)
5415 else
5416 write(*,'(a,5(es12.5,1x))') ' sph_intersection thick profile: ',profile_global
5417 write(*,'(a,4(es12.5,1x))') ' sph_intersection thick physics maxj maxk sumjds sumkds: ',&
5418 phys_max_global(1),phys_max_global(2),phys_sum_global(1),phys_sum_global(2)
5419 endif
5420 endif
5422
5423 }
5424
5425 {^ifthreed
5426
5427 subroutine get_sph_intersection_image_bounds(xImin1,xImax1,xImin2,xImax2)
5428 double precision, intent(out) :: xImin1,xImax1,xImin2,xImax2
5429
5430 integer, parameter :: nsample=5
5431 integer :: iigrid,igrid,ir,it,ip
5432 integer :: ixI^L,ixO^L
5433 double precision, allocatable :: rface(:),thetaface(:),phiface(:)
5434 double precision :: local_min1,local_max1,local_min2,local_max2
5435 double precision :: sph(1:3),xcent(1:2),wr,wt,wp
5436
5437 local_min1=huge(one)
5438 local_max1=-huge(one)
5439 local_min2=huge(one)
5440 local_max2=-huge(one)
5441
5442 do iigrid=1,igridstail
5443 igrid=igrids(iigrid)
5444 ^d&ixomin^d=ixmlo^d\
5445 ^d&ixomax^d=ixmhi^d\
5446 ^d&iximin^d=ixglo^d\
5447 ^d&iximax^d=ixghi^d\
5448
5449 call build_sph_intersection_faces(ixi^l,ixo^l,ps(igrid)%x,ps(igrid)%dx,&
5450 rface,thetaface,phiface)
5451 do ir=0,nsample-1
5452 wr=dble(ir)/dble(nsample-1)
5453 sph(1)=(one-wr)*rface(ixomin1)+wr*rface(ixomax1+1)
5454 do it=0,nsample-1
5455 wt=dble(it)/dble(nsample-1)
5456 sph(2)=(one-wt)*thetaface(ixomin2)+wt*thetaface(ixomax2+1)
5457 do ip=0,nsample-1
5458 wp=dble(ip)/dble(nsample-1)
5459 if (ir/=0 .and. ir/=nsample-1 .and. it/=0 .and. it/=nsample-1 .and. &
5460 ip/=0 .and. ip/=nsample-1) cycle
5461 sph(3)=(one-wp)*phiface(ixomin3)+wp*phiface(ixomax3+1)
5462 call get_cor_image_spherical(sph,xcent)
5463 local_min1=min(local_min1,xcent(1))
5464 local_max1=max(local_max1,xcent(1))
5465 local_min2=min(local_min2,xcent(2))
5466 local_max2=max(local_max2,xcent(2))
5467 enddo
5468 enddo
5469 enddo
5470 deallocate(rface,thetaface,phiface)
5471 enddo
5472
5473 call mpi_allreduce(local_min1,ximin1,1,mpi_double_precision,mpi_min,icomm,ierrmpi)
5474 call mpi_allreduce(local_max1,ximax1,1,mpi_double_precision,mpi_max,icomm,ierrmpi)
5475 call mpi_allreduce(local_min2,ximin2,1,mpi_double_precision,mpi_min,icomm,ierrmpi)
5476 call mpi_allreduce(local_max2,ximax2,1,mpi_double_precision,mpi_max,icomm,ierrmpi)
5477 if (ximin1>0.5d0*huge(one) .or. ximax1<-0.5d0*huge(one) .or. &
5478 ximin2>0.5d0*huge(one) .or. ximax2<-0.5d0*huge(one)) then
5479 call mpistop("sph_intersection could not determine image bounds")
5480 endif
5482
5484 double precision, intent(out) :: dxI
5485
5486 integer :: iigrid,igrid,ixI^L,ixO^L,ix^D
5487 double precision :: local_min,global_min,dr,ds_theta,ds_phi,rval,theta
5488
5489 local_min=huge(one)
5490 do iigrid=1,igridstail
5491 igrid=igrids(iigrid)
5492 ^d&ixomin^d=ixmlo^d\
5493 ^d&ixomax^d=ixmhi^d\
5494 ^d&iximin^d=ixglo^d\
5495 ^d&iximax^d=ixghi^d\
5496
5497 do ix1=ixomin1,ixomax1
5498 do ix2=ixomin2,ixomax2
5499 do ix3=ixomin3,ixomax3
5500 rval=max(smalldouble,ps(igrid)%x(ix^d,1))
5501 theta=ps(igrid)%x(ix^d,2)
5502 dr=ps(igrid)%dx(ix^d,1)
5503 ds_theta=rval*ps(igrid)%dx(ix^d,2)
5504 ds_phi=rval*max(smalldouble,sin(theta))*ps(igrid)%dx(ix^d,3)
5505 local_min=min(local_min,dr,ds_theta,ds_phi)
5506 enddo
5507 enddo
5508 enddo
5509 enddo
5510
5511 call mpi_allreduce(local_min,global_min,1,mpi_double_precision,mpi_min,icomm,ierrmpi)
5512 if (global_min<=zero .or. global_min>half*huge(one)) then
5513 call mpistop("sph_intersection could not determine dat-resolution image spacing")
5514 endif
5515 dxi=global_min
5517
5518 subroutine get_image(qunit,datatype,fl)
5519 ! integrate emission flux along line of sight (LOS)
5520 ! in a 3D simulation box and get a 2D EUV image
5522 use mod_constants
5523
5524 integer, intent(in) :: qunit
5525 type(te_fluid), intent(in) :: fl
5526 character(20), intent(in) :: datatype
5527
5528 integer :: ix^D,numXI1,numXI2,numWI
5529 double precision :: xImin1,xImax1,xImin2,xImax2,xIcent1,xIcent2,dxI
5530 double precision, allocatable :: xI1(:),xI2(:),dxI1(:),dxI2(:)
5531 double precision, allocatable :: wI(:,:,:),wIs(:,:,:),EM(:,:),Dpl(:,:),Tau(:,:),EMthin(:,:),WLB(:,:,:)
5532 double precision :: vec_temp1(1:3),vec_temp2(1:3)
5533 double precision :: vec_z(1:3),vec_cor(1:3),xI_cor(1:2)
5534 double precision :: res,LOS_psi,r_max,r_loc
5535
5536 integer :: mass
5537 character (30) :: ion
5538 double precision :: logTe,lineCent,sigma_PSF,spaceRsl,wlRsl,wslit
5539 double precision :: arcsec,RHESSI_rsl,LASCO_rsl,pixel,R_occult,smallflux
5540 integer :: iigrid,igrid,i,j,numSI,iw
5541 logical :: emit,ray_image_global,has_thick_output
5542
5543 if (coordinate==spherical) then
5545 else
5546 ! cartesian
5548 endif
5549
5550 ! calculate domain of the image
5551 if (coordinate==spherical) then
5552 if (trim(ray_method_active)=='spherical' .and. datatype=='image_euv') then
5553 call get_sph_intersection_image_bounds(ximin1,ximax1,ximin2,ximax2)
5554 else
5555 ximin1=-abs(xprobmax1)
5556 ximin2=-abs(xprobmax1)
5557 ximax1=abs(xprobmax1)
5558 ximax2=abs(xprobmax1)
5559 endif
5560 else
5561 ! calculate domain of the image
5562 do ix1=1,2
5563 if (ix1==1) vec_cor(1)=xprobmin1
5564 if (ix1==2) vec_cor(1)=xprobmax1
5565 do ix2=1,2
5566 if (ix2==1) vec_cor(2)=xprobmin2
5567 if (ix2==2) vec_cor(2)=xprobmax2
5568 do ix3=1,2
5569 if (ix3==1) vec_cor(3)=xprobmin3
5570 if (ix3==2) vec_cor(3)=xprobmax3
5571 if (big_image) then
5572 r_loc=(vec_cor(1)-x_origin(1))**2
5573 r_loc=r_loc+(vec_cor(2)-x_origin(2))**2
5574 r_loc=r_loc+(vec_cor(3)-x_origin(3))**2
5575 r_loc=sqrt(r_loc)
5576 if (ix1==1 .and. ix2==1 .and. ix3==1) then
5577 r_max=r_loc
5578 else
5579 r_max=max(r_max,r_loc)
5580 endif
5581 else
5582 call get_cor_image(vec_cor,xi_cor)
5583 if (ix1==1 .and. ix2==1 .and. ix3==1) then
5584 ximin1=xi_cor(1)
5585 ximax1=xi_cor(1)
5586 ximin2=xi_cor(2)
5587 ximax2=xi_cor(2)
5588 else
5589 ximin1=min(ximin1,xi_cor(1))
5590 ximax1=max(ximax1,xi_cor(1))
5591 ximin2=min(ximin2,xi_cor(2))
5592 ximax2=max(ximax2,xi_cor(2))
5593 endif
5594 endif
5595 enddo
5596 enddo
5597 enddo
5598 if (big_image) then
5599 ximin1=-r_max
5600 ximin2=-r_max
5601 ximax1=r_max
5602 ximax2=r_max
5603 endif
5604 endif
5605 xicent1=(ximin1+ximax1)/2.d0
5606 xicent2=(ximin2+ximax2)/2.d0
5607
5608 ! tables for image
5609 if (si_unit) then
5610 arcsec=7.25d5/unit_length
5611 else
5612 arcsec=7.25d7/unit_length
5613 endif
5614 if (datatype=='image_euv') then
5615 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
5616 dxi=spacersl*arcsec ! intrument resolution of image
5617 smallflux=smalldouble
5618 else if (datatype=='image_sxr') then
5619 rhessi_rsl=2.3d0/instrument_resolution_factor
5620 dxi=rhessi_rsl*arcsec
5621 smallflux=1.d-40
5622 else if (datatype=='image_whitelight') then
5623 if (whitelight_instrument=='LASCO/C1') then
5624 lasco_rsl=5.6d0/instrument_resolution_factor
5625 r_occult=1.1d0
5626 else if (whitelight_instrument=='LASCO/C2') then
5627 lasco_rsl=11.4d0/instrument_resolution_factor
5628 r_occult=2.d0
5629 else if (whitelight_instrument=='LASCO/C3') then
5630 lasco_rsl=56.d0/instrument_resolution_factor
5631 r_occult=3.7d0
5632 else
5633 call mpistop('Whitelight synthesis: instrument is not supported!')
5634 endif
5635 dxi=lasco_rsl*arcsec
5636 if (r_occultor>1.d0) r_occult=r_occultor
5637 r_occult=r_occult*const_rsun/unit_length
5638 smallflux=1.d-20
5639 endif
5640 numxi1=8*ceiling((ximax1-xicent1)/dxi/8.d0)
5641 ximin1=xicent1-numxi1*dxi
5642 ximax1=xicent1+numxi1*dxi
5643 numxi1=numxi1*2
5644 numxi2=8*ceiling((ximax2-xicent2)/dxi/8.d0)
5645 ximin2=xicent2-numxi2*dxi
5646 ximax2=xicent2+numxi2*dxi
5647 numxi2=numxi2*2
5648 allocate(xi1(numxi1),xi2(numxi2),dxi1(numxi1),dxi2(numxi2))
5649 do ix1=1,numxi1
5650 xi1(ix1)=ximin1+dxi*(ix1-half)
5651 dxi1(ix1)=dxi
5652 enddo
5653 do ix2=1,numxi2
5654 xi2(ix2)=ximin2+dxi*(ix2-half)
5655 dxi2(ix2)=dxi
5656 enddo
5657
5658 ! calculate emission
5659 if (datatype=='image_euv' .or. datatype=='image_sxr') then
5660 has_thick_output=datatype=='image_euv' .and. trim(radiation_transfer)=='thick' .and. &
5661 ((coordinate==spherical .and. trim(ray_method_active)=='spherical') .or. &
5662 (coordinate==cartesian .and. trim(ray_method_active)=='cart'))
5663 if (datatype=='image_euv') then
5664 numwi=radsyn_euv_num_outputs(.false.,has_thick_output)
5665 else
5666 numwi=1
5667 endif
5668 allocate(wi(numxi1,numxi2,numwi),wis(numxi1,numxi2,numwi),em(numxi1,numxi2))
5669 wi=zero
5670 wis=zero
5671 em=zero
5672 ray_image_global=.false.
5673 if (has_thick_output) then
5674 allocate(tau(numxi1,numxi2),emthin(numxi1,numxi2))
5675 tau=zero
5676 emthin=zero
5677 endif
5678 if (coordinate==cartesian .and. datatype=='image_euv' .and. &
5679 trim(ray_method_active)=='cart') then
5680 ray_image_global=.true.
5681 allocate(dpl(numxi1,numxi2))
5682 dpl=zero
5683 if (trim(radiation_transfer)=='thick') then
5684 call integrate_euv_cart_dda_thick_datresol(numxi1,numxi2,xi1,xi2,fl,em,dpl,tau,emthin)
5685 else
5686 call integrate_euv_cart_dda_datresol(numxi1,numxi2,xi1,xi2,fl,em,dpl)
5687 endif
5688 deallocate(dpl)
5689 else if (coordinate==cartesian) then
5690 do iigrid=1,igridstail; igrid=igrids(iigrid);
5691 call integrate_emission_cartesian(igrid,numxi1,numxi2,xi1,xi2,dxi,fl,datatype,em)
5692 enddo
5693 else if (trim(ray_method_active) == 'spherical' .and. datatype == 'image_euv') then
5694 if (trim(radiation_transfer) == 'thick') then
5695 ray_image_global=.true.
5696 call integrate_euv_sph_intersection_thick(numxi1,numxi2,xi1,xi2,dxi,fl,em,tau,emthin)
5697 else
5698 call integrate_euv_sph_intersection_thin(numxi1,numxi2,xi1,xi2,dxi,fl,em)
5699 endif
5700 else
5701 do iigrid=1,igridstail; igrid=igrids(iigrid);
5702 call integrate_emission_spherical(igrid,numxi1,numxi2,xi1,xi2,dxi,fl,datatype,em)
5703 enddo
5704 endif
5705 if (ray_image_global) then
5706 if (has_thick_output) then
5707 call pack_euv_image_outputs(numxi1,numxi2,em,wi,smallflux,.false.,&
5708 has_thick_output,tau=tau,euvthin=emthin,&
5709 cap_absorption=.true.)
5710 else
5711 call pack_euv_image_outputs(numxi1,numxi2,em,wi,smallflux,.false.,has_thick_output)
5712 endif
5713 else
5714 do ix1=1,numxi1
5715 do ix2=1,numxi2
5716 if (em(ix1,ix2)>smallflux) wis(ix1,ix2,1)=em(ix1,ix2)
5717 enddo
5718 enddo
5719 endif
5720 if (.not. ray_image_global) then
5721 numsi=numxi1*numxi2*numwi
5722 call mpi_allreduce(wis,wi,numsi,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5723 endif
5724 if (activate_unit_arcsec) then
5725 xi1=xi1/arcsec
5726 dxi1=dxi1/arcsec
5727 xi2=xi2/arcsec
5728 dxi2=dxi2/arcsec
5729 endif
5730 call output_data(qunit,xi1,xi2,dxi1,dxi2,wi,numxi1,numxi2,numwi,datatype)
5731 if (allocated(tau)) deallocate(tau)
5732 if (allocated(emthin)) deallocate(emthin)
5733 deallocate(wi,wis,em)
5734 else if (datatype=='image_whitelight') then
5735 numwi=2
5736 allocate(wi(numxi1,numxi2,numwi),wis(numxi1,numxi2,numwi),wlb(numxi1,numxi2,numwi))
5737 wi=zero
5738 wis=zero
5739 wlb=zero
5740 if (coordinate==spherical) then
5741 do iigrid=1,igridstail; igrid=igrids(iigrid);
5742 call integrate_whitelight_spherical(igrid,numxi1,numxi2,numwi,xi1,xi2,dxi,fl,datatype,wlb)
5743 enddo
5744 endif
5745 do ix1=1,numxi1
5746 do ix2=1,numxi2
5747 if (wlb(ix1,ix2,1)>smallflux) then
5748 wis(ix1,ix2,1)=wlb(ix1,ix2,1)
5749 wis(ix1,ix2,2)=wlb(ix1,ix2,2)
5750 endif
5751 enddo
5752 enddo
5753 numsi=numxi1*numxi2*numwi
5754 call mpi_allreduce(wis,wi,numsi,mpi_double_precision,mpi_sum,icomm,ierrmpi)
5755 if (activate_unit_arcsec) then
5756 xi1=xi1/arcsec
5757 dxi1=dxi1/arcsec
5758 xi2=xi2/arcsec
5759 dxi2=dxi2/arcsec
5760 endif
5761 call output_data(qunit,xi1,xi2,dxi1,dxi2,wi,numxi1,numxi2,numwi,datatype)
5762 deallocate(wi,wis,wlb)
5763 endif
5764
5765 deallocate(xi1,xi2,dxi1,dxi2)
5766
5767 end subroutine get_image
5768
5769 subroutine integrate_emission_cartesian(igrid,numXI1,numXI2,xI1,xI2,dxI,fl,datatype,EM)
5770 integer, intent(in) :: igrid,numXI1,numXI2
5771 double precision, intent(in) :: xI1(numXI1),xI2(numXI2)
5772 double precision, intent(in) :: dxI
5773 type(te_fluid), intent(in) :: fl
5774 character(20), intent(in) :: datatype
5775 double precision, intent(inout) :: EM(numXI1,numXI2)
5776
5777 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
5778 double precision :: xb^L,xd^D
5779 double precision, allocatable :: flux(:^D&),opacity(:^D&)
5780 double precision :: res
5781 integer :: ixP^L,ixP^D,nSubC^D,iSubC^D
5782 double precision :: xSubP1,xSubP2,dxSubP,xerf^L,fluxsubC
5783 double precision :: xSubC(1:3),dxSubC^D,xCent(1:2)
5784
5785 integer :: mass
5786 double precision :: logTe
5787 character (30) :: ion
5788 double precision :: lineCent
5789 double precision :: sigma_PSF,spaceRsl,wlRsl,sigma0,factor,wslit
5790 double precision :: arcsec,pixel,RHESSI_rsl,area_1AU
5791 double precision :: aa,bb
5792
5793 ^d&ixomin^d=ixmlo^d\
5794 ^d&ixomax^d=ixmhi^d\
5795 ^d&iximin^d=ixglo^d\
5796 ^d&iximax^d=ixghi^d\
5797 ^d&xbmin^d=rnode(rpxmin^d_,igrid)\
5798 ^d&xbmax^d=rnode(rpxmax^d_,igrid)\
5799
5800 if (si_unit) then
5801 arcsec=7.25d5/unit_length
5802 else
5803 arcsec=7.25d7/unit_length
5804 endif
5805
5806 allocate(flux(ixi^s),opacity(ixi^s))
5807 if (datatype=='image_euv') then
5808 if (trim(emission_model)=='pseudo_current') then
5809 call get_pseudo_current(igrid,ixi^l,ixo^l,ps(igrid)%w,flux)
5810 else if (trim(emission_model)=='radio_ff') then
5811 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,opacity)
5812 else
5813 ! get local EUV flux and velocity
5814 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux)
5815 flux(ixo^s)=flux(ixo^s)/instrument_resolution_factor**2 ! adjust flux due to artifical change of resolution
5816 endif
5817 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
5818 pixel=spacersl*arcsec
5819 sigma0=sigma_psf*pixel
5820 else if (datatype=='image_sxr') then
5821 ! get local SXR flux photons cm^-3 s^-1 (cgs) or photons m^-3 s^-1 (SI)
5822 call get_sxr(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,emin_sxr,emax_sxr)
5823 rhessi_rsl=2.3d0/instrument_resolution_factor
5824 sigma_psf=1.d0
5825 pixel=rhessi_rsl*arcsec
5826 sigma0=sigma_psf*pixel
5827 area_1au=2.81d27
5828 endif
5829
5830 ! integrate emission
5831 {do ix^d=ixomin^d,ixomax^d\}
5832 ^d&nsubc^d=1;
5833 ^d&nsubc^d=max(nsubc^d,ceiling(ps(igrid)%dx(ix^dd,^d)*abs(vec_xi1(^d))/(dxi/2.d0)));
5834 ^d&nsubc^d=max(nsubc^d,ceiling(ps(igrid)%dx(ix^dd,^d)*abs(vec_xi2(^d))/(dxi/2.d0)));
5835 ^d&dxsubc^d=ps(igrid)%dx(ix^dd,^d)/nsubc^d;
5836 if (datatype=='image_euv') then
5837 if (si_unit) then
5838 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length*1.d2/dxi/dxi ! DN s^-1
5839 else
5840 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length/dxi/dxi ! DN s^-1
5841 endif
5842 else if (datatype=='image_sxr') then
5843 ! sub-cell SXR flux at 1 AU [photons s^-1 cm^-2]
5844 fluxsubc=flux(ix^d)*dxsubc1*dxsubc2*dxsubc3*unit_length**3/area_1au
5845 endif
5846 if (fluxsubc>smalldouble) then
5847 ! dividing a cell to several parts to get more accurate integrating values
5848 {do isubc^d=1,nsubc^d\}
5849 ^d&xsubc(^d)=ps(igrid)%x(ix^dd,^d)-half*ps(igrid)%dx(ix^dd,^d)+(isubc^d-half)*dxsubc^d;
5850 ! mapping the 3D coordinate to location at the image
5851 call get_cor_image(xsubc,xcent)
5852 ! distribution at nearby pixels
5853 ixp1=floor((xcent(1)-(xi1(1)-half*dxi))/dxi)+1
5854 ixp2=floor((xcent(2)-(xi2(1)-half*dxi))/dxi)+1
5855 ixpmin1=max(1,ixp1-3)
5856 ixpmax1=min(ixp1+3,numxi1)
5857 ixpmin2=max(1,ixp2-3)
5858 ixpmax2=min(ixp2+3,numxi2)
5859 do ixp1=ixpmin1,ixpmax1
5860 do ixp2=ixpmin2,ixpmax2
5861 xerfmin1=((xi1(ixp1)-half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
5862 xerfmax1=((xi1(ixp1)+half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
5863 xerfmin2=((xi2(ixp2)-half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
5864 xerfmax2=((xi2(ixp2)+half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
5865 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
5866 em(ixp1,ixp2)=em(ixp1,ixp2)+fluxsubc*factor
5867 enddo !ixP2
5868 enddo !ixP1
5869 {enddo\} !iSubC
5870 endif
5871 {enddo\} !ix
5872
5873 deallocate(flux,opacity)
5874 end subroutine integrate_emission_cartesian
5875
5876 subroutine integrate_emission_spherical(igrid,numXI1,numXI2,xI1,xI2,dxI,fl,datatype,EM)
5877 integer, intent(in) :: igrid,numXI1,numXI2
5878 double precision, intent(in) :: xI1(numXI1),xI2(numXI2)
5879 double precision, intent(in) :: dxI
5880 type(te_fluid), intent(in) :: fl
5881 character(20), intent(in) :: datatype
5882 double precision, intent(inout) :: EM(numXI1,numXI2)
5883
5884 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
5885 double precision, allocatable :: flux(:^D&),Ne(:^D&),opacity(:^D&)
5886 integer :: ixP^L,ixP^D,nSubC^D,iSubC^D
5887 double precision :: xSubP1,xSubP2,dxSubP,xerf^L,fluxsubC,RsubC
5888 double precision :: TBsubC,PBsubC
5889 double precision :: xSubC(1:3),dxSubC^D,xCent(1:2),xSubC_car(1:3)
5890 double precision :: R_thick,dotp,dvolume,R_occult,Rc
5891 double precision :: dxl(1:3),x_sph(1:3),dx_sph(1:3)
5892 double precision :: unitv_r(1:3),unitv_theta(1:3),unitv_phi(1:3)
5893 logical :: sun_back_side,emit
5894
5895 integer :: mass
5896 double precision :: logTe
5897 character (30) :: ion
5898 double precision :: lineCent
5899 double precision :: sigma_PSF,spaceRsl,wlRsl,sigma0,factor,wslit
5900 double precision :: RHESSI_rsl,area_1AU,arcsec,pixel
5901
5902 ^d&ixomin^d=ixmlo^d;
5903 ^d&ixomax^d=ixmhi^d;
5904 ^d&iximin^d=ixglo^d;
5905 ^d&iximax^d=ixghi^d;
5906
5907 if (si_unit) then
5908 arcsec=7.25d5/unit_length
5909 else
5910 arcsec=7.25d7/unit_length
5911 endif
5912
5913 allocate(flux(ixi^s),opacity(ixi^s))
5914 if (datatype=='image_euv') then
5915 if (trim(emission_model)=='pseudo_current') then
5916 call get_pseudo_current(igrid,ixi^l,ixo^l,ps(igrid)%w,flux)
5917 else if (trim(emission_model)=='radio_ff') then
5918 call get_radio_ff_source_opacity(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,opacity)
5919 else
5920 ! get local EUV flux and velocity
5921 call get_euv(wavelength,ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux)
5922 flux(ixo^s)=flux(ixo^s)/instrument_resolution_factor**2 ! adjust flux due to artifical change of resolution
5923 endif
5924 call get_line_info(wavelength,ion,mass,logte,linecent,spacersl,wlrsl,sigma_psf,wslit)
5925 pixel=spacersl*arcsec
5926 sigma0=sigma_psf*pixel
5927 else if (datatype=='image_sxr') then
5928 ! get local SXR flux photons cm^-3 s^-1 (cgs) or photons m^-3 s^-1 (SI)
5929 call get_sxr(ixi^l,ixo^l,ps(igrid)%w,ps(igrid)%x,fl,flux,emin_sxr,emax_sxr)
5930 rhessi_rsl=2.3d0/instrument_resolution_factor
5931 sigma_psf=1.d0
5932 pixel=rhessi_rsl*arcsec
5933 sigma0=sigma_psf*pixel
5934 area_1au=2.81d27
5935 endif
5936
5937 ! integrate emission
5938 r_thick=r_opt_thick*const_rsun/unit_length
5939 {do ix^d=ixomin^d,ixomax^d\}
5940 x_sph(1:3)=ps(igrid)%x(ix^d,1:3)
5941 dx_sph(1:3)=ps(igrid)%dx(ix^d,1:3)
5942 dxl(1)=dx_sph(1) ! cell size in length
5943 dxl(2)=x_sph(1)*dx_sph(2) ! cell size in length
5944 dxl(3)=x_sph(1)*dsin(x_sph(2))*dx_sph(3) ! cell size in length
5945 ! dividing a cell to several sub-cells to get more accurate integrating values
5946 ^d&nsubc^d=1;
5947 call get_unit_vector_spherical(x_sph,unitv_r,unitv_theta,unitv_phi)
5948 call dot_product_loc(unitv_r,vec_xi1,dotp)
5949 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
5950 call dot_product_loc(unitv_r,vec_xi2,dotp)
5951 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
5952 call dot_product_loc(unitv_theta,vec_xi1,dotp)
5953 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
5954 call dot_product_loc(unitv_theta,vec_xi2,dotp)
5955 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
5956 call dot_product_loc(unitv_phi,vec_xi1,dotp)
5957 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
5958 call dot_product_loc(unitv_phi,vec_xi2,dotp)
5959 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
5960
5961 ! integrate sub-cells
5962 do isubc1=1,nsubc1
5963 ! sub-cell center coordinate in spherical
5964 xsubc(1)=x_sph(1)-half*dx_sph(1)+(isubc1-half)*dx_sph(1)/nsubc1
5965 rsubc=xsubc(1)
5966 dxsubc1=dx_sph(1)/nsubc1 ! sub-cell size in length
5967 do isubc2=1,nsubc2
5968 ! sub-cell center coordinate in spherical
5969 xsubc(2)=x_sph(2)-half*dx_sph(2)+(isubc2-half)*dx_sph(2)/nsubc2
5970 dxsubc2=xsubc(1)*dx_sph(2)/nsubc2 ! sub-cell size in length
5971 dxsubc3=xsubc(1)*dsin(xsubc(2))*dx_sph(3)/nsubc3 ! sub-cell size in length
5972 dvolume=dxsubc1*dxsubc2*dxsubc3
5973 if (datatype=='image_euv') then
5974 if (si_unit) then
5975 fluxsubc=flux(ix^d)*dvolume*unit_length*1.d2/dxi/dxi ! DN s^-1
5976 else
5977 fluxsubc=flux(ix^d)*dvolume*unit_length/dxi/dxi ! DN s^-1
5978 endif
5979 else if (datatype=='image_sxr') then
5980 ! sub-cell SXR flux at 1 AU [photons s^-1 cm^-2]
5981 fluxsubc=flux(ix^d)*dvolume*unit_length**3/area_1au
5982 endif
5983 ! enter integration if flux large enough
5984 if (fluxsubc>smalldouble) then
5985 do isubc3=1,nsubc3
5986 ! sub-cell center coordinate in spherical
5987 xsubc(3)=x_sph(3)-half*dx_sph(3)+(isubc3-half)*dx_sph(3)/nsubc3
5988 call get_cor_image_spherical(xsubc,xcent)
5989 rc=dsqrt(xcent(1)**2+xcent(2)**2) ! distance to sun center (on the image plane)
5990 !
5991 ! whether the local emitted photons can arrive the telescope
5992 call spherical_to_cartesian(xsubc,xsubc_car)
5993 call dot_product_loc(vec_los,xsubc_car,dotp)
5994 sun_back_side=.true.
5995 if (dotp<0.d0) sun_back_side=.false.
5996 ! whether the local emission can reach the telescope
5997 if (sun_back_side) then
5998 emit=.false.
5999 if (rc>r_thick) emit=.true.
6000 else
6001 emit=.true.
6002 if (xsubc(1)<=r_thick) emit=.false.
6003 endif
6004 !
6005 if (emit) then
6006 ! mapping the 3D coordinate to location at the image
6007 ! distribution at nearby pixels
6008 ixp1=floor((xcent(1)-(xi1(1)-half*dxi))/dxi)+1
6009 ixp2=floor((xcent(2)-(xi2(1)-half*dxi))/dxi)+1
6010 ixpmin1=max(1,ixp1-3)
6011 ixpmax1=min(ixp1+3,numxi1)
6012 ixpmin2=max(1,ixp2-3)
6013 ixpmax2=min(ixp2+3,numxi2)
6014 do ixp1=ixpmin1,ixpmax1
6015 do ixp2=ixpmin2,ixpmax2
6016 xerfmin1=((xi1(ixp1)-half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6017 xerfmax1=((xi1(ixp1)+half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6018 xerfmin2=((xi2(ixp2)-half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6019 xerfmax2=((xi2(ixp2)+half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6020 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
6021 em(ixp1,ixp2)=em(ixp1,ixp2)+fluxsubc*factor
6022 enddo !ixP2
6023 enddo !ixP1
6024 endif !emit
6025 enddo !iSubC3
6026 endif !smallflux
6027 enddo !iSubC2
6028 enddo !iSubC1
6029 {enddo\} !ix
6030
6031 deallocate(flux,opacity)
6032
6033 end subroutine integrate_emission_spherical
6034
6035 subroutine integrate_whitelight_spherical(igrid,numXI1,numXI2,numWI,xI1,xI2,dxI,fl,datatype,WLB)
6036 use mod_eos, only: eos
6037
6038 integer, intent(in) :: igrid,numXI1,numXI2,numWI
6039 double precision, intent(in) :: xI1(numXI1),xI2(numXI2)
6040 double precision, intent(in) :: dxI
6041 type(te_fluid), intent(in) :: fl
6042 character(20), intent(in) :: datatype
6043 double precision, intent(inout) :: WLB(numXI1,numXI2,numWI)
6044
6045 integer :: ixO^L,ixO^D,ixI^L,ix^D,i,j
6046 double precision, allocatable :: flux(:^D&),Ne(:^D&)
6047 integer :: ixP^L,ixP^D,nSubC^D,iSubC^D
6048 double precision :: xSubP1,xSubP2,dxSubP,xerf^L,fluxsubC,RsubC
6049 double precision :: sigma_PSF,sigma0,arcsec,pixel,LASCO_rsl
6050 double precision :: A,B,C,D,Rc,Ne0,TBsubC,PBsubC,factor
6051 double precision :: R_thick,dotp,dvolume,R_occult
6052 double precision :: xSubC(1:3),dxSubC^D,xCent(1:2),xSubC_car(1:3)
6053 double precision :: dxl(1:3),x_sph(1:3),dx_sph(1:3)
6054 double precision :: unitv_r(1:3),unitv_theta(1:3),unitv_phi(1:3)
6055 logical :: emit
6056
6057 ^d&ixomin^d=ixmlo^d;
6058 ^d&ixomax^d=ixmhi^d;
6059 ^d&iximin^d=ixglo^d;
6060 ^d&iximax^d=ixghi^d;
6061
6062 if (si_unit) then
6063 arcsec=7.25d5/unit_length
6064 else
6065 arcsec=7.25d7/unit_length
6066 endif
6067
6068 allocate(ne(ixi^s))
6069 if (whitelight_instrument=='LASCO/C1') then
6070 lasco_rsl=5.6d0/instrument_resolution_factor
6071 r_occult=1.1d0
6072 else if (whitelight_instrument=='LASCO/C2') then
6073 lasco_rsl=11.4d0/instrument_resolution_factor
6074 r_occult=2.d0
6075 else if (whitelight_instrument=='LASCO/C3') then
6076 lasco_rsl=56.d0/instrument_resolution_factor
6077 r_occult=3.7d0
6078 endif
6079 if (r_occultor>1.d0) r_occult=r_occultor
6080 r_occult=r_occult*const_rsun/unit_length
6081 call fl%get_rho(ps(igrid)%w,ps(igrid)%x,ixi^l,ixo^l,ne)
6082 ! get actual electron density from EoS (replaces rho with ne)
6083 block
6084 double precision :: nH_dummy(ixI^S)
6085 call eos%get_ne_nH(ixi^l, ixo^l, ps(igrid)%w, ne, nh_dummy)
6086 end block
6087 sigma_psf=1.d0
6088 pixel=lasco_rsl*arcsec
6089 sigma0=sigma_psf*pixel
6090
6091 ! integrate emission
6092 r_thick=r_opt_thick*const_rsun/unit_length
6093 {do ix^d=ixomin^d,ixomax^d\}
6094 x_sph(1:3)=ps(igrid)%x(ix^d,1:3)
6095 dx_sph(1:3)=ps(igrid)%dx(ix^d,1:3)
6096 dxl(1)=dx_sph(1) ! cell size in length
6097 dxl(2)=x_sph(1)*dx_sph(2) ! cell size in length
6098 dxl(3)=x_sph(1)*dsin(x_sph(2))*dx_sph(3) ! cell size in length
6099 ne0=ne(ix^d)*unit_numberdensity
6100 ! dividing a cell to several sub-cells to get more accurate integrating values
6101 ^d&nsubc^d=1;
6102 call get_unit_vector_spherical(x_sph,unitv_r,unitv_theta,unitv_phi)
6103 call dot_product_loc(unitv_r,vec_xi1,dotp)
6104 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
6105 call dot_product_loc(unitv_r,vec_xi2,dotp)
6106 nsubc1=max(nsubc1,ceiling(dxl(1)*abs(dotp)/(dxi/2.d0)))
6107 call dot_product_loc(unitv_theta,vec_xi1,dotp)
6108 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
6109 call dot_product_loc(unitv_theta,vec_xi2,dotp)
6110 nsubc2=max(nsubc2,ceiling(dxl(2)*abs(dotp)/(dxi/2.d0)))
6111 call dot_product_loc(unitv_phi,vec_xi1,dotp)
6112 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
6113 call dot_product_loc(unitv_phi,vec_xi2,dotp)
6114 nsubc3=max(nsubc3,ceiling(dxl(3)*abs(dotp)/(dxi/2.d0)))
6115
6116 ! integrate sub-cells
6117 do isubc1=1,nsubc1
6118 ! sub-cell center coordinate in spherical
6119 xsubc(1)=x_sph(1)-half*dx_sph(1)+(isubc1-half)*dx_sph(1)/nsubc1
6120 rsubc=xsubc(1)
6121 dxsubc1=dx_sph(1)/nsubc1 ! sub-cell size in length
6122 call get_thomson_parameters(rsubc,a,b,c,d)
6123 do isubc2=1,nsubc2
6124 ! sub-cell center coordinate in spherical
6125 xsubc(2)=x_sph(2)-half*dx_sph(2)+(isubc2-half)*dx_sph(2)/nsubc2
6126 dxsubc2=xsubc(1)*dx_sph(2)/nsubc2 ! sub-cell size in length
6127 dxsubc3=xsubc(1)*dsin(xsubc(2))*dx_sph(3)/nsubc3 ! sub-cell size in length
6128 dvolume=dxsubc1*dxsubc2*dxsubc3
6129 do isubc3=1,nsubc3
6130 ! sub-cell center coordinate in spherical
6131 xsubc(3)=x_sph(3)-half*dx_sph(3)+(isubc3-half)*dx_sph(3)/nsubc3
6132 call get_cor_image_spherical(xsubc,xcent)
6133 rc=dsqrt(xcent(1)**2+xcent(2)**2) ! distance to sun center (on the image plane)
6134 ! whether the local emitted photons can arrive the telescope
6135 emit=.false.
6136 if (rc>r_occult) then
6137 emit=.true.
6138 ! scaterring flux from cm^-3 of plasma
6139 call get_whitelight_thomson(rsubc,rc,ne0,a,b,c,d,tbsubc,pbsubc)
6140 tbsubc=tbsubc*dvolume*unit_length/dxi/dxi
6141 pbsubc=pbsubc*dvolume*unit_length/dxi/dxi
6142 if (tbsubc<1.d-20) emit=.false.
6143 endif
6144 if (emit) then
6145 ! mapping the 3D coordinate to location at the image
6146 ! distribution at nearby pixels
6147 ixp1=floor((xcent(1)-(xi1(1)-half*dxi))/dxi)+1
6148 ixp2=floor((xcent(2)-(xi2(1)-half*dxi))/dxi)+1
6149 ixpmin1=max(1,ixp1-3)
6150 ixpmax1=min(ixp1+3,numxi1)
6151 ixpmin2=max(1,ixp2-3)
6152 ixpmax2=min(ixp2+3,numxi2)
6153 do ixp1=ixpmin1,ixpmax1
6154 do ixp2=ixpmin2,ixpmax2
6155 xerfmin1=((xi1(ixp1)-half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6156 xerfmax1=((xi1(ixp1)+half*dxi)-xcent(1))/(sqrt(2.d0)*sigma0)
6157 xerfmin2=((xi2(ixp2)-half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6158 xerfmax2=((xi2(ixp2)+half*dxi)-xcent(2))/(sqrt(2.d0)*sigma0)
6159 factor=(erfc(xerfmin1)-erfc(xerfmax1))*(erfc(xerfmin2)-erfc(xerfmax2))/4.d0
6160 wlb(ixp1,ixp2,1)=wlb(ixp1,ixp2,1)+tbsubc*factor
6161 wlb(ixp1,ixp2,2)=wlb(ixp1,ixp2,2)+pbsubc*factor
6162 enddo !ixP2
6163 enddo !ixP1
6164 endif
6165 enddo !iSubC3
6166 enddo !iSubC2
6167 enddo !iSubC1
6168 {enddo\} !ix
6169
6170 deallocate(ne)
6171
6172 end subroutine integrate_whitelight_spherical
6173
6174 subroutine get_thomson_parameters(Rl,A,B,C,D)
6175 ! parameters given in Billings 1968
6176 use mod_constants
6177 double precision, intent(in) :: Rl
6178 double precision, intent(inout) :: A,B,C,D
6179
6180 double precision :: sinO,cosO,sinO2,cosO2,tmp
6181
6182 sino=const_rsun/(rl*unit_length)
6183 sino2=sino**2
6184 coso2=1.d0-sino2
6185 coso=abs(dsqrt(coso2))
6186 tmp=log((1.d0+sino)/coso)
6187 a=coso*sino2
6188 b=-(1.d0-3.d0*sino2-(coso2/sino)*(1.d0+3.d0*sino2)*tmp)/8.d0
6189 c=4.d0/3.d0-coso-coso*coso2/3.d0
6190 d=(5.d0+sino2-(coso2/sino)*(5.d0-sino2)*tmp)/8.d0
6191
6192 end subroutine get_thomson_parameters
6193
6194 subroutine get_whitelight_thomson(Rl,Rin,Ne,A,B,C,D,fluxTB,fluxPB)
6195 ! use the method in SSW/eltheory
6196 double precision, intent(in) :: Rl,Rin,Ne,A,B,C,D
6197 double precision, intent(inout) :: fluxTB,fluxPB
6198
6199 double precision :: const,u,Bt,Br,PB,TB,sinchi2
6200
6201 u=0.63d0
6202 const=1.24878d-25/(1.d0-u/3.d0)
6203 sinchi2=(rin/rl)**2
6204 bt=const*(c+u*(d-c))
6205 pb=const*sinchi2*((a+u*(b-a)))
6206 br=bt-pb
6207 tb=bt+br
6208 fluxtb=tb*ne
6209 fluxpb=pb*ne
6210
6211 end subroutine get_whitelight_thomson
6212
6213 subroutine get_unit_vector_spherical(x_sph,unitv_r,unitv_theta,unitv_phi)
6214 double precision, intent(in) :: x_sph(1:3)
6215 double precision, intent(inout) :: unitv_r(1:3),unitv_theta(1:3),unitv_phi(1:3)
6216
6217 unitv_r(1)=dsin(x_sph(2))*dcos(x_sph(3))
6218 unitv_r(2)=dsin(x_sph(2))*dsin(x_sph(3))
6219 unitv_r(3)=dcos(x_sph(2))
6220 unitv_theta(1)=dcos(x_sph(2))*dcos(x_sph(3))
6221 unitv_theta(2)=dcos(x_sph(2))*dsin(x_sph(3))
6222 unitv_theta(3)=-dsin(x_sph(2))
6223 unitv_phi(1)=-dsin(x_sph(3))
6224 unitv_phi(2)=dcos(x_sph(3))
6225 unitv_phi(3)=zero
6226
6227 end subroutine get_unit_vector_spherical
6228
6229 subroutine output_data(qunit,xO1,xO2,dxO1,dxO2,wO,nXO1,nXO2,nWO,datatype)
6230 ! change the format of data and write data
6232
6233 integer, intent(in) :: qunit,nXO1,nXO2,nWO
6234 double precision, intent(in) :: dxO1(nxO1),dxO2(nxO2)
6235 double precision, intent(in) :: xO1(nXO1),xO2(nxO2)
6236 double precision, intent(inout) :: wO(nXO1,nXO2,nWO)
6237 character(20), intent(in) :: datatype
6238
6239 integer :: nPiece,nP1,nP2,nC1,nC2,nWC
6240 integer :: piece_nmax1,piece_nmax2,ix1,ix2,j,ipc,ixc1,ixc2
6241 double precision :: uniform_tol
6242 double precision, allocatable :: xC(:,:,:,:),wC(:,:,:,:),dxC(:,:,:,:)
6243
6244 ! clean small values
6245 uniform_tol=1.d-10
6246 do ix1=1,nxo1
6247 do ix2=1,nxo2
6248 do j=1,nwo
6249 if (abs(wo(ix1,ix2,j))<smalldouble) wo(ix1,ix2,j)=zero
6250 enddo
6251 enddo
6252 enddo
6253
6254 ! how many cells in each grid
6255 if (dat_resolution) then
6256 if (datatype=='image_euv' .or. datatype=='image_sxr') then
6257 if (los_phi==0 .and. los_theta==90) then
6258 piece_nmax1=block_nx2
6259 piece_nmax2=block_nx3
6260 else if (los_phi==90 .and. los_theta==90) then
6261 piece_nmax1=block_nx3
6262 piece_nmax2=block_nx1
6263 else
6264 piece_nmax1=block_nx1
6265 piece_nmax2=block_nx2
6266 endif
6267 else if (datatype=='spectrum_euv') then
6268 piece_nmax1=16
6269 if (direction_slit==1) then
6270 piece_nmax2=block_nx1
6271 else if (direction_slit==2) then
6272 piece_nmax2=block_nx2
6273 else
6274 piece_nmax2=block_nx3
6275 endif
6276 endif
6277 else
6278 piece_nmax1=20
6279 piece_nmax2=20
6280 endif
6281 loopn1: do j=piece_nmax1,1,-1
6282 if(mod(nxo1,j)==0) then
6283 nc1=j
6284 exit loopn1
6285 endif
6286 enddo loopn1
6287 loopn2: do j=piece_nmax2,1,-1
6288 if(mod(nxo2,j)==0) then
6289 nc2=j
6290 exit loopn2
6291 endif
6292 enddo loopn2
6293 ! how many grids
6294 np1=nxo1/nc1
6295 np2=nxo2/nc2
6296 npiece=np1*np2
6297 nwc=nwo
6298
6299 ! output images
6300 select case(convert_type)
6301 case('EIvtuCCmpi','ESvtuCCmpi','SIvtuCCmpi','WIvtuCCmpi')
6302 ! put data into grids
6303 allocate(xc(npiece,nc1,nc2,2))
6304 allocate(dxc(npiece,nc1,nc2,2))
6305 allocate(wc(npiece,nc1,nc2,nwo))
6306 do ipc=1,npiece
6307 do ixc1=1,nc1
6308 do ixc2=1,nc2
6309 ix1=mod(ipc-1,np1)*nc1+ixc1
6310 ix2=floor(1.0*(ipc-1)/np1)*nc2+ixc2
6311 xc(ipc,ixc1,ixc2,1)=xo1(ix1)
6312 xc(ipc,ixc1,ixc2,2)=xo2(ix2)
6313 dxc(ipc,ixc1,ixc2,1)=dxo1(ix1)
6314 dxc(ipc,ixc1,ixc2,2)=dxo2(ix2)
6315 do j=1,nwc
6316 wc(ipc,ixc1,ixc2,j)=wo(ix1,ix2,j)
6317 enddo
6318 enddo
6319 enddo
6320 enddo
6321 ! write data into vtu file
6322 call write_image_vtucc(qunit,xc,wc,dxc,npiece,nc1,nc2,nwc,datatype)
6323 deallocate(xc,dxc,wc)
6324 case('EIvtiCCmpi','ESvtiCCmpi','SIvtiCCmpi','WIvtiCCmpi')
6325 if (dat_resolution .and. &
6326 (maxval(abs(dxo1(:)-dxo1(1)))>uniform_tol*max(one,abs(dxo1(1))) .or. &
6327 maxval(abs(dxo2(:)-dxo2(1)))>uniform_tol*max(one,abs(dxo2(1))))) then
6328 call mpistop("vti needs uniform dat-resolution image grids")
6329 else
6330 call write_image_vticc(qunit,xo1,xo2,dxo1,dxo2,wo,nxo1,nxo2,nwo,nc1,nc2)
6331 endif
6332 case default
6333 call mpistop("Error in synthesize emission: Unknown convert_type")
6334 end select
6335
6336 end subroutine output_data
6337 }
6338
6339 subroutine write_image_vticc(qunit,xO1,xO2,dxO1,dxO2,wO,nXO1,nXO2,nWO,nC1,nC2)
6340 ! write image data to vti
6342
6343 integer, intent(in) :: qunit,nXO1,nXO2,nWO,nC1,nC2
6344 double precision, intent(in) :: xO1(nXO1),xO2(nxO2)
6345 double precision, intent(in) :: dxO1(nxO1),dxO2(nxO2)
6346 double precision, intent(in) :: wO(nXO1,nXO2,nWO)
6347
6348 double precision :: origin(1:3), spacing(1:3)
6349 integer :: wholeExtent(1:6)
6350 integer :: iw
6351 integer :: ixC1,ixC2
6352
6353 integer :: filenr
6354 logical :: fileopen
6355 character (70) :: subname,wname,vname,nameL,nameS
6356 character (len=std_len) :: filename
6357 logical :: sph_datres_no_doppler
6358
6359
6360 origin(1)=xo1(1)-0.5d0*dxo1(1)
6361 origin(2)=xo2(1)-0.5d0*dxo2(1)
6362 origin(3)=zero
6363 spacing(1)=dxo1(1)
6364 spacing(2)=dxo2(1)
6365 spacing(3)=one
6366 wholeextent=0
6367 wholeextent(2)=nxo1
6368 wholeextent(4)=nxo2
6369 sph_datres_no_doppler=dat_resolution .and. coordinate==spherical .and. trim(ray_method_active)=='spherical'
6370
6371 if (mype==0) then
6372 inquire(qunit,opened=fileopen)
6373 if(.not.fileopen)then
6374 ! generate filename
6375 filenr=snapshotini
6376 if (autoconvert) filenr=snapshotnext
6377 if (convert_type=='EIvtiCCmpi') then
6378 write(filename,'(a,i4.4,a)') trim(filename_euv),filenr,".vti"
6379 else if (convert_type=='SIvtiCCmpi') then
6380 write(filename,'(a,i4.4,a)') trim(filename_sxr),filenr,".vti"
6381 else if (convert_type=='WIvtiCCmpi') then
6382 write(filename,'(a,i4.4,a)') trim(filename_whitelight),filenr,".vti"
6383 else if (convert_type=='ESvtiCCmpi') then
6384 write(filename,'(a,i4.4,a)') trim(filename_spectrum),filenr,".vti"
6385 endif
6386 open(qunit,file=filename,status='unknown',form='formatted')
6387 endif
6388
6389 ! generate xml header
6390 write(qunit,'(a)')'<?xml version="1.0"?>'
6391 write(qunit,'(a)',advance='no') '<VTKFile type="ImageData"'
6392 write(qunit,'(a)')' version="0.1" byte_order="LittleEndian">'
6393 write(qunit,'(a,3(1pe14.6),a,6(i10),a,3(1pe14.6),a)')' <ImageData Origin="',&
6394 origin,'" WholeExtent="',wholeextent,'" Spacing="',spacing,'">'
6395 ! file info
6396 write(qunit,'(a)')'<FieldData>'
6397 write(qunit,'(2a)')'<DataArray type="Float32" Name="TIME" ',&
6398 'NumberOfTuples="1" format="ascii">'
6399 write(qunit,*) real(global_time*time_convert_factor)
6400 write(qunit,'(a)')'</DataArray>'
6401 write(qunit,'(a)')'</FieldData>'
6402 ! pixel/cell data
6403 write(qunit,'(a,6(i10),a)') '<Piece Extent="',wholeextent,'">'
6404 write(qunit,'(a)')'<CellData>'
6405 do iw=1,nwo
6406 ! variable name
6407 if (convert_type=='EIvtiCCmpi') then
6408 if (wavelength<100) then
6409 write(vname,'(a,i2)') "AIA",wavelength
6410 else if (wavelength<1000) then
6411 write(vname,'(a,i3)') "AIA",wavelength
6412 else
6413 write(vname,'(a,i4)') "IRIS",wavelength
6414 endif
6415 if (trim(emission_model)=='pseudo_current' .and. iw==1) vname='pseudo_current'
6416 if (trim(emission_model)=='radio_ff' .and. iw==1) vname='radio_brightness_temperature'
6417 if (trim(radiation_transfer)=='thick' .and. iw==1) vname=trim(vname)//'_thick'
6418 if (iw==2 .and. dat_resolution .and. (.not. sph_datres_no_doppler) .and. &
6419 trim(emission_model)/='radio_ff' .and. &
6420 trim(emission_model)/='pseudo_current') vname='Doppler_velocity'
6421 if (output_tau .and. trim(radiation_transfer)=='thick' .and. &
6422 ((trim(emission_model)=='radio_ff' .and. iw==2) .or. &
6423 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6424 ((dat_resolution .and. ((sph_datres_no_doppler .and. iw==2) .or. &
6425 ((.not. sph_datres_no_doppler) .and. iw==3))) .or. &
6426 ((.not. dat_resolution) .and. iw==2))))) then
6427 vname='tau'
6428 endif
6429 if (output_absorption_fraction .and. trim(radiation_transfer)=='thick' .and. &
6430 ((trim(emission_model)=='radio_ff' .and. ((output_tau .and. iw==3) .or. &
6431 ((.not. output_tau) .and. iw==2))) .or. &
6432 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6433 ((dat_resolution .and. sph_datres_no_doppler .and. output_tau .and. iw==3) .or. &
6434 (dat_resolution .and. sph_datres_no_doppler .and. (.not. output_tau) .and. iw==2) .or. &
6435 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. output_tau .and. iw==4) .or. &
6436 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. (.not. output_tau) .and. iw==3) .or. &
6437 ((.not. dat_resolution) .and. output_tau .and. iw==3) .or. &
6438 ((.not. dat_resolution) .and. (.not. output_tau) .and. iw==2))))) then
6439 vname='absorption_fraction'
6440 endif
6441 else if (convert_type=='SIvtiCCmpi') then
6442 if (emin_sxr<10 .and. emax_sxr<10) then
6443 write(vname,'(a,i1,a,i1,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6444 else if (emin_sxr<10 .and. emax_sxr>=10) then
6445 write(vname,'(a,i1,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6446 else
6447 write(vname,'(a,i2,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6448 endif
6449 else if (convert_type=='WIvtiCCmpi') then
6450 if (iw==1) write(vname,'(a)')'B'
6451 if (iw==2) write(vname,'(a)')'pB'
6452 else if (convert_type=='ESvtiCCmpi') then
6453 if (spectrum_wl==1354) then
6454 write(vname,'(a,i4)') "SG",spectrum_wl
6455 else
6456 write(vname,'(a,i3)') "EIS",spectrum_wl
6457 endif
6458 endif
6459 write(qunit,'(a,a,a)')&
6460 '<DataArray type="Float64" Name="',trim(vname),'" format="ascii">'
6461 write(qunit,'(200(1pe14.6))') ((wo(ixc1,ixc2,iw),ixc1=1,nxo1),ixc2=1,nxo2)
6462 write(qunit,'(a)')'</DataArray>'
6463 enddo
6464 write(qunit,'(a)')'</CellData>'
6465 write(qunit,'(a)')'</Piece>'
6466 ! end
6467 write(qunit,'(a)')'</ImageData>'
6468 write(qunit,'(a)')'</VTKFile>'
6469 close(qunit)
6470 endif
6471
6472 end subroutine write_image_vticc
6473
6474 subroutine write_image_vtucc(qunit,xC,wC,dxC,nPiece,nC1,nC2,nWC,datatype)
6475 ! write image data to vtu
6477
6478 integer, intent(in) :: qunit
6479 integer, intent(in) :: nPiece,nC1,nC2,nWC
6480 double precision, intent(in) :: xC(nPiece,nC1,nC2,2),dxC(nPiece,nc1,nc2,2)
6481 double precision, intent(in) :: wC(nPiece,nC1,nC2,nWC)
6482 character(20), intent(in) :: datatype
6483
6484 integer :: nP1,nP2
6485 double precision :: xP(nPiece,nC1+1,nC2+1,2)
6486 integer :: filenr
6487 logical :: fileopen
6488 character (70) :: subname,wname,vname,nameL,nameS
6489 character (len=std_len) :: filename
6490 integer :: ixC1,ixC2,ixP,ix1,ix2,j
6491 integer :: nc,np,icel,VTK_type
6492 logical :: sph_datres_no_doppler
6493
6494 np1=nc1+1
6495 np2=nc2+1
6496 np=np1*np2
6497 nc=nc1*nc2
6498 sph_datres_no_doppler=dat_resolution .and. coordinate==spherical .and. trim(ray_method_active)=='spherical'
6499 ! cell corner location
6500 do ixp=1,npiece
6501 do ix1=1,np1
6502 do ix2=1,np2
6503 if (ix1<np1) xp(ixp,ix1,ix2,1)=xc(ixp,ix1,1,1)-0.5d0*dxc(ixp,ix1,1,1)
6504 if (ix1==np1) xp(ixp,ix1,ix2,1)=xc(ixp,ix1-1,1,1)+0.5d0*dxc(ixp,ix1-1,1,1)
6505 if (ix2<np2) xp(ixp,ix1,ix2,2)=xc(ixp,1,ix2,2)-0.5d0*dxc(ixp,1,ix2,2)
6506 if (ix2==np2) xp(ixp,ix1,ix2,2)=xc(ixp,1,ix2-1,2)+0.5d0*dxc(ixp,1,ix2-1,2)
6507 enddo
6508 enddo
6509 enddo
6510 if (mype==0) then
6511 inquire(qunit,opened=fileopen)
6512 if(.not.fileopen)then
6513 ! generate filename
6514 filenr=snapshotini
6515 if (autoconvert) filenr=snapshotnext
6516 if (datatype=='image_euv') then
6517 write(filename,'(a,i4.4,a)') trim(filename_euv),filenr,".vtu"
6518 else if (datatype=='image_sxr') then
6519 write(filename,'(a,i4.4,a)') trim(filename_sxr),filenr,".vtu"
6520 else if (datatype=='image_whitelight') then
6521 write(filename,'(a,i4.4,a)') trim(filename_whitelight),filenr,".vtu"
6522 else if (datatype=='spectrum_euv') then
6523 write(filename,'(a,i4.4,a)') trim(filename_spectrum),filenr,".vtu"
6524 endif
6525 open(qunit,file=filename,status='unknown',form='formatted')
6526 endif
6527 ! generate xml header
6528 write(qunit,'(a)')'<?xml version="1.0"?>'
6529 write(qunit,'(a)',advance='no') '<VTKFile type="UnstructuredGrid"'
6530 write(qunit,'(a)')' version="0.1" byte_order="LittleEndian">'
6531 write(qunit,'(a)')'<UnstructuredGrid>'
6532 write(qunit,'(a)')'<FieldData>'
6533 write(qunit,'(2a)')'<DataArray type="Float32" Name="TIME" ',&
6534 'NumberOfTuples="1" format="ascii">'
6535 write(qunit,*) real(global_time*time_convert_factor)
6536 write(qunit,'(a)')'</DataArray>'
6537 write(qunit,'(a)')'</FieldData>'
6538 do ixp=1,npiece
6539 write(qunit,'(a,i7,a,i7,a)') &
6540 '<Piece NumberOfPoints="',np,'" NumberOfCells="',nc,'">'
6541 write(qunit,'(a)')'<CellData>'
6542 do j=1,nwc
6543 if (datatype=='image_euv') then
6544 if (j==1) then
6545 if (wavelength<100) then
6546 write(vname,'(a,i2)') "AIA",wavelength
6547 else if (wavelength<1000) then
6548 write(vname,'(a,i3)') "AIA",wavelength
6549 else
6550 write(vname,'(a,i4)') "IRIS",wavelength
6551 endif
6552 if (trim(emission_model)=='pseudo_current') vname='pseudo_current'
6553 if (trim(emission_model)=='radio_ff') vname='radio_brightness_temperature'
6554 if (trim(radiation_transfer)=='thick') vname=trim(vname)//'_thick'
6555 endif
6556 if (j==2 .and. dat_resolution .and. (.not. sph_datres_no_doppler) .and. &
6557 trim(emission_model)/='radio_ff' .and. &
6558 trim(emission_model)/='pseudo_current') vname='Doppler_velocity'
6559 if (output_tau .and. trim(radiation_transfer)=='thick' .and. &
6560 ((trim(emission_model)=='radio_ff' .and. j==2) .or. &
6561 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6562 ((dat_resolution .and. ((sph_datres_no_doppler .and. j==2) .or. &
6563 ((.not. sph_datres_no_doppler) .and. j==3))) .or. &
6564 ((.not. dat_resolution) .and. j==2))))) then
6565 vname='tau'
6566 endif
6567 if (output_absorption_fraction .and. trim(radiation_transfer)=='thick' .and. &
6568 ((trim(emission_model)=='radio_ff' .and. ((output_tau .and. j==3) .or. &
6569 ((.not. output_tau) .and. j==2))) .or. &
6570 (trim(emission_model)/='radio_ff' .and. trim(emission_model)/='pseudo_current' .and. &
6571 ((dat_resolution .and. sph_datres_no_doppler .and. output_tau .and. j==3) .or. &
6572 (dat_resolution .and. sph_datres_no_doppler .and. (.not. output_tau) .and. j==2) .or. &
6573 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. output_tau .and. j==4) .or. &
6574 (dat_resolution .and. (.not. sph_datres_no_doppler) .and. (.not. output_tau) .and. j==3) .or. &
6575 ((.not. dat_resolution) .and. output_tau .and. j==3) .or. &
6576 ((.not. dat_resolution) .and. (.not. output_tau) .and. j==2))))) then
6577 vname='absorption_fraction'
6578 endif
6579 else if (datatype=='image_sxr') then
6580 if (emin_sxr<10 .and. emax_sxr<10) then
6581 write(vname,'(a,i1,a,i1,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6582 else if (emin_sxr<10 .and. emax_sxr>=10) then
6583 write(vname,'(a,i1,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6584 else
6585 write(vname,'(a,i2,a,i2,a)') "SXR",emin_sxr,"-",emax_sxr,"keV"
6586 endif
6587 else if (datatype=='image_whitelight') then
6588 write(vname,'(a)')'whitelight'
6589 else if (datatype=='spectrum_euv') then
6590 if (spectrum_wl==1354) then
6591 write(vname,'(a,i4)') "SG",spectrum_wl
6592 else
6593 write(vname,'(a,i3)') "EIS",spectrum_wl
6594 endif
6595 endif
6596 write(qunit,'(a,a,a)')&
6597 '<DataArray type="Float64" Name="',trim(vname),'" format="ascii">'
6598 write(qunit,'(200(1pe14.6))') ((wc(ixp,ixc1,ixc2,j),ixc1=1,nc1),ixc2=1,nc2)
6599 write(qunit,'(a)')'</DataArray>'
6600 enddo
6601 write(qunit,'(a)')'</CellData>'
6602 write(qunit,'(a)')'<Points>'
6603 write(qunit,'(a)')'<DataArray type="Float32" NumberOfComponents="3" format="ascii">'
6604 do ix2=1,np2
6605 do ix1=1,np1
6606 if (datatype=='image_euv' .and. dat_resolution) then
6607 if (los_phi==0 .and. los_theta==90) then
6608 write(qunit,'(3(1pe14.6))') 0.d0,xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2)
6609 else if (los_phi==90 .and. los_theta==90) then
6610 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,2),0.d0,xp(ixp,ix1,ix2,1)
6611 else
6612 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2),0.d0
6613 endif
6614 else if (datatype=='image_sxr' .and. dat_resolution) then
6615 if (los_phi==0 .and. los_theta==90) then
6616 write(qunit,'(3(1pe14.6))') 0.d0,xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2)
6617 else if (los_phi==90 .and. los_theta==90) then
6618 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,2),0.d0,xp(ixp,ix1,ix2,1)
6619 else
6620 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2),0.d0
6621 endif
6622 else
6623 write(qunit,'(3(1pe14.6))') xp(ixp,ix1,ix2,1),xp(ixp,ix1,ix2,2),0.d0
6624 endif
6625 enddo
6626 enddo
6627 write(qunit,'(a)')'</DataArray>'
6628 write(qunit,'(a)')'</Points>'
6629 ! connetivity part
6630 write(qunit,'(a)')'<Cells>'
6631 write(qunit,'(a)')'<DataArray type="Int32" Name="connectivity" format="ascii">'
6632 do ix2=1,nc2
6633 do ix1=1,nc1
6634 write(qunit,'(4(i7))') ix1-1+(ix2-1)*np1,ix1+(ix2-1)*np1,&
6635 ix1-1+ix2*np1,ix1+ix2*np1
6636 enddo
6637 enddo
6638 write(qunit,'(a)')'</DataArray>'
6639 ! offsets data array
6640 write(qunit,'(a)')'<DataArray type="Int32" Name="offsets" format="ascii">'
6641 do icel=1,nc
6642 write(qunit,'(i7)') icel*(2**2)
6643 enddo
6644 write(qunit,'(a)')'</DataArray>'
6645 ! VTK cell type data array
6646 write(qunit,'(a)')'<DataArray type="Int32" Name="types" format="ascii">'
6647 ! VTK_LINE=3; VTK_PIXEL=8; VTK_VOXEL=11 -> vtk-syntax
6648 vtk_type=8
6649 do icel=1,nc
6650 write(qunit,'(i2)') vtk_type
6651 enddo
6652 write(qunit,'(a)')'</DataArray>'
6653 write(qunit,'(a)')'</Cells>'
6654 write(qunit,'(a)')'</Piece>'
6655 enddo
6656 write(qunit,'(a)')'</UnstructuredGrid>'
6657 write(qunit,'(a)')'</VTKFile>'
6658 close(qunit)
6659 endif
6660 end subroutine write_image_vtucc
6661
6662 subroutine dot_product_loc(vec1,vec2,res)
6663 double precision, intent(in) :: vec1(1:3),vec2(1:3)
6664 double precision, intent(out) :: res
6665
6666 res=vec1(1)*vec2(1)+vec1(2)*vec2(2)+vec1(3)*vec2(3)
6667
6668 end subroutine dot_product_loc
6669
6670 subroutine cross_product_loc(vec_in1,vec_in2,vec_out)
6671 double precision, intent(in) :: vec_in1(1:3),vec_in2(1:3)
6672 double precision, intent(out) :: vec_out(1:3)
6673
6674 vec_out(1)=vec_in1(2)*vec_in2(3)-vec_in1(3)*vec_in2(2)
6675 vec_out(2)=vec_in1(3)*vec_in2(1)-vec_in1(1)*vec_in2(3)
6676 vec_out(3)=vec_in1(1)*vec_in2(2)-vec_in1(2)*vec_in2(1)
6677
6678 end subroutine cross_product_loc
6679
6681 integer :: j
6682 double precision :: LOS_psi
6683 double precision :: vec_car(1:3),vec_z(1:3),vec_temp1(1:3),vec_temp2(1:3)
6684 double precision :: vec_LOS_sph(1:3),vec_xI1_sph(1:3),vec_xI2_sph(1:3)
6685
6686 ! antiparallel to LOS in spherical
6687 vec_los(1)=1.d0
6688 vec_los(2)=dpi*los_theta/180.d0
6689 vec_los(3)=dpi*los_phi/180.d0
6690 ! LOS in cartesian
6691 call spherical_to_cartesian(vec_los,vec_car)
6692 vec_los=-vec_car
6693
6694 ! theta=0 in cartesian
6695 vec_z(:)=zero
6696 vec_z(3)=1.d0
6697
6698 ! x direction for image
6699 if (los_theta==zero) then
6700 vec_temp1(1)=1.d0
6701 vec_temp1(2)=dpi/2.d0
6702 vec_temp1(3)=dpi*los_phi/180.d0
6703 call spherical_to_cartesian(vec_temp1,vec_car)
6704 vec_temp1=-vec_car
6705 call cross_product_loc(vec_temp1,vec_z,vec_xi1)
6706 else
6708 endif
6709
6710 ! y direction for image
6712
6713 ! rotate the image
6714 vec_temp1=vec_xi1/sqrt(vec_xi1(1)**2+vec_xi1(2)**2+vec_xi1(3)**2)
6715 vec_temp2=vec_xi2/sqrt(vec_xi2(1)**2+vec_xi2(2)**2+vec_xi2(3)**2)
6716 los_psi=dpi*image_rotate/180.d0
6717 vec_xi1=vec_temp1*cos(los_psi)-vec_temp2*sin(los_psi)
6718 vec_xi2=vec_temp2*cos(los_psi)+vec_temp1*sin(los_psi)
6719
6720 do j=1,3
6721 if (abs(vec_los(j))<smalldouble) vec_los(j)=zero
6722 if (abs(vec_xi1(j))<smalldouble) vec_xi1(j)=zero
6723 if (abs(vec_xi2(j))<smalldouble) vec_xi2(j)=zero
6724 enddo
6725
6726 call cartesian_to_spherical(vec_los,vec_los_sph)
6727 call cartesian_to_spherical(vec_xi1,vec_xi1_sph)
6728 call cartesian_to_spherical(vec_xi2,vec_xi2_sph)
6729 vec_los_sph(2:3)=vec_los_sph(2:3)*180.d0/dpi
6730 vec_xi1_sph(2:3)=vec_xi1_sph(2:3)*180.d0/dpi
6731 vec_xi2_sph(2:3)=vec_xi2_sph(2:3)*180.d0/dpi
6732
6733 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),']'
6734 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),']'
6735 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),']'
6736
6737 end subroutine init_vectors_spherical
6738
6739 subroutine spherical_to_cartesian(vec_sph,vec_car)
6740 ! angles in rad
6741 double precision, intent(in) :: vec_sph(1:3)
6742 double precision, intent(inout) :: vec_car(1:3)
6743
6744 vec_car(1)=vec_sph(1)*dsin(vec_sph(2))*dcos(vec_sph(3))
6745 vec_car(2)=vec_sph(1)*dsin(vec_sph(2))*dsin(vec_sph(3))
6746 vec_car(3)=vec_sph(1)*dcos(vec_sph(2))
6747
6748 end subroutine spherical_to_cartesian
6749
6750 subroutine cartesian_to_spherical(vec_car,vec_sph)
6751 ! angles in rad
6752 double precision, intent(in) :: vec_car(1:3)
6753 double precision, intent(inout) :: vec_sph(1:3)
6754
6755 vec_sph(1)=dsqrt(vec_car(1)**2+vec_car(2)**2+vec_car(3)**2)
6756 vec_sph(2)=dacos(vec_car(3)/vec_sph(1))
6757 vec_sph(3)=atan2(vec_car(2),vec_car(1))
6758
6759 end subroutine cartesian_to_spherical
6760
6762 integer :: j
6763 double precision :: LOS_psi
6764 double precision :: vec_z(1:3),vec_temp1(1:3),vec_temp2(1:3)
6765
6766 ! vectors for image coordinate
6767 vec_los(1)=-cos(dpi*los_phi/180.d0)*sin(dpi*los_theta/180.d0)
6768 vec_los(2)=-sin(dpi*los_phi/180.d0)*sin(dpi*los_theta/180.d0)
6769 vec_los(3)=-cos(dpi*los_theta/180.d0)
6770 do j=1,3
6771 if (abs(vec_los(j))<=smalldouble) vec_los(j)=zero
6772 enddo
6773 vec_z(:)=zero
6774 vec_z(3)=1.d0
6775 if (los_theta==zero) then
6776 vec_xi1(1)=cos(dpi*los_phi/180.d0)
6777 vec_xi1(2)=sin(dpi*los_phi/180.d0)
6778 vec_xi1(3)=zero
6779 else
6781 endif
6783 vec_temp1=vec_xi1/sqrt(vec_xi1(1)**2+vec_xi1(2)**2+vec_xi1(3)**2)
6784 vec_temp2=vec_xi2/sqrt(vec_xi2(1)**2+vec_xi2(2)**2+vec_xi2(3)**2)
6785 los_psi=dpi*image_rotate/180.d0
6786 vec_xi1=vec_temp1*cos(los_psi)-vec_temp2*sin(los_psi)
6787 vec_xi2=vec_temp2*cos(los_psi)+vec_temp1*sin(los_psi)
6788
6789 do j=1,3
6790 if (abs(vec_xi1(j))<smalldouble) vec_xi1(j)=zero
6791 if (abs(vec_xi2(j))<smalldouble) vec_xi2(j)=zero
6792 enddo
6793
6794 if (mype==0) write(*,'(a,f5.2,f6.2,f6.2,a)') ' LOS vector: [',vec_los(1),vec_los(2),vec_los(3),']'
6795 if (mype==0) write(*,'(a,f5.2,f6.2,f6.2,a)') ' xI1 vector: [',vec_xi1(1),vec_xi1(2),vec_xi1(3),']'
6796 if (mype==0) write(*,'(a,f5.2,f6.2,f6.2,a)') ' xI2 vector: [',vec_xi2(1),vec_xi2(2),vec_xi2(3),']'
6797
6798 end subroutine init_vectors_cartesian
6799
6800 subroutine get_cor_image_spherical(x_3D_sph,x_image)
6801 double precision, intent(in) :: x_3D_sph(1:3)
6802 double precision, intent(inout) :: x_image(1:2)
6803 double precision :: res,res_origin
6804 double precision :: x_3D(1:3)
6805
6806 call spherical_to_cartesian(x_3d_sph,x_3d)
6807 call dot_product_loc(x_3d,vec_xi1,res)
6808 x_image(1)=res
6809 call dot_product_loc(x_3d,vec_xi2,res)
6810 x_image(2)=res
6811
6812 end subroutine get_cor_image_spherical
6813
6814 subroutine get_cor_image(x_3D,x_image)
6815 double precision, intent(in) :: x_3D(1:3)
6816 double precision, intent(inout) :: x_image(1:2)
6817 double precision :: res,res_origin
6818
6819 call dot_product_loc(x_3d,vec_xi1,res)
6820 call dot_product_loc(x_origin,vec_xi1,res_origin)
6821 x_image(1)=res-res_origin
6822 call dot_product_loc(x_3d,vec_xi2,res)
6823 call dot_product_loc(x_origin,vec_xi2,res_origin)
6824 x_image(2)=res-res_origin
6825
6826 end subroutine get_cor_image
6827
6828end 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)