Commit c17e39e3 authored by Theophile Terraz's avatar Theophile Terraz
Browse files

Merge branch 'hydraulics-structure' of...

Merge branch 'hydraulics-structure' of gitlab-ssh.irstea.fr:theophile.terraz/pamhyr into hydraulics-structure
Showing with 722 additions and 1 deletion
+722 -1
# HydraulicStructures.py -- Pamhyr
# Copyright (C) 2023 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import logging
from tools import trace, timer
from Model.Tools.PamhyrDB import SQLSubModel
from Model.Except import NotImplementedMethodeError
from Model.HydraulicStructures.Basic.Value import (
BHSValue
)
logger = logging.getLogger()
class BasicHS(SQLSubModel):
_sub_classes = [
BHSValue,
]
_id_cnt = 0
def __init__(self, id: int = -1, name: str = "",
status=None):
super(BasicHS, self).__init__()
self._status = status
if id == -1:
self.id = BasicHS._id_cnt
else:
self.id = id
self._name = name
self._type = ""
self._enabled = True
self._data = []
BasicHS._id_cnt = max(BasicHS._id_cnt + 1, self.id)
@classmethod
def _db_create(cls, execute):
execute("""
CREATE TABLE hydraulic_structures_basic(
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
type TEXT NOT NULL,
enabled BOOLEAN NOT NULL,
hs INTEGER,
FOREIGN KEY(hs) REFERENCES hydraulic_structures(id)
)
""")
return cls._create_submodel(execute)
@classmethod
def _db_update(cls, execute, version):
major, minor, release = version.strip().split(".")
if major == minor == "0":
if int(release) < 6:
cls._db_create(execute)
return True
@classmethod
def _get_ctor_from_type(cls, t):
from Model.HydraulicStructure.Basic.Types import (
NotDefined,
)
res = NotDefined
return res
@classmethod
def _db_load(cls, execute, data=None):
new = []
table = execute(
"SELECT id, name, type, enabled, hs " +
"FROM hydraulic_structures "
)
for row in table:
bhs_id = row[0]
name = row[1]
type = row[2]
enabled = (row[3] == 1)
hs_id = row[4]
ctor = cls._get_ctor_from_type(type)
bhs = ctor(
id=bhs_id,
name=name,
status=data['status']
)
bhs.enabled = enabled
data['bhs_id'] = bhs_id
bhs._data = BasicHSValue._db_load(
execute, data
)
new.append(bhs)
return new
def _db_save(self, execute, data=None):
execute(
"DELETE FROM hydraulic_structures_basic " +
f"WHERE id = {self.id}"
)
hs_id = data['hs_id']
sql = (
"INSERT INTO " +
"hydraulic_structures_basic(id, name, type, enabled, hs) " +
"VALUES (" +
f"{self.id}, " +
f"'{self._db_format(self._name)}', " +
f"'{self._db_format(self._type)}', " +
f"{self._db_format(self.enabled)}, " +
f"{hs_id} " +
")"
)
execute(sql)
data['bhs_id'] = self.id
execute(
"DELETE FROM hydraulic_structures_basic_value "+
f"WHERE bhs = {bhs_id}"
)
for values in self._data:
values._db_save(execute, data)
return True
def __len__(self):
return len(self._data)
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
self._status.modified()
@property
def type(self):
return self._type
@type.setter
def type(self, type):
self._type = type
self._status.modified()
@property
def enabled(self):
return self._enabled
@enabled.setter
def enabled(self, enabled):
self._enabled = enabled
self._status.modified()
@property
def lst(self):
return self._data.copy()
# Types.py -- Pamhyr
# Copyright (C) 2023 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from Model.Except import NotImplementedMethodeError
from Model.HydraulicStructures.Basic.HydraulicStructures import (
BasicHS
)
from Model.HydraulicStructures.Basic.Value import (
BHSValue
)
class NotDefined(BasicHS):
def __init__(self, id: int = -1, name: str = "", status=None):
super(NotDefined, self).__init__(id=id, name=name, status=status)
self._type = "ND"
self._data = [
BHSValue("foo", float, 0.0),
BHSValue("bar", float, 42.0),
BHSValue("baz", int, 13),
]
# Value.py -- Pamhyr
# Copyright (C) 2023 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from Model.Tools.PamhyrDB import SQLSubModel
class BHSValue(SQLSubModel):
_sub_classes = []
_id_cnt = 0
def __init__(self, name: str = "", type = float, value = 0.0,
status=None):
super(BHSValue, self).__init__()
self._status = status
self._name = name
self._type = type
self._value = type(value)
@classmethod
def _db_create(cls, execute):
execute("""
CREATE TABLE hydraulic_structures_basic_value(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
type TEXT NOT NULL,
value TEXT NOT NULL,
bhs INTEGER,
FOREIGN KEY(bhs) REFERENCES hydraulic_structures_basic(id)
)
""")
return cls._create_submodel(execute)
@classmethod
def _db_update(cls, execute, version):
major, minor, release = version.strip().split(".")
if major == minor == "0":
if int(release) < 6:
cls._db_create(execute)
return True
@classmethod
def _str_to_type(cls, type):
res = str
if type == "float":
res = float
elif type == "int":
res = int
elif type == "bool":
res = bool
return res
@classmethod
def _type_to_str(cls, type):
res = "str"
if type == float:
res = "float"
elif type == int:
res = "int"
elif type == bool:
res = "bool"
return res
@classmethod
def _db_load(cls, execute, data=None):
new = []
bhs_id = data["bhs_id"]
table = execute(
"SELECT name, type, value " +
"FROM hydraulic_structures_basic_value " +
f"WHERE bhs = '{bhs_id}'"
)
for row in table:
name = row[0]
type = cls._str_to_type(row[1])
value = row[2]
val = cls(
name=name,
type=type,
value=value,
status=data['status']
)
new.append(val)
return new
def _db_save(self, execute, data=None):
bhs_id = data["bhs_id"]
sql = (
"INSERT INTO " +
"hydraulic_structures_basic_value(name, type, value, bhs) " +
"VALUES (" +
f"'{self._db_format(self._name)}', " +
f"'{self._db_format(self._type_to_str(self._type))}', "+
f"'{self._db_format(self._value)}', " +
f"{bhs_id}" +
")"
)
execute(sql)
return True
@property
def name(self):
return self._name
@property
def type(self):
return self._type
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = self._type(value)
self._status.modified()
# HydraulicStructures.py -- Pamhyr
# Copyright (C) 2023 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import logging
from tools import trace, timer, old_pamhyr_date_to_timestamp
from Model.Tools.PamhyrDB import SQLSubModel
from Model.Except import NotImplementedMethodeError
from Model.HydraulicStructures.Basic.HydraulicStructures import BasicHS
logger = logging.getLogger()
class HydraulicStructure(SQLSubModel):
_sub_classes = [
BasicHS,
]
_id_cnt = 0
def __init__(self, id: int = -1, name: str = "",
status=None):
super(HydraulicStructure, self).__init__()
self._status = status
if id == -1:
self.id = HydraulicStructure._id_cnt
else:
self.id = id
self._name = name
self._input_kp = None
self._output_kp = None
self._input_reach = None
self._output_reach = None
self._enabled = True
self._data = []
HydraulicStructure._id_cnt = max(HydraulicStructure._id_cnt + 1, self.id)
@classmethod
def _db_create(cls, execute):
execute("""
CREATE TABLE hydraulic_structures(
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
enabled BOOLEAN NOT NULL,
input_kp INTEGER,
output_kp INTEGER,
input_reach INTEGER,
output_reach INTEGER,
FOREIGN KEY(input_reach) REFERENCES river_reach(id),
FOREIGN KEY(output_reach) REFERENCES river_reach(id)
)
""")
return cls._create_submodel(execute)
@classmethod
def _db_update(cls, execute, version):
major, minor, release = version.strip().split(".")
if major == minor == "0":
if int(release) < 6:
cls._db_create(execute)
return True
@classmethod
def _db_load(cls, execute, data=None):
new = []
table = execute(
"SELECT id, name, enabled, " +
"input_kp, output_kp, " +
"input_reach, output_reach " +
"FROM hydraulic_structures "
)
for row in table:
it = iter(row)
hs_id = next(it)
name = next(it)
enabled = (next(it) == 1)
input_kp = next(it)
output_kp = next(it)
input_reach_id = next(it)
output_reach_id = next(it)
hs = cls(
id=hs_id,
name=name,
status=data['status']
)
hs.enabled = enabled
hs.input_kp = input_kp
hs.output_kp = output_kp
hs.input_reach, hs.output_reach = reduce(
lambda acc, n: (
n if n.id == input_reach_id else acc[0],
n if n.id == output_reach_id else acc[1]
),
data["reachs"],
[None, None]
)
data['hs_id'] = hs_id
hs._data = BasicHS._db_load(execute, data)
new.append(hs)
return new
def _db_save(self, execute, data=None):
execute(f"DELETE FROM hydraulic_structures WHERE id = {self.id}")
input_reach_id = -1
if self._input_reach is not None:
input_reach_id = self._input_reach.id
output_reach_id = -1
if self._output_reach is not None:
output_reach_id = self._output_reach.id
sql = (
"INSERT INTO " +
"hydraulic_structures(" +
" id, name, enabled, input_kp, output_kp, " +
" input_reach, output_reach" +
") " +
"VALUES (" +
f"{self.id}, '{self._db_format(self._name)}', " +
f"{self._db_format(self.enabled)}, " +
f"{self.input_kp}, {self.input_kp}, " +
f"{input_reach_id}, {output_reach_id}" +
")"
)
execute(sql)
data['hs_id'] = self.id
for basic in self._data:
basic._db_save(execute, data)
return True
def __len__(self):
return len(self._data)
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
self._status.modified()
@property
def input_kp(self):
return self._input_kp
@input_kp.setter
def input_kp(self, input_kp):
self._input_kp = input_kp
self._status.modified()
@property
def output_kp(self):
return self._output_kp
@output_kp.setter
def output_kp(self, output_kp):
self._output_kp = output_kp
self._status.modified()
@property
def enabled(self):
return self._enabled
@enabled.setter
def enabled(self, enabled):
self._enabled = enabled
self._status.modified()
@property
def input_reach(self):
return self._input_reach
@input_reach.setter
def input_reach(self, input_reach):
self._input_reach = input_reach
self._status.modified()
@property
def output_reach(self):
return self._output_reach
@output_reach.setter
def output_reach(self, output_reach):
self._output_reach = output_reach
self._status.modified()
@property
def basic_structures(self):
return self._data.copy()
def add(self, index: int):
value = BasicHS(status=self._status)
self._data.insert(index, value)
self._status.modified()
return value
def insert(self, index: int, value: BasicHS):
self._data.insert(index, value)
self._status.modified()
def delete_i(self, indexes):
self._data = list(
map(
lambda e: e[1],
filter(
lambda e: e[0] not in indexes,
enumerate(self.data)
)
)
)
self._status.modified()
def delete(self, els):
self._data = list(
filter(
lambda e: e not in els,
self.data
)
)
self._status.modified()
def sort(self, _reverse=False, key=None):
if key is None:
self._data.sort(reverse=_reverse)
else:
self._data.sort(reverse=_reverse, key=key)
self._status.modified()
# HydraulicStructuresList.py -- Pamhyr
# Copyright (C) 2023 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from copy import copy
from tools import trace, timer
from Model.Tools.PamhyrList import PamhyrModelList
from Model.HydraulicStructures.HydraulicStructures import HydraulicStructure
class HydraulicStructureList(PamhyrModelList):
_sub_classes = [
HydraulicStructure,
]
@classmethod
def _db_load(cls, execute, data=None):
new = cls(status=data['status'])
if data is None:
data = {}
new._lst = HydraulicStructure._db_load(
execute, data
)
return new
def _db_save(self, execute, data=None):
execute("DELETE FROM hydraulic_structures")
if data is None:
data = {}
for hs in self._lst:
hs._db_save(execute, data=data)
return True
def new(self, lst, index):
n = HydraulicStructure(status=self._status)
self._lst.insert(index, n)
self._status.modified()
return n
def __copy__(self):
new = HydraulicStructureList()
for lst in self._tabs:
new.tabs[lst] = self._tabs[lst].copy()
return new
def __deepcopy__(self):
new = HydraulicStructureList()
for lst in self._tabs:
new.tabs[lst] = self._tabs[lst].deepcopy()
return new
def copy(self):
return copy(self)
...@@ -37,6 +37,9 @@ from Model.Friction.FrictionList import FrictionList ...@@ -37,6 +37,9 @@ from Model.Friction.FrictionList import FrictionList
from Model.SolverParameters.SolverParametersList import SolverParametersList from Model.SolverParameters.SolverParametersList import SolverParametersList
from Model.SedimentLayer.SedimentLayerList import SedimentLayerList from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
from Model.Reservoir.ReservoirList import ReservoirList from Model.Reservoir.ReservoirList import ReservoirList
from Model.HydraulicStructures.HydraulicStructuresList import (
HydraulicStructureList,
)
from Solver.Solvers import solver_type_list from Solver.Solvers import solver_type_list
...@@ -219,6 +222,7 @@ class River(Graph, SQLSubModel): ...@@ -219,6 +222,7 @@ class River(Graph, SQLSubModel):
SolverParametersList, SolverParametersList,
SedimentLayerList, SedimentLayerList,
ReservoirList, ReservoirList,
HydraulicStructureList,
] ]
def __init__(self, status=None): def __init__(self, status=None):
...@@ -237,6 +241,7 @@ class River(Graph, SQLSubModel): ...@@ -237,6 +241,7 @@ class River(Graph, SQLSubModel):
self._parameters = {} self._parameters = {}
self._sediment_layers = SedimentLayerList(status=self._status) self._sediment_layers = SedimentLayerList(status=self._status)
self._reservoir = ReservoirList(status=self._status) self._reservoir = ReservoirList(status=self._status)
self._hydraulic_structures = HydraulicStructureList(status=self._status)
@classmethod @classmethod
def _db_create(cls, execute): def _db_create(cls, execute):
...@@ -303,6 +308,12 @@ class River(Graph, SQLSubModel): ...@@ -303,6 +308,12 @@ class River(Graph, SQLSubModel):
data data
) )
# Hydraulic Structures
new._hydraulic_structures = HydraulicStructureList._db_load(
execute,
data
)
# Parameters # Parameters
new._parameters = SolverParametersList._db_load( new._parameters = SolverParametersList._db_load(
execute, execute,
...@@ -319,6 +330,7 @@ class River(Graph, SQLSubModel): ...@@ -319,6 +330,7 @@ class River(Graph, SQLSubModel):
objs.append(self._sediment_layers) objs.append(self._sediment_layers)
objs.append(self._stricklers) objs.append(self._stricklers)
objs.append(self._reservoir) objs.append(self._reservoir)
objs.append(self._hydraulic_structures)
for solver in self._parameters: for solver in self._parameters:
objs.append(self._parameters[solver]) objs.append(self._parameters[solver])
...@@ -363,6 +375,10 @@ class River(Graph, SQLSubModel): ...@@ -363,6 +375,10 @@ class River(Graph, SQLSubModel):
def reservoir(self): def reservoir(self):
return self._reservoir return self._reservoir
@property
def hydraulics_structures(self):
return self._hydraulics_structures
@property @property
def parameters(self): def parameters(self):
return self._parameters return self._parameters
......
...@@ -41,7 +41,7 @@ class Study(SQLModel): ...@@ -41,7 +41,7 @@ class Study(SQLModel):
def __init__(self, filename=None, init_new=True): def __init__(self, filename=None, init_new=True):
# Metadata # Metadata
self._version = "0.0.5" self._version = "0.0.6"
self.creation_date = datetime.now() self.creation_date = datetime.now()
self.last_modification_date = datetime.now() self.last_modification_date = datetime.now()
self.last_save_date = datetime.now() self.last_save_date = datetime.now()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment