From cc1baee5005ab23857bba628ec445b082f901961 Mon Sep 17 00:00:00 2001 From: Paul RASCLE Date: Tue, 18 Aug 2020 15:38:58 +0200 Subject: [PATCH] dialog initial field --- src/HYDROGUI/CMakeLists.txt | 1 - src/HYDROGUI/HYDROSOLVERGUI.py | 20 +- src/HYDROTools/CMakeLists.txt | 1 + src/HYDROTools/initialField.py | 59 ++++++ src/salome_hydro/CMakeLists.txt | 2 + src/salome_hydro/initialField.ui | 280 +++++++++++++++++++++++++ src/salome_hydro/initialFieldDialog.py | 253 ++++++++++++++++++++++ 7 files changed, 605 insertions(+), 11 deletions(-) create mode 100644 src/HYDROTools/initialField.py create mode 100644 src/salome_hydro/initialField.ui create mode 100644 src/salome_hydro/initialFieldDialog.py diff --git a/src/HYDROGUI/CMakeLists.txt b/src/HYDROGUI/CMakeLists.txt index f385352..6850242 100644 --- a/src/HYDROGUI/CMakeLists.txt +++ b/src/HYDROGUI/CMakeLists.txt @@ -21,7 +21,6 @@ SET(PYFILES HYDROSOLVERGUI.py BndConditionsDialog.py BreachesDialog.py - InitialConditionsDialog.py LiquidBoundariesDialog.py ) diff --git a/src/HYDROGUI/HYDROSOLVERGUI.py b/src/HYDROGUI/HYDROSOLVERGUI.py index d80a6c5..b3c2b80 100755 --- a/src/HYDROGUI/HYDROSOLVERGUI.py +++ b/src/HYDROGUI/HYDROSOLVERGUI.py @@ -52,7 +52,7 @@ from eficasSalome import runEficas from BndConditionsDialog import BoundaryConditionsDialog from LiquidBoundariesDialog import LiquidBoundariesDialog from BreachesDialog import BreachesDialog -from InitialConditionsDialog import InitialConditionsDialog +from salome.hydro.initialFieldDialog import initialFieldDialog ################################################ # GUI context class @@ -61,7 +61,7 @@ from InitialConditionsDialog import InitialConditionsDialog class GUIcontext: - # --- menus/toolbars/actions IDs + # --- menus/toolbars/actions IDss HYDRO_MENU_ID = 90 CREATE_STUDY_ID = 951 @@ -79,7 +79,7 @@ class GUIcontext: EDIT_BOUNDARY_CONDITIONS_FILE_ID = 959 EDIT_LIQUID_BOUNDARY_FILE_ID = 960 EDIT_BREACHES_FILE_ID = 961 - EDIT_INITIAL_CONDITIONS_FILE_ID = 962 + EDIT_INITIAL_FIELD_FILE_ID = 962 CREATE_PARAM_STUDY_ID = 963 EDIT_PARAM_STUDY_ID = 964 @@ -152,10 +152,10 @@ class GUIcontext: sgPyQt.createTool(act, tid) act = sgPyQt.createAction(\ - GUIcontext.EDIT_INITIAL_CONDITIONS_FILE_ID, - "Edit initial conditions file", - "Edit initial conditions file", - "Create/edit the initial conditions file for Telemac", + GUIcontext.EDIT_INITIAL_FIELD_FILE_ID, + "Edit initial field file", + "Edit initial field file", + "Create/edit the initial field file for Telemac", "edit_boundary_conditions_file.png" ) sgPyQt.createMenu( act, mid ) sgPyQt.createTool( act, tid ) @@ -454,9 +454,9 @@ def edit_breaches_file(): ### # Open dialog for initial conditions edition ### -def edit_initial_conditions_file(): +def edit_initial_field_file(): desktop = sgPyQt.getDesktop() - dlg = InitialConditionsDialog(desktop) + dlg = initialFieldDialog(desktop) dlg.exec_() ### @@ -539,7 +539,7 @@ dict_command = { GUIcontext.EDIT_LIQUID_BOUNDARY_FILE_ID: edit_liquid_boundary_file, GUIcontext.EDIT_BOUNDARY_CONDITIONS_FILE_ID: edit_boundary_conditions_file, GUIcontext.EDIT_BREACHES_FILE_ID: edit_breaches_file, - GUIcontext.EDIT_INITIAL_CONDITIONS_FILE_ID: edit_initial_conditions_file, + GUIcontext.EDIT_INITIAL_FIELD_FILE_ID: edit_initial_field_file, GUIcontext.CREATE_PARAM_STUDY_ID: create_param_study, GUIcontext.EDIT_PARAM_STUDY_ID: edit_param_study, GUIcontext.GEN_PARAM_STUDY_PYTHON_ID: generate_param_study_python, diff --git a/src/HYDROTools/CMakeLists.txt b/src/HYDROTools/CMakeLists.txt index 61a10ec..bacfd43 100644 --- a/src/HYDROTools/CMakeLists.txt +++ b/src/HYDROTools/CMakeLists.txt @@ -23,6 +23,7 @@ SET(PYFILES __init__.py interpolS.py boundaryConditions.py + initialField.py ) # --- rules --- diff --git a/src/HYDROTools/initialField.py b/src/HYDROTools/initialField.py new file mode 100644 index 0000000..da4797c --- /dev/null +++ b/src/HYDROTools/initialField.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +import MEDLoader as ml +import numpy as np + +# Open the file + +def set_var_on_group(filename, meshname, groups_val, varname): + """ + Set values on groups_val + + @param filename Name of the MED file + @param meshname Name of the mesh in the MED file + @param groups_val List of tuples(Name, value) + @param varname Name of the field + """ + # Opening mesh + meshFile2D = ml.MEDFileUMesh(filename, meshname) + + m2D = meshFile2D.getMeshAtLevel(0) + + npoin = m2D.getNumberOfNodes() + + # Values for the field + values = ml.DataArrayDouble(npoin) + + for group , val in groups_val: + # Getting element in the group + cellsInGroup = meshFile2D.getGroupArr(0, group) + for cell in cellsInGroup: + # Get list of nodes in the element + nodes = m2D.getNodeIdsOfCell(cell[0]) + for node in nodes: + values[node] = val + + # Building the new field + field = ml.MEDCouplingFieldDouble.New(ml.ON_NODES) + field.setName(varname) + field.setMesh(m2D) + field.setArray(values) + field.setTime(0.0, 0, -1) + + # Writing field on file + ml.WriteField(filename, field, False) + + +if __name__ == "__main__": + filename = "garonne_1F.med" + meshname = "HYDRO_garonne_1" + groups = [("riveDroite",0.010), + ("riveGauche",0.010), + ("litMineur",10.0), + ] + varname = "WATER DEPTH" + + set_var_on_group(filename, meshname, groups, varname) + + + diff --git a/src/salome_hydro/CMakeLists.txt b/src/salome_hydro/CMakeLists.txt index a8fdfdf..f40a286 100644 --- a/src/salome_hydro/CMakeLists.txt +++ b/src/salome_hydro/CMakeLists.txt @@ -30,12 +30,14 @@ SET(PYFILES assignStrickler_gui.py interpolz_gui.py changeCoordsDialog.py + initialFieldDialog.py ) SET(UIFILES assignStrickler.ui interpolz.ui changeCoords.ui + initialField.ui ) SET(TEMPLFILES diff --git a/src/salome_hydro/initialField.ui b/src/salome_hydro/initialField.ui new file mode 100644 index 0000000..d745905 --- /dev/null +++ b/src/salome_hydro/initialField.ui @@ -0,0 +1,280 @@ + + + Dialog + + + + 0 + 0 + 586 + 576 + + + + Initial Field + + + Qt::LeftToRight + + + + + + Input + + + + + + + + + + + + 0 + 0 + + + + MED file + + + + + + + + + + + 0 + 0 + + + + ... + + + + + + + + + + + + Output + + + + + + + + + 0 + 0 + + + + MED File + + + + + + + directory to store shapefiles and output mesh file if kept + + + + + + + + 0 + 0 + + + + ... + + + + + + + + + + + + 0 + 0 + + + + Field name + + + + + + + WATER DEPTH + + + + + + + + + + + + 0 + 0 + + + + default value + + + + + + + If modified, all the values at previous default value will be udated, leaving others as they are. + + + 3 + + + -9999.000000000000000 + + + 9999.000000000000000 + + + 0.010000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Reset all values to default value + + + reset + + + + + + + + + + group + + + + + value + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 66 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Help + + + + + + + + + + diff --git a/src/salome_hydro/initialFieldDialog.py b/src/salome_hydro/initialFieldDialog.py new file mode 100644 index 0000000..14b3b62 --- /dev/null +++ b/src/salome_hydro/initialFieldDialog.py @@ -0,0 +1,253 @@ +# 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 . + +import os +import sys +import shutil + +from PyQt5.QtCore import * +from PyQt5.QtGui import * +from PyQt5.QtWidgets import * +from PyQt5 import uic + +import salome +salome.salome_init() + +import SMESH +from salome.smesh import smeshBuilder +smesh = smeshBuilder.New() + +from salome.hydro.initialField import set_var_on_group + +import sysconfig +pythonVersion = 'python' + sysconfig.get_python_version() +hydro_solver_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', pythonVersion, 'site-packages', 'salome', 'salome', 'hydro') + +def get_med_groups( file_path ): + """ + Get all the groups of faces in the first mesh + """ + try: + (meshes, status) = smesh.CreateMeshesFromMED(file_path) + except: + print('No meshes found') + return (None, []) + if len(meshes)==0: + print('No mesh found') + return (None, []) + mesh1 = meshes[0] + print('Found mesh:', mesh1) + try: + grps = mesh1.GetGroups() + groups = [grp.GetName().strip() for grp in grps if grp.GetType() == SMESH.FACE] + if len(groups) == 0: + print("Problem! There are no groups of faces in the mesh!") + print("Please create at least the groups of faces corresponding to each region of the HYDRO case") + return (mesh1, []) + print('Found groups:', groups) + except: + print('No groups found') + return (mesh1, []) + return (mesh1, groups) + +class initialFieldDialog(QDialog): + """ + """ + + def __init__(self, parent = None, modal = 0): + QDialog.__init__(self, parent) + uic.loadUi(os.path.join(hydro_solver_root, 'initialField.ui'), self ) + + # Connections + self.pb_medFileIn.clicked.connect(self.on_med_file_in_browse) + self.pb_medFileOut.clicked.connect(self.on_med_file_out_browse) + self.pb_reset.clicked.connect(self.on_fieldReset) + self.pb_help.clicked.connect(self.on_help) + self.pb_ok.accepted.connect(self.on_accept) + self.pb_ok.rejected.connect(self.on_reject) + self.dsb_defaultValue.valueChanged.connect(self.on_defaultValueChanged) + self.medFileIn = None + self.medFileOut = None + self.le_field.setText("WATER DEPTH") + self.dsb_defaultValue.setValue(0.01) + self.previousDefaultValue = self.dsb_defaultValue.value() + self.med_groups = [] + + def on_med_file_in_browse(self): + """ + Select input MED file + """ + print("on_med_file_in_browse") + self.medFileIn, filt = QFileDialog.getOpenFileName(self, self.tr("Input MED file"), "", self.tr("MED files (*.med)")) + print(self.medFileIn) + if not self.medFileIn: + return + self.le_medFileIn.setText(self.medFileIn) + if not os.path.isfile(self.medFileIn): + msgBox = QMessageBox() + msgBox.setText( "Input MED file does not exist" ) + msgBox.exec_() + return + a = os.path.splitext(self.medFileIn) + self.medFileOut = a[0] + '_ic' + a[1] + self.le_medFileOut.setText(self.medFileOut) + self.onMEDChanged() + + def onMEDChanged(self): + mesh, self.med_groups = get_med_groups(self.medFileIn) + self.meshName = mesh.GetName() + print(self.meshName) + print(self.med_groups) + + self.dsbItems = [] + n = len(self.med_groups) + self.tw_fieldValues.setRowCount(n) + for i in range(n): + if self.tw_fieldValues.item( i, 0 ) is None: + self.tw_fieldValues.setItem( i, 0, QTableWidgetItem() ) + self.tw_fieldValues.setItem( i, 1, QTableWidgetItem() ) + self.tw_fieldValues.item( i, 0 ).setText( self.med_groups[i] ) + dsb = QDoubleSpinBox() + dsb.setDecimals(3) + dsb.setRange(-9999.0, 9999.0) + dsb.setSingleStep(1.0) + dsb.setValue(self.dsb_defaultValue.value()) + self.tw_fieldValues.setCellWidget( i, 1, dsb ) + self.dsbItems.append(dsb) + + def on_med_file_out_browse(self): + """ + Select output MED file + """ + print("on_med_file_out_browse") + self.medFileOut, filt = QFileDialog.getSaveFileName(self, self.tr("Output MED file"), "", self.tr("MED files (*.med)")) + print(self.medFileOut) + if not self.medFileOut: + return + self.le_medFileOut.setText(self.medFileOut) + + def on_fieldReset(self): + """ + Reset the values on each group to default value, erasing previous settings + """ + print("onFieldReset") + for dsb in self.dsbItems: + dsb.setValue(self.dsb_defaultValue.value()) + + def on_defaultValueChanged(self): + """ + change the values set to previous default to new default, leaving other values unchanged + """ + print("on_defaultValueChanged") + for dsb in self.dsbItems: + if dsb.value() == self.previousDefaultValue: + dsb.setValue(self.dsb_defaultValue.value()) + self.previousDefaultValue = self.dsb_defaultValue.value() + + def on_help(self): + """ + display a help message + """ + msg = """ +

Initial field dialog

+ + This dialog is used set an initial field with constant values per groups of faces in a mesh. + Typical use is to set an initial water depth on the minor bed of a river, for instance. +

+ The modified mesh is saved in a new file by default. +
+ All the groups of faces are listed with their name, and a constant default value is set by default for each group. + It is possible to modify the value associated with some groups. It is also possible to modify the default value, + or to reset all the values to the default. +
+

+ Below is the description of the dialog controls. + +

Input MED file

+ This field allows the selection of a med file (via the standard file open dialog). + The filling of this field is mandatory. + +

Output MED file

+ This field allows the definition of a med file (via the standard file save dialog). + The filling of this field is mandatory. It is set by default, with a suffix on input MED file. + It can be set equal to input MED file. + +

Field name

+ The name of the field to create. + +

default value

+ The default value for the field. When modified, groups set to the default value are modified. + +

reset

+ This button forces a general reset of all the groups to the default value. + +

table group value

+ This table is filled with one line per group of faces found in the mesh + """ + QMessageBox.about(self, self.tr("About mesh edges to shapes dialog"), msg); + + + def on_accept(self): + print("accept") + #TODO check medfile in and out not empty + #TODO preset for medFileOut + medFileIn = self.le_medFileIn.text() + medFileOut = self.le_medFileOut.text() + meshName = self.meshName + fieldName = self.le_field.text() + groups = [] + n = len(self.med_groups) + for i in range(n): + groups.append((self.med_groups[i], self.dsbItems[i].value())) + print(medFileIn) + print(medFileOut) + print(meshName) + print(fieldName) + print(groups) + + if not os.path.isfile(medFileIn): + msgBox = QMessageBox() + msgBox.setText( "Input MED file does not exist" ) + msgBox.exec_() + return + dir = os.path.dirname(medFileOut) + base = os.path.basename(medFileOut) + ext = os.path.splitext(medFileOut)[1] + if not os.path.isdir(dir) or (base == "") or (ext.lower() != ".med"): + msgBox = QMessageBox() + msgBox.setText( "Output MED file is not a valid path" ) + msgBox.exec_() + return + if medFileOut != medFileIn: + shutil.copyfile(medFileIn, medFileOut) + set_var_on_group(medFileOut, meshName, groups, fieldName) + self.accept() + + #initialField(medFileIn, medFileOut, epsgIn, epsgOut, offsetXin, offsetYin, offsetXout, offsetYout) + + def on_reject(self): + print("reject") + self.reject() + + +def execDialog(context): + print("execDialog") + # get context study, salomeGui + study = context.study + sg = context.sg + dlg = initialFieldDialog() + dlg.exec_() -- 2.39.2