-
Notifications
You must be signed in to change notification settings - Fork 5
/
evolve_source.F90
593 lines (520 loc) · 18.3 KB
/
evolve_source.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
!>
!! \brief This module contains routines for calculating the effect (ionization
!! and heating) of one source (3D).
!! The routines in this module handle the stepping through the (3D) grid.
!! The actual work is done per grid point using the routines in the
!! module evolve_point.
!!
!! Module for Capreole / C2-Ray (f90)
!!
!! \b Author: Garrelt Mellema
!!
!! \b Date: 2013-09-05
!!
!! \b Version: 3D, MPI & OpenMP
module evolve_source
use precision, only: dp
use my_mpi ! supplies all the MPI and OpenMP definitions and variables
use file_admin, only: logf,timefile,iterdump, results_dir, dump_dir
use abundances, only: abu_he
use c2ray_parameters, only: subboxsize, max_subbox, loss_fraction
use sizes, only: Ndim, mesh
use sourceprops, only: NumSrc, srcpos, NormFlux_stellar, NormFlux_xray !SrcSeries
use radiation_sed_parameters, only: S_star, pl_S_star
use photonstatistics, only: photon_loss
use evolve_data, only: periodic_bc
use evolve_data, only: coldensh_out
use evolve_data, only: photon_loss_src_thread
use evolve_data, only: last_l,last_r
use evolve_data, only: tn
use evolve_point, only: evolve0d
implicit none
save
private
! mesh positions of end points for RT
integer,dimension(Ndim) :: lastpos_l !< mesh position of left end point for RT
integer,dimension(Ndim) :: lastpos_r !< mesh position of right end point for RT
integer,public :: sum_nbox !< sum of all nboxes (on one processor)
integer,public :: sum_nbox_all !< sum of all nboxes (on all processors)
real(kind=dp) :: photon_loss_src
public do_source
contains
! ===========================================================================
!> Does the ray-tracing over the entire 3D grid for one source.
!! The number of this source in the current list is ns1.
subroutine do_source(dt,ns1,niter)
! Does the ray-tracing over the entire 3D grid for one source.
! The number of this source in the current list is ns1.
real(kind=dp),intent(in) :: dt !< time step, passed on to evolve0D
integer, intent(in) :: ns1 !< number of the source being done
integer,intent(in) :: niter !< interation counter, passed on to evolve0D
integer :: naxis,nplane,nquadrant
integer :: ns
integer :: k
integer :: nbox
integer :: nnt
integer :: logf1
! Total ionizing photon rate of all contributions to the source
real(kind=dp) :: total_source_flux
! Mesh position of the cell being treated
integer,dimension(Ndim) :: rtpos
! Pick up source number from the source list
!ns=SrcSeries(ns1)
ns=ns1
! Report on source
!write(logf,*) "Source number: ",ns
!write(logf,*) NormFlux_stellar(ns)
!write(logf,*) srcpos(:,ns)
! reset column densities for new source point
! coldensh_out is unique for each source point
coldensh_out(:,:,:)=0.0
! Find the mesh position for the end points of the loop
! We trace until we reach max_subbox (set in c2ray_parameters)
! or the end of the grid. In the periodic case the end of the
! grid is always mesh/2 away from the source. If the grid is
! even-sized we trave mesh/2 cells to the left and mesh/2-1
! cell to the right. If it is odd, it is mesh/2 in either direction.
! The mod(mesh,2) takes care of handling this.
if (periodic_bc) then
lastpos_r(:)=srcpos(:,ns)+min(max_subbox,mesh(:)/2-1+mod(mesh(:),2))
lastpos_l(:)=srcpos(:,ns)-min(max_subbox,mesh(:)/2)
else
lastpos_r(:)=min(srcpos(:,ns)+max_subbox,mesh(:))
lastpos_l(:)=max(srcpos(:,ns)-max_subbox,1)
endif
! Loop through grid in the order required by
! short characteristics
! Transfer is done in a set of cubes of increasing size.
! If the HII region is small we do not waste time calculating
! column densities of parts of the grid where no radiation
! penetrates. To test whether the current subbox is large
! enough we use the photon_loss_src. If this is non-zero,
! photons are leaving this subbox and we need to do another
! one. We also stop once we have done the whole grid.
nbox=0 ! subbox counter
total_source_flux=NormFlux_stellar(ns)*S_star !&
! + NormFlux_xray(ns)*pl_S_star
photon_loss_src=total_source_flux !-1.0 ! to pass the first while test
last_r(:)=srcpos(:,ns) ! to pass the first while test
last_l(:)=srcpos(:,ns) ! to pass the first while test
! Loop through boxes of increasing size
! NOTE: make this limit on the photon_loss a fraction of
! a source flux loss_fraction*NormFlux_stellar(ns)*S_star)
do while (photon_loss_src > loss_fraction*total_source_flux &
!do while (all(photon_loss_src(:) /= 0.0) &
.and. last_r(3) < lastpos_r(3) &
.and. last_l(3) > lastpos_l(3))
nbox=nbox+1 ! increase subbox counter
photon_loss_src = 0.0 ! reset photon_loss_src to zero
photon_loss_src_thread(:) = 0.0 ! reset photon_loss_src to zero
last_r(:)=min(srcpos(:,ns)+subboxsize*nbox,lastpos_r(:))
last_l(:)=max(srcpos(:,ns)-subboxsize*nbox,lastpos_l(:))
! OpenMP: if we have multiple OpenMP threads (nthreads > 1) we
! parallelize over the threads by doing independent parts of
! the mesh.
if (nthreads > 1) then ! OpenMP parallelization
! First do source point (on first pass)
if (nbox == 1) then
rtpos(:)=srcpos(:,ns)
call evolve0D(dt,rtpos,ns,niter)
endif
! do independent areas of the mesh in parallel using OpenMP
!$omp parallel default(shared) private(tn)
!!!reduction(+:photon_loss_src)
! Find out your thread number
#ifdef MY_OPENMP
tn=omp_get_thread_num()+1
#else
tn=1
#endif
! Then do the the axes
!$omp do schedule(dynamic,1)
do naxis=1,6
call evolve1D_axis(dt,ns,niter,naxis)
enddo
!$omp end do
! Then the source planes
!$omp do schedule (dynamic,1)
do nplane=1,12
call evolve2D_plane(dt,ns,niter,nplane)
end do
!$omp end do
! Then the quadrants
!$omp do schedule (dynamic,1)
do nquadrant=1,8
call evolve3D_quadrant(dt,ns,niter,nquadrant)
end do
!$omp end do
!$omp end parallel
! Collect photon losses for each thread
do nnt=1,nthreads
photon_loss_src=photon_loss_src + &
photon_loss_src_thread(nnt)
enddo
else ! No OpenMP parallelization
! 1. transfer in the upper part of the grid
! (srcpos(3)-plane and above)
do k=srcpos(3,ns),last_r(3)
rtpos(3)=k
call evolve2D(dt,rtpos,ns,niter)
end do
! 2. transfer in the lower part of the grid (below srcpos(3))
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
call evolve2D(dt,rtpos,ns,niter)
end do
! No OpenMP threads so we use position 1
! GM/121127: previous versions of the code did not have
! the variable tn set to 1 if we were not running OpenMP.
! This led to non-photon-conservations (and should have
! led to memory errors...)
photon_loss_src=photon_loss_src_thread(1)
endif
enddo
! Record the final photon loss, this is the photon loss that leaves
! the grid.
photon_loss(1)=photon_loss(1) + photon_loss_src
! Sum the total number of subboxes used for reporting later
sum_nbox=sum_nbox+nbox
end subroutine do_source
! ===========================================================================
!> Traverse a z-plane (z=rtpos(3)) by sweeping in the x and y
!! directions.
subroutine evolve2D(dt,rtpos,ns,niter)
! Traverse a z-plane (z=rtpos(3)) by sweeping in the x and y
! directions.
real(kind=dp),intent(in) :: dt !! passed on to evolve0D
integer,dimension(Ndim),intent(inout) :: rtpos !< mesh position, pos(3) is
!! intent(in)
integer,intent(in) :: ns !< current source
integer,intent(in) :: niter !< passed on to evolve0D
integer :: i,j ! mesh positions
! sweep in `positive' j direction
do j=srcpos(2,ns),last_r(2)
rtpos(2)=j
do i=srcpos(1,ns),last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) ! `positive' i
end do
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) ! `negative' i
end do
end do
! sweep in `negative' j direction
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
do i=srcpos(1,ns),last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) ! `positive' i
end do
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) ! `negative' i
end do
end do
end subroutine evolve2D
! ===========================================================================
! Ray tracing for the axes going through the source point
! should be called after having done the source point
subroutine evolve1D_axis(dt,ns,niter,naxis)
real(kind=dp),intent(in) :: dt ! passed on to evolve0D
integer,intent(in) :: ns ! current source
integer,intent(in) :: niter ! passed on to evolve0D
integer,intent(in) :: naxis ! axis to do
integer :: i,j,k
integer,dimension(Ndim) :: rtpos ! mesh position
select case (naxis)
case(1)
! sweep in +i direction
rtpos(2:3)=srcpos(2:3,ns)
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `positive' i
enddo
case(2)
! sweep in -i direction
rtpos(2:3)=srcpos(2:3,ns)
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `negative' i
end do
case(3)
! sweep in +j direction
rtpos(1)=srcpos(1,ns)
rtpos(3)=srcpos(3,ns)
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
call evolve0D(dt,rtpos,ns,niter) !# `positive' j
end do
case(4)
! sweep in -j direction
rtpos(1)=srcpos(1,ns)
rtpos(3)=srcpos(3,ns)
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
call evolve0D(dt,rtpos,ns,niter) !# `negative' j
end do
case(5)
! sweep in +k direction
rtpos(1:2)=srcpos(1:2,ns)
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
call evolve0D(dt,rtpos,ns,niter) !# `positive' k
end do
case(6)
! sweep in -k direction
rtpos(1:2)=srcpos(1:2,ns)
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
call evolve0D(dt,rtpos,ns,niter) !# `negative' k
end do
end select
end subroutine evolve1D_axis
! ===========================================================================
!> Ray tracing for planes containing the source point
!! should be called after evolve1D_axis
subroutine evolve2D_plane(dt,ns,niter,nplane)
! find column density for the axes going through the source point
! should be called after having done the source point
real(kind=dp),intent(in) :: dt ! passed on to evolve0D
integer,intent(in) :: ns ! current source
integer,intent(in) :: niter ! passed on to evolve0D
integer,intent(in) :: nplane ! plane to do
integer :: i,j,k
integer,dimension(Ndim) :: rtpos ! mesh position
select case (nplane)
case(1)
! sweep in +i,+j direction
rtpos(3)=srcpos(3,ns)
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(2)
! sweep in +i,-j direction
rtpos(3)=srcpos(3,ns)
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(3)
! sweep in -i,+j direction
rtpos(3)=srcpos(3,ns)
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(4)
! sweep in -i,-j direction
rtpos(3)=srcpos(3,ns)
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(5)
! sweep in +i,+k direction
rtpos(2)=srcpos(2,ns)
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(6)
! sweep in -i,+k direction
rtpos(2)=srcpos(2,ns)
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(7)
! sweep in -i,-k direction
rtpos(2)=srcpos(2,ns)
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(8)
! sweep in +i,-k direction
rtpos(2)=srcpos(2,ns)
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(9)
! sweep in +j,+k direction
rtpos(1)=srcpos(1,ns)
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(10)
! sweep in -j,+k direction
rtpos(1)=srcpos(1,ns)
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(11)
! sweep in +j,-k direction
rtpos(1)=srcpos(1,ns)
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
case(12)
! sweep in -j,-k direction
rtpos(1)=srcpos(1,ns)
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
call evolve0D(dt,rtpos,ns,niter)
enddo
enddo
end select
end subroutine evolve2D_plane
! ===========================================================================
!> Ray tracing for the 8 octants
!! should be called after evolve2D_plane
subroutine evolve3D_quadrant(dt,ns,niter,nquadrant)
! find column density for a z-plane srcpos(3) by sweeping in x and y
! directions
real(kind=dp),intent(in) :: dt ! passed on to evolve0D
integer,intent(in) :: ns ! current source
integer,intent(in) :: niter ! passed on to evolve0D
integer,intent(in) :: nquadrant ! which quadrant to do
integer :: i,j,k
integer,dimension(Ndim) :: rtpos ! mesh position
select case (nquadrant)
case (1)
! sweep in +i,+j,+k direction
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter)
end do
enddo
enddo
case (2)
! sweep in -i,+j,+k direction
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `negative' i
end do
end do
enddo
case (3)
! sweep in +i,-j,+k direction
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `negative' i
end do
end do
enddo
case(4)
! sweep in -i,-j,+k direction
do k=srcpos(3,ns)+1,last_r(3)
rtpos(3)=k
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `negative' i
end do
end do
enddo
case (5)
! sweep in +i,+j,-k direction
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `positive' i
end do
enddo
enddo
case (6)
! sweep in -i,+j,-k direction
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do j=srcpos(2,ns)+1,last_r(2)
rtpos(2)=j
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `negative' i
end do
end do
enddo
case (7)
! sweep in +i,-j,-k direction
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
do i=srcpos(1,ns)+1,last_r(1)
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `negative' i
end do
end do
enddo
case(8)
! sweep in -i,-j,-k direction
do k=srcpos(3,ns)-1,last_l(3),-1
rtpos(3)=k
do j=srcpos(2,ns)-1,last_l(2),-1
rtpos(2)=j
do i=srcpos(1,ns)-1,last_l(1),-1
rtpos(1)=i
call evolve0D(dt,rtpos,ns,niter) !# `negative' i
end do
end do
enddo
end select
end subroutine evolve3D_quadrant
end module evolve_source