mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
RubarBE: export the upstream solid boundary condition (hydros), and refuse unused, missing or invalid solid conditions
This commit is contained in:
1 parent
f43d108871
commit
4e767d86d6
2 files changed
+77
-32
No files matched your search
+62
-27
@@ -160,23 +160,13 @@ class Rubar3(CommandLineSolver):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
trased = self._parameter_flag(study, "trased") == "O"
|
trased = self._parameter_flag(study, "trased") == "O"
|
||||||
if trased:
|
|
||||||
# Notice §3.6: HYDROS is required at each upstream boundary
|
|
||||||
missing = self._reaches_without_solid_boundary(study)
|
|
||||||
if missing:
|
|
||||||
trad = RunSolverTranslate()
|
|
||||||
message = trad["missing_solid_boundary"].format(
|
|
||||||
reaches=", ".join(missing)
|
|
||||||
)
|
|
||||||
logger.warning(message)
|
|
||||||
if qlog is not None:
|
|
||||||
qlog.put(trad["warning"].format(message=message))
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Check the hydraulic data before writing any file
|
# Check the hydraulic data before writing any file
|
||||||
try:
|
try:
|
||||||
hydraulics = self._hydraulic_data(study, values)
|
hydraulics = self._hydraulic_data(study, values)
|
||||||
geometry = self._geometry_data(hydraulics["edge"], trased)
|
geometry = self._geometry_data(hydraulics["edge"], trased)
|
||||||
|
solid = self._solid_boundary(
|
||||||
|
study.river, hydraulics["edge"], values, trased)
|
||||||
except RubarExportError as error:
|
except RubarExportError as error:
|
||||||
self._cancel(qlog, str(error))
|
self._cancel(qlog, str(error))
|
||||||
return False
|
return False
|
||||||
@@ -197,6 +187,8 @@ class Rubar3(CommandLineSolver):
|
|||||||
self._export_condin(hydraulics, repertory, qlog, name=name)
|
self._export_condin(hydraulics, repertory, qlog, name=name)
|
||||||
self._export_stricklers(hydraulics, repertory, qlog, name=name)
|
self._export_stricklers(hydraulics, repertory, qlog, name=name)
|
||||||
self._export_boundaries(hydraulics, repertory, qlog, name=name)
|
self._export_boundaries(hydraulics, repertory, qlog, name=name)
|
||||||
|
if solid is not None:
|
||||||
|
self._export_hydros(solid, repertory, qlog, name=name)
|
||||||
# self._export_abshyd(study, repertory, qlog, name=name)
|
# self._export_abshyd(study, repertory, qlog, name=name)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -217,7 +209,10 @@ class Rubar3(CommandLineSolver):
|
|||||||
"5": (), "7": ()}
|
"5": (), "7": ()}
|
||||||
_boundary_kinds = {"TD": "hydrograph Q(t)", "TZ": "water level Z(t)",
|
_boundary_kinds = {"TD": "hydrograph Q(t)", "TZ": "water level Z(t)",
|
||||||
"ZD": "rating curve Q(Z)",
|
"ZD": "rating curve Q(Z)",
|
||||||
"PC": "punctual contribution"}
|
"PC": "punctual contribution",
|
||||||
|
"SL": "solid discharge Qs(t)"}
|
||||||
|
# NCLMAX (variables.f90): points of all the solid hydrographs
|
||||||
|
_max_solid_points = 1000
|
||||||
|
|
||||||
def _hydraulic_data(self, study, values):
|
def _hydraulic_data(self, study, values):
|
||||||
"""Check the single reach data needed by DONNEE, MAIL, CONDIN,
|
"""Check the single reach data needed by DONNEE, MAIL, CONDIN,
|
||||||
@@ -452,6 +447,47 @@ class Rubar3(CommandLineSolver):
|
|||||||
|
|
||||||
return selected
|
return selected
|
||||||
|
|
||||||
|
def _solid_boundary(self, river, edge, values, trased):
|
||||||
|
"""Solid boundary condition written in HYDROS. RubarBE reads it
|
||||||
|
at the upstream node when TRASED is enabled and CONDAM=1 (CONDAM=2
|
||||||
|
is refused), and has no downstream solid condition (rubar_init.f90,
|
||||||
|
inits). Without sediment transport the solid conditions are
|
||||||
|
ignored. Return the condition or None"""
|
||||||
|
if not trased:
|
||||||
|
return None
|
||||||
|
trad = RunSolverTranslate()
|
||||||
|
condam = values.get("rubarbe_condam", "")
|
||||||
|
|
||||||
|
solid = [
|
||||||
|
bc for bc in river.boundary_condition.get_tab("solid")
|
||||||
|
if not bc.is_deleted() and bc.bctype == "SL"
|
||||||
|
]
|
||||||
|
for bc in solid:
|
||||||
|
if bc.node == edge.node2:
|
||||||
|
raise RubarExportError(
|
||||||
|
trad["solid_boundary_downstream"].format(
|
||||||
|
name=bc.name, node=edge.node2.name))
|
||||||
|
|
||||||
|
expected = ("SL",) if condam == "1" else ()
|
||||||
|
selected = self._select_boundaries(
|
||||||
|
[bc for bc in solid if bc.node == edge.node1], expected,
|
||||||
|
edge.node1, {"SL": f"TRASED=O, CONDAM={condam}"},
|
||||||
|
f"CONDAM={condam}"
|
||||||
|
)
|
||||||
|
bc = selected.get("SL")
|
||||||
|
if bc is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(bc) > self._max_solid_points:
|
||||||
|
raise RubarExportError(trad["solid_boundary_too_long"].format(
|
||||||
|
name=bc.name, node=edge.node1.name, count=len(bc),
|
||||||
|
maximum=self._max_solid_points))
|
||||||
|
# RubarBE stops on a zero D or S
|
||||||
|
if not (bc.d50 > 0 and bc.sigma >= 1):
|
||||||
|
raise RubarExportError(trad["solid_boundary_invalid"].format(
|
||||||
|
name=bc.name, node=edge.node1.name))
|
||||||
|
return bc
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _interpolated_frictions(edge):
|
def _interpolated_frictions(edge):
|
||||||
"""Minor and medium Strickler at each centre of cell. The model
|
"""Minor and medium Strickler at each centre of cell. The model
|
||||||
@@ -578,20 +614,6 @@ class Rubar3(CommandLineSolver):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _reaches_without_solid_boundary(study):
|
|
||||||
river = study.river
|
|
||||||
solid = [
|
|
||||||
bc for bc in river.boundary_condition.get_tab("solid")
|
|
||||||
if not bc.is_deleted() and bc.bctype == "SL" and len(bc) > 0
|
|
||||||
]
|
|
||||||
|
|
||||||
return [
|
|
||||||
edge.name for edge in river.enable_edges()
|
|
||||||
if river.is_upstream_node(edge.node1)
|
|
||||||
and not any(bc.node == edge.node1 for bc in solid)
|
|
||||||
]
|
|
||||||
|
|
||||||
def _parameter_values(self, study):
|
def _parameter_values(self, study):
|
||||||
return {p.name: str(p.value).strip()
|
return {p.name: str(p.value).strip()
|
||||||
for p in study.river.get_params(self.type).parameters}
|
for p in study.river.get_params(self.type).parameters}
|
||||||
@@ -930,6 +952,19 @@ class Rubar3(CommandLineSolver):
|
|||||||
lines = [header(len(bc))] + records(bc, columns)
|
lines = [header(len(bc))] + records(bc, columns)
|
||||||
self._write_parameters(repertory, f"{filename}.{name}", lines)
|
self._write_parameters(repertory, f"{filename}.{name}", lines)
|
||||||
|
|
||||||
|
def _export_hydros(self, bc, repertory, qlog, name="0"):
|
||||||
|
"""HYDROS: number of points, then Qs, t, D, S (notice annex 1).
|
||||||
|
Qs is a solid discharge (kg/s) or a concentration (kg/m3)
|
||||||
|
according to UNISOL, D and S are those of the condition"""
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export HYDROS file")
|
||||||
|
d50, sigma = float(bc.d50), float(bc.sigma)
|
||||||
|
lines = [f"{len(bc)}\n"] + [
|
||||||
|
f"{float(qs)!r} {float(t)!r} {d50!r} {sigma!r}\n"
|
||||||
|
for t, qs in bc.data
|
||||||
|
]
|
||||||
|
self._write_parameters(repertory, f"hydros.{name}", lines)
|
||||||
|
|
||||||
def read_profil(self, study, fname, results, qlog=None, name="0"):
|
def read_profil(self, study, fname, results, qlog=None, name="0"):
|
||||||
logger.info(f"read: profil.{name}")
|
logger.info(f"read: profil.{name}")
|
||||||
with open(fname, "r") as f:
|
with open(fname, "r") as f:
|
||||||
|
|||||||
@@ -49,12 +49,22 @@ class RunSolverTranslate(PamhyrTranslate):
|
|||||||
"use a dimensionless critical stress given by the user. "
|
"use a dimensionless critical stress given by the user. "
|
||||||
"Fill it in the parameters (tab Solid Transport)."
|
"Fill it in the parameters (tab Solid Transport)."
|
||||||
)
|
)
|
||||||
self._dict["missing_solid_boundary"] = _translate(
|
self._dict["solid_boundary_downstream"] = _translate(
|
||||||
"Solver",
|
"Solver",
|
||||||
"Export cancelled: sediment transport (TRASED) is enabled but "
|
"Export cancelled: solid boundary condition {name} at node "
|
||||||
"no solid boundary condition is defined at the upstream node "
|
"{node}: RubarBE only reads a solid boundary condition at the "
|
||||||
"of reach(es): {reaches}. Add a solid boundary condition, or "
|
"upstream node. Remove it."
|
||||||
"disable sediment transport in the solver parameters."
|
)
|
||||||
|
self._dict["solid_boundary_too_long"] = _translate(
|
||||||
|
"Solver",
|
||||||
|
"Export cancelled: solid boundary condition {name} at node "
|
||||||
|
"{node} has {count} points, RubarBE accepts at most {maximum}."
|
||||||
|
)
|
||||||
|
self._dict["solid_boundary_invalid"] = _translate(
|
||||||
|
"Solver",
|
||||||
|
"Export cancelled: solid boundary condition {name} at node "
|
||||||
|
"{node} must have D50 > 0 m and sigma >= 1 (1 for a uniform "
|
||||||
|
"sediment)."
|
||||||
)
|
)
|
||||||
self._dict["multireach_unsupported"] = _translate(
|
self._dict["multireach_unsupported"] = _translate(
|
||||||
"Solver",
|
"Solver",
|
||||||
|
|||||||
Reference in new issue
Block a user