diff --git a/avaframe/com1DFA/com1DFA.py b/avaframe/com1DFA/com1DFA.py index d4cf92d82..50d34963f 100644 --- a/avaframe/com1DFA/com1DFA.py +++ b/avaframe/com1DFA/com1DFA.py @@ -467,10 +467,8 @@ def prepareReleaseEntrainment(cfg, rel, inputSimLines): badName = False if "_" in relName: badName = True - log.warning( - "Release area scenario file name includes an underscore \ - the suffix _AF will be added for the simulation name" - ) + log.warning("Release area scenario file name includes an underscore \ + the suffix _AF will be added for the simulation name") # set release thickness if cfg["GENERAL"].getboolean("timeDependentRelease"): @@ -639,7 +637,7 @@ def prepareInputData(inputSimFiles, cfg): # get line from release area polygon if cfg["GENERAL"].getboolean("timeDependentRelease"): releaseLine["type"] = "time dependent Release" - timeDepRelValues, _ = gI.getTimeDepRelCsv(inputSimFiles["timeDepRelCsv"]) + timeDepRelValues, _ = gI.getTimeDepRelCsv(cfg["INPUT"]["timeDepRelCsv"]) releaseLine["thickness"] = [ timeDepRelValues["thickness"][timeDepRelValues["timeStep"] == 0].item() ] * len(releaseLine["Name"]) @@ -763,7 +761,7 @@ def prepareInputData(inputSimFiles, cfg): damLine = None if cfg["GENERAL"].getboolean("timeDependentRelease"): - releaseLine = debF.prepareTimeDepRelLine(inputSimFiles, releaseLine, cfg) + releaseLine = debF.prepareTimeDepRelLine(releaseLine, cfg) inputSimLines = { "releaseLine": releaseLine, @@ -3351,11 +3349,26 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting inputSimFiles["entResInfo"]["secondaryRelRemeshed"] = remeshedSecRel if cfgSim["GENERAL"]["timeDependentRelease"] == "True": - cfgSim["INPUT"]["timeDepRelCsv"] = inputSimFiles["timeDepRelCsv"] - timeDepRelValues, _ = gI.getTimeDepRelCsv(inputSimFiles["timeDepRelCsv"]) + cfgSim["INPUT"]["timeDepRelCsv"] = pathlib.Path( + cfgSim["GENERAL"]["avalancheDir"], + "Inputs", + "REL", + (cfgSim["GENERAL"]["timeDependentReleaseScenarios"] + ".csv"), + ) + if cfgSim["INPUT"]["timeDepRelCsv"].exists() is False: + message = ( + "time dependent release file: %s file in Inputs/REL with file ending .csv not found" + % (cfgSim["GENERAL"]["timeDependentReleaseScenarios"]) + ) + log.error(message) + raise FileNotFoundError(message) + + timeDepRelValues, _ = gI.getTimeDepRelCsv(cfgSim["INPUT"]["timeDepRelCsv"]) cfgSim["INPUT"]["timeDepRelTimeStep"] = str(timeDepRelValues["timeStep"]) cfgSim["INPUT"]["timeDepRelThickness"] = str(timeDepRelValues["thickness"]) cfgSim["INPUT"]["timeDepRelVelocity"] = str(timeDepRelValues["velocity"]) + else: + cfgSim["INPUT"]["timeDepRelCsv"] = "" if modName in ["com1DFA", "com5SnowSlide", "com6RockAvalanche"]: # check if spatialVoellmy is chosen that friction fields have correct extent @@ -3460,7 +3473,7 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting cfgSim, pathToDemFull, inputSimFiles["secondaryRelFile"], - timeDepRelFile=inputSimFiles["timeDepRelCsv"], + timeDepRelFile=cfgSim["INPUT"]["timeDepRelCsv"], ) else: relVolume = "" diff --git a/avaframe/com1DFA/com1DFACfg.ini b/avaframe/com1DFA/com1DFACfg.ini index 0927cca80..085c50f37 100644 --- a/avaframe/com1DFA/com1DFACfg.ini +++ b/avaframe/com1DFA/com1DFACfg.ini @@ -132,10 +132,15 @@ entThDistVariation = # entrainment thickness (only considered if ENT file is shapefile and entThFromFile=False) [m] entTh = -#+++++++++++++general start conditions: time dependent release -# if timeDependentRelease is True, provide the the timesteps, thickness and velocity +#+++++++++++++General start conditions: time dependent release +# if timeDependentRelease is True (and relThFromFile is True), provide the the timesteps, thickness and velocity # for a releases in a csv-file in the REL folder timeDependentRelease = False +# specify one or multiple particular time dependent release files, +# provide name of csv file with or without extension .csv +# multiple files are separated with a | +# if no file is specified, all csv files in the Inputs/REL folder are computed +timeDependentReleaseScenarios = # when checking if an already existing particle is within a release polygon # (that would cause numerical instabilities and rise an error), one can decide to add a buffer # around the polygon (0 means take strictly the points inside, a very small value diff --git a/avaframe/com1DFA/com1DFATools.py b/avaframe/com1DFA/com1DFATools.py index 5ba11a87a..5abd0d857 100644 --- a/avaframe/com1DFA/com1DFATools.py +++ b/avaframe/com1DFA/com1DFATools.py @@ -20,7 +20,6 @@ from avaframe.in3Utils import cfgUtils from avaframe.in2Trans import rasterUtils as IOf - # create local logger # change log level in calling module to DEBUG to see log messages log = logging.getLogger(__name__) diff --git a/avaframe/com1DFA/debrisFunctions.py b/avaframe/com1DFA/debrisFunctions.py index 9a63c13d1..08410304d 100644 --- a/avaframe/com1DFA/debrisFunctions.py +++ b/avaframe/com1DFA/debrisFunctions.py @@ -145,59 +145,7 @@ def addReleaseParticles(cfg, particles, inputSimLines, thickness, velocityMag, d return particles, zPartArray0 -def checkTimeDepRelease(timeDepRelValues, timeDepRelCsv): - """ - check if time dependent release values satisfy the following requirements: - - release - timesteps are unique - - the release - timesteps are not too close (that the particle density becomes too high) - - provided release - thickness is larger than zero - - provided velocity is zero or larger. - - Parameters - ----------- - timeDepRelCsv: str - directory to csv table containing time dependent release values - timeDepRelValues: dict - contains time dependent release values: timestep, thickness, velocity - """ - # check if timesteps are unique - timeStepUnique = np.unique(timeDepRelValues["timeStep"]) - if timeStepUnique.ndim == 0: - if timeStepUnique != timeDepRelValues["timeStep"]: - message = "The provided time dependent release time steps in %s are not unique" % (timeDepRelCsv) - log.error(message) - raise ValueError(message) - elif len(timeStepUnique) != len(timeDepRelValues["timeStep"]): - message = "The provided time dependent release timesteps in %s are not unique" % (timeDepRelCsv) - log.error(message) - raise ValueError(message) - - # check if a timestep = 0 is provided - if 0 not in timeStepUnique: - message = ( - "If release is time dependent, a thickness needs to be provided for time step 0 s in %s" - % (timeDepRelCsv) - ) - log.error(message) - raise ValueError(message) - - # check that release thickness > 0 - for th in timeDepRelValues["thickness"]: - if th <= 0: - message = "For every release time step a thickness > 0 needs to be provided in %s" % ( - timeDepRelCsv - ) - log.error(message) - raise ValueError(message) - - for vel in timeDepRelValues["velocity"]: - if vel < 0: - message = "The initial velocity provided in %s can not be negative." % (timeDepRelCsv) - log.error(message) - raise ValueError(message) - - -def prepareTimeDepRelLine(inputSimFiles, releaseLine, cfg): +def prepareTimeDepRelLine(releaseLine, cfg): """ read time dependent release values and return them as a dictionary containing: - timestep @@ -207,9 +155,6 @@ def prepareTimeDepRelLine(inputSimFiles, releaseLine, cfg): Parameters ---------- - inputSimFiles : dict - dictionary containing - - timeDepRelCsv: str, path to time dependent release values (csv-)file releaseLine: dict contains information of release line cfg: configparser object @@ -224,14 +169,12 @@ def prepareTimeDepRelLine(inputSimFiles, releaseLine, cfg): """ try: - releaseLine["values"], timeDepRelValuesDF = gI.getTimeDepRelCsv(inputSimFiles["timeDepRelCsv"]) + releaseLine["values"], timeDepRelValuesDF = gI.getTimeDepRelCsv(cfg["INPUT"]["timeDepRelCsv"]) releaseLine["thicknessSource"] = ["csv file"] except: - message = "No time dependent release csv file found" + message = "Provide a valid csv file containing time dependent release values" log.error(message) raise FileNotFoundError(message) - # check if some criterias are satisfied in the csv file - checkTimeDepRelease(releaseLine["values"], inputSimFiles["timeDepRelCsv"]) # write the time dependent values into configurationFiles folder cfgUtils.writeReleaseCsvFile(cfg, timeDepRelValuesDF) diff --git a/avaframe/com1DFA/deriveParameterSet.py b/avaframe/com1DFA/deriveParameterSet.py index c80bcc8ca..6b536284d 100644 --- a/avaframe/com1DFA/deriveParameterSet.py +++ b/avaframe/com1DFA/deriveParameterSet.py @@ -433,8 +433,15 @@ def checkThicknessSettings(cfg, thName, inputSimFiles): log.error(message) raise FileNotFoundError(message) if ( - cfg["GENERAL"].getboolean("timeDependentRelease") - and cfg["GENERAL"].getboolean("relThFromFile") is False + cfg["GENERAL"].getboolean("timeDependentRelease") + and inputSimFiles["entResInfo"]["timeDepRelCsvAvailable"] == "No" + ): + message = "When release is time dependent, a csv file containing time dependent release parameters needs to be provided." + log.error(message) + raise FileNotFoundError(message) + if ( + cfg["GENERAL"].getboolean("timeDependentRelease") + and cfg["GENERAL"].getboolean("relThFromFile") is False ): message = "When release is time dependent, relThFromFile needs to be set to True" log.error(message) diff --git a/avaframe/in1Data/getInput.py b/avaframe/in1Data/getInput.py index acf4e7ac2..4f9c451db 100644 --- a/avaframe/in1Data/getInput.py +++ b/avaframe/in1Data/getInput.py @@ -226,6 +226,10 @@ def getInputDataCom1DFA(avaDir): message = "Release area information - use either .shp or .asc/.tif files" log.error(message) raise AssertionError(message) + if len(relFiles) == 0: + message = "No release area is found - provide a .shp or .asc or .tif file" + log.error(message) + raise FileNotFoundError(message) else: log.info("Release area files are: %s" % [str(relFilestr) for relFilestr in relFiles]) entResInfo["relThFileType"] = relFiles[0].suffix @@ -297,9 +301,11 @@ def getInputDataCom1DFA(avaDir): entResInfo["resRemeshed"] = "No" entResInfo["bhdRemeshed"] = "No" - timeDepRelCsv, entResInfo["timeDepRelCsv"], _ = getAndCheckInputFiles( - inputDir, "REL", "Time dependent release parameters (csv)", fileExt="csv" - ) + timeDepRelFiles = sorted(list(releaseDir.glob("*.csv"))) + if len(timeDepRelFiles) > 0: + entResInfo["timeDepRelCsvAvailable"] = "Yes" + else: + entResInfo["timeDepRelCsvAvailable"] = "No" # return DEM, first item of release, entrainment and resistance areas inputSimFiles = { @@ -315,7 +321,7 @@ def getInputDataCom1DFA(avaDir): "kFile": kFile, "tauCFile": tauCFile, "bhdFile": bhdFile, - "timeDepRelCsv": timeDepRelCsv, + "timeDepRelCsv": timeDepRelFiles, } for thFile in ["rel", "secondaryRel", "ent"]: @@ -362,7 +368,7 @@ def getAndCheckInputFiles(inputDir, folder, inputType, fileExt="shp", fileSuffix """ available = "No" - supportedFileFormats = [".shp", ".asc", ".tif", ".csv"] + supportedFileFormats = [".shp", ".asc", ".tif"] # Define the directory to search and the extensions if fileExt == "": @@ -401,8 +407,7 @@ def getAndCheckInputFiles(inputDir, folder, inputType, fileExt="shp", fileSuffix if OutputFile.suffix not in supportedFileFormats: message = ( - "Unsupported file format found for OutputFile %s; shp, asc, tif, csv are allowed" - % OutputFile + "Unsupported file format found for OutputFile %s; shp, asc, tif are allowed" % OutputFile ) log.error(message) raise AssertionError(message) @@ -498,12 +503,19 @@ def updateThicknessCfg(inputSimFiles, cfgInitial): thTypeList.append("entFile") if cfgInitial["GENERAL"].getboolean("secRelArea"): thTypeList.append("secondaryRelFile") + if cfgInitial["GENERAL"].getboolean("timeDependentRelease"): + thTypeList.append("timeDepRelFile") # initialize release scenario list releaseScenarioIni = cfgInitial["INPUT"]["releaseScenario"] if releaseScenarioIni == "": releaseScenarioList = inputSimFiles["releaseScenarioList"] else: + for scenario in cfgInitial["INPUT"]["releaseScenario"].split("|"): + if scenario not in inputSimFiles["releaseScenarioList"]: + message = "Chosen release scenario: %s not available" % scenario + log.error(message) + raise FileNotFoundError(message) releaseScenarioList = cfgInitial["INPUT"]["releaseScenario"].split("|") # add input data info to cfg object @@ -539,18 +551,40 @@ def updateThicknessCfg(inputSimFiles, cfgInitial): ) cfgInitial["INPUT"]["secondaryReleaseScenario"] = inputSimFiles["secondaryRelFile"].stem + # get time dependent release scenario + if inputSimFiles["timeDepRelCsv"] is not None and "timeDepRelFile" in thTypeList: + timeDepRelFileIni = cfgInitial["GENERAL"]["timeDependentReleaseScenarios"] + availableTimeDepRelScenarios = [] + for file in inputSimFiles["timeDepRelCsv"]: + availableTimeDepRelScenarios.append(file.stem) + + if timeDepRelFileIni == "": + # if no scenario is specified in the ini file, use all available csv files + timeDepRelScenarioList = availableTimeDepRelScenarios + else: + # use specified scenario + timeDepRelScenarioList = [] + for timeDepScenario in cfgInitial["GENERAL"]["timeDependentReleaseScenarios"].split("|"): + timeDepRelScenarioList.append(pathlib.Path(timeDepScenario).stem) + + timeDepRelScenariosCfg = cfgUtils.convertToCfgList(timeDepRelScenarioList) + if timeDepRelFileIni == "": + cfgInitial["GENERAL"]["timeDependentReleaseScenarios"] = timeDepRelScenariosCfg + # check if a csv file exists for the specified scenario(s) + for timeDepIniFileName in cfgInitial["GENERAL"]["timeDependentReleaseScenarios"].split("|"): + timeDepIniFileName = pathlib.Path(timeDepIniFileName).stem + if timeDepIniFileName not in availableTimeDepRelScenarios: + message = "Chosen time dependent release scenario: %s not available" % timeDepIniFileName + log.error(message) + raise FileNotFoundError(message) + else: + cfgInitial["GENERAL"]["timeDependentReleaseScenarios"] = timeDepRelScenariosCfg + # create cfg string from release scenario list and add to cfg object releaseScenarioName = cfgUtils.convertToCfgList(releaseScenarioList) if cfgInitial["INPUT"]["releaseScenario"] == "": cfgInitial["INPUT"]["releaseScenario"] = releaseScenarioName - else: - for relIniFileName in cfgInitial["INPUT"]["releaseScenario"].split("|"): - if relIniFileName not in releaseScenarioList: - message = "Chosen release scenario: %s not available" % relIniFileName - log.error(message) - raise FileNotFoundError(message) - else: - log.info("Chosen release scenarios: %s" % cfgInitial["INPUT"]["releaseScenario"]) + log.info("Chosen release scenarios: %s" % cfgInitial["INPUT"]["releaseScenario"]) return cfgInitial @@ -705,7 +739,7 @@ def fetchReleaseFile(inputSimFiles, releaseScenario, cfgSim, releaseList): releaseScenarioPath.parts[-2] + "/" + releaseScenarioPath.parts[-1] ) elif ( - cfgSim["GENERAL"]["relThFromFile"] == "True" and cfgSim["GENERAL"]["timeDependentRelease"] == "False" + cfgSim["GENERAL"]["relThFromFile"] == "True" and cfgSim["GENERAL"]["timeDependentRelease"] == "False" ): # shapefile with thickness attributes - handle thickness/id/ci95 values for scenario in releaseList: @@ -1177,4 +1211,58 @@ def getTimeDepRelCsv(timeDepRelCsv): "thickness": timeDepRelDF["thickness"].to_numpy(dtype=np.float64), "velocity": timeDepRelDF["velocity"].to_numpy(dtype=np.float64), } + # check if some criterias are satisfied in the csv file + checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) return timeDepRelValues, timeDepRelDF + + +def checkTimeDepRelease(timeDepRelValues, timeDepRelCsv): + """ + check if time dependent release values satisfy the following requirements: + - release - timesteps are unique + - the release - timesteps are not too close (that the particle density becomes too high) + - provided release - thickness is larger than zero + - provided velocity is zero or larger. + + Parameters + ----------- + timeDepRelCsv: str + directory to csv table containing time dependent release values + timeDepRelValues: dict + contains time dependent release values: timestep, thickness, velocity + """ + # check if timesteps are unique + timeStepUnique = np.unique(timeDepRelValues["timeStep"]) + if timeStepUnique.ndim == 0: + if timeStepUnique != timeDepRelValues["timeStep"]: + message = "The provided time dependent release time steps in %s are not unique" % (timeDepRelCsv) + log.error(message) + raise ValueError(message) + elif len(timeStepUnique) != len(timeDepRelValues["timeStep"]): + message = "The provided time dependent release timesteps in %s are not unique" % (timeDepRelCsv) + log.error(message) + raise ValueError(message) + + # check if a timestep = 0 is provided + if 0 not in timeStepUnique: + message = ( + "If release is time dependent, a thickness needs to be provided for time step 0 s in %s" + % (timeDepRelCsv) + ) + log.error(message) + raise ValueError(message) + + # check that release thickness > 0 + for th in timeDepRelValues["thickness"]: + if th <= 0: + message = "For every release time step a thickness > 0 needs to be provided in %s" % ( + timeDepRelCsv + ) + log.error(message) + raise ValueError(message) + + for vel in timeDepRelValues["velocity"]: + if vel < 0: + message = "The initial velocity provided in %s can not be negative." % (timeDepRelCsv) + log.error(message) + raise ValueError(message) diff --git a/avaframe/tests/test_com1DFA.py b/avaframe/tests/test_com1DFA.py index 64cca3b46..70592941f 100644 --- a/avaframe/tests/test_com1DFA.py +++ b/avaframe/tests/test_com1DFA.py @@ -54,6 +54,7 @@ def test_prepareInputData(tmp_path): cfg["INPUT"] = {"DEM": "avaAlr.tif"} cfg["INPUT"]["relThFile"] = "" cfg["INPUT"]["entThFile"] = "" + cfg["INPUT"]["timeDepRelCsv"] = "" # call function to be tested demOri, inputSimLines = com1DFA.prepareInputData(inputSimFiles, cfg) @@ -231,6 +232,7 @@ def test_prepareInputData(tmp_path): } cfg["INPUT"] = {"DEM": "testDEM.asc"} cfg["INPUT"]["relThFile"] = str(inputSimFiles["relThFile"]) + cfg["INPUT"]["timeDepRelCsv"] = "" demOri, inputSimLines = com1DFA.prepareInputData(inputSimFiles, cfg) @@ -278,6 +280,7 @@ def test_prepareInputData(tmp_path): cfg["INPUT"] = {"DEM": "testDEM.asc"} cfg["INPUT"]["relThFile"] = "" cfg["INPUT"]["secondaryRelThFile"] = str(inputSimFiles["secondaryRelThFile"]) + cfg["INPUT"]["timeDepRelCsv"] = "" demOri, inputSimLines = com1DFA.prepareInputData(inputSimFiles, cfg) @@ -322,6 +325,7 @@ def test_prepareInputData(tmp_path): } cfg["INPUT"] = {"DEM": "testDEM.asc"} cfg["INPUT"]["relThFile"] = str(inputSimFiles["relThFile"]) + cfg["INPUT"]["timeDepRelCsv"] = "" # with pytest.raises(AssertionError) as e: # assert com1DFA.prepareInputData(inputSimFiles, cfg) @@ -348,6 +352,7 @@ def test_prepareInputData(tmp_path): } cfg["INPUT"] = {"DEM": "avaAlr.tif"} cfg["INPUT"]["relThFile"] = "" + cfg["INPUT"]["timeDepRelCsv"] = "" with pytest.raises(AssertionError) as e: assert com1DFA.prepareInputData(inputSimFiles, cfg) @@ -380,6 +385,7 @@ def test_prepareInputData(tmp_path): cfg["INPUT"]["relThFile"] = "" cfg["INPUT"]["entThFile"] = "" cfg["INPUT"]["releaseScenario"] = "release1PF" + cfg["INPUT"]["timeDepRelCsv"] = str(avaDir / "Inputs" / "REL" / "release1PF.csv") # call function to be tested demOri, inputSimLines = com1DFA.prepareInputData(inputSimFiles, cfg) @@ -1837,7 +1843,7 @@ def test_savePartToPickle(tmp_path): particlesRead7 = pickle.load(open(picklePath7, "rb")) for pProp in particlesRead7: - assert pProp in ['ux', 'uy', 'uz', 'iCell', 'z', 'x', 'y', 'm', 'h', 't'] + assert pProp in ["ux", "uy", "uz", "iCell", "z", "x", "y", "m", "h", "t"] def test_exportFields(tmp_path): @@ -2096,6 +2102,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "dam": "True", "explicitFriction": 0, "timeDependentRelease": "False", + "timeDependentReleaseScenarios": "", } standardCfg["INPUT"] = { "entThThickness": "1.", @@ -2103,6 +2110,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "entThCi95": "None", "releaseScenario": "", "relThFile": "", + "timeDepRelCsv": "", } testDir = pathlib.Path(__file__).parents[0] @@ -2170,6 +2178,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "dam": "True", "explicitFriction": 0, "timeDependentRelease": "False", + "timeDependentReleaseScenarios": "", } testCfg["INPUT"] = { @@ -2177,6 +2186,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "entThId": "0", "entThCi95": "None", "releaseScenario": "relAlr", + "timeDepRelCsv": "", } testCfg["INPUT"]["DEM"] = "avaAlr.tif" testCfg["INPUT"]["relThFile"] = "" @@ -2281,6 +2291,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "dam": "True", "explicitFriction": 0, "timeDependentRelease": "False", + "timeDependentReleaseScenarios": "", } testCfg2["INPUT"] = { "entThThickness": "1.", @@ -2288,6 +2299,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "entThCi95": "None", "releaseScenario": "relAlr", "DAM": str(pathlib.Path("DAM", relPath.name)), + "timeDepRelCsv": "", } testCfg2["INPUT"]["DEM"] = "avaAlr.tif" testCfg2["INPUT"]["relThFile"] = "" @@ -2366,6 +2378,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "entThCi95": "None", "releaseScenario": "", "relThFile": "", + "timeDepRelCsv": "", } testDir = pathlib.Path(__file__).parents[0] @@ -2377,6 +2390,8 @@ def test_prepareVarSimDict(tmp_path, caplog): standardCfg["INPUT"]["DEM"] = "DEM_PF_Topo.asc" standardCfg["GENERAL"]["avalancheDir"] = str(avaDir) + standardCfg["GENERAL"]["timeDependentReleaseScenarios"] = "release1PF" + relPath = pathlib.Path(avaDir, "Inputs", "REL", "release1PF.shp") inputSimFiles = { "relFiles": [relPath], @@ -2432,6 +2447,7 @@ def test_prepareVarSimDict(tmp_path, caplog): "dam": "False", "explicitFriction": 0, "timeDependentRelease": "True", + "timeDependentReleaseScenarios": "release1PF", } testCfg["INPUT"] = { diff --git a/avaframe/tests/test_debrisFunctions.py b/avaframe/tests/test_debrisFunctions.py index 8781ff7e4..92c01f8a0 100644 --- a/avaframe/tests/test_debrisFunctions.py +++ b/avaframe/tests/test_debrisFunctions.py @@ -150,65 +150,6 @@ def test_addReleaseParticles(): debF.addReleaseParticles(cfg, particles, inputSimLines, thickness, velocityMag, dem, zPartArray0) -def test_checkTimeDepRelease(): - timeDepRelValues = { - "timeStep": np.array([0, 10, 20, 30, 35]), - "thickness": np.array([1, 1, 1, 1, 1]), - "velocity": np.array([10, 10, 10, 10, 10]), - } - timeDepRelCsv = "path2TimeDepRel.csv" - # no error should occur - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - - timeDepRelValues["timeStep"] = np.array([20, 10, 0, 30, 35]) - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - - # timesteps are not unique - timeDepRelValues["timeStep"] = np.array([0, 10, 10, 30, 35]) - - with pytest.raises(ValueError) as e: - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - assert ("The provided time dependent release timesteps in %s are not unique" % (timeDepRelCsv)) in str( - e.value - ) - - timeDepRelValues["timeStep"] = np.array([0, 0]) - with pytest.raises(ValueError) as e: - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - assert ("The provided time dependent release timesteps in %s are not unique" % (timeDepRelCsv)) in str( - e.value - ) - - # no timestep 0 - timeDepRelValues["timeStep"] = np.array([20, 15, 10, 30, 35]) - - with pytest.raises(ValueError) as e: - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - assert ( - "If release is time dependent, a thickness needs to be provided for time step 0 s in %s" - % (timeDepRelCsv) - ) in str(e.value) - - # thickness needs to be > 0 - timeDepRelValues["timeStep"] = np.array([20, 10, 0, 30, 35]) - timeDepRelValues["thickness"] = np.array([1, 0, 1, 1, 1]) - with pytest.raises(ValueError) as e: - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - assert ("For every release time step a thickness > 0") in str(e.value) - - timeDepRelValues["thickness"] = np.array([1, 1, -1, 1, 1]) - with pytest.raises(ValueError) as e: - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - assert ("For every release time step a thickness > 0") in str(e.value) - - # velocity needs to be >= 0 - timeDepRelValues["thickness"] = np.array([1, 1, 1, 1, 1]) - timeDepRelValues["velocity"] = np.array([10, 10, 10, -10, 10]) - with pytest.raises(ValueError) as e: - debF.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) - assert ("The initial velocity provided in %s can not be negative." % (timeDepRelCsv)) in str(e.value) - - """ Test does not word because: When calling pytest, executing DFAfunctionsCython.upfateFieldsC() raises an error ("Fatal Python error: Aborted") (see issue #1002?) diff --git a/avaframe/tests/test_getInput.py b/avaframe/tests/test_getInput.py index 3944101a1..553556fec 100644 --- a/avaframe/tests/test_getInput.py +++ b/avaframe/tests/test_getInput.py @@ -309,6 +309,7 @@ def test_updateThicknessCfg(tmp_path): cfg["GENERAL"]["relThFromFile"] = "True" cfg["GENERAL"]["simTypeList"] = "null|ent" cfg["GENERAL"]["secRelAra"] = "False" + cfg["GENERAL"]["timeDependentRelease"] = "False" cfg["INPUT"] = {"releaseScenario": ""} demFile = avaTestDirInputs / "DEM_HS_Topo.asc" @@ -332,6 +333,7 @@ def test_updateThicknessCfg(tmp_path): "releaseScenarioList": ["release1HS", "release2HS"], "seondaryRelThFile": None, "entThFile": None, + "timeDepRelCsv": None, } inputSimFiles["release1HS"] = {"thickness": ["1.0"], "id": ["0"], "ci95": ["None", "None"]} @@ -358,6 +360,30 @@ def test_updateThicknessCfg(tmp_path): assert cfg["INPUT"]["entThId"] == "0" assert cfg["INPUT"]["entThThickness"] == "0.3" + # test with time dependent release option + + cfg["GENERAL"]["timeDependentRelease"] = "True" + cfg["GENERAL"]["timeDependentReleaseScenarios"] = "" + inputSimFiles["timeDepRelCsv"] = [ + avaTestDirInputs / "REL" / "relTest1.csv", + avaTestDirInputs / "REL" / "relTest2.csv", + ] + + cfg = getInput.updateThicknessCfg(inputSimFiles, cfg) + + assert cfg["GENERAL"]["timeDependentReleaseScenarios"] == "relTest1|relTest2" + + cfg["GENERAL"]["timeDependentRelease"] = "True" + cfg["GENERAL"]["timeDependentReleaseScenarios"] = "relTest1.csv" + inputSimFiles["timeDepRelCsv"] = [ + avaTestDirInputs / "REL" / "relTest1.csv", + avaTestDirInputs / "REL" / "relTest2.csv", + ] + + cfg = getInput.updateThicknessCfg(inputSimFiles, cfg) + + assert cfg["GENERAL"]["timeDependentReleaseScenarios"] == "relTest1" + def test_selectReleaseFile(tmp_path): """testing selecting a release area scenario according to configuration settings""" @@ -1344,6 +1370,7 @@ def test_updateThicknessCfg_with_specified_scenarios(tmp_path): }, "relThFile": None, "releaseScenarioList": ["release1HS", "release2HS"], + "timeDepRelCsv": None, } inputSimFiles["release1HS"] = {"thickness": ["1.0"], "id": ["0"], "ci95": ["None"]} @@ -1400,6 +1427,7 @@ def test_updateThicknessCfg_with_secondary_release_raster(tmp_path): }, "relThFile": None, "releaseScenarioList": ["release1HS"], + "timeDepRelCsv": None, } inputSimFiles["release1HS"] = {"thickness": ["1.0"], "id": ["0"], "ci95": ["None"]} @@ -1556,11 +1584,69 @@ def test_getTimeDepRelCsv(): testDir = pathlib.Path(__file__).parents[0] timeDepRelCsv = testDir / "data" / "testTimeDepRel" / "rel.csv" - timeDepRelValues, timeDepRelValuesTxt = getInput.getTimeDepRelCsv(timeDepRelCsv) - assert np.all(timeDepRelValues["timeStep"] == np.array([0, 20, 50])) - assert np.all(timeDepRelValues["thickness"] == np.array([3, 1, 0])) + with pytest.raises(ValueError): + timeDepRelValues, timeDepRelValuesTxt = getInput.getTimeDepRelCsv(timeDepRelCsv) timeDepRelCsv = testDir / "data" / "testTimeDepRel" / "rel_notSorted.csv" timeDepRelValues, timeDepRelValuesTxt = getInput.getTimeDepRelCsv(timeDepRelCsv) assert np.all(timeDepRelValues["timeStep"] == np.array([0, 20, 50])) assert np.all(timeDepRelValues["thickness"] == np.array([3, 1, 1])) + + +def test_checkTimeDepRelease(): + timeDepRelValues = { + "timeStep": np.array([0, 10, 20, 30, 35]), + "thickness": np.array([1, 1, 1, 1, 1]), + "velocity": np.array([10, 10, 10, 10, 10]), + } + timeDepRelCsv = "path2TimeDepRel.csv" + # no error should occur + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + + timeDepRelValues["timeStep"] = np.array([20, 10, 0, 30, 35]) + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + + # timesteps are not unique + timeDepRelValues["timeStep"] = np.array([0, 10, 10, 30, 35]) + + with pytest.raises(ValueError) as e: + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + assert ("The provided time dependent release timesteps in %s are not unique" % (timeDepRelCsv)) in str( + e.value + ) + + timeDepRelValues["timeStep"] = np.array([0, 0]) + with pytest.raises(ValueError) as e: + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + assert ("The provided time dependent release timesteps in %s are not unique" % (timeDepRelCsv)) in str( + e.value + ) + + # no timestep 0 + timeDepRelValues["timeStep"] = np.array([20, 15, 10, 30, 35]) + + with pytest.raises(ValueError) as e: + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + assert ( + "If release is time dependent, a thickness needs to be provided for time step 0 s in %s" + % (timeDepRelCsv) + ) in str(e.value) + + # thickness needs to be > 0 + timeDepRelValues["timeStep"] = np.array([20, 10, 0, 30, 35]) + timeDepRelValues["thickness"] = np.array([1, 0, 1, 1, 1]) + with pytest.raises(ValueError) as e: + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + assert ("For every release time step a thickness > 0") in str(e.value) + + timeDepRelValues["thickness"] = np.array([1, 1, -1, 1, 1]) + with pytest.raises(ValueError) as e: + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + assert ("For every release time step a thickness > 0") in str(e.value) + + # velocity needs to be >= 0 + timeDepRelValues["thickness"] = np.array([1, 1, 1, 1, 1]) + timeDepRelValues["velocity"] = np.array([10, 10, 10, -10, 10]) + with pytest.raises(ValueError) as e: + getInput.checkTimeDepRelease(timeDepRelValues, timeDepRelCsv) + assert ("The initial velocity provided in %s can not be negative." % (timeDepRelCsv)) in str(e.value) diff --git a/docs/moduleCom1DFA.rst b/docs/moduleCom1DFA.rst index 81b12941c..31ad44898 100644 --- a/docs/moduleCom1DFA.rst +++ b/docs/moduleCom1DFA.rst @@ -177,7 +177,7 @@ input file (shape file or raster file) or 2) through the :py:mod:`com1DFA` confi - if the flag `timeDependentRelease` is True, in various provided time steps flowing mass is initialized (`relThFromFile` is also set to True, currently the only option to read time dependent thickness is from csv file) - - additional to a .shp file (raster file does not work yet), a csv file is provided in the `REL` folder, that contains: + - additional to a .shp file (raster file does not work yet), at least one csv file is provided in the `REL` folder, that contains: - a header (first line) - the following columns with the respective column names: