diff --git a/src/View/CheckList/Window.py b/src/View/CheckList/Window.py
index 0004f3e9399886b290ebb9baf42224b145f0681d..d96994a805f13cba329222e14cc1af06abd45c1e 100644
--- a/src/View/CheckList/Window.py
+++ b/src/View/CheckList/Window.py
@@ -68,6 +68,9 @@ class CheckListWindow(PamhyrWindow):
             parent=parent
         )
 
+        # Add solver to hash computation data
+        self._hash_data.append(self._solver)
+
         self._checker_list = (
             self._study.checkers() +
             self._solver.checkers()
diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py
index 2558ab432eafc47a64c1f214afc32ac42fc9482b..b6dd6afaec0e4f7244d2b404478da8ecc172ebbd 100644
--- a/src/View/Frictions/Window.py
+++ b/src/View/Frictions/Window.py
@@ -83,6 +83,9 @@ class FrictionsWindow(PamhyrWindow):
             parent=parent
         )
 
+        # Add reach to hash computation data
+        self._hash_data.append(self._reach)
+
         self.setup_table()
         self.setup_graph()
         self.setup_connections()
diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py
index eca958b454bf5046a939c5f40a134600851ae4f2..ac021ad1b3b3541e6ab766cdc761f4dc5a1a5407 100644
--- a/src/View/Geometry/Window.py
+++ b/src/View/Geometry/Window.py
@@ -73,6 +73,9 @@ class GeometryWindow(PamhyrWindow):
             parent=parent
         )
 
+        # Add reach to hash computation data
+        self._hash_data.append(self._reach)
+
         self._tablemodel = None
         self._profile_window = []
 
diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py
index 6fb29ca2d2d4ecad81a6ff3a3bb7a0f28586a7fa..a0911c4be718961e260b9f0042d5ef8940f76043 100644
--- a/src/View/InitialConditions/Window.py
+++ b/src/View/InitialConditions/Window.py
@@ -87,6 +87,9 @@ class InitialConditionsWindow(PamhyrWindow):
             parent=parent
         )
 
+        # Add reach to hash computation data
+        self._hash_data.append(self._reach)
+
         self._ics = study.river.initial_conditions.get(self._reach)
 
         self.setup_table()
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 2c77ed7159dc1146af6c47f24ac40098c4e3e8c4..116045038d0d40f480dfe71edda2ca5bdbe2821a 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -480,6 +480,30 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
     # SUBWINDOW #
     #############
 
+    def _sub_window_exists(self, cls,
+                           data=None):
+        """Check if window already exists
+
+        Check if window already exists, used to deni window open
+        duplication
+
+        Args:
+            cls: Window class, must inerit to PamhyrWindow or
+                PamhyrDialog
+            data: Data used for hash computation of cls
+
+        Returns:
+            The window if hash already exists on sub window dictionary,
+            otherelse None
+        """
+        hash = cls._hash(data)
+        if self.sub_win_exists(hash):
+            win = self.get_sub_win(hash)
+            win.activateWindow()
+            return True
+        else:
+            return False
+
     def open_configure(self):
         """Open configure window
 
@@ -488,6 +512,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         Returns:
             Nothing
         """
+        if self._sub_window_exists(
+            ConfigureWindow,
+            data=[None, self.conf]
+        ):
+            return
+
         self.config = ConfigureWindow(config=self.conf, parent=self)
         self.config.show()
 
@@ -499,6 +529,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         Returns:
             Nothing
         """
+        if self._sub_window_exists(
+            AboutWindow,
+            data=[None, None]
+        ):
+            return
+
         self.about = AboutWindow(parent=self)
         self.about.show()
 
@@ -527,6 +563,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             Nothing
         """
         if self._study is None:
+            if self._sub_window_exists(
+                NewStudyWindow,
+                data=[None, None]
+            ):
+                return
+
             self.new_study = NewStudyWindow(parent=self)
             self.new_study.show()
 
@@ -537,6 +579,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             Nothing
         """
         if self._study is not None:
+            if self._sub_window_exists(
+                NewStudyWindow,
+                data=[self._study, None]
+            ):
+                return
+
             self.new_study = NewStudyWindow(study=self._study, parent=self)
             self.new_study.show()
 
@@ -547,11 +595,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             Nothing
         """
         if self._study is not None:
-            if not self.sub_win_exists("River network"):
-                self.network = NetworkWindow(study=self._study, parent=self)
-                self.network.show()
-            else:
-                self.network.activateWindow()
+            if self._sub_window_exists(
+                NetworkWindow,
+                data=[self._study, None]
+            ):
+                return
+
+            self.network = NetworkWindow(study=self._study, parent=self)
+            self.network.show()
 
     def open_geometry(self):
         """Open geometry window
@@ -560,115 +611,117 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             Nothing
         """
         if (self._study is not None and self._study.river.has_current_reach()):
-            geometry = self.sub_win_filter_first(
-                "Geometry",
-                contain=[self._study.river.current_reach().name]
-            )
+            reach = self._study.river.current_reach().reach
 
-            if geometry is None:
-                geometry = GeometryWindow(
-                    study=self._study, config=self.conf, parent=self)
-                geometry.show()
-            else:
-                geometry.activateWindow()
+            if self._sub_window_exists(
+                GeometryWindow,
+                data=[self._study, self.conf, reach]
+            ):
+                return
+
+            geometry = GeometryWindow(
+                study=self._study,
+                config=self.conf,
+                reach=reach,
+                parent=self
+            )
+            geometry.show()
         else:
             self.msg_select_reach()
 
     def open_boundary_cond(self):
-        bound = self.sub_win_filter_first(
-            "Boundary conditions",
-            contain=[]
-        )
+        if self._sub_window_exists(
+            BoundaryConditionWindow,
+            data=[self._study, None]
+        ):
+            return
 
-        if bound is None:
-            bound = BoundaryConditionWindow(study=self._study, parent=self)
-            bound.show()
-        else:
-            bound.activateWindow()
+        bound = BoundaryConditionWindow(study=self._study, parent=self)
+        bound.show()
 
     def open_lateral_contrib(self):
-        lateral = self.sub_win_filter_first(
-            "Lateral contribution",
-            contain=[]
-        )
+        if self._sub_window_exists(
+            LateralContributionWindow,
+            data=[self._study, None]
+        ):
+            return
 
-        if lateral is None:
-            lateral = LateralContributionWindow(study=self._study, parent=self)
-            lateral.show()
-        else:
-            lateral.activateWindow()
+        lateral = LateralContributionWindow(study=self._study, parent=self)
+        lateral.show()
 
     def open_stricklers(self):
-        strick = self.sub_win_filter_first(
-            "Stricklers",
-            contain=[]
-        )
+        if self._sub_window_exists(
+            StricklersWindow,
+            data=[self._study, self.conf]
+        ):
+            return
 
-        if strick is None:
-            strick = StricklersWindow(
-                study=self._study,
-                config=self.conf,
-                parent=self
-            )
-            strick.show()
-        else:
-            strick.activateWindow()
+        strick = StricklersWindow(
+            study=self._study,
+            config=self.conf,
+            parent=self
+        )
+        strick.show()
 
     def open_frictions(self):
-        if (self._study is not None and
-                self._study.river.has_current_reach()):
+        if self._study is not None:
+            if self._study.river.has_current_reach():
+                reach = self._study.river.current_reach()
 
-            frictions = self.sub_win_filter_first(
-                "Frictions",
-                contain=[self._study.river.current_reach().name]
-            )
+                if self._sub_window_exists(
+                    FrictionsWindow,
+                    data=[self._study, None, reach]
+                ):
+                    return
 
-            if frictions is None:
                 frictions = FrictionsWindow(
                     study=self._study,
                     parent=self
                 )
                 frictions.show()
             else:
-                frictions.activateWindow()
-        else:
-            self.msg_select_reach()
+                self.msg_select_reach()
 
     def open_initial_conditions(self):
         if self._study.river.has_current_reach():
-            initial = self.sub_win_filter_first(
-                "Initial condition",
-                contain=[self._study.river.current_reach().name]
-            )
-
-            if initial is None:
-                initial = InitialConditionsWindow(
-                    study=self._study,
-                    config=self.conf,
-                    parent=self
-                )
-                initial.show()
-            else:
-                initial.activateWindow()
-        else:
-            self.msg_select_reach()
+            reach = self._study.river.current_reach()
 
-    def open_solver_parameters(self):
-        params = self.sub_win_filter_first(
-            "Solver parameters",
-            contain=[]
-        )
+            if self._sub_window_exists(
+                InitialConditionsWindow,
+                data=[self._study, self.conf, reach]
+            ):
+                return
 
-        if params is None:
-            params = SolverParametersWindow(
+            initial = InitialConditionsWindow(
                 study=self._study,
+                config=self.conf,
+                reach=reach,
                 parent=self
             )
-            params.show()
+            initial.show()
         else:
-            params.activateWindow()
+            self.msg_select_reach()
+
+    def open_solver_parameters(self):
+        if self._sub_window_exists(
+            SolverParametersWindow,
+            data=[self._study, None]
+        ):
+            return
+
+        params = SolverParametersWindow(
+            study=self._study,
+            parent=self
+        )
+        params.show()
 
     def open_sediment_layers(self):
+        if self._sub_window_exists(
+            SedimentLayersWindow,
+            data=[self._study, None]
+        ):
+            return
+
         sl = SedimentLayersWindow(
             study=self._study,
             parent=self
@@ -676,8 +729,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         sl.show()
 
     def open_reach_sediment_layers(self):
+        reach = self._study.river.current_reach().reach
+
+        if self._sub_window_exists(
+            ReachSedimentLayersWindow,
+            data=[self._study, None, reach]
+        ):
+            return
+
         sl = ReachSedimentLayersWindow(
             study=self._study,
+            reach=reach,
             parent=self
         )
         sl.show()
@@ -693,6 +755,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         )
         if run.exec():
             solver = run.solver
+
+            if self._sub_window_exists(
+                CheckListWindow,
+                data=[
+                    self._study,
+                    self.conf,
+                    solver
+                ]
+            ):
+                return
+
             check = CheckListWindow(
                 study=self._study,
                 config=self.conf,
diff --git a/src/View/SedimentLayers/Reach/Window.py b/src/View/SedimentLayers/Reach/Window.py
index 6c4cad968efd2cd829cd95b3af9eb646b230ac8b..854e06a59564138de185f56994f71903bd25edff 100644
--- a/src/View/SedimentLayers/Reach/Window.py
+++ b/src/View/SedimentLayers/Reach/Window.py
@@ -46,9 +46,12 @@ class ReachSedimentLayersWindow(PamhyrWindow):
     _pamhyr_ui = "ReachSedimentLayers"
     _pamhyr_name = "Reach sediment layers"
 
-    def __init__(self, study=None, config=None, parent=None):
+    def __init__(self, study=None, config=None, reach=None, parent=None):
         self._sediment_layers = study.river.sediment_layers
-        self._reach = study.river.current_reach().reach
+        if reach is None:
+            self._reach = study.river.current_reach().reach
+        else:
+            self._reach = reach
 
         name = (
             self._pamhyr_name + " - " +
@@ -64,6 +67,9 @@ class ReachSedimentLayersWindow(PamhyrWindow):
             parent=parent
         )
 
+        # Add reach to hash computation data
+        self._hash_data.append(self._reach)
+
         self.setup_table()
         self.setup_plot()
         self.setup_connections()
diff --git a/src/View/Tools/ASubWindow.py b/src/View/Tools/ASubWindow.py
index a2e8fc88baa3b4de0c63c43daa84469f37d21d58..0a3ca2ae6cdf0dc3ef40f98851f2a676a809efb5 100644
--- a/src/View/Tools/ASubWindow.py
+++ b/src/View/Tools/ASubWindow.py
@@ -483,7 +483,7 @@ class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
 
     def closeEvent(self, event):
         if self.parent is not None:
-            self.parent.sub_win_del(self.name)
+            self.parent.sub_win_del(self.hash())
 
     def find(self, qtype, name):
         """Find an ui component
@@ -520,7 +520,7 @@ class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit):
 
     def closeEvent(self, event):
         if self.parent is not None:
-            self.parent.sub_win_del(self.name)
+            self.parent.sub_win_del(self.hash())
 
     def find(self, qtype, name):
         """Find an ui component
diff --git a/src/View/Tools/ListedSubWindow.py b/src/View/Tools/ListedSubWindow.py
index b548cb315d4d20e0bbd1226e2d4b6a40410a540f..5c3bf1dd5af6e9bd39d40b8e961257caa669f19d 100644
--- a/src/View/Tools/ListedSubWindow.py
+++ b/src/View/Tools/ListedSubWindow.py
@@ -42,59 +42,33 @@ class ListedSubWindow(object):
                 f"Open window: {name}: {self.sub_win_cnt}: {win.hash()}")
         except Exception:
             logger.info(f"Open window: {name}: {self.sub_win_cnt}: X")
+            logger.warning(f"Sub window without hash method !")
 
-    def sub_win_del(self, name):
+    def sub_win_del(self, h):
         self.sub_win_list = list(
             filter(
-                lambda x: x[0] != name,
+                lambda x: x[1].hash() != h,
                 self.sub_win_list
             )
         )
         self.sub_win_cnt = len(self.sub_win_list)
-        logger.info(f"Close window: {name}: {self.sub_win_cnt}")
+        logger.info(f"Close window: {h}: {self.sub_win_cnt}")
 
-    def _sub_win_exists(self, name):
+    def _sub_win_exists(self, h):
         return reduce(
-            lambda acc, n: (acc or (n[0] == name)),
+            lambda acc, el: (acc or (h == (el[1].hash()))),
             self.sub_win_list,
             False
         )
 
-    def _sub_win_exists_with_contain(self, name, contain):
-        return reduce(
-            lambda acc, n: (
-                acc or
-                (
-                    (n[0] == name) and
-                    reduce(
-                        lambda acc, c: acc and (c in n[1]._title),
-                        contain,
-                        True
-                    )
-                )
-            ),
-            self.sub_win_list,
-            False
-        )
-
-    def sub_win_exists(self, name, contain=[]):
-        if contain == []:
-            return self._sub_win_exists(name)
-        else:
-            return self._sub_win_exists_with_contain(name, contain)
+    def sub_win_exists(self, h):
+        return self._sub_win_exists(h)
 
-    def sub_win_filter_first(self, name, contain):
+    def get_sub_win(self, h):
         try:
             return next(
                 filter(
-                    lambda n: (
-                        (name in n[0]) and
-                        reduce(
-                            lambda acc, c: acc and (c in n[1]._title),
-                            contain,
-                            True
-                        )
-                    ),
+                    lambda el: (h == el[1].hash()),
                     self.sub_win_list,
                 )
             )[1]
diff --git a/src/View/Tools/PamhyrWindow.py b/src/View/Tools/PamhyrWindow.py
index a3c7d4c302730cb4e1d42a37e102a483a4ca0e57..74756167b65b01ebefb02a9f996095d28ced6923 100644
--- a/src/View/Tools/PamhyrWindow.py
+++ b/src/View/Tools/PamhyrWindow.py
@@ -122,7 +122,6 @@ class PamhyrWindowTools(object):
             hash_str += repr(el)
 
         h = hash(hash_str)
-        logger.debug(f"Compute hash = {h} for window {cls._pamhyr_name}")
 
         return h