RubarBE: split critical Shields stress (TCADIM) from water viscosity (VISC)

This commit is contained in:
Dylan Jeannin committed 2026-10-15 03:40:52 +02:00
1 parent bf2d3ae7a9
commit 657f54ff91
5 files changed
+81 -19

No files matched your search

@@ -315,6 +315,14 @@ class SolverParametersList(PamhyrModelList):
n._lst = list(map(lambda t: t[1], sorted(lst)))
# Parameters added to the solver after the study was saved
names = {p.name for p in n._lst}
n._lst += [
Parameter(name=name, value=value, status=status)
for name, value in st.default_parameters()
if name not in names
]
new[solver] = n
return new
+44 -1
View File
@@ -92,6 +92,7 @@ class Rubar3(CommandLineSolver):
("rubarbe_sediment_mult_3", ""),
("rubarbe_sediment_mult_4", ""),
("rubarbe_sediment_mult_5", ""),
("rubarbe_sediment_tcadim", "0.047"),
("rubarbe_sediment_visc", "1.3E-06"),
("rubarbe_sediment_opts", "3"),
("rubarbe_sediment_odchar", "0"),
@@ -200,7 +201,7 @@ class Rubar3(CommandLineSolver):
_ts_fields = (
("ros", "real"), ("por", "real"), ("dcharg", "real"),
("halfa", "real"), ("mult_1", "multipliers"),
("visc", "real"), ("opts", "law"), ("odchar", "integer"),
("visc", "visc"), ("opts", "law"), ("odchar", "integer"),
("unisol", "integer"), ("typdef", "integer"),
("depot", "depot"), ("choixc", "integer"),
("option", "options"), ("capsol", "integer"),
@@ -208,6 +209,28 @@ class Rubar3(CommandLineSolver):
("defond", "integer"), ("varcons", "integer"),
)
# rubar_init.f90 (inits): laws whose critical stress may come from the
# Shields diagram, and laws without critical stress
_shields_laws = {1, 10, 11, 12, 14, 25, 26}
_no_threshold_laws = {2, 3, 8, 13, 18, 19, 22, 23, 24}
_brownlie_law = 16
@classmethod
def tcadim_required(cls, opts, option):
"""True if RubarBE reads the dimensionless critical stress TCADIM
for transport law OPTS and options OPTION (notice §3.10)"""
try:
law = int(opts)
except ValueError:
return False
shields = len(option) == 3 and option[1] != "1"
if shields and law in cls._shields_laws:
return False
if law in cls._no_threshold_laws or law == cls._brownlie_law:
return False
return True
@staticmethod
def _reaches_without_solid_boundary(study):
river = study.river
@@ -344,6 +367,26 @@ class Rubar3(CommandLineSolver):
value = self._required(values, key)
if kind == "real":
result = self._real(value, key)
elif kind == "visc":
# Notice annex 1: TCADIM then VISC, read as (A50, A20) then
# two F10.0. A single value would be read as TCADIM, with
# VISC = 0 (rubar_init.f90, inits).
if Decimal(self._real(value, key)) <= 0:
raise ValueError(f"{key}: expected a positive viscosity")
tcadim_key = prefix + "tcadim"
tcadim = values.get(tcadim_key, "")
if tcadim:
result = self._real(tcadim, tcadim_key)
elif self.tcadim_required(values.get(prefix + "opts", ""),
values.get(prefix + "option", "")):
message = trad["missing_tcadim"].format(key=tcadim_key)
logger.warning(message)
if qlog is not None:
qlog.put(trad["warning"].format(message=message))
return False
else:
result = " " * 10
result += self._real(value, key)
elif kind == "multipliers":
result = self._real(value, key)
extras = [values.get(prefix + f"mult_{i}", "")
+6
View File
@@ -43,6 +43,12 @@ class RunSolverTranslate(PamhyrTranslate):
"Export cancelled: REGIME=1 is incompatible with CONDAM=0. "
"A reflecting upstream boundary cannot impose the water depth."
)
self._dict["missing_tcadim"] = _translate(
"Solver",
"Export cancelled: {key}: the selected transport law and options "
"use a dimensionless critical stress given by the user. "
"Fill it in the parameters (tab Solid Transport)."
)
self._dict["missing_solid_boundary"] = _translate(
"Solver",
"Export cancelled: sediment transport (TRASED) is enabled but "
+13 -4
View File
@@ -156,10 +156,15 @@ def fields():
add('sediment_option', 2, 'Calcul de la contrainte critique',
'Trois choix indépendants, enregistrés ensemble dans OPTION.',
kind='options')
add('sediment_visc', 2, 'Viscosité ou seuil critique',
'Selon la configuration : seuil critique adimensionnel fourni, ou '
'viscosité cinématique de l’eau. À 15 °C : environ 1,30 × 10⁻⁶ m²/s. '
'Un changement de mode ne convertit pas la valeur.', positive=True)
add('sediment_tcadim', 2, 'Seuil critique adimensionnel (—)',
'Contrainte critique adimensionnelle (TCADIM) fournie par '
'l’utilisateur, par exemple 0,047 pour Meyer-Peter et Müller ou 0,15 '
'pour Recking et al. (2008). Utilisée lorsque le seuil n’est pas '
'calculé par le diagramme de Shields et que la loi en a besoin.',
positive=True, optional=True)
add('sediment_visc', 2, 'Viscosité cinématique de l’eau (m²/s)',
'Viscosité cinématique de l’eau, variable avec la température. '
'À 15 °C : environ 1,30 × 10⁻⁶ m²/s.', positive=True)
choice('sediment_choixc', 2, 'Calcul de la contrainte hydrodynamique de '
'cisaillement',
'MPC : méthode des perpendiculaires confondues (notice §8.5).',
@@ -327,6 +332,10 @@ def active(field, values):
return False
if key == 'tiopdt':
return values.get('rubarbe_iopdt', '').lower() == 'm'
if key == 'sediment_tcadim':
return Rubar3.tcadim_required(
values.get('rubarbe_sediment_opts', ''),
values.get('rubarbe_sediment_option', ''))
if key in ('ros', 'dm', 'segma'):
return (not transport and
values.get('rubarbe_optfpc', '0') not in ('', '0'))
+10 -14
View File
@@ -296,16 +296,6 @@ class RubarForm(QWidget):
self._refreshing = False
def _update_context(self, values):
option = values.get('rubarbe_sediment_option', '')
label = self.labels.get('rubarbe_sediment_visc')
if label is not None:
if len(option) == 3 and all(c in '12' for c in option):
title = ('Seuil critique adimensionnel (—)' if option[1] == '1'
else 'Viscosité cinématique de l’eau (m²/s)')
label.setText(tr(title))
else:
label.setText(tr(
'Viscosité / seuil : préciser les trois choix'))
warnings = []
if not self.editable:
warnings.append(tr('Étude en lecture seule.'))
@@ -334,15 +324,21 @@ class RubarForm(QWidget):
warnings.append(tr('La fin du calcul doit suivre son début.'))
except (KeyError, ValueError):
pass
if transport and len(option) == 3 and option[1] == '2':
if transport:
try:
if float(values.get('rubarbe_sediment_visc', '0')) > 0.001:
warnings.append(tr(
'Viscosité élevée pour de l’eau : vérifiez la valeur, '
'qui n’a pas été convertie lors du changement '
'de mode.'))
'Viscosité élevée pour de l’eau : vérifiez la valeur. '
'Le seuil critique adimensionnel se saisit dans son '
'propre champ.'))
except ValueError:
pass
if (FIELDS['rubarbe_sediment_tcadim'].key in self.editors and
active(FIELDS['rubarbe_sediment_tcadim'], values) and
not values.get('rubarbe_sediment_tcadim', '').strip()):
warnings.append(tr(
'La loi et les options choisies utilisent un seuil '
'critique adimensionnel : renseignez-le.'))
self.notice.setText('\n'.join(warnings))
self.notice.setVisible(bool(warnings))