├── .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 | --------------------------------------------------------------------------------