-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathread.f90
More file actions
620 lines (495 loc) · 22 KB
/
Copy pathread.f90
File metadata and controls
620 lines (495 loc) · 22 KB
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
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
submodule (grid) grid_read
implicit none
interface ! readgrid_{raw,hdf5,nc4}.f90
module subroutine get_grid3(path, flagswap, x, g1all,g2all,g3all, altall,glatall,glonall,Bmagall,Incall,nullptsall,&
e1all,e2all,e3all,erall,ethetaall,ephiall,rall,thetaall,phiall)
character(*), intent(in) :: path
integer, intent(in) :: flagswap
type(curvmesh), intent(inout) :: x
real(wp), intent(out), dimension(:,:,:) :: g1all,g2all,g3all,altall,glatall,glonall,Bmagall,nullptsall,rall,thetaall,phiall
real(wp), intent(out), dimension(:,:) :: Incall
real(wp), intent(out), dimension(:,:,:,:) :: e1all,e2all,e3all,erall,ethetaall,ephiall
end subroutine get_grid3
end interface
contains
module procedure read_grid
! subroutine read_grid(indatsize,indatgrid,flagperiodic,x)
!! READS GRID INFORMATION FROM A BBINARY FILE AND ALLOCATES
!! GRID STRUCTURE. NOTE THAT THE INPUT FILE DOES NOT,
!! BY DEFAULT INCLUDE THE GHOST CELLS. THIS FUNCTION
!! IS A WRAPPER WHICH PASSES WORK OFF TO APPROPRIATE
!! SUBROUTINE DEPENDING ON WHETHER IT IS CALLED BY ROOT
!! OR NOT. THIS SUBRoutINE ALSO CLASSIFIES THE GRID.
!> READ IN THE GRID DATA
if(myid==0) then
call read_grid_root(indatsize,indatgrid,x)
else
call read_grid_workers(x)
end if
!FLAG THE GRID AS PERIODIC, IF REQUESTED; IF SO PERIODICITY WILL BE ASSUMED
!IN THE X3-DIRECTION, NOTE BOTH ROOT AND WORKERS MUST DO THIS!!!
if (flagperiodic==1) then
x%flagper=.true.
else
x%flagper=.false.
end if
!DETERMINE THE TYPE OF GRID WE HAVE AND SET AN APPROPRIATE FLAG
!FIXME: this needs to be done once, globally and also needs to be more
!robust...
if (abs(x%alt(1,1,1)-x%alt(lx1,1,1))<100d3) then !closed dipole grid
gridflag=0
else if (x%alt(1,1,1)>x%alt(2,1,1)) then !open dipole grid with inverted structure wrt altitude
gridflag=1
else !something different (viz. non-inverted - lowest altitudes at the logical bottom of the grid)
gridflag=2
end if
end procedure read_grid
subroutine read_grid_root(indatsize,indatgrid,x)
!------------------------------------------------------------
!--------SOME CODE DUPLICATION WITH WORKER VERSION - CAN WE
!--------CREATE A COMMON SUBROUTINE THAT ALLOCATES SOME VARS?
!--------THE GRID SIZES MUST ALREADY BE DEFINED IN TEH MODULE
!--------, PROBABLY FROM CALLING GRID_SIZE
!------------------------------------------------------------
character(*), intent(in) :: indatsize,indatgrid
type(curvmesh), intent(inout) :: x !does this need to be inout? I think if anything is unallocated, it does...
integer u,ierr,iid,ix1,ix2,ix3,icount,icomp!,itell
!NOTE THAT HAVING THESE ARE LOCAL (TEMPORARY) VARS. PREVENTS ROOT FROM WRITING ENTIRE GRID TO FILE AT SOME LATER POINT...
real(wp), dimension(:,:,:), allocatable :: g1all,g2all,g3all !to temporarily store input data to be distributed
real(wp), dimension(:,:,:), allocatable :: altall,glatall,glonall
real(wp), dimension(:,:,:), allocatable :: rall,thetaall,phiall
real(wp), dimension(:,:,:), allocatable :: Bmagall
real(wp), dimension(:,:), allocatable :: Incall
real(wp), dimension(:,:,:), allocatable :: nullptsall
real(wp), dimension(:,:,:,:), allocatable :: e1all,e2all,e3all,erall,ethetaall,ephiall !might be best to have a tmp vector array...
real(wp), dimension(:,:,:), allocatable :: mpisendbuf
real(wp), dimension(:,:,:), allocatable :: mpirecvbuf
!print*, 'Entering read_grid_root', lx1,lx2all,lx3all,lid2,lid3,lx2all/lid2
!DETERMINE NUMBER OF SLABS AND CORRESPONDING SIZE FOR EACH WORKER
!NOTE THAT WE WILL ASSUME THAT THE GRID SIZE IS DIVISIBLE BY NUMBER OF WORKERS AS THIS HAS BEEN CHECKED A FEW LINES BELOW
x%lx1=lx1; x%lx2all=lx2all; x%lx3all=lx3all;
!> ADJUST THE SIZES OF THE VARIABLES IF LX3ALL==1, SO THAT THE ALLOCATIONS ARE THE CORRECT SIZE
if (lx3all==1) then
print *, '2D run: **SWAP** x2 and x3 dims'
lx3all=lx2all; x%lx3all=lx2all;
lx2=1
lx2all=1; x%lx2all=1;
lx3=lx3all/lid
!! use total number of processes since we only divide in one direction here...
flagswap=1
else
if(lx2all==1) then
print *, '2D run: do not swap x2 and x3 dims.'
lx2=1
lx3=lx3all/lid
else
print *, '3D run'
lx2=lx2all/lid2
!! should divide evenly if generated from mpigrid
lx3=lx3all/lid3
endif
flagswap=0
end if
x%lx2=lx2; x%lx3=lx3
print '(A,3I6)', 'Grid slab size: ',lx1,lx2,lx3
!> COMMUNICATE THE GRID SIZE TO THE WORKERS SO THAT THEY CAN ALLOCATE SPACE
ierr=0
!! if this is a root-only simulation we don't want to error out
do iid=1,lid-1
call mpi_send(lx2,1,MPI_INTEGER,iid,taglx2,MPI_COMM_WORLD,ierr)
!! need to also pass the lx2all size to all workers to they know
!if (ierr/=0) error stop 'grid:read_grid_root failed mpi_send lx2'
call mpi_send(lx3,1,MPI_INTEGER,iid,taglx3,MPI_COMM_WORLD,ierr)
!if (ierr/=0) error stop 'grid:read_grid_root failed mpi_send lx3'
end do
if (ierr/=0) error stop 'grid:read_grid_root failed mpi_send grid size'
!TELL WORKERS IF WE'VE SWAPPED DIMENSIONS
ierr=0
do iid=1,lid-1
call mpi_send(flagswap,1,MPI_INTEGER,iid,tagswap,MPI_COMM_WORLD,ierr)
!if (ierr/=0) error stop 'grid:read_grid_root failed mpi_send flagswap'
end do
if (ierr/=0) error stop 'grid:read_grid_root failed mpi_send flagswap'
!ALLOCATE SPACE FOR ROOTS SLAB OF DATA
allocate(x%x1(-1:lx1+2))
allocate(x%dx1i(lx1),x%x1i(lx1+1),x%dx1(0:lx1+2))
!FULL GRID X2 VARIABLE
allocate(x%x2all(-1:lx2all+2))
allocate(x%dx2all(0:lx2all+2))
allocate(x%dx2iall(lx2all),x%x2iall(lx2all+1))
!FULL-GRID X3-VARIABLE
allocate(x%x3all(-1:lx3all+2))
allocate(x%dx3all(0:lx3all+2))
allocate(x%x3iall(lx3all+1),x%dx3iall(lx3all))
allocate(x%h1all(-1:lx1+2,-1:lx2all+2,-1:lx3all+2),x%h2all(-1:lx1+2,-1:lx2all+2,-1:lx3all+2), &
x%h3all(-1:lx1+2,-1:lx2all+2,-1:lx3all+2)) !do we need the ghost cell values? Yes the divergence in compression term is computed using one ghost cell in each direction!!!!
allocate(x%h1x1iall(1:lx1+1,1:lx2all,1:lx3all),x%h2x1iall(1:lx1+1,1:lx2all,1:lx3all), &
x%h3x1iall(1:lx1+1,1:lx2all,1:lx3all))
allocate(x%h1x2iall(1:lx1,1:lx2all+1,1:lx3all),x%h2x2iall(1:lx1,1:lx2all+1,1:lx3all), &
x%h3x2iall(1:lx1,1:lx2all+1,1:lx3all))
allocate(x%h1x3iall(1:lx1,1:lx2all,1:lx3all+1),x%h2x3iall(1:lx1,1:lx2all,1:lx3all+1), &
x%h3x3iall(1:lx1,1:lx2all,1:lx3all+1))
allocate(x%rall(1:lx1,1:lx2all,1:lx3all),x%thetaall(1:lx1,1:lx2all,1:lx3all),x%phiall(1:lx1,1:lx2all,1:lx3all))
!DETERMINE AND ALLOCATE SPACE NEEDED FOR ROOT SUBGRIDS (WORKERS USE SIMILAR ALLOCATE STATEMENTS)
allocate(x%x3(-1:lx3+2))
allocate(x%dx3i(lx3),x%x3i(lx3+1),x%dx3(0:lx3+2))
allocate(x%x2(-1:lx2+2))
allocate(x%dx2i(lx2),x%x2i(lx2+1),x%dx2(0:lx2+2))
allocate(x%h1(-1:lx1+2,-1:lx2+2,-1:lx3+2),x%h2(-1:lx1+2,-1:lx2+2,-1:lx3+2),x%h3(-1:lx1+2,-1:lx2+2,-1:lx3+2))
! allocate(x%h1(1:lx1,1:lx2,1:lx3),x%h2(1:lx1,1:lx2,1:lx3),x%h3(1:lx1,1:lx2,1:lx3))
allocate(x%h1x1i(1:lx1+1,1:lx2,1:lx3),x%h2x1i(1:lx1+1,1:lx2,1:lx3),x%h3x1i(1:lx1+1,1:lx2,1:lx3))
allocate(x%h1x2i(1:lx1,1:lx2+1,1:lx3),x%h2x2i(1:lx1,1:lx2+1,1:lx3),x%h3x2i(1:lx1,1:lx2+1,1:lx3))
allocate(x%h1x3i(1:lx1,1:lx2,1:lx3+1),x%h2x3i(1:lx1,1:lx2,1:lx3+1),x%h3x3i(1:lx1,1:lx2,1:lx3+1))
allocate(x%glat(1:lx1,1:lx2,1:lx3),x%glon(1:lx1,1:lx2,1:lx3),x%alt(1:lx1,1:lx2,1:lx3))
allocate(x%r(1:lx1,1:lx2,1:lx3),x%theta(1:lx1,1:lx2,1:lx3),x%phi(1:lx1,1:lx2,1:lx3))
allocate(x%Bmag(1:lx1,1:lx2,1:lx3))
allocate(x%I(1:lx2,1:lx3))
allocate(x%nullpts(1:lx1,1:lx2,1:lx3))
allocate(x%e1(1:lx1,1:lx2,1:lx3,1:3),x%e2(1:lx1,1:lx2,1:lx3,1:3),x%e3(1:lx1,1:lx2,1:lx3,1:3))
allocate(x%er(1:lx1,1:lx2,1:lx3,1:3),x%etheta(1:lx1,1:lx2,1:lx3,1:3),x%ephi(1:lx1,1:lx2,1:lx3,1:3))
!NOW WE NEED TO READ IN THE FULL GRID DATA AND PUT IT INTO THE STRUCTURE.
!IF WE HAVE DONE ANY DIMENSION SWAPPING HERE WE NEED TO TAKE THAT INTO ACCOUNT IN THE VARIABLES THAT ARE BEING READ IN
print *, 'Starting grid input from file: ',indatgrid
allocate(g1all(lx1,lx2all,lx3all), g2all(lx1,lx2all,lx3all), g3all(lx1,lx2all,lx3all))
allocate(altall(lx1,lx2all,lx3all), glatall(lx1,lx2all,lx3all), glonall(lx1,lx2all,lx3all))
allocate(Bmagall(lx1,lx2all,lx3all))
allocate(Incall(lx2all,lx3all))
allocate(nullptsall(lx1,lx2all,lx3all))
allocate(e1all(lx1,lx2all,lx3all,3), e2all(lx1,lx2all,lx3all,3), e3all(lx1,lx2all,lx3all,3))
allocate(erall(lx1,lx2all,lx3all,3), ethetaall(lx1,lx2all,lx3all,3), ephiall(lx1,lx2all,lx3all,3))
allocate(rall(lx1,lx2all,lx3all), thetaall(lx1,lx2all,lx3all), phiall(lx1,lx2all,lx3all))
if (flagswap/=1) then
!! normal (i.e. full 3D) grid ordering, or a 2D grid with 1 element naturally in the second dimension
else
!! this is apparently a 2D grid, so the x2 and x3 dimensions have been/need to be swapped
!! MZ - may need to change lx2-->lx2all???
!! Note there that the fortran arrays are the correct size, but the input data are not!!!
!! This means tmp variable and permutes...
print *, '2D grid: **PERMUTE** x2 and x3 dimensions'
end if
call get_grid3(indatgrid, flagswap, x, g1all,g2all,g3all, altall,glatall,glonall,Bmagall,Incall,nullptsall,&
e1all,e2all,e3all,erall,ethetaall,ephiall,rall,thetaall,phiall)
!! ALLOCATE SPACE FOR ROOTS SUBGRID GRAVITATIONAL FIELD
allocate(g1(1:lx1,1:lx2,1:lx3),g2(1:lx1,1:lx2,1:lx3),g3(1:lx1,1:lx2,1:lx3))
!! SEND FULL X1 AND X2 GRIDS TO EACH WORKER (ONLY X3-DIM. IS INVOLVED IN THE MPI
print*, 'Exchanging grid spacings...'
do iid=1,lid-1
call mpi_send(x%x1,lx1+4,mpi_realprec,iid,tagx1,MPI_COMM_WORLD,ierr)
!if (ierr/=0) error stop 'failed mpi_send x1'
call mpi_send(x%x2all,lx2all+4,mpi_realprec,iid,tagx2all,MPI_COMM_WORLD,ierr)
!if (ierr/=0) error stop 'failed mpi_send x2all'
call mpi_send(x%x3all,lx3all+4,mpi_realprec,iid,tagx3all,MPI_COMM_WORLD,ierr)
!! workers may need a copy of this, e.g. for boudnary conditions
!if (ierr/=0) error stop 'failed mpi_send x3all'
call mpi_send(x%dx1,lx1+3,mpi_realprec,iid,tagx1,MPI_COMM_WORLD,ierr)
!if (ierr/=0) error stop 'failed mpi_send dx1'
call mpi_send(x%x1i,lx1+1,mpi_realprec,iid,tagx1,MPI_COMM_WORLD,ierr)
!if (ierr/=0) error stop 'failed mpi_send x1i'
call mpi_send(x%dx1i,lx1,mpi_realprec,iid,tagx1,MPI_COMM_WORLD,ierr)
!if (ierr/=0) error stop 'failed mpi_send dx1i'
end do
if (ierr/=0) error stop 'failed mpi_send x grid'
!! NOW SEND THE INFO THAT DEPENDS ON X3 SLAB SIZE
print*, 'Computing subdomain spacing...'
call bcast_send1D_3(x%x3all,tagx3,x%x3)
x%dx3=x%x3(0:lx3+2)-x%x3(-1:lx3+1) !computing these avoids extra message passing (could be done for other coordinates, as well)
x%x3i(1:lx3+1)=0.5*(x%x3(0:lx3)+x%x3(1:lx3+1))
x%dx3i=x%x3i(2:lx3+1)-x%x3i(1:lx3)
call bcast_send1D_2(x%x2all,tagx2,x%x2)
x%dx2=x%x2(0:lx2+2)-x%x2(-1:lx2+1) !computing these avoids extra message passing (could be done for other coordinates
x%x2i(1:lx2+1)=0.5*(x%x2(0:lx2)+x%x2(1:lx2+1))
x%dx2i=x%x2i(2:lx2+1)-x%x2i(1:lx2)
print*, 'Dealing with metric factors...'
allocate(mpisendbuf(-1:lx1+2,-1:lx2all+2,-1:lx3all+2),mpirecvbuf(-1:lx1+2,-1:lx2+2,-1:lx3+2))
mpisendbuf=x%h1all !since metric factors are pointers they are not gauranteed to be contiguous in memory so pack them into a buffer that is...
call bcast_send3D_ghost(mpisendbuf,tagh1,mpirecvbuf) !special broadcast subroutine to handle 3D arrays with ghost cells
x%h1=mpirecvbuf !store roots slab of metric factors in its grid structure
mpisendbuf=x%h2all
call bcast_send3D_ghost(mpisendbuf,tagh2,mpirecvbuf)
x%h2=mpirecvbuf
mpisendbuf=x%h3all
call bcast_send3D_ghost(mpisendbuf,tagh3,mpirecvbuf)
x%h3=mpirecvbuf
deallocate(mpisendbuf,mpirecvbuf) !we need different sized buffers below
call bcast_send(x%h1x1iall,tagh1,x%h1x1i) !do the weird sizes here (ie. lx1+1) give issues with MPI? probably... No because bcast reads the size off of the variable...
call bcast_send(x%h2x1iall,tagh2,x%h2x1i)
call bcast_send(x%h3x1iall,tagh3,x%h3x1i)
call bcast_send3D_x2i(x%h1x2iall,tagh1,x%h1x2i)
call bcast_send3D_x2i(x%h2x2iall,tagh2,x%h2x2i)
call bcast_send3D_x2i(x%h3x2iall,tagh3,x%h3x2i)
call bcast_send3D_x3i(x%h1x3iall,tagh1,x%h1x3i)
call bcast_send3D_x3i(x%h2x3iall,tagh2,x%h2x3i)
call bcast_send3D_x3i(x%h3x3iall,tagh3,x%h3x3i)
print *, 'Sending gravity, etc...'
call bcast_send(g1all,tagh1,g1)
call bcast_send(g2all,tagh2,g2)
call bcast_send(g3all,tagh3,g3)
call bcast_send(glatall,tagglat,x%glat)
call bcast_send(glonall,tagglon,x%glon)
call bcast_send(altall,tagalt,x%alt)
call bcast_send(Bmagall,tagBmag,x%Bmag)
call bcast_send(Incall,taginc,x%I)
call bcast_send(nullptsall,tagnull,x%nullpts)
print *, 'Now sending unit vectors...'
allocate(mpisendbuf(1:lx1,1:lx2all,1:lx3all),mpirecvbuf(1:lx1,1:lx2,1:lx3)) !why is buffering used/needed here???
do icomp=1,3
mpisendbuf=e1all(:,:,:,icomp)
call bcast_send(mpisendbuf,tageunit1,mpirecvbuf)
x%e1(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
mpisendbuf=e2all(:,:,:,icomp)
call bcast_send(mpisendbuf,tageunit2,mpirecvbuf)
x%e2(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
mpisendbuf=e3all(:,:,:,icomp)
call bcast_send(mpisendbuf,tageunit3,mpirecvbuf)
x%e3(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
mpisendbuf=erall(:,:,:,icomp)
call bcast_send(mpisendbuf,tager,mpirecvbuf)
x%er(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
mpisendbuf=ethetaall(:,:,:,icomp)
call bcast_send(mpisendbuf,tagetheta,mpirecvbuf)
x%etheta(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
mpisendbuf=ephiall(:,:,:,icomp)
call bcast_send(mpisendbuf,tagephi,mpirecvbuf)
x%ephi(:,:,:,icomp)=mpirecvbuf
end do
deallocate(mpisendbuf,mpirecvbuf)
call bcast_send(rall,tagr,x%r)
call bcast_send(thetaall,tagtheta,x%theta)
call bcast_send(phiall,tagphi,x%phi)
print *, 'Done sending slabbed variables to workers...'
!COUNT THE NUMBER OF NULL GRID POINTS AND GENERATE A LIST OF NULL INDICES FOR LATER USE
x%lnull=0;
do ix3=1,lx3
do ix2=1,lx2
do ix1=1,lx1
if(x%nullpts(ix1,ix2,ix3) > 0.5_wp) then
x%lnull=x%lnull+1
end if
end do
end do
end do
allocate(x%inull(1:x%lnull,1:3))
icount=1
do ix3=1,lx3
do ix2=1,lx2
do ix1=1,lx1
if(x%nullpts(ix1,ix2,ix3) > 0.5_wp) then
x%inull(icount,:)=[ix1,ix2,ix3]
icount=icount+1
end if
end do
end do
end do
print *, 'Done computing null grid points... Process: ',myid,' has: ',x%lnull
!COMPUTE DIFFERENTIAL DISTANCES ALONG EACH DIRECTION (TO BE USED IN TIME STEP DETERMINATION...
block
real(wp), dimension(1:lx1,1:lx2,1:lx3) :: tmpdx
allocate(x%dl1i(1:lx1,1:lx2,1:lx3),x%dl2i(1:lx1,1:lx2,1:lx3),x%dl3i(1:lx1,1:lx2,1:lx3))
tmpdx=spread(spread(x%dx1i,2,lx2),3,lx3)
x%dl1i=tmpdx*x%h1(1:lx1,1:lx2,1:lx3)
tmpdx=spread(spread(x%dx2i,1,lx1),3,lx3)
x%dl2i=tmpdx*x%h2(1:lx1,1:lx2,1:lx3)
tmpdx=spread(spread(x%dx3i,1,lx1),2,lx2)
x%dl3i=tmpdx*x%h3(1:lx1,1:lx2,1:lx3)
end block
! !THIS CODE BLOCK HAS ROOT "PARROT" THE GRID TO A FILE FOR DEBUGGING PURPOSES.
! !THIS BLOCK MUST BE HERE DUE TO THE FACT MANY OF HTE ALL-GRID VARIABLES ARE ONLY
! !IN SCOPE INSIDE THIS FUNCITON BEFORE THE DEALLOCATE STATEMENT BELOW
! open(newunit=outunit,file='testsize.dat',status='replace',form='unformatted', &
! access='stream', action='write')
! write(outunit) lx1,lx2,lx3all !note that these sizes exxclude ghost cells
! close(outunit)
!
! open(outunit,file='testgrid.dat',status='replace',form='unformatted', &
! access='stream')
! write(outunit) x%x1,x%x1i,x%dx1,x%dx1i !I guess the number of elements is obtained from the size of the arrays???
! write(outunit) x%x2,x%x2i,x%dx2,x%dx2i
! write(outunit) x%x3all,x%x3iall,x%dx3all,x%dx3iall
! write(outunit) x%h1all,x%h2all,x%h3all
! write(outunit) x%h1x1iall,x%h2x1iall,x%h3x1iall
! write(outunit) x%h1x2iall,x%h2x2iall,x%h3x2iall
! write(outunit) x%h1x3iall,x%h2x3iall,x%h3x3iall
! write(outunit) g1all,g2all,g3all
! write(outunit) altall,glatall,glonall
! write(outunit) Bmagall
! write(outunit) Incall
! write(outunit) nullptsall
! close(outunit)
! print *, 'Done creating copy of grid...'
!
! !FLAG THE GRID AS PERIODIC, IF REQUESTED; IF SO PERIODICITY WILL BE ASSUMED IN THE X3-DIRECTION
! if (flagperiodic==1) then
! x%flagper=1
! else
! x%flagper=0
! end if
!
!DEALLOCATE ANY FULL GRID VARIABLES THAT ARE NO LONGER NEEDED
deallocate(g1all,g2all,g3all,altall,glatall,glonall,Bmagall,Incall,nullptsall,rall,thetaall,phiall)
end subroutine read_grid_root
subroutine read_grid_workers(x)
type(curvmesh), intent(inout) :: x
integer :: ix1,ix2,ix3,icount,icomp, ierr
!GET ROOTS MESSAGE WITH THE SIZE OF THE GRID WE ARE TO RECEIVE
call mpi_recv(lx2,1,MPI_INTEGER,0,taglx2,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv lx2'
call mpi_recv(lx3,1,MPI_INTEGER,0,taglx3,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv lx3'
x%lx1=lx1; x%lx2=lx2; x%lx2all=lx2all; x%lx3all=lx3all; x%lx3=lx3
!ROOT NEEDS TO TELL US WHETHER WE'VE SWAPPED DIMENSIONS SINCE THIS AFFECTS HOW CURRENTS ARE COMPUTED
call mpi_recv(flagswap,1,MPI_INTEGER,0,tagswap,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv flagswap'
if (flagswap==1) then
x%lx3all=lx2all
x%lx2all=lx3all
lx2all=x%lx2all
lx3all=x%lx3all
end if
!ALLOCATE SPACE FOR MY SLAB OF DATA
allocate(x%x1(-1:lx1+2))
allocate(x%dx1i(lx1),x%x1i(lx1+1),x%dx1(0:lx1+2))
allocate(x%x2(-1:lx2+2))
allocate(x%dx2i(lx2),x%x2i(lx2+1),x%dx2(0:lx2+2))
allocate(x%x2all(-1:lx2all+2))
!DETERMINE AND ALLOCATE SPACE NEEDED FOR WORKERS SUBGRIDS
allocate(x%x3(-1:lx3+2))
allocate(x%dx3i(lx3),x%x3i(lx3+1),x%dx3(0:lx3+2))
allocate(x%x3all(-1:lx3all+2))
allocate(x%h1(-1:lx1+2,-1:lx2+2,-1:lx3+2),x%h2(-1:lx1+2,-1:lx2+2,-1:lx3+2),x%h3(-1:lx1+2,-1:lx2+2,-1:lx3+2))
allocate(x%h1x1i(1:lx1+1,1:lx2,1:lx3),x%h2x1i(1:lx1+1,1:lx2,1:lx3),x%h3x1i(1:lx1+1,1:lx2,1:lx3))
allocate(x%h1x2i(1:lx1,1:lx2+1,1:lx3),x%h2x2i(1:lx1,1:lx2+1,1:lx3),x%h3x2i(1:lx1,1:lx2+1,1:lx3))
allocate(x%h1x3i(1:lx1,1:lx2,1:lx3+1),x%h2x3i(1:lx1,1:lx2,1:lx3+1),x%h3x3i(1:lx1,1:lx2,1:lx3+1))
allocate(x%glat(1:lx1,1:lx2,1:lx3),x%glon(1:lx1,1:lx2,1:lx3),x%alt(1:lx1,1:lx2,1:lx3))
allocate(x%r(1:lx1,1:lx2,1:lx3),x%theta(1:lx1,1:lx2,1:lx3),x%phi(1:lx1,1:lx2,1:lx3))
allocate(x%Bmag(1:lx1,1:lx2,1:lx3))
allocate(x%I(1:lx2,1:lx3))
allocate(x%nullpts(1:lx1,1:lx2,1:lx3))
allocate(x%e1(1:lx1,1:lx2,1:lx3,1:3),x%e2(1:lx1,1:lx2,1:lx3,1:3),x%e3(1:lx1,1:lx2,1:lx3,1:3))
allocate(x%er(1:lx1,1:lx2,1:lx3,1:3),x%etheta(1:lx1,1:lx2,1:lx3,1:3),x%ephi(1:lx1,1:lx2,1:lx3,1:3))
!ALLOCATE SPACE FOR WORKER'S GRAVITATIONAL FIELD
allocate(g1(1:lx1,1:lx2,1:lx3),g2(1:lx1,1:lx2,1:lx3),g3(1:lx1,1:lx2,1:lx3))
!RECEIVE GRID DATA FROM ROOT
call mpi_recv(x%x1,lx1+4,mpi_realprec,0,tagx1,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv x1'
call mpi_recv(x%x2all,lx2all+4,mpi_realprec,0,tagx2all,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv x2all'
call mpi_recv(x%x3all,lx3all+4,mpi_realprec,0,tagx3all,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv x3all'
call mpi_recv(x%dx1,lx1+3,mpi_realprec,0,tagx1,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv dx1'
call mpi_recv(x%x1i,lx1+1,mpi_realprec,0,tagx1,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv x1i'
call mpi_recv(x%dx1i,lx1,mpi_realprec,0,tagx1,MPI_COMM_WORLD,MPI_STATUS_IGNORE,ierr)
if (ierr/=0) error stop 'failed mpi_recv dx1i'
call bcast_recv1D_3(x%x3,tagx3)
x%dx3=x%x3(0:lx3+2)-x%x3(-1:lx3+1) !computing these avoids extra message passing (could be done for other coordinates
x%x3i(1:lx3+1)=0.5*(x%x3(0:lx3)+x%x3(1:lx3+1))
x%dx3i=x%x3i(2:lx3+1)-x%x3i(1:lx3)
call bcast_recv1D_2(x%x2,tagx2)
x%dx2=x%x2(0:lx2+2)-x%x2(-1:lx2+1)
x%x2i(1:lx2+1)=0.5*(x%x2(0:lx2)+x%x2(1:lx2+1))
x%dx2i=x%x2i(2:lx2+1)-x%x2i(1:lx2)
block
real(wp), dimension(-1:lx1+2,-1:lx2+2,-1:lx3+2) :: mpirecvbuf
call bcast_recv3D_ghost(mpirecvbuf,tagh1)
x%h1=mpirecvbuf
call bcast_recv3D_ghost(mpirecvbuf,tagh2)
x%h2=mpirecvbuf
call bcast_recv3D_ghost(mpirecvbuf,tagh3)
x%h3=mpirecvbuf
end block
call bcast_recv(x%h1x1i,tagh1)
call bcast_recv(x%h2x1i,tagh2)
call bcast_recv(x%h3x1i,tagh3)
call bcast_recv3D_x2i(x%h1x2i,tagh1)
call bcast_recv3D_x2i(x%h2x2i,tagh2)
call bcast_recv3D_x2i(x%h3x2i,tagh3)
call bcast_recv3D_x3i(x%h1x3i,tagh1)
call bcast_recv3D_x3i(x%h2x3i,tagh2)
call bcast_recv3D_x3i(x%h3x3i,tagh3)
call bcast_recv(g1,tagh1)
call bcast_recv(g2,tagh2)
call bcast_recv(g3,tagh3)
call bcast_recv(x%glat,tagglat)
call bcast_recv(x%glon,tagglon)
call bcast_recv(x%alt,tagalt)
call bcast_recv(x%Bmag,tagBmag)
call bcast_recv(x%I,taginc) !only time that we need to exchange 2D array data, I think
call bcast_recv(x%nullpts,tagnull) !note that this is not an integer array
block
real(wp), dimension(1:lx1,1:lx2,1:lx3) :: mpirecvbuf
do icomp=1,3
call bcast_recv(mpirecvbuf,tageunit1)
x%e1(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
call bcast_recv(mpirecvbuf,tageunit2)
x%e2(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
call bcast_recv(mpirecvbuf,tageunit3)
x%e3(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
call bcast_recv(mpirecvbuf,tager)
x%er(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
call bcast_recv(mpirecvbuf,tagetheta)
x%etheta(:,:,:,icomp)=mpirecvbuf
end do
do icomp=1,3
call bcast_recv(mpirecvbuf,tagephi)
x%ephi(:,:,:,icomp)=mpirecvbuf
end do
end block
call bcast_recv(x%r,tagr)
call bcast_recv(x%theta,tagtheta)
call bcast_recv(x%phi,tagphi)
!COUNT THE NUMBER OF NULL GRID POINTS AND GENERATE A LIST OF NULL INDICES FOR LATER USE
x%lnull=0;
do ix3=1,lx3
do ix2=1,lx2
do ix1=1,lx1
if(x%nullpts(ix1,ix2,ix3)>0.5d0) then
x%lnull=x%lnull+1
end if
end do
end do
end do
allocate(x%inull(1:x%lnull,1:3))
icount=1
do ix3=1,lx3
do ix2=1,lx2
do ix1=1,lx1
if(x%nullpts(ix1,ix2,ix3)>0.5d0) then
x%inull(icount,:)=[ix1,ix2,ix3]
icount=icount+1
end if
end do
end do
end do
print *, 'Done computing null grid points... Process: ',myid,' has: ',x%lnull
!! COMPUTE DIFFERENTIAL DISTANCES ALONG EACH DIRECTION
block
real(wp), dimension(1:lx1,1:lx2,1:lx3) :: tmpdx
allocate(x%dl1i(1:lx1,1:lx2,1:lx3),x%dl2i(1:lx1,1:lx2,1:lx3),x%dl3i(1:lx1,1:lx2,1:lx3))
tmpdx=spread(spread(x%dx1i,2,lx2),3,lx3)
x%dl1i=tmpdx*x%h1(1:lx1,1:lx2,1:lx3)
tmpdx=spread(spread(x%dx2i,1,lx1),3,lx3)
x%dl2i=tmpdx*x%h2(1:lx1,1:lx2,1:lx3)
tmpdx=spread(spread(x%dx3i,1,lx1),2,lx2)
x%dl3i=tmpdx*x%h3(1:lx1,1:lx2,1:lx3)
end block
end subroutine read_grid_workers
end submodule grid_read