1# -*- coding: utf-8 -*- 2 3#------------------------------------------------------------------------------- 4 5# This file is part of Code_Saturne, a general-purpose CFD tool. 6# 7# Copyright (C) 1998-2021 EDF S.A. 8# 9# This program is free software; you can redistribute it and/or modify it under 10# the terms of the GNU General Public License as published by the Free Software 11# Foundation; either version 2 of the License, or (at your option) any later 12# version. 13# 14# This program is distributed in the hope that it will be useful, but WITHOUT 15# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17# details. 18# 19# You should have received a copy of the GNU General Public License along with 20# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin 21# Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 23#------------------------------------------------------------------------------- 24 25""" 26This module defines the turbulence model data management. 27 28This module contains the following classes: 29- TurbulenceAdvancedOptionsDialogView 30- TurbulenceView 31""" 32 33#------------------------------------------------------------------------------- 34# Library modules import 35#------------------------------------------------------------------------------- 36 37import sys, logging 38 39#------------------------------------------------------------------------------- 40# Third-party modules 41#------------------------------------------------------------------------------- 42 43from code_saturne.Base.QtCore import * 44from code_saturne.Base.QtGui import * 45from code_saturne.Base.QtWidgets import * 46 47#------------------------------------------------------------------------------- 48# Application modules import 49#------------------------------------------------------------------------------- 50 51from code_saturne.model.Common import GuiParam 52from code_saturne.Base.QtPage import ComboModel, DoubleValidator, from_qvariant 53from code_saturne.Pages.TurbulenceForm import Ui_TurbulenceForm 54from code_saturne.Pages.TurbulenceAdvancedOptionsDialogForm import Ui_TurbulenceAdvancedOptionsDialogForm 55from code_saturne.model.TurbulenceModel import TurbulenceModel 56 57#------------------------------------------------------------------------------- 58# log config 59#------------------------------------------------------------------------------- 60 61logging.basicConfig() 62log = logging.getLogger("TurbulenceView") 63log.setLevel(GuiParam.DEBUG) 64 65#------------------------------------------------------------------------------- 66# Advanced dialog 67#------------------------------------------------------------------------------- 68 69class TurbulenceAdvancedOptionsDialogView(QDialog, Ui_TurbulenceAdvancedOptionsDialogForm): 70 """ 71 Advanced dialog 72 """ 73 def __init__(self, parent, case, default): 74 """ 75 Constructor 76 """ 77 QDialog.__init__(self, parent) 78 79 Ui_TurbulenceAdvancedOptionsDialogForm.__init__(self) 80 self.setupUi(self) 81 82 self.case = case 83 self.case.undoStopGlobal() 84 85 self.labelTurbDiff.hide() 86 self.comboBoxTurbDiff.hide() 87 self.turbDiff = None 88 89 self.default = default 90 self.result = self.default.copy() 91 92 if default['model'] in ('k-epsilon', 'k-epsilon-PL'): 93 title = self.tr("Options for k-epsilon model") 94 elif default['model'] in ('Rij-epsilon', 'Rij-SSG', 'Rij-EBRSM'): 95 title = self.tr("Options for Rij-epsilon model") 96 97 self.labelTurbDiff.show() 98 self.comboBoxTurbDiff.show() 99 self.turbDiff = ComboModel(self.comboBoxTurbDiff, 2, 1) 100 self.turbDiff.addItem(self.tr("Scalar diffusivity (Shir model)"), 'shir') 101 self.turbDiff.addItem(self.tr("Tensorial diffusivity (Daly and Harlow model)"), 'daly_harlow') 102 103 # Initialization of turb diff model 104 self.turbDiff.setItem(str_model=str(self.result['turb_diff'])) 105 106 elif default['model'] == 'k-omega-SST': 107 title = self.tr("Options for k-omega-SST model") 108 elif default['model'] == 'v2f-BL-v2/k': 109 title = self.tr("Options for v2f-BL-v2/k model") 110 elif default['model'] == 'Spalart-Allmaras': 111 title = self.tr("Options for Spalart-Allmaras model") 112 113 self.setWindowTitle(title) 114 115 self.checkBoxGravity.setEnabled(True) 116 self.comboBoxWallFunctions.setEnabled(True) 117 118 if default['model'] == 'Rij-EBRSM': 119 # Combo - piecewise laws (iwallf=2,3) unavailable through the GUI 120 self.wallFunctions = ComboModel(self.comboBoxWallFunctions, 2, 1) 121 self.wallFunctions.addItem(self.tr("No wall function"), '0') 122 self.wallFunctions.addItem(self.tr("2-scale model (all y+)"), '7') 123 124 # Initialization of wall function model 125 self.wallFunctions.setItem(str_model=str(self.result['wall_function'])) 126 127 elif default['model'] == 'v2f-BL-v2/k': 128 self.wallFunctions = ComboModel(self.comboBoxWallFunctions, 1, 1) 129 self.wallFunctions.addItem(self.tr("No wall function"), '0') 130 self.comboBoxWallFunctions.setEnabled(False) 131 elif default['model'] == 'Spalart-Allmaras': 132 self.wallFunctions = ComboModel(self.comboBoxWallFunctions, 1, 1) 133 self.wallFunctions.addItem(self.tr("One scale model (log law)"), '2') 134 self.comboBoxWallFunctions.setEnabled(False) 135 elif default['model'] == 'k-omega-SST': 136 # Combo - power law (iwallf=1) unavailable through the GUI 137 self.wallFunctions = ComboModel(self.comboBoxWallFunctions, 5, 1) 138 self.wallFunctions.addItem(self.tr("No wall function"), '0') 139 self.wallFunctions.addItem(self.tr("1-scale model (log law)"), '2') 140 self.wallFunctions.addItem(self.tr("2-scale model (log law)"), '3') 141 self.wallFunctions.addItem(self.tr("2-scale model (all y+)"), '7') 142 self.wallFunctions.addItem(self.tr("Scalable 2-scale model (log law)"), '4') 143 144 # Initialization of wall function model 145 self.wallFunctions.setItem(str_model=str(self.result['wall_function'])) 146 else: 147 # Combo - power law (iwallf=1) unavailable through the GUI 148 self.wallFunctions = ComboModel(self.comboBoxWallFunctions, 4, 1) 149 self.wallFunctions.addItem(self.tr("No wall function"), '0') 150 self.wallFunctions.addItem(self.tr("1-scale model (log law)"), '2') 151 self.wallFunctions.addItem(self.tr("2-scale model (log law)"), '3') 152 self.wallFunctions.addItem(self.tr("Scalable 2-scale model (log law)"), '4') 153 154 # Initialization of wall function model 155 self.wallFunctions.setItem(str_model=str(self.result['wall_function'])) 156 157 # Initialization gravity terms 158 if self.result['gravity_terms'] == 'on': 159 self.checkBoxGravity.setChecked(True) 160 else: 161 self.checkBoxGravity.setChecked(False) 162 163 self.case.undoStartGlobal() 164 165 166 def get_result(self): 167 """ 168 Method to get the result 169 """ 170 return self.result 171 172 173 def accept(self): 174 """ 175 Method called when user clicks 'OK' 176 """ 177 if self.checkBoxGravity.isChecked(): 178 self.result['gravity_terms'] = "on" 179 else: 180 self.result['gravity_terms'] = "off" 181 self.result['wall_function'] = \ 182 int(self.wallFunctions.dicoV2M[str(self.comboBoxWallFunctions.currentText())]) 183 if self.turbDiff: 184 self.result['turb_diff'] = self.turbDiff.dicoV2M[str(self.comboBoxTurbDiff.currentText())] 185 186 QDialog.accept(self) 187 188 189 def reject(self): 190 """ 191 Method called when user clicks 'Cancel' 192 """ 193 QDialog.reject(self) 194 195 196#------------------------------------------------------------------------------- 197# Main view class 198#------------------------------------------------------------------------------- 199 200class TurbulenceView(QWidget, Ui_TurbulenceForm): 201 """ 202 Class to open Turbulence Page. 203 """ 204 def __init__(self, parent=None, case=None): 205 """ 206 Constructor 207 """ 208 QWidget.__init__(self, parent) 209 210 Ui_TurbulenceForm.__init__(self) 211 self.setupUi(self) 212 213 self.case = case 214 self.case.undoStopGlobal() 215 self.model = TurbulenceModel(self.case) 216 217 # Combo model 218 219 self.modelTurbModel = ComboModel(self.comboBoxTurbModel,10,1) 220 221 self.modelTurbModel.addItem(self.tr("No model (i.e. laminar flow)"), "off") 222 223 # RANS - Algebraic 224 self.modelTurbModel.addItemGroup(self.tr("RANS - Algebraic")) 225 self.modelTurbModel.addItem(self.tr("Mixing length"), "mixing_length", groupName="RANS - Algebraic") 226 227 # RANS - 1st order 228 self.modelTurbModel.addItemGroup(self.tr("RANS - 1st order")) 229 230 e = {"k-epsilon-PL": "k-\u03B5 Linear Production", 231 "v2f-BL-v2/k": "v\u00B2-f BL-v\u00B2/k", 232 "k-omega-SST": "k-\u03C9 SST", 233 "Spalart-Allmaras": "Spalart-Allmaras"} 234 235 if QT_API == "PYQT4": 236 e["k-epsilon-PL"] = "k-epsilon Linear Production" 237 e["v2f-BL-v2/k"] = "v2f BL-v2/k" 238 e["k-omega-SST"] = "k-omega SST" 239 240 for k in ("k-epsilon-PL", "v2f-BL-v2/k", 241 "k-omega-SST", "Spalart-Allmaras"): 242 self.modelTurbModel.addItem(self.tr(e[k]), k, 243 groupName="RANS - 1st order") 244 245 # RANS - 2nd order 246 self.modelTurbModel.addItemGroup(self.tr("RANS - 2nd order")) 247 248 e = {"Rij-SSG": "R\u1D62\u2C7C-\u03B5 SSG", 249 "Rij-EBRSM": "R\u1D62\u2C7C-\u03B5 EBRSM"} 250 251 if QT_API == "PYQT4": 252 e["Rij-SSG"] = "Rij-SSG" 253 e["Rij-EBRSM"] = "Rij-EBRSM" 254 255 for k in ("Rij-SSG", "Rij-EBRSM"): 256 self.modelTurbModel.addItem(self.tr(e[k]), k, 257 groupName="RANS - 2nd order") 258 259 # LES 260 self.modelTurbModel.addItemGroup(self.tr("LES")) 261 262 self.modelTurbModel.addItem(self.tr("Smagorinsky"), 263 "LES_Smagorinsky", 264 groupName="LES") 265 self.modelTurbModel.addItem(self.tr("Standard dynamic model"), 266 "LES_dynamique", 267 groupName="LES") 268 self.modelTurbModel.addItem(self.tr("WALE"), 269 "LES_WALE", 270 groupName="LES") 271 272 # Others 273 self.modelTurbModel.addItemGroup(self.tr("")) 274 self.modelTurbModel.addItemGroup(self.tr("Others")) 275 276 e = {"Rij-epsilon": "R\u1D62\u2C7C-\u03B5 LRR", 277 "k-epsilon": "k-\u03B5"} 278 279 if QT_API == "PYQT4": 280 e["Rij-epsilon"] = "Rij-LRR" 281 e["k-epsilon"] = "k-epsilon" 282 283 for k in ("Rij-epsilon", "k-epsilon"): 284 self.modelTurbModel.addItem(self.tr(e[k]), k, 285 groupName="Others") 286 287 self.modelLength = ComboModel(self.comboBoxLength,2,1) 288 self.modelLength.addItem(self.tr("Automatic"), 'automatic') 289 self.modelLength.addItem(self.tr("Prescribed"), 'prescribed') 290 self.comboBoxLength.setSizeAdjustPolicy(QComboBox.AdjustToContents) 291 292 # Connections 293 294 self.comboBoxTurbModel.activated[str].connect(self.slotTurbulenceModel) 295 self.pushButtonAdvanced.clicked.connect(self.slotAdvancedOptions) 296 self.lineEditLength.textChanged[str].connect(self.slotLengthScale) 297 298 self.lineEditV0.textChanged[str].connect(self.slotVelocity) 299 self.comboBoxLength.activated[str].connect(self.slotLengthChoice) 300 self.lineEditL0.textChanged[str].connect(self.slotLength) 301 302 # Frames display 303 304 self.frameAdvanced.hide() 305 self.frameLength.hide() 306 307 # Validators 308 309 validator = DoubleValidator(self.lineEditLength, min=0.0) 310 validator.setExclusiveMin(True) 311 self.lineEditLength.setValidator(validator) 312 313 validatorV0 = DoubleValidator(self.lineEditV0, min=0.0) 314 self.lineEditV0.setValidator(validatorV0) 315 316 validatorL0 = DoubleValidator(self.lineEditL0, min=0.0) 317 self.lineEditL0.setValidator(validatorL0) 318 319 # Update the turbulence models list with the calculation features 320 321 for turb in self.model.turbulenceModels(): 322 if turb not in self.model.turbulenceModelsList(): 323 self.modelTurbModel.disableItem(str_model=turb) 324 325 # Select the turbulence model 326 327 model = self.model.getTurbulenceModel() 328 self.modelTurbModel.setItem(str_model=model) 329 self.__initializeView() 330 331 # Length scale 332 333 l_scale = self.model.getLengthScale() 334 self.lineEditLength.setText(str(l_scale)) 335 336 # Initialization 337 338 v = self.model.getVelocity() 339 self.lineEditV0.setText(str(v)) 340 341 init_length_choice = self.model.getLengthChoice() 342 self.modelLength.setItem(str_model=init_length_choice) 343 if init_length_choice == 'automatic': 344 self.lineEditL0.setText(str()) 345 self.lineEditL0.hide() 346 self.labelUnitL0.hide() 347 else: 348 self.lineEditL0.show() 349 self.labelUnitL0.show() 350 l = self.model.getLength() 351 self.lineEditL0.setText(str(l)) 352 353 self.case.undoStartGlobal() 354 355 356 def __initializeView(self): 357 """ 358 Private Method. 359 initalize view for a turbulence model 360 """ 361 model = self.model.getTurbulenceModel() 362 363 self.frameAdvanced.hide() 364 self.frameLength.hide() 365 self.groupBoxReferenceValues.hide() 366 367 if model not in ('off', 'mixing_length', 'LES_Smagorinsky', 'LES_dynamique', 'LES_WALE'): 368 self.groupBoxReferenceValues.show() 369 370 if model == 'mixing_length': 371 self.frameLength.show() 372 self.frameAdvanced.hide() 373 self.model.getLengthScale() 374 elif model not in ('off', 'LES_Smagorinsky', 'LES_dynamique', 'LES_WALE', 'Spalart-Allmaras'): 375 self.frameLength.hide() 376 self.frameAdvanced.show() 377 378 if model in ('off', 'LES_Smagorinsky', 'LES_dynamique', 'LES_WALE', 'Spalart-Allmaras'): 379 self.line.hide() 380 else: 381 self.line.show() 382 383 384 @pyqtSlot(str) 385 def slotLengthScale(self, text): 386 """ 387 Private slot. 388 Input XLOMLG. 389 """ 390 if self.lineEditLength.validator().state == QValidator.Acceptable: 391 l_scale = from_qvariant(text, float) 392 self.model.setLengthScale(l_scale) 393 394 395 @pyqtSlot(str) 396 def slotTurbulenceModel(self, text): 397 """ 398 Private slot. 399 Input ITURB. 400 """ 401 model = self.modelTurbModel.dicoV2M[str(text)] 402 self.model.setTurbulenceModel(model) 403 self.__initializeView() 404 405 @pyqtSlot(str) 406 def slotVelocity(self, text): 407 """ 408 Private slot. 409 Input reference velocity. 410 """ 411 if self.lineEditV0.validator().state == QValidator.Acceptable: 412 v = from_qvariant(text, float) 413 self.model.setVelocity(v) 414 415 416 @pyqtSlot(str) 417 def slotLengthChoice(self,text): 418 """ 419 Private slot. 420 Input mode for reference length. 421 """ 422 choice = self.modelLength.dicoV2M[str(text)] 423 self.model.setLengthChoice(choice) 424 if choice == 'automatic': 425 self.lineEditL0.setText(str()) 426 self.lineEditL0.hide() 427 self.labelUnitL0.hide() 428 else: 429 self.lineEditL0.show() 430 self.labelUnitL0.show() 431 value = self.model.getLength() 432 self.lineEditL0.setText(str(value)) 433 log.debug("slotlengthchoice-> %s" % choice) 434 435 436 @pyqtSlot(str) 437 def slotLength(self, text): 438 """ 439 Private slot. 440 Input reference length. 441 """ 442 if self.lineEditL0.validator().state == QValidator.Acceptable: 443 l = from_qvariant(text, float) 444 self.model.setLength(l) 445 446 447 @pyqtSlot() 448 def slotAdvancedOptions(self): 449 """ 450 Private slot. 451 Ask one popup for advanced specifications 452 """ 453 default = {} 454 default['model'] = self.model.getTurbulenceModel() 455 default['wall_function'] = self.model.getWallFunction() 456 default['turb_diff'] = self.model.getTurbDiffModel() 457 default['gravity_terms'] = self.model.getGravity() 458 log.debug("slotAdvancedOptions -> %s" % str(default)) 459 460 dialog = TurbulenceAdvancedOptionsDialogView(self, self.case, default) 461 if dialog.exec_(): 462 result = dialog.get_result() 463 log.debug("slotAdvancedOptions -> %s" % str(result)) 464 self.model.setTurbulenceModel(result['model']) 465 self.model.setWallFunction(result['wall_function']) 466 self.model.setTurbDiffModel(result['turb_diff']) 467 self.model.setGravity(result['gravity_terms']) 468 469 470#------------------------------------------------------------------------------- 471# End 472#------------------------------------------------------------------------------- 473