Commit 8e82772c authored by Pierre-Antoine Rouby's avatar Pierre-Antoine Rouby
Browse files

Checker: Add modules impact and add IC and BC study checker.

Showing with 205 additions and 16 deletions
+205 -16
...@@ -92,6 +92,21 @@ class AbstractModelChecker(object): ...@@ -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 @@ ...@@ -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 ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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 ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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
) )
......
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