├── .gitignore
├── LICENSE
├── Zeltron2D
├── Makefile
├── extcmd.f90
├── main.f90
├── mod_analysis.f90
├── mod_extcmd.f90
├── mod_fields.f90
├── mod_initial.f90
├── mod_input.f90
├── mod_interp.f90
├── mod_io_hdf5.f90
├── mod_io_txt.f90
├── mod_log.f90
├── mod_motion.f90
├── mod_mpi.f90
├── mod_rhoj.f90
├── mod_sync.f90
├── mod_track.f90
├── script_restore.sh
└── script_run.sh
├── Zeltron3D
├── Makefile
├── extcmd.f90
├── main.f90
├── mod_analysis.f90
├── mod_extcmd.f90
├── mod_fields.f90
├── mod_initial.f90
├── mod_input.f90
├── mod_interp.f90
├── mod_io_hdf5.f90
├── mod_io_txt.f90
├── mod_log.f90
├── mod_motion.f90
├── mod_mpi.f90
├── mod_rhoj.f90
├── mod_sync.f90
├── mod_track.f90
├── script_restore.sh
└── script_run.sh
├── plot2D
├── energy.py
├── plot_current.py
├── plot_density.py
├── plot_field.py
├── plot_spectrum.py
└── timestep.py
└── plot3D
├── energy.py
├── plot3D_current.py
├── plot3D_density.py
├── plot3D_field.py
├── plot_spectrum.py
└── timestep.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
--------------------------------------------------------------------------------
/Zeltron2D/Makefile:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 |
20 | # ---------------------Macro-Defs-----------------------------
21 | ## Common options for F90 are: ftn, h5pfc, mpif90
22 | F90=mpif90
23 |
24 | ## for debugging, OPT=-g -fbacktrace -fbounds-check -O0
25 | OPT=-g -O3
26 |
27 | ##-----------------I/O---------------
28 | ## IO should be "h5" for hdf5 output (hdf5 modules need to be loaded,
29 | ## or include and library files available), or "txt" for text output
30 | ## files, in which case no hdf5 capability need be present.
31 | IO?=h5
32 |
33 | ifeq ($(IO),h5)
34 | modio=mod_io_hdf5
35 | ## The following compiler/linker options should be set for each machine,
36 | # except for supercomputers where they are set through module loading
37 | # and the correct compiler command (e.g., ftn or h5pfc).
38 | LPATH=-L /scr_verus/wernerg/contrib2/hdf5-1.8.11-par/lib
39 | LIB=-lhdf5_fortran -lhdf5_f90cstub -lhdf5
40 | INCLUDE=-I /scr_verus/wernerg/contrib2/hdf5-1.8.11-par/include/fortran
41 | ## On supercomputers with hdf5 modules loaded
42 | # (or systems with h5pfc defined), uncomment the following 3 lines,
43 | # and comment the above 3 lines.
44 | #LPATH=
45 | #LIB=
46 | #INCLUDE=
47 | else
48 | modio=mod_io_txt
49 | LPATH=
50 | LIB=
51 | INCLUDE=
52 | endif
53 |
54 | # -------------------End-macro-Defs---------------------------
55 |
56 | all:main testExtcmd
57 |
58 | # Here is the link step
59 | main:mod_input.o mod_extcmd.o mod_initial.o mod_mpi.o mod_log.o mod_interp.o $(modio).o mod_fields.o mod_motion.o mod_rhoj.o mod_sync.o mod_track.o mod_analysis.o main.o
60 | $(F90) $(OPT) -o zeltron.exe $(LPATH) mod_input.o mod_extcmd.o mod_initial.o mod_mpi.o mod_log.o mod_interp.o $(modio).o mod_fields.o mod_motion.o mod_rhoj.o mod_sync.o mod_track.o mod_analysis.o main.o $(LIB)
61 |
62 | testExtcmd:extcmd.o mod_extcmd.o
63 | $(F90) $(OPT) mod_extcmd.o extcmd.o -o testExtcmd
64 |
65 | # Here are the compile steps
66 |
67 | mod_extcmd.o:mod_extcmd.f90
68 | $(F90) $(OPT) -c mod_extcmd.f90
69 |
70 | extcmd.o:extcmd.f90
71 | $(F90) $(OPT) -c extcmd.f90
72 |
73 | mod_input.o:mod_input.f90
74 | $(F90) $(OPT) -c mod_input.f90
75 |
76 | mod_initial.o:mod_initial.f90
77 | $(F90) $(OPT) -c mod_initial.f90
78 |
79 | mod_mpi.o:mod_mpi.f90
80 | $(F90) $(OPT) -c mod_mpi.f90
81 |
82 | mod_log.o:mod_log.f90
83 | $(F90) $(OPT) -c mod_log.f90
84 |
85 | mod_interp.o:mod_interp.f90
86 | $(F90) $(OPT) -c mod_interp.f90
87 |
88 | $(modio).o:$(modio).f90
89 | $(F90) $(OPT) $(INCLUDE) -c $(modio).f90
90 |
91 | mod_fields.o:mod_fields.f90
92 | $(F90) $(OPT) -c mod_fields.f90
93 |
94 | mod_motion.o:mod_motion.f90
95 | $(F90) $(OPT) -c mod_motion.f90
96 |
97 | mod_rhoj.o:mod_rhoj.f90
98 | $(F90) $(OPT) -c mod_rhoj.f90
99 |
100 | mod_sync.o:mod_sync.f90
101 | $(F90) $(OPT) -c mod_sync.f90
102 |
103 | mod_track.o:mod_track.f90
104 | $(F90) $(OPT) -c mod_track.f90
105 |
106 | mod_analysis.o:mod_analysis.f90
107 | $(F90) $(OPT) -c mod_analysis.f90
108 |
109 | main.o:main.f90 mod_input.o mod_initial.o mod_mpi.o mod_log.o mod_interp.o $(modio).o mod_fields.o mod_motion.o mod_rhoj.o mod_sync.o mod_track.o mod_analysis.o
110 | $(F90) $(OPT) -c main.f90
111 |
112 |
--------------------------------------------------------------------------------
/Zeltron2D/extcmd.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | PROGRAM EXTCMD
21 |
22 | USE MOD_EXTCMD
23 |
24 | IMPLICIT NONE
25 |
26 | INTEGER :: cmd, step
27 |
28 | PRINT *, "Directions:"
29 | PRINT *, "1. Create a file simCmd.txt (in any directory but data/)"
30 | PRINT *, "2. simCmd.txt should contain one line; at the time of this writing"
31 | PRINT *, " it contains 4 numbers: timeStep quit dump save"
32 | PRINT *, " where quit, dump, and save are either 0 (don't do) or 1 (do)."
33 | PRINT *, "3. Run ./testExtcmd to verify that simCmd is what it should be."
34 | PRINT *, "4. Move or copy simCmd.txt to the data/ directory."
35 |
36 | PRINT *, " "
37 | PRINT *, "Executing the command to read simCmd.txt:"
38 |
39 | CALL READ_COMMAND("simCmd.txt", step, cmd)
40 | CALL PRINT_COMMAND(step, cmd)
41 |
42 | END PROGRAM EXTCMD
43 |
--------------------------------------------------------------------------------
/Zeltron2D/mod_extcmd.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_EXTCMD
21 |
22 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23 | !
24 | ! This module reads the contents of a (command) file. The file should
25 | ! have a single line (subsequent lines will be ignored) with 4 integers
26 | ! separated by a space:
27 | ! timeStep quit dump save
28 | ! where timeStep is an integer timeStep at which the command should be
29 | ! executed, and quit, dump, and save are either 0 or 1, depending
30 | ! on whether those actions should be performed at the time step.
31 | !
32 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
33 |
34 | IMPLICIT NONE
35 |
36 | PRIVATE
37 |
38 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_DO_NOTHING = 0
39 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_QUIT = 1
40 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_DUMP = 2
41 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_SAVE = 4
42 |
43 | PUBLIC :: READ_COMMAND
44 | PUBLIC :: PRINT_COMMAND
45 |
46 | CONTAINS
47 |
48 | FUNCTION BoolToInt(b)
49 |
50 | IMPLICIT NONE
51 |
52 | LOGICAL :: b
53 | INTEGER :: BoolToInt
54 |
55 | IF (b) THEN
56 | BoolToInt = 1
57 | ELSE
58 | BoolToInt = 0
59 | ENDIF
60 |
61 | END FUNCTION
62 |
63 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
64 | ! Subroutine READ_COMMAND
65 | ! Reads a command file, and returns a timeStep and a command.
66 | !
67 | ! INPUT:
68 | ! - fileName the name of the command file
69 | ! OUTPUT:
70 | ! - timeStep: an integer time step
71 | ! - cmd: an integer command, the sum of the EXTCMD_* flags indicating
72 | ! the actions to be performed.
73 | !
74 | ! If the command file does not exist, or there are any errors reading
75 | ! the command file, this returns timeStep = -1
76 | ! and cmd = 0 = EXTCMD_DO_NOTHING.
77 | !
78 | ! Passing a command through a file is very klugey approach; we want
79 | ! this subroutine never to fail, never to result in a crash.
80 | ! By using the IOSTAT option for file operations, we try to avoid
81 | ! failure, and in such cases return innocuous EXTCMD_DO_NOTHING.
82 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83 |
84 | SUBROUTINE READ_COMMAND(fileName, timeStep, cmd)
85 |
86 | IMPLICIT NONE
87 |
88 | ! INPUT
89 | CHARACTER(len=*) :: fileName
90 | INTEGER, INTENT(OUT) :: timeStep, cmd
91 |
92 | ! LOCAL
93 | LOGICAL :: cmdFileExists, fail
94 | INTEGER :: step
95 | INTEGER :: doNothing, doQuit, doDump, doSave
96 | INTEGER :: ioStatus
97 | !***********************************************************************
98 |
99 | ! check for command file
100 | fail = .TRUE.
101 | INQUIRE(FILE=fileName, EXIST=cmdFileExists, IOSTAT = ioStatus)
102 | IF (ioStatus == 0) THEN
103 | IF (cmdFileExists) THEN
104 | OPEN(10, FILE = fileName, IOSTAT = ioStatus)
105 | IF (ioStatus == 0) THEN
106 | READ(10, *, IOSTAT = ioStatus) step, doQuit, doDump, doSave
107 | IF (ioStatus == 0) THEN
108 | timeStep = step
109 | cmd = EXTCMD_QUIT*BoolToInt(doQuit>0) + EXTCMD_DUMP*BoolToInt(doDump > 0) &
110 | + EXTCMD_SAVE*BoolToInt(doSave > 0)
111 | fail = .FALSE.
112 | ELSE
113 | PRINT *, "Error: IOSTAT=", ioStatus, " while reading command file ", fileName
114 | ENDIF
115 | CLOSE(10, IOSTAT = ioStatus)
116 | ELSE
117 | PRINT *, "Error: IOSTAT=", ioStatus, " while opening command file ", fileName
118 | ENDIF
119 | ENDIF
120 | ELSE
121 | PRINT *, "Error: IOSTAT=", ioStatus, " while inquiring about existence of file ", fileName
122 | ENDIF
123 |
124 | IF (fail) THEN
125 | timeStep = -1
126 | cmd = EXTCMD_DO_NOTHING
127 | ENDIF
128 |
129 | END SUBROUTINE READ_COMMAND
130 |
131 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
132 | ! Subroutine PRINT_COMMAND
133 | ! Prints the interpretation of a command from a command file
134 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
135 |
136 | SUBROUTINE PRINT_COMMAND(timeStep, cmd)
137 |
138 | IMPLICIT NONE
139 |
140 | INTEGER :: timeStep, cmd
141 | !***********************************************************************
142 |
143 | PRINT *, "At timestep", timeStep, ":"
144 | IF (cmd == 0) THEN
145 | PRINT *, " do nothing"
146 | ELSE
147 | IF (IAND(cmd, EXTCMD_QUIT) /= 0) PRINT *, " quit"
148 | IF (IAND(cmd, EXTCMD_DUMP) /= 0) PRINT *, " dump"
149 | IF (IAND(cmd, EXTCMD_SAVE) /= 0) PRINT *, " save"
150 | ENDIF
151 |
152 | END SUBROUTINE PRINT_COMMAND
153 |
154 | !***********************************************************************
155 |
156 | END MODULE MOD_EXTCMD
157 |
--------------------------------------------------------------------------------
/Zeltron2D/mod_input.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_INPUT
21 |
22 | IMPLICIT NONE
23 |
24 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25 | !+++++++++++++++++++++++++++++ CONSTANTS +++++++++++++++++++++++++++++
26 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27 |
28 | ! Speed of light [cm/s]
29 | DOUBLE PRECISION, PARAMETER, PUBLIC :: c=299792458d2
30 | ! Fundamental charge [esu]
31 | DOUBLE PRECISION, PARAMETER, PUBLIC :: e=4.8032068d-10
32 | ! Boltzmann constant [erg/K]
33 | DOUBLE PRECISION, PARAMETER, PUBLIC :: k=1.380658d-16
34 | ! Planck constant [erg.s]
35 | DOUBLE PRECISION, PARAMETER, PUBLIC :: h=6.6260755d-27
36 | ! Mass of the electron [g]
37 | DOUBLE PRECISION, PARAMETER, PUBLIC :: me=9.1093897d-28
38 | ! Mass of the proton [g]
39 | DOUBLE PRECISION, PARAMETER, PUBLIC :: mp=1.6726231d-24
40 | ! 1 eV in erg [erg]
41 | DOUBLE PRECISION, PARAMETER, PUBLIC :: evtoerg=1.602177d-12
42 | ! pi
43 | DOUBLE PRECISION, PARAMETER, PUBLIC :: pi=acos(-1.0d0)
44 |
45 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
46 | !+++++++++++++++++++++++++ DIMENSION ++++++++++++++++++++++++++++++
47 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48 |
49 | ! Spatial dimension
50 | INTEGER, PARAMETER, PUBLIC :: NDIM=2
51 |
52 | ! If NDIM = 2, define some parameters in the z direction
53 | INTEGER, PARAMETER, PUBLIC :: NPZ=1
54 |
55 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56 | !+++++++++++++++++++++++++ SAVE/RESTORE ++++++++++++++++++++++++++++++
57 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58 |
59 | ! Save particle and field data for future restoration of the simulation
60 | LOGICAL, PARAMETER, PUBLIC :: CHECKPOINT=.FALSE.
61 |
62 | ! Restore a simulation where it stopped
63 | LOGICAL, PARAMETER, PUBLIC :: RESTORE=.FALSE.
64 |
65 | ! Saving frequency, in seconds (the simulation will try to save its
66 | ! current state *before* elapsed time n*FSAVE, for integer n).
67 | ! N.B. It is highly recommended to have more than 1 checkpoint during
68 | ! the simulation, unless it is certain that the simulation will end
69 | ! naturally (as opposed to being killed before it is finished).
70 | DOUBLE PRECISION, PARAMETER, PUBLIC :: FSAVE=0.
71 |
72 | ! Give the time step from which the simulation should restart
73 | INTEGER, PARAMETER, PUBLIC :: time_ref=0
74 |
75 | ! Whether to test restore capability: this restores data from step
76 | ! time_ref, and then immediately write data (as if dumping
77 | ! for a checkpoint) under the next time step; the simulation then halts.
78 | LOGICAL, PARAMETER, PUBLIC :: TEST_RESTORE=.FALSE.
79 |
80 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
81 | !++++++++++++++++++++++ BOUNDARY CONDITIONS ++++++++++++++++++++++++++
82 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
83 |
84 | ! Specify the boundary conditions for the fields:
85 | ! 1. "PERIODIC": Periodic boundary conditions
86 | ! 2. "METAL": Perfect metal with infinite conductivity
87 |
88 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_XMIN="PERIODIC"
89 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_XMAX="PERIODIC"
90 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_YMIN="PERIODIC"
91 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_YMAX="PERIODIC"
92 |
93 | ! Specify the boundary conditions for the particles:
94 | ! 1. "PERIODIC": Periodic boundary conditions
95 | ! 2. "REFLECT": Particles are elastically reflected at the wall
96 | ! 3. "ABSORB": Particles are absorbed at the wall
97 |
98 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_XMIN="PERIODIC"
99 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_XMAX="PERIODIC"
100 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_YMIN="PERIODIC"
101 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_YMAX="PERIODIC"
102 |
103 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
104 | !+++++++++++++++++++++++++ INPUT PARAMETERS ++++++++++++++++++++++++++
105 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
106 |
107 | ! Number of cells in X
108 | INTEGER*8, PARAMETER, PUBLIC :: NCX=128
109 |
110 | ! Number of cells in Y
111 | INTEGER*8, PARAMETER, PUBLIC :: NCY=128
112 |
113 | ! Number of particles per cell per species
114 | INTEGER*8, PARAMETER, PUBLIC :: PPC=2
115 |
116 | ! Number of process (domain decomposition in the X- and Y-directions)
117 | INTEGER, PARAMETER, PUBLIC :: NPX=1
118 | INTEGER, PARAMETER, PUBLIC :: NPY=1
119 |
120 | ! Mass ratio IONS/ELECTRONS
121 | DOUBLE PRECISION, PARAMETER, PUBLIC :: mass_ratio=1.0
122 |
123 | ! Spatial boundaries in the X-direction
124 | DOUBLE PRECISION, PARAMETER, PUBLIC :: xmin=0d0,xmax=100.0
125 |
126 | ! Spatial boundaries in the Y-direction
127 | DOUBLE PRECISION, PARAMETER, PUBLIC :: ymin=0d0,ymax=100.0
128 |
129 | ! Dump data frequency in terms of timesteps
130 | INTEGER, PARAMETER, PUBLIC :: FDUMP=500
131 |
132 | ! Number of data dumps
133 | INTEGER, PARAMETER, PUBLIC :: NDUMP=3
134 |
135 | ! Number of time steps
136 | INTEGER, PARAMETER, PUBLIC :: NT=FDUMP*NDUMP
137 |
138 | ! Poisson solver calling frequency in terms of timesteps
139 | INTEGER, PARAMETER, PUBLIC :: FREQ_POISSON=25
140 |
141 | ! Number of iterations to solve Poisson's equation
142 | INTEGER, PARAMETER, PUBLIC :: NIT=500
143 |
144 | ! Switch ON/OFF the radiation reaction force (synchrotron radiation and
145 | ! inverse Compton scattering in the Thomson regime only)
146 | LOGICAL, PARAMETER, PUBLIC :: RAD_FORCE=.FALSE.
147 |
148 | ! Switch ON/OFF spatial filtering
149 | LOGICAL, PARAMETER, PUBLIC :: FILTER=.FALSE.
150 |
151 | ! Smoothing parameter
152 | DOUBLE PRECISION, PARAMETER, PUBLIC :: alpha=1.0/16.0
153 |
154 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
155 |
156 | ! Number of grid cells in X
157 | INTEGER, PARAMETER, PUBLIC :: NX=NCX+1
158 |
159 | ! Number of grid cells in Y
160 | INTEGER, PARAMETER, PUBLIC :: NY=NCY+1
161 |
162 | ! Number of cell per process in the X-direction
163 | INTEGER, PARAMETER, PUBLIC :: NCXP=NCX/NPX
164 |
165 | ! Number of cell per process in the Y-direction
166 | INTEGER, PARAMETER, PUBLIC :: NCYP=NCY/NPY
167 |
168 | ! Number of grid cells per process in X
169 | INTEGER, PARAMETER, PUBLIC :: NXP=NCXP+1
170 |
171 | ! Number of grid cells per process in Y
172 | INTEGER, PARAMETER, PUBLIC :: NYP=NCYP+1
173 |
174 | ! Total number of particles per species NP=NCX*NCY*PPC
175 | INTEGER*8, PARAMETER, PUBLIC :: NP=NCX*NCY*PPC
176 |
177 | ! Spatial step
178 | DOUBLE PRECISION, PARAMETER, PUBLIC :: dx=(xmax-xmin)/NCX
179 | DOUBLE PRECISION, PARAMETER, PUBLIC :: dy=(ymax-ymin)/NCY
180 |
181 | ! Time step (Courant-Friedrichs-Lewy timestep)
182 | DOUBLE PRECISION, PARAMETER, PUBLIC :: dt=0.99*dx*dy/sqrt(dx*dx+dy*dy)/c
183 |
184 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
185 |
186 | ! Initial (tearing-mode) perturbation amplitude
187 | DOUBLE PRECISION, PARAMETER, PUBLIC :: perturb_amp=0.0
188 |
189 | ! Ratio of Bz/B0 (Guide field / reconnecting field)
190 | DOUBLE PRECISION, PARAMETER, PUBLIC :: guide_field=0.0
191 |
192 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
193 |
194 | ! Temperature in unit of me*c^2/k of the DRIFTING ELECTRONS in the co-moving frame
195 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thde=1.0
196 |
197 | ! Temperature in unit of mi*c^2/k of the DRIFTING IONS in the co-moving frame
198 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thdi=1.0
199 |
200 | ! Temperature in unit of me*c^2/k of the BACKGROUND ELECTRONS in the lab frame
201 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thbe=1.0
202 |
203 | ! Temperature in unit of mi*c^2/k of the BACKGROUND IONS in the lab frame
204 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thbi=1.0
205 |
206 | ! Minimum Larmor radius of the electrons
207 | DOUBLE PRECISION, PARAMETER, PUBLIC :: rhoc=2.0
208 |
209 | ! Drift velocity betad=vdrift/c
210 | DOUBLE PRECISION, PARAMETER, PUBLIC :: betad=0.6
211 |
212 | ! Density ratio between initial DRIFTING and BACKGROUND particles
213 | DOUBLE PRECISION, PARAMETER, PUBLIC :: density_ratio=0.1
214 |
215 | ! Energy density ratio between external radiation field and the magnetic field
216 | ! udens_ratio=Uph/Ub, where Ub=B0^2/8*pi
217 | DOUBLE PRECISION, PARAMETER, PUBLIC :: udens_ratio=0.0
218 |
219 | ! :TODO: add following options for ions as well as electrons
220 | ! 4-velocity boundaries for the particles
221 | DOUBLE PRECISION, PARAMETER, PUBLIC :: umin=1d-2,umax=1d2
222 |
223 | ! 4-velocity boundaries for the drifting electrons
224 | DOUBLE PRECISION, PARAMETER, PUBLIC :: udemin=-1d2,udemax=1d2
225 |
226 | ! 4-velocity boundaries for the drifting ions
227 | DOUBLE PRECISION, PARAMETER, PUBLIC :: udpmin=-1d2,udpmax=1d2
228 |
229 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
230 | !++++++++++++++++++++++ DEFINE PARTICLE ARRAYS +++++++++++++++++++++++
231 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
232 | !
233 | ! pcl_species(1,:)=x : x position of the particle
234 | ! pcl_species(2,:)=y : y position of the particle
235 | ! pcl_species(3,:)=z : z position of the particle
236 | ! pcl_species(4,:)=ux : x-component of the reduced particle 4-velocity
237 | ! pcl_species(5,:)=uy : y-component of the reduced particle 4-velocity
238 | ! pcl_species(6,:)=uz : z-component of the reduced particle 4-velocity
239 | ! pcl_species(7,:)=weight : weight of the particle
240 | !
241 | ! Defition of the particle distribution data function: it gives extra
242 | ! information regarding the particles, e.g., electric/magnetic field/force
243 | ! at the location of the particle.
244 | !
245 | ! pcl_data_species(1,:)=Ell : Electric field parallel to the particle velocity
246 | ! pcl_data_species(2,:)=Bpp : Magnetic field perp. to the particle velocity
247 | ! pcl_data_species(3,:)=Fr : Synchrotron radiation reaction force
248 | ! pcl_data_species(4,:)=Fe : Electric force
249 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
250 |
251 | ! DRIFTING ELECTRONS distribution function components
252 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_ed(:,:)
253 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_ed(:,:)
254 | INTEGER*8, ALLOCATABLE, PUBLIC :: taged(:)
255 |
256 | ! DRIFTING IONS distribution function components
257 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_pd(:,:)
258 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_pd(:,:)
259 | INTEGER*8, ALLOCATABLE, PUBLIC :: tagpd(:)
260 |
261 | ! BACKGROUND ELECTRONS distribution function components
262 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_eb(:,:)
263 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_eb(:,:)
264 | INTEGER*8, ALLOCATABLE, PUBLIC :: tageb(:)
265 |
266 | ! BACKGROUND IONS distribution function components
267 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_pb(:,:)
268 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_pb(:,:)
269 | INTEGER*8, ALLOCATABLE, PUBLIC :: tagpb(:)
270 |
271 | ! Temporary particle distribution function
272 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_f(:,:)
273 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_f(:,:)
274 | INTEGER*8, ALLOCATABLE, PUBLIC :: tagf(:)
275 |
276 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
277 | !+++++++++++++++++++++++++++++ ANALYSIS ++++++++++++++++++++++++++++++
278 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
279 |
280 | ! Data formatting (for data in text files) for integers and doubles
281 | CHARACTER(LEN=6), PARAMETER, PUBLIC :: FMT_INT="I26"
282 | CHARACTER(LEN=11), PARAMETER, PUBLIC :: FMT_DBL="E26.16E3"
283 |
284 | ! For text output of fields/density/pressure/current: (irrelevant for hdf5 output)
285 | ! If .TRUE., each MPI process will write to a separate file.
286 | ! This can be faster (for large simulations), but may create too many files.
287 | LOGICAL, PARAMETER, PUBLIC :: DUMP_FIELDS_PARALLEL=.FALSE.
288 |
289 | ! Switch ON/OFF write fields to disk
290 | LOGICAL, PARAMETER, PUBLIC :: WRITE_FIELDS=.TRUE.
291 |
292 | ! Switch ON/OFF write the charge and current densities to disk
293 | LOGICAL, PARAMETER, PUBLIC :: WRITE_RHOJ=.TRUE.
294 |
295 | ! For text output of particle data: (irrelevant for hdf5 output)
296 | ! If .TRUE., each MPI process will write to its own file.
297 | ! This can be faster (for large simulations), but may create too many files.
298 | LOGICAL, PARAMETER, PUBLIC :: DUMP_PARTICLES_PARALLEL=.FALSE.
299 |
300 | ! Switch ON/OFF write raw particle data to disk
301 | LOGICAL, PARAMETER, PUBLIC :: WRITE_PARTICLES=.FALSE.
302 |
303 | ! Switch ON/OFF particle tracker
304 | LOGICAL, PARAMETER, PUBLIC :: TRACK_PARTICLES=.FALSE.
305 |
306 | ! Switch ON/OFF analysis of particle energy and angular distributions
307 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_DISTRIBUTIONS=.TRUE.
308 |
309 | ! Switch ON/OFF analysis the plasma density
310 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_DENSITIES=.TRUE.
311 |
312 | ! Switch ON/OFF analysis the relativistic macroscopic fluid quantities
313 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_FLUID=.FALSE.
314 |
315 | ! Switch ON/OFF analysis the radiation spectra and anisotropies
316 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_RADIATION=.FALSE.
317 |
318 | ! Total number of tracked particles
319 | INTEGER, PARAMETER, PUBLIC :: NSAMPLE=100
320 |
321 | ! The time step from which particle-tracking should start
322 | INTEGER, PARAMETER, PUBLIC :: time_track=1
323 |
324 | ! The tracking frequency (timesteps between recording of tracking data)
325 | ! E.g., 1 = record every step; 2 = record every other step; ....
326 | INTEGER, PARAMETER, PUBLIC :: FTRACK=1
327 |
328 | ! Particle's 4-velocity grid for the spectrum
329 | INTEGER, PARAMETER, PUBLIC :: NU=100
330 |
331 | ! Spatial grid size for dumping EM-related fields
332 | ! If NFIELDX = NCX, etc., Zeltron dumps exactly the (nodal) field it uses.
333 | INTEGER, PARAMETER, PUBLIC :: NFIELDX=100,NFIELDY=100
334 |
335 | ! Spatial grid for dumping particle-related fields (densities, etc.)
336 | INTEGER, PARAMETER, PUBLIC :: NDX=100,NDY=100
337 |
338 | ! Angular distribution grid
339 | INTEGER, PARAMETER, PUBLIC :: NPHI=50,NLBA=90
340 |
341 | ! Synchrotron radiation frequency
342 | INTEGER, PARAMETER, PUBLIC :: NNU=100
343 |
344 | ! Frequency boundaries for the synchrotron radiation
345 | DOUBLE PRECISION, PARAMETER, PUBLIC :: nmin=1d9,nmax=1d14
346 |
347 | ! Latitude boundaries for the angular distribution (phi)
348 | DOUBLE PRECISION, PARAMETER, PUBLIC :: pmin=-89.99,pmax=89.99
349 |
350 | ! Longitude boundaries for the angular distribution (lambda)
351 | DOUBLE PRECISION, PARAMETER, PUBLIC :: lmin=-179.99,lmax=179.99
352 |
353 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
354 | !+++++++++++++++++++++++++ TUNING ++++++++++++++++++++++++++++++++++++
355 | ! You might want to adjust these parameters, but they should mostly
356 | ! be left as they are.
357 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
358 |
359 | ! (Inverse) frequency, in steps, with which all ranks communicate
360 | ! general info, such as whether to checkpoint, or the contents of the
361 | ! command file.
362 | INTEGER, PARAMETER, PUBLIC :: FGENCOMM=20
363 |
364 | ! Fraction of FSAVE by which a checkpoint time can be shifted (earlier)
365 | ! so that it occurs as the same time as a dump.
366 | DOUBLE PRECISION, PARAMETER, PUBLIC :: FSAVE_SHIFT_FRAC=0.25
367 |
368 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
369 | !+++++++++++++++++++++++++++++ DEBUGGING +++++++++++++++++++++++++++++
370 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
371 |
372 | ! For normal runs, RANDOMIZE = true ensures a different seed each run
373 | ! For testing new code, can set to false for reproducibility
374 | LOGICAL, PARAMETER, PUBLIC :: RANDOMIZE=.TRUE.
375 |
376 | ! whether to write one diagnostic file per rank
377 | LOGICAL, PARAMETER, PUBLIC :: writePerRankFiles=.FALSE.
378 |
379 | ! the name of the per-rank file
380 | CHARACTER(len=18), PUBLIC :: perRankFile
381 |
382 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
383 |
384 | END MODULE MOD_INPUT
385 |
--------------------------------------------------------------------------------
/Zeltron2D/mod_interp.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_INTERP
21 |
22 | USE MOD_INPUT
23 | USE MOD_MPI
24 |
25 | IMPLICIT NONE
26 |
27 | PRIVATE
28 |
29 | PUBLIC :: BILINEAR_FIELD ! Bilinear interpolation of a field value
30 | PUBLIC :: BILINEAR_FIELDS ! Bilinear interpolation of fields
31 |
32 | CONTAINS
33 |
34 | !***********************************************************************
35 | ! Function BILINEAR_FIELD: bilinear interpolation of the E and B fields
36 | ! INPUT: F (2D field to interpolate),
37 | ! (i,j) lower corner of cell within which to inteprolate
38 | ! xp, yq : weights within the cell for interpolation
39 | ! (xp = 0 means use F at i, xp = 1 means use F at i+1)
40 | ! (yq = 0 means use F at j, yq = 1 means use F at j+1)
41 | ! OUTPUT: interpolated value
42 | !***********************************************************************
43 |
44 | FUNCTION BILINEAR_FIELD(F, i, j, xp, yq)
45 |
46 | IMPLICIT NONE
47 |
48 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP) :: F
49 | INTEGER :: i,j
50 | DOUBLE PRECISION :: xp,yq
51 | INTEGER :: ip,jp
52 |
53 | DOUBLE PRECISION :: f00,f10,f01,f11
54 | DOUBLE PRECISION :: BILINEAR_FIELD
55 | !***********************************************************************
56 |
57 | ! Don't examine i+1 if it has zero weight, in case i+1 is past the array
58 | ip = i
59 | jp = j
60 | IF (xp > 0.) ip = ip + 1
61 | IF (yq > 0.) jp = jp + 1
62 | f00=F(i,j)
63 | f10=F(ip,j)
64 | f01=F(i,jp)
65 | f11=F(ip,jp)
66 |
67 | BILINEAR_FIELD = f00*(1.0-xp)*(1.0-yq) + f10*xp*(1.0-yq) &
68 | +f01*(1.0-xp)*yq + f11*xp*yq
69 |
70 | END FUNCTION
71 |
72 | !***********************************************************************
73 | ! Function BILINEAR_FIELDS: bilinear interpolation of the E and B fields
74 | ! INPUT: Bx,By,Bz,Ex,Ey,Ez (2D functions to interpolate),
75 | ! (xi,yi) (initial grid where fun2d is defined), and (xf,yf) (final grid).
76 | ! OUTPUT: bilinear_fields: fun2d calculated in the (xf,yf) grid.
77 | !***********************************************************************
78 |
79 | SUBROUTINE BILINEAR_FIELDS(xi,yi,xf,yf, Finterp, F1,F2,F3,F4,F5,F6)
80 |
81 | IMPLICIT NONE
82 |
83 | ! INPUT
84 | DOUBLE PRECISION, DIMENSION(1:NXP) :: xi
85 | DOUBLE PRECISION, DIMENSION(1:NYP) :: yi
86 | DOUBLE PRECISION :: xf,yf
87 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP) :: F1
88 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP), OPTIONAL :: F2,F3,F4,F5,F6
89 | ! OUTPUT
90 | DOUBLE PRECISION, DIMENSION(:), INTENT(OUT) :: Finterp
91 |
92 | ! indices
93 | INTEGER :: i,j
94 | ! weights
95 | DOUBLE PRECISION :: xp,yq
96 | !***********************************************************************
97 |
98 | ! Computation of the nearest node index to (xf,yf), for a constant dx,dy
99 | i=FLOOR((xf-xi(1))/dx)+1
100 | j=FLOOR((yf-yi(1))/dy)+1
101 |
102 | IF (i.EQ.NXP) THEN
103 | i=i-1
104 | END IF
105 |
106 | IF (j.EQ.NYP) THEN
107 | j=j-1
108 | END IF
109 |
110 | xp=(xf-xi(i))/dx
111 | yq=(yf-yi(j))/dy
112 |
113 | Finterp(1) = BILINEAR_FIELD(F1, i, j, xp, yq)
114 | IF (PRESENT(F2)) Finterp(2) = BILINEAR_FIELD(F2, i, j, xp, yq)
115 | IF (PRESENT(F3)) Finterp(3) = BILINEAR_FIELD(F3, i, j, xp, yq)
116 | IF (PRESENT(F4)) Finterp(4) = BILINEAR_FIELD(F4, i, j, xp, yq)
117 | IF (PRESENT(F5)) Finterp(5) = BILINEAR_FIELD(F5, i, j, xp, yq)
118 | IF (PRESENT(F6)) Finterp(6) = BILINEAR_FIELD(F6, i, j, xp, yq)
119 |
120 | END SUBROUTINE BILINEAR_FIELDS
121 |
122 | END MODULE MOD_INTERP
123 |
--------------------------------------------------------------------------------
/Zeltron2D/mod_log.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_LOG
21 |
22 | IMPLICIT NONE
23 |
24 | PRIVATE
25 |
26 | INTEGER, PARAMETER :: maxFileNameLen = 256
27 |
28 | TYPE DataLogObj
29 | DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: logEntries
30 | CHARACTER(len=maxFileNameLen) :: fileName
31 | INTEGER :: numEntries
32 | DOUBLE PRECISION :: waitTime
33 | DOUBLE PRECISION :: lastWriteTime
34 | ENDTYPE DataLogObj
35 |
36 | PUBLIC :: DataLogObj
37 |
38 | PUBLIC :: START_LOG
39 | PUBLIC :: END_LOG
40 | PUBLIC :: WRITE_LOG_TO_DISK
41 | PUBLIC :: ADD_LOG_DATA
42 |
43 | CONTAINS
44 |
45 | !***********************************************************************
46 | ! Subroutine START_LOG
47 | ! Allocate data log array
48 | !
49 | ! IN/OUT:
50 | ! - dataLog: the log
51 | ! - numColumns: the number of columns per entry
52 | ! - entriesPerDump: the maximum number of entries to store before writing to disk
53 | ! - timeBetweenDumps: the desired time between dumps, in seconds
54 | !
55 | !***********************************************************************
56 |
57 | SUBROUTINE START_LOG(dataLog, fileName, numColumns, entriesPerDump, &
58 | timeBetweenDumps)
59 |
60 | IMPLICIT NONE
61 |
62 | INCLUDE 'mpif.h'
63 |
64 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
65 | CHARACTER(len=*) :: fileName
66 | INTEGER :: numColumns, entriesPerDump
67 | DOUBLE PRECISION :: timeBetweenDumps
68 | !***********************************************************************
69 |
70 | ALLOCATE(dataLog%logEntries(numColumns, entriesPerDump))
71 | dataLog%numEntries = 0
72 | dataLog%fileName = " "
73 | dataLog%fileName(1:LEN(fileName)) = fileName
74 | dataLog%waitTime = timeBetweenDumps
75 | dataLog%lastWriteTime = MPI_WTIME()
76 |
77 | END SUBROUTINE START_LOG
78 |
79 | !***********************************************************************
80 | ! Subroutine END_LOG
81 | ! Finish writing log, never to add any more data
82 | !
83 | ! IN/OUT:
84 | ! - dataLog: the log
85 | !
86 | !***********************************************************************
87 |
88 | SUBROUTINE END_LOG(dataLog)
89 |
90 | IMPLICIT NONE
91 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
92 | !***********************************************************************
93 |
94 | CALL WRITE_LOG_TO_DISK(dataLog)
95 | DEALLOCATE(dataLog%logEntries)
96 |
97 | END SUBROUTINE END_LOG
98 |
99 | !***********************************************************************
100 | ! Subroutine WRITE_LOG_TO_DISK
101 | ! Write all log data to disk.
102 | !
103 | ! IN/OUT:
104 | ! - dataLog: the log
105 | !
106 | !***********************************************************************
107 |
108 | SUBROUTINE WRITE_LOG_TO_DISK(dataLog)
109 |
110 | IMPLICIT NONE
111 |
112 | INCLUDE 'mpif.h'
113 |
114 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
115 | ! LOCAL
116 | CHARACTER(len=280) :: fName
117 | INTEGER :: i,j, numColumns
118 | !***********************************************************************
119 |
120 | ! Open the file only if there's some data to be written
121 | IF (dataLog%numEntries > 0) THEN
122 | fname = trim(adjustl(dataLog%fileName))
123 | OPEN(9,FILE=fname,POSITION='APPEND')
124 | numColumns = SIZE(dataLog%logEntries, DIM = 1)
125 | DO j=1,dataLog%numEntries
126 | WRITE(9,*) (dataLog%logEntries(i,j), i=1, numColumns)
127 | ENDDO
128 | CLOSE(9)
129 | dataLog%numEntries = 0
130 | dataLog%lastWriteTime = MPI_WTIME()
131 | ENDIF
132 |
133 | END SUBROUTINE WRITE_LOG_TO_DISK
134 |
135 | !***********************************************************************
136 | ! Subroutine ADD_LOG_DATA
137 | ! Add a line of data to the log.
138 | !
139 | ! INPUT:
140 | ! - newLine: a new line of data to be logged
141 | ! IN/OUT:
142 | ! - dataLog: the to which data should be added
143 | !
144 | !***********************************************************************
145 |
146 | SUBROUTINE ADD_LOG_DATA(dataLog, newLine)
147 |
148 | IMPLICIT NONE
149 |
150 | INCLUDE 'mpif.h'
151 |
152 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
153 | DOUBLE PRECISION, DIMENSION(:) :: newLine
154 | !***********************************************************************
155 |
156 | dataLog%numEntries = dataLog%numEntries + 1
157 | dataLog%logEntries(:, dataLog%numEntries) = newLine
158 | IF ((dataLog%numEntries == SIZE(dataLog%logEntries, DIM = 2)) &
159 | .OR. (MPI_WTIME() - dataLog%lastWriteTime >= dataLog%waitTime)) THEN
160 | !print *, "Logger", dataLog%fileName, dataLog%numEntries, SIZE(dataLog%logEntries, DIM=2)
161 | !print *, " ", MPI_WTIME() - dataLog%lastWriteTime, dataLog%waitTime
162 | CALL WRITE_LOG_TO_DISK(dataLog)
163 | ENDIF
164 |
165 | END SUBROUTINE ADD_LOG_DATA
166 |
167 | !***********************************************************************
168 |
169 | END MODULE MOD_LOG
170 |
--------------------------------------------------------------------------------
/Zeltron2D/mod_mpi.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_MPI
21 |
22 | USE MOD_INPUT
23 |
24 | IMPLICIT NONE
25 |
26 | ! create a global variable to store the mpi rank, to be used for
27 | ! debugging output when a function doesn't have immediate access to this
28 | ! (except for debugging, this shouldn't be used, global variables being
29 | ! deprecated)
30 | INTEGER, PUBLIC :: globalMpiRank
31 |
32 | PRIVATE
33 | !PUBLIC
34 |
35 | PUBLIC :: CUMSUM ! Form the cumulative sum (running integral) of an array
36 | PUBLIC :: FILL_DOMAIN_INDEX ! Get the NDIM-dimensional domain index in cart. topology
37 | PUBLIC :: FILL_DOMAIN_DECOMP ! Get the NDIM-dimensional domain decomp, with index
38 | PUBLIC :: ELEMENTS_PER_DOMAIN ! Find the number elements per domain in each 1D direction
39 | PUBLIC :: FILL_GLOBAL_FIELD_SHAPE ! Get the global shape of a field from local shapes
40 | PUBLIC :: GATHER_GLOBAL_FIELD ! Gather the global field on one mpi rank
41 | PUBLIC :: FILL_RANK_ORDER ! Get the #ranks/node and the rank-node ordering
42 | PUBLIC :: ASSERT_DOUBLE ! verify (at compile time) that a variable is a double
43 |
44 | INTERFACE CUMSUM
45 | MODULE PROCEDURE CUMSUM_INT, CUMSUM_INT8
46 | END INTERFACE
47 |
48 | INTERFACE ELEMENTS_PER_DOMAIN
49 | MODULE PROCEDURE ELEMENTS_PER_DOMAIN_4, ELEMENTS_PER_DOMAIN_8
50 | END INTERFACE
51 |
52 | INTERFACE FILL_GLOBAL_FIELD_SHAPE
53 | MODULE PROCEDURE FILL_GLOBAL_FIELD_SHAPE_4, FILL_GLOBAL_FIELD_SHAPE_8
54 | END INTERFACE
55 |
56 | CONTAINS
57 |
58 | !***********************************************************************
59 | ! Subroutine CUMSUM
60 | ! Find the cumulative sum (like a running integral) of an array,
61 | ! such that the first element is zero,
62 | ! and also find the sum of all elements of raIn
63 | !
64 | ! INPUT:
65 | !
66 | ! - raIn: a 1D array
67 | ! OUTPUT:
68 | ! - raOut: raOut(n) = Sum_{m=1}^{n-1} raIn(m) (undefined for n > SIZE(raIn))
69 | ! raOut is the same size as raIn (or longer)
70 | ! - total: total = SUM(raIn)
71 | !
72 | !***********************************************************************
73 |
74 | SUBROUTINE CUMSUM_INT(raIn, raOut, total)
75 |
76 | IMPLICIT NONE
77 |
78 | ! INPUT
79 | INTEGER, DIMENSION(:), INTENT(IN) :: raIn
80 | INTEGER, DIMENSION(:), INTENT(OUT) :: raOut
81 | INTEGER, INTENT(OUT) :: total
82 | ! LOCAL
83 | INTEGER :: i
84 | !***********************************************************************
85 |
86 | total = 0
87 | IF (SIZE(raIn) > 0) THEN
88 | raOut(1) = 0
89 | DO i = 2, SIZE(raIn)
90 | raOut(i) = raOut(i-1) + raIn(i-1)
91 | ENDDO
92 | total = raOut(SIZE(raIn)) + raIn(SIZE(raIn))
93 | ENDIF
94 |
95 | END SUBROUTINE CUMSUM_INT
96 |
97 | !***********************************************************************
98 | ! Subroutine CUMSUM
99 | ! Find the cumulative sum (like a running integral) of an array,
100 | ! such that the first element is zero,
101 | ! and also find the sum of all elements of raIn
102 | !
103 | ! INPUT:
104 | !
105 | ! - raIn: a 1D array
106 | ! OUTPUT:
107 | ! - raOut: raOut(n) = Sum_{m=1}^{n-1} raIn(m) (undefined for n > SIZE(raIn))
108 | ! raOut is the same size as raIn (or longer)
109 | ! - total: total = SUM(raIn)
110 | !
111 | !***********************************************************************
112 |
113 | SUBROUTINE CUMSUM_INT8(raIn, raOut, total)
114 |
115 | IMPLICIT NONE
116 |
117 | ! INPUT
118 | INTEGER*8, DIMENSION(:), INTENT(IN) :: raIn
119 | INTEGER*8, DIMENSION(:), INTENT(OUT) :: raOut
120 | INTEGER*8, INTENT(OUT) :: total
121 | ! LOCAL
122 | INTEGER*8 :: i
123 | !***********************************************************************
124 |
125 | total = 0
126 | IF (SIZE(raIn) > 0) THEN
127 | raOut(1) = 0
128 | DO i = 2, SIZE(raIn)
129 | raOut(i) = raOut(i-1) + raIn(i-1)
130 | ENDDO
131 | total = raOut(SIZE(raIn)) + raIn(SIZE(raIn))
132 | ENDIF
133 |
134 | END SUBROUTINE CUMSUM_INT8
135 |
136 | !***********************************************************************
137 | ! Subroutine FILL_DOMAIN_DECOMP
138 | !
139 | ! INPUT:
140 | !
141 | ! - COMM: mpi comm
142 | !
143 | ! OUTPUT:
144 | ! - ierr: error code
145 | ! - domainDecomp the cartesian topology; e.g., in 2D, returns (NXP, NYP)
146 | ! if there are NXP domains in the x-direction, and NYP in y.
147 | ! - domainIndex the NDIM-dimensional domain index in cartesian topology
148 | ! (0-indexed)
149 | !
150 | !***********************************************************************
151 |
152 | SUBROUTINE FILL_DOMAIN_DECOMP(COMM, err, domainDecomp, domainIndex)
153 |
154 | IMPLICIT NONE
155 |
156 | INTEGER :: COMM
157 | INTEGER, INTENT(OUT):: err
158 | INTEGER, INTENT(OUT) :: domainDecomp(NDIM)
159 | INTEGER, INTENT(OUT) :: domainIndex(NDIM)
160 | LOGICAL :: periods(NDIM)
161 | INTEGER :: rank
162 | !***********************************************************************
163 |
164 | CALL MPI_COMM_RANK(COMM, rank, err)
165 |
166 | CALL MPI_CART_GET(COMM, NDIM, domainDecomp, periods, domainIndex, err)
167 |
168 | END SUBROUTINE FILL_DOMAIN_DECOMP
169 |
170 | !***********************************************************************
171 | ! Subroutine FILL_DOMAIN_INDEX
172 | !
173 | ! INPUT:
174 | !
175 | ! - COMM: mpi comm
176 | !
177 | ! OUTPUT:
178 | ! - ierr: error code
179 | ! - domainIndex the NDIM-dimensional domain index in cartesian topology
180 | ! (0-indexed)
181 | !
182 | !***********************************************************************
183 |
184 | SUBROUTINE FILL_DOMAIN_INDEX(COMM, err, domainIndex)
185 |
186 | IMPLICIT NONE
187 |
188 | INTEGER :: COMM
189 | INTEGER, INTENT(OUT):: err
190 | INTEGER, INTENT(OUT):: domainIndex(NDIM)
191 | INTEGER :: dims(NDIM)
192 | !***********************************************************************
193 |
194 | CALL FILL_DOMAIN_DECOMP(COMM, err, dims, domainIndex)
195 |
196 | END SUBROUTINE FILL_DOMAIN_INDEX
197 |
198 | !***********************************************************************
199 | ! Subroutine ELEMENTS_PER_DOMAIN
200 | ! This subroutine calculates the number of elements (of a grid), in
201 | ! each direction, belonging to each MPI domain. It assumes a rectangular
202 | ! decomposition, so that all domains at the same x-location have the
203 | ! same number of elements in the x-direction, etc.
204 | !
205 | ! INPUT:
206 | !
207 | ! - localRaShape: the shape of the array of values belonging to this domain
208 | ! - domIndex: 0-indexed coordinates of this domain, e.g., (/0,1/)
209 | ! - COMM: mpi comm
210 | !
211 | ! OUTPUT: the number of elements/proc in each direction
212 | ! - xElems: an array of size decompShape(1)
213 | ! - yElems: an array of size decompShape(2)
214 | ! E.g., xElems(domIndex(1)) = localRaShape(1)
215 | ! yElems(domIndex(2)) = localRaShape(2)
216 | !
217 | !***********************************************************************
218 |
219 | SUBROUTINE ELEMENTS_PER_DOMAIN_8(localRaShape, COMM, xElems, yElems, zElems)
220 |
221 | IMPLICIT NONE
222 |
223 | INCLUDE 'mpif.h'
224 |
225 | ! INPUT
226 | INTEGER(8), DIMENSION(NDIM) :: localRaShape
227 | INTEGER :: COMM
228 | ! OUTPUT
229 | INTEGER, INTENT(OUT) :: xElems(NPX), yElems(NPY)
230 | INTEGER, INTENT(OUT), OPTIONAL :: zElems(NPZ)
231 | ! LOCAL
232 | INTEGER, DIMENSION(NDIM) :: domIndex
233 | INTEGER :: mpiErr, rank
234 | INTEGER :: d
235 | INTEGER(8), DIMENSION(NDIM) :: raShape
236 | INTEGER :: xElemsTmp(NPX), yElemsTmp(NPY), zElemsTmp(NPZ)
237 | !***********************************************************************
238 |
239 | xElemsTmp = 0
240 | yElemsTmp = 0
241 | zElemsTmp = 0
242 |
243 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
244 | xElemsTmp(domIndex(1)+1) = localRaShape(1)
245 | yElemsTmp(domIndex(2)+1) = localRaShape(2)
246 |
247 | CALL MPI_ALLREDUCE(xElemsTmp, xElems, NPX, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
248 | CALL MPI_ALLREDUCE(yElemsTmp, yElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
249 |
250 | IF (NDIM == 2) THEN
251 | xElems = xElems / NPY
252 | yElems = yElems / NPX
253 | ELSEIF (NDIM == 3) THEN
254 | xElems = xElems / (NPY*NPZ)
255 | yElems = yElems / (NPX*NPY)
256 | d = MIN(NDIM, 3)
257 | zElemsTmp(domIndex(d)+1) = localRaShape(d)
258 | CALL MPI_ALLREDUCE(zElemsTmp, zElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
259 | ZElems = zElems / (NPX*NPY)
260 | raShape(d) = zElems(domIndex(d)+1)
261 | ENDIF
262 |
263 | ! check validity
264 | raShape(1) = xElems(domIndex(1)+1)
265 | raShape(2) = yElems(domIndex(2)+1)
266 | DO d = 1, NDIM
267 | IF (raShape(d) /= localRaShape(d)) THEN
268 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
269 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
270 | PRINT *, 'Error (in mod_io 8): rank ', rank, ' should have ', raShape(d), &
271 | ' elements (like all other procs in same line) in dir ', d, ' but has ', localRaShape(d)
272 | ENDIF
273 | ENDDO
274 |
275 | END SUBROUTINE
276 |
277 | !***********************************************************************
278 |
279 | SUBROUTINE ELEMENTS_PER_DOMAIN_4(localRaShape, COMM, xElems, yElems, zElems)
280 |
281 | IMPLICIT NONE
282 |
283 | INCLUDE 'mpif.h'
284 |
285 | ! INPUT
286 | INTEGER(4), DIMENSION(NDIM) :: localRaShape
287 | INTEGER :: COMM
288 | ! OUTPUT
289 | INTEGER, INTENT(OUT) :: xElems(NPX), yElems(NPY)
290 | INTEGER, INTENT(OUT), OPTIONAL :: zElems(NPZ)
291 | ! LOCAL
292 | INTEGER, DIMENSION(NDIM) :: domIndex
293 | INTEGER :: mpiErr, rank
294 | INTEGER :: d
295 | INTEGER(4), DIMENSION(NDIM) :: raShape
296 | INTEGER :: xElemsTmp(NPX), yElemsTmp(NPY), zElemsTmp(NPZ)
297 | !***********************************************************************
298 |
299 | xElemsTmp = 0
300 | yElemsTmp = 0
301 | zElemsTmp = 0
302 |
303 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
304 | xElemsTmp(domIndex(1)+1) = localRaShape(1)
305 | yElemsTmp(domIndex(2)+1) = localRaShape(2)
306 |
307 | CALL MPI_ALLREDUCE(xElemsTmp, xElems, NPX, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
308 | CALL MPI_ALLREDUCE(yElemsTmp, yElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
309 |
310 | IF (NDIM == 2) THEN
311 | xElems = xElems / NPY
312 | yElems = yElems / NPX
313 | ELSEIF (NDIM == 3) THEN
314 | xElems = xElems / (NPY*NPZ)
315 | yElems = yElems / (NPX*NPY)
316 | d = MIN(NDIM, 3)
317 | zElemsTmp(domIndex(d)+1) = localRaShape(d)
318 | CALL MPI_ALLREDUCE(zElemsTmp, zElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
319 | ZElems = zElems / (NPX*NPY)
320 | raShape(d) = zElems(domIndex(d)+1)
321 | ENDIF
322 |
323 | ! check validity
324 | raShape(1) = xElems(domIndex(1)+1)
325 | raShape(2) = yElems(domIndex(2)+1)
326 | DO d = 1, NDIM
327 | IF (raShape(d) /= localRaShape(d)) THEN
328 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
329 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
330 | PRINT *, 'Error (in mod_io 4): rank ', rank, ' should have ', raShape(d), &
331 | ' elements (like all other procs in same line) in dir ', d, ' but has ', localRaShape(d)
332 | ENDIF
333 | ENDDO
334 |
335 | END SUBROUTINE
336 |
337 | !***********************************************************************
338 | ! Subroutine FILL_GLOBAL_FIELD_SHAPE
339 | ! Given the local field shape on each rank,
340 | ! find the global field shape, and the offset, in global indices,
341 | ! of the field value with local index (0,0)
342 | !
343 | ! INPUT:
344 | ! - localShape
345 | ! - COMM: mpi comm
346 | ! OUTPUT:
347 | ! - globalShape
348 | ! - offset
349 | !***********************************************************************
350 |
351 | SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_4(localShape, globalShape, offset, COMM)
352 |
353 | IMPLICIT NONE
354 |
355 | INCLUDE 'mpif.h'
356 |
357 | ! INPUT
358 | ! following must have rank=NDIM
359 | INTEGER*4, DIMENSION(NDIM) :: localShape
360 | INTEGER*4, DIMENSION(NDIM), INTENT(OUT) :: globalShape, offset
361 | INTEGER :: COMM
362 |
363 | ! LOCAL
364 | INTEGER, DIMENSION(NDIM) :: domIndex
365 | INTEGER, DIMENSION(NPX) :: xElemPerProc
366 | INTEGER, DIMENSION(NPY) :: yElemPerProc
367 | INTEGER, DIMENSION(NPZ) :: zElemPerProc
368 | INTEGER :: mpiErr, numRanks, rank
369 | !***********************************************************************
370 |
371 | CALL MPI_COMM_SIZE(COMM, numRanks, mpiErr)
372 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
373 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
374 |
375 | ! find shape of local array on each domain
376 | IF (NDIM == 2) THEN
377 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc)
378 | ELSE
379 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc, zElemPerProc)
380 | ENDIF
381 |
382 | globalShape(1) = SUM(xElemPerProc)
383 | globalShape(2) = SUM(yElemPerProc)
384 |
385 | offset(1) = SUM(xElemPerProc(:domIndex(1)))
386 | offset(2) = SUM(yElemPerProc(:domIndex(2)))
387 |
388 | IF (NDIM >= 3) THEN
389 | globalShape(MIN(NDIM,3)) = SUM(zElemPerProc)
390 | offset(MIN(NDIM,3)) = SUM(zElemPerProc(:domIndex(MIN(NDIM,3))))
391 | ENDIF
392 |
393 | END SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_4
394 |
395 | !***********************************************************************
396 | ! Subroutine FILL_GLOBAL_FIELD_SHAPE
397 | ! Given the local field shape on each rank,
398 | ! find the global field shape, and the offset, in global indices,
399 | ! of the field value with local index (0,0)
400 | !
401 | ! INPUT:
402 | ! - localShape
403 | ! - COMM: mpi comm
404 | ! OUTPUT:
405 | ! - globalShape
406 | ! - offset
407 | !***********************************************************************
408 |
409 | SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_8(localShape, globalShape, offset, COMM)
410 |
411 | IMPLICIT NONE
412 |
413 | INCLUDE 'mpif.h'
414 |
415 | ! INPUT
416 | ! following must have rank=NDIM
417 | INTEGER*8, DIMENSION(NDIM) :: localShape
418 | INTEGER*8, DIMENSION(NDIM), INTENT(OUT) :: globalShape, offset
419 | INTEGER :: COMM
420 |
421 | ! LOCAL
422 | INTEGER, DIMENSION(NDIM) :: domIndex
423 | INTEGER, DIMENSION(NPX) :: xElemPerProc
424 | INTEGER, DIMENSION(NPY) :: yElemPerProc
425 | INTEGER, DIMENSION(NPZ) :: zElemPerProc
426 | INTEGER :: mpiErr, numRanks, rank
427 | !***********************************************************************
428 |
429 | CALL MPI_COMM_SIZE(COMM, numRanks, mpiErr)
430 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
431 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
432 |
433 | ! find shape of local array on each domain
434 | IF (NDIM == 2) THEN
435 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc)
436 | ELSE
437 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc, zElemPerProc)
438 | ENDIF
439 |
440 | globalShape(1) = SUM(xElemPerProc)
441 | globalShape(2) = SUM(yElemPerProc)
442 |
443 | offset(1) = SUM(xElemPerProc(:domIndex(1)))
444 | offset(2) = SUM(yElemPerProc(:domIndex(2)))
445 |
446 | IF (NDIM >= 3) THEN
447 | globalShape(MIN(NDIM,3)) = SUM(zElemPerProc)
448 | offset(MIN(NDIM,3)) = SUM(zElemPerProc(:domIndex(MIN(NDIM,3))))
449 | ENDIF
450 |
451 | END SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_8
452 |
453 | !***********************************************************************
454 | ! Subroutine GATHER_GLOBAL_FIELD
455 | ! Gather field values from all ranks to a global field on one rank.
456 | !
457 | ! INPUT:
458 | !
459 | ! - F the local field values for this rank
460 | ! - Ft an array (already allocated) with the global field shape
461 | ! - on rank = gatherRank, this will contain the global field
462 | ! - on other ranks, this is undefined
463 | ! - offset an array giving the global index of F(0,0[,0])
464 | ! - COMM: mpi comm
465 | !
466 | ! OUTPUT: the number of elements/proc in each direction
467 | !
468 | !***********************************************************************
469 |
470 | SUBROUTINE GATHER_GLOBAL_FIELD(F, Ft, offset, gatherRank, COMM)
471 |
472 | IMPLICIT NONE
473 |
474 | INCLUDE 'mpif.h'
475 |
476 | ! INPUT
477 | ! following must have rank=NDIM
478 | DOUBLE PRECISION, DIMENSION(:,:) :: F
479 | DOUBLE PRECISION, DIMENSION(:,:), INTENT(OUT) :: Ft
480 | INTEGER, DIMENSION(NDIM) :: offset
481 | INTEGER :: gatherRank
482 | INTEGER :: COMM
483 |
484 | ! LOCAL
485 | DOUBLE PRECISION, ALLOCATABLE :: Ft2(:,:)
486 | INTEGER, DIMENSION(NDIM) :: domIndex
487 | INTEGER, DIMENSION(NPX) :: xElemPerProc
488 | INTEGER, DIMENSION(NPY) :: yElemPerProc
489 | INTEGER, DIMENSION(NPZ) :: zElemPerProc
490 | CHARACTER(len=10) :: cit
491 |
492 | ! shape of local and global field array
493 | INTEGER, DIMENSION(NDIM) :: localShape
494 | INTEGER, DIMENSION(NDIM) :: globalShape
495 |
496 | INTEGER :: mpiErr, numRanks, rank
497 |
498 | INTEGER :: d, i, j
499 | !***********************************************************************
500 |
501 | localShape = SHAPE(F)
502 | globalShape = SHAPE(Ft)
503 |
504 | ALLOCATE(Ft2(globalShape(1), globalShape(2)))
505 |
506 | Ft2 = 0.
507 |
508 | DO j=1, localShape(2)
509 | DO i=1, localShape(1)
510 | Ft2(offset(1) + i, offset(2) + j) = F(i,j)
511 | ENDDO
512 | ENDDO
513 |
514 | ! :TODO: it would be better to use MPI_GATHERV, but it's a lot easier to use MPI_REDUCE
515 | ! Get all field values on rank 0
516 | CALL MPI_REDUCE(Ft2,Ft,PRODUCT(globalShape),MPI_DOUBLE_PRECISION,MPI_SUM,&
517 | gatherRank,COMM,mpiErr)
518 |
519 | DEALLOCATE(Ft2)
520 |
521 | END SUBROUTINE GATHER_GLOBAL_FIELD
522 |
523 | !***********************************************************************
524 | ! Subroutine FILL_RANK_ORDER
525 | ! Determine (by examing the hostname of the first two ranks)
526 | ! whether the order is round-robin or not.
527 | !
528 | ! INPUT:
529 | ! -COMM: mpi comm (should be global comm)
530 | !
531 | ! OUTPUT: Assuming M ranks per node, and N nodes
532 | ! - rankOrder
533 | ! =0 if rank r is on node (r%N)
534 | ! =1 if rank r is on node floor(r/M)
535 | ! If there's only one rank, or if ranksPerNode = 1, then rankOrder = 1
536 | ! - ranksPerNode: the number of ranksPerNode
537 | !
538 | !***********************************************************************
539 |
540 | SUBROUTINE FILL_RANK_ORDER(COMM, rankOrder, ranksPerNode)
541 |
542 | IMPLICIT NONE
543 |
544 | INCLUDE 'mpif.h'
545 |
546 | ! INPUT
547 | INTEGER :: COMM
548 | INTEGER, INTENT(OUT) :: rankOrder, ranksPerNode
549 | ! LOCAL
550 | CHARACTER*(MPI_MAX_PROCESSOR_NAME) :: hostName, hostNameRank0
551 | INTEGER :: hostnameLen
552 | INTEGER :: sameNameAsRank0
553 | INTEGER :: rank, numRanks, mpiErr
554 | INTEGER :: i, nextOnDifferentNode, nextOnSameNode
555 | INTEGER :: tag
556 | INTEGER, DIMENSION(:), ALLOCATABLE :: onFirstNode
557 | !***********************************************************************
558 |
559 | ! Determine which other ranks are running on the same node as rank 0.
560 | ! From that, infer the number of ranks per node, and whether the ordering
561 | ! has adjacent ranks on the same node, or is round robin.
562 |
563 | CALL MPI_COMM_SIZE(COMM, numRanks, mpiErr)
564 | IF (numRanks == 1) THEN
565 | rankOrder = 1
566 | ranksPerNode = 1
567 | ELSE
568 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
569 | CALL MPI_GET_PROCESSOR_NAME(hostName, hostnameLen, mpiErr)
570 | hostName(hostnameLen+1:MPI_MAX_PROCESSOR_NAME) = ' '
571 | ! Broadcast hostName of rank 0 to everybody
572 | IF (rank == 0) THEN
573 | CALL MPI_BCAST(hostName, MPI_MAX_PROCESSOR_NAME, MPI_CHARACTER, 0, &
574 | COMM, mpiErr)
575 | hostNameRank0 = hostName
576 | ALLOCATE(onFirstNode(numRanks))
577 | ELSE
578 | CALL MPI_BCAST(hostNameRank0, MPI_MAX_PROCESSOR_NAME, MPI_CHARACTER, 0,&
579 | COMM, mpiErr)
580 | ENDIF
581 | sameNameAsRank0 = 0
582 | IF (hostName == hostNameRank0) sameNameAsRank0 = 1
583 | CALL MPI_GATHER(sameNameAsRank0, 1, MPI_INTEGER, onFirstNode, 1,&
584 | MPI_INTEGER, 0, COMM, mpiErr)
585 | IF (rank == 0) THEN
586 | ! Find the next rank that's on the same node, and the next that's
587 | ! on a different node (from rank 0).
588 | nextOnDifferentNode = numRanks
589 | DO i = 2, numRanks
590 | IF (onFirstNode(i) == 0) THEN
591 | nextOnDifferentNode = i - 1
592 | EXIT
593 | ENDIF
594 | ENDDO
595 | nextOnSameNode = numRanks
596 | DO i = 2, numRanks
597 | IF (onFirstNode(i) == 1) THEN
598 | nextOnSameNode = i - 1
599 | EXIT
600 | ENDIF
601 | ENDDO
602 | IF (nextOnSameNode == 1) THEN
603 | rankOrder = 1
604 | ranksPerNode = nextOnDifferentNode
605 | ENDIF
606 | IF (nextOnDifferentNode == 1) THEN
607 | rankOrder = 0
608 | ! Following assumes a constant ranksPerNode
609 | ranksPerNode = numRanks / nextOnSameNode
610 | ENDIF
611 | IF (ranksPerNode == 1) THEN
612 | rankOrder = 1
613 | ENDIF
614 | DEALLOCATE(onFirstNode)
615 | ENDIF
616 | CALL MPI_BCAST(rankOrder, 1, MPI_INTEGER, 0, COMM, mpiErr)
617 | CALL MPI_BCAST(ranksPerNode, 1, MPI_INTEGER, 0, COMM, mpiErr)
618 | ENDIF
619 |
620 | END SUBROUTINE FILL_RANK_ORDER
621 |
622 | !***********************************************************************
623 | ! Subroutine CHECK_DOUBLE
624 | !
625 | ! This subroutine will cause a compilation error if the argument is not
626 | ! a double.
627 | !***********************************************************************
628 |
629 | SUBROUTINE ASSERT_DOUBLE(dbl)
630 |
631 | IMPLICIT NONE
632 |
633 | DOUBLE PRECISION, INTENT(IN) :: dbl
634 |
635 | END SUBROUTINE ASSERT_DOUBLE
636 |
637 | !***********************************************************************
638 |
639 | END MODULE
640 |
--------------------------------------------------------------------------------
/Zeltron2D/mod_rhoj.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_RHOJ
21 |
22 | USE MOD_INPUT
23 |
24 | IMPLICIT NONE
25 |
26 | PRIVATE
27 |
28 | PUBLIC :: RHOJ ! computes the charge density and current on grid nodes
29 | PUBLIC :: COM_RHOJ ! computes the charge density and current at the boundaries between domains
30 | PUBLIC :: JYEE ! computes J in the Yee lattice
31 |
32 | CONTAINS
33 |
34 | !***********************************************************************
35 | ! Subroutine RHOJ
36 | ! This subroutine computes the charge density RHO and *half* of the
37 | ! current density J on grid nodes.
38 |
39 | ! INPUT:
40 | ! - q: sign electric charge
41 | ! - pcl: Particle distribution function
42 | !
43 | ! OUTPUT: RHO at t=t+dt and Jx, Jy, Jz at t=t+dt/2
44 | !
45 | ! REMINDER: North=1,East=2,South=3,West=4,NEast=5,SEast=6,SWest=7,NWest=8
46 | !***********************************************************************
47 |
48 | SUBROUTINE RHOJ(q,pcl,rho,Jx,Jy,Jz,xgp,ygp,NPP,id,ngh,COMM,ierr)
49 |
50 | IMPLICIT NONE
51 |
52 | INCLUDE 'mpif.h'
53 |
54 | INTEGER*8 :: ip,NPP
55 | DOUBLE PRECISION :: q,rhop,gam,vx,vy,vz
56 | DOUBLE PRECISION, DIMENSION(1:7,1:NPP) :: pcl
57 | DOUBLE PRECISION :: x,y,ux,uy,uz,wght
58 | DOUBLE PRECISION, DIMENSION(1:NXP) :: xgp
59 | DOUBLE PRECISION, DIMENSION(1:NYP) :: ygp
60 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP) :: rho,Jx,Jy,Jz
61 | DOUBLE PRECISION :: fp,fq
62 | INTEGER :: i,j
63 | INTEGER, DIMENSION(8) :: ngh
64 | INTEGER :: id,COMM,ierr
65 |
66 | !***********************************************************************
67 |
68 | rho=0.0
69 | Jx=0.0
70 | Jy=0.0
71 | Jz=0.0
72 |
73 | DO ip=1,NPP
74 |
75 | x=pcl(1,ip)
76 | y=pcl(2,ip)
77 | ux=pcl(4,ip)
78 | uy=pcl(5,ip)
79 | uz=pcl(6,ip)
80 | wght=pcl(7,ip)
81 |
82 | ! Charge density of 1 super-particle in the cell (i,j)
83 | rhop=q*e*wght/(dx*dy)
84 |
85 | ! Lorentz factor
86 | gam=sqrt(1.0+ux*ux+uy*uy+uz*uz)
87 |
88 | ! 3-velocity components
89 | vx=ux*c/gam
90 | vy=uy*c/gam
91 | vz=uz*c/gam
92 |
93 | ! Computation of the nearest node index to (xf,yf), for a constant dx,dy
94 | i=FLOOR((x-xgp(1))/dx)+1
95 | j=FLOOR((y-ygp(1))/dy)+1
96 |
97 | IF (i.EQ.NXP) THEN
98 | i=i-1
99 | END IF
100 |
101 | IF (j.EQ.NYP) THEN
102 | j=j-1
103 | END IF
104 |
105 | fp=(x-xgp(i))/dx
106 | fq=(y-ygp(j))/dy
107 |
108 | !=====================================================================
109 | ! Charge density
110 |
111 | rho(i,j)=rho(i,j)+rhop*(1.0-fp)*(1.0-fq)
112 | rho(i+1,j)=rho(i+1,j)+rhop*fp*(1.0-fq)
113 | rho(i,j+1)=rho(i,j+1)+rhop*(1.0-fp)*fq
114 | rho(i+1,j+1)=rho(i+1,j+1)+rhop*fp*fq
115 |
116 | !=====================================================================
117 | ! Current density
118 |
119 | ! x-component:
120 | Jx(i,j)=Jx(i,j)+0.5*rhop*vx*(1.0-fp)*(1.0-fq)
121 | Jx(i+1,j)=Jx(i+1,j)+0.5*rhop*vx*fp*(1.0-fq)
122 | Jx(i,j+1)=Jx(i,j+1)+0.5*rhop*vx*(1.0-fp)*fq
123 | Jx(i+1,j+1)=Jx(i+1,j+1)+0.5*rhop*vx*fp*fq
124 |
125 | ! y-component:
126 | Jy(i,j)=Jy(i,j)+0.5*rhop*vy*(1.0-fp)*(1.0-fq)
127 | Jy(i+1,j)=Jy(i+1,j)+0.5*rhop*vy*fp*(1.0-fq)
128 | Jy(i,j+1)=Jy(i,j+1)+0.5*rhop*vy*(1.0-fp)*fq
129 | Jy(i+1,j+1)=Jy(i+1,j+1)+0.5*rhop*vy*fp*fq
130 |
131 | ! z-component:
132 | Jz(i,j)=Jz(i,j)+0.5*rhop*vz*(1.0-fp)*(1.0-fq)
133 | Jz(i+1,j)=Jz(i+1,j)+0.5*rhop*vz*fp*(1.0-fq)
134 | Jz(i,j+1)=Jz(i,j+1)+0.5*rhop*vz*(1.0-fp)*fq
135 | Jz(i+1,j+1)=Jz(i+1,j+1)+0.5*rhop*vz*fp*fq
136 |
137 | ENDDO
138 |
139 | CALL COM_RHOJ(rho,xgp,ygp,id,ngh,COMM,ierr)
140 | CALL COM_RHOJ(Jx,xgp,ygp,id,ngh,COMM,ierr)
141 | CALL COM_RHOJ(Jy,xgp,ygp,id,ngh,COMM,ierr)
142 | CALL COM_RHOJ(Jz,xgp,ygp,id,ngh,COMM,ierr)
143 |
144 | END SUBROUTINE RHOJ
145 |
146 | !***********************************************************************
147 | ! Subroutine COM_RHOJ
148 | ! This subroutine computes the charge density RHO and current density J
149 | ! at the boundaries between sub-domains.
150 |
151 | ! INPUT:
152 | ! - fun: RHO or Jx,y,z
153 | ! - local grid: xgp,ygp
154 | !
155 | ! OUTPUT: RHO or Jx,y,z at the boundaries
156 | !
157 | ! REMINDER: North=1,East=2,South=3,West=4,NEast=5,SEast=6,SWest=7,NWest=8
158 | !***********************************************************************
159 |
160 | SUBROUTINE COM_RHOJ(fun,xgp,ygp,id,ngh,COMM,ierr)
161 |
162 | IMPLICIT NONE
163 |
164 | INCLUDE 'mpif.h'
165 |
166 | INTEGER, DIMENSION(MPI_STATUS_SIZE) :: stat
167 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP) :: fun
168 | DOUBLE PRECISION, DIMENSION(1:NXP) :: xgp
169 | DOUBLE PRECISION, DIMENSION(1:NYP) :: ygp
170 | INTEGER, DIMENSION(8) :: ngh
171 | INTEGER, PARAMETER :: tag1=10,tag2=20,tag3=30,tag4=40
172 | INTEGER, PARAMETER :: tag5=50,tag6=60,tag7=70,tag8=80
173 | INTEGER :: id,COMM,ierr
174 | DOUBLE PRECISION, DIMENSION(1:NXP) :: bufSN,bufSS,bufRN,bufRS
175 | DOUBLE PRECISION, DIMENSION(1:NYP) :: bufSE,bufSW,bufRE,bufRW
176 | DOUBLE PRECISION :: bufSNE,bufSSE,bufSSW,bufSNW
177 | DOUBLE PRECISION :: bufRNE,bufRSE,bufRSW,bufRNW
178 | !***********************************************************************
179 |
180 | bufSS=fun(:,1)
181 | bufSN=fun(:,NYP)
182 |
183 | bufSW=fun(1,:)
184 | bufSE=fun(NXP,:)
185 |
186 | bufSNE=fun(NXP,NYP)
187 | bufSSE=fun(NXP,1)
188 | bufSSW=fun(1,1)
189 | bufSNW=fun(1,NYP)
190 |
191 | IF (MOD(id,2).EQ.0) THEN
192 |
193 | CALL MPI_SENDRECV(bufSN,NXP,MPI_DOUBLE_PRECISION,ngh(1),tag1,&
194 | bufRS,NXP,MPI_DOUBLE_PRECISION,ngh(3),tag1,COMM,stat,ierr)
195 |
196 | CALL MPI_SENDRECV(bufSS,NXP,MPI_DOUBLE_PRECISION,ngh(3),tag2,&
197 | bufRN,NXP,MPI_DOUBLE_PRECISION,ngh(1),tag2,COMM,stat,ierr)
198 |
199 | CALL MPI_SENDRECV(bufSE,NYP,MPI_DOUBLE_PRECISION,ngh(2),tag3,&
200 | bufRW,NYP,MPI_DOUBLE_PRECISION,ngh(4),tag3,COMM,stat,ierr)
201 |
202 | CALL MPI_SENDRECV(bufSW,NYP,MPI_DOUBLE_PRECISION,ngh(4),tag4,&
203 | bufRE,NYP,MPI_DOUBLE_PRECISION,ngh(2),tag4,COMM,stat,ierr)
204 |
205 | CALL MPI_SENDRECV(bufSNE,1,MPI_DOUBLE_PRECISION,ngh(5),tag5,&
206 | bufRSW,1,MPI_DOUBLE_PRECISION,ngh(7),tag5,COMM,stat,ierr)
207 |
208 | CALL MPI_SENDRECV(bufSSE,1,MPI_DOUBLE_PRECISION,ngh(6),tag6,&
209 | bufRNW,1,MPI_DOUBLE_PRECISION,ngh(8),tag6,COMM,stat,ierr)
210 |
211 | CALL MPI_SENDRECV(bufSSW,1,MPI_DOUBLE_PRECISION,ngh(7),tag7,&
212 | bufRNE,1,MPI_DOUBLE_PRECISION,ngh(5),tag7,COMM,stat,ierr)
213 |
214 | CALL MPI_SENDRECV(bufSNW,1,MPI_DOUBLE_PRECISION,ngh(8),tag8,&
215 | bufRSE,1,MPI_DOUBLE_PRECISION,ngh(6),tag8,COMM,stat,ierr)
216 |
217 | ELSE
218 |
219 | CALL MPI_SENDRECV(bufSN,NXP,MPI_DOUBLE_PRECISION,ngh(1),tag1,&
220 | bufRS,NXP,MPI_DOUBLE_PRECISION,ngh(3),tag1,COMM,stat,ierr)
221 |
222 | CALL MPI_SENDRECV(bufSS,NXP,MPI_DOUBLE_PRECISION,ngh(3),tag2,&
223 | bufRN,NXP,MPI_DOUBLE_PRECISION,ngh(1),tag2,COMM,stat,ierr)
224 |
225 | CALL MPI_SENDRECV(bufSE,NYP,MPI_DOUBLE_PRECISION,ngh(2),tag3,&
226 | bufRW,NYP,MPI_DOUBLE_PRECISION,ngh(4),tag3,COMM,stat,ierr)
227 |
228 | CALL MPI_SENDRECV(bufSW,NYP,MPI_DOUBLE_PRECISION,ngh(4),tag4,&
229 | bufRE,NYP,MPI_DOUBLE_PRECISION,ngh(2),tag4,COMM,stat,ierr)
230 |
231 | CALL MPI_SENDRECV(bufSNE,1,MPI_DOUBLE_PRECISION,ngh(5),tag5,&
232 | bufRSW,1,MPI_DOUBLE_PRECISION,ngh(7),tag5,COMM,stat,ierr)
233 |
234 | CALL MPI_SENDRECV(bufSSE,1,MPI_DOUBLE_PRECISION,ngh(6),tag6,&
235 | bufRNW,1,MPI_DOUBLE_PRECISION,ngh(8),tag6,COMM,stat,ierr)
236 |
237 | CALL MPI_SENDRECV(bufSSW,1,MPI_DOUBLE_PRECISION,ngh(7),tag7,&
238 | bufRNE,1,MPI_DOUBLE_PRECISION,ngh(5),tag7,COMM,stat,ierr)
239 |
240 | CALL MPI_SENDRECV(bufSNW,1,MPI_DOUBLE_PRECISION,ngh(8),tag8,&
241 | bufRSE,1,MPI_DOUBLE_PRECISION,ngh(6),tag8,COMM,stat,ierr)
242 |
243 | ENDIF
244 |
245 | !***********************************************************************
246 | ! Check boundary conditions along X
247 |
248 | IF (xgp(1).EQ.xmin) THEN
249 |
250 | IF (BOUND_FIELD_XMIN.NE."PERIODIC") THEN
251 | bufRW(:)=0.0
252 | bufRNW=0.0
253 | bufRSW=0.0
254 | END IF
255 |
256 | END IF
257 |
258 | IF (xgp(NXP).EQ.xmax) THEN
259 |
260 | IF (BOUND_FIELD_XMAX.NE."PERIODIC") THEN
261 | bufRE(:)=0.0
262 | bufRNE=0.0
263 | bufRSE=0.0
264 | END IF
265 |
266 | END IF
267 |
268 | !***********************************************************************
269 | ! Check boundary conditions along Y
270 |
271 | IF (ygp(1).EQ.ymin) THEN
272 |
273 | IF (BOUND_FIELD_YMIN.NE."PERIODIC") THEN
274 | bufRS(:)=0.0
275 | bufRSW=0.0
276 | bufRSE=0.0
277 | END IF
278 |
279 | END IF
280 |
281 | IF (ygp(NYP).EQ.ymax) THEN
282 |
283 | IF (BOUND_FIELD_YMAX.NE."PERIODIC") THEN
284 | bufRN(:)=0.0
285 | bufRNW=0.0
286 | bufRNE=0.0
287 | END IF
288 |
289 | END IF
290 |
291 | !***********************************************************************
292 |
293 | fun(NXP,:)=fun(NXP,:)+bufRE(:)
294 | fun(1,:)=fun(1,:)+bufRW(:)
295 |
296 | fun(:,NYP)=fun(:,NYP)+bufRN(:)
297 | fun(:,1)=fun(:,1)+bufRS(:)
298 |
299 | fun(1,1)=fun(1,1)+bufRSW
300 | fun(NXP,1)=fun(NXP,1)+bufRSE
301 | fun(1,NYP)=fun(1,NYP)+bufRNW
302 | fun(NXP,NYP)=fun(NXP,NYP)+bufRNE
303 |
304 | END SUBROUTINE COM_RHOJ
305 |
306 | !***********************************************************************
307 | ! Subroutine JYEE
308 | ! This subroutine computes the current density in the Yee lattice.
309 |
310 | ! INPUT:
311 | ! - Jx: x-component of the current density J at the nodes at t=t+dt/2
312 | ! - Jy: y-component of the current density J at the nodes at t=t+dt/2
313 | ! - Jz: z-component of the current density J at the nodes at t=t+dt/2
314 | !
315 | ! OUTPUT: Jx, Jy, Jz at t=t+dt/2 in the Yee lattice
316 | !
317 | ! REMINDER: North=1,East=2,South=3,West=4,NEast=5,SEast=6,SWest=7,NWest=8
318 | !***********************************************************************
319 |
320 | SUBROUTINE JYEE(Jx,Jy,Jz,xgp,ygp,id,ngh,COMM,ierr)
321 |
322 | IMPLICIT NONE
323 |
324 | INCLUDE 'mpif.h'
325 |
326 | INTEGER, DIMENSION(MPI_STATUS_SIZE) :: stat
327 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP) :: Jx,Jy,Jz
328 | DOUBLE PRECISION, DIMENSION(1:NXP) :: xgp
329 | DOUBLE PRECISION, DIMENSION(1:NYP) :: ygp
330 | DOUBLE PRECISION :: xmaxp,ymaxp
331 | INTEGER :: ix,iy
332 | INTEGER, DIMENSION(8) :: ngh
333 | INTEGER, PARAMETER :: tag=5
334 | INTEGER :: id,COMM,ierr
335 | DOUBLE PRECISION, ALLOCATABLE :: bufS(:),bufR(:)
336 |
337 | !***********************************************************************
338 |
339 | xmaxp=xgp(NXP)
340 | ymaxp=ygp(NYP)
341 |
342 | !***********************************************************************
343 | ! Jx
344 |
345 | ALLOCATE(bufS(1:NYP),bufR(1:NYP))
346 |
347 | bufS=Jx(2,:)
348 |
349 | IF (MOD(id,2).EQ.0) THEN
350 | CALL MPI_SENDRECV(bufS,NYP,MPI_DOUBLE_PRECISION,ngh(4),tag,&
351 | bufR,NYP,MPI_DOUBLE_PRECISION,ngh(2),tag,COMM,stat,ierr)
352 | ELSE
353 | CALL MPI_SENDRECV(bufS,NYP,MPI_DOUBLE_PRECISION,ngh(4),tag,&
354 | bufR,NYP,MPI_DOUBLE_PRECISION,ngh(2),tag,COMM,stat,ierr)
355 | ENDIF
356 |
357 | DO ix=1,NXP-1
358 | Jx(ix,:)=(Jx(ix+1,:)+Jx(ix,:))/2.0
359 | ENDDO
360 |
361 | !***********************************************************************
362 | ! Check boundary conditions along X
363 |
364 | IF (xmaxp.EQ.xmax) THEN
365 |
366 | IF (BOUND_FIELD_XMAX.EQ."METAL") THEN
367 | bufR(:)=0.0
368 | ENDIF
369 |
370 | END IF
371 | !***********************************************************************
372 |
373 | Jx(NXP,:)=(bufR(:)+Jx(NXP,:))/2.0
374 |
375 | DEALLOCATE(bufS,bufR)
376 |
377 | !***********************************************************************
378 | ! Jy
379 |
380 | ALLOCATE(bufS(1:NXP),bufR(1:NXP))
381 |
382 | bufS=Jy(:,2)
383 |
384 | IF (MOD(id,2).EQ.0) THEN
385 | CALL MPI_SENDRECV(bufS,NXP,MPI_DOUBLE_PRECISION,ngh(3),tag,&
386 | bufR,NXP,MPI_DOUBLE_PRECISION,ngh(1),tag,COMM,stat,ierr)
387 | ELSE
388 | CALL MPI_SENDRECV(bufS,NXP,MPI_DOUBLE_PRECISION,ngh(3),tag,&
389 | bufR,NXP,MPI_DOUBLE_PRECISION,ngh(1),tag,COMM,stat,ierr)
390 | ENDIF
391 |
392 | DO iy=1,NYP-1
393 | Jy(:,iy)=(Jy(:,iy+1)+Jy(:,iy))/2.0
394 | ENDDO
395 |
396 | !***********************************************************************
397 | ! Check boundary conditions along Y
398 |
399 | IF (ymaxp.EQ.ymax) THEN
400 |
401 | IF (BOUND_FIELD_YMAX.EQ."METAL") THEN
402 | bufR(:)=0.0
403 | ENDIF
404 |
405 | END IF
406 | !***********************************************************************
407 |
408 | Jy(:,NYP)=(bufR(:)+Jy(:,NYP))/2.0
409 |
410 | DEALLOCATE(bufS,bufR)
411 |
412 | !***********************************************************************
413 | Jz=Jz
414 |
415 | END SUBROUTINE JYEE
416 |
417 | !***********************************************************************
418 |
419 | END MODULE MOD_RHOJ
420 |
--------------------------------------------------------------------------------
/Zeltron2D/mod_sync.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_SYNC
21 |
22 | USE MOD_INPUT
23 |
24 | IMPLICIT NONE
25 |
26 | PRIVATE
27 | PUBLIC :: SYNC ! Synchrotron kernel with pitch angle alpha
28 | PUBLIC :: FSYNC ! Precalculated synchrotron kernel F(x)
29 | PUBLIC :: GSYNC ! Precalculated synchrotron kernel G(x)
30 | PUBLIC :: LOG_INTERPOL ! Interpol function in the log-log plane
31 |
32 | CONTAINS
33 |
34 | !***********************************************************************
35 | ! Subroutine SYNC
36 | ! Calculation of the synchrotron kernel for a pitch angle alpha
37 | !
38 | ! INPUT: photon energy e1 [in eV], magnetic field B [in Gauss],
39 | ! Lorentz factor of the electron gam, pitch angle alpha [rad]
40 | ! and the mass of the particles [g].
41 | !
42 | ! OUTPUT: Synchrotron kernel kern=dN/dtde1 [ph/s/erg]
43 | !***********************************************************************
44 |
45 | SUBROUTINE SYNC(mass,kern,e1,B,gam,alpha)
46 |
47 | IMPLICIT NONE
48 |
49 | !!! INPUT/OUTPUT PARAMETERS !!!
50 | DOUBLE PRECISION :: mass,e1,kern,B,gam,alpha
51 | DOUBLE PRECISION :: x1(100),x1intK53(100),x2
52 |
53 | !***********************************************************************
54 |
55 | ! Initialisation
56 | kern=0d0
57 |
58 | CALL FSYNC(x1,x1intK53)
59 |
60 | IF (B*sin(alpha).NE.0d0) THEN
61 |
62 | x2=e1*evtoerg*4d0*pi*mass*c/(3d0*h*e*B*gam*gam*sin(alpha))
63 |
64 | kern=LOG_INTERPOL(x1intK53,x1,x2,100)
65 |
66 | ! Asymptotic formulae for x<<1 et x>>1
67 | IF (x2.LT.1d-6.or.x2.GT.20d0) THEN
68 |
69 | IF (x2.LT.1d-6) THEN
70 | ! for x<<1
71 | kern=2.1495285*x2**(1d0/3d0)
72 | ELSE
73 | ! for x>>1
74 | kern=sqrt(pi/2d0)*exp(-x2)*sqrt(x2)
75 | ENDIF
76 |
77 | ENDIF
78 |
79 | kern=kern*sqrt(3d0)*e**(3d0)*B*sin(alpha)/(mass*c*c*h*e1*evtoerg)
80 |
81 | ELSE
82 | kern=0d0
83 | END IF
84 |
85 | END SUBROUTINE SYNC
86 |
87 | !***********************************************************************
88 | ! Subroutine FSYNC
89 | ! Precalculated synchrotron kernel F(x)=x*Int_{x}^{+\infty}K_{5/3}(t)dt
90 | !
91 | ! INPUT: x1,x1intK53
92 | !
93 | ! OUTPUT: x1,x1intK53
94 | !***********************************************************************
95 |
96 | SUBROUTINE FSYNC(x1,x1intK53)
97 |
98 | IMPLICIT NONE
99 |
100 | DOUBLE PRECISION :: x1(100),x1intK53(100)
101 |
102 | !***********************************************************************
103 |
104 | x1=[1.000000000000000E-006,1.185080297211958E-006,1.404415310839983E-006,&
105 | 1.664344913979274E-006,1.972382365321769E-006,2.337431479711146E-006,&
106 | 2.770043992688672E-006,3.282724558145690E-006,3.890292195032295E-006,&
107 | 4.610308630730232E-006,5.463585922344638E-006,6.474788028695254E-006,&
108 | 7.673143721430598E-006,9.093291441943042E-006,1.077628052465281E-005,&
109 | 1.277075772699502E-005,1.513437336272916E-005,1.793544768281981E-005,&
110 | 2.125494567058563E-005,2.518881733252163E-005,2.985077113084251E-005,&
111 | 3.537556072374498E-005,4.192288001653537E-005,4.968197910997698E-005,&
112 | 5.887713456972981E-005,6.977413213488398E-005,8.268794924811474E-005,&
113 | 9.799185947080311E-005,1.161282219460118E-004,1.376212677784760E-004,&
114 | 1.630922529216028E-004,1.932774155653010E-004,2.290492570824860E-004,&
115 | 2.714417616594907E-004,3.216802835831666E-004,3.812169660759664E-004,&
116 | 4.517727154595472E-004,5.353869439090540E-004,6.344765186111429E-004,&
117 | 7.519056212497024E-004,8.910685371059391E-004,1.055987766789732E-003,&
118 | 1.251430296519367E-003,1.483045387739222E-003,1.757527868880820E-003,&
119 | 2.082811649211582E-003,2.468299048284192E-003,2.925132569748623E-003,&
120 | 3.466516975142080E-003,4.108100967191674E-003,4.868429515176245E-003,&
121 | 5.769479896800527E-003,6.837296950858798E-003,8.102745902650151E-003,&
122 | 9.602404522545615E-003,1.137962040552782E-002,1.348576393234217E-002,&
123 | 1.598171312907039E-002,1.893961334495499E-002,2.244496261191877E-002,&
124 | 2.659908296304404E-002,3.152204914340976E-002,3.735615936760205E-002,&
125 | 4.427004844605502E-002,5.246356217003877E-002,6.217353384926757E-002,&
126 | 7.368062997280773E-002,8.731746286693928E-002,0.103478204846147,&
127 | 0.122629981754031,0.145326375224165,0.172223423943389,0.204098586433693,&
128 | 0.241873213471381,0.286639179708277,0.339690444281276,0.402560452668916,&
129 | 0.477066460894660,0.565362063266901,0.669999441968706,0.794003137820118,&
130 | 0.940957474555095,1.11511016360957,1.32149508411450,1.56607778704655,&
131 | 1.85592792933017,2.19942362209458,2.60649359976684,3.08890420989276,&
132 | 3.66059951911898,4.33810436609147,5.14100201150418,6.09250019176065,&
133 | 7.22010193801562,8.55640055060418,10.1400217075746,12.0167399389482,&
134 | 14.2408017383675,16.8764935566412,20.0000000000000]
135 |
136 | x1intK53=[2.149740291554781E-002,2.274901841108215E-002,2.407347673895755E-02,&
137 | 2.547501192814867E-002,2.695810311511616E-002,2.852748854769207E-002,&
138 | 3.018818035452749E-002,3.194548011543796E-002,3.380499526832988E-002,&
139 | 3.577265638843877E-002,3.785473537529143E-002,4.005786458201257E-002,&
140 | 4.238905692024220E-002,4.485572697186294E-002,4.746571313581508E-002,&
141 | 5.022730083430440E-002,5.314924679746723E-002,5.624080443877249E-002,&
142 | 5.951175032481285E-002,6.297241173226253E-002,6.663369527122917E-002,&
143 | 7.050711653745867E-002,7.460483073522131E-002,7.893966418747039E-002,&
144 | 8.352514661910548E-002,8.837554406184385E-002,9.350589218401047E-002,&
145 | 9.893202979401500E-002,0.104670632200595,0.110739244033946,&
146 | 0.117156311037122,0.123941210223590,0.131114277661013,0.138696832979062,&
147 | 0.146711199505309,0.155180718702228,0.164129757302985,0.173583705215995,&
148 | 0.183568961878227,0.194112908273776,0.205243861283644,0.216991006379192,&
149 | 0.229384303896832,0.242454363213354,0.256232278054607,0.270749414885549,&
150 | 0.286037144813124,0.302126507646095,0.319047794653951,0.336830034101253,&
151 | 0.355500360750710,0.375083247170932,0.395599570795967,0.417065486209677,&
152 | 0.439491067027217,0.462878676000437,0.487221015609695,0.512498804519786,&
153 | 0.538678018088907,0.565706624027361,0.593510737989999,0.621990119460058,&
154 | 0.651012927475406,0.680409661204000,0.709966226034660,0.739416097466217,&
155 | 0.768431610877948,0.796614496726025,0.823485923402867,0.848476524260903,&
156 | 0.870917196368038,0.890031895276086,0.904934240857714,0.914630512970876,&
157 | 0.918032544174628,0.913985044579456,0.901312851526806,0.878894144928416,&
158 | 0.845765223343403,0.801260109434639,0.745182884585394,0.678001036863573,&
159 | 0.601033606171899,0.516589597155386,0.427994417761062,0.339434248068025,&
160 | 0.255564108478843,0.180878805791705,0.118939475992646,&
161 | 7.165783884585139E-002,3.890601404389666E-002,1.866644749682380E-002,&
162 | 7.731985450943564E-003,2.689821816878248E-003,7.606072676721128E-004,&
163 | 1.681815907755760E-004,2.777448106239215E-005,3.244518011577780E-006,&
164 | 2.513722787179256E-007,1.196759294412181E-008]
165 |
166 | END SUBROUTINE FSYNC
167 |
168 | !***********************************************************************
169 | ! Subroutine GSYNC
170 | ! Precalculated synchrotron kernel G(x)=x*K_{2/3}(x)
171 | !
172 | ! INPUT: x1,x1K23
173 | !
174 | ! OUTPUT: x1,x1K23
175 | !***********************************************************************
176 |
177 | SUBROUTINE GSYNC(x1,x1K23)
178 |
179 | IMPLICIT NONE
180 |
181 | DOUBLE PRECISION :: x1(100),x1K23(100)
182 |
183 | !***********************************************************************
184 |
185 | x1=[1.000000000000000E-006,1.185080297211958E-006,1.404415310839983E-006,&
186 | 1.664344913979274E-006,1.972382365321769E-006,2.337431479711146E-006,&
187 | 2.770043992688672E-006,3.282724558145690E-006,3.890292195032295E-006,&
188 | 4.610308630730232E-006,5.463585922344638E-006,6.474788028695254E-006,&
189 | 7.673143721430598E-006,9.093291441943042E-006,1.077628052465281E-005,&
190 | 1.277075772699502E-005,1.513437336272916E-005,1.793544768281981E-005,&
191 | 2.125494567058563E-005,2.518881733252163E-005,2.985077113084251E-005,&
192 | 3.537556072374498E-005,4.192288001653537E-005,4.968197910997698E-005,&
193 | 5.887713456972981E-005,6.977413213488398E-005,8.268794924811474E-005,&
194 | 9.799185947080311E-005,1.161282219460118E-004,1.376212677784760E-004,&
195 | 1.630922529216028E-004,1.932774155653010E-004,2.290492570824860E-004,&
196 | 2.714417616594907E-004,3.216802835831666E-004,3.812169660759664E-004,&
197 | 4.517727154595472E-004,5.353869439090540E-004,6.344765186111429E-004,&
198 | 7.519056212497024E-004,8.910685371059391E-004,1.055987766789732E-003,&
199 | 1.251430296519367E-003,1.483045387739222E-003,1.757527868880820E-003,&
200 | 2.082811649211582E-003,2.468299048284192E-003,2.925132569748623E-003,&
201 | 3.466516975142080E-003,4.108100967191674E-003,4.868429515176245E-003,&
202 | 5.769479896800527E-003,6.837296950858798E-003,8.102745902650151E-003,&
203 | 9.602404522545615E-003,1.137962040552782E-002,1.348576393234217E-002,&
204 | 1.598171312907039E-002,1.893961334495499E-002,2.244496261191877E-002,&
205 | 2.659908296304404E-002,3.152204914340976E-002,3.735615936760205E-002,&
206 | 4.427004844605502E-002,5.246356217003877E-002,6.217353384926757E-002,&
207 | 7.368062997280773E-002,8.731746286693928E-002,0.103478204846147,&
208 | 0.122629981754031,0.145326375224165,0.172223423943389,0.204098586433693,&
209 | 0.241873213471381,0.286639179708277,0.339690444281276,0.402560452668916,&
210 | 0.477066460894660,0.565362063266901,0.669999441968706,0.794003137820118,&
211 | 0.940957474555095,1.11511016360957,1.32149508411450,1.56607778704655,&
212 | 1.85592792933017,2.19942362209458,2.60649359976684,3.08890420989276,&
213 | 3.66059951911898,4.33810436609147,5.14100201150418,6.09250019176065,&
214 | 7.22010193801562,8.55640055060418,10.1400217075746,12.0167399389482,&
215 | 14.2408017383675,16.8764935566412,20.0000000000000]
216 |
217 | x1K23=[1.0747643897745062E-02,1.1373545210783379E-02,1.2035896592231921E-02,&
218 | 1.2736820749913969E-02,1.3478564008782041E-02,1.4263503509513454E-02,&
219 | 1.5094154826196853E-02,1.5973180027474308E-02,1.6903396206909029E-02,&
220 | 1.7887784509830962E-02,1.8929499685476209E-02,2.0031880194881776E-02,&
221 | 2.1198458906729667E-02,2.2432974415152813E-02,2.3739383015421545E-02,&
222 | 2.5121871375423030E-02,2.6584869942922768E-02,2.8133067130752962E-02,&
223 | 2.9771424324296393E-02,3.1505191757913456E-02,3.3339925309272031E-02,&
224 | 3.5281504262853688E-02,3.7336150096185156E-02,3.9510446344517433E-02,&
225 | 4.1811359601670921E-02,4.4246261716466256E-02,4.6822953245424861E-02,&
226 | 4.9549688223044487E-02,5.2435200310667798E-02,5.5488730383404079E-02,&
227 | 5.8720055611260404E-02,6.2139520084949121E-02,6.5758067027916547E-02,&
228 | 6.9587272622869414E-02,7.3639381461965511E-02,7.7927343602935212E-02,&
229 | 8.2464853176107314E-02,8.7266388436226042E-02,9.2347253083557665E-02,&
230 | 9.7723618585195612E-02,1.0341256710191914E-01,1.0943213445827858E-01,&
231 | 1.1580135237047884E-01,1.2254028885076103E-01,1.2967008531576230E-01,&
232 | 1.3721298841045385E-01,1.4519237388080361E-01,1.5363275893842104E-01,&
233 | 1.6255979839644882E-01,1.7200025833790941E-01,1.8198195910426676E-01,&
234 | 1.9253367683570879E-01,2.0368498949697711E-01,2.1546604908839945E-01,&
235 | 2.2790725633507314E-01,2.4103880728814336E-01,2.5489007263888469E-01,&
236 | 2.6948875978360587E-01,2.8485979441901821E-01,3.0102384236008223E-01,&
237 | 3.1799537313269710E-01,3.3578014472089196E-01,3.5437196411308958E-01,&
238 | 3.7374855224180692E-01,3.9386631705642655E-01,4.1465381928802320E-01,&
239 | 4.3600370938982375E-01,4.5776293286262165E-01,4.7972106230544437E-01,&
240 | 5.0159674344171334E-01,5.2302247393686374E-01,5.4352831324898032E-01,&
241 | 5.6252570297275262E-01,5.7929341614688590E-01,5.9296879293422222E-01,&
242 | 6.0254885612078724E-01,6.0690753191603164E-01,6.0483674932169196E-01,&
243 | 5.9512008984440556E-01,5.7664695249016851E-01,5.4857149882323297E-01,&
244 | 5.1051228601562937E-01,4.6277410354308585E-01,4.0655319823184477E-01,&
245 | 3.4406425214049335E-01,2.7851101631629366E-01,2.1382723252770189E-01,&
246 | 1.5415740709436007E-01,1.0313621159571919E-01,6.3142610234701455E-02,&
247 | 3.4793456825950260E-02,1.6920308680868815E-02,7.0950242834264222E-03,&
248 | 2.4955701251498405E-03,7.1265991922884824E-04,1.5896437702472136E-04,&
249 | 2.6456199476679287E-05,3.1116648932472386E-06,2.4252957578827992E-07,&
250 | 1.1607696861888819E-08]
251 |
252 | END SUBROUTINE GSYNC
253 |
254 | !***********************************************************************
255 | ! Function LOG_INTERPOL: linear interpolation
256 | ! INPUT: fun (function to interpolate), xi (initial grid where fun is
257 | ! defined), and xf (final grid).
258 | ! OUTPUT: LOG_INTERPOL (fun calculated in the xf grid)
259 | !***********************************************************************
260 |
261 | FUNCTION LOG_INTERPOL(fun,xi,xf,n_xi)
262 |
263 | IMPLICIT NONE
264 |
265 | !!! INPUT/OUTPUT PARAMETERS !!!
266 | INTEGER :: n_xi
267 | DOUBLE PRECISION, DIMENSION(1:n_xi) :: fun,xi,mind
268 | DOUBLE PRECISION :: xf,log_interpol
269 |
270 | !!! Intermediate variables !!!
271 | DOUBLE PRECISION :: xp,diff,ly1,ly0,lh,lf1,lf0,lp
272 |
273 | !!! Loop indexes !!!
274 | INTEGER :: j
275 |
276 | !***********************************************************************
277 |
278 | IF (xf.LT.minval(xi).OR.xf.GT.maxval(xi)) THEN
279 | log_interpol=0.0
280 | ELSE
281 |
282 | mind=minloc(abs(xf-xi))
283 | j=mind(1)
284 |
285 | ly1=log10(xi(j+1))
286 | ly0=log10(xi(j))
287 | lh=ly1-ly0
288 | lf1=log10(fun(j+1))
289 | lf0=log10(fun(j))
290 | lp=(log10(xf)-ly0)/lh
291 |
292 | ! Linear interpolation in the log-log plane
293 | log_interpol=1d1**((1d0-lp)*lf0+lp*lf1)
294 |
295 | ENDIF
296 |
297 | END FUNCTION LOG_INTERPOL
298 |
299 | !***********************************************************************
300 |
301 | END MODULE MOD_SYNC
302 |
--------------------------------------------------------------------------------
/Zeltron2D/script_restore.sh:
--------------------------------------------------------------------------------
1 | # Remove all .mod and .o files
2 | rm *.mod *.o
3 |
4 | # Compile the code
5 | make IO=txt
6 |
7 | # Run the code
8 | mpirun -np 1 zeltron.exe
9 |
--------------------------------------------------------------------------------
/Zeltron2D/script_run.sh:
--------------------------------------------------------------------------------
1 | # Remove all .mod and .o files
2 | rm *.mod *.o
3 | rm zeltron.exe zeltron.out zeltron.err rankLog_*.txt
4 |
5 | # Remove all data
6 | rm -r ./data/*
7 | rm ./data_restore/*
8 |
9 | if [ ! -d data ]
10 | then
11 | mkdir data
12 | fi
13 |
14 | # Create folders where data will be dumped
15 | mkdir data/orbits
16 | mkdir data/fields
17 | mkdir data/densities
18 | mkdir data/currents
19 | mkdir data/particles
20 | mkdir data_restore
21 |
22 | # Just make the executable; don't run it.
23 | make IO=txt
24 |
25 | # Run the code
26 | mpirun -np 1 zeltron.exe
27 |
--------------------------------------------------------------------------------
/Zeltron3D/Makefile:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 |
20 | # ---------------------Macro-Defs-----------------------------
21 | ## Common options for F90 are: ftn, h5pfc, mpif90
22 | F90=mpif90
23 |
24 | ## for debugging, OPT=-g -fbacktrace -fbounds-check -O0
25 | ## for normal runs, OPT=-g -O3
26 | OPT=-g -O3
27 |
28 | ##-----------------I/O---------------
29 | ## IO should be "h5" for hdf5 output (hdf5 modules need to be loaded,
30 | ## or include and library files available), or "txt" for text output
31 | ## files, in which case no hdf5 capability need be present.
32 | IO?=h5
33 |
34 | ifeq ($(IO),h5)
35 | modio=mod_io_hdf5
36 | ## The following compiler/linker options should be set for each machine,
37 | # except for supercomputers where they are set through module loading
38 | # and the correct compiler command (e.g., ftn or h5pfc).
39 | LPATH=-L /scr_verus/wernerg/contrib2/hdf5-1.8.11-par/lib
40 | LIB=-lhdf5_fortran -lhdf5_f90cstub -lhdf5
41 | INCLUDE=-I /scr_verus/wernerg/contrib2/hdf5-1.8.11-par/include/fortran
42 | ## On supercomputers with hdf5 modules loaded
43 | # (or systems with h5pfc defined), uncomment the following 3 lines,
44 | # and comment the above 3 lines.
45 | #LPATH=
46 | #LIB=
47 | #INCLUDE=
48 | else
49 | modio=mod_io_txt
50 | LPATH=
51 | LIB=
52 | INCLUDE=
53 | endif
54 | # -------------------End-macro-Defs---------------------------
55 |
56 | all:main testExtcmd
57 |
58 | # Here is the link step
59 | main:mod_input.o mod_extcmd.o mod_initial.o mod_mpi.o mod_log.o mod_interp.o $(modio).o mod_fields.o mod_motion.o mod_rhoj.o mod_sync.o mod_track.o mod_analysis.o main.o
60 | $(F90) $(OPT) -o zeltron.exe $(LPATH) mod_input.o mod_extcmd.o mod_initial.o mod_mpi.o mod_log.o mod_interp.o $(modio).o mod_fields.o mod_motion.o mod_rhoj.o mod_sync.o mod_track.o mod_analysis.o main.o $(LIB)
61 |
62 | testExtcmd:extcmd.o mod_extcmd.o
63 | $(F90) $(OPT) mod_extcmd.o extcmd.o -o testExtcmd
64 |
65 | # Here are the compile steps
66 |
67 | mod_extcmd.o:mod_extcmd.f90
68 | $(F90) $(OPT) -c mod_extcmd.f90
69 |
70 | extcmd.o:extcmd.f90
71 | $(F90) $(OPT) -c extcmd.f90
72 |
73 | mod_input.o:mod_input.f90
74 | $(F90) $(OPT) -c mod_input.f90
75 |
76 | mod_initial.o:mod_initial.f90
77 | $(F90) $(OPT) -c mod_initial.f90
78 |
79 | mod_mpi.o:mod_mpi.f90
80 | $(F90) $(OPT) -c mod_mpi.f90
81 |
82 | mod_log.o:mod_log.f90
83 | $(F90) $(OPT) -c mod_log.f90
84 |
85 | mod_interp.o:mod_interp.f90
86 | $(F90) $(OPT) -c mod_interp.f90
87 |
88 | $(modio).o:$(modio).f90
89 | $(F90) $(OPT) $(INCLUDE) -c $(modio).f90
90 |
91 | mod_fields.o:mod_fields.f90
92 | $(F90) $(OPT) -c mod_fields.f90
93 |
94 | mod_motion.o:mod_motion.f90
95 | $(F90) $(OPT) -c mod_motion.f90
96 |
97 | mod_rhoj.o:mod_rhoj.f90
98 | $(F90) $(OPT) -c mod_rhoj.f90
99 |
100 | mod_sync.o:mod_sync.f90
101 | $(F90) $(OPT) -c mod_sync.f90
102 |
103 | mod_track.o:mod_track.f90
104 | $(F90) $(OPT) -c mod_track.f90
105 |
106 | mod_analysis.o:mod_analysis.f90
107 | $(F90) $(OPT) -c mod_analysis.f90
108 |
109 | main.o:main.f90 mod_input.o mod_initial.o mod_mpi.o mod_log.o mod_interp.o $(modio).o mod_fields.o mod_motion.o mod_rhoj.o mod_sync.o mod_track.o mod_analysis.o
110 | $(F90) $(OPT) -c main.f90
111 |
112 |
--------------------------------------------------------------------------------
/Zeltron3D/extcmd.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | PROGRAM EXTCMD
21 |
22 | USE MOD_EXTCMD
23 |
24 | IMPLICIT NONE
25 |
26 | INTEGER :: cmd, step
27 | !***********************************************************************!
28 |
29 | PRINT *, "Directions:"
30 | PRINT *, "1. Create a file simCmd.txt (in any directory but data/)"
31 | PRINT *, "2. simCmd.txt should contain one line; at the time of this writing"
32 | PRINT *, " it contains 4 numbers: timeStep quit dump save"
33 | PRINT *, " where quit, dump, and save are either 0 (don't do) or 1 (do)."
34 | PRINT *, "3. Run ./testExtcmd to verify that simCmd is what it should be."
35 | PRINT *, "4. Move or copy simCmd.txt to the data/ directory."
36 |
37 | PRINT *, " "
38 | PRINT *, "Executing the command to read simCmd.txt:"
39 |
40 | CALL READ_COMMAND("simCmd.txt", step, cmd)
41 | CALL PRINT_COMMAND(step, cmd)
42 |
43 | END PROGRAM EXTCMD
44 |
--------------------------------------------------------------------------------
/Zeltron3D/mod_extcmd.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_EXTCMD
21 |
22 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23 | !
24 | ! This module reads the contents of a (command) file. The file should
25 | ! have a single line (subsequent lines will be ignored) with 4 integers
26 | ! separated by a space:
27 | ! timeStep quit dump save
28 | ! where timeStep is an integer timeStep at which the command should be
29 | ! executed, and quit, dump, and save are either 0 or 1, depending
30 | ! on whether those actions should be performed at the time step.
31 | !
32 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
33 |
34 | IMPLICIT NONE
35 |
36 | PRIVATE
37 |
38 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_DO_NOTHING = 0
39 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_QUIT = 1
40 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_DUMP = 2
41 | INTEGER, PARAMETER, PUBLIC :: EXTCMD_SAVE = 4
42 |
43 | PUBLIC :: READ_COMMAND
44 | PUBLIC :: PRINT_COMMAND
45 |
46 | CONTAINS
47 |
48 | FUNCTION BoolToInt(b)
49 |
50 | IMPLICIT NONE
51 |
52 | LOGICAL :: b
53 | INTEGER :: BoolToInt
54 |
55 | IF (b) THEN
56 | BoolToInt = 1
57 | ELSE
58 | BoolToInt = 0
59 | ENDIF
60 |
61 | END FUNCTION
62 |
63 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
64 | ! Subroutine READ_COMMAND
65 | ! Reads a command file, and returns a timeStep and a command.
66 | !
67 | ! INPUT:
68 | ! - fileName the name of the command file
69 | ! OUTPUT:
70 | ! - timeStep: an integer time step
71 | ! - cmd: an integer command, the sum of the EXTCMD_* flags indicating
72 | ! the actions to be performed.
73 | !
74 | ! If the command file does not exist, or there are any errors reading
75 | ! the command file, this returns timeStep = -1
76 | ! and cmd = 0 = EXTCMD_DO_NOTHING.
77 | !
78 | ! Passing a command through a file is very klugey approach; we want
79 | ! this subroutine never to fail, never to result in a crash.
80 | ! By using the IOSTAT option for file operations, we try to avoid
81 | ! failure, and in such cases return innocuous EXTCMD_DO_NOTHING.
82 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83 |
84 | SUBROUTINE READ_COMMAND(fileName, timeStep, cmd)
85 |
86 | IMPLICIT NONE
87 |
88 | ! INPUT
89 | CHARACTER(len=*) :: fileName
90 | INTEGER, INTENT(OUT) :: timeStep, cmd
91 |
92 | ! LOCAL
93 | LOGICAL :: cmdFileExists, fail
94 | INTEGER :: step
95 | INTEGER :: doNothing, doQuit, doDump, doSave
96 | INTEGER :: ioStatus
97 | !***********************************************************************
98 |
99 | ! check for command file
100 | fail = .TRUE.
101 | INQUIRE(FILE=fileName, EXIST=cmdFileExists, IOSTAT = ioStatus)
102 | IF (ioStatus == 0) THEN
103 | IF (cmdFileExists) THEN
104 | OPEN(10, FILE = fileName, IOSTAT = ioStatus)
105 | IF (ioStatus == 0) THEN
106 | READ(10, *, IOSTAT = ioStatus) step, doQuit, doDump, doSave
107 | IF (ioStatus == 0) THEN
108 | timeStep = step
109 | cmd = EXTCMD_QUIT*BoolToInt(doQuit>0) + EXTCMD_DUMP*BoolToInt(doDump > 0) &
110 | + EXTCMD_SAVE*BoolToInt(doSave > 0)
111 | fail = .FALSE.
112 | ELSE
113 | PRINT *, "Error: IOSTAT=", ioStatus, " while reading command file ", fileName
114 | ENDIF
115 | CLOSE(10, IOSTAT = ioStatus)
116 | ELSE
117 | PRINT *, "Error: IOSTAT=", ioStatus, " while opening command file ", fileName
118 | ENDIF
119 | ENDIF
120 | ELSE
121 | PRINT *, "Error: IOSTAT=", ioStatus, " while inquiring about existence of file ", fileName
122 | ENDIF
123 |
124 | IF (fail) THEN
125 | timeStep = -1
126 | cmd = EXTCMD_DO_NOTHING
127 | ENDIF
128 |
129 | END SUBROUTINE READ_COMMAND
130 |
131 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
132 | ! Subroutine PRINT_COMMAND
133 | ! Prints the interpretation of a command from a command file
134 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
135 |
136 | SUBROUTINE PRINT_COMMAND(timeStep, cmd)
137 |
138 | IMPLICIT NONE
139 |
140 | INTEGER :: timeStep, cmd
141 | !***********************************************************************
142 |
143 | PRINT *, "At timestep", timeStep, ":"
144 | IF (cmd == 0) THEN
145 | PRINT *, " do nothing"
146 | ELSE
147 | IF (IAND(cmd, EXTCMD_QUIT) /= 0) PRINT *, " quit"
148 | IF (IAND(cmd, EXTCMD_DUMP) /= 0) PRINT *, " dump"
149 | IF (IAND(cmd, EXTCMD_SAVE) /= 0) PRINT *, " save"
150 | ENDIF
151 |
152 | END SUBROUTINE PRINT_COMMAND
153 |
154 | !***********************************************************************
155 |
156 | END MODULE MOD_EXTCMD
157 |
--------------------------------------------------------------------------------
/Zeltron3D/mod_input.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_INPUT
21 |
22 | IMPLICIT NONE
23 |
24 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25 | !+++++++++++++++++++++++++++++ CONSTANTS +++++++++++++++++++++++++++++
26 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27 |
28 | ! Speed of light [cm/s]
29 | DOUBLE PRECISION, PARAMETER, PUBLIC :: c=299792458d2
30 | ! Fundamental charge [esu]
31 | DOUBLE PRECISION, PARAMETER, PUBLIC :: e=4.8032068d-10
32 | ! Boltzmann constant [erg/K]
33 | DOUBLE PRECISION, PARAMETER, PUBLIC :: k=1.380658d-16
34 | ! Planck constant [erg.s]
35 | DOUBLE PRECISION, PARAMETER, PUBLIC :: h=6.6260755d-27
36 | ! Mass of the electron [g]
37 | DOUBLE PRECISION, PARAMETER, PUBLIC :: me=9.1093897d-28
38 | ! Mass of the proton [g]
39 | DOUBLE PRECISION, PARAMETER, PUBLIC :: mp=1.6726231d-24
40 | ! 1 eV in erg [erg]
41 | DOUBLE PRECISION, PARAMETER, PUBLIC :: evtoerg=1.602177d-12
42 | ! pi
43 | DOUBLE PRECISION, PARAMETER, PUBLIC :: pi=dacos(-1d0)
44 |
45 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
46 | !+++++++++++++++++++++++++ DIMENSION ++++++++++++++++++++++++++++++
47 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48 |
49 | ! spatial dimension
50 | INTEGER, PARAMETER, PUBLIC :: NDIM=3
51 |
52 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
53 | !+++++++++++++++++++++++++ SAVE/RESTORE ++++++++++++++++++++++++++++++
54 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
55 |
56 | ! Save particle and field data for future restoration of the simulation
57 | LOGICAL, PARAMETER, PUBLIC :: CHECKPOINT=.FALSE.
58 |
59 | ! Restore a simulation where it stopped
60 | LOGICAL, PARAMETER, PUBLIC :: RESTORE=.FALSE.
61 |
62 | ! Saving frequency, in seconds (the simulation will try to save its
63 | ! current state *before* elapsed time n*FSAVE, for integer n).
64 | ! N.B. It is highly recommended to have more than 1 checkpoint during
65 | ! the simulation, unless it is certain that the simulation will end
66 | ! naturally (as opposed to being killed before it is finished).
67 | DOUBLE PRECISION, PARAMETER, PUBLIC :: FSAVE=0.
68 |
69 | ! Give the time step from which the simulation should restart
70 | INTEGER, PARAMETER, PUBLIC :: time_ref=0
71 |
72 | ! Whether to test restore capability: this restores data from step
73 | ! time_ref, and then immediately write data (as if dumping
74 | ! for a checkpoint) under the next time step; the simulation then halts.
75 | LOGICAL, PARAMETER, PUBLIC :: TEST_RESTORE = .FALSE.
76 |
77 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
78 | !++++++++++++++++++++++ BOUNDARY CONDITIONS ++++++++++++++++++++++++++
79 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
80 |
81 | ! Specify the boundary conditions for the fields:
82 | ! 1. "PERIODIC": Periodic boundary conditions
83 | ! 2. "METAL": Perfect metal with infinite conductivity
84 |
85 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_XMIN="PERIODIC"
86 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_XMAX="PERIODIC"
87 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_YMIN="PERIODIC"
88 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_YMAX="PERIODIC"
89 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_ZMIN="PERIODIC"
90 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_FIELD_ZMAX="PERIODIC"
91 |
92 | ! Specify the boundary conditions for the particles:
93 | ! 1. "PERIODIC": Periodic boundary conditions
94 | ! 2. "REFLECT": Particles are elastically reflected at the wall
95 | ! 3. "ABSORB": Particles are absorbed at the wall
96 |
97 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_XMIN="PERIODIC"
98 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_XMAX="PERIODIC"
99 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_YMIN="PERIODIC"
100 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_YMAX="PERIODIC"
101 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_ZMIN="PERIODIC"
102 | CHARACTER(LEN=10), PARAMETER, PUBLIC :: BOUND_PART_ZMAX="PERIODIC"
103 |
104 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
105 | !+++++++++++++++++++++++++ INPUT PARAMETERS ++++++++++++++++++++++++++
106 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
107 |
108 | ! Number of cells in X
109 | INTEGER*8, PARAMETER, PUBLIC :: NCX=32
110 |
111 | ! Number of cells in Y
112 | INTEGER*8, PARAMETER, PUBLIC :: NCY=32
113 |
114 | ! Number of cells in Z
115 | INTEGER*8, PARAMETER, PUBLIC :: NCZ=16
116 |
117 | ! Number of particles per cell per species
118 | INTEGER*8, PARAMETER, PUBLIC :: PPC=1
119 |
120 | ! Number of process (domain decomposition in the X- Y- and Z-directions)
121 | INTEGER, PARAMETER, PUBLIC :: NPX=1
122 | INTEGER, PARAMETER, PUBLIC :: NPY=1
123 | INTEGER, PARAMETER, PUBLIC :: NPZ=1
124 |
125 | ! Mass ratio IONS/ELECTRONS
126 | DOUBLE PRECISION, PARAMETER, PUBLIC :: mass_ratio=1d0
127 |
128 | ! Spatial boundaries in the X-direction
129 | DOUBLE PRECISION, PARAMETER, PUBLIC :: xmin=0d0,xmax=32d0
130 |
131 | ! Spatial boundaries in the Y-direction
132 | DOUBLE PRECISION, PARAMETER, PUBLIC :: ymin=0d0,ymax=32d0
133 |
134 | ! Spatial boundaries in the Z-direction
135 | DOUBLE PRECISION, PARAMETER, PUBLIC :: zmin=0d0,zmax=16d0
136 |
137 | ! Dump data frequency in terms of timesteps
138 | INTEGER, PARAMETER, PUBLIC :: FDUMP=200
139 |
140 | ! Number of data dumps
141 | INTEGER, PARAMETER, PUBLIC :: NDUMP=5
142 |
143 | ! Number of time steps
144 | INTEGER, PARAMETER, PUBLIC :: NT=FDUMP*NDUMP
145 |
146 | ! Poisson solver calling frequency in terms of timesteps
147 | INTEGER, PARAMETER, PUBLIC :: FREQ_POISSON=25
148 |
149 | ! Number of iterations to solve Poisson's equation
150 | INTEGER, PARAMETER, PUBLIC :: NIT=500
151 |
152 | ! Switch ON/OFF the radiation reaction force (synchrotron radiation and
153 | ! inverse Compton scattering in the Thomson regime only)
154 | LOGICAL, PARAMETER, PUBLIC :: RAD_FORCE=.FALSE.
155 |
156 | ! Switch ON/OFF spatial filtering the electric field
157 | LOGICAL, PARAMETER, PUBLIC :: FILTER=.FALSE.
158 |
159 | ! Smoothing parameter
160 | DOUBLE PRECISION, PARAMETER, PUBLIC :: alpha=1d0/64d0
161 |
162 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
163 |
164 | ! Number of grid cells in X
165 | INTEGER, PARAMETER, PUBLIC :: NX=NCX+1
166 |
167 | ! Number of grid cells in Y
168 | INTEGER, PARAMETER, PUBLIC :: NY=NCY+1
169 |
170 | ! Number of grid cells in Z
171 | INTEGER, PARAMETER, PUBLIC :: NZ=NCZ+1
172 |
173 | ! Number of cell per process in the X-direction
174 | INTEGER, PARAMETER, PUBLIC :: NCXP=NCX/NPX
175 |
176 | ! Number of cell per process in the Y-direction
177 | INTEGER, PARAMETER, PUBLIC :: NCYP=NCY/NPY
178 |
179 | ! Number of cell per process in the Z-direction
180 | INTEGER, PARAMETER, PUBLIC :: NCZP=NCZ/NPZ
181 |
182 | ! Number of grid cells per process in X
183 | INTEGER, PARAMETER, PUBLIC :: NXP=NCXP+1
184 |
185 | ! Number of grid cells per process in Y
186 | INTEGER, PARAMETER, PUBLIC :: NYP=NCYP+1
187 |
188 | ! Number of grid cells per process in Z
189 | INTEGER, PARAMETER, PUBLIC :: NZP=NCZP+1
190 |
191 | ! Total number of particles per species NP=NCX*NCY*NCZ*PPC
192 | INTEGER*8, PARAMETER, PUBLIC :: NP=NCX*NCY*NCZ*PPC
193 |
194 | ! Spatial step
195 | DOUBLE PRECISION, PARAMETER, PUBLIC :: dx=(xmax-xmin)/NCX
196 | DOUBLE PRECISION, PARAMETER, PUBLIC :: dy=(ymax-ymin)/NCY
197 | DOUBLE PRECISION, PARAMETER, PUBLIC :: dz=(zmax-zmin)/NCZ
198 |
199 | ! Time step (Courant-Friedrichs-Lewy timestep)
200 | DOUBLE PRECISION, PARAMETER, PUBLIC :: dt=0.99*1d0/sqrt(1d0/dx**2d0+&
201 | 1d0/dy**2d0+1d0/dz**2d0)/c
202 |
203 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
204 |
205 | ! Initial (tearing-mode) perturbation amplitude
206 | DOUBLE PRECISION, PARAMETER, PUBLIC :: perturb_amp=0.0
207 |
208 | ! Ratio of Bz/B0 (Guide field / reconnecting field)
209 | DOUBLE PRECISION, PARAMETER, PUBLIC :: guide_field=0.0
210 |
211 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
212 |
213 | ! Temperature in unit of me*c^2/k of the DRIFTING ELECTRONS in the co-moving frame
214 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thde=1d0
215 |
216 | ! Temperature in unit of mi*c^2/k of the DRIFTING IONS in the co-moving frame
217 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thdi=1d0
218 |
219 | ! Temperature in unit of me*c^2/k of the BACKGROUND ELECTRONS in the lab frame
220 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thbe=1d0
221 |
222 | ! Temperature in unit of mi*c^2/k of the BACKGROUND IONS in the lab frame
223 | DOUBLE PRECISION, PARAMETER, PUBLIC :: thbi=1d0
224 |
225 | ! Minimum Larmor radius of the electrons
226 | DOUBLE PRECISION, PARAMETER, PUBLIC :: rhoc=2d0
227 |
228 | ! Drift velocity betad=vdrift/c
229 | DOUBLE PRECISION, PARAMETER, PUBLIC :: betad=0.6d0
230 |
231 | ! Density ratio between initial DRIFTING and BACKGROUND particles
232 | DOUBLE PRECISION, PARAMETER, PUBLIC :: density_ratio=0.1d0
233 |
234 | ! Energy density ratio between external radiation field and the magnetic field
235 | ! udens_ratio=Uph/Ub, where Ub=B0^2/8*pi
236 | DOUBLE PRECISION, PARAMETER, PUBLIC :: udens_ratio=0d0
237 |
238 | ! 4-velocity boundaries for the particles
239 | DOUBLE PRECISION, PARAMETER, PUBLIC :: umin=1d-2,umax=1d2
240 |
241 | ! 4-velocity boundaries for the drifting electrons
242 | DOUBLE PRECISION, PARAMETER, PUBLIC :: udemin=-1d2,udemax=1d2
243 | ! 4-velocity boundaries for the drifting ions
244 | DOUBLE PRECISION, PARAMETER, PUBLIC :: udpmin=-1d2,udpmax=1d2
245 |
246 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
247 | !++++++++++++++++++++++ DEFINE PARTICLE ARRAYS +++++++++++++++++++++++
248 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
249 | !
250 | ! pcl_species(1,:)=x : x position of the particle
251 | ! pcl_species(2,:)=y : y position of the particle
252 | ! pcl_species(3,:)=z : z position of the particle
253 | ! pcl_species(4,:)=ux : x-component of the reduced particle 4-velocity
254 | ! pcl_species(5,:)=uy : y-component of the reduced particle 4-velocity
255 | ! pcl_species(6,:)=uz : z-component of the reduced particle 4-velocity
256 | ! pcl_species(7,:)=weight : weight of the particle
257 | !
258 | ! Defition of the particle distribution data function: it gives extra
259 | ! information regarding the particles, e.g., electric/magnetic field/force
260 | ! at the location of the particle.
261 | !
262 | ! pcl_data_species(1,:)=Ell : Electric field parallel to the particle velocity
263 | ! pcl_data_species(2,:)=Bpp : Magnetic field perp. to the particle velocity
264 | ! pcl_data_species(3,:)=Fr : Synchrotron radiation reaction force
265 | ! pcl_data_species(4,:)=Fe : Electric force
266 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
267 |
268 | ! DRIFTING ELECTRONS distribution function components
269 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_ed(:,:)
270 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_ed(:,:)
271 | INTEGER*8, ALLOCATABLE, PUBLIC :: taged(:)
272 |
273 | ! DRIFTING IONS distribution function components
274 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_pd(:,:)
275 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_pd(:,:)
276 | INTEGER*8, ALLOCATABLE, PUBLIC :: tagpd(:)
277 |
278 | ! BACKGROUND ELECTRONS distribution function components
279 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_eb(:,:)
280 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_eb(:,:)
281 | INTEGER*8, ALLOCATABLE, PUBLIC :: tageb(:)
282 |
283 | ! BACKGROUND IONS distribution function components
284 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_pb(:,:)
285 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_pb(:,:)
286 | INTEGER*8, ALLOCATABLE, PUBLIC :: tagpb(:)
287 |
288 | ! Temporary particle distribution function
289 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_f(:,:)
290 | DOUBLE PRECISION, ALLOCATABLE, PUBLIC :: pcl_data_f(:,:)
291 | INTEGER*8, ALLOCATABLE, PUBLIC :: tagf(:)
292 |
293 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
294 | !+++++++++++++++++++++++++++++ ANALYSIS ++++++++++++++++++++++++++++++
295 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
296 |
297 | ! Data formatting (for data in text files) for integers and doubles
298 | CHARACTER(LEN=6), PARAMETER, PUBLIC :: FMT_INT="I26"
299 | CHARACTER(LEN=11), PARAMETER, PUBLIC :: FMT_DBL="E26.16E3"
300 |
301 | ! For text output of fields/density/pressure/current: (irrelevant for hdf5 output)
302 | ! If .TRUE., each MPI process will write to a separate file.
303 | ! This can be faster (for large simulations), but may create too many files.
304 | LOGICAL, PARAMETER, PUBLIC :: DUMP_FIELDS_PARALLEL=.FALSE.
305 |
306 | ! Switch ON/OFF write fields to disk
307 | LOGICAL, PARAMETER, PUBLIC :: WRITE_FIELDS=.TRUE.
308 |
309 | ! Switch ON/OFF write the charge and current densities to disk
310 | LOGICAL, PARAMETER, PUBLIC :: WRITE_RHOJ=.TRUE.
311 |
312 | ! For text output of particle data: (irrelevant for hdf5 output)
313 | ! If .TRUE., each MPI process will write to its own file.
314 | ! This can be faster (for large simulations), but may create too many files.
315 | LOGICAL, PARAMETER, PUBLIC :: DUMP_PARTICLES_PARALLEL=.FALSE.
316 |
317 | ! Switch ON/OFF write raw particle data to disk
318 | LOGICAL, PARAMETER, PUBLIC :: WRITE_PARTICLES=.FALSE.
319 |
320 | ! Switch ON/OFF particle tracker
321 | LOGICAL, PARAMETER, PUBLIC :: TRACK_PARTICLES=.FALSE.
322 |
323 | ! Switch ON/OFF analysis of particle energy and angular distributions
324 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_DISTRIBUTIONS=.TRUE.
325 |
326 | ! Switch ON/OFF analysis the plasma density
327 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_DENSITIES=.TRUE.
328 |
329 | ! Switch ON/OFF analysis the relativistic macroscopic fluid quantities
330 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_FLUID=.FALSE.
331 |
332 | ! Switch ON/OFF analysis the radiation spectra and anisotropies
333 | LOGICAL, PARAMETER, PUBLIC :: ANALYZE_RADIATION=.FALSE.
334 |
335 | ! Total number of tracked particles
336 | INTEGER, PARAMETER, PUBLIC :: NSAMPLE=100
337 |
338 | ! Give the time step from which the tracker should restart
339 | INTEGER, PARAMETER, PUBLIC :: time_track=1
340 |
341 | ! The tracking frequency (timesteps between recording of tracking data)
342 | ! E.g., 1 = record every step; 2 = record every other step; ....
343 | INTEGER, PARAMETER, PUBLIC :: FTRACK=1
344 |
345 | ! Particle's Lorentz factor grid for the spectrum
346 | INTEGER, PARAMETER, PUBLIC :: NU=100
347 |
348 | ! Spatial grid size for dumping EM-related fields (E,B,J)
349 | ! Spatial grid size for dumping EM-related fields
350 | ! If NFIELDX = NCX, etc., Zeltron dumps exactly the (nodal) field it uses.
351 | INTEGER, PARAMETER, PUBLIC :: NFIELDX=NCX,NFIELDY=NCY,NFIELDZ=NCZ
352 |
353 | ! Spatial grid size for dumping particle-related fields (densities, etc.)
354 | INTEGER, PARAMETER, PUBLIC :: NDX=NCX,NDY=NCY,NDZ=NCZ
355 |
356 | ! Angular distribution grid
357 | INTEGER, PARAMETER, PUBLIC :: NPHI=50,NLBA=90
358 |
359 | ! Synchrotron radiation frequency
360 | INTEGER, PARAMETER, PUBLIC :: NNU=100
361 |
362 | ! Frequency boundaries for the synchrotron radiation
363 | DOUBLE PRECISION, PARAMETER, PUBLIC :: nmin=1d9,nmax=1d14
364 |
365 | ! Latitude boundaries for the angular distribution (phi)
366 | DOUBLE PRECISION, PARAMETER, PUBLIC :: pmin=-89.99d0,pmax=89.99d0
367 |
368 | ! Longitude boundaries for the angular distribution (lambda)
369 | DOUBLE PRECISION, PARAMETER, PUBLIC :: lmin=-179.99d0,lmax=179.99d0
370 |
371 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
372 | !+++++++++++++++++++++++++ TUNING ++++++++++++++++++++++++++++++++++++
373 | ! You might want to adjust these parameters, but they should mostly
374 | ! be left as they are.
375 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
376 |
377 | ! (Inverse) frequency, in steps, with which all ranks communicate
378 | ! general info, such as whether to checkpoint, or the contents of the
379 | ! command file.
380 | INTEGER, PARAMETER, PUBLIC :: FGENCOMM=20
381 |
382 | ! Fraction of FSAVE by which a checkpoint time can be shifted (earlier)
383 | ! so that it occurs as the same time as a dump.
384 | DOUBLE PRECISION, PARAMETER, PUBLIC :: FSAVE_SHIFT_FRAC=0.25
385 |
386 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
387 | !+++++++++++++++++++++++++++++ DEBUGGING +++++++++++++++++++++++++++++
388 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
389 |
390 | ! For normal runs, RANDOMIZE = true ensures a different seed each run
391 | ! For testing new code, can set to false for reproducibility
392 | LOGICAL, PARAMETER, PUBLIC :: RANDOMIZE=.TRUE.
393 |
394 | ! whether to write one diagnostic file per rank
395 | LOGICAL, PARAMETER, PUBLIC :: writePerRankFiles=.FALSE.
396 |
397 | ! the name of the per-rank file
398 | CHARACTER(len=18), PUBLIC :: perRankFile
399 |
400 | !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
401 |
402 | END MODULE MOD_INPUT
403 |
--------------------------------------------------------------------------------
/Zeltron3D/mod_interp.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_INTERP
21 |
22 | USE MOD_INPUT
23 | USE MOD_MPI
24 |
25 | IMPLICIT NONE
26 |
27 | PRIVATE
28 |
29 | PUBLIC :: TRILINEAR_FIELD ! Bilinear interpolation of a field value
30 | PUBLIC :: TRILINEAR_FIELDS ! Bilinear interpolation of fields
31 |
32 | CONTAINS
33 |
34 | !***********************************************************************
35 | ! Function TRILINEAR_FIELD: bilinear interpolation of the E and B fields
36 | ! INPUT: F (2D field to interpolate),
37 | ! (i,j,k) lower corner of cell within which to inteprolate
38 | ! xq, yq, zq : weights within the cell for interpolation
39 | ! (xq = 0 means use F at i, xq = 1 means use F at i+1)
40 | ! (yq = 0 means use F at j, yq = 1 means use F at j+1)
41 | ! (zq = 0 means use F at k, zq = 1 means use F at k+1)
42 | ! OUTPUT: interpolated value
43 | !***********************************************************************
44 |
45 | FUNCTION TRILINEAR_FIELD(F, i, j, k, xq, yq, zq)
46 |
47 | IMPLICIT NONE
48 |
49 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP,1:NZP) :: F
50 | INTEGER :: i,j,k
51 | DOUBLE PRECISION :: xq,yq,zq
52 | INTEGER :: ip,jp,kp
53 |
54 | DOUBLE PRECISION :: f000,f001,f010,f011
55 | DOUBLE PRECISION :: f100,f101,f110,f111
56 | DOUBLE PRECISION :: TRILINEAR_FIELD
57 | !***********************************************************************
58 |
59 | ! Don't examine i+1 if it has zero weight, in case i+1 is past the array
60 | ip = i
61 | jp = j
62 | kp = k
63 | IF (xq > 0.) ip = ip + 1
64 | IF (yq > 0.) jp = jp + 1
65 | IF (zq > 0.) kp = kp + 1
66 | f000=F(i,j,k)
67 | f100=F(ip,j,k)
68 | f010=F(i,jp,k)
69 | f110=F(ip,jp,k)
70 | f001=F(i,j,kp)
71 | f101=F(ip,j,kp)
72 | f011=F(i,jp,kp)
73 | f111=F(ip,jp,kp)
74 |
75 | TRILINEAR_FIELD = (1.-xq) &
76 | * ((1.-yq)*(1.-zq)*f000 + yq*(1.-zq)*f010 + yq*zq*f011 + (1.-yq)*zq*f001) &
77 | + xq &
78 | * ((1.-yq)*(1.-zq)*f100 + yq*(1.-zq)*f110 + yq*zq*f111 + (1.-yq)*zq*f101)
79 |
80 | END FUNCTION
81 |
82 | !***********************************************************************
83 | ! Function TRILINEAR_FIELDS: bilinear interpolation of the E and B fields
84 | ! INPUT: Bx,By,Bz,Ex,Ey,Ez (2D functions to interpolate),
85 | ! (xi,yi) (initial grid where fun2d is defined), and (xf,yf) (final grid).
86 | ! OUTPUT: bilinear_fields: fun2d calculated in the (xf,yf) grid.
87 | !***********************************************************************
88 |
89 | SUBROUTINE TRILINEAR_FIELDS(xi,yi,zi,xf,yf,zf, Finterp, F1,F2,F3,F4,F5,F6)
90 |
91 | IMPLICIT NONE
92 |
93 | ! INPUT
94 | DOUBLE PRECISION, DIMENSION(1:NXP) :: xi
95 | DOUBLE PRECISION, DIMENSION(1:NYP) :: yi
96 | DOUBLE PRECISION, DIMENSION(1:NZP) :: zi
97 | DOUBLE PRECISION :: xf,yf,zf
98 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP,1:NZP) :: F1
99 | DOUBLE PRECISION, DIMENSION(1:NXP,1:NYP,1:NZP), OPTIONAL :: F2,F3,F4,F5,F6
100 | ! OUTPUT
101 | DOUBLE PRECISION, DIMENSION(:), INTENT(OUT) :: Finterp
102 |
103 | ! indices
104 | INTEGER :: i,j,k
105 | ! weights
106 | DOUBLE PRECISION :: xq,yq,zq
107 | !***********************************************************************
108 |
109 | ! Computation of the nearest node index to (xf,yf), for a constant dx,dy
110 | i=FLOOR((xf-xi(1))/dx)+1
111 | j=FLOOR((yf-yi(1))/dy)+1
112 | k=FLOOR((zf-zi(1))/dz)+1
113 |
114 | IF (i.EQ.NXP) THEN
115 | i=i-1
116 | END IF
117 |
118 | IF (j.EQ.NYP) THEN
119 | j=j-1
120 | END IF
121 |
122 | IF (k.EQ.NZP) THEN
123 | k=k-1
124 | END IF
125 |
126 | xq=(xf-xi(i))/dx
127 | yq=(yf-yi(j))/dy
128 | zq=(zf-zi(k))/dz
129 |
130 | Finterp(1) = TRILINEAR_FIELD(F1, i, j, k, xq, yq, zq)
131 | IF (PRESENT(F2)) Finterp(2) = TRILINEAR_FIELD(F2, i, j, k, xq, yq, zq)
132 | IF (PRESENT(F3)) Finterp(3) = TRILINEAR_FIELD(F3, i, j, k, xq, yq, zq)
133 | IF (PRESENT(F4)) Finterp(4) = TRILINEAR_FIELD(F4, i, j, k, xq, yq, zq)
134 | IF (PRESENT(F5)) Finterp(5) = TRILINEAR_FIELD(F5, i, j, k, xq, yq, zq)
135 | IF (PRESENT(F6)) Finterp(6) = TRILINEAR_FIELD(F6, i, j, k, xq, yq, zq)
136 |
137 | END SUBROUTINE TRILINEAR_FIELDS
138 |
139 | !***********************************************************************
140 |
141 | END MODULE MOD_INTERP
142 |
--------------------------------------------------------------------------------
/Zeltron3D/mod_log.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_LOG
21 |
22 | IMPLICIT NONE
23 |
24 | PRIVATE
25 |
26 | INTEGER, PARAMETER :: maxFileNameLen = 256
27 |
28 | TYPE DataLogObj
29 | DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: logEntries
30 | CHARACTER(len=maxFileNameLen) :: fileName
31 | INTEGER :: numEntries
32 | DOUBLE PRECISION :: waitTime
33 | DOUBLE PRECISION :: lastWriteTime
34 | ENDTYPE DataLogObj
35 |
36 | PUBLIC :: DataLogObj
37 |
38 | PUBLIC :: START_LOG
39 | PUBLIC :: END_LOG
40 | PUBLIC :: WRITE_LOG_TO_DISK
41 | PUBLIC :: ADD_LOG_DATA
42 |
43 |
44 | CONTAINS
45 |
46 | !***********************************************************************
47 | ! Subroutine START_LOG
48 | ! Allocate data log array
49 | !
50 | ! IN/OUT:
51 | ! - dataLog: the log
52 | ! - numColumns: the number of columns per entry
53 | ! - entriesPerDump: the maximum number of entries to store before writing to disk
54 | ! - timeBetweenDumps: the desired time between dumps, in seconds
55 | !
56 | !***********************************************************************
57 |
58 | SUBROUTINE START_LOG(dataLog, fileName, numColumns, entriesPerDump, &
59 | timeBetweenDumps)
60 |
61 | IMPLICIT NONE
62 |
63 | INCLUDE 'mpif.h'
64 |
65 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
66 | CHARACTER(len=*) :: fileName
67 | INTEGER :: numColumns, entriesPerDump
68 | DOUBLE PRECISION :: timeBetweenDumps
69 | !***********************************************************************
70 |
71 | ALLOCATE(dataLog%logEntries(numColumns, entriesPerDump))
72 | dataLog%numEntries = 0
73 | dataLog%fileName = " "
74 | dataLog%fileName(1:LEN(fileName)) = fileName
75 | dataLog%waitTime = timeBetweenDumps
76 | dataLog%lastWriteTime = MPI_WTIME()
77 |
78 | END SUBROUTINE START_LOG
79 |
80 | !***********************************************************************
81 | ! Subroutine END_LOG
82 | ! Finish writing log, never to add any more data
83 | !
84 | ! IN/OUT:
85 | ! - dataLog: the log
86 | !
87 | !***********************************************************************
88 |
89 | SUBROUTINE END_LOG(dataLog)
90 |
91 | IMPLICIT NONE
92 |
93 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
94 | !***********************************************************************
95 |
96 | CALL WRITE_LOG_TO_DISK(dataLog)
97 | DEALLOCATE(dataLog%logEntries)
98 |
99 | END SUBROUTINE END_LOG
100 |
101 | !***********************************************************************
102 | ! Subroutine WRITE_LOG_TO_DISK
103 | ! Write all log data to disk.
104 | !
105 | ! IN/OUT:
106 | ! - dataLog: the log
107 | !
108 | !***********************************************************************
109 |
110 | SUBROUTINE WRITE_LOG_TO_DISK(dataLog)
111 |
112 | IMPLICIT NONE
113 |
114 | INCLUDE 'mpif.h'
115 |
116 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
117 | ! LOCAL
118 | CHARACTER(len=280) :: fName
119 | INTEGER :: i,j, numColumns
120 | !***********************************************************************
121 |
122 | ! Open the file only if there's some data to be written
123 | IF (dataLog%numEntries > 0) THEN
124 | fname = trim(adjustl(dataLog%fileName))
125 | OPEN(9,FILE=fname,POSITION='APPEND')
126 | numColumns = SIZE(dataLog%logEntries, DIM = 1)
127 | DO j=1,dataLog%numEntries
128 | WRITE(9,*) (dataLog%logEntries(i,j), i=1, numColumns)
129 | ENDDO
130 | CLOSE(9)
131 | dataLog%numEntries = 0
132 | dataLog%lastWriteTime = MPI_WTIME()
133 | ENDIF
134 |
135 | END SUBROUTINE WRITE_LOG_TO_DISK
136 |
137 | !***********************************************************************
138 | ! Subroutine ADD_LOG_DATA
139 | ! Add a line of data to the log.
140 | !
141 | ! INPUT:
142 | ! - newLine: a new line of data to be logged
143 | ! IN/OUT:
144 | ! - dataLog: the to which data should be added
145 | !
146 | !***********************************************************************
147 |
148 | SUBROUTINE ADD_LOG_DATA(dataLog, newLine)
149 |
150 | IMPLICIT NONE
151 |
152 | INCLUDE 'mpif.h'
153 |
154 | TYPE(DataLogObj), INTENT(INOUT) :: dataLog
155 | DOUBLE PRECISION, DIMENSION(:) :: newLine
156 |
157 | !***********************************************************************
158 |
159 | dataLog%numEntries = dataLog%numEntries + 1
160 | dataLog%logEntries(:, dataLog%numEntries) = newLine
161 | IF ((dataLog%numEntries == SIZE(dataLog%logEntries, DIM = 2)) &
162 | .OR. (MPI_WTIME() - dataLog%lastWriteTime >= dataLog%waitTime)) THEN
163 | !print *, "Logger", dataLog%fileName, dataLog%numEntries, SIZE(dataLog%logEntries, DIM=2)
164 | !print *, " ", MPI_WTIME() - dataLog%lastWriteTime, dataLog%waitTime
165 | CALL WRITE_LOG_TO_DISK(dataLog)
166 | ENDIF
167 |
168 | END SUBROUTINE ADD_LOG_DATA
169 |
170 | !***********************************************************************
171 |
172 | END MODULE MOD_LOG
173 |
--------------------------------------------------------------------------------
/Zeltron3D/mod_mpi.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_MPI
21 |
22 | USE MOD_INPUT
23 |
24 | IMPLICIT NONE
25 |
26 | ! create a global variable to store the mpi rank, to be used for
27 | ! debugging output when a function doesn't have immediate access to this
28 | ! (except for debugging, this shouldn't be used, global variables being
29 | ! deprecated)
30 | INTEGER, PUBLIC :: globalMpiRank
31 |
32 | PRIVATE
33 | !PUBLIC
34 |
35 | PUBLIC :: CUMSUM ! Form the cumulative sum (running integral) of an array
36 | PUBLIC :: FILL_DOMAIN_INDEX ! Get the NDIM-dimensional domain index in cart. topology
37 | PUBLIC :: FILL_DOMAIN_DECOMP ! Get the NDIM-dimensional domain decomp, with index
38 | PUBLIC :: ELEMENTS_PER_DOMAIN ! Find the number elements per domain in each 1D direction
39 | PUBLIC :: FILL_GLOBAL_FIELD_SHAPE ! Get the global shape of a field from local shapes
40 | PUBLIC :: GATHER_GLOBAL_FIELD ! Gather the global field on one mpi rank
41 | PUBLIC :: FILL_RANK_ORDER ! Get the #ranks/node and the rank-node ordering
42 | PUBLIC :: ASSERT_DOUBLE ! verify (at compile time) that a variable is a double
43 |
44 | INTERFACE CUMSUM
45 | MODULE PROCEDURE CUMSUM_INT, CUMSUM_INT8
46 | END INTERFACE
47 |
48 | INTERFACE ELEMENTS_PER_DOMAIN
49 | MODULE PROCEDURE ELEMENTS_PER_DOMAIN_4, ELEMENTS_PER_DOMAIN_8
50 | END INTERFACE
51 |
52 | INTERFACE FILL_GLOBAL_FIELD_SHAPE
53 | MODULE PROCEDURE FILL_GLOBAL_FIELD_SHAPE_4, FILL_GLOBAL_FIELD_SHAPE_8
54 | END INTERFACE
55 |
56 | CONTAINS
57 |
58 | !***********************************************************************
59 | ! Subroutine CUMSUM
60 | ! Find the cumulative sum (like a running integral) of an array,
61 | ! such that the first element is zero,
62 | ! and also find the sum of all elements of raIn
63 | !
64 | ! INPUT:
65 | !
66 | ! - raIn: a 1D array
67 | ! OUTPUT:
68 | ! - raOut: raOut(n) = Sum_{m=1}^{n-1} raIn(m) (undefined for n > SIZE(raIn))
69 | ! raOut is the same size as raIn (or longer)
70 | ! - total: total = SUM(raIn)
71 | !
72 | !***********************************************************************
73 |
74 | SUBROUTINE CUMSUM_INT(raIn, raOut, total)
75 |
76 | IMPLICIT NONE
77 |
78 | ! INPUT
79 | INTEGER, DIMENSION(:), INTENT(IN) :: raIn
80 | INTEGER, DIMENSION(:), INTENT(OUT) :: raOut
81 | INTEGER, INTENT(OUT) :: total
82 | ! LOCAL
83 | INTEGER :: i
84 | !***********************************************************************
85 |
86 | total = 0
87 | IF (SIZE(raIn) > 0) THEN
88 | raOut(1) = 0
89 | DO i = 2, SIZE(raIn)
90 | raOut(i) = raOut(i-1) + raIn(i-1)
91 | ENDDO
92 | total = raOut(SIZE(raIn)) + raIn(SIZE(raIn))
93 | ENDIF
94 |
95 | END SUBROUTINE CUMSUM_INT
96 |
97 | !***********************************************************************
98 | ! Subroutine CUMSUM
99 | ! Find the cumulative sum (like a running integral) of an array,
100 | ! such that the first element is zero,
101 | ! and also find the sum of all elements of raIn
102 | !
103 | ! INPUT:
104 | !
105 | ! - raIn: a 1D array
106 | ! OUTPUT:
107 | ! - raOut: raOut(n) = Sum_{m=1}^{n-1} raIn(m) (undefined for n > SIZE(raIn))
108 | ! raOut is the same size as raIn (or longer)
109 | ! - total: total = SUM(raIn)
110 | !
111 | !***********************************************************************
112 |
113 | SUBROUTINE CUMSUM_INT8(raIn, raOut, total)
114 |
115 | IMPLICIT NONE
116 |
117 | ! INPUT
118 | INTEGER*8, DIMENSION(:), INTENT(IN) :: raIn
119 | INTEGER*8, DIMENSION(:), INTENT(OUT) :: raOut
120 | INTEGER*8, INTENT(OUT) :: total
121 | ! LOCAL
122 | INTEGER*8 :: i
123 | !***********************************************************************
124 |
125 | total = 0
126 | IF (SIZE(raIn) > 0) THEN
127 | raOut(1) = 0
128 | DO i = 2, SIZE(raIn)
129 | raOut(i) = raOut(i-1) + raIn(i-1)
130 | ENDDO
131 | total = raOut(SIZE(raIn)) + raIn(SIZE(raIn))
132 | ENDIF
133 |
134 | END SUBROUTINE CUMSUM_INT8
135 |
136 | !***********************************************************************
137 | ! Subroutine FILL_DOMAIN_DECOMP
138 | !
139 | ! INPUT:
140 | !
141 | ! - COMM: mpi comm
142 | !
143 | ! OUTPUT:
144 | ! - ierr: error code
145 | ! - domainDecomp the cartesian topology; e.g., in 2D, returns (NXP, NYP)
146 | ! if there are NXP domains in the x-direction, and NYP in y.
147 | ! - domainIndex the NDIM-dimensional domain index in cartesian topology
148 | ! (0-indexed)
149 | !
150 | !***********************************************************************
151 |
152 | SUBROUTINE FILL_DOMAIN_DECOMP(COMM, err, domainDecomp, domainIndex)
153 |
154 | IMPLICIT NONE
155 |
156 | INTEGER :: COMM
157 | INTEGER, INTENT(OUT):: err
158 | INTEGER, INTENT(OUT) :: domainDecomp(NDIM)
159 | INTEGER, INTENT(OUT) :: domainIndex(NDIM)
160 | LOGICAL :: periods(NDIM)
161 | INTEGER :: rank
162 | !***********************************************************************
163 |
164 | CALL MPI_COMM_RANK(COMM, rank, err)
165 |
166 | CALL MPI_CART_GET(COMM, NDIM, domainDecomp, periods, domainIndex, err)
167 |
168 | END SUBROUTINE FILL_DOMAIN_DECOMP
169 |
170 | !***********************************************************************
171 | ! Subroutine FILL_DOMAIN_INDEX
172 | !
173 | ! INPUT:
174 | !
175 | ! - COMM: mpi comm
176 | !
177 | ! OUTPUT:
178 | ! - ierr: error code
179 | ! - domainIndex the NDIM-dimensional domain index in cartesian topology
180 | ! (0-indexed)
181 | !
182 | !***********************************************************************
183 |
184 | SUBROUTINE FILL_DOMAIN_INDEX(COMM, err, domainIndex)
185 |
186 | IMPLICIT NONE
187 |
188 | INTEGER :: COMM
189 | INTEGER, INTENT(OUT):: err
190 | INTEGER, INTENT(OUT):: domainIndex(NDIM)
191 | INTEGER :: dims(NDIM)
192 | !***********************************************************************
193 |
194 | CALL FILL_DOMAIN_DECOMP(COMM, err, dims, domainIndex)
195 |
196 | END SUBROUTINE FILL_DOMAIN_INDEX
197 |
198 | !***********************************************************************
199 | ! Subroutine ELEMENTS_PER_DOMAIN
200 | ! This subroutine calculates the number of elements (of a grid), in
201 | ! each direction, belonging to each MPI domain. It assumes a rectangular
202 | ! decomposition, so that all domains at the same x-location have the
203 | ! same number of elements in the x-direction, etc.
204 | !
205 | ! INPUT:
206 | !
207 | ! - localRaShape: the shape of the array of values belonging to this domain
208 | ! - domIndex: 0-indexed coordinates of this domain, e.g., (/0,1/)
209 | ! - COMM: mpi comm
210 | !
211 | ! OUTPUT: the number of elements/proc in each direction
212 | ! - xElems: an array of size decompShape(1)
213 | ! - yElems: an array of size decompShape(2)
214 | ! E.g., xElems(domIndex(1)) = localRaShape(1)
215 | ! yElems(domIndex(2)) = localRaShape(2)
216 | !
217 | !***********************************************************************
218 |
219 | SUBROUTINE ELEMENTS_PER_DOMAIN_8(localRaShape, COMM, xElems, yElems, zElems)
220 |
221 | IMPLICIT NONE
222 |
223 | INCLUDE 'mpif.h'
224 |
225 | ! INPUT
226 | INTEGER(8), DIMENSION(NDIM) :: localRaShape
227 | INTEGER :: COMM
228 | ! OUTPUT
229 | INTEGER, INTENT(OUT) :: xElems(NPX), yElems(NPY)
230 | INTEGER, INTENT(OUT), OPTIONAL :: zElems(NPZ)
231 | ! LOCAL
232 | INTEGER, DIMENSION(NDIM) :: domIndex
233 | INTEGER :: mpiErr, rank
234 | INTEGER :: d
235 | INTEGER(8), DIMENSION(NDIM) :: raShape
236 | INTEGER :: xElemsTmp(NPX), yElemsTmp(NPY), zElemsTmp(NPZ)
237 | !***********************************************************************
238 |
239 | xElemsTmp = 0
240 | yElemsTmp = 0
241 | zElemsTmp = 0
242 |
243 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
244 | xElemsTmp(domIndex(1)+1) = localRaShape(1)
245 | yElemsTmp(domIndex(2)+1) = localRaShape(2)
246 |
247 | CALL MPI_ALLREDUCE(xElemsTmp, xElems, NPX, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
248 | CALL MPI_ALLREDUCE(yElemsTmp, yElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
249 |
250 | IF (NDIM == 2) THEN
251 | xElems = xElems / NPY
252 | yElems = yElems / NPX
253 | ELSEIF (NDIM == 3) THEN
254 | xElems = xElems / (NPY*NPZ)
255 | yElems = yElems / (NPX*NPY)
256 | d = MIN(NDIM, 3)
257 | zElemsTmp(domIndex(d)+1) = localRaShape(d)
258 | CALL MPI_ALLREDUCE(zElemsTmp, zElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
259 | ZElems = zElems / (NPX*NPY)
260 | ! set raShape(3), but use d to avoid error when NDIM=2
261 | raShape(d) = zElems(domIndex(d)+1)
262 | ENDIF
263 |
264 | ! check validity
265 | raShape(1) = xElems(domIndex(1)+1)
266 | raShape(2) = yElems(domIndex(2)+1)
267 | DO d = 1, NDIM
268 | IF (raShape(d) /= localRaShape(d)) THEN
269 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
270 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
271 | PRINT *, 'Error (in mod_io 8): rank ', rank, ' should have ', raShape(d), &
272 | ' elements (like all other procs in same line) in dir ', d, ' but has ', localRaShape(d)
273 | ENDIF
274 | ENDDO
275 |
276 | END SUBROUTINE
277 |
278 | !***********************************************************************
279 |
280 | SUBROUTINE ELEMENTS_PER_DOMAIN_4(localRaShape, COMM, xElems, yElems, zElems)
281 |
282 | IMPLICIT NONE
283 |
284 | INCLUDE 'mpif.h'
285 |
286 | ! INPUT
287 | INTEGER(4), DIMENSION(NDIM) :: localRaShape
288 | INTEGER :: COMM
289 | ! OUTPUT
290 | INTEGER, INTENT(OUT) :: xElems(NPX), yElems(NPY)
291 | INTEGER, INTENT(OUT), OPTIONAL :: zElems(NPZ)
292 | ! LOCAL
293 | INTEGER, DIMENSION(NDIM) :: domIndex
294 | INTEGER :: mpiErr, rank
295 | INTEGER :: d
296 | INTEGER(4), DIMENSION(NDIM) :: raShape
297 | INTEGER :: xElemsTmp(NPX), yElemsTmp(NPY), zElemsTmp(NPZ)
298 | !***********************************************************************
299 |
300 | xElemsTmp = 0
301 | yElemsTmp = 0
302 | zElemsTmp = 0
303 |
304 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
305 | xElemsTmp(domIndex(1)+1) = localRaShape(1)
306 | yElemsTmp(domIndex(2)+1) = localRaShape(2)
307 |
308 | CALL MPI_ALLREDUCE(xElemsTmp, xElems, NPX, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
309 | CALL MPI_ALLREDUCE(yElemsTmp, yElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
310 |
311 | IF (NDIM == 2) THEN
312 | xElems = xElems / NPY
313 | yElems = yElems / NPX
314 | ELSEIF (NDIM == 3) THEN
315 | xElems = xElems / (NPY*NPZ)
316 | yElems = yElems / (NPX*NPY)
317 | d = MIN(NDIM, 3)
318 | zElemsTmp(domIndex(d)+1) = localRaShape(d)
319 | CALL MPI_ALLREDUCE(zElemsTmp, zElems, NPY, MPI_INTEGER, MPI_SUM, COMM, mpiErr)
320 | ZElems = zElems / (NPX*NPY)
321 | ! set raShape(3), but use d to avoid error when NDIM=2
322 | raShape(d) = zElems(domIndex(d)+1)
323 | ENDIF
324 |
325 | ! check validity
326 | raShape(1) = xElems(domIndex(1)+1)
327 | raShape(2) = yElems(domIndex(2)+1)
328 | DO d = 1, NDIM
329 | IF (raShape(d) /= localRaShape(d)) THEN
330 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
331 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
332 | PRINT *, 'Error (in mod_io 4): rank ', rank, ' should have ', raShape(d), &
333 | ' elements (like all other procs in same line) in dir ', d, ' but has ', localRaShape(d)
334 | ENDIF
335 | ENDDO
336 |
337 | END SUBROUTINE
338 |
339 | !***********************************************************************
340 | ! Subroutine FILL_GLOBAL_FIELD_SHAPE
341 | ! Given the local field shape on each rank,
342 | ! find the global field shape, and the offset, in global indices,
343 | ! of the field value with local index (0,0)
344 | !
345 | ! INPUT:
346 | ! - localShape
347 | ! - COMM: mpi comm
348 | ! OUTPUT:
349 | ! - globalShape
350 | ! - offset
351 | !***********************************************************************
352 |
353 | SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_4(localShape, globalShape, offset, COMM)
354 |
355 | IMPLICIT NONE
356 |
357 | INCLUDE 'mpif.h'
358 |
359 | ! INPUT
360 | ! following must have rank=NDIM
361 | INTEGER*4, DIMENSION(NDIM) :: localShape
362 | INTEGER*4, DIMENSION(NDIM), INTENT(OUT) :: globalShape, offset
363 | INTEGER :: COMM
364 |
365 | ! LOCAL
366 | INTEGER, DIMENSION(NDIM) :: domIndex
367 | INTEGER, DIMENSION(NPX) :: xElemPerProc
368 | INTEGER, DIMENSION(NPY) :: yElemPerProc
369 | INTEGER, DIMENSION(NPZ) :: zElemPerProc
370 | INTEGER :: mpiErr, numRanks, rank
371 | !***********************************************************************
372 |
373 | CALL MPI_COMM_SIZE(COMM, numRanks, mpiErr)
374 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
375 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
376 |
377 | ! find shape of local array on each domain
378 | IF (NDIM == 2) THEN
379 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc)
380 | ELSE
381 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc, zElemPerProc)
382 | ENDIF
383 |
384 | globalShape(1) = SUM(xElemPerProc)
385 | globalShape(2) = SUM(yElemPerProc)
386 |
387 | offset(1) = SUM(xElemPerProc(:domIndex(1)))
388 | offset(2) = SUM(yElemPerProc(:domIndex(2)))
389 |
390 | IF (NDIM >= 3) THEN
391 | globalShape(MIN(NDIM,3)) = SUM(zElemPerProc)
392 | offset(MIN(NDIM,3)) = SUM(zElemPerProc(:domIndex(MIN(NDIM,3))))
393 | ENDIF
394 |
395 | END SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_4
396 |
397 | !***********************************************************************
398 | ! Subroutine FILL_GLOBAL_FIELD_SHAPE
399 | ! Given the local field shape on each rank,
400 | ! find the global field shape, and the offset, in global indices,
401 | ! of the field value with local index (0,0)
402 | !
403 | ! INPUT:
404 | ! - localShape
405 | ! - COMM: mpi comm
406 | ! OUTPUT:
407 | ! - globalShape
408 | ! - offset
409 | !***********************************************************************
410 |
411 | SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_8(localShape, globalShape, offset, COMM)
412 |
413 | IMPLICIT NONE
414 |
415 | INCLUDE 'mpif.h'
416 |
417 | ! INPUT
418 | ! following must have rank=NDIM
419 | INTEGER*8, DIMENSION(NDIM) :: localShape
420 | INTEGER*8, DIMENSION(NDIM), INTENT(OUT) :: globalShape, offset
421 | INTEGER :: COMM
422 |
423 | ! LOCAL
424 | INTEGER, DIMENSION(NDIM) :: domIndex
425 | INTEGER, DIMENSION(NPX) :: xElemPerProc
426 | INTEGER, DIMENSION(NPY) :: yElemPerProc
427 | INTEGER, DIMENSION(NPZ) :: zElemPerProc
428 | INTEGER :: mpiErr, numRanks, rank
429 | !***********************************************************************
430 |
431 | CALL MPI_COMM_SIZE(COMM, numRanks, mpiErr)
432 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
433 | CALL FILL_DOMAIN_INDEX(COMM, mpiErr, domIndex)
434 |
435 | ! find shape of local array on each domain
436 | IF (NDIM == 2) THEN
437 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc)
438 | ELSE
439 | CALL ELEMENTS_PER_DOMAIN(localShape, COMM, xElemPerProc, yElemPerProc, zElemPerProc)
440 | ENDIF
441 |
442 | globalShape(1) = SUM(xElemPerProc)
443 | globalShape(2) = SUM(yElemPerProc)
444 |
445 | offset(1) = SUM(xElemPerProc(:domIndex(1)))
446 | offset(2) = SUM(yElemPerProc(:domIndex(2)))
447 |
448 | IF (NDIM >= 3) THEN
449 | globalShape(MIN(NDIM,3)) = SUM(zElemPerProc)
450 | offset(MIN(NDIM,3)) = SUM(zElemPerProc(:domIndex(MIN(NDIM,3))))
451 | ENDIF
452 |
453 | END SUBROUTINE FILL_GLOBAL_FIELD_SHAPE_8
454 |
455 | !***********************************************************************
456 | ! Subroutine GATHER_GLOBAL_FIELD
457 | ! Gather field values from all ranks to a global field on one rank.
458 | !
459 | ! INPUT:
460 | !
461 | ! - F the local field values for this rank
462 | ! - Ft an array (already allocated) with the global field shape
463 | ! - on rank = gatherRank, this will contain the global field
464 | ! - on other ranks, this is undefined
465 | ! - offset an array giving the global index of F(0,0[,0])
466 | ! - COMM: mpi comm
467 | !
468 | ! OUTPUT: the number of elements/proc in each direction
469 | !
470 | !***********************************************************************
471 |
472 | SUBROUTINE GATHER_GLOBAL_FIELD(F, Ft, offset, gatherRank, COMM)
473 |
474 | IMPLICIT NONE
475 |
476 | INCLUDE 'mpif.h'
477 |
478 | ! INPUT
479 | ! following must have rank=NDIM
480 | DOUBLE PRECISION, DIMENSION(:,:,:) :: F
481 | DOUBLE PRECISION, DIMENSION(:,:,:), INTENT(OUT) :: Ft
482 | INTEGER, DIMENSION(NDIM) :: offset
483 | INTEGER :: gatherRank
484 | INTEGER :: COMM
485 |
486 | ! LOCAL
487 | DOUBLE PRECISION, ALLOCATABLE :: Ft2(:,:,:)
488 | INTEGER, DIMENSION(NDIM) :: domIndex
489 | INTEGER, DIMENSION(NPX) :: xElemPerProc
490 | INTEGER, DIMENSION(NPY) :: yElemPerProc
491 | INTEGER, DIMENSION(NPZ) :: zElemPerProc
492 | CHARACTER(len=10) :: cit
493 |
494 | ! shape of local and global field array
495 | INTEGER, DIMENSION(NDIM) :: localShape
496 | INTEGER, DIMENSION(NDIM) :: globalShape
497 |
498 | INTEGER :: mpiErr, numRanks, rank
499 |
500 | INTEGER :: d, i, j, k
501 | !***********************************************************************
502 |
503 | localShape = SHAPE(F)
504 | globalShape = SHAPE(Ft)
505 |
506 | ALLOCATE(Ft2(globalShape(1), globalShape(2), globalShape(3)))
507 |
508 | Ft2 = 0.
509 |
510 | DO k=1, localShape(3)
511 | DO j=1, localShape(2)
512 | DO i=1, localShape(1)
513 | Ft2(offset(1) + i, offset(2) + j, offset(3) + k) = F(i,j,k)
514 | ENDDO
515 | ENDDO
516 | ENDDO
517 |
518 | ! :TODO: it would be better to use MPI_GATHERV, but it's a lot easier to use MPI_REDUCE
519 | ! Get all field values on rank 0
520 | CALL MPI_REDUCE(Ft2,Ft,PRODUCT(globalShape),MPI_DOUBLE_PRECISION,MPI_SUM,&
521 | gatherRank,COMM,mpiErr)
522 |
523 | DEALLOCATE(Ft2)
524 |
525 | END SUBROUTINE GATHER_GLOBAL_FIELD
526 |
527 | !***********************************************************************
528 | ! Subroutine FILL_RANK_ORDER
529 | ! Determine (by examing the hostname of the first two ranks)
530 | ! whether the order is round-robin or not.
531 | !
532 | ! INPUT:
533 | ! -COMM: mpi comm (should be global comm)
534 | !
535 | ! OUTPUT: Assuming M ranks per node, and N nodes
536 | ! - rankOrder
537 | ! =0 if rank r is on node (r%N)
538 | ! =1 if rank r is on node floor(r/M)
539 | ! If there's only one rank, or if ranksPerNode = 1, then rankOrder = 1
540 | ! - ranksPerNode: the number of ranksPerNode
541 | !
542 | !***********************************************************************
543 |
544 | SUBROUTINE FILL_RANK_ORDER(COMM, rankOrder, ranksPerNode)
545 |
546 | IMPLICIT NONE
547 |
548 | INCLUDE 'mpif.h'
549 |
550 | ! INPUT
551 | INTEGER :: COMM
552 | INTEGER, INTENT(OUT) :: rankOrder, ranksPerNode
553 | ! LOCAL
554 | CHARACTER*(MPI_MAX_PROCESSOR_NAME) :: hostName, hostNameRank0
555 | INTEGER :: hostnameLen
556 | INTEGER :: sameNameAsRank0
557 | INTEGER :: rank, numRanks, mpiErr
558 | INTEGER :: i, nextOnDifferentNode, nextOnSameNode
559 | INTEGER :: tag
560 | INTEGER, DIMENSION(:), ALLOCATABLE :: onFirstNode
561 | !***********************************************************************
562 |
563 | ! Determine which other ranks are running on the same node as rank 0.
564 | ! From that, infer the number of ranks per node, and whether the ordering
565 | ! has adjacent ranks on the same node, or is round robin.
566 |
567 | CALL MPI_COMM_SIZE(COMM, numRanks, mpiErr)
568 | IF (numRanks == 1) THEN
569 | rankOrder = 1
570 | ranksPerNode = 1
571 | ELSE
572 | CALL MPI_COMM_RANK(COMM, rank, mpiErr)
573 | CALL MPI_GET_PROCESSOR_NAME(hostName, hostnameLen, mpiErr)
574 | hostName(hostnameLen+1:MPI_MAX_PROCESSOR_NAME) = ' '
575 | ! Broadcast hostName of rank 0 to everybody
576 | IF (rank == 0) THEN
577 | CALL MPI_BCAST(hostName, MPI_MAX_PROCESSOR_NAME, MPI_CHARACTER, 0, &
578 | COMM, mpiErr)
579 | hostNameRank0 = hostName
580 | ALLOCATE(onFirstNode(numRanks))
581 | ELSE
582 | CALL MPI_BCAST(hostNameRank0, MPI_MAX_PROCESSOR_NAME, MPI_CHARACTER, 0,&
583 | COMM, mpiErr)
584 | ENDIF
585 | sameNameAsRank0 = 0
586 | IF (hostName == hostNameRank0) sameNameAsRank0 = 1
587 | CALL MPI_GATHER(sameNameAsRank0, 1, MPI_INTEGER, onFirstNode, 1,&
588 | MPI_INTEGER, 0, COMM, mpiErr)
589 | IF (rank == 0) THEN
590 | ! Find the next rank that's on the same node, and the next that's
591 | ! on a different node (from rank 0).
592 | nextOnDifferentNode = numRanks
593 | DO i = 2, numRanks
594 | IF (onFirstNode(i) == 0) THEN
595 | nextOnDifferentNode = i - 1
596 | EXIT
597 | ENDIF
598 | ENDDO
599 | nextOnSameNode = numRanks
600 | DO i = 2, numRanks
601 | IF (onFirstNode(i) == 1) THEN
602 | nextOnSameNode = i - 1
603 | EXIT
604 | ENDIF
605 | ENDDO
606 | IF (nextOnSameNode == 1) THEN
607 | rankOrder = 1
608 | ranksPerNode = nextOnDifferentNode
609 | ENDIF
610 | IF (nextOnDifferentNode == 1) THEN
611 | rankOrder = 0
612 | ! Following assumes a constant ranksPerNode
613 | ranksPerNode = numRanks / nextOnSameNode
614 | ENDIF
615 | IF (ranksPerNode == 1) THEN
616 | rankOrder = 1
617 | ENDIF
618 | DEALLOCATE(onFirstNode)
619 | ENDIF
620 | CALL MPI_BCAST(rankOrder, 1, MPI_INTEGER, 0, COMM, mpiErr)
621 | CALL MPI_BCAST(ranksPerNode, 1, MPI_INTEGER, 0, COMM, mpiErr)
622 | ENDIF
623 |
624 | END SUBROUTINE FILL_RANK_ORDER
625 |
626 | !***********************************************************************
627 | ! Subroutine CHECK_DOUBLE
628 | !
629 | ! This subroutine will cause a compilation error if the argument is not
630 | ! a double.
631 | !***********************************************************************
632 |
633 | SUBROUTINE ASSERT_DOUBLE(dbl)
634 |
635 | IMPLICIT NONE
636 |
637 | DOUBLE PRECISION, INTENT(IN) :: dbl
638 |
639 | END SUBROUTINE ASSERT_DOUBLE
640 |
641 | !***********************************************************************
642 |
643 | END MODULE
644 |
645 |
--------------------------------------------------------------------------------
/Zeltron3D/mod_sync.f90:
--------------------------------------------------------------------------------
1 | !***********************************************************************!
2 | ! The Zeltron code project. !
3 | !***********************************************************************!
4 | ! Copyright (C) 2012-2015. Authors: Benoît Cerutti & Greg Werner !
5 | ! !
6 | ! This program is free software: you can redistribute it and/or modify !
7 | ! it under the terms of the GNU General Public License as published by !
8 | ! the Free Software Foundation, either version 3 of the License, or !
9 | ! (at your option) any later version. !
10 | ! !
11 | ! This program is distributed in the hope that it will be useful, !
12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | ! GNU General Public License for more details. !
15 | ! !
16 | ! You should have received a copy of the GNU General Public License !
17 | ! along with this program. If not, see . !
18 | !***********************************************************************!
19 |
20 | MODULE MOD_SYNC
21 |
22 | USE MOD_INPUT
23 |
24 | IMPLICIT NONE
25 |
26 | PRIVATE
27 | PUBLIC :: SYNC ! Synchrotron kernel with pitch angle alpha
28 | PUBLIC :: FSYNC ! Precalculated synchrotron kernel F(x)
29 | PUBLIC :: GSYNC ! Precalculated synchrotron kernel G(x)
30 | PUBLIC :: LOG_INTERPOL ! Interpol function in the log-log plane
31 |
32 | CONTAINS
33 |
34 | !***********************************************************************
35 | ! Subroutine SYNC
36 | ! Calculation of the synchrotron kernel for a pitch angle alpha
37 | !
38 | ! INPUT: photon energy e1 [in eV], magnetic field B [in Gauss],
39 | ! Lorentz factor of the electron gam, pitch angle alpha [rad]
40 | ! and the mass of the particles [g].
41 | !
42 | ! OUTPUT: Synchrotron kernel kern=dN/dtde1 [ph/s/erg]
43 | !***********************************************************************
44 |
45 | SUBROUTINE SYNC(mass,kern,e1,B,gam,alpha)
46 |
47 | IMPLICIT NONE
48 |
49 | !!! INPUT/OUTPUT PARAMETERS !!!
50 | DOUBLE PRECISION :: mass,e1,kern,B,gam,alpha
51 | DOUBLE PRECISION :: x1(100),x1intK53(100),x2
52 |
53 | !***********************************************************************
54 |
55 | ! Initialisation
56 | kern=0d0
57 |
58 | CALL FSYNC(x1,x1intK53)
59 |
60 | IF (B*sin(alpha).NE.0d0) THEN
61 |
62 | x2=e1*evtoerg*4d0*pi*mass*c/(3d0*h*e*B*gam*gam*sin(alpha))
63 |
64 | kern=LOG_INTERPOL(x1intK53,x1,x2,100)
65 |
66 | ! Asymptotic formulae for x<<1 et x>>1
67 | IF (x2.LT.1d-6.or.x2.GT.20d0) THEN
68 |
69 | IF (x2.LT.1d-6) THEN
70 | ! for x<<1
71 | kern=2.1495285*x2**(1d0/3d0)
72 | ELSE
73 | ! for x>>1
74 | kern=sqrt(pi/2d0)*exp(-x2)*sqrt(x2)
75 | ENDIF
76 |
77 | ENDIF
78 |
79 | kern=kern*sqrt(3d0)*e**(3d0)*B*sin(alpha)/(mass*c*c*h*e1*evtoerg)
80 |
81 | ELSE
82 | kern=0d0
83 | END IF
84 |
85 | END SUBROUTINE SYNC
86 |
87 | !***********************************************************************
88 | ! Subroutine FSYNC
89 | ! Precalculated synchrotron kernel averaged over isotropic pitch angle
90 | !
91 | ! INPUT: x1,x1intK53
92 | !
93 | ! OUTPUT: x1,x1intK53
94 | !***********************************************************************
95 |
96 | SUBROUTINE FSYNC(x1,x1intK53)
97 |
98 | IMPLICIT NONE
99 |
100 | DOUBLE PRECISION :: x1(100),x1intK53(100)
101 |
102 | !***********************************************************************
103 |
104 | x1=[1.000000000000000E-006,1.185080297211958E-006,1.404415310839983E-006,&
105 | 1.664344913979274E-006,1.972382365321769E-006,2.337431479711146E-006,&
106 | 2.770043992688672E-006,3.282724558145690E-006,3.890292195032295E-006,&
107 | 4.610308630730232E-006,5.463585922344638E-006,6.474788028695254E-006,&
108 | 7.673143721430598E-006,9.093291441943042E-006,1.077628052465281E-005,&
109 | 1.277075772699502E-005,1.513437336272916E-005,1.793544768281981E-005,&
110 | 2.125494567058563E-005,2.518881733252163E-005,2.985077113084251E-005,&
111 | 3.537556072374498E-005,4.192288001653537E-005,4.968197910997698E-005,&
112 | 5.887713456972981E-005,6.977413213488398E-005,8.268794924811474E-005,&
113 | 9.799185947080311E-005,1.161282219460118E-004,1.376212677784760E-004,&
114 | 1.630922529216028E-004,1.932774155653010E-004,2.290492570824860E-004,&
115 | 2.714417616594907E-004,3.216802835831666E-004,3.812169660759664E-004,&
116 | 4.517727154595472E-004,5.353869439090540E-004,6.344765186111429E-004,&
117 | 7.519056212497024E-004,8.910685371059391E-004,1.055987766789732E-003,&
118 | 1.251430296519367E-003,1.483045387739222E-003,1.757527868880820E-003,&
119 | 2.082811649211582E-003,2.468299048284192E-003,2.925132569748623E-003,&
120 | 3.466516975142080E-003,4.108100967191674E-003,4.868429515176245E-003,&
121 | 5.769479896800527E-003,6.837296950858798E-003,8.102745902650151E-003,&
122 | 9.602404522545615E-003,1.137962040552782E-002,1.348576393234217E-002,&
123 | 1.598171312907039E-002,1.893961334495499E-002,2.244496261191877E-002,&
124 | 2.659908296304404E-002,3.152204914340976E-002,3.735615936760205E-002,&
125 | 4.427004844605502E-002,5.246356217003877E-002,6.217353384926757E-002,&
126 | 7.368062997280773E-002,8.731746286693928E-002,0.103478204846147,&
127 | 0.122629981754031,0.145326375224165,0.172223423943389,0.204098586433693,&
128 | 0.241873213471381,0.286639179708277,0.339690444281276,0.402560452668916,&
129 | 0.477066460894660,0.565362063266901,0.669999441968706,0.794003137820118,&
130 | 0.940957474555095,1.11511016360957,1.32149508411450,1.56607778704655,&
131 | 1.85592792933017,2.19942362209458,2.60649359976684,3.08890420989276,&
132 | 3.66059951911898,4.33810436609147,5.14100201150418,6.09250019176065,&
133 | 7.22010193801562,8.55640055060418,10.1400217075746,12.0167399389482,&
134 | 14.2408017383675,16.8764935566412,20.0000000000000]
135 |
136 | x1intK53=[2.149740291554781E-002,2.274901841108215E-002,2.407347673895755E-02,&
137 | 2.547501192814867E-002,2.695810311511616E-002,2.852748854769207E-002,&
138 | 3.018818035452749E-002,3.194548011543796E-002,3.380499526832988E-002,&
139 | 3.577265638843877E-002,3.785473537529143E-002,4.005786458201257E-002,&
140 | 4.238905692024220E-002,4.485572697186294E-002,4.746571313581508E-002,&
141 | 5.022730083430440E-002,5.314924679746723E-002,5.624080443877249E-002,&
142 | 5.951175032481285E-002,6.297241173226253E-002,6.663369527122917E-002,&
143 | 7.050711653745867E-002,7.460483073522131E-002,7.893966418747039E-002,&
144 | 8.352514661910548E-002,8.837554406184385E-002,9.350589218401047E-002,&
145 | 9.893202979401500E-002,0.104670632200595,0.110739244033946,&
146 | 0.117156311037122,0.123941210223590,0.131114277661013,0.138696832979062,&
147 | 0.146711199505309,0.155180718702228,0.164129757302985,0.173583705215995,&
148 | 0.183568961878227,0.194112908273776,0.205243861283644,0.216991006379192,&
149 | 0.229384303896832,0.242454363213354,0.256232278054607,0.270749414885549,&
150 | 0.286037144813124,0.302126507646095,0.319047794653951,0.336830034101253,&
151 | 0.355500360750710,0.375083247170932,0.395599570795967,0.417065486209677,&
152 | 0.439491067027217,0.462878676000437,0.487221015609695,0.512498804519786,&
153 | 0.538678018088907,0.565706624027361,0.593510737989999,0.621990119460058,&
154 | 0.651012927475406,0.680409661204000,0.709966226034660,0.739416097466217,&
155 | 0.768431610877948,0.796614496726025,0.823485923402867,0.848476524260903,&
156 | 0.870917196368038,0.890031895276086,0.904934240857714,0.914630512970876,&
157 | 0.918032544174628,0.913985044579456,0.901312851526806,0.878894144928416,&
158 | 0.845765223343403,0.801260109434639,0.745182884585394,0.678001036863573,&
159 | 0.601033606171899,0.516589597155386,0.427994417761062,0.339434248068025,&
160 | 0.255564108478843,0.180878805791705,0.118939475992646,&
161 | 7.165783884585139E-002,3.890601404389666E-002,1.866644749682380E-002,&
162 | 7.731985450943564E-003,2.689821816878248E-003,7.606072676721128E-004,&
163 | 1.681815907755760E-004,2.777448106239215E-005,3.244518011577780E-006,&
164 | 2.513722787179256E-007,1.196759294412181E-008]
165 |
166 | END SUBROUTINE FSYNC
167 |
168 | !***********************************************************************
169 | ! Subroutine GSYNC
170 | ! Precalculated synchrotron kernel G(x)=x*K_{2/3}(x)
171 | !
172 | ! INPUT: x1,x1K23
173 | !
174 | ! OUTPUT: x1,x1K23
175 | !***********************************************************************
176 |
177 | SUBROUTINE GSYNC(x1,x1K23)
178 |
179 | IMPLICIT NONE
180 |
181 | DOUBLE PRECISION :: x1(100),x1K23(100)
182 |
183 | !***********************************************************************
184 |
185 | x1=[1.000000000000000E-006,1.185080297211958E-006,1.404415310839983E-006,&
186 | 1.664344913979274E-006,1.972382365321769E-006,2.337431479711146E-006,&
187 | 2.770043992688672E-006,3.282724558145690E-006,3.890292195032295E-006,&
188 | 4.610308630730232E-006,5.463585922344638E-006,6.474788028695254E-006,&
189 | 7.673143721430598E-006,9.093291441943042E-006,1.077628052465281E-005,&
190 | 1.277075772699502E-005,1.513437336272916E-005,1.793544768281981E-005,&
191 | 2.125494567058563E-005,2.518881733252163E-005,2.985077113084251E-005,&
192 | 3.537556072374498E-005,4.192288001653537E-005,4.968197910997698E-005,&
193 | 5.887713456972981E-005,6.977413213488398E-005,8.268794924811474E-005,&
194 | 9.799185947080311E-005,1.161282219460118E-004,1.376212677784760E-004,&
195 | 1.630922529216028E-004,1.932774155653010E-004,2.290492570824860E-004,&
196 | 2.714417616594907E-004,3.216802835831666E-004,3.812169660759664E-004,&
197 | 4.517727154595472E-004,5.353869439090540E-004,6.344765186111429E-004,&
198 | 7.519056212497024E-004,8.910685371059391E-004,1.055987766789732E-003,&
199 | 1.251430296519367E-003,1.483045387739222E-003,1.757527868880820E-003,&
200 | 2.082811649211582E-003,2.468299048284192E-003,2.925132569748623E-003,&
201 | 3.466516975142080E-003,4.108100967191674E-003,4.868429515176245E-003,&
202 | 5.769479896800527E-003,6.837296950858798E-003,8.102745902650151E-003,&
203 | 9.602404522545615E-003,1.137962040552782E-002,1.348576393234217E-002,&
204 | 1.598171312907039E-002,1.893961334495499E-002,2.244496261191877E-002,&
205 | 2.659908296304404E-002,3.152204914340976E-002,3.735615936760205E-002,&
206 | 4.427004844605502E-002,5.246356217003877E-002,6.217353384926757E-002,&
207 | 7.368062997280773E-002,8.731746286693928E-002,0.103478204846147,&
208 | 0.122629981754031,0.145326375224165,0.172223423943389,0.204098586433693,&
209 | 0.241873213471381,0.286639179708277,0.339690444281276,0.402560452668916,&
210 | 0.477066460894660,0.565362063266901,0.669999441968706,0.794003137820118,&
211 | 0.940957474555095,1.11511016360957,1.32149508411450,1.56607778704655,&
212 | 1.85592792933017,2.19942362209458,2.60649359976684,3.08890420989276,&
213 | 3.66059951911898,4.33810436609147,5.14100201150418,6.09250019176065,&
214 | 7.22010193801562,8.55640055060418,10.1400217075746,12.0167399389482,&
215 | 14.2408017383675,16.8764935566412,20.0000000000000]
216 |
217 | x1K23=[1.0747643897745062E-02,1.1373545210783379E-02,1.2035896592231921E-02,&
218 | 1.2736820749913969E-02,1.3478564008782041E-02,1.4263503509513454E-02,&
219 | 1.5094154826196853E-02,1.5973180027474308E-02,1.6903396206909029E-02,&
220 | 1.7887784509830962E-02,1.8929499685476209E-02,2.0031880194881776E-02,&
221 | 2.1198458906729667E-02,2.2432974415152813E-02,2.3739383015421545E-02,&
222 | 2.5121871375423030E-02,2.6584869942922768E-02,2.8133067130752962E-02,&
223 | 2.9771424324296393E-02,3.1505191757913456E-02,3.3339925309272031E-02,&
224 | 3.5281504262853688E-02,3.7336150096185156E-02,3.9510446344517433E-02,&
225 | 4.1811359601670921E-02,4.4246261716466256E-02,4.6822953245424861E-02,&
226 | 4.9549688223044487E-02,5.2435200310667798E-02,5.5488730383404079E-02,&
227 | 5.8720055611260404E-02,6.2139520084949121E-02,6.5758067027916547E-02,&
228 | 6.9587272622869414E-02,7.3639381461965511E-02,7.7927343602935212E-02,&
229 | 8.2464853176107314E-02,8.7266388436226042E-02,9.2347253083557665E-02,&
230 | 9.7723618585195612E-02,1.0341256710191914E-01,1.0943213445827858E-01,&
231 | 1.1580135237047884E-01,1.2254028885076103E-01,1.2967008531576230E-01,&
232 | 1.3721298841045385E-01,1.4519237388080361E-01,1.5363275893842104E-01,&
233 | 1.6255979839644882E-01,1.7200025833790941E-01,1.8198195910426676E-01,&
234 | 1.9253367683570879E-01,2.0368498949697711E-01,2.1546604908839945E-01,&
235 | 2.2790725633507314E-01,2.4103880728814336E-01,2.5489007263888469E-01,&
236 | 2.6948875978360587E-01,2.8485979441901821E-01,3.0102384236008223E-01,&
237 | 3.1799537313269710E-01,3.3578014472089196E-01,3.5437196411308958E-01,&
238 | 3.7374855224180692E-01,3.9386631705642655E-01,4.1465381928802320E-01,&
239 | 4.3600370938982375E-01,4.5776293286262165E-01,4.7972106230544437E-01,&
240 | 5.0159674344171334E-01,5.2302247393686374E-01,5.4352831324898032E-01,&
241 | 5.6252570297275262E-01,5.7929341614688590E-01,5.9296879293422222E-01,&
242 | 6.0254885612078724E-01,6.0690753191603164E-01,6.0483674932169196E-01,&
243 | 5.9512008984440556E-01,5.7664695249016851E-01,5.4857149882323297E-01,&
244 | 5.1051228601562937E-01,4.6277410354308585E-01,4.0655319823184477E-01,&
245 | 3.4406425214049335E-01,2.7851101631629366E-01,2.1382723252770189E-01,&
246 | 1.5415740709436007E-01,1.0313621159571919E-01,6.3142610234701455E-02,&
247 | 3.4793456825950260E-02,1.6920308680868815E-02,7.0950242834264222E-03,&
248 | 2.4955701251498405E-03,7.1265991922884824E-04,1.5896437702472136E-04,&
249 | 2.6456199476679287E-05,3.1116648932472386E-06,2.4252957578827992E-07,&
250 | 1.1607696861888819E-08]
251 |
252 | END SUBROUTINE GSYNC
253 |
254 | !***********************************************************************
255 | ! Function LOG_INTERPOL: linear interpolation
256 | ! INPUT: fun (function to interpolate), xi (initial grid where fun is
257 | ! defined), and xf (final grid).
258 | ! OUTPUT: LOG_INTERPOL (fun calculated in the xf grid)
259 | !***********************************************************************
260 |
261 | FUNCTION LOG_INTERPOL(fun,xi,xf,n_xi)
262 |
263 | IMPLICIT NONE
264 |
265 | !!! INPUT/OUTPUT PARAMETERS !!!
266 | INTEGER :: n_xi
267 | DOUBLE PRECISION, DIMENSION(1:n_xi) :: fun,xi,mind
268 | DOUBLE PRECISION :: xf,log_interpol
269 |
270 | !!! Intermediate variables !!!
271 | DOUBLE PRECISION :: xp,diff,ly1,ly0,lh,lf1,lf0,lp
272 |
273 | !!! Loop indexes !!!
274 | INTEGER :: j
275 |
276 | !***********************************************************************
277 |
278 | IF (xf.LT.minval(xi).OR.xf.GT.maxval(xi)) THEN
279 | log_interpol=0.0
280 | ELSE
281 |
282 | mind=minloc(abs(xf-xi))
283 | j=mind(1)
284 |
285 | ly1=log10(xi(j+1))
286 | ly0=log10(xi(j))
287 | lh=ly1-ly0
288 | lf1=log10(fun(j+1))
289 | lf0=log10(fun(j))
290 | lp=(log10(xf)-ly0)/lh
291 | ! Linear interpolation in the log-log plane
292 | log_interpol=1d1**((1d0-lp)*lf0+lp*lf1)
293 |
294 | ENDIF
295 |
296 | END FUNCTION LOG_INTERPOL
297 |
298 | !***********************************************************************
299 |
300 | END MODULE MOD_SYNC
301 |
--------------------------------------------------------------------------------
/Zeltron3D/script_restore.sh:
--------------------------------------------------------------------------------
1 | # Remove all .mod and .o files
2 | rm *.mod *.o
3 |
4 | # Compile the code
5 | make IO=txt
6 |
7 | # Run the code
8 | mpirun -np 1 zeltron.exe
9 |
--------------------------------------------------------------------------------
/Zeltron3D/script_run.sh:
--------------------------------------------------------------------------------
1 | # Remove all .mod and .o files
2 | rm *.mod *.o
3 | rm zeltron.exe zeltron.out zeltron.err rankLog_*.txt
4 |
5 | # Remove all data
6 | rm -r ./data/*
7 | rm ./data_restore/*
8 |
9 | if [ ! -d data ]
10 | then
11 | mkdir data
12 | fi
13 |
14 | # Create folders where data will be dumped
15 | mkdir data/orbits
16 | mkdir data/fields
17 | mkdir data/densities
18 | mkdir data/currents
19 | mkdir data/particles
20 | mkdir data_restore
21 |
22 | # Just make the executable; don't run it.
23 | make IO=txt
24 |
25 | # Run the code
26 | mpirun -np 1 zeltron.exe
27 |
--------------------------------------------------------------------------------
/plot2D/energy.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the total magnetic, electric, particle,
21 | # and radiative energies as a function of time.
22 | #
23 | # To execute, type for instance:$ python energy.py &
24 | #
25 | #***********************************************************************!
26 |
27 | import numpy
28 | import math
29 | import matplotlib.pyplot as plt
30 | import pylab
31 |
32 | def energy():
33 |
34 | #===============================================================================
35 | # Magnetic and electric energies
36 |
37 | data=numpy.loadtxt(".././Zeltron2D/data/Eem.dat")
38 | emag=data[:,0]
39 | eelc=data[:,1]
40 |
41 | plt.plot(emag,color='blue',lw=2)
42 | plt.plot(eelc,color='red',lw=2)
43 |
44 | plt.xlabel('Time step',fontsize=18)
45 | plt.ylabel('Energy',fontsize=18)
46 |
47 | #===============================================================================
48 | # Particle kinetic energies
49 |
50 | # Electrons
51 | ekineb=numpy.loadtxt(".././Zeltron2D/data/Ekin_electrons_bg.dat")
52 | ekined=numpy.loadtxt(".././Zeltron2D/data/Ekin_electrons_drift.dat")
53 |
54 | # Ions
55 | ekinpb=numpy.loadtxt(".././Zeltron2D/data/Ekin_ions_bg.dat")
56 | ekinpd=numpy.loadtxt(".././Zeltron2D/data/Ekin_ions_drift.dat")
57 |
58 | plt.plot(ekineb+ekined+ekinpb+ekinpd,ls='--',lw=2,color='green')
59 |
60 | #===============================================================================
61 | # Radiative energies
62 |
63 | # Synchrotron
64 | # Electrons
65 | esyne=numpy.loadtxt(".././Zeltron2D/data/Esyn_electrons.dat")
66 | # Ions
67 | esynp=numpy.loadtxt(".././Zeltron2D/data/Esyn_electrons.dat")
68 |
69 | plt.plot(esyne+esynp,ls='--',lw=2,color='magenta')
70 |
71 | # Inverse Compton
72 | # Electrons
73 | eicse=numpy.loadtxt(".././Zeltron2D/data/Eics_electrons.dat")
74 | # Ions
75 | eicsp=numpy.loadtxt(".././Zeltron2D/data/Eics_electrons.dat")
76 |
77 | plt.plot(eicse+eicsp,ls=':',lw=2,color='magenta')
78 |
79 | #===============================================================================
80 | # Total energy
81 |
82 | etot=emag+eelc+ekineb+ekined+ekinpb+ekinpd+esyne+esynp+eicse+eicsp
83 | plt.plot(etot,ls='-',lw=3,color='black')
84 |
85 | error=(etot[len(etot)-1]-etot[0])/etot[0]*100.0
86 |
87 | # Relative error
88 | print ""
89 | print "********************************"
90 | print "Total energy relative error:"
91 | print error,"%"
92 | print "********************************"
93 |
94 | # Plot legend
95 | pylab.legend(('Magnetic','Electric','Particles','Synchrotron','Inv. Compton','Total'),shadow=False,loc=(0.65,0.27))
96 | ltext = pylab.gca().get_legend().get_texts()
97 | pylab.setp(ltext[0],fontsize=15)
98 | pylab.setp(ltext[1],fontsize=15)
99 | pylab.setp(ltext[2],fontsize=15)
100 | pylab.setp(ltext[3],fontsize=15)
101 | pylab.setp(ltext[4],fontsize=15)
102 | pylab.setp(ltext[5],fontsize=15)
103 |
104 | plt.title("Error= %+2.3f " % error + "%", fontsize=20)
105 |
106 | #===============================================================================
107 |
108 | plt.show()
109 |
110 | #===============================================================================
111 |
112 | energy()
113 |
--------------------------------------------------------------------------------
/plot2D/plot_current.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw any component of the total current density
21 | # or the total charge density along with the in-plane magnetic field lines
22 | # as function of x and y, at a given time step it.
23 | #
24 | # To execute, type for instance:$ python plot_current.py 0 Jz &
25 | # This command will draw the strength of Jz at time step 0.
26 | #
27 | #***********************************************************************!
28 |
29 | import numpy
30 | import math
31 | import matplotlib.pyplot as plt
32 | import sys
33 |
34 | def plot_current(it,current):
35 |
36 | if it=='':
37 | it='0'
38 |
39 | if current=='':
40 | current='Jx'
41 |
42 | #===============================================================================
43 | # Parameters of the simulation
44 |
45 | params1=numpy.loadtxt(".././Zeltron2D/data/phys_params.dat",skiprows=1)
46 | params2=numpy.loadtxt(".././Zeltron2D/data/input_params.dat",skiprows=1)
47 |
48 | # Nominal Larmor radius
49 | rho=2.9979246e+10/params1[3]
50 |
51 | #===============================================================================
52 | # The grid
53 | x=numpy.loadtxt(".././Zeltron2D/data/xfield.dat")
54 | y=numpy.loadtxt(".././Zeltron2D/data/yfield.dat")
55 |
56 | # The current density
57 | rhoJe=numpy.loadtxt(".././Zeltron2D/data/currents/"+current+"_electrons"+it+".dat")
58 | rhoJi=numpy.loadtxt(".././Zeltron2D/data/currents/"+current+"_ions"+it+".dat")
59 |
60 | rhoJ=rhoJe+rhoJi
61 |
62 | plt.pcolormesh(x/rho,y/rho,rhoJ)
63 | plt.xlabel(r'$x/\rho$',fontsize=18)
64 | plt.ylabel(r'$y/\rho$',fontsize=18)
65 |
66 | plt.colorbar().ax.set_ylabel(current,fontsize=18)
67 |
68 | plt.title("Time step="+it+", Current="+current,fontsize=18)
69 |
70 | #===============================================================================
71 | # Plotting magnetic field lines
72 |
73 | # The fields
74 | Bx=numpy.loadtxt(".././Zeltron2D/data/fields/Bx"+it+".dat")
75 | By=numpy.loadtxt(".././Zeltron2D/data/fields/By"+it+".dat")
76 |
77 | # The magnetic flux function
78 | psi=numpy.empty((len(y),len(x)))
79 |
80 | dx=x[1]-x[0]
81 | dy=y[1]-y[0]
82 |
83 | for iy in range(0,len(y)-1):
84 | psi[iy+1,0]=psi[iy,0]+Bx[iy,0]*dy
85 |
86 | for ix in range(0,len(x)-1):
87 | psi[iy,ix+1]=psi[iy,ix]-By[iy,ix]*dx
88 |
89 | # Periodic boundary conditions
90 | psi[:,len(x)-1]=psi[:,0]
91 | psi[len(y)-1,:]=psi[0,:]
92 |
93 | # To set the negative contour as solid lines (dashed is default)
94 | plt.rcParams['contour.negative_linestyle']='solid'
95 | plt.contour(x/rho,y/rho,psi,25,lw=1.0,colors='white')
96 |
97 | #===============================================================================
98 |
99 | plt.show()
100 |
101 | #===============================================================================
102 |
103 | plot_current(sys.argv[1],sys.argv[2])
104 |
--------------------------------------------------------------------------------
/plot2D/plot_density.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the electron or ion density and the
21 | # in-plane magnetic field lines as function of x and y, at a given time
22 | # step it.
23 | #
24 | # To execute, type for instance:$ python plot_density.py 0 ions &
25 | # This command will draw the ions density at time step 0.
26 | #
27 | #***********************************************************************!
28 |
29 | import numpy
30 | import math
31 | import matplotlib.pyplot as plt
32 | import sys
33 |
34 | def plot_density(it,spec):
35 |
36 | if it=='':
37 | it='0'
38 |
39 | if spec=='':
40 | spec='electrons'
41 |
42 | #===============================================================================
43 | # Parameters of the simulation
44 |
45 | params1=numpy.loadtxt(".././Zeltron2D/data/phys_params.dat",skiprows=1)
46 | params2=numpy.loadtxt(".././Zeltron2D/data/input_params.dat",skiprows=1)
47 |
48 | # Nominal Larmor radius
49 | rho=2.9979246e+10/params1[3]
50 |
51 | #===============================================================================
52 | # The grid
53 | x=numpy.loadtxt(".././Zeltron2D/data/x.dat")
54 | y=numpy.loadtxt(".././Zeltron2D/data/y.dat")
55 |
56 | # The density
57 | mapxy0=numpy.loadtxt(".././Zeltron2D/data/densities/mapxy_"+spec+"_drift0.dat")
58 | map_bg=numpy.loadtxt(".././Zeltron2D/data/densities/mapxy_"+spec+"_bg"+it+".dat")
59 | map_drift=numpy.loadtxt(".././Zeltron2D/data/densities/mapxy_"+spec+"_drift"+it+".dat")
60 |
61 | mapxy=(map_bg+map_drift)/numpy.max(mapxy0)
62 |
63 | plt.pcolormesh(x/rho,y/rho,mapxy)
64 | plt.xlabel(r'$x/\rho$',fontsize=18)
65 | plt.ylabel(r'$y/\rho$',fontsize=18)
66 |
67 | plt.colorbar().ax.set_ylabel(r'$n/n_0$',fontsize=18)
68 |
69 | plt.title("Time step="+it+", Species="+spec,fontsize=18)
70 |
71 | #===============================================================================
72 | # Plotting magnetic field lines
73 |
74 | xf=numpy.loadtxt(".././Zeltron2D/data/xfield.dat")
75 | yf=numpy.loadtxt(".././Zeltron2D/data/yfield.dat")
76 |
77 | # The fields
78 | Bx=numpy.loadtxt(".././Zeltron2D/data/fields/Bx"+it+".dat")
79 | By=numpy.loadtxt(".././Zeltron2D/data/fields/By"+it+".dat")
80 |
81 | # The magnetic flux function
82 | psi=numpy.empty((len(yf),len(xf)))
83 |
84 | dx=xf[1]-xf[0]
85 | dy=yf[1]-yf[0]
86 |
87 | for iy in range(0,len(yf)-1):
88 | psi[iy+1,0]=psi[iy,0]+Bx[iy,0]*dy
89 |
90 | for ix in range(0,len(xf)-1):
91 | psi[iy,ix+1]=psi[iy,ix]-By[iy,ix]*dx
92 |
93 | # Periodic boundary conditions
94 | psi[:,len(xf)-1]=psi[:,0]
95 | psi[len(yf)-1,:]=psi[0,:]
96 |
97 | # To set the negative contour as solid lines (dashed is default)
98 | plt.rcParams['contour.negative_linestyle']='solid'
99 | plt.contour(xf/rho,yf/rho,psi,25,lw=1.0,colors='white')
100 |
101 | #===============================================================================
102 |
103 | plt.show()
104 |
105 | #===============================================================================
106 |
107 | plot_density(sys.argv[1],sys.argv[2])
108 |
--------------------------------------------------------------------------------
/plot2D/plot_field.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw any component of the E or B field along
21 | # with the in-plane magnetic field lines as function of x and y, at a
22 | # given time step it.
23 | #
24 | # To execute, type for instance:$ python plot_field.py 0 Bx &
25 | # This command will draw the strength of Bx at time step 0.
26 | #
27 | #***********************************************************************!
28 |
29 | import numpy
30 | import math
31 | import matplotlib.pyplot as plt
32 | import sys
33 |
34 | def plot_field(it,field):
35 |
36 | if it=='':
37 | it='0'
38 |
39 | if field=='':
40 | field='Bx'
41 |
42 | #===============================================================================
43 | # Parameters of the simulation
44 |
45 | params1=numpy.loadtxt(".././Zeltron2D/data/phys_params.dat",skiprows=1)
46 | params2=numpy.loadtxt(".././Zeltron2D/data/input_params.dat",skiprows=1)
47 |
48 | # Nominal Larmor radius
49 | rho=2.9979246e+10/params1[3]
50 |
51 | # Upstream reconnecting magnetic field
52 | B0=params1[2]
53 |
54 | #===============================================================================
55 | # The grid
56 | x=numpy.loadtxt(".././Zeltron2D/data/xfield.dat")
57 | y=numpy.loadtxt(".././Zeltron2D/data/yfield.dat")
58 |
59 | # The field
60 | mapxy=numpy.loadtxt(".././Zeltron2D/data/fields/"+field+it+".dat")
61 |
62 | plt.pcolormesh(x/rho,y/rho,mapxy/B0)
63 | plt.xlabel(r'$x/\rho$',fontsize=18)
64 | plt.ylabel(r'$y/\rho$',fontsize=18)
65 |
66 | plt.colorbar().ax.set_ylabel(field+r'$/B_0$',fontsize=18)
67 |
68 | plt.title("Time step="+it+", Field="+field,fontsize=18)
69 |
70 | #===============================================================================
71 | # Plotting magnetic field lines
72 |
73 | # The fields
74 | Bx=numpy.loadtxt(".././Zeltron2D/data/fields/Bx"+it+".dat")
75 | By=numpy.loadtxt(".././Zeltron2D/data/fields/By"+it+".dat")
76 |
77 | # The magnetic flux function
78 | psi=numpy.empty((len(y),len(x)))
79 |
80 | dx=x[1]-x[0]
81 | dy=y[1]-y[0]
82 |
83 | for iy in range(0,len(y)-1):
84 | psi[iy+1,0]=psi[iy,0]+Bx[iy,0]*dy
85 |
86 | for ix in range(0,len(x)-1):
87 | psi[iy,ix+1]=psi[iy,ix]-By[iy,ix]*dx
88 |
89 | # Periodic boundary conditions
90 | psi[:,len(x)-1]=psi[:,0]
91 | psi[len(y)-1,:]=psi[0,:]
92 |
93 | # To set the negative contour as solid lines (dashed is default)
94 | plt.rcParams['contour.negative_linestyle']='solid'
95 | plt.contour(x/rho,y/rho,psi,25,lw=1.0,colors='white')
96 |
97 | #===============================================================================
98 |
99 | plt.show()
100 |
101 | #===============================================================================
102 |
103 | plot_field(sys.argv[1],sys.argv[2])
104 |
--------------------------------------------------------------------------------
/plot2D/plot_spectrum.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the total electron or ion energy spectrum:
21 | # dN/du(u), where u is the 4 velocity, at a given time step it.
22 | #
23 | # To execute, type for instance:$ python plot_spectrum.py 0 ions &
24 | # This command will draw the ions spectrum at time step 0.
25 | #
26 | #***********************************************************************!
27 |
28 | import matplotlib
29 | import numpy
30 | import math
31 | import matplotlib.pyplot as plt
32 | import sys
33 |
34 | def plot_spectrum(it,spec):
35 |
36 | if it=='':
37 | it='0'
38 |
39 | if spec=='':
40 | spec='electrons'
41 |
42 | #===============================================================================
43 | # 4-velocity
44 | u=numpy.loadtxt(".././Zeltron2D/data/u.dat")
45 | u=u[0:len(u)-1]
46 |
47 | # Spectrum
48 | dNdud=numpy.loadtxt(".././Zeltron2D/data/spectrum_"+spec+"_drift"+it+".dat")
49 | dNdub=numpy.loadtxt(".././Zeltron2D/data/spectrum_"+spec+"_bg"+it+".dat")
50 |
51 | # Total spectrum
52 | dNdu=dNdud+dNdub
53 |
54 | plt.plot(u,dNdu,color='blue',lw=2)
55 | plt.xscale('log')
56 | plt.yscale('log')
57 |
58 | plt.xlabel(r'$\gamma\beta$',fontsize=20)
59 | plt.ylabel(r'$\frac{dN}{d(\gamma\beta)}$',fontsize=20)
60 | plt.ylim([1e-3*numpy.max(dNdu),3.0*numpy.max(dNdu)])
61 |
62 | plt.title("Time step="+it+", Species="+spec, fontsize=18)
63 |
64 | #===============================================================================
65 |
66 | plt.show()
67 |
68 | #===============================================================================
69 |
70 | plot_spectrum(sys.argv[1],sys.argv[2])
71 |
--------------------------------------------------------------------------------
/plot2D/timestep.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the duration of each time step as a
21 | # function of time.
22 | #
23 | # To execute, type for instance:$ python timestep.py &
24 | #
25 | #***********************************************************************!
26 |
27 | import numpy
28 | import math
29 | import matplotlib.pyplot as plt
30 |
31 | def timestep():
32 |
33 | #===============================================================================
34 | time=numpy.loadtxt(".././Zeltron2D/data/timestep.dat")
35 |
36 | plt.plot(time,color='blue',lw=2)
37 | plt.yscale('log')
38 |
39 | plt.xlabel('Time step',fontsize=18)
40 | plt.ylabel('Duration time step [s]',fontsize=18)
41 |
42 | average=numpy.mean(time)
43 |
44 | plt.plot([0,len(time)],[average,average],lw=2,ls='--',color='black')
45 |
46 | print ""
47 | print "********************************"
48 | print "Average: ", average," seconds"
49 | print "********************************"
50 |
51 | plt.title("Average time step = %2.3f " % average + "seconds", fontsize=20)
52 |
53 | #===============================================================================
54 |
55 | plt.show()
56 |
57 | #===============================================================================
58 |
59 | timestep()
60 |
--------------------------------------------------------------------------------
/plot3D/energy.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the total magnetic, electric, particle,
21 | # and radiative energies as a function of time.
22 | #
23 | # To execute, type for instance:$ python energy.py &
24 | #
25 | #***********************************************************************!
26 |
27 | import numpy
28 | import math
29 | import matplotlib.pyplot as plt
30 | import pylab
31 |
32 | def energy():
33 |
34 | #===============================================================================
35 | # Magnetic and electric energies
36 |
37 | data=numpy.loadtxt(".././Zeltron3D/data/Eem.dat")
38 | emag=data[:,0]
39 | eelc=data[:,1]
40 |
41 | plt.plot(emag,color='blue',lw=2)
42 | plt.plot(eelc,color='red',lw=2)
43 |
44 | plt.xlabel('Time step',fontsize=18)
45 | plt.ylabel('Energy',fontsize=18)
46 |
47 | #===============================================================================
48 | # Particle kinetic energies
49 |
50 | # Electrons
51 | ekineb=numpy.loadtxt(".././Zeltron3D/data/Ekin_electrons_bg.dat")
52 | ekined=numpy.loadtxt(".././Zeltron3D/data/Ekin_electrons_drift.dat")
53 |
54 | # Ions
55 | ekinpb=numpy.loadtxt(".././Zeltron3D/data/Ekin_ions_bg.dat")
56 | ekinpd=numpy.loadtxt(".././Zeltron3D/data/Ekin_ions_drift.dat")
57 |
58 | plt.plot(ekineb+ekined+ekinpb+ekinpd,ls='--',lw=2,color='green')
59 |
60 | #===============================================================================
61 | # Radiative energies
62 |
63 | # Synchrotron
64 | # Electrons
65 | esyne=numpy.loadtxt(".././Zeltron3D/data/Esyn_electrons.dat")
66 | # Ions
67 | esynp=numpy.loadtxt(".././Zeltron3D/data/Esyn_electrons.dat")
68 |
69 | plt.plot(esyne+esynp,ls='--',lw=2,color='magenta')
70 |
71 | # Inverse Compton
72 | # Electrons
73 | eicse=numpy.loadtxt(".././Zeltron3D/data/Eics_electrons.dat")
74 | # Ions
75 | eicsp=numpy.loadtxt(".././Zeltron3D/data/Eics_electrons.dat")
76 |
77 | plt.plot(eicse+eicsp,ls=':',lw=2,color='magenta')
78 |
79 | #===============================================================================
80 | # Total energy
81 |
82 | etot=emag+eelc+ekineb+ekined+ekinpb+ekinpd+esyne+esynp+eicse+eicsp
83 | plt.plot(etot,ls='-',lw=3,color='black')
84 |
85 | error=(etot[len(etot)-1]-etot[0])/etot[0]*100.0
86 |
87 | # Relative error
88 | print ""
89 | print "********************************"
90 | print "Total energy relative error:"
91 | print error,"%"
92 | print "********************************"
93 |
94 | # Plot legend
95 | pylab.legend(('Magnetic','Electric','Particles','Synchrotron','Inv. Compton','Total'),shadow=False,loc=(0.65,0.27))
96 | ltext = pylab.gca().get_legend().get_texts()
97 | pylab.setp(ltext[0],fontsize=15)
98 | pylab.setp(ltext[1],fontsize=15)
99 | pylab.setp(ltext[2],fontsize=15)
100 | pylab.setp(ltext[3],fontsize=15)
101 | pylab.setp(ltext[4],fontsize=15)
102 | pylab.setp(ltext[5],fontsize=15)
103 |
104 | plt.title("Error= %+2.3f " % error + "%", fontsize=20)
105 |
106 | #===============================================================================
107 |
108 | plt.show()
109 |
110 | #===============================================================================
111 |
112 | energy()
113 |
--------------------------------------------------------------------------------
/plot3D/plot3D_current.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw any component of the total current density
21 | # or the total charge density in 3D (isosurfaces) as function of x, y, z,
22 | # at a given time step it.
23 | #
24 | # To execute, type for instance:$ python plot3D_current.py 0 Jz &
25 | # This command will draw the strength of Jz at time step 0.
26 | #
27 | # Notice: You need the Mayavi library to run this script
28 | #***********************************************************************!
29 |
30 | import numpy
31 | import math
32 | from mayavi.mlab import *
33 | from mayavi import mlab
34 | import sys
35 |
36 | def plot3D_current(it,current):
37 |
38 | if it=='':
39 | it='0'
40 |
41 | if current=='':
42 | current='Jx'
43 |
44 | #===============================================================================
45 | # Parameters of the simulation
46 |
47 | params1=numpy.loadtxt(".././Zeltron3D/data/phys_params.dat",skiprows=1)
48 | params2=numpy.loadtxt(".././Zeltron3D/data/input_params.dat",skiprows=1)
49 |
50 | # Nominal cyclotron frequency
51 | rho=2.9979246e+10/params1[3]
52 |
53 | #===============================================================================
54 | # The grid
55 | x=numpy.loadtxt(".././Zeltron3D/data/xfield.dat")
56 | y=numpy.loadtxt(".././Zeltron3D/data/yfield.dat")
57 | z=numpy.loadtxt(".././Zeltron3D/data/zfield.dat")
58 |
59 | # The current
60 | rhoJe=numpy.loadtxt(".././Zeltron3D/data/currents/"+current+"_electrons"+it+".dat")
61 | rhoJi=numpy.loadtxt(".././Zeltron3D/data/currents/"+current+"_ions"+it+".dat")
62 |
63 | nx=len(x)
64 | ny=len(y)
65 | nz=len(z)
66 |
67 | dx,ptx=x[1]-x[0],nx*1j
68 | dy,pty=y[1]-y[0],ny*1j
69 | dz,ptz=z[1]-z[0],nz*1j
70 |
71 | x,y,z=numpy.ogrid[-dx:dx:ptx,-dy:dy:pty,-dz:dz:ptz]
72 |
73 | mapxyz=numpy.empty((nx,ny,nz))
74 |
75 | for ix in range(0,nx):
76 | for iy in range(0,ny):
77 | for iz in range(0,nz):
78 | mapxyz[ix,iy,iz]=rhoJe[iy+iz*ny,ix]+rhoJi[iy+iz*ny,ix]
79 |
80 | contour3d(mapxyz,contours=10,transparent=True,opacity=0.9)
81 | mlab.outline()
82 | mlab.colorbar(title=current,orientation='vertical',nb_labels=10)
83 | mlab.axes()
84 | mlab.title("Time="+it+", "+current)
85 |
86 | #===============================================================================
87 |
88 | mlab.show()
89 |
90 | #===============================================================================
91 |
92 | plot3D_current(sys.argv[1],sys.argv[2])
93 |
--------------------------------------------------------------------------------
/plot3D/plot3D_density.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the 3D electron or ion density isosurfaces
21 | # as function of x, y, z, at a given time step it.
22 | #
23 | # To execute, type for instance:$ python plot3D_density.py 0 ions &
24 | # This command will draw the 3D ions density at time step 0.
25 | #
26 | # Notice: You need the Mayavi library to run this script
27 | #***********************************************************************!
28 |
29 | import numpy
30 | import math
31 | from mayavi.mlab import *
32 | from mayavi import mlab
33 | import sys
34 |
35 | def plot3D_density(it,spec):
36 |
37 | if it=='':
38 | it='0'
39 |
40 | if spec=='':
41 | spec='electrons'
42 |
43 | #===============================================================================
44 | # Parameters of the simulation
45 |
46 | params1=numpy.loadtxt(".././Zeltron3D/data/phys_params.dat",skiprows=1)
47 | params2=numpy.loadtxt(".././Zeltron3D/data/input_params.dat",skiprows=1)
48 |
49 | # Nominal cyclotron frequency
50 | rho=2.9979246e+10/params1[3]
51 |
52 | #===============================================================================
53 | # The grid
54 | x=numpy.loadtxt(".././Zeltron3D/data/x.dat")
55 | y=numpy.loadtxt(".././Zeltron3D/data/y.dat")
56 | z=numpy.loadtxt(".././Zeltron3D/data/z.dat")
57 |
58 | # The density
59 | map0=numpy.loadtxt(".././Zeltron3D/data/densities/mapxyz_"+spec+"_drift0.dat")
60 | mapd=numpy.loadtxt(".././Zeltron3D/data/densities/mapxyz_"+spec+"_drift"+it+".dat")
61 | mapb=numpy.loadtxt(".././Zeltron3D/data/densities/mapxyz_"+spec+"_bg"+it+".dat")
62 |
63 | nx=len(x)-1
64 | ny=len(y)-1
65 | nz=len(z)-1
66 |
67 | dx,ptx=x[1]-x[0],nx*1j
68 | dy,pty=y[1]-y[0],ny*1j
69 | dz,ptz=z[1]-z[0],nz*1j
70 |
71 | x,y,z=numpy.ogrid[-dx:dx:ptx,-dy:dy:pty,-dz:dz:ptz]
72 |
73 | mapxyz=numpy.empty((nx,ny,nz))
74 |
75 | for ix in range(0,nx):
76 | for iy in range(0,ny):
77 | for iz in range(0,nz):
78 | mapxyz[ix,iy,iz]=mapd[iy+iz*ny,ix]+mapb[iy+iz*ny,ix]
79 |
80 | mapxyz=mapxyz/numpy.max(map0)
81 |
82 | contour3d(mapxyz,contours=10,transparent=True,opacity=0.9)
83 | mlab.outline()
84 | mlab.colorbar(title='n/n0',orientation='vertical',nb_labels=10)
85 | mlab.axes()
86 | mlab.title("Time="+it+", "+spec)
87 |
88 | #===============================================================================
89 |
90 | mlab.show()
91 |
92 | #===============================================================================
93 |
94 | plot3D_density(sys.argv[1],sys.argv[2])
95 |
--------------------------------------------------------------------------------
/plot3D/plot3D_field.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw any component of the E or B field in 3D
21 | # (isosurfaces) as function of x, y, z, at a given time step it.
22 | #
23 | # To execute, type for instance:$ python plot3D_field.py 0 Bx &
24 | # This command will draw the strength of Bx at time step 0.
25 | #
26 | # Notice: You need the Mayavi library to run this script
27 | #***********************************************************************!
28 |
29 | import numpy
30 | import math
31 | from mayavi.mlab import *
32 | from mayavi import mlab
33 | import sys
34 |
35 | def plot3D_field(it,field):
36 |
37 | if it=='':
38 | it='0'
39 |
40 | if field=='':
41 | field='Bx'
42 |
43 | #===============================================================================
44 | # Parameters of the simulation
45 |
46 | params1=numpy.loadtxt(".././Zeltron3D/data/phys_params.dat",skiprows=1)
47 | params2=numpy.loadtxt(".././Zeltron3D/data/input_params.dat",skiprows=1)
48 |
49 | # Nominal cyclotron frequency
50 | rho=2.9979246e+10/params1[3]
51 |
52 | # Upstream magnetic field
53 | B0=params1[2]
54 |
55 | #===============================================================================
56 | # The grid
57 | x=numpy.loadtxt(".././Zeltron3D/data/xfield.dat")
58 | y=numpy.loadtxt(".././Zeltron3D/data/yfield.dat")
59 | z=numpy.loadtxt(".././Zeltron3D/data/zfield.dat")
60 |
61 | # The Field
62 | map_temp=numpy.loadtxt(".././Zeltron3D/data/fields/"+field+it+".dat")
63 |
64 | nx=len(x)
65 | ny=len(y)
66 | nz=len(z)
67 |
68 | dx,ptx=x[1]-x[0],nx*1j
69 | dy,pty=y[1]-y[0],ny*1j
70 | dz,ptz=z[1]-z[0],nz*1j
71 |
72 | x,y,z=numpy.ogrid[-dx:dx:ptx,-dy:dy:pty,-dz:dz:ptz]
73 |
74 | mapxyz=numpy.empty((nx,ny,nz))
75 |
76 | for ix in range(0,nx):
77 | for iy in range(0,ny):
78 | for iz in range(0,nz):
79 | mapxyz[ix,iy,iz]=map_temp[iy+iz*ny,ix]
80 |
81 | mapxyz=mapxyz/B0
82 |
83 | contour3d(mapxyz,contours=10,transparent=True,opacity=0.9)
84 | mlab.outline()
85 | mlab.colorbar(title=field+'/B0',orientation='vertical',nb_labels=10)
86 | mlab.axes()
87 | mlab.title("Time="+it+", "+field)
88 |
89 | #===============================================================================
90 |
91 | mlab.show()
92 |
93 | #===============================================================================
94 |
95 | plot3D_field(sys.argv[1],sys.argv[2])
96 |
--------------------------------------------------------------------------------
/plot3D/plot_spectrum.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the total electron or ion energy spectrum:
21 | # dN/du(u), where u is the 4 velocity, at a given time step it.
22 | #
23 | # To execute, type for instance:$ python plot_spectrum.py 0 ions &
24 | # This command will draw the ions spectrum at time step 0.
25 | #
26 | #***********************************************************************!
27 |
28 | import matplotlib
29 | import numpy
30 | import math
31 | import matplotlib.pyplot as plt
32 | import sys
33 |
34 | def plot_spectrum(it,spec):
35 |
36 | if it=='':
37 | it='0'
38 |
39 | if spec=='':
40 | spec='electrons'
41 |
42 | #===============================================================================
43 | # 4-velocity
44 | u=numpy.loadtxt(".././Zeltron3D/data/u.dat")
45 | u=u[0:len(u)-1]
46 |
47 | # Spectrum
48 | dNdud=numpy.loadtxt(".././Zeltron3D/data/spectrum_"+spec+"_drift"+it+".dat")
49 | dNdub=numpy.loadtxt(".././Zeltron3D/data/spectrum_"+spec+"_bg"+it+".dat")
50 |
51 | # Total spectrum
52 | dNdu=dNdud+dNdub
53 |
54 | plt.plot(u,dNdu,color='blue',lw=2)
55 | plt.xscale('log')
56 | plt.yscale('log')
57 |
58 | plt.xlabel(r'$\gamma\beta$',fontsize=20)
59 | plt.ylabel(r'$\frac{dN}{d(\gamma\beta)}$',fontsize=20)
60 | plt.ylim([1e-3*numpy.max(dNdu),3.0*numpy.max(dNdu)])
61 |
62 | plt.title("Time step="+it+", Species="+spec, fontsize=18)
63 |
64 | #===============================================================================
65 |
66 | plt.show()
67 |
68 | #===============================================================================
69 |
70 | plot_spectrum(sys.argv[1],sys.argv[2])
71 |
--------------------------------------------------------------------------------
/plot3D/timestep.py:
--------------------------------------------------------------------------------
1 | #***********************************************************************!
2 | # The Zeltron code project. !
3 | #***********************************************************************!
4 | # Copyright (C) 2012-2015. Authors: Benoit Cerutti & Greg Werner !
5 | # !
6 | # This program is free software: you can redistribute it and/or modify !
7 | # it under the terms of the GNU General Public License as published by !
8 | # the Free Software Foundation, either version 3 of the License, or !
9 | # (at your option) any later version. !
10 | # !
11 | # This program is distributed in the hope that it will be useful, !
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of !
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !
14 | # GNU General Public License for more details. !
15 | # !
16 | # You should have received a copy of the GNU General Public License !
17 | # along with this program. If not, see . !
18 | #***********************************************************************!
19 | #
20 | # This python script will draw the duration of each time step as a
21 | # function of time.
22 | #
23 | # To execute, type for instance:$ python timestep.py &
24 | #
25 | #***********************************************************************!
26 |
27 | import numpy
28 | import math
29 | import matplotlib.pyplot as plt
30 |
31 | def timestep():
32 |
33 | #===============================================================================
34 | time=numpy.loadtxt(".././Zeltron3D/data/timestep.dat")
35 |
36 | plt.plot(time,color='blue',lw=2)
37 | plt.yscale('log')
38 |
39 | plt.xlabel('Time step',fontsize=18)
40 | plt.ylabel('Duration time step [s]',fontsize=18)
41 |
42 | average=numpy.mean(time)
43 |
44 | plt.plot([0,len(time)],[average,average],lw=2,ls='--',color='black')
45 |
46 | print ""
47 | print "********************************"
48 | print "Average: ", average," seconds"
49 | print "********************************"
50 |
51 | plt.title("Average time step = %2.3f " % average + "seconds", fontsize=20)
52 |
53 | #===============================================================================
54 |
55 | plt.show()
56 |
57 | #===============================================================================
58 |
59 | timestep()
60 |
--------------------------------------------------------------------------------