mirror of https://gitlab.com/pamhyr/pamhyr2
Checker: Add modules impact and add IC and BC study checker.
parent
6dc96b86b4
commit
8e82772cfc
|
|
@ -92,6 +92,21 @@ class AbstractModelChecker(object):
|
||||||
def is_error(self):
|
def is_error(self):
|
||||||
return self._status == STATUS.ERROR
|
return self._status == STATUS.ERROR
|
||||||
|
|
||||||
|
# Basic check
|
||||||
|
def basic_check(self, study):
|
||||||
|
if study is None:
|
||||||
|
self._status = STATUS.ERROR
|
||||||
|
self._summary = "invalid_study"
|
||||||
|
return False
|
||||||
|
|
||||||
|
river = study.river
|
||||||
|
if river is None:
|
||||||
|
self._status = STATUS.ERROR
|
||||||
|
self._summary = "no_river_found"
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
# Abstract function
|
# Abstract function
|
||||||
|
|
||||||
def _run(self, study):
|
def _run(self, study):
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import logging
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication
|
from PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
|
@ -25,6 +27,7 @@ from Checker.Checker import AbstractModelChecker, STATUS
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
class StudyNetworkReachChecker(AbstractModelChecker):
|
class StudyNetworkReachChecker(AbstractModelChecker):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -37,16 +40,10 @@ class StudyNetworkReachChecker(AbstractModelChecker):
|
||||||
self._modules = Modules.NETWORK
|
self._modules = Modules.NETWORK
|
||||||
|
|
||||||
def run(self, study):
|
def run(self, study):
|
||||||
if study is None:
|
if not self.basic_check(study):
|
||||||
self._status = STATUS.ERROR
|
|
||||||
self._summary = "invalid_study"
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
river = study.river
|
river = study.river
|
||||||
if river is None:
|
|
||||||
self._status = STATUS.ERROR
|
|
||||||
self._summary = "no_river_found"
|
|
||||||
return False
|
|
||||||
|
|
||||||
edges = list(filter(lambda e: e.is_enable(), river.edges()))
|
edges = list(filter(lambda e: e.is_enable(), river.edges()))
|
||||||
if len(edges) == 0:
|
if len(edges) == 0:
|
||||||
|
|
@ -77,16 +74,10 @@ class StudyGeometryChecker(AbstractModelChecker):
|
||||||
summary = "ok"
|
summary = "ok"
|
||||||
status = STATUS.OK
|
status = STATUS.OK
|
||||||
|
|
||||||
if study is None:
|
if not self.basic_check(study):
|
||||||
self._status = STATUS.ERROR
|
|
||||||
self._summary = "invalid_study"
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
river = study.river
|
river = study.river
|
||||||
if river is None:
|
|
||||||
self._status = STATUS.ERROR
|
|
||||||
self._summary = "no_river_found"
|
|
||||||
return False
|
|
||||||
|
|
||||||
edges = river.enable_edges()
|
edges = river.enable_edges()
|
||||||
if len(edges) == 0:
|
if len(edges) == 0:
|
||||||
|
|
@ -105,6 +96,118 @@ class StudyGeometryChecker(AbstractModelChecker):
|
||||||
self._status = status
|
self._status = status
|
||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
class StudyInitialConditionsChecker(AbstractModelChecker):
|
||||||
|
def __init__(self):
|
||||||
|
super(StudyInitialConditionsChecker, self).__init__()
|
||||||
|
|
||||||
|
self._name = _translate("Checker", "Study initial conditions checker")
|
||||||
|
self._description = _translate(
|
||||||
|
"Checker", "Check initial conditions for each node of study"
|
||||||
|
)
|
||||||
|
self._modules = Modules.INITIAL_CONDITION
|
||||||
|
|
||||||
|
def run(self, study):
|
||||||
|
ok = True
|
||||||
|
nerror = 0
|
||||||
|
self._summary = "ok"
|
||||||
|
self._status = STATUS.OK
|
||||||
|
|
||||||
|
if not self.basic_check(study):
|
||||||
|
return False
|
||||||
|
|
||||||
|
for reach in study.river.enable_edges():
|
||||||
|
ok &= self.check_reach(study, reach.reach)
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def check_reach(self, study, reach):
|
||||||
|
ok = True
|
||||||
|
river = study.river
|
||||||
|
|
||||||
|
if reach not in river.initial_conditions:
|
||||||
|
self._summary = "missing_initial_condition_defined"
|
||||||
|
self._status = STATUS.WARNING
|
||||||
|
return ok
|
||||||
|
|
||||||
|
ic = river.initial_conditions[reach]
|
||||||
|
len_ic = len(ic)
|
||||||
|
len_reach = len(reach)
|
||||||
|
|
||||||
|
if len_ic < len_reach:
|
||||||
|
self._summary = "initial_condition_missing_profile"
|
||||||
|
self._status = STATUS.WARNING
|
||||||
|
|
||||||
|
if len_ic > len_reach:
|
||||||
|
self._summary = "more_initial_condition_than_profile"
|
||||||
|
self._status = STATUS.ERROR
|
||||||
|
ok = False
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
class StudyBoundaryConditionChecker(AbstractModelChecker):
|
||||||
|
def __init__(self):
|
||||||
|
super(StudyBoundaryConditionChecker, self).__init__()
|
||||||
|
|
||||||
|
self._name = _translate("Checker", "Study boundary conditions checker")
|
||||||
|
self._description = _translate(
|
||||||
|
"Checker", "Check boundary conditions for each node of study"
|
||||||
|
)
|
||||||
|
self._modules = Modules.BOUNDARY_CONDITION
|
||||||
|
|
||||||
|
def run(self, study):
|
||||||
|
ok = True
|
||||||
|
nerror = 0
|
||||||
|
self._summary = "ok"
|
||||||
|
self._status = STATUS.OK
|
||||||
|
|
||||||
|
if not self.basic_check(study):
|
||||||
|
return False
|
||||||
|
|
||||||
|
ok = self.check_liquid(study)
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def check_liquid(self, study):
|
||||||
|
river = study.river
|
||||||
|
|
||||||
|
bcs = river.boundary_condition.get_tab('liquid')
|
||||||
|
if len(bcs) == 0:
|
||||||
|
self._status = STATUS.ERROR
|
||||||
|
self._summary = "no_boundary_condition_defined"
|
||||||
|
return False
|
||||||
|
|
||||||
|
upstream, downstream = reduce(
|
||||||
|
lambda acc, n: (
|
||||||
|
acc[0] + [n] if river.is_upstream_node(n) else acc[0],
|
||||||
|
acc[1] + [n] if river.is_downstream_node(n) else acc[1],
|
||||||
|
),
|
||||||
|
filter(
|
||||||
|
lambda n: river.is_enable_node(n),
|
||||||
|
river.nodes()
|
||||||
|
),
|
||||||
|
([], [])
|
||||||
|
)
|
||||||
|
|
||||||
|
bcs_nodes = set(map(lambda bc: bc.node, bcs))
|
||||||
|
|
||||||
|
upstream_ok = self.check_liquid_all_node_has_bc(bcs_nodes, upstream)
|
||||||
|
downstream_ok = self.check_liquid_all_node_has_bc(bcs_nodes, downstream)
|
||||||
|
|
||||||
|
ok = upstream_ok and downstream_ok
|
||||||
|
|
||||||
|
if not ok:
|
||||||
|
self._status = STATUS.ERROR
|
||||||
|
self._summary = "no_boundary_condition_at_boundary_node"
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def check_liquid_all_node_has_bc(self, bcs_nodes, nodes):
|
||||||
|
return reduce(
|
||||||
|
lambda acc, n: (acc and (n in bcs_nodes)),
|
||||||
|
nodes,
|
||||||
|
True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DummyOK(AbstractModelChecker):
|
class DummyOK(AbstractModelChecker):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,8 @@ class Study(SQLModel):
|
||||||
lst = [
|
lst = [
|
||||||
StudyNetworkReachChecker(),
|
StudyNetworkReachChecker(),
|
||||||
StudyGeometryChecker(),
|
StudyGeometryChecker(),
|
||||||
|
StudyInitialConditionsChecker(),
|
||||||
|
StudyBoundaryConditionChecker(),
|
||||||
# DummyOK(),
|
# DummyOK(),
|
||||||
# DummyWARNING(),
|
# DummyWARNING(),
|
||||||
# DummyERROR(),
|
# DummyERROR(),
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,20 @@ from enum import Flag, auto
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class Modules(Flag):
|
class IterableFlag(Flag):
|
||||||
|
def __iter__(self):
|
||||||
|
all = filter(
|
||||||
|
lambda v: v in self,
|
||||||
|
type(self).values()
|
||||||
|
)
|
||||||
|
return all
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def values(cls):
|
||||||
|
raise Exception("Not implemented yet")
|
||||||
|
|
||||||
|
|
||||||
|
class Modules(IterableFlag):
|
||||||
NONE = 0
|
NONE = 0
|
||||||
|
|
||||||
# General
|
# General
|
||||||
|
|
@ -48,6 +61,24 @@ class Modules(Flag):
|
||||||
# Display
|
# Display
|
||||||
WINDOW_LIST = auto()
|
WINDOW_LIST = auto()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def values(cls):
|
||||||
|
return [
|
||||||
|
cls.STUDY, cls.CONFIG,
|
||||||
|
cls.NETWORK,
|
||||||
|
cls.GEOMETRY,
|
||||||
|
cls.BOUNDARY_CONDITION,
|
||||||
|
cls.LATERAL_CONTRIBUTION,
|
||||||
|
cls.FRICTION,
|
||||||
|
cls.INITIAL_CONDITION,
|
||||||
|
cls.HYDRAULIC_STRUCTURES,
|
||||||
|
cls.RESERVOIR,
|
||||||
|
cls.SEDIMENT_LAYER,
|
||||||
|
cls.ADDITIONAL_FILES,
|
||||||
|
cls.RESULTS,
|
||||||
|
cls.WINDOW_LIST,
|
||||||
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def all(cls):
|
def all(cls):
|
||||||
return ~cls.NONE
|
return ~cls.NONE
|
||||||
|
|
@ -93,3 +124,40 @@ class Modules(Flag):
|
||||||
cls.RESERVOIR: "Reservoir",
|
cls.RESERVOIR: "Reservoir",
|
||||||
cls.SEDIMENT_LAYER: "Sediment layer",
|
cls.SEDIMENT_LAYER: "Sediment layer",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def impact(self):
|
||||||
|
res = Modules(0)
|
||||||
|
for mod in self:
|
||||||
|
if mod in _impact:
|
||||||
|
for i in _impact[mod]:
|
||||||
|
res |= i
|
||||||
|
return res
|
||||||
|
|
||||||
|
def impact_set(self):
|
||||||
|
res = []
|
||||||
|
for mod in self:
|
||||||
|
if mod in _impact:
|
||||||
|
res += _impact[mod]
|
||||||
|
|
||||||
|
return set(res)
|
||||||
|
|
||||||
|
_impact = {
|
||||||
|
Modules.NETWORK: [
|
||||||
|
Modules.GEOMETRY, Modules.BOUNDARY_CONDITION,
|
||||||
|
Modules.LATERAL_CONTRIBUTION, Modules.FRICTION,
|
||||||
|
Modules.RESERVOIR, Modules.SEDIMENT_LAYER,
|
||||||
|
],
|
||||||
|
Modules.GEOMETRY: [
|
||||||
|
Modules.LATERAL_CONTRIBUTION, Modules.FRICTION,
|
||||||
|
Modules.INITIAL_CONDITION, Modules.SEDIMENT_LAYER,
|
||||||
|
],
|
||||||
|
Modules.BOUNDARY_CONDITION: [
|
||||||
|
Modules.SEDIMENT_LAYER
|
||||||
|
],
|
||||||
|
Modules.LATERAL_CONTRIBUTION: [],
|
||||||
|
Modules.FRICTION: [],
|
||||||
|
Modules.INITIAL_CONDITION: [],
|
||||||
|
Modules.HYDRAULIC_STRUCTURES: [],
|
||||||
|
Modules.RESERVOIR: [],
|
||||||
|
Modules.SEDIMENT_LAYER: [],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,9 @@ class WidgetChecker(PamhyrWidget):
|
||||||
self._study = study
|
self._study = study
|
||||||
|
|
||||||
def _checkers_filtered(self, modules):
|
def _checkers_filtered(self, modules):
|
||||||
|
impacted = modules | modules.impact()
|
||||||
return filter(
|
return filter(
|
||||||
lambda c: c._modules in modules,
|
lambda c: c._modules in impacted,
|
||||||
self._checkers
|
self._checkers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue