Merge branch 'master' of gitlab-ssh.irstea.fr:theophile.terraz/pamhyr

setup.py
Theophile Terraz 2023-11-29 15:26:22 +01:00
commit 8d67442ca3
4 changed files with 202 additions and 23 deletions

View File

@ -345,3 +345,9 @@ class Profile(object):
# Abstract method, must be implemented for in non abstract class # Abstract method, must be implemented for in non abstract class
def get_station(self): def get_station(self):
raise NotImplementedMethodeError(self, self.get_station) raise NotImplementedMethodeError(self, self.get_station)
# Computation method
# Abstract method for width approximation
def width_approximation(self):
raise NotImplementedMethodeError(self, self.width_approximation)

View File

@ -287,6 +287,27 @@ class ProfileXYZ(Profile, SQLSubModel):
except IndexError: except IndexError:
raise IndexError(f"Invalid point index: {index}") raise IndexError(f"Invalid point index: {index}")
def get_point_by_name(self, name: str) -> PointXYZ:
"""Get point by name.
Args:
name: Point name.
Returns:
The point.
"""
try:
n_name = name.lower().strip()
return next(
filter(
lambda p: p.name.lower().strip() == n_name,
self.points
)
)
except Exception as e:
logger.debug(f"{e}")
raise IndexError(f"Invalid point name: {name}")
def add(self): def add(self):
"""Add a new PointXYZ to profile. """Add a new PointXYZ to profile.
@ -415,3 +436,9 @@ class ProfileXYZ(Profile, SQLSubModel):
constant = station[index_profile_z_min[0]] constant = station[index_profile_z_min[0]]
return list(map(lambda s: s - constant, station)) return list(map(lambda s: s - constant, station))
def width_approximation(self):
rg = self.get_point_by_name("rg")
rd = self.get_point_by_name("rd")
return abs(rg.dist(rd))

View File

@ -578,3 +578,103 @@ class Reach(SQLSubModel):
file_st.write(" 999.9990 999.9990 999.9990") file_st.write(" 999.9990 999.9990 999.9990")
file_st.write("\n") file_st.write("\n")
def get_incline(self):
first = self.profile(0)
last = self.profile(len(self) - 1)
z_first = first.z_min()
kp_first = first.kp
z_last = last.z_min()
kp_last = last.kp
return (
(z_last - z_first)
/
(kp_last - kp_first)
)
def get_incline_mean(self):
profiles = self.profiles
previous = profiles[0]
incline_acc = 0
for profile in profiles[1:]:
z_first = previous.z_min()
kp_first = previous.kp
z_last = profile.z_min()
kp_last = profile.kp
incline_acc += (
(z_last - z_first)
/
(kp_last - kp_first)
)
previous = profile
return (incline_acc / (len(profiles) - 1))
def get_incline_median(self):
profiles = self.profiles
previous = profiles[0]
incline_acc = []
for profile in profiles[1:]:
z_first = previous.z_min()
kp_first = previous.kp
z_last = profile.z_min()
kp_last = profile.kp
incline_acc += [
(z_last - z_first)
/
(kp_last - kp_first)
]
previous = profile
incline_acc.sort()
return incline_acc[round(len(profiles)/2)]
def get_incline_median_mean(self):
profiles = self.profiles
previous = profiles[0]
incline_acc = []
for profile in profiles[1:]:
z_first = previous.z_min()
kp_first = previous.kp
z_last = profile.z_min()
kp_last = profile.kp
incline_acc += [
(z_last - z_first)
/
(kp_last - kp_first)
]
previous = profile
incline_acc.sort()
marge = round(len(incline_acc) * 0.1)
incline_set = incline_acc[marge:-marge]
logger.debug(f"+{incline_acc}")
logger.debug(f"-{incline_set}")
return (
reduce(
lambda acc, x: acc + x,
incline_set,
0.0
) / (len(incline_set))
)

View File

@ -16,12 +16,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from copy import copy, deepcopy from copy import copy, deepcopy
from tools import trace, timer from tools import trace, timer
from functools import reduce from functools import reduce
from Model.Tools.PamhyrDB import SQLSubModel from Model.Tools.PamhyrDB import SQLSubModel
logger = logging.getLogger()
class Data(SQLSubModel): class Data(SQLSubModel):
def __init__(self, name: str = "", def __init__(self, name: str = "",
@ -358,37 +362,79 @@ class InitialConditions(SQLSubModel):
profiles = self._reach.reach.profiles.copy() profiles = self._reach.reach.profiles.copy()
self._sort_by_z_and_kp(profiles) self._sort_by_z_and_kp(profiles)
prev = None incline = self._reach.reach.get_incline_median_mean()
logger.debug(f"incline = {incline}")
previous_elevation = -99999.99
for profile in profiles: for profile in profiles:
width = profile.width_approximation()
strickler = 25
discharge = (
((width * 0.8)
* strickler
* (height ** (5/3))
* (abs(incline) ** (0.5)))
)
elevation= max(
profile.z_min() + height,
previous_elevation
)
logger.debug(f"({profile.kp}):")
logger.debug(f" width = {width}")
logger.debug(f" strickler = {strickler}")
logger.debug(f" discharge = {discharge}")
new = Data(reach=self._reach, status=self._status) new = Data(reach=self._reach, status=self._status)
new["kp"] = profile.kp new["kp"] = profile.kp
new["discharge"] = discharge
if prev is None: new["elevation"] = elevation
new["elevation"] = profile.z_min() + height
else:
new["elevation"] = max(
profile.z_min() + height,
prev["elevation"]
)
self._data.append(new) self._data.append(new)
prev = new previous_elevation = elevation
is_reverse = False
if profiles[0].kp > profiles[-1].kp:
is_reverse = True
self._data.sort(
reverse=not is_reverse,
key=lambda d: d['kp']
)
def generate_discharge(self, discharge: float): def generate_discharge(self, discharge: float):
self._new = [] self._data = []
for d in self._data: self._generate_height_estimation_from_discharge(
n = d.copy() discharge
n['discharge'] = discharge )
self._new.append(n)
self._data = self._new def _generate_height_estimation_from_discharge(self, discharge: float):
profiles = self._reach.reach.profiles.copy()
self._sort_by_z_and_kp(profiles)
previous_elevation = -99999.99
incline = self._reach.reach.get_incline_median_mean()
logger.debug(f"incline = {incline}")
for profile in profiles:
width = profile.width_approximation()
strickler = 25
height = (
discharge
/
((width * 0.8) * strickler * (abs(incline) ** (0.5)))
) ** (0.6)
elevation= max(
profile.z_min() + height,
previous_elevation
)
logger.debug(f"({profile.kp}):")
logger.debug(f" width = {width}")
logger.debug(f" strickler = {strickler}")
logger.debug(f" hieght = {height}")
new = Data(reach=self._reach, status=self._status)
new["kp"] = profile.kp
new["discharge"] = discharge
new["elevation"] = elevation
previous_elevation = elevation
self._data.append(new)