diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a0191d0..df4150ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,12 +70,17 @@ set(EBIC ${EBICDEF} CACHE FILEPATH "CHIMP EB IC file") include(cmake/user.cmake OPTIONAL) if(ENABLE_MPI) - if(MPI_ADDRESS_SIZE) - # user is using MPI and over-riding MPI address size - add_compile_definitions(MPI_ADDRESS_SIZE=${MPI_ADDRESS_SIZE}) - message("Over-riding default MPI Address Size with new value of ${MPI_ADDRESS_SIZE}") + if(MPI_BASE_ADDR_SIZE) + add_compile_definitions(MPI_BASE_ADDR_SIZE=${MPI_BASE_ADDR_SIZE}) + message("Over-riding default MPI Address Size with new value of ${MPI_BASE_ADDR_SIZE} for basic MPI functions") else() - message("Using default MPI Address Size of MPI_ADDRESS_KIND") + message("Using default MPI Address Size of MPI_ADDRESS_KIND for basic MPI functions") + endif() + if(MPI_AN_ADDR_SIZE) + add_compile_definitions(MPI_AN_ADDR_SIZE=${MPI_AN_ADDR_SIZE}) + message("Over-riding default MPI Address Size with new value of ${MPI_AN_ADDR_SIZE} for neighborhood MPI functions") + else() + message("Using default MPI Address Size of MPI_ADDRESS_KIND for neighborhood MPI functions") endif() endif() diff --git a/analysis/notebooks/Tutorial/RBSP-Spectra.ipynb b/analysis/notebooks/Tutorial/RBSP-Spectra.ipynb new file mode 100644 index 00000000..f8ca867c --- /dev/null +++ b/analysis/notebooks/Tutorial/RBSP-Spectra.ipynb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac3a6ce828a6b7786d2b461d38e1b3278f2529cebe971a5eca652c5641547e74 +size 34734 diff --git a/cmake/compilers.cmake b/cmake/compilers.cmake index 09c9dee3..aa1c554c 100644 --- a/cmake/compilers.cmake +++ b/cmake/compilers.cmake @@ -112,5 +112,7 @@ if(ENABLE_MPI) endif() # no matching flag for GNU set(CMAKE_Fortran_COMPILER ${MPI_Fortran_COMPILER}) + # we changed compiler, link HDF5 libraries + link_libraries(${HDF5_Fortran_LIBRARIES} ${HDF5_Fortran_HL_LIBRARIES}) endif() diff --git a/scripts/XMLGenerator.py b/scripts/XMLGenerator.py deleted file mode 100644 index c4f093f4..00000000 --- a/scripts/XMLGenerator.py +++ /dev/null @@ -1,75 +0,0 @@ -import sys -import configparser -import xml.etree.ElementTree as ET - -# Found on Stack Overflow. -# This indents everything in the elem node properly since apparently etree doesn't do that on it's own... -def indent(elem, level=0): - i = "\n" + level*" " - if len(elem): - if not elem.text or not elem.text.strip(): - elem.text = i + " " - if not elem.tail or not elem.tail.strip(): - elem.tail = i - for elem in elem: - indent(elem, level+1) - if not elem.tail or not elem.tail.strip(): - elem.tail = i - else: - if level and (not elem.tail or not elem.tail.strip()): - elem.tail = i - -# Check number of command line arguments -if (len(sys.argv) < 2): - print("ERROR: Too few arguments") - exit() - -if (len(sys.argv) > 2): - print("ERROR: Too many arguments") - exit() - -# Get output file name -output = sys.argv[1] - -# Read in default settings -tree = ET.parse('voltron.xml') -root = tree.getroot() - -# Initilization -user = configparser.RawConfigParser() - -# Try to turn on case sensitivity -user.optionxform = lambda option: option - -# Read user-defined options in -user.read('voltron.ini') - -# Get all sections of user config file -sections = user.sections() - -# Go through the new settings and see if they match elements in the default -for element in sections: - # If tag appears, check sub-entries - if (root.find(element) is not None): - subelement = root.find(element) - print("I found " + element + " in the default tree") - # For each option in element, add that to the ETree element - for item in user.items(element): - subelement.set(item[0], item[1]) - # If tag does not appear, append new one to ETree - else: - print("I did not find " + element + " in the default tree") - tempElement = ET.Element(element) - # Go through the options and add them to a new element - item = user.items(element) - for item in user.items(element): - tempElement.set(item[0],item[1]) - - # Insert this new element at the end of the current section - root.insert(len(list(root)),tempElement) - -# Run root through the indentation function -indent(root) - -# Write the XML file -tree.write(output) diff --git a/scripts/XMLGenerator/XMLGenerator.py b/scripts/XMLGenerator/XMLGenerator.py new file mode 100644 index 00000000..04ae775a --- /dev/null +++ b/scripts/XMLGenerator/XMLGenerator.py @@ -0,0 +1,137 @@ +import sys +import configparser +import subprocess +import os +import xml.etree.ElementTree as ET +from xml.etree.ElementTree import Element + +# Found on Stack Overflow. +# This indents everything in the elem node properly since apparently etree doesn't do that on it's own... +def indent(elem, level=0): + i = "\n" + level*" " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + indent(elem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + +# Check number of command line arguments +if (len(sys.argv) < 4): + print("ERROR: Too few arguments") + exit() + +if (len(sys.argv) > 4): + print("ERROR: Too many arguments") + exit() + +# Get template file name +template = sys.argv[1] + +# Get settings file name +settings = sys.argv[2] + +# Get output file name +output = sys.argv[3] + +# Run Initialization for Settings +p1 = subprocess.Popen("python3 initialize.py " + settings, shell=True) +p1.wait() + +# Read in default settings for this template +tree = ET.parse(template) +templateRoot = tree.getroot() + +# Make a Parser +user = configparser.RawConfigParser() + +# Try to turn on case sensitivity +user.optionxform = lambda option: option + +# Go to Settings folder generated by initialize.py +os.chdir("Settings") + +inputDicts = {} + +# Iterate through each file there and make the root node the key for the resultant tree in a dictionary +for filename in os.listdir(): + user = configparser.RawConfigParser() + user.optionxform = lambda option: option + user.read(filename) + temp = filename.split('.') + newFileName = temp[0] + inputDicts[newFileName] = user + +#print(inputDicts) + +# Make bigger ETree by adding all roots as sub elements +top = Element('Kaiju') + +for key in inputDicts.keys(): + temp = Element(key) + ET.dump(temp) + for section in inputDicts[key].sections(): + deeperTemp = Element(section) + for option in inputDicts[key].options(section): + deeperTemp.set(option, inputDicts[key].get(section, option)) + ET.SubElement(temp, deeperTemp.tag, deeperTemp.attrib) + top.append(temp) + +ET.dump(top) + +# Go through the new settings and see if they match elements in the default +for child in top: + print(child.tag) + # Try to find that child tag in the default tree + if (templateRoot.find(child.tag) is not None): + # If it exists, go one level down and iterate through those nodes + firstLevel = templateRoot.find(child.tag) + for lower in child: + # Find the corresponding tag in the default + nextLevel = firstLevel.find(lower.tag) + print(nextLevel) + print(lower) + # Check if that tag exists. If not, just add it + if (nextLevel is not None): + for item in lower.keys(): + nextLevel.set(item, lower.get(item)) + else: + ET.SubElement(firstLevel, lower.tag, lower.attrib) + else: + # Else, just add that element to the root + templateRoot.insert(child) +# for key in child.keys(): +# # If tag appears, check sub-entries +# if (templateRoot.find(key) is not None): +# subelement = templateRoot.find(key) +# print("I found " + key + " in the default tree") +# # For each option in element, add that to the ETree element +# for item in key: +# subelement.set(item[0], item[1]) +# # If tag does not appear, append new one to ETree +# else: +# print("I did not find " + key + " in the default tree") +# tempElement = ET.Element(key) +# # Go through the options and add them to a new element +# for item in child: +# tempElement.set(item[0],item[1]) +# +# # Insert this new element at the end of the current section +# templateRoot.insert(len(list(templateRoot)),tempElement) + +# Run root through the indentation function +indent(templateRoot) + +os.chdir('..') + +# Write the XML file +tree.write(output) + +# Cleanup Settigns folder +subprocess.Popen("rm -rf Settings/", shell=True) diff --git a/scripts/XMLGenerator/initialize.py b/scripts/XMLGenerator/initialize.py new file mode 100644 index 00000000..c9850dd5 --- /dev/null +++ b/scripts/XMLGenerator/initialize.py @@ -0,0 +1,65 @@ +import sys +import os +from string import ascii_letters + +# Check number of arguments +if (len(sys.argv) < 2): + print("ERROR: Too few arguments") + exit() +elif (len(sys.argv) > 2): + print("ERROR: Too many arguments") + exit() + +# Set up whitelist for section names (letters only) +whiteList = set(ascii_letters) + +# Open up settings file +settings = sys.argv[1] # First argument is input file name + +# Create a sub-folder called "Parsed Settings", or something +os.system("mkdir Settings") + +# Go through the settings file and check for section flags +with open(settings, 'r') as file: + content = file.read() + +# Move to subfilder +os.chdir("Settings") + +# Put everything between section flags in it's own subfile in the created directory. +# The name should correspond to the section. +contentSplit = content.splitlines() + +# Create a temporary string to hold the temporary settings files +temporary = "" +name = ''.join(l for l in contentSplit[0] if l in whiteList) +contentSplit.pop(0) + +pos = -1 + +# Loop through the split file +for line in contentSplit: + pos += 1 + + if (len(line) < 1): + temporary = temporary + "\n" + # If there is a # at the beginning of the string + elif (line[0] == '#'): + # Then write file, change name, and reset temporary + tempFile = open(name + ".ini", "w") + tempFile.write(temporary) + tempFile.close() + name = ''.join(l for l in line if l in whiteList) + temporary = "" + elif (pos == (len(contentSplit) - 1)): + # Last one, add line then write everything out! + temporary = temporary + line + "\n" + tempFile = open(name + ".ini", "w") + tempFile.write(temporary) + tempFile.close() + else: + # Add line to temporary + temporary = temporary + line + "\n" + +print(contentSplit) + diff --git a/scripts/XMLGenerator/output.xml b/scripts/XMLGenerator/output.xml new file mode 100644 index 00000000..3d09beab --- /dev/null +++ b/scripts/XMLGenerator/output.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/voltron.ini b/scripts/XMLGenerator/settings.ini similarity index 79% rename from scripts/voltron.ini rename to scripts/XMLGenerator/settings.ini index 757fa1ec..b21381b0 100644 --- a/scripts/voltron.ini +++ b/scripts/XMLGenerator/settings.ini @@ -1,3 +1,4 @@ +## VOLTRON ## [time] tFin = 3601.1 @@ -26,3 +27,11 @@ doQkSquish = T Test Value = 1 Other Test Value = 2 Third Test Value = hello + +## Gamera ## +[sim] +runid=junk + +## CHIMP ## +[units] +uid=MOREJUNK diff --git a/scripts/XMLGenerator/template0.xml b/scripts/XMLGenerator/template0.xml new file mode 100644 index 00000000..2b687e6b --- /dev/null +++ b/scripts/XMLGenerator/template0.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/voltron.xml b/scripts/voltron.xml deleted file mode 100644 index 0dd00d12..00000000 --- a/scripts/voltron.xml +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/src/base/mpi/mpidefs.F90 b/src/base/mpi/mpidefs.F90 index 2b60b846..0f72052d 100644 --- a/src/base/mpi/mpidefs.F90 +++ b/src/base/mpi/mpidefs.F90 @@ -7,10 +7,16 @@ module mpidefs integer, public :: MPI_MYFLOAT -#ifdef MPI_ADDRESS_SIZE - integer, parameter :: MPI_MYADDRESS = MPI_ADDRESS_SIZE +#ifdef MPI_BASE_ADDR_SIZE + integer, parameter :: MPI_BASE_MYADDR = MPI_BASE_ADDR_SIZE #else - integer, parameter :: MPI_MYADDRESS = MPI_ADDRESS_KIND ! this is the default + integer, parameter :: MPI_BASE_MYADDR = MPI_ADDRESS_KIND ! this is the default +#endif + +#ifdef MPI_AN_ADDR_SIZE + integer, parameter :: MPI_AN_MYADDR = MPI_AN_ADDR_SIZE +#else + integer, parameter :: MPI_AN_MYADDR = MPI_ADDRESS_KIND ! this is the default #endif contains @@ -37,7 +43,7 @@ contains integer :: numInts, numAdds, numDTs, combiner, ierr, i integer, dimension(:), allocatable :: arrayInts, arrayDTs - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: arrayAdds + integer(kind=MPI_BASE_MYADDR), dimension(:), allocatable :: arrayAdds call mpi_type_get_envelope(datatype, numInts, numAdds, numDTs, combiner, ierr) SELECT CASE(combiner) diff --git a/src/base/types/volttypes.F90 b/src/base/types/volttypes.F90 index 28690604..d6a1efee 100644 --- a/src/base/types/volttypes.F90 +++ b/src/base/types/volttypes.F90 @@ -145,10 +145,10 @@ module volttypes integer :: imType = 0 !Type of inner magnetosphere model (0 = None) integer :: prType = 0 !Type of projection for coupling (0 = None) logical :: doQkSquish = .false. !Whether or not to do fast squishing + integer :: qkSquishStride = 2 ! Stride to use when fast squishing !Dynamic coupling info logical :: doDynCplDT = .false. !Whether to do dynamic coupling cadence - integer :: qkSquishStride = 2 ! Stride to use when fast squishing end type voltApp_T diff --git a/src/drivers/voltron_mpix.F90 b/src/drivers/voltron_mpix.F90 index 49f88a52..d2494a51 100644 --- a/src/drivers/voltron_mpix.F90 +++ b/src/drivers/voltron_mpix.F90 @@ -224,7 +224,7 @@ program voltron_mpix endif !Restart output if (vApp%IO%doRestart(vApp%time)) then - call resOutputVOnly(vApp) + call resOutputVOnly(vApp,vApp%gAppLocal) endif !Data output if (vApp%IO%doOutput(vApp%time)) then diff --git a/src/gamera/gamapp.F90 b/src/gamera/gamapp.F90 index b1eafa75..5b58a59b 100644 --- a/src/gamera/gamapp.F90 +++ b/src/gamera/gamapp.F90 @@ -13,6 +13,7 @@ module gamapp type(Grid_T) :: Grid type(State_T) :: State, oState type(Solver_T) :: Solver + end type gamApp_T contains diff --git a/src/gamera/mpi/gamapp_mpi.F90 b/src/gamera/mpi/gamapp_mpi.F90 index 8e9eaf61..ba230766 100644 --- a/src/gamera/mpi/gamapp_mpi.F90 +++ b/src/gamera/mpi/gamapp_mpi.F90 @@ -19,12 +19,12 @@ module gamapp_mpi ! Gas Data Transfer Variables integer, dimension(:), allocatable :: sendCountsGas, sendTypesGas integer, dimension(:), allocatable :: recvCountsGas, recvTypesGas - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: sendDisplsGas, recvDisplsGas + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: sendDisplsGas, recvDisplsGas ! Magnetic Flux Data Transfer Variables integer, dimension(:), allocatable :: sendCountsMagFlux, sendTypesMagFlux integer, dimension(:), allocatable :: recvCountsMagFlux, recvTypesMagFlux - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: sendDisplsMagFlux, recvDisplsMagFlux + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: sendDisplsMagFlux, recvDisplsMagFlux ! Debugging flags logical :: printMagFluxFaceError = .false. @@ -1359,7 +1359,7 @@ module gamapp_mpi integer :: offsetI, offsetJ, offsetK, dataSum, ierr, dataSize logical :: anyMaxDim,sendSharedFace integer :: countArray(3) - integer(kind=MPI_MYADDRESS) :: offsetArray(3) + integer(kind=MPI_BASE_MYADDR) :: offsetArray(3) associate(Grid=>gamAppMpi%Grid,Model=>gamAppMpi%Model) @@ -1471,7 +1471,7 @@ module gamapp_mpi ! default counts and offsets countArray = (/1,1,1/) - offsetArray = (/integer(kind=MPI_MYADDRESS):: offsetI, offsetJ, offsetK /) + offsetArray = (/integer(kind=MPI_BASE_MYADDR):: offsetI, offsetJ, offsetK /) if(sendSharedFace) then ! this is only sending data for shared faces with an adjacent type if(iData /= 1) then @@ -1502,14 +1502,14 @@ module gamapp_mpi integer, intent(in) :: dType, offset integer :: ierr - integer(kind=MPI_MYADDRESS) :: tempOffsets(2) + integer(kind=MPI_BASE_MYADDR) :: tempOffsets(2) if(appendType == MPI_DATATYPE_NULL) then ! the root datatype is empty, just add the new type and offset call mpi_type_hindexed(1, (/ 1 /), (/ offset /), dType, appendType, ierr) else ! the root datatype already has defined structure, so merge with the new one into a struct - ! need to use a temporary array so that the ints are of type MPI_MYADDRESS + ! need to use a temporary array so that the ints are of type MPI_BASE_MYADDR tempOffsets = (/ 0, offset /) call mpi_type_create_struct(2, (/ 1, 1 /), tempOffsets, (/ appendType, dType /), appendType, ierr) endif diff --git a/src/voltron/mpi/gam2VoltComm_mpi.F90 b/src/voltron/mpi/gam2VoltComm_mpi.F90 index 76d80083..c72095db 100644 --- a/src/voltron/mpi/gam2VoltComm_mpi.F90 +++ b/src/voltron/mpi/gam2VoltComm_mpi.F90 @@ -21,17 +21,17 @@ module gam2VoltComm_mpi ! array of all zeroes to simplify various send/receive calls integer, dimension(1) :: zeroArrayCounts = (/ 0 /), zeroArrayTypes = (/ MPI_INT /) - integer(kind=MPI_MYADDRESS), dimension(1) :: zeroArrayDispls = (/ 0 /) + integer(kind=MPI_AN_MYADDR), dimension(1) :: zeroArrayDispls = (/ 0 /) ! SHALLOW COUPLING VARIABLES integer, dimension(1) :: sendCountsGasShallow, sendTypesGasShallow - integer(kind=MPI_MYADDRESS), dimension(1) :: sendDisplsGasShallow + integer(kind=MPI_AN_MYADDR), dimension(1) :: sendDisplsGasShallow integer, dimension(1) :: sendCountsBxyzShallow, sendTypesBxyzShallow - integer(kind=MPI_MYADDRESS), dimension(1) :: sendDisplsBxyzShallow + integer(kind=MPI_AN_MYADDR), dimension(1) :: sendDisplsBxyzShallow integer, dimension(1) :: recvCountsIneijkShallow, recvTypesIneijkShallow - integer(kind=MPI_MYADDRESS), dimension(1) :: recvDisplsIneijkShallow + integer(kind=MPI_AN_MYADDR), dimension(1) :: recvDisplsIneijkShallow integer, dimension(1) :: recvCountsInexyzShallow, recvTypesInexyzShallow - integer(kind=MPI_MYADDRESS), dimension(1) :: recvDisplsInexyzShallow + integer(kind=MPI_AN_MYADDR), dimension(1) :: recvDisplsInexyzShallow ! SHALLOW ASYNCHRONOUS VARIABLES integer :: shallowGasSendReq=MPI_REQUEST_NULL, shallowBxyzSendReq=MPI_REQUEST_NULL, shallowTimeBcastReq=MPI_REQUEST_NULL real(rp), dimension(:,:,:,:,:), allocatable :: gasBuffer @@ -39,11 +39,11 @@ module gam2VoltComm_mpi ! DEEP COUPLING VARIABLES integer, dimension(1) :: sendCountsGasDeep, sendTypesGasDeep - integer(kind=MPI_MYADDRESS), dimension(1) :: sendDisplsGasDeep + integer(kind=MPI_AN_MYADDR), dimension(1) :: sendDisplsGasDeep integer, dimension(1) :: sendCountsBxyzDeep, sendTypesBxyzDeep - integer(kind=MPI_MYADDRESS), dimension(1) :: sendDisplsBxyzDeep + integer(kind=MPI_AN_MYADDR), dimension(1) :: sendDisplsBxyzDeep integer, dimension(1) :: recvCountsGas0Deep, recvTypesGas0Deep - integer(kind=MPI_MYADDRESS), dimension(1) :: recvDisplsGas0Deep + integer(kind=MPI_AN_MYADDR), dimension(1) :: recvDisplsGas0Deep end type gam2VoltCommMpi_T diff --git a/src/voltron/mpi/voltapp_mpi.F90 b/src/voltron/mpi/voltapp_mpi.F90 index 9891db12..bfc924c9 100644 --- a/src/voltron/mpi/voltapp_mpi.F90 +++ b/src/voltron/mpi/voltapp_mpi.F90 @@ -83,7 +83,7 @@ module voltapp_mpi logical :: reorder, wasWeighted integer, allocatable, dimension(:) :: neighborRanks, inData, outData integer, allocatable, dimension(:) :: iRanks, jRanks, kRanks - integer(KIND=MPI_MYADDRESS) :: winsize + integer(KIND=MPI_BASE_MYADDR) :: winsize vApp%isSeparate = .true. ! running on a different process from the actual gamera ranks vApp%gAppLocal%Grid%lowMem = .true. ! tell Gamera to limit its memory usage @@ -309,22 +309,6 @@ module voltapp_mpi call initVoltron(vApp, vApp%gAppLocal) endif - ! receive current time information in case of a restart - if(vApp%gAppLocal%Model%isRestart) then - call mpi_recv(vApp%IO%nOut, 1, MPI_INT, MPI_ANY_SOURCE, 97520, vApp%voltMpiComm, MPI_STATUS_IGNORE, ierr) - call mpi_recv(vApp%IO%nRes, 1, MPI_INT, MPI_ANY_SOURCE, 97530, vApp%voltMpiComm, MPI_STATUS_IGNORE, ierr) - call mpi_recv(vApp%gAppLocal%Model%t, 1, MPI_MYFLOAT, MPI_ANY_SOURCE, 97540, vApp%voltMpiComm, MPI_STATUS_IGNORE, ierr) - call mpi_recv(vApp%gAppLocal%Model%ts, 1, MPI_INT, MPI_ANY_SOURCE, 97550, vApp%voltMpiComm, MPI_STATUS_IGNORE, ierr) - endif - - ! update voltron app time, MJD and ts values - call stepVoltron(vApp, vApp%gAppLocal) - - ! correct initial shallow time, which always starts immediately - vApp%ShallowT = vApp%time - ! Deep start time is user-defined and may not have occurred before restart - if(vApp%time > vApp%DeepT) vApp%DeepT = vApp%time - ! send all of the initial voltron parameters to the gamera ranks call mpi_bcast(vApp%time, 1, MPI_MYFLOAT, vApp%myRank, vApp%voltMpiComm, ierr) call mpi_bcast(vApp%tFin, 1, MPI_MYFLOAT, vApp%myRank, vApp%voltMpiComm, ierr) @@ -347,11 +331,6 @@ module voltapp_mpi ! receive updated gamera parameters from gamera rank call mpi_recv(vApp%gAppLocal%Model%dt0, 1, MPI_MYFLOAT, MPI_ANY_SOURCE, 97510, vApp%voltMpiComm, MPI_STATUS_IGNORE, ierr) - ! calculate what the next output and restart timing should be for gamera - if(vApp%gAppLocal%Model%isRestart) then - vApp%IO%tOut = floor(vApp%time/vApp%IO%dtOut)*vApp%IO%dtOut - vApp%IO%tRes = vApp%time + vApp%IO%dtRes - endif ! synchronize IO timing call mpi_bcast(vApp%IO%tOut/vApp%gAppLocal%Model%Units%gT0, & 1, MPI_MYFLOAT, vApp%myRank, vApp%voltMpiComm, ierr) diff --git a/src/voltron/mpi/volthelpers_mpi.F90 b/src/voltron/mpi/volthelpers_mpi.F90 index 65909ad3..d1ddd248 100644 --- a/src/voltron/mpi/volthelpers_mpi.F90 +++ b/src/voltron/mpi/volthelpers_mpi.F90 @@ -61,7 +61,7 @@ module volthelpers_mpi integer :: ierr, length character( len = MPI_MAX_ERROR_STRING) :: message - integer(KIND=MPI_MYADDRESS) :: disp + integer(KIND=MPI_BASE_MYADDR) :: disp ! lock the data window to set my status call mpi_win_lock(MPI_LOCK_EXCLUSIVE, 0, 0, vApp%vHelpWin, ierr) diff --git a/src/voltron/mpi/voltmpitypes.F90 b/src/voltron/mpi/voltmpitypes.F90 index 8bc01f0a..5600e668 100644 --- a/src/voltron/mpi/voltmpitypes.F90 +++ b/src/voltron/mpi/voltmpitypes.F90 @@ -25,7 +25,7 @@ module voltmpitypes ! array of all zeroes to simplify various send/receive calls integer, dimension(:), allocatable :: zeroArrayCounts, zeroArrayTypes - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: zeroArrayDispls + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: zeroArrayDispls ! list of gamera ranks to communicate with integer, dimension(:), allocatable :: sendRanks, recvRanks @@ -37,24 +37,24 @@ module voltmpitypes ! SHALLOW COUPLING VARIABLES integer, dimension(:), allocatable :: recvCountsGasShallow, recvTypesGasShallow - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: recvDisplsGasShallow + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: recvDisplsGasShallow integer, dimension(:), allocatable :: recvCountsBxyzShallow, recvTypesBxyzShallow - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: recvDisplsBxyzShallow + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: recvDisplsBxyzShallow integer, dimension(:), allocatable :: sendCountsIneijkShallow, sendTypesIneijkShallow - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: sendDisplsIneijkShallow + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: sendDisplsIneijkShallow integer, dimension(:), allocatable :: sendCountsInexyzShallow, sendTypesInexyzShallow - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: sendDisplsInexyzShallow + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: sendDisplsInexyzShallow ! SHALLOW ASYNCHRONOUS VARIABLES integer :: shallowIneijkSendReq=MPI_REQUEST_NULL, shallowInexyzSendReq=MPI_REQUEST_NULL integer :: asyncShallowBcastReq=MPI_REQUEST_NULL ! DEEP COUPLING VARIABLES integer, dimension(:), allocatable :: recvCountsGasDeep, recvTypesGasDeep - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: recvDisplsGasDeep + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: recvDisplsGasDeep integer, dimension(:), allocatable :: recvCountsBxyzDeep, recvTypesBxyzDeep - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: recvDisplsBxyzDeep + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: recvDisplsBxyzDeep integer, dimension(:), allocatable :: sendCountsGas0Deep, sendTypesGas0Deep - integer(kind=MPI_MYADDRESS), dimension(:), allocatable :: sendDisplsGas0Deep + integer(kind=MPI_AN_MYADDR), dimension(:), allocatable :: sendDisplsGas0Deep logical :: deepProcessingInProgress = .false. end type voltAppMpi_T diff --git a/src/voltron/voltapp.F90 b/src/voltron/voltapp.F90 index 0aca7923..265d1adf 100644 --- a/src/voltron/voltapp.F90 +++ b/src/voltron/voltapp.F90 @@ -32,7 +32,7 @@ module voltapp type(XML_Input_T) :: xmlInp type(TimeSeries_T) :: tsMJD real(rp) :: gTScl,tSpin,tIO - logical :: doSpin,doDelayIO + logical :: doSpin if(present(optFilename)) then ! read from the prescribed file @@ -67,9 +67,7 @@ module voltapp !Check for spinup info call xmlInp%Set_Val(doSpin,"spinup/doSpin",.true.) - tIO = 0.0 - doDelayIO = .false. - if (doSpin .and. (.not. gApp%Model%isRestart)) then + if (doSpin) then !Doing spinup and not a restart call xmlInp%Set_Val(tSpin,"spinup/tSpin",7200.0) !Default two hours !Rewind Gamera time to negative tSpin (seconds) @@ -77,44 +75,27 @@ module voltapp !Reset State/oState gApp% State%time = gApp%Model%t gApp%oState%time = gApp%Model%t-gApp%Model%dt - - doDelayIO = .true. - call xmlInp%Set_Val(tIO,"spinup/tIO",0.0) !Time of first restart endif - vApp%time = gApp%Model%t*gTScl !Time in seconds - vApp%ts = gApp%Model%ts !Timestep - !Use MJD from time series tsMJD%wID = vApp%tilt%wID call tsMJD%initTS("MJD",doLoudO=.false.) gApp%Model%MJD0 = tsMJD%evalAt(0.0_rp) !Evaluate at T=0 - vApp%MJD = T2MJD(vApp%time,gApp%Model%MJD0) - !Time options call xmlInp%Set_Val(vApp%tFin,'time/tFin',1.0_rp) !Sync Gamera to Voltron endtime gApp%Model%tFin = vApp%tFin/gTScl - !IO/Restart options - if (doDelayIO) then - call vApp%IO%init(xmlInp,tIO,vApp%ts) - else - call vApp%IO%init(xmlInp,vApp%time,vApp%ts) - endif + call vApp%IO%init(xmlInp,vApp%time,vApp%ts) !Pull numbering from Gamera - vApp%IO%nRes = gApp%Model%IO%nRes - vApp%IO%nOut = gApp%Model%IO%nOut vApp%IO%tsNext = gApp%Model%IO%tsNext !Force Gamera IO times to match Voltron IO call IOSync(vApp%IO,gApp%Model%IO,1.0/gTScl) !Shallow coupling - !Start shallow coupling immediately - vApp%ShallowT = vApp%time call xmlInp%Set_Val(vApp%ShallowDT ,"coupling/dt" , 0.1_rp) vApp%TargetShallowDT = vApp%ShallowDT call xmlInp%Set_Val(vApp%doGCM, "coupling/doGCM",.false.) @@ -124,7 +105,6 @@ module voltapp end if !Deep coupling - vApp%DeepT = 0.0_rp call xmlInp%Set_Val(vApp%DeepDT, "coupling/dtDeep", -1.0_rp) vApp%TargetDeepDT = vApp%DeepDT call xmlInp%Set_Val(vApp%rTrc, "coupling/rTrc" , 40.0) @@ -135,10 +115,45 @@ module voltapp vApp%doDeep = .false. endif - ! Deep enabled, not restart, not spinup is an error. Restart or spinup is required - if (vApp%doDeep .and. (.not. gApp%Model%isRestart) .and. (.not. doSpin) ) then - write(*,*) 'Spinup is required with deep coupling. Please enable the spinup/doSpin option. At least 1 minute of spinup is recommended.' - stop + if(gApp%Model%isRestart) then + call readVoltronRestart(vApp, xmlInp) + vApp%IO%tOut = floor(vApp%time/vApp%IO%dtOut)*vApp%IO%dtOut + vApp%IO%tRes = vApp%time + vApp%IO%dtRes + vApp%IO%tsNext = vApp%ts + if(vApp%isSeparate) then + gApp%Model%ts = vApp%ts + gApp%Model%t = vApp%time/gTScl + gApp% State%time = gApp%Model%t + gApp%oState%time = gApp%Model%t-gApp%Model%dt + endif + else + ! non-restart initialization + !Check for spinup info + call xmlInp%Set_Val(doSpin,"spinup/doSpin",.true.) + ! Deep enabled, not restart, not spinup is an error. Restart or spinup is required + if (vApp%doDeep .and. (.not. doSpin) ) then + write(*,*) 'Spinup is required with deep coupling. Please enable the spinup/doSpin option. At least 1 minute of spinup is recommended.' + stop + endif + if (doSpin) then + call xmlInp%Set_Val(tSpin,"spinup/tSpin",7200.0) !Default two hours + !Rewind Gamera time to negative tSpin (seconds) + gApp%Model%t = -tSpin/gTScl + !Reset State/oState + gApp% State%time = gApp%Model%t + gApp%oState%time = gApp%Model%t-gApp%Model%dt + call xmlInp%Set_Val(tIO,"spinup/tIO",gApp%Model%t*gTScl) !Time of first restart and output + gApp%Model%IO%tRes = tIO/gTScl + gApp%Model%IO%tOut = tIO/gTScl + vApp%IO%tRes = tIO + vApp%IO%tOut = tIO + endif + vApp%time = gApp%Model%t*gTScl !Time in seconds + vApp%ts = gApp%Model%ts !Timestep + vApp%MJD = T2MJD(vApp%time,gApp%Model%MJD0) + vApp%ShallowT = vApp%time ! shallow coupling immediately + !Set first deep coupling (defaulting to 0) + call xmlInp%Set_Val(vApp%DeepT, "coupling/tDeep", 0.0_rp) endif if (vApp%doDeep) then @@ -164,14 +179,7 @@ module voltapp write(*,*) 'Necessary CHIMP XML paramters not found, sort that out ...' stop endif - - !Set first deep coupling (defaulting to 0) - call xmlInp%Set_Val(vApp%DeepT, "coupling/tDeep", 0.0_rp) - - ! correct tDeep on restart for the serial version - ! mpi version corrects on its own in voltapp_mpi - if(.not. vApp%isSeparate .and. vApp%time > vApp%DeepT) vApp%DeepT = vApp%time - + !Initialize deep coupling type/inner magnetosphere model call InitInnerMag(vApp,gApp,xmlInp) endif @@ -307,7 +315,6 @@ module voltapp end subroutine initializeFromGamera - !---------- !Shallow coupling stuff subroutine ShallowUpdate(vApp, gApp, time) diff --git a/src/voltron/voltio.F90 b/src/voltron/voltio.F90 index bce31f9e..9de68fb5 100644 --- a/src/voltron/voltio.F90 +++ b/src/voltron/voltio.F90 @@ -171,12 +171,13 @@ module voltio call resOutput(gApp%Model,gApp%Grid,gApp%State) !Write Voltron restart data - call resOutputVOnly(vApp) + call resOutputVOnly(vApp,gApp) end subroutine resOutputV - subroutine resOutputVOnly(vApp) + subroutine resOutputVOnly(vApp, gApp) class(voltApp_T), intent(inout) :: vApp + class(gamApp_T) , intent(inout) :: gApp if (vApp%writeFiles) then call writeMIXRestart(vApp%remixApp%ion,vApp%IO%nRes,mjd=vApp%MJD,time=vApp%time) @@ -184,6 +185,7 @@ module voltio if (vApp%doDeep) then call vApp%imagApp%doRestart(vApp%IO%nRes,vApp%MJD,vApp%time) endif + call writeVoltRestart(vApp,gApp) endif if (vApp%time>vApp%IO%tRes) then @@ -193,6 +195,85 @@ module voltio end subroutine resOutputVOnly + subroutine writeVoltRestart(vApp,gApp) + class(voltApp_T), intent(in) :: vApp + class(gamApp_T) , intent(in) :: gApp + + character(len=strLen) :: ResF + type(IOVAR_T), dimension(MAXVOLTIOVAR) :: IOVars + + write (ResF, '(A,A,I0.5,A)') trim(gApp%Model%RunID), ".volt.Res.", vApp%IO%nRes, ".h5" + call CheckAndKill(ResF) + + call StampIO(ResF) + + call ClearIO(IOVars) + + !Main attributes + call AddOutVar(IOVars,"nOut",vApp%IO%nOut) + call AddOutVar(IOVars,"nRes",vApp%IO%nRes) + call AddOutVar(IOVars,"ts" ,vApp%ts) + call AddOutVar(IOVars,"MJD" ,vApp%MJD) + call AddOutVar(IOVars,"time",vApp%time) + + !Coupling info + call AddOutVar(IOVars,"ShallowT",vApp%ShallowT) + call AddOutVar(IOVars,"DeepT" ,vApp%DeepT) + + call WriteVars(IOVars,.false.,ResF) + + end subroutine writeVoltRestart + + subroutine readVoltronRestart(vApp,xmlInp) + class(voltApp_T), intent(inout) :: vApp + type(XML_Input_T), intent(inout) :: xmlInp + + character(len=strLen) :: ResF,resID,nStr + type(IOVAR_T), dimension(MAXVOLTIOVAR) :: IOVars + logical :: fExist + integer :: nRes + + call xmlInp%Set_Val(resID,"/gamera/restart/resID","msphere") + call xmlInp%Set_Val(nRes,"/gamera/restart/nRes" ,-1) + !Get number string + if (nRes == -1) then + nStr = "XXXXX" + else + write (nStr,'(I0.5)') nRes + endif + + write (ResF, '(A,A,A,A)') trim(resID), ".volt.Res.", trim(nStr), ".h5" + write(*,*) 'Reading Voltron restart from ', trim(ResF) + inquire(file=ResF,exist=fExist) + if (.not. fExist) then + !Error out and leave + write(*,*) 'Unable to open input voltron restart file, exiting' + stop + endif + + call ClearIO(IOVars) + + call AddInVar(IOVars,"nOut" ,vTypeO=IOINT) + call AddInVar(IOVars,"nRes" ,vTypeO=IOINT) + call AddInVar(IOVars,"ts" ,vTypeO=IOINT) + call AddInVar(IOVars,"MJD" ,vTypeO=IOREAL) + call AddInVar(IOVars,"time" ,vTypeO=IOREAL) + call AddInVar(IOVars,"ShallowT",vTypeO=IOREAL) + call AddInVar(IOVars,"DeepT" ,vTypeO=IOREAL) + + !Get data + call ReadVars(IOVars,.false.,ResF) + + vApp%IO%nOut = GetIOInt(IOVars,"nOut") + vApp%IO%nRes = GetIOInt(IOVars,"nRes") + 1 + vApp%ts = GetIOInt(IOVars,"ts") + vApp%MJD = GetIOReal(IOVars,"MJD") + vApp%time = GetIOReal(IOVars,"time") + vApp%ShallowT = GetIOReal(IOVars,"ShallowT") + vApp%DeepT = GetIOReal(IOVars,"DeepT") + + end subroutine + subroutine fOutputV(vApp,gApp) class(gamApp_T) , intent(inout) :: gApp class(voltApp_T), intent(inout) :: vApp