Metadata-Version: 2.4
Name: pendulo
Version: 0.9.8
Summary: Python interface to Pendulo water hammer simulation kernel
Author: Dr. Pierre Antoine Jarrige
Author-email: piccolo@safege.fr
License: EUPL-1.2
Keywords: Pendulo
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Win32 (MS Windows)
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Fortran
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: ==313
Description-Content-Type: text/x-rst
Requires-Dist: numpy>=2.0
Requires-Dist: ganessa>=2.2.9
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: keywords
Dynamic: license
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

PenWin32 (Pendulo) python API calling interface

What is it?
-----------
A python package enabling users to call a minimal set of PenWin32.dll API functions and subroutines within python scripts. For latest python version e.g. 3.10. 32 bits only.

Installation
------------
*Windows only* :: 

    pip install pendulo

Requirements (32 bits)
----------------------
  #) python 3.10
  #) numpy 1.21.3 (python 3.10)
  #) ganessa 2.2.9
  #) Pendulo kernel library (penwin32.dll) 2022+
  #) valid Pendulo_size and Pendulo_version license


This tool expects Picwin32.dll to be in the PATH or in one of the following folders::

                 %localappdata%/Programs/Safege/Pendulo or
                 %localappdata%/Programs/Suez/Pendulo or
 [ C: or D: ] / 'Program Files (x86)/Safege/Pendulo_' 
              + ['' or '_fr' or '_uk' or '_esp' or '_eng'] + ['' or '_ck']

With custom installations, PENDULO_DIR environment variable can be set to define the path. 

Content
-------

The package provides:
 #) pen_vers = init(debug=0) function
 #) close() function
 #) coef, name, ref_name = get_unit_info(attr) retrieves the unit coef, name and reference unit
 #) index, z, cs, head = get_node(node) returns node index (>0), elevation, demand, head at node
 #) stat = set_node_boundary_condition(node, ts_data, cond='CS') sets demand boundary condition at node. ts_data is a sequence of (time, value) tuples.
 #) stat = run_simulation(horizon=-1, storage_factor=-1) runs the transient simulation over the given horizon and store results every storage_factor step. Defaults to the model values.
 #) vdat, vval = ts(id_elem, typelt, attr) retrieves the result TS for element 'id_elem' of type 'typelt' and attribute 'attr'.
 
Example of 'typelt' and 'attr': 
 #) 'LINK' or 'ARC': 'Q'
 #) 'NODE' or 'NOEUD': 'P', 'CH' or 'HH'
 #) 'TANK' or 'RESERVOIR': 'NC' or 'NV', 'VO'
 #) 'PUMP' or 'POMPE': 'PC', 'VR', 'Q'
 #) 'VANNE' or 'ROBINET' or 'REGULATEUR': 'DO', 'PC', 'Q'
 #) 'ANB': 'Q', 'VO', 'NC' or 'NV'


Example
-------

::

 # -*- coding: utf-8 -*-
 from logging import root
 import os.path as OP
 import pendulo
 from ganessa.plot import pageplot
 from ganessa.util import winstr, strf3
 import ganessa.sim as pic
 
 
 folder = OP.dirname(__file__)
 # init pendulo
 pendulo.init()
 model = OP.join(folder, 'VIROFL_1.PEN')
 # load Pendulo model
 print('===\nChargement de ', model)
 istat = pendulo.loadmodel(winstr(model))
 if not istat:
     print(' * Erreur au chargement *')
 
 # get unit for demand at node
 cs_coef, cs_name, cs_ref = pendulo.get_unit_info('CS')
 print(f'Unit CS: {cs_name} = {cs_coef} {cs_ref}')
 # get demand value at a given node
 node = 'PEN1'
 idx, z_node, cs_node, ch_node = pendulo.get_node(node)
 print(f'Demand at node {node} is: {strf3(cs_node)} {cs_name}')
 # set / change demand boundary condition: sequence of (time, value) tuples
 stat = pendulo.set_node_boundary_condition(node, [(0, cs_node), (0.5, 3*cs_node)])
 print('Changing demand', 'OK' if stat else '*failed*')
 
 # run simulation
 print('Starting simulation ... please wait')
 stat = pendulo.run_simulation(horizon=20, storage_factor=10)
 print('Simulation','OK' if stat else '*failed*')
 # collect results
 results = []
 for node in ['PEN1', '36N646', '36N495', '36N488', '36N463', '36N35']:
     t, v = pendulo.ts(winstr(node), typelt='NODE', attr='CH')
     if len(t) and len(v):
         results.append((node, t, v))
 fname = OP.join(folder, 'Simulation_1.png')
 pageplot(results, 'Simulation #1 - Charge aux noeuds', 2, 3, fname, inter=False, orient='h')
 pendulo.close()

