#
# You should have received a copy of the GNU General Public License
# along with SALOME HYDRO module. If not, see <http://www.gnu.org/licenses/>.
-
-import sys
-import os
-import tempfile
-from ctypes import cdll
-
-
-class Telemac2D(object):
-
- _instanciated = False
- _api_module = None
-
- def __new__(cls, *args, **kwargs):
- if cls._instanciated:
- raise Exception("Telemac2D instance already exists")
- instance = super(Telemac2D, cls).__new__(cls, *args, **kwargs)
- cls._instanciated = True
- return instance
-
- def __init__(self, user_fortran = None):
- self.user_fortran_lib = None
- self.user_fortran_lib_path = None
- # User Fortran MUST be loaded before apit2d importation
- if user_fortran is not None:
- self._load_user_fortran(user_fortran)
- if Telemac2D._api_module is None:
- import salome.hydro.telemac2d._apit2d
- Telemac2D._api_module = sys.modules["salome.hydro.telemac2d._apit2d"]
- else:
- reload(Telemac2D._api_module)
- self.api = Telemac2D._api_module.api_interface_t2d
- self.errapi = Telemac2D._api_module.api_handle_error_t2d
- self.id, ierr = self.api.run_set_config_t2d(6, 2)
- self.handle_error("run_set_config_t2d", ierr)
-
- def __del__(self):
- # No way to cleanly unload user fortran lib, so I don't know if it's possible
- # to reload and use another one in the same process (to be tested)
- if self.user_fortran_lib_path is not None:
- os.remove(self.user_fortran_lib_path)
- Telemac2D._instanciated = False
-
- def _load_user_fortran(self, fortran_filename):
- basename = os.path.basename(fortran_filename)
- root = os.path.splitext(basename)[0]
- (fd, self.user_fortran_lib_path) = tempfile.mkstemp(prefix = root + "_", suffix = ".so")
- os.close(fd)
- python_version = "%d.%d" % (sys.version_info[0], sys.version_info[1])
- t2d_ld_flags = "-L${TELEMAC_DIR}/builds/salome/wrap_api/lib -lapi -ltelemac2d -lsisyphe -ltomawac "
- #t2d_ld_flags += "-lbief -lparallel -lpartel -lgretel -lhermes -ldamocles -lspecial "
- t2d_ld_flags += "-lbief -lparallel -lhermes -ldamocles -lspecial "
- t2d_ld_flags += "-L${MED3HOME}/lib -L${HDF5HOME}/lib -lhdf5 -lmed"
- command = "gfortran %s -shared -o %s -L${PYTHONHOME}/lib -lpython%s %s -I${TELEMAC_DIR}/wrap_api/include -fPIC" % \
- (fortran_filename, self.user_fortran_lib_path, python_version, t2d_ld_flags)
- ret = os.system(command)
- if ret != 0:
- raise Exception("Cannot compile user fortran file %s" % fortran_filename)
- self.user_fortran_lib = cdll.LoadLibrary(self.user_fortran_lib_path)
-
- def handle_error(self, funcname, ierr):
- if ierr != 0:
- raise Exception('Error in function %s:\n Error code: %d\n Error message: %s' %
- (funcname, ierr, self.errapi.err_mess.tostring().strip()))
-
- def run_read_case_t2d(self, steering_filename, dico_filename = None):
- if dico_filename is None:
- dico_filename = os.path.join(os.getenv("TELEMAC_DIR"), "sources", "telemac2d", "telemac2d.dico")
- if not os.path.isfile(steering_filename):
- raise Exception("Steering file {0} does not exist".format(steering_filename))
- if not os.path.isfile(dico_filename):
- raise Exception("Dictionary file {0} does not exist".format(dico_filename))
- ierr = self.api.run_read_case_t2d(self.id, steering_filename, dico_filename)
- self.handle_error("run_read_case_t2d", ierr)
-
- def get_double(self, varname, *args):
- args = list(args) + [0] * (3 - len(args)) # Fill last parameters with 0
- value, ierr = self.api.get_double_t2d(self.id, varname, *args)
- self.handle_error("get_double_t2d", ierr)
- return value
-
- def set_double(self, varname, value, *args):
- args = list(args) + [0] * (3 - len(args)) # Fill last parameters with 0
- ierr = self.api.set_double_t2d(self.id, varname, value, *args)
- self.handle_error("set_double_t2d", ierr)
-
- def get_integer(self, varname, *args):
- args = list(args) + [0] * (3 - len(args)) # Fill last parameters with 0
- value, ierr = self.api.get_integer_t2d(self.id, varname, *args)
- self.handle_error("get_integer_t2d", ierr)
- return value
-
- def set_integer(self, varname, value, *args):
- args = list(args) + [0] * (3 - len(args)) # Fill last parameters with 0
- ierr = self.api.set_integer_t2d(self.id, varname, value, *args)
- self.handle_error("set_integer_t2d", ierr)
-
- def get_string(self, varname):
- value, ierr = self.api.get_string_t2d(self.id, varname, 144)
- self.handle_error("get_string_t2d", ierr)
- return value.tostring().strip()
-
- def set_string(self, varname, value):
- padded_value = value + " " * (144 - len(value)) # Pad with spaces
- ierr = self.api.set_string_t2d(self.id, varname, padded_value, 144)
- self.handle_error("set_string_t2d", ierr)
-
- def run_all_timesteps(self):
- ntimesteps = self.get_integer("MODEL.NTIMESTEPS")
- for i in xrange(ntimesteps):
- ierr = self.api.run_timestep_t2d(self.id)
- self.handle_error("run_timestep_t2d", ierr)
-
- def finalize(self):
- ierr = self.api.run_finalize_t2d(self.id)
- self.handle_error("run_finalize_t2d", ierr)
-
- def save_state(self, state = None):
- nbpoints = self.get_integer('MODEL.NPOIN')
- if state is None:
- state = Telemac2DState(nbpoints)
- elif state.nbpoints != nbpoints:
- raise Exception("Allocated state size (%d) is different from the size "
- "of Telemac2D state (%d)" % (state.nbpoints, nbpoints))
- for i in xrange(nbpoints):
- #state.h[i] = self.get_double('MODEL.WATERDEPTH', i+1)
- #state.u[i] = self.get_double('MODEL.VELOCITYU' , i+1)
- #state.v[i] = self.get_double('MODEL.VELOCITYV' , i+1)
- # The following lines are an optimization of the previous ones,
- # to be replaced by a proper array copy
- state.h[i] = self.api.get_double_t2d(self.id, 'MODEL.WATERDEPTH', i+1, 0, 0)[0]
- state.u[i] = self.api.get_double_t2d(self.id, 'MODEL.VELOCITYU' , i+1, 0, 0)[0]
- state.v[i] = self.api.get_double_t2d(self.id, 'MODEL.VELOCITYV' , i+1, 0, 0)[0]
- return state
-
- def restore_state(self, state):
- nbpoints = self.get_integer('MODEL.NPOIN')
- if state.nbpoints != nbpoints:
- raise Exception("Allocated state size (%d) is different from the size "
- "of Telemac2D state (%d)" % (state.nbpoints, nbpoints))
- for i in xrange(nbpoints):
- #self.set_double('MODEL.WATERDEPTH', state.h[i], i+1)
- #self.set_double('MODEL.VELOCITYU' , state.u[i], i+1)
- #self.set_double('MODEL.VELOCITYV' , state.v[i], i+1)
- # The following lines are an optimization of the previous ones,
- # to be replaced by a proper array copy
- self.api.set_double_t2d(self.id, 'MODEL.WATERDEPTH', state.h[i], i+1, 0, 0)
- self.api.set_double_t2d(self.id, 'MODEL.VELOCITYU' , state.u[i], i+1, 0, 0)
- self.api.set_double_t2d(self.id, 'MODEL.VELOCITYV' , state.v[i], i+1, 0, 0)
-
-
-class Telemac2DState:
- def __init__(self, nbpoints):
- self.nbpoints = nbpoints
- self.h = [0.0] * nbpoints
- self.u = [0.0] * nbpoints
- self.v = [0.0] * nbpoints