From 60cbb016efdb2339d053d809ac54f2bfed8bd5f6 Mon Sep 17 00:00:00 2001 From: mzn Date: Fri, 23 Sep 2016 14:11:41 +0300 Subject: [PATCH] Lot4: add boundary conditions reader/writer, presets reader and tests --- src/HYDROTools/CMakeLists.txt | 30 +++++ src/HYDROTools/__init__.py | 0 src/HYDROTools/boundaryConditions.py | 176 ++++++++++++++++++++++++++ tests/boundaryConditionsTest.py | 65 ++++++++++ tests/data/bnd_conditions1.cli | 8 ++ tests/data/bnd_conditions_presets.txt | 4 + 6 files changed, 283 insertions(+) create mode 100644 src/HYDROTools/CMakeLists.txt create mode 100644 src/HYDROTools/__init__.py create mode 100644 src/HYDROTools/boundaryConditions.py create mode 100644 tests/boundaryConditionsTest.py create mode 100644 tests/data/bnd_conditions1.cli create mode 100644 tests/data/bnd_conditions_presets.txt diff --git a/src/HYDROTools/CMakeLists.txt b/src/HYDROTools/CMakeLists.txt new file mode 100644 index 0000000..1e3e7d5 --- /dev/null +++ b/src/HYDROTools/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (C) 2012-2013 EDF +# +# This file is part of SALOME HYDRO module. +# +# SALOME HYDRO module is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SALOME HYDRO module is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SALOME HYDRO module. If not, see . + +#ADD_SUBDIRECTORY(xxx) + +# --- Python files --- + +SET(PYFILES + __init__.py + interpolS.py + boundaryConditions.py +) + +# --- rules --- + +SALOME_INSTALL_SCRIPTS("${PYFILES}" ${SALOME_INSTALL_PYTHON}/salome/hydrotools) diff --git a/src/HYDROTools/__init__.py b/src/HYDROTools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/HYDROTools/boundaryConditions.py b/src/HYDROTools/boundaryConditions.py new file mode 100644 index 0000000..307f6b4 --- /dev/null +++ b/src/HYDROTools/boundaryConditions.py @@ -0,0 +1,176 @@ +import os + +PRS_SEP = "," +BND_SEP = " " + +"""Preset file reader""" +class PresetReader(): + def __init__(self, file_name): + self.file_name = file_name + self._errors = [] + + @property + def errors(self): + return self._errors + + def __get_value(self, str): + value = None + + if str.isdigit(): + value = int(str) + + return value + + def read(self): + del self._errors[:] + + presets = {} + + try: + with open(self.file_name) as f: + # Read presets line by line + line_number = 1 + groups = [] + for line in f: + cstr = " ".join(line.split()) + values = cstr.strip().split(PRS_SEP) + + if len(values) != 5: + self._errors.append("Line #%s: wrong number of values in the preset." % line_number) + elif values[0].strip() == "": + self._errors.append("Line #%s: empty name of the preset." % line_number) + elif presets.has_key(values[0]): + self._errors.append("Line #%s: preset name %s is already used." % (line_number, values[0])) + else: + name = values[0] + lihbor = self.__get_value(values[1]) + liubor = self.__get_value(values[2]) + livbor = self.__get_value(values[3]) + litbor = self.__get_value(values[4]) + + presets[name] = (lihbor, liubor, livbor, litbor) + except IOError as err: + self._errors.append(err.strerror) + + return presets + +"""Boundary condition object""" +class BoundaryCondition(): + def __init__(self, lihbor, liubor, livbor, litbor, group): + self.lihbor = lihbor + self.liubor = liubor + self.livbor = livbor + self.litbor = litbor + self.group = group + +"""Boundary conditions file reader""" +class BoundaryConditionReader(): + def __init__(self, file_name): + self.file_name = file_name + self._errors = [] + + def __get_condition(self, str): + condition = None + + try: + cstr = " ".join(str.split()) + values = cstr.strip().split(BND_SEP) + + if len(values) == 5: + lihbor = int(values[0]) + liubor = int(values[1]) + livbor = int(values[2]) + litbor = int(values[3]) + group = values[4] + + condition = BoundaryCondition(lihbor, liubor, livbor, litbor, group) + except ValueError: + pass + + return condition + + @property + def errors(self): + return self._errors + + def read(self): + del self._errors[:] + + conditions = [] + + try: + with open(self.file_name) as f: + # Read the number of conditions + nb_conditions = 0 + first_line = f.readline().strip() + if not first_line.isdigit(): + self._errors.append("First line is not a number.") + else: + nb_conditions = int(first_line) + + # Read conditions line by line + line_number = 2 + cnd_count = 0 + groups = [] + for line in f: + cnd = self.__get_condition(line) + + if cnd: + if groups.count(cnd.group) == 0: + conditions.append(cnd) + groups.append(cnd.group) + cnd_count += 1 + else: + self._errors.append("Line #%s: group name '%s' is already used." % (line_number, cnd.group)) + else: + self._errors.append("Line #%s: wrong format." % line_number) + + line_number += 1 + + if cnd_count != nb_conditions: + self._errors.append("Number of conditions does not match (%s instead of %s)" % (cnd_count, nb_conditions)) + except IOError as err: + self._errors.append(err.strerror) + + return conditions + +"""Boundary conditions file writer""" +class BoundaryConditionWriter(): + def __init__(self, file_name): + self.file_name = file_name + self._errors = [] + + def __get_string(self, condition): + lihbor = str(condition.lihbor) + liubor = str(condition.liubor) + livbor = str(condition.livbor) + litbor = str(condition.litbor) + values = (lihbor, liubor, livbor, litbor, condition.group) + line = BND_SEP.join(values) + + return line + + @property + def errors(self): + return self._errors + + def write(self, conditions): + del self._errors[:] + + try: + with open(self.file_name, 'w') as f: + lines = [] + + # The number of conditions + lines.append(str(len(conditions)) + '\n') + + # Conditions + for cnd in conditions: + lines.append(self.__get_string(cnd) + '\n') + + # Write + if len(lines) > 1: + f.writelines(lines) + except IOError as err: + self._errors.append(err.strerror) + diff --git a/tests/boundaryConditionsTest.py b/tests/boundaryConditionsTest.py new file mode 100644 index 0000000..0c22492 --- /dev/null +++ b/tests/boundaryConditionsTest.py @@ -0,0 +1,65 @@ +import os +import sys +import tempfile +import filecmp + +import unittest + +cur_dir = os.path.dirname(os.path.realpath(__file__)) +data_dir = os.path.join(cur_dir, "data") + +sys.path.append(os.path.join(cur_dir, "..", "src", "HYDROTools")) +import boundaryConditions + + +class TestBoundaryConditions(unittest.TestCase): + def testReadPresets(self): + file_path = os.path.join(data_dir, "bnd_conditions_presets.txt") + reader = boundaryConditions.PresetReader(file_path) + presets = reader.read() + self.assertEqual(3, len(presets)) + + self.assertEqual(True, presets.has_key("Closed boundaries/walls")) + self.assertEqual((2,2,2,2), presets["Closed boundaries/walls"]) + + self.assertEqual(True, presets.has_key("Incident waves")) + self.assertEqual((1,1,1,None), presets["Incident waves"]) + + self.assertEqual(True, presets.has_key("Free T")) + self.assertEqual((None,None,None,4), presets["Free T"]) + + def testRead(self): + file_path = os.path.join(data_dir, "bnd_conditions1.cli") + reader = boundaryConditions.BoundaryConditionReader(file_path) + conditions = reader.read() + self.assertEqual(7, len(conditions)) + self.assertEqual(0, len(reader.errors)) + + def testWrite(self): + file_path = os.path.join(tempfile.gettempdir(), "bnd_conditions_w.cli") + writer = boundaryConditions.BoundaryConditionWriter(file_path) + + cnd1 = boundaryConditions.BoundaryCondition(5, 4, 4, 4, "group1") + cnd2 = boundaryConditions.BoundaryCondition(4, 5, 5, 5, "group2") + + writer.write([cnd1, cnd2]) + self.assertEqual(True, os.path.exists(file_path)) + self.assertEqual(0, len(writer.errors)) + + os.remove(file_path) + + def testReadWrite(self): + input_file_path = os.path.join(data_dir, "bnd_conditions1.cli") + reader = boundaryConditions.BoundaryConditionReader(input_file_path) + conditions = reader.read() + + output_file_path = os.path.join(tempfile.gettempdir(), "bnd_conditions1_w.cli") + writer = boundaryConditions.BoundaryConditionWriter(output_file_path) + writer.write(conditions) + + try: + self.assertEqual(True, filecmp.cmp(input_file_path, output_file_path)) + finally: + os.remove(output_file_path) + +unittest.main() \ No newline at end of file diff --git a/tests/data/bnd_conditions1.cli b/tests/data/bnd_conditions1.cli new file mode 100644 index 0000000..de5e143 --- /dev/null +++ b/tests/data/bnd_conditions1.cli @@ -0,0 +1,8 @@ +7 +5 4 4 4 litMineur_aval +4 5 5 5 litMineur_amont +4 5 5 5 amontGauche +4 5 5 5 amontDroite +2 2 2 2 bordDroite +2 2 2 2 CasEtendu2_chati02_Outer +2 2 2 2 CasEtendu2_chati03_Outer diff --git a/tests/data/bnd_conditions_presets.txt b/tests/data/bnd_conditions_presets.txt new file mode 100644 index 0000000..eb9a37b --- /dev/null +++ b/tests/data/bnd_conditions_presets.txt @@ -0,0 +1,4 @@ +Closed boundaries/walls,2,2,2,2 +Incident waves,1,1,1,* +Free T,*,*,*,4 + -- 2.39.2