wolfhece 2.1.99__py3-none-any.whl → 2.1.101__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wolfhece/PyDraw.py +220 -29
- wolfhece/PyGui.py +1039 -53
- wolfhece/PyVertexvectors.py +2 -2
- wolfhece/Results2DGPU.py +37 -13
- wolfhece/acceptability/Parallels.py +2 -2
- wolfhece/acceptability/_add_path.py +23 -0
- wolfhece/acceptability/acceptability.py +594 -563
- wolfhece/acceptability/acceptability_gui.py +564 -331
- wolfhece/acceptability/cli.py +307 -120
- wolfhece/acceptability/func.py +1754 -1597
- wolfhece/apps/version.py +1 -1
- wolfhece/bernoulli/losses.py +76 -23
- wolfhece/bernoulli/losses_jax.py +143 -0
- wolfhece/bernoulli/pipe.py +7 -2
- wolfhece/gpuview.py +4 -1
- wolfhece/libs/__init__.py +11 -10
- wolfhece/libs/wolfogl.cp310-win_amd64.pyd +0 -0
- wolfhece/math_parser/__init__.py +4 -4
- wolfhece/math_parser/calculator.py +51 -9
- wolfhece/mesh2d/bc_manager.py +25 -2
- wolfhece/mesh2d/gpu_2d.py +644 -0
- wolfhece/mesh2d/simple_2d.py +2817 -0
- wolfhece/mesh2d/wolf2dprev.py +5 -2
- wolfhece/pidcontroller.py +131 -0
- wolfhece/pywalous.py +7 -7
- wolfhece/scenario/config_manager.py +98 -21
- wolfhece/wolf_array.py +391 -176
- wolfhece/wolf_vrt.py +108 -7
- wolfhece/wolfresults_2D.py +113 -6
- wolfhece/xyz_file.py +91 -51
- {wolfhece-2.1.99.dist-info → wolfhece-2.1.101.dist-info}/METADATA +3 -1
- {wolfhece-2.1.99.dist-info → wolfhece-2.1.101.dist-info}/RECORD +35 -30
- {wolfhece-2.1.99.dist-info → wolfhece-2.1.101.dist-info}/WHEEL +1 -1
- {wolfhece-2.1.99.dist-info → wolfhece-2.1.101.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.99.dist-info → wolfhece-2.1.101.dist-info}/top_level.txt +0 -0
    
        wolfhece/mesh2d/wolf2dprev.py
    CHANGED
    
    | @@ -40,7 +40,7 @@ from ..PyVertex import getIfromRGB | |
| 40 40 | 
             
            from ..PyTranslate import _
         | 
| 41 41 | 
             
            from ..CpGrid import CpGrid
         | 
| 42 42 | 
             
            from ..GraphNotebook import PlotPanel
         | 
| 43 | 
            -
            from ..PyParams import Wolf_Param, new_json
         | 
| 43 | 
            +
            from ..PyParams import Wolf_Param, new_json, key_Param, Type_Param
         | 
| 44 44 | 
             
            from .cst_2D_boundary_conditions import BCType_2D, Direction, BCType_2D_To_BCType_2D_GPU
         | 
| 45 45 |  | 
| 46 46 | 
             
            PREV_INFILTRATION_NULL = 0  #PAS D'INFILTRATION
         | 
| @@ -8100,9 +8100,12 @@ class prev_infiltration(): | |
| 8100 8100 |  | 
| 8101 8101 | 
             
                    sequence, nb_zones = self._infiltrations_chronology.shape
         | 
| 8102 8102 | 
             
                    for zone in range(1,nb_zones):
         | 
| 8103 | 
            -
                        ax.plot(self._infiltrations_chronology[:, 0], self._infiltrations_chronology[:, zone], label=f' | 
| 8103 | 
            +
                        ax.plot(self._infiltrations_chronology[:, 0], self._infiltrations_chronology[:, zone], label=f'Zone {zone}')
         | 
| 8104 8104 |  | 
| 8105 | 
            +
                    ax.set_xlabel(_('Time [s]'))
         | 
| 8106 | 
            +
                    ax.set_ylabel(_('Infiltration [$m^3/s$]'))
         | 
| 8105 8107 | 
             
                    ax.legend()
         | 
| 8108 | 
            +
                    fig.tight_layout()
         | 
| 8106 8109 |  | 
| 8107 8110 | 
             
                    if show:
         | 
| 8108 8111 | 
             
                        fig.show()
         | 
| @@ -0,0 +1,131 @@ | |
| 1 | 
            +
            import numpy as np
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class PIDController:
         | 
| 4 | 
            +
                """
         | 
| 5 | 
            +
                Tuning a PID controller -- https://dewesoft.com/blog/what-is-pid-controller
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                Tuning the PID parameters Kp, Ki and Kd is crucial in PID controller design. 
         | 
| 8 | 
            +
                Tuning must be customized for each of the many PID applications. 
         | 
| 9 | 
            +
                Key tuning parameters include:
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                 - Proportional Gain (Kp): This parameter determines the proportion of 
         | 
| 12 | 
            +
                   the error signal contributing to the controller output. A higher  
         | 
| 13 | 
            +
                   Kp value results in a stronger response to the current error. 
         | 
| 14 | 
            +
                   Too high a Kp can lead to oscillations or instability, while too 
         | 
| 15 | 
            +
                   low a value can result in a sluggish response.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                 - Integral Gain (Ki): The integral term considers the accumulation 
         | 
| 18 | 
            +
                   of past errors and amplifies them over time. It helps eliminate 
         | 
| 19 | 
            +
                   steady-state error by continuously adjusting the control signal. 
         | 
| 20 | 
            +
                   A higher Ki value helps reduce steady-state error but can lead 
         | 
| 21 | 
            +
                   to overshoot or instability if set too high.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                 - Derivative Gain (Kd): The derivative term predicts the future behavior 
         | 
| 24 | 
            +
                   of the error based on its current rate of change. It helps dampen 
         | 
| 25 | 
            +
                   oscillations by counteracting rapid changes in the error signal. 
         | 
| 26 | 
            +
                   Increasing Kd enhances damping and reduces overshoot, but too high 
         | 
| 27 | 
            +
                   a value can lead to instability or sensitivity to noise.
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                The tuning process involves adjusting these parameters to achieve 
         | 
| 30 | 
            +
                desired system performance, such as stability, responsiveness, 
         | 
| 31 | 
            +
                and minimal overshoot. Several methods are used for PID tuning, 
         | 
| 32 | 
            +
                including manual tuning, Ziegler-Nichols method, and optimization 
         | 
| 33 | 
            +
                algorithms. Let’s take a closer look at each of these methods:
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                In manual tuning, the engineer adjusts the parameters based on their 
         | 
| 36 | 
            +
                understanding of the system dynamics and the desired performance criteria. 
         | 
| 37 | 
            +
                This method involves iteratively tweaking the parameters while observing 
         | 
| 38 | 
            +
                the system's response until satisfactory performance is achieved.
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                The Ziegler-Nichols Method provides a systematic approach to PID 
         | 
| 41 | 
            +
                tuning based on step response experiments. The integral and derivative 
         | 
| 42 | 
            +
                gains are set to zero and gradually increased until the system oscillates 
         | 
| 43 | 
            +
                at a constant amplitude. The proportional gain and oscillation period 
         | 
| 44 | 
            +
                are determined from the oscillation period and amplitude, which are 
         | 
| 45 | 
            +
                then used to calculate suitable PID parameters. Several other tuning 
         | 
| 46 | 
            +
                methods exist, including Cohen-Coon, Lambda, and Dead Time. 
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                Optimization algorithms such as gradient descent, genetic algorithms, 
         | 
| 49 | 
            +
                or particle swarm optimization automatically search for optimal PID 
         | 
| 50 | 
            +
                parameters based on specified performance criteria and system models.
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                PID tuning is a critical step in control system design. It ensures 
         | 
| 53 | 
            +
                that the controller effectively regulates the system while meeting 
         | 
| 54 | 
            +
                performance requirements.    
         | 
| 55 | 
            +
                """
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def __init__(self, kp, ki, kd):
         | 
| 58 | 
            +
                    """
         | 
| 59 | 
            +
                    Initialize the PID controller with given coefficients.
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    :params kp (float): Proportional gain coefficient.
         | 
| 62 | 
            +
                    :params ki (float): Integral gain coefficient.
         | 
| 63 | 
            +
                    :params kd (float): Derivative gain coefficient.
         | 
| 64 | 
            +
                    """
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    self.kp = kp
         | 
| 67 | 
            +
                    self.ki = ki
         | 
| 68 | 
            +
                    self.kd = kd
         | 
| 69 | 
            +
                    self.error_sum = 0
         | 
| 70 | 
            +
                    self.last_error = 0
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def calculate(self, setpoint, feedback):
         | 
| 73 | 
            +
                    """ Compute the PID response.
         | 
| 74 | 
            +
                    
         | 
| 75 | 
            +
                    :param setpoint: Objective value to achieve.
         | 
| 76 | 
            +
                    :type setpoint: float
         | 
| 77 | 
            +
                    :param feedback: Current measured value.
         | 
| 78 | 
            +
                    :type feedback: float
         | 
| 79 | 
            +
                    :return: PID control output.
         | 
| 80 | 
            +
                    :rtype: float
         | 
| 81 | 
            +
                    """ 
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    error = setpoint - feedback
         | 
| 84 | 
            +
                    self.error_sum += error
         | 
| 85 | 
            +
                    error_diff = error - self.last_error
         | 
| 86 | 
            +
                    self.last_error = error
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                    p = self.kp * error
         | 
| 89 | 
            +
                    i = self.ki * self.error_sum
         | 
| 90 | 
            +
                    d = self.kd * error_diff
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                    return p + i + d
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            if __name__ == "__main__":    
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                import matplotlib.pyplot as plt
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                # Create a PIDController instance
         | 
| 99 | 
            +
                pid_controller = PIDController(kp=0.5, ki=0.1, kd=.5)
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                # Define time range and step size
         | 
| 102 | 
            +
                t_start = 0
         | 
| 103 | 
            +
                t_end = 10
         | 
| 104 | 
            +
                dt = 0.1
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                # Initialize lists to store time and output values
         | 
| 107 | 
            +
                time = []
         | 
| 108 | 
            +
                output = []
         | 
| 109 | 
            +
                measures = [1]
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                # Simulate the system over time
         | 
| 112 | 
            +
                for t in np.arange(t_start, t_end, dt):
         | 
| 113 | 
            +
                    # Calculate the output using the PID controller
         | 
| 114 | 
            +
                    setpoint = 10  # Example setpoint
         | 
| 115 | 
            +
                    control_signal = pid_controller.calculate(setpoint, measures[-1])
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    # Simulate the system dynamics
         | 
| 118 | 
            +
                    # In a real-world application, this would be replaced by actual measurements
         | 
| 119 | 
            +
                    measures.append(measures[-1] + .4 * control_signal)
         | 
| 120 | 
            +
                    
         | 
| 121 | 
            +
                    # Store the time and output values
         | 
| 122 | 
            +
                    time.append(t)
         | 
| 123 | 
            +
                    output.append(control_signal)
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                # Plot the output over time
         | 
| 126 | 
            +
                plt.plot(time, measures[1:], label='System Output')
         | 
| 127 | 
            +
                plt.xlabel('Time')
         | 
| 128 | 
            +
                plt.ylabel('Output')
         | 
| 129 | 
            +
                plt.title('PID Controller Output')
         | 
| 130 | 
            +
                plt.grid(True)
         | 
| 131 | 
            +
                plt.show()
         | 
    
        wolfhece/pywalous.py
    CHANGED
    
    | @@ -130,13 +130,13 @@ def update_palette_walous(which:Literal['MAJ_NIV1', 'MAJ_NIV2'], pal:wolfpalette | |
| 130 130 | 
             
                return 0
         | 
| 131 131 |  | 
| 132 132 |  | 
| 133 | 
            -
            WALOUS2MANNING_MAJ_NIV1 = {1.: 0.04,
         | 
| 134 | 
            -
                                       2.: 0.02,
         | 
| 135 | 
            -
                                       3.: 0.02,
         | 
| 136 | 
            -
                                       4.: 0.03,
         | 
| 137 | 
            -
                                       5.: 0.025 | 
| 138 | 
            -
                                       6.: 0.04,
         | 
| 139 | 
            -
                                       7.: 0.05}
         | 
| 133 | 
            +
            WALOUS2MANNING_MAJ_NIV1 = {1.: 0.04, # Production primaire
         | 
| 134 | 
            +
                                       2.: 0.02, # Production secondaire
         | 
| 135 | 
            +
                                       3.: 0.02, # Production tertiaire
         | 
| 136 | 
            +
                                       4.: 0.03, # Réseaux de transport, Logistique et réseaux d'utilité publique
         | 
| 137 | 
            +
                                       5.: 0.025,# Usage résidentiel
         | 
| 138 | 
            +
                                       6.: 0.04, # Autres usages
         | 
| 139 | 
            +
                                       7.: 0.05} # Zones naturelles
         | 
| 140 140 |  | 
| 141 141 | 
             
            WALOUS2MANNING_MAJ_NIV2 = {11.: 0.04, # Agriculture
         | 
| 142 142 | 
             
                                       12.: 0.04, # Sylviculture
         | 
| @@ -202,14 +202,15 @@ class Config_Manager_2D_GPU: | |
| 202 202 | 
             
                Gestionnaire de configurations 2D - code GPU
         | 
| 203 203 | 
             
                """
         | 
| 204 204 |  | 
| 205 | 
            -
                def __init__(self, workingdir:str = '', mapviewer:WolfMapViewer = None) -> None:
         | 
| 205 | 
            +
                def __init__(self, workingdir:str = '', mapviewer:WolfMapViewer = None, python_venv:Path = None) -> None:
         | 
| 206 206 | 
             
                    """
         | 
| 207 207 | 
             
                    Recherche de toutes les modélisation dans un répertoire et ses sous-répertoires
         | 
| 208 208 | 
             
                    """
         | 
| 209 209 | 
             
                    self.wx_exists = wx.App.Get() is not None
         | 
| 210 210 |  | 
| 211 | 
            -
                    self.workingdir =  | 
| 212 | 
            -
                    self. | 
| 211 | 
            +
                    self.workingdir:Path = None
         | 
| 212 | 
            +
                    self.wolfgpu:Path = None
         | 
| 213 | 
            +
                    self._py_env:Path = python_venv
         | 
| 213 214 |  | 
| 214 215 | 
             
                    if workingdir == '':
         | 
| 215 216 | 
             
                        if self.wx_exists:
         | 
| @@ -228,6 +229,7 @@ class Config_Manager_2D_GPU: | |
| 228 229 | 
             
                        logging.error(_('Directory does not exist !'))
         | 
| 229 230 | 
             
                        return
         | 
| 230 231 |  | 
| 232 | 
            +
                    self.find_wolfgpu()
         | 
| 231 233 | 
             
                    self.workingdir = Path(workingdir)
         | 
| 232 234 | 
             
                    self.mapviewer  = mapviewer
         | 
| 233 235 |  | 
| @@ -239,6 +241,33 @@ class Config_Manager_2D_GPU: | |
| 239 241 |  | 
| 240 242 | 
             
                    self.load_data()
         | 
| 241 243 |  | 
| 244 | 
            +
                def find_wolfgpu(self):
         | 
| 245 | 
            +
                    """ Find the wolfgpu Path from wolfgpu package"""
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                    import importlib.util
         | 
| 248 | 
            +
                    import sys
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                    if self._py_env is None:
         | 
| 251 | 
            +
                        self._py_env = Path(sys.executable).parent
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                    # Find wolfgpu.exe in script directory
         | 
| 254 | 
            +
                    candidate = self._py_env / 'wolfgpu.exe'
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                    if candidate.exists():
         | 
| 257 | 
            +
                        self.wolfgpu = candidate
         | 
| 258 | 
            +
                        return
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                    candidate = self._py_env / 'Scripts' / 'wolfgpu.exe'
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                    if candidate.exists():
         | 
| 263 | 
            +
                        self.wolfgpu = candidate
         | 
| 264 | 
            +
                        return
         | 
| 265 | 
            +
                    else:
         | 
| 266 | 
            +
                        logging.error(_('WOLFGPU not found !'))
         | 
| 267 | 
            +
                        self.wolfgpu = None
         | 
| 268 | 
            +
                        self._py_env = None
         | 
| 269 | 
            +
             | 
| 270 | 
            +
             | 
| 242 271 | 
             
                def _test_ui(self):
         | 
| 243 272 | 
             
                    """ Test if the UI is available """
         | 
| 244 273 |  | 
| @@ -1142,7 +1171,7 @@ class Config_Manager_2D_GPU: | |
| 1142 1171 | 
             
                        quit = True
         | 
| 1143 1172 |  | 
| 1144 1173 | 
             
                    if quit:
         | 
| 1145 | 
            -
                        logging.error(_(' | 
| 1174 | 
            +
                        logging.error(_('Bad assembly operation -- Simulation creation aborted !'))
         | 
| 1146 1175 | 
             
                        return
         | 
| 1147 1176 |  | 
| 1148 1177 | 
             
                    bat = WolfArray(str(dir / '__bathymetry.tif'))
         | 
| @@ -1263,25 +1292,35 @@ class Config_Manager_2D_GPU: | |
| 1263 1292 | 
             
                        logging.info(cursim.check_errors())
         | 
| 1264 1293 | 
             
                        logging.info(_('Simulation {} created !'.format(curdir)))
         | 
| 1265 1294 |  | 
| 1266 | 
            -
             | 
| 1267 1295 | 
             
                        with open(curdir / 'quickrun.bat', 'w', encoding='utf-8') as f:
         | 
| 1296 | 
            +
                            f.write("@echo off\n")
         | 
| 1297 | 
            +
                            f.write("\n")
         | 
| 1268 1298 | 
             
                            f.write(str(curdir.drive) + '\n')
         | 
| 1269 1299 | 
             
                            f.write('cd {}\n'.format(str(curdir.parent)))
         | 
| 1270 | 
            -
                            f.write( | 
| 1271 | 
            -
             | 
| 1272 | 
            -
                             | 
| 1273 | 
            -
                             | 
| 1274 | 
            -
                             | 
| 1275 | 
            -
                             | 
| 1276 | 
            -
                             | 
| 1277 | 
            -
                             | 
| 1278 | 
            -
                             | 
| 1279 | 
            -
                             | 
| 1280 | 
            -
                             | 
| 1300 | 
            +
                            f.write("\n")
         | 
| 1301 | 
            +
                            f.write("WOLFGPU_PARAMS=-quickrun " + str(curdir.name) + "\n")
         | 
| 1302 | 
            +
                            f.write("\n")
         | 
| 1303 | 
            +
                            f.write("where wolfgpu.exe\n")
         | 
| 1304 | 
            +
                            f.write("IF %ERRORLEVEL%==0 (\n")
         | 
| 1305 | 
            +
                            f.write("wolfgpu %WOLFGPU_PARAMS%\n")
         | 
| 1306 | 
            +
                            f.write("goto :end\n")
         | 
| 1307 | 
            +
                            f.write(")\n")
         | 
| 1308 | 
            +
                            f.write("\n")
         | 
| 1309 | 
            +
                            f.write("echo -------------------------------\n")
         | 
| 1310 | 
            +
                            f.write("echo ERROR !!!\n")
         | 
| 1311 | 
            +
                            f.write("echo -------------------------------\n")
         | 
| 1312 | 
            +
                            f.write("echo I can't find wolfgpu.exe.\n")
         | 
| 1313 | 
            +
                            f.write("echo It is normally installed in the 'Scripts' subdirectory of your python\n")
         | 
| 1314 | 
            +
                            f.write("echo directory (or environment).\n")
         | 
| 1315 | 
            +
                            f.write("echo This 'Scripts' subdirectory must be available on the PATH environment variable.\n")
         | 
| 1316 | 
            +
                            f.write("echo I am now going to try to run wolfgpu as a regular python module\n")
         | 
| 1317 | 
            +
                            f.write("echo -------------------------------\n")
         | 
| 1318 | 
            +
                            f.write("pause\n")
         | 
| 1319 | 
            +
                            f.write("python -m wolfgpu.cli %WOLFGPU_PARAMS%\n")
         | 
| 1320 | 
            +
                            f.write(":end\n")
         | 
| 1281 1321 |  | 
| 1282 1322 | 
             
                        allsims.append(curdir / 'quickrun.bat')
         | 
| 1283 1323 |  | 
| 1284 | 
            -
             | 
| 1285 1324 | 
             
                    logging.info(_('Simulation creation finished !'))
         | 
| 1286 1325 | 
             
                    logging.warning(_('Do not forget to update/set the boundary conditions if not set by scripts !'))
         | 
| 1287 1326 |  | 
| @@ -1303,10 +1342,24 @@ class Config_Manager_2D_GPU: | |
| 1303 1342 | 
             
                    with open(path, 'w', encoding='utf-8') as f:
         | 
| 1304 1343 | 
             
                        f.write(batch)
         | 
| 1305 1344 |  | 
| 1345 | 
            +
                    if self.wolfgpu is None:
         | 
| 1346 | 
            +
                        logging.warning('****************************************************')
         | 
| 1347 | 
            +
                        logging.warning(_('Wolfgpu.exe not found !'))
         | 
| 1348 | 
            +
                        logging.warning(_('It is normally installed in the "Scripts" subdirectory of your python directory (or environment).'))
         | 
| 1349 | 
            +
                        logging.warning(_('This "Scripts" subdirectory must be available on the PATH environment variable.'))
         | 
| 1350 | 
            +
                        logging.warning('****************************************************')
         | 
| 1351 | 
            +
                    else:
         | 
| 1352 | 
            +
                        logging.info('****************************************************')
         | 
| 1353 | 
            +
                        logging.info(_('Wolfgpu.exe found in {}!').format(self.wolfgpu))
         | 
| 1354 | 
            +
                        logging.info(_('You can now run the simulations !'))
         | 
| 1355 | 
            +
                        logging.info(_('Do not forget to activate your Python virtual environment if you are using one !'))
         | 
| 1356 | 
            +
                        logging.info('****************************************************')
         | 
| 1357 | 
            +
             | 
| 1306 1358 | 
             
                    return batch
         | 
| 1307 1359 |  | 
| 1308 1360 | 
             
                def run_batch(self, batch:Path):
         | 
| 1309 1361 | 
             
                    """ run a batch file in a subprocess """
         | 
| 1362 | 
            +
             | 
| 1310 1363 | 
             
                    if not batch.exists():
         | 
| 1311 1364 | 
             
                        logging.error(_('Batch file {} does not exist !'.format(batch)))
         | 
| 1312 1365 | 
             
                        return
         | 
| @@ -1763,9 +1816,33 @@ class UI_Manager_2D_GPU(): | |
| 1763 1816 |  | 
| 1764 1817 | 
             
                    log = self._parent.check_consistency()
         | 
| 1765 1818 | 
             
                    if log =='':
         | 
| 1766 | 
            -
                        self._txtctrl.WriteText(_("All is fine  | 
| 1819 | 
            +
                        self._txtctrl.WriteText(_("All is fine !\n\n"))
         | 
| 1767 1820 | 
             
                    else:
         | 
| 1768 | 
            -
                        self._txtctrl.WriteText(log)
         | 
| 1821 | 
            +
                        self._txtctrl.WriteText(log +"\n\n")
         | 
| 1822 | 
            +
             | 
| 1823 | 
            +
                    # Info on Python Environment and wolfgpu Path and version
         | 
| 1824 | 
            +
                    # -------------------------------------------------------
         | 
| 1825 | 
            +
             | 
| 1826 | 
            +
                    import sys
         | 
| 1827 | 
            +
                    # Python Environment
         | 
| 1828 | 
            +
                    self._txtctrl.write(_('Python Environment\n'))
         | 
| 1829 | 
            +
                    self._txtctrl.write('-------------------\n')
         | 
| 1830 | 
            +
                    self._txtctrl.write('Python version : {}\n'.format(sys.version))
         | 
| 1831 | 
            +
                    self._txtctrl.write('Python path : {}\n'.format(sys.executable))
         | 
| 1832 | 
            +
                    self._txtctrl.write('Python version info : {}\n'.format(sys.version_info))
         | 
| 1833 | 
            +
             | 
| 1834 | 
            +
                    # Test if wolfgpu.exe exists in script directory
         | 
| 1835 | 
            +
                    # wolfgpu Path and version
         | 
| 1836 | 
            +
                    self._txtctrl.write('\nWolfgpu Path and version\n')
         | 
| 1837 | 
            +
                    self._txtctrl.write('------------------------\n')
         | 
| 1838 | 
            +
             | 
| 1839 | 
            +
                    wolfgpu = self._parent.wolfgpu
         | 
| 1840 | 
            +
                    if wolfgpu.exists():
         | 
| 1841 | 
            +
                        self._txtctrl.write('Wolfgpu.exe found in : {}\n'.format(self._parent.wolfgpu.parent))
         | 
| 1842 | 
            +
                    else:
         | 
| 1843 | 
            +
                        self._txtctrl.write('Wolfgpu.exe not found !\n')
         | 
| 1844 | 
            +
                        self._parent.wolfgpu = None
         | 
| 1845 | 
            +
             | 
| 1769 1846 |  | 
| 1770 1847 | 
             
                def choice_hydrograph(self) -> list[int]:
         | 
| 1771 1848 |  | 
| @@ -1975,7 +2052,7 @@ class UI_Manager_2D_GPU(): | |
| 1975 2052 | 
             
                            try:
         | 
| 1976 2053 | 
             
                                if curwp.Shown:
         | 
| 1977 2054 | 
             
                                    cursim.from_wolfparam(curwp)
         | 
| 1978 | 
            -
                                    cursim. | 
| 2055 | 
            +
                                    cursim._save_json()
         | 
| 1979 2056 | 
             
                            except Exception as e:
         | 
| 1980 2057 | 
             
                                self._wp[cursim] = None
         | 
| 1981 2058 | 
             
                                logging.debug(_('Error while saving parameters for simulation {}'.format(cursim.path.name)))
         | 
| @@ -1989,7 +2066,7 @@ class UI_Manager_2D_GPU(): | |
| 1989 2066 | 
             
                            try:
         | 
| 1990 2067 | 
             
                                if curwp.Shown:
         | 
| 1991 2068 | 
             
                                    cursim.from_wolfparam(curwp)
         | 
| 1992 | 
            -
                                    cursim. | 
| 2069 | 
            +
                                    cursim._save_json()
         | 
| 1993 2070 | 
             
                            except Exception as e:
         | 
| 1994 2071 | 
             
                                self._wp[cursim] = None
         | 
| 1995 2072 | 
             
                                logging.debug(_('Error while saving parameters for simulation {}'.format(cursim.path.name)))
         |