def set_leq_method(self, val, index): ui = self.ui.numerics cb = ui.tablewidget_linear_solver.cellWidget(index - 1, COL_SOLVER) cb.setToolTip(get_combobox_item(cb, val).toolTip()) key = 'leq_method' self.update_keyword(key, LEQ_METHODS[val], args=[index]) cb.setToolTip(get_combobox_item(cb, val).toolTip())
def set_sweep(self, val, index): ui = self.ui.numerics cb = ui.tablewidget_preconditioner.cellWidget(index - 1, COL_SWEEP) cb.setToolTip(get_combobox_item(cb, val).toolTip()) key = 'leq_sweep' self.update_keyword(key, SWEEP_TYPES[val], args=[index]) cb.setToolTip(get_combobox_item(cb, val).toolTip()) self.setup_numerics()
def init_model_setup(self): ui = self.ui.model_setup ui.combobox_solver.activated.connect(self.set_solver) ui.checkbox_disable_fluid_solver.clicked.connect(self.disable_fluid_solver) ui.checkbox_keyword_energy_eq.clicked.connect(self.enable_energy_eq) key = 'turbulence_model' cb = ui.combobox_turbulence_model cb.activated.connect(self.set_turbulence_model) for (i, value) in enumerate(TURBULENCE_MODELS): item = get_combobox_item(cb, i) self.add_tooltip(item, key, value=value) key = 'drag_type' cb = ui.combobox_drag_type cb.activated.connect(self.set_drag_type) assert ui.combobox_drag_type.count() == len(DRAG_TYPES) for item in (ui.label_drag_type, cb): self.add_tooltip(item, key) for (i, val) in enumerate(DRAG_TYPES): item = get_combobox_item(cb, i) self.add_tooltip(item, key=key, description=self.keyword_doc[key]['valids'][val]['note'], value=val) cb = ui.combobox_momentum_formulation cb.activated.connect(self.set_momentum_formulation) self.add_tooltip(ui.label_momentum_formulation, key=None, description=self.keyword_doc['model_b']['description']) for i in range(4): item = get_combobox_item(cb, i) if i == 0: key = 'model_b' value = False elif i == 1: key = 'model_b' value = True elif i == 2: key = 'jackson' value = None else: key = 'ishii' value = None self.add_tooltip(item, key=key, value=value) key = 'subgrid_type' cb = ui.combobox_subgrid_type cb.activated.connect(self.set_subgrid_type) for (i, value) in enumerate(SUBGRID_TYPES): if value == 'NONE': self.add_tooltip(get_combobox_item(cb, i), key, value='None', description='No subgrid model') else: self.add_tooltip(get_combobox_item(cb, i), key, value=value.title()) self.fluid_solver_disabled = False # squelch pylint access-member-before-definition
def init_monitors(self): ui = self.ui.monitors self.monitors = {} # key: index. value: data dictionary for monitor self.monitors_current_index = None self.monitors_current_region = None # And the names of the regions which define them self.monitors_region_dict = None self.monitors_saved_solids_names = [] ui.dynamic_widgets = {} ui.toolbutton_add.clicked.connect(self.monitors_show_regions_popup) ui.toolbutton_delete.clicked.connect(self.monitors_delete_regions) for tb in (ui.toolbutton_delete, ): tb.setEnabled(False) # Need a selection ui.tablewidget_regions.itemSelectionChanged.connect( self.handle_monitors_region_selection) self.monitors_current_tab = FLUID_TAB # If fluid is disabled, we will switch self.monitors_current_solid = self.P = None ui.pushbutton_fluid.pressed.connect( lambda: self.monitors_change_tab(FLUID_TAB, None)) ui.pushbutton_scalar.pressed.connect( lambda: self.monitors_change_tab(SCALAR_TAB, None)) ui.pushbutton_reactions.pressed.connect( lambda: self.monitors_change_tab(REACTIONS_TAB, None)) # Phase tab is not user-selectable # Trim width of "Fluid", "Scalar" "Reactions" and "Phase", like we do for # dynamically-created "Solid #" buttons for b in (ui.pushbutton_fluid, ui.pushbutton_scalar, ui.pushbutton_reactions, ui.pushbutton_phase): w = b.fontMetrics().boundingRect(b.text()).width() + 20 b.setMaximumWidth(w) # Show groupbox without title (title is empty string) height = ui.checkbox_keyword_monitor_ep_g_args_MONITOR.sizeHint( ).height() tweak = 3 ui.stackedwidget_detail.setStyleSheet( # Fix gap where title would be, with negative padding. # This is somewhat questionable (i.e. a total hack) 'QGroupBox {margin-top: %spx; padding-top: %spx }' % (tweak - height, height)) cb = ui.combobox_monitor_type key = 'monitor_type' for i in range(len(cb)): self.add_tooltip(get_combobox_item(cb, i), key, value=i) cb.setToolTip(get_combobox_item(cb, cb.currentIndex()).toolTip()) cb.activated.connect(self.handle_combobox_monitor_type) # Make the table update when user changed MONITOR_NAME le = ui.lineedit_keyword_monitor_name_args_MONITOR le.post_update = self.setup_monitors
def init_numerics_linear_solver_pane(self): ui = self.ui.numerics tw = ui.tablewidget_linear_solver # Add some tooltips key = 'leq_method' self.add_tooltip(tw.horizontalHeaderItem(COL_SOLVER), key) key = 'leq_it' self.add_tooltip(tw.horizontalHeaderItem(COL_RELAX), key) key = 'leq_tol' self.add_tooltip(tw.horizontalHeaderItem(COL_TOL), key) # Populate table with combobox and lineedit widgets for i in range(1, 1 + DIM_EQS): row = i - 1 key = 'leq_method' cb = ComboBox() cb.args = [i] for (j, name) in enumerate(LEQ_METHOD_NAMES): cb.addItem(name) for (j, method) in enumerate(LEQ_METHODS): item = get_combobox_item(cb, j) item.args = [i] self.add_tooltip(item, key, value=method) cb.setToolTip(get_combobox_item(cb, 0).toolTip()) cb.currentIndexChanged.connect( lambda val, i=i: self.set_leq_method(val, i)) tw.setCellWidget(row, COL_SOLVER, cb) key = 'leq_it' le = LineEdit() le.dtype = int le.min = 0 le.key = key le.args = [i] tw.setCellWidget(row, COL_ITER, le) le.value_updated.connect(self.project.submit_change) self.add_tooltip(le, key) key = 'leq_tol' le = LineEdit() le.dtype = float le.min = 0 le.key = key le.args = [i] tw.setCellWidget(row, COL_TOL, le) le.value_updated.connect(self.project.submit_change) self.add_tooltip(le, key)
def handle_combobox_monitor_type(self, index): ui = self.ui.monitors cb = ui.combobox_monitor_type cb.setToolTip(get_combobox_item(cb, index).toolTip()) mon = self.monitors_current_index if mon is None: # No selection return key = 'monitor_type' val = index prev_phase_required = self.monitor_requires_phase(mon) self.update_keyword(key, val, args=[mon]) new_phase_required = self.monitor_requires_phase(mon) if prev_phase_required != new_phase_required: # Unset keys when 'phase_required' changes.. kwlist = list(self.project.keywordItems()) for kw in kwlist: key, args = kw.key, kw.args if key.startswith('monitor_') and args and args[0] == mon: if key in ('monitor_x_w', 'monitor_y_s', 'monitor_z_b', 'monitor_x_e', 'monitor_y_n', 'monitor_z_t', 'monitor_name', 'monitor_type', 'monitor_dt'): continue self.unset_keyword(key, args=args) self.handle_monitors_region_selection( ) # Will update tabset & ensure valid tab
def set_discretize(self, val, index): ui = self.ui.numerics key = 'discretize' self.update_keyword(key, val, args=[index]) cb = ui.tablewidget_discretization.cellWidget(index - 1, COL_SCHEME) cb.setToolTip(get_combobox_item(cb, val).toolTip()) self.setup_numerics() # update checkboxes etc
def init_numerics_discretization_pane(self): # Add some extra tooltips ui = self.ui.numerics cb = ui.combobox_cn_on key = 'cn_on' cb.currentIndexChanged.connect(self.set_cn_on) self.add_tooltip(get_combobox_item(cb, 0), key, value='.FALSE.') self.add_tooltip(get_combobox_item(cb, 1), key, value='.TRUE.') tw = ui.tablewidget_discretization key = 'discretize' self.add_tooltip(tw.horizontalHeaderItem(COL_SCHEME), key) key = 'ur_fac' self.add_tooltip(tw.horizontalHeaderItem(COL_RELAX), key) # Populate table with combobox and lineedit widgets for i in range(1, 1 + DIM_EQS): row = i - 1 key = 'discretize' cb = ComboBox() cb.args = [i] for name in DISCRETIZATION_NAMES: cb.addItem(name) for j in range(len(DISCRETIZATION_NAMES)): item = get_combobox_item(cb, j) item.args = [i] self.add_tooltip(item, key, value=j) cb.setToolTip(get_combobox_item(cb, 0).toolTip()) cb.currentIndexChanged.connect( lambda val, i=i: self.set_discretize(val, i)) tw.setCellWidget(row, COL_SCHEME, cb) key = 'ur_fac' le = LineEdit() le.dtype = float le.key = key le.args = [i] tw.setCellWidget(row, COL_RELAX, le) le.value_updated.connect(self.project.submit_change) self.add_tooltip(le, key)
def set_subgrid_type(self, idx): # Sets keyword SUBGRID_TYPE # Available selections # NONE (DEFAULT) # IGCI # MILIOLI ui = self.ui.model_setup cb = ui.combobox_subgrid_type self.update_keyword('subgrid_type', SUBGRID_TYPES[idx]) cb.setToolTip(get_combobox_item(cb, idx).toolTip()) self.setup_model_setup()
def init_numerics_preconditioner_pane(self): ui = self.ui.numerics tw = ui.tablewidget_preconditioner # Add some tooltips to column headers key = 'leq_pc' self.add_tooltip(tw.horizontalHeaderItem(COL_PRECON), key) key = 'leq_sweep' self.add_tooltip(tw.horizontalHeaderItem(COL_SWEEP), key) # Populate table for i in range(1, 1 + DIM_EQS): row = i - 1 key = 'leq_pc' cb = ComboBox() cb.args = [i] for j, name in enumerate(PRECON_NAMES): cb.addItem(name) item = get_combobox_item(cb, j) item.args = [i] self.add_tooltip(item, key, value=PRECON_TYPES[j]) cb.currentIndexChanged.connect( lambda val, i=i: self.set_preconditioner(val, i)) tw.setCellWidget(row, COL_PRECON, cb) self.add_tooltip(cb, key) key = 'leq_sweep' cb = ComboBox() cb.args = [i] for j, name in enumerate(SWEEP_NAMES): cb.addItem(name) item = get_combobox_item(cb, j) item.args = [i] self.add_tooltip(item, key, value=SWEEP_TYPES[j]) cb.currentIndexChanged.connect( lambda val, i=i: self.set_sweep(val, i)) tw.setCellWidget(row, COL_SWEEP, cb) self.add_tooltip(cb, key)
def init_solids_tfm(self): ui = self.ui.solids key = 'kt_type' cb = ui.combobox_kt_type cb.activated.connect(self.set_kt_type) self.add_tooltip(cb, key) for (i, v) in enumerate(KT_TYPES): self.add_tooltip(get_combobox_item(cb, i), key, value=v) key = 'friction_model' cb = ui.combobox_friction_model self.add_tooltip(cb, key) for (i, v) in enumerate(FRICTION_MODELS): self.add_tooltip(get_combobox_item(cb, i), key, value=v) cb.activated.connect(self.set_friction_model) key = 'rdf_type' cb = ui.combobox_rdf_type self.add_tooltip(cb, key) for (i, v) in enumerate(RDF_TYPES): self.add_tooltip(get_combobox_item(cb, i), key, value=v or 'CARNAHAN_STARLING') cb.activated.connect(self.set_rdf_type) key = 'blending_function' cb = ui.combobox_blending_function self.add_tooltip(cb, key) for (i, v) in enumerate(BLENDING_FUNCTIONS): self.add_tooltip(get_combobox_item(cb, i), key, value=v) cb.activated.connect(self.set_blending_function) # This does not correspond to a single keyword label = ui.label_max_packing_correlation cb = ui.combobox_max_packing_correlation description = 'Correlation to compute maximum packing for polydisperse systems' self.add_tooltip(label, key=None, description=description) self.add_tooltip(cb, key=None, description=description) self.add_tooltip(get_combobox_item(cb, 0), key=None, description="Constant packing correlation") self.add_tooltip(get_combobox_item(cb, 1), key='yu_standish') self.add_tooltip(get_combobox_item(cb, 2), key='fedors_landel') cb.activated.connect(self.set_max_packing_correlation)
def set_turbulence_model(self, val): # Available selections: # None; [DEFAULT] # Mixing Length: # Selection always available # Sets keyword TURBULENCE_MODEL to MIXING_LENGTH # Requires IC_L_SCALE for all IC regions # K-Epsilon # Selection always available # Sets keyword TURBULENCE_MODEL to K_EPSILON # Requires IC_K_TURB_G for all IC regions TODO # Requires IC_E_TURB_G for all IC regions TODO # Requires BC_K_TURB_G for inflow (MI and PI) BC regions TODO # Requires BC_E_TURB_G for inflow (MI and PI) BC regions TODO ui = self.ui.model_setup cb = ui.combobox_turbulence_model if cb.currentIndex() != val: cb.setCurrentIndex(val) turbulence_model = TURBULENCE_MODELS[val] # Avoid resetting turbulence_model from None to 'NONE' at startup if turbulence_model != self.project.get_value('turbulence_model', default=DEFAULT_TURBULENCE_MODEL): self.update_keyword('turbulence_model', turbulence_model) # Set combobox tooltip to match item value cb.setToolTip(get_combobox_item(cb, val).toolTip()) enabled = (turbulence_model != 'NONE') #Specify maximum fluid viscosity (not shown in mockup) # Selection available if TURBULENCE_MODEL =/ 'NONE' # Sets keyword MU_GMAX # DEFAULT 1.0e3 (Pa.s) for item in (ui.label_mu_gmax, ui.lineedit_keyword_mu_gmax, ui.label_mu_gmax_units): item.setEnabled(enabled) if enabled: val = ui.lineedit_keyword_mu_gmax.value if val=='' or val is None: val = default_values.mu_g0 self.update_keyword('mu_gmax', val) else: self.unset_keyword('mu_gmax')
def setup_model_setup(self): ui = self.ui.model_setup solver = self.project.solver ui.checkbox_disable_fluid_solver.setChecked(self.fluid_solver_disabled) self.add_tooltip(ui.checkbox_disable_fluid_solver, key=None, description="""Granular flow in vacuum: Sets ro_g0 (fluid density) to 0 and disables fluid momentum equations for faster convergence""") self.disable_fluid_solver(self.fluid_solver_disabled) # Don't allow setting single-phase once solids are defined cb = ui.combobox_solver get_combobox_item(cb, 0).setEnabled(not self.solids) key = 'turbulence_model' turbulence_model = self.project.get_value(key, default=DEFAULT_TURBULENCE_MODEL) if turbulence_model not in TURBULENCE_MODELS: self.error("Invalid turbulence model %s" % turbulence_model) turbulence_model = DEFAULT_TURBULENCE_MODEL self.update_keyword(key, turbulence_model) else: self.set_turbulence_model(TURBULENCE_MODELS.index(turbulence_model)) #Specify Gravitational acceleration # Specification always available # Sets keywords GRAVITY_X, GRAVITY_Y, GRAVITY_Z # DEFAULT values # handled by keyword widgets # Leave blank when converting dat files to mfx # New cases take the values from the mfix.dat.template # Implementation Note: Not doing this. There's not a # strong reason for it, and we don't distinguish converting dat files from opening existing projects. # If keyword GRAVITY is specified # GRAVITY_Y = -GRAVITY # GRAVITY_X = GRAVITY_Z = 0.0 #Specify drag model # Selection requires TFM, DEM, or PIC solver enabled = self.project.solver in (TFM, DEM, PIC) for item in (ui.label_drag_type, ui.combobox_drag_type): item.setEnabled(enabled) val = self.project.get_value('drag_type') if val is None: idx = DRAG_TYPES.index(DEFAULT_DRAG_TYPE) else: if not val in DRAG_TYPES: self.error('Invalid drag_type %s' % val) idx = DRAG_TYPES.index(DEFAULT_DRAG_TYPE) else: idx = DRAG_TYPES.index(val) ui.combobox_drag_type.setCurrentIndex(idx) drag_type = DRAG_TYPES[idx] # SYAM_OBRIEN # Specify model parameter: DRAG_C1 # DEFAULT 0.8 # Specify model parameter: DRAG_D1 # DEFAULT 2.65 enabled = self.project.solver in (TFM, DEM, PIC) and drag_type == 'SYAM_OBRIEN' for item in (ui.label_syam_obrien, ui.label_drag_c1, ui.lineedit_keyword_drag_c1, ui.label_drag_d1, ui.lineedit_keyword_drag_d1): item.setEnabled(enabled) if enabled: for (key, default) in (('drag_c1', 0.8), ('drag_d1', 2.65)): val = self.project.get_value(key) if val is None: val = default self.update_keyword(key, val) # HYS # Specify model parameter LAM_HYS # DEFAULT 1.0e-6 (meters) key = 'lam_hys' default = 1.0e-6 enabled = self.project.solver in (TFM, DEM, PIC) and drag_type == 'HYS' for item in (ui.label_lam_hys, ui.lineedit_keyword_lam_hys, ui.label_lam_hys_units): item.setEnabled(enabled) if enabled: val = self.project.get_value(key) if val is None: val = default self.update_keyword(key, val) #Specify momentum equation formulation; Select Model A, Model B; Jackson, Ishii #MODEL_B #[ .FALSE. ] -------------------------- Use Model A #.TRUE. ----------------------------- Use Model B. model_b = self.project.get_value('model_b', default=False) #ISHII #Flag to enable Ishii form of momentum equations. two-phase flow. #.TRUE. ----------------------------- Solve Ishii form of momentum equations. # [ .FALSE. ] ishii = self.project.get_value('ishii', default=False) #JACKSON #LOGICAL #Flag to enable Jackson form of momentum equations. #.TRUE. ----------------------------- Solve Jackson form of momentum equations. #[ .FALSE. ] -------------------------- Default jackson = self.project.get_value('jackson', default=False) if model_b + ishii + jackson > 1: self.error("Invalid momentum equations: more than 1 of model_b, ishii and jackson specified") cb = ui.combobox_momentum_formulation idx = 0 # model A if model_b: idx = 1 elif jackson: idx = 2 elif ishii: idx = 3 cb.setCurrentIndex(idx) # set combobox cb.setToolTip(get_combobox_item(cb, idx).toolTip()) #Select sub-grid model: # Selection requirements: # Only available with MFIX-TFM solver # DRAG_TYPE="WEN_YU" # KT_TYPE="ALGEBRAIC" # TURBULENCE_MODEL /= K_EPSILON # BLENDING_STRESS = NONE # FRICTION_MODEL /= SRIVASTAVA # (There are more restrictions…) key = 'subgrid_type' cb = ui.combobox_subgrid_type drag_type = self.project.get_value('drag_type', default=DEFAULT_DRAG_TYPE) kt_type = self.project.get_value('kt_type', default=DEFAULT_KT_TYPE) turbulence_model = self.project.get_value('turbulence_model', default=DEFAULT_TURBULENCE_MODEL) blending_stress = self.project.get_value('blending_stress') # Note, not set anywhere in GUI friction_model = self.project.get_value('friction_model', default=DEFAULT_FRICTION_MODEL) enabled = (solver == TFM and drag_type == 'WEN_YU' and kt_type == 'ALGEBRAIC' and turbulence_model != 'K_EPSILON' and bool(blending_stress) == False and friction_model != 'SRIVASTAVA') cb = ui.combobox_subgrid_type for item in (ui.label_subgrid_type, cb, ui.label_filter_size_ratio, ui.lineedit_keyword_filter_size_ratio, ui.checkbox_keyword_subgrid_wall): item.setEnabled(enabled) if not enabled: self.unset_keyword(key) value = self.project.get_value(key, default=DEFAULT_SUBGRID_TYPE) if value not in SUBGRID_TYPES: self.error("Invalid subgrid_type %s" % value) value = DEFAULT_SUBGRID_TYPE idx = SUBGRID_TYPES.index(value) cb.setCurrentIndex(idx) cb.setToolTip(get_combobox_item(cb, idx).toolTip()) #Specify sub-grid model filter size ratio: # Specification requires SUBGRID_TYPE =/ NONE # Sets keyword FILTER_SIZE_RATIO # DEFAULT 2.0 # handled by widget.default #Enable sub-grid wall correction model: # Specification requires SUBGRID_TYPE =/ NONE # Sets keyword SUBGRID_WALL # DEFAULT FALSE # handled by widget.default enabled = self.project.get_value('subgrid_type') not in (None, 'NONE') for item in (ui.label_filter_size_ratio, ui.lineedit_keyword_filter_size_ratio, ui.checkbox_keyword_subgrid_wall): item.setEnabled(enabled)
def setup_tfm_tab(self): # Note - we are doing this setup on first show of this tab, rather # than at init or project load time ui = self.ui.solids # Select Viscous Stress Model (KTGS): # Selection is unavailable for constant solids viscosity (MU_S0 defined) # FIXME This is not right, solids viscosity model is phase-dependent #enabled = (self.solids_viscosity_model != CONSTANT) # SRS p18 #for item in (ui.label_kt_type, ui.combobox_kt_type, # ui.label_friction_model, ui.combobox_friction_model): # item.setEnabled(enabled) # SRS p18 - enable/disable menu items in viscous stress model key = 'kt_type' kt_type = self.project.get_value(key, default=DEFAULT_KT_TYPE) cb = ui.combobox_kt_type if kt_type: if kt_type not in KT_TYPES: self.warn("Invalid kt_type %s" % kt_type) self.unset_keyword(key) self.add_tooltip(cb, key=key) else: cb.setCurrentIndex(KT_TYPES.index(kt_type)) self.add_tooltip(cb, key=key, value=kt_type) else: self.add_tooltip(cb, key=key) mmax = self.project.get_value('mmax', default=1) k_e = (self.project.get_value( 'turbulence_model', default=DEFAULT_TURBULENCE_MODEL) == 'K_EPSILON') added_mass = self.project.get_value('m_am') or self.project.get_value( 'added_mass') drag_type = self.project.get_value('drag_type') friction_model = self.project.get_value('friction_model', default=DEFAULT_FRICTION_MODEL) enabled = [ True, #ALGEBRAIC True, #LUN_1984 True, #IA_NONEP k_e, #SIMONIN k_e, #AHMADI mmax == 1, #GD99 mmax == 1, #GTSH mmax <= 2 and (not added_mass) and drag_type in ('WEN_YU', 'HYS') ] # GHD #assert len(enabled) == len(KT_TYPES) for (i, e) in enumerate(enabled): set_item_enabled(get_combobox_item(cb, i), e) # Select Frictional Stress Model cb = ui.combobox_friction_model key = 'friction_model' # Srivastava and Sundaresan, 2003 # Unavailable for Algebraic Formulation viscous stress model set_item_enabled(get_combobox_item(cb, 1), (kt_type != 'ALGEBRAIC')) if kt_type == 'ALGEBRAIC': if friction_model == 'SRIVASTAVA': # Forbidden cb.setCurrentIndex(2) # None friction_model = FRICTION_MODELS[2] self.update_keyword(key, friction_model) if friction_model not in FRICTION_MODELS: self.warn("Unrecogized friction_model %s" % friction_model) cb.setCurrentIndex(2) # None friction_model = FRICTION_MODELS[2] self.update_keyword(key, friction_model) else: cb.setCurrentIndex(FRICTION_MODELS.index(friction_model)) self.add_tooltip(cb, key=key, value=friction_model) # Specify solids volume fraction at onset of friction enabled = (friction_model == 'SRIVASTAVA') for item in (ui.label_eps_f_min, ui.lineedit_keyword_eps_f_min): item.setEnabled(enabled) #Specify particle-particle restitution coefficient # Specification available only when required # Required for MMAX >=2 # Required for viscous stress models except GHD and algebraic formulation # Sets keyword C_E enabled = (mmax >= 2) or (kt_type not in ('GHD', 'ALGEBRAIC')) for item in (ui.label_c_e, ui.lineedit_keyword_c_e): item.setEnabled(enabled) # Garzo, Hrenya and Dufty, 2007 # Selection not available for MMAX > 2 # Selection not available with added mass force # Sets keyword KT_TYPE to GHD # Requires WEN_YU or HYS drag model # Specify coefficient of restitution; R_p (optional) # note R_P *replaces* C_E for kt_type==GHD ghd = (kt_type == 'GHD') if ghd: names = list(self.solids.keys()) if names: ui.label_r_p_1_1.setText("%s restitution coeff." % names[0]) if len(names) > 1: ui.label_r_p_1_2.setText("%s-%s restitution coeff." % (names[0], names[1])) ui.label_r_p_2_2.setText("%s restitution coeff." % names[1]) for item in (ui.label_c_e, ui.lineedit_keyword_c_e): item.hide() if ghd else item.show() for item in (ui.label_r_p_1_1, ui.lineedit_keyword_r_p_args_1_1): item.show() if ghd else item.hide() for item in (ui.label_r_p_1_2, ui.label_r_p_2_2, ui.lineedit_keyword_r_p_args_1_2, ui.lineedit_keyword_r_p_args_2_2): item.show() if (ghd and len(names) > 1) else item.hide() #Specify interphase friction coefficient # Specification available only when required # Required for MMAX >= 2 # Sets keyword C_F enabled = (mmax >= 2) for item in (ui.label_c_f, ui.lineedit_keyword_c_f): item.setEnabled(enabled) #Specify angle of particle-particle friction # Specification available only when required # Required for FRICTION_MODEL=SCHAEFFER # Required for FRICTION_MODEL=SRIVASTAVA # Sets keyword PHI enabled = friction_model in ('SCHAEFFER', 'SRIVASTAVA') for item in (ui.label_phi, ui.lineedit_keyword_phi): item.setEnabled(enabled) ### Advanced # Select radial distribution function key = 'rdf_type' rdf_type = self.project.get_value(key) if mmax > 1: if rdf_type not in RDF_TYPES: self.warn('Invalid rdf_type %s' % rdf_type) rdf_type = 'LEBOWITZ' self.update_keyword('rdf_type', rdf_type) if mmax < 2: if rdf_type: self.warn('Invalid rdf_type %s' % rdf_type) rdf_type = None self.update_keyword(key, rdf_type) cb = ui.combobox_rdf_type index = RDF_TYPES.index(rdf_type) if index == 0 and mmax > 1: index = 1 # Lebowitz rdf_type = 'LEBOWITZ' # So that tooltip will be set correctly cb.setCurrentIndex(index) self.add_tooltip(cb, key=key, value=rdf_type or 'CARNAHAN_STARLING') enabled = [mmax == 1] + 4 * [mmax > 1] for (i, e) in enumerate(enabled): set_item_enabled(get_combobox_item(cb, i), e) # Select stress blending model # Selection only available with FRICTION_MODEL=SCHAEFFER key = 'blending_function' cb = ui.combobox_blending_function blending_function = self.project.get_value( 'blending_function', default=DEFAULT_BLENDING_FUNCTION) if blending_function not in BLENDING_FUNCTIONS: self.warn('Invalid blending_function %s' % blending_function) blending_function = DEFAULT_BLENDING_FUNCTION self.update_keyword(key, blending_function) cb.setCurrentIndex(BLENDING_FUNCTIONS.index(blending_function)) self.add_tooltip(cb, key, value=blending_function) enabled = (friction_model == 'SCHAEFFER') for item in (ui.label_blending_function, cb): item.setEnabled(enabled) if not enabled: self.unset_keyword(key) else: # Restore value (should we do this?) v = cb.currentIndex() if self.project.get_value(key, default=DEFAULT_BLENDING_FUNCTION ) != BLENDING_FUNCTIONS[v]: self.update_keyword(key, BLENDING_FUNCTIONS[v]) # Specify the segregation slope coefficient # Only available for MMAX > 1 in conjunction with the following viscous stress # algebraic formulation; Lun. 1984; Simonin, 1996; Ahmadi, 1995 enabled = (mmax > 1) and kt_type in [ 'ALGEBRAIC', 'LUN_1984', 'SIMONIN', 'AHMADI' ] for item in (ui.label_segregation_slope_coefficient, ui.lineedit_keyword_segregation_slope_coefficient): item.setEnabled(enabled) # Select maximum packing correlation # Selection only available with FRICTION_MODEL=SCHAEFFER and MMAX >1 enabled = (friction_model == 'SCHAEFFER') and (mmax > 1) for item in (ui.label_max_packing_correlation, ui.combobox_max_packing_correlation): item.setEnabled(enabled) # Constant [DEFAULT] # Selection always available # Yu & Standish # Selection always available cb = ui.combobox_max_packing_correlation yu_standish = self.project.get_value('yu_standish') fedors_landel = self.project.get_value('fedors_landel') set_item_enabled(get_combobox_item(cb, 2), mmax == 2) # Only enable F_L for binary mixture if yu_standish and fedors_landel: self.warn("YU_STANDISH and FEDORS_LANDEL both set") self.unset_keyword('yu_standish') self.unset_keyword('fedors_landel') yu_standish = fedors_landel = False if fedors_landel and (mmax != 2): self.warn("FEDORS_LANDEL only valid for binary mixtures") self.unset_keyword('fedors_landel') fedors_landel = False if yu_standish: cb.setCurrentIndex(1) self.add_tooltip(cb, key='YU_STANDISH') elif fedors_landel: cb.setCurrentIndex(2) self.add_tooltip(cb, key='FEDORS_LANDEL') else: cb.setCurrentIndex(0) self.add_tooltip(cb, key=None, description="Constant packing correlation") # Specify excluded volume in Boyle-Massoudi stress (optional) # Only available with algebraic formulation of viscous stress model enabled = (kt_type == 'ALGEBRAIC') for item in (ui.label_v_ex, ui.lineedit_keyword_v_ex): item.setEnabled(enabled)
def handle_regions_selection(self): tw = self.ui.table cb = self.ui.combobox selections = get_selected_rows(tw) buttonbox = self.ui.buttonbox buttonbox.button(buttonbox.Ok).setEnabled(bool(selections)) region_types = [tw.item(x, 1).text() for x in selections] types_match = len(set(region_types)) < 2 if self.boundary: # Pressure Inflow # Not available for STL regions # Not available for volume regions # (also, chained regions must match type) disable = any(x in ('STL', 'box') for x in region_types) or not types_match item = get_combobox_item(cb, PRESSURE_INFLOW) set_item_enabled(item, not disable) # Volume BCs are only allowed for walls disable = any(x == 'box' for x in region_types) or not types_match for idx in (MASS_INFLOW, PRESSURE_OUTFLOW, MASS_OUTFLOW): item = get_combobox_item(cb, idx) set_item_enabled(item, not disable) # Don't stay on disabled item if not item_enabled(get_combobox_item(cb, cb.currentIndex())): cb.setCurrentIndex(BC_TYPES.index(DEFAULT_BC_TYPE)) bc_type = BC_TYPES[cb.currentIndex()] # Wall type boundary if bc_type.endswith('W'): self.handle_type(cb.currentIndex()) # For inflows/outflows, only allow compatible orientation else: if len(selections) == 1: region_type = tw.item(selections[0], 1).text() for i in range(0, tw.rowCount()): if i == selections[0]: continue enable = (tw.item(i, 1).text() == region_type) self.enable_row(i, enable) elif len(selections) == 0: self.handle_type(cb.currentIndex()) else: pass elif self.surface: # (would be nicer if this were in iss.py) # IS regions can be planes or volumes (not points or STLs) # *-Axis permeable/semipermeable not available for planes disable = selections and any('plane' in tw.item(x, 1).text() for x in selections) for index in (X_SEMIPERMEABLE, Y_SEMIPERMEABLE, Z_SEMIPERMEABLE, X_IMPERMEABLE, Y_IMPERMEABLE, Z_IMPERMEABLE): item = get_combobox_item(cb, index) set_item_enabled(item, (not selections) or (not disable)) for index in (SEMIPERMEABLE, IMPERMEABLE): item = get_combobox_item(cb, index) set_item_enabled(item, (not selections) or disable) # Available selections: # Impermeable # Selection only available for plane regions # X-Axis Impermeable # Selection only available for volume regions # Y-Axis Impermeable # Selection only available for volume regions # z-Axis Impermeable # Selection only available for volume regions # Semi-permeable # Selection only available for plane regions # X-Axis semi-permeable # Selection only available for volume regions # Y-Axis semi-permeable # Selection only available for volume regions # Z-Axis semi-permeable # Selection only available for volume regions # DEFAULT - Impermeable if len(selections) == 1: region_type = tw.item(selections[0], 1).text() plane = 'plane' in region_type for i in range(0, tw.rowCount()): if i == selections[0]: continue text = tw.item(i, 1).text() enable = (('plane' in text or text == 'box') or (plane == ('plane' in tw.item(i, 1).text()))) self.enable_row(i, enable) elif len(selections) == 0: self.handle_type(self.ui.combobox.currentIndex()) elif self.monitor: if len(selections) == 1: region_type = tw.item(selections[0], 1).text() for monitor_type in MONITOR_TYPES: point = monitor_type in MONITOR_TYPES_POINT plane = monitor_type in MONITOR_TYPES_PLANE volume = monitor_type in MONITOR_TYPES_VOLUME enable = (point and region_type == 'point' or plane and 'plane' in region_type or volume and region_type == 'box') item = get_combobox_item(cb, monitor_type) set_item_enabled(item, enable) elif len(selections) == 0: for monitor_type in MONITOR_TYPES: item = get_combobox_item(cb, monitor_type) set_item_enabled(item, True) self.handle_type(self.ui.combobox.currentIndex())
def popup(self, label_text): # Widget is shared by ICs/BCs/PSs/ISs/VTK output # NB, we distinguish the caller based on the label text ui = self.ui ui.label_top.setText(label_text) buttonbox = self.ui.buttonbox buttonbox.button(buttonbox.Ok).setEnabled(False) self.boundary = boundary = ('boundary condition' in label_text) self.surface = surface = ('internal surface' in label_text) self.vtk = vtk = ('VTK output' in label_text) self.monitor = monitor = ('monitor' in label_text) tw = ui.table if (monitor or vtk ): # Output filenames will collide if we allow multiple regions tw.setSelectionMode(QAbstractItemView.SingleSelection) self.setWindowTitle("Select region") else: tw.setSelectionMode(QAbstractItemView.MultiSelection) self.setWindowTitle("Select regions") # setup the combobox appropriately cb = ui.combobox label = ui.label_type gui = self.parent show_type = False if boundary or surface: label.setText('Boundary type' if boundary else 'Surface type') cb.clear() cb.addItems(BC_NAMES if boundary else IS_NAMES) if boundary: for i in range(len(cb)): gui.add_tooltip(get_combobox_item(cb, i), key='bc_type', value=BC_TYPES[i]) gui.add_tooltip( get_combobox_item(cb, BC_TYPES.index('CYCLIC')), key=None, description= 'Cyclic boundary condition in specified direction') if surface: for i in range(len(cb)): gui.add_tooltip(get_combobox_item(cb, i), key='is_type', value=IS_TYPES[i]) index = BC_TYPES.index( DEFAULT_BC_TYPE) if boundary else IS_TYPES.index( DEFAULT_IS_TYPE) cb.setCurrentIndex(index) self.handle_type(index) show_type = True elif vtk: label.setText('Output type') cb.clear() cb.addItems(['Cell data', 'Particle data']) # slight hack to set tooltips get_combobox_item(cb, 0).setToolTip('Cell data (VTU file)') get_combobox_item(cb, 1).setToolTip('Particle data (VTP file)') show_type = True elif monitor: label.setText('Monitor type') cb.clear() cb.addItems(MONITOR_TYPE_NAMES) for i in range(len(cb)): gui.add_tooltip(get_combobox_item(cb, i), key='monitor_type', value=i) ui.frame_object_type.show() show_type = True if show_type: ui.frame_object_type.show() set_combobox_tooltip(cb) nrows = 2 else: ui.frame_object_type.hide() nrows = 1 self.show() self.raise_() self.activateWindow() # Table fixup resize = tw.horizontalHeader().setSectionResizeMode ncols = tw.columnCount() stretch_column = 0 for col_index in range(0, ncols): if col_index == stretch_column: resize(col_index, QHeaderView.Stretch) else: resize(col_index, QHeaderView.ResizeToContents) table_height = 4 + tw.horizontalHeader().height() + (tw.rowHeight(0) * tw.rowCount()) min_table_height = 150 tw.setMinimumHeight(min(min_table_height, table_height)) tw.setMaximumHeight(table_height) width = (tw.horizontalHeader().width() + tw.verticalScrollBar().isVisible() * (4 + tw.verticalScrollBar().width())) self.setMaximumWidth(max(width, ui.label_top.size().width())) #self.setMinimumWidth(width) # Height of all stuff other than the main table - try to prevent scrollbars margins = 10 line_spacing = 6 stuff_height = (nrows + 1) * self.combobox.size().height( ) + margins + (nrows + 2) * line_spacing height = (table_height + stuff_height) self.setMinimumHeight(min(min_table_height + stuff_height, height)) self.setMaximumHeight(height)
def numerics_setup_discretization_tab(self): """Discretization (tab)""" ui = self.ui.numerics #Select temporal discretization scheme # Selection always available # Available selections: # Implicit Euler [DEFAULT] # Sets keyword CN_ON to .FALSE. # Crank-Nicolson # Sets keyword CN_ON to .TRUE. cb = ui.combobox_cn_on idx = 1 if self.project.get_value('cn_on') else 0 cb.setCurrentIndex(idx) cb.setToolTip(get_combobox_item(cb, idx).toolTip()) tw = ui.tablewidget_discretization self.fixup_numerics_table(tw) # Available selections # First-order upwind [DEFAULT for all equations] # Sets keyword DISCRETIZE(#) to 0 # First-order upwind (dwf) # Sets keyword DISCRETIZE(#) to 1 # Superbee # Sets keyword DISCRETIZE(#) to 2 # SMART # Sets keyword DISCRETIZE(#) to 3 # ULTRA-QUICK # Sets keyword DISCRETIZE(#) to 4 # QUICKEST # Sets keyword DISCRETIZE(#) to 5 # MUSCL # Sets keyword DISCRETIZE(#) to 6 # van Leer # Sets keyword DISCRETIZE(#) to 7 # minmod # Sets keyword DISCRETIZE(#) to 8 # Central # Sets keyword DISCRETIZE(#) to 9 # see "make_combobox" # Column 3: Specify under relaxation factors # Specification always available # Sets keyword UR_FAC for each equation # # DEFAULTS are equation type specific defaults = [ None, # 0 - unused 0.8, # 1 - gas pressure: 0.8 0.5, # 2 - volume fraction: 0.5 0.5, # 3 - u-momentum: 0.5 0.5, # 4 - v-momentum: 0.5 0.5, # 5 - w-momentum: 0.5 1.0, # 6 - energy: 1.0 1.0, # 7 - species: 1.0 0.5, # 8 - granular energy: 0.5 0.8, # 9 - user-scalar/k-epsilon: 0.8 1.0 ] # 10 - DES diffusion: 1.0 for i in range(1, 1 + DIM_EQS): row = i - 1 key = 'discretize' default = 0 cb = tw.cellWidget(row, COL_SCHEME) val = self.project.get_value(key, args=[i]) if val is None: val = default #self.update_keyword(key, val, args=[i]) #? cb.setCurrentIndex(val) key = 'ur_fac' le = tw.cellWidget(row, COL_RELAX) val = self.project.get_value(key, args=[i]) if val is None: val = defaults[i] #self.update_keyword(key, val, args=[i]) #? le.updateValue( key, val) # initialize lineedit, since it's not registered #Enable deferred correction # Selection only available if minval(discretize) > 0 # Sets keyword DEF_COR # DEFAULT value .FALSE. key = 'discretize' enabled = min( self.project.get_value(key, args=[i], default=0) for i in range(1, 1 + DIM_EQS)) > 0 key = 'def_cor' cb = ui.checkbox_keyword_def_cor cb.setEnabled(enabled) self.add_tooltip(cb, key) if not enabled: cb.setToolTip(cb.toolTip() + " Disabled for first-order upwinding.") cb.setChecked(False) self.unset_keyword(key) #Enable chi-scheme correction # Selection only available if the species equation spatial discretization is SMART or #MUSCL (DISCRETIZE(7) = 3 or 6) # Sets keyword CHI_SCHEME # DEFAULT value .FALSE. enabled = self.project.get_value('discretize', args=[7]) in (3, 6) key = 'chi_scheme' cb = ui.checkbox_keyword_chi_scheme cb.setEnabled(enabled) if not enabled: cb.setChecked(False) self.unset_keyword(key)
def __init__(self, app, parent=None, phases='GLCS'): super(SpeciesPopup, self).__init__(parent) self.app = app self.phases = phases self.include_comments = False self.default_phase = phases[0] if phases else '' self.density_enabled = True datadir = os.path.abspath(os.path.dirname(__file__)) self.load_burcat(os.path.join(datadir, 'burcat.pickle')) ui = self.ui = get_ui('species_popup.ui', self) # key=species, val=data tuple. can add phase to key if needed self.defined_species = OrderedDict() self.extra_aliases = set() # To support enforcing uniqueness self.mfix_keywords = set(k.lower() for k in self.parent().keyword_doc.keys()) self.mfix_fortran_globals = set() # TODO: implement this # uniqueness of aliases across all phases self.search_results = [] self.user_species_names = set() # Set up UI ui.lineedit_search.textChanged.connect(self.do_search) ui.pushbutton_import.clicked.connect(self.do_import) ui.pushbutton_import.setEnabled(False) ui.tablewidget_search.itemSelectionChanged.connect( self.handle_search_selection) ui.tablewidget_defined_species.itemSelectionChanged.connect( self.handle_defined_species_selection) ui.pushbutton_new.clicked.connect(self.handle_new) ui.pushbutton_copy.clicked.connect(self.handle_copy) ui.checkbox_include_comments.clicked.connect( self.handle_include_comments) for phase in 'GLSC': button = getattr(self.ui, 'pushbutton_%s' % phase) button.clicked.connect(self.handle_phase) cb = ui.combobox_phase cb.currentIndexChanged.connect(self.handle_combobox_phase) for i, t in enumerate(phase_names): get_combobox_item(cb, i).setToolTip(t) #http://stackoverflow.com/questions/15845487/how-do-i-prevent-the-enter-key-from-closing-my-qdialog-qt-4-8-1 # Do not use buttonbox. https://mfix.netl.doe.gov/gitlab/develop/mfix/issues/101 buttons = (ui.pushbutton_ok, ui.pushbutton_cancel) buttons[0].clicked.connect(lambda: (self.save.emit(), self.close())) buttons[1].clicked.connect(lambda: (self.cancel.emit(), self.close())) class AliasValidator(QValidator): # Make sure aliases are unique def __init__(self, parent=None): super(AliasValidator, self).__init__() self.parent = parent def validate(self, text, pos): if text == "": self.parent.set_ok_button(False) return (QValidator.Intermediate, text, pos) dig_start = text[0].isdigit() und_start = text[0] == '_' not_alphanum_und = not all(c.isalnum() or c == '_' for c in text) if dig_start or und_start or not_alphanum_und: return (QValidator.Invalid, text, pos) current_species = self.parent.current_species if current_species not in self.parent.defined_species: # Why would this happen? self.parent.set_ok_button(False) return (QValidator.Invalid, text, pos) current_alias = self.parent.defined_species[ current_species].get('alias') if current_alias is None: self.parent.set_ok_button(False) return (QValidator.Invalid, text, pos) for v in self.parent.defined_species.values(): v_alias = v.get('alias', '') if v_alias.lower() == current_alias.lower( ): # Skip selected item continue if v_alias.lower() == text.lower(): self.parent.set_ok_button(False, 'Alias must be unique') return (QValidator.Intermediate, text, pos) tlower = text.lower() if tlower in self.parent.extra_aliases: self.parent.set_ok_button(False, 'Alias must be unique') return (QValidator.Intermediate, text, pos) if tlower in self.parent.mfix_keywords: self.parent.set_ok_button(False, '%s is an MFiX keyword' % text) return (QValidator.Intermediate, text, pos) self.parent.set_ok_button(True) return (QValidator.Acceptable, text, pos) lineedit = ui.lineedit_alias lineedit.setValidator(AliasValidator(parent=self)) lineedit.editingFinished.connect(self.handle_alias) for line_edit in (ui.lineedit_mol_weight, ui.lineedit_h_f, ui.lineedit_density): line_edit.setValidator(QDoubleValidator()) self.species_panel_items = [ ui.label_species, ui.lineedit_alias, ui.lineedit_mol_weight, ui.lineedit_h_f, ui.lineedit_density, ui.tablewidget_params ] hv = QHeaderView for tw in (self.tablewidget_search, self.tablewidget_defined_species): resize_column(tw, 0, hv.Stretch) resize_column(tw, 1, hv.ResizeToContents) tw = self.tablewidget_params for i in (0, 1): resize_column(tw, i, hv.Stretch) self.set_ok_button(False) # nothing to accept self.clear_species_panel()
def setup_pic_tab(self): # Note - we are doing this setup on first show of this tab, rather # than at init or project load time ui = self.ui.solids #Specify void fraction at close pack (required) # Sets keyword EP_STAR [0.42] #Define parcel CFL number # Sets keyword CFL_PIC # DEFAULT 0.1 for (key, default) in [('ep_star', 0.42), ('cfl_pic', 0.1)]: val = self.project.get_value(key) if val is None: self.update_keyword(key, default) #Select solid stress model # Selection always available # Available selection # Snider, 2001 [DEFAULT] # Selection always available # Sets keyword MPPIC_SOLID_STRESS_SNIDER=.T. self.update_keyword('mppic_solid_stress_snider', True) # TODO FIXME does this ever get cleared? #Option to enable implicit treatment of drag force # Sets keyword: MPPIC_PDRAG_IMPLICIT # Disabled [DEFAULT] pass #Define particle-particle momentum retention # Sets keyword MPPIC_COEFF_EN1 # DEFAULT 0.4 #Define wall normal momentum retention # Sets keyword MPPIC_COEFF_EN_WALL # DEFAULT 0.3 #Define wall tangential momentum retention # Sets keyword MPPIC_COEFF_ET_WALL # DEFAULT 0.99 for (key, default) in [('mppic_coeff_en1', 0.4), ('mppic_coeff_en_wall', 0.3), ('mppic_coeff_et_wall', 0.99)]: val = self.project.get_value(key) if val is None: self.update_keyword(key, default) #Select gas-solids coupling scheme: # Selection unavailable if fluid model is disabled # Available selections: # One-way Coupled # Selection always available # Sets keyword DES_ONEWAY_COUPLED true # Fully Coupled # Selection always available # Sets keyword DES_ONEWAY_COUPLED false enabled = not self.fluid_solver_disabled for item in (ui.label_coupling_method_2, ui.combobox_coupling_method_2): item.setEnabled(enabled) des_oneway_coupled = self.project.get_value('des_oneway_coupled', default=False) if des_oneway_coupled not in (True, False): self.warn("Invalid des_oneway_coupled %s" % des_oneway_coupled) des_oneway_coupled = False self.update_keyword('des_oneway_coupled', des_oneway_coupled) ui.combobox_coupling_method_2.setCurrentIndex( 0 if des_oneway_coupled else 1) #Select interpolation framework: # Selection always available # Available selections: # field-to-particle and particle-to-field [DEFAULT] # Sets keyword DES_INTERP_ON to true # Sets keyword DES_INTERP_MEAN_FIELDS to true # field-to-particle only # Sets keyword DES_INTERP_ON to true # Sets keyword DES_INTERP_MEAN_FIELDS to false # particle-to-field only # Sets keyword DES_INTERP_ON to false # Sets keyword DES_INTERP_MEAN_FIELDS to true # no-interpolation # Sets keyword DES_INTERP_ON to false # Sets keyword DES_INTERP_MEAN_FIELDS to false des_interp_on = self.project.get_value('des_interp_on', default=True) if des_interp_on not in (True, False): self.warn("Invalid des_interp_on %s" % des_interp_on) des_interp_on = True self.update_keyword('des_interp_on', des_interp_on) des_interp_mean_fields = self.project.get_value( 'des_interp_mean_fields', default=True) if des_interp_mean_fields not in (True, False): self.warn("Invalid des_interp_mean_fields %s" % des_interp_mean_fields) des_interp_mean_fields = True self.update_keyword('des_interp_mean_fields', des_interp_mean_fields) index = 2 * (1 - des_interp_on) + (1 - des_interp_mean_fields) ui.combobox_des_interp_2.setCurrentIndex(index) #Select interpolation scheme: # Selection available except when no-interpolation framework is selected # Available selections: # None [locked default for no-interpolation framework] # Selection not available # Sets keyword DES_INTERP_SCHEME='NONE' # Todo, update SRS # Garg 2012 # Selection not available with explicit coupling enabled # Sets keyword DES_INTERP_SCHEME='GARG_2012' # Square DPVM # Selection always available # Requires an interpolation width, DES_INTERP_WIDTH # Sets keyword DES_INTERP_SCHEME='SQUARE_DPVM' # cb = ui.combobox_des_interp_scheme_2 label = ui.label_des_interp_scheme_2 des_interp_scheme = self.project.get_value('des_interp_scheme') des_explicitly_coupled = self.project.get_value( 'des_explicitly_coupled') interp_enabled = des_interp_on or des_interp_mean_fields # not no-interp for item in (cb, label): item.setEnabled(interp_enabled) if not interp_enabled: cb.setCurrentIndex(NONE) des_interp_scheme = 'NONE' else: if des_interp_scheme not in des_interp_schemes: self.warning("invalid des_interp_scheme %s" % des_interp_scheme) des_interp_scheme = 'SQUARE_DPVM' idx = des_interp_schemes.index(des_interp_scheme) cb.setCurrentIndex(idx) # per-item enable flags enabled = (not interp_enabled, not des_explicitly_coupled, True) for (i, e) in enumerate(enabled): set_item_enabled(get_combobox_item(cb, i), e) # Make sure we don't leave the combobox on an invalid item! if not enabled[cb.currentIndex()]: idx = enabled.index(True) # 2 is always True so this is safe cb.setCurrentIndex(idx) des_interp_scheme = des_interp_schemes[idx] # Value of des_interp_scheme may have changed self.update_keyword('des_interp_scheme', des_interp_scheme) #Define interpolation width (DPVM only) (required) # Specification only available with SQUARE_DPVM interpolation scheme # Sets keyword DES_INTERP_WIDTH # TODO default? key = 'des_interp_width' enabled = interp_enabled and (des_interp_scheme == 'SQUARE_DPVM') #? for item in (ui.label_des_interp_width_2, ui.lineedit_keyword_des_interp_width_2, ui.label_des_interp_width_2_units): item.setEnabled(enabled) if des_interp_scheme != 'SQUARE_DPVM': self.unset_keyword(key) else: self.update_keyword('des_interp_width', ui.lineedit_keyword_des_interp_width_2.value) #Define solids stress model parameter: pressure constant # Sets keyword PSFAC_FRIC_PIC # DEFAULT 10.0 #Define solids stress model parameter: volume fraction exponent # Sets keyword FRIC_EXP_PIC # DEFAULT 3.0 #Define solids stress model parameter: non-singularity factor # Sets keyword FRIC_NON_SING_FAC # DEFAULT 1.0E-8 for (key, default) in [('psfac_fric_pic', 10.0), ('fric_exp_pic', 3.0), ('fric_non_sing_fac', 1.0e-8)]: val = self.project.get_value(key) if val is None: self.update_keyword(key, default)
def set_cn_on(self, val): ui = self.ui.numerics cb = ui.combobox_cn_on key = 'cn_on' self.update_keyword(key, bool(val)) cb.setToolTip(get_combobox_item(cb, int(val)).toolTip())
def setup_dem_tab(self): # Ensures all constraints (items enabled/disabled) are set # called by each 'set_' function, so don't call those here ui = self.ui.solids # Inline comments from MFIX-UI_SRS as of 2016-07-01 # Please update as needed! #MFIX-UI_SRS #Enable automatic particle generation # Enabled sets keyword GENER_PART_CONFIG to true # Disabled enables the user to specify number of entries in particle input file # Default value is 0 default = 0 # Sets keyword PARTICLES gener_part_config = self.project.get_value('gener_part_config') particles = self.project.get_value('particles') if gener_part_config: if particles: # Should not both be set self.warning("gener_part_config set, particles=%s" % particles) particles = default else: if particles is None: # set to 0 if not set particles = default elif particles < 0: self.warning("Invalid particles %s" % particles) particles = default self.update_keyword('particles', particles) enabled = not gener_part_config for item in (ui.label_particles, ui.lineedit_keyword_particles): item.setEnabled(enabled) #Select numerical integration method # Selection always available # Available selections #Euler [DEFAULT] # Selection always available # Sets keyword DES_INTG_METHOD to 'EULER' #Adams-Bashforth # Selection always available # Sets keyword DES_INTG_METHOD to 'ADAMS_BASHFORTH'1 des_intg_method = self.project.get_value('des_intg_method', default='EULER') if des_intg_method not in des_intg_methods: self.warn("Invalid des_intg_method %s" % des_intg_method) des_intg_method = 'EULER' ui.combobox_des_intg_method.setCurrentIndex( des_intg_methods.index(des_intg_method)) #Selection collision model # Selection always available # Available selections #Linear Spring-Dashpot [DEFAULT] # Selection always available # Sets keyword DES_COLL_MODEL to 'LSD' #Hertzian # Selection always available # Sets keyword DES_COLL_MODEL to 'HERTZIAN' des_coll_model = self.project.get_value('des_coll_model', default='LSD') if des_coll_model not in des_coll_models: self.warn("Invalid des_coll_model %s" % des_coll_model) des_coll_model = 'LSD' ui.combobox_des_coll_model.setCurrentIndex( des_coll_models.index(des_coll_model)) #Select gas-solids coupling scheme: # Selection unavailable if fluid model is disabled # Available selections: # One-way Coupled # Selection always available # Sets keyword DES_ONEWAY_COUPLED true # Fully Coupled # Selection always available # Sets keyword DES_ONEWAY_COUPLED false enabled = not self.fluid_solver_disabled for item in (ui.label_coupling_method, ui.combobox_coupling_method): item.setEnabled(enabled) des_oneway_coupled = self.project.get_value('des_oneway_coupled', default=False) if des_oneway_coupled not in (True, False): self.warn("Invalid des_oneway_coupled %s" % des_oneway_coupled) des_oneway_coupled = False self.update_keyword('des_oneway_coupled', des_oneway_coupled) ui.combobox_coupling_method.setCurrentIndex( 0 if des_oneway_coupled else 1) #Optional to enable explicitly coupled simulation # Unavailable for GARG_2012 interpolation des_interp_scheme = self.project.get_value('des_interp_scheme') enabled = (des_interp_scheme != 'GARG_2012') ui.checkbox_keyword_des_explicitly_coupled.setEnabled(enabled) #Select interpolation framework: # Selection always available # Available selections: # Field-to-Particle and Particle-to-Field [DEFAULT] # Sets keyword DES_INTERP_ON to true # Sets keyword DES_INTERP_MEAN_FIELDS to true # Field-to-Particle only # Sets keyword DES_INTERP_ON to true # Sets keyword DES_INTERP_MEAN_FIELDS to false # Particle-to-Field only # Sets keyword DES_INTERP_ON to false # Sets keyword DES_INTERP_MEAN_FIELDS to true # No Interpolation # Sets keyword DES_INTERP_ON to false # Sets keyword DES_INTERP_MEAN_FIELDS to false # # issues/116 must also set DES_INTERP_SCHEME to None when no-interpolation des_interp_on = self.project.get_value('des_interp_on', default=True) if des_interp_on not in (True, False): self.warn("Invalid des_interp_on %s" % des_interp_on) des_interp_on = True self.update_keyword('des_interp_on', des_interp_on) des_interp_mean_fields = self.project.get_value( 'des_interp_mean_fields', default=True) if des_interp_mean_fields not in (True, False): self.warn("Invalid des_interp_mean_fields %s" % des_interp_mean_fields) des_interp_mean_fields = True self.update_keyword('des_interp_mean_fields', des_interp_mean_fields) index = 2 * (1 - des_interp_on) + (1 - des_interp_mean_fields) ui.combobox_des_interp.setCurrentIndex(index) #Select interpolation scheme: # Selection available except when no-interpolation framework is selected # Available selections: # None [locked default for no-interpolation framework] # Selection always available # Sets keyword DES_INTERP_SCHEME='NONE' # Garg 2012 # Selection not available with explicit coupling enabled # Sets keyword DES_INTERP_SCHEME='GARG_2012' # Square DPVM # Selection always available # Requires an interpolation width, DES_INTERP_WIDTH # Sets keyword DES_INTERP_SCHEME='SQUARE_DPVM' # cb = ui.combobox_des_interp_scheme label = ui.label_des_interp_scheme des_interp_scheme = self.project.get_value('des_interp_scheme') des_explicitly_coupled = self.project.get_value( 'des_explicitly_coupled') interp_enabled = des_interp_on or des_interp_mean_fields # not no-interp for item in (cb, label): item.setEnabled(interp_enabled) if not interp_enabled: cb.setCurrentIndex(NONE) des_interp_scheme = 'NONE' else: if des_interp_scheme not in des_interp_schemes: des_interp_scheme = 'NONE' cb.setCurrentIndex(des_interp_schemes.index(des_interp_scheme)) # # per-item enable flags enabled = (True, True, not des_explicitly_coupled) for (i, e) in enumerate(enabled): set_item_enabled(get_combobox_item(cb, i), e) # Make sure we don't leave the combobox on an invalid item! if not enabled[cb.currentIndex()]: idx = enabled.index(True) # 2 is always True so this is safe cb.setCurrentIndex(idx) des_interp_scheme = des_interp_schemes[idx] # Value of des_interp_scheme may have changed self.update_keyword('des_interp_scheme', des_interp_scheme) #Define interpolation width (DPVM only) (required) # Specification only available with SQUARE_DPVM interpolation scheme # Sets keyword DES_INTERP_WIDTH # TODO default? key = 'des_interp_width' enabled = interp_enabled and (des_interp_scheme == 'SQUARE_DPVM') #? for item in (ui.label_des_interp_width, ui.lineedit_keyword_des_interp_width, ui.label_des_interp_width_units): item.setEnabled(enabled) if des_interp_scheme != 'SQUARE_DPVM': self.unset_keyword(key) else: self.update_keyword(key, ui.lineedit_keyword_des_interp_width.value) #Option to enable diffusion of particle data # Selection unavailable with GARG_2012 interpolation scheme # No keyword is set by this option # Enables the user to specify a diffusion width # Sets keyword DES_DIFFUSE_WIDTH key = 'des_diffuse_width' enabled = (des_interp_scheme != 'GARG_2012') ui.checkbox_enable_des_diffuse_width.setEnabled(enabled) if not enabled: ui.checkbox_enable_des_diffuse_width.setChecked(False) self.unset_keyword(key) ui.lineedit_keyword_des_diffuse_width.clear() # ??? FIXME enabled = ui.checkbox_enable_des_diffuse_width.isChecked() for item in (ui.label_des_diffuse_width, ui.lineedit_keyword_des_diffuse_width, ui.label_des_diffuse_width_units): item.setEnabled(enabled) if enabled: self.update_keyword( key, ui.lineedit_keyword_des_diffuse_width.value) #Specify friction coefficient # Specification always required # Sets keyword MEW (MEW_W) pass #Specify normal spring constant # Only available for LSD collision model # Sets keyword KN (KN_W) #Specify tangential spring constant factor # Only available for LSD collision model # Sets keyword KT_FAC (KT_W_FAC) # Default values of 2.0/7.0 #Specify tangential damping coefficient factor # Only available for LSD collision model # Sets keyword DES_ETAT_FAC (DES_ETAT_W_FAC) # Default values of 0.5 enabled = (des_coll_model == 'LSD') for item in (ui.label_kn, ui.lineedit_keyword_kn, ui.lineedit_keyword_kn_w, ui.label_kn_units, ui.label_kt_fac, ui.lineedit_keyword_kt_fac, ui.lineedit_keyword_kt_w_fac, ui.label_des_etat_fac, ui.lineedit_keyword_des_etat_fac, ui.lineedit_keyword_des_etat_w_fac): item.setEnabled(enabled) if enabled: # TODO set these defaults at load-time, not when this tab is shown for (key, default) in [('kt_fac', Equation('2/7')), ('kt_w_fac', Equation('2/7')), ('des_etat_fac', 0.5), ('des_etat_w_fac', 0.5)]: if self.project.get_value(key) is None: self.update_keyword(key, default) # Unset keywords if not enabled? #Specify Young's modulus # Only available for Hertzian collision model # Sets keyword E_YOUNG (EW_YOUNG) layout = ui.gridlayout_dem_parameters enabled = (des_coll_model == 'HERTZIAN') for item in (ui.label_e_young, ui.lineedit_keyword_ew_young, ui.label_e_young_units, ui.label_v_poisson, ui.lineedit_keyword_vw_poisson): item.setEnabled(enabled) key = 'e_young' solids_names = list(self.solids.keys()) if self.solids_dem_saved_solids_names != solids_names: # We put these back after inserting rows for item in (ui.label_v_poisson, ui.lineedit_keyword_vw_poisson): item.hide() layout.removeWidget(item) # Delete all the old ones... for idx in range(layout.count() - 1, -1, -1): item = layout.itemAt(idx) w = item.widget() if not w: continue name = w.objectName() if '_args_' in name: w.hide() if isinstance(w, LineEdit): self.project.unregister_widget(w) layout.removeWidget(w) w.setParent(None) w.deleteLater() # ...and make new ones idx = layout.indexOf(ui.lineedit_keyword_ew_young) columns = 4 row = 1 + int(idx / columns) for (p, name) in enumerate(self.solids.keys(), 1): row += 1 label = QLabel(' ' + name) label.setObjectName('label_%s_args_%s' % (key, p)) # FIXME use dynamic_widgets instead of setattr setattr(ui, label.objectName(), label) label.args = [p] self.add_tooltip(label, key) layout.addWidget(label, row, 0, 1, 1) label.setEnabled(enabled) le = LineEdit() le.setMaximumWidth(150) # matches ui file le.key = key le.args = [p] le.dtype = float le.setValInfo(min=0.0) le.setObjectName('lineedit_keyword_%s_args_%s' % (key, p)) setattr(ui, le.objectName(), le) self.add_tooltip(le, key) layout.addWidget(le, row, 1, 1, 1) le.setEnabled(enabled) val = self.project.get_value(key, args=[p]) if val is not None: le.updateValue(key, val) self.project.register_widget(le, keys=[key], args=[p]) label = QLabel('Pa') label.setObjectName('label_%s_units_args_%s' % (key, p)) layout.addWidget(label, row, 3, 1, 1) label.setEnabled(enabled) #Specify Poisson ratio: # Only available for Hertzian collision model # Sets keyword V_POISSON (VW_POISSON) row += 1 layout.addWidget(ui.label_v_poisson, row, 0, 1, 1) layout.addWidget(ui.lineedit_keyword_vw_poisson, row, 2, 1, 1) for item in (ui.label_v_poisson, ui.lineedit_keyword_vw_poisson): item.show() item.setEnabled(enabled) row += 1 key = 'v_poisson' for (p, name) in enumerate(self.solids.keys(), 1): row += 1 label = QLabel(' ' + name) label.setObjectName('label_%s_args_%s' % (key, p)) setattr(ui, label.objectName(), label) label.args = [p] self.add_tooltip(label, key) layout.addWidget(label, row, 0, 1, 1) label.setEnabled(enabled) le = LineEdit() le.setMaximumWidth(150) #? le.key = key le.args = [p] le.dtype = float le.setValInfo(min=0.0) le.setObjectName('lineedit_keyword_%s_args_%s' % (key, p)) setattr(ui, le.objectName(), le) self.add_tooltip(le, key) layout.addWidget(le, row, 1, 1, 1) le.setEnabled(enabled) val = self.project.get_value(key, args=[p]) if val is not None: le.updateValue(key, val) self.project.register_widget(le, keys=[key], args=[p]) # Use dynamic_widgets here instead of setattr/getattr for key in 'e_young', 'v_poisson': for p in range(1, 1 + len(self.solids.keys())): for pat in 'label_%s_args_%s', 'lineedit_keyword_%s_args_%s': w = getattr(ui, pat % (key, p), None) if w: w.setEnabled(enabled) #Specify normal restitution coefficient # Specification always required # Sets keyword DES_EN_INPUT (DES_EN_WALL_INPUT) # Input given as an upper triangular matrix mmax = self.project.get_value('mmax', default=len(self.solids)) tw = ui.tablewidget_des_en_input def make_item(str): item = QTableWidgetItem(str) set_item_noedit(item) set_item_enabled(item, False) return item if (self.solids_dem_saved_solids_names != solids_names or tw.rowCount() != mmax + 1 or tw.columnCount() != mmax): # Clear out old lineedit widgets for row in range(tw.rowCount()): for col in range(tw.columnCount()): w = tw.cellWidget(row, col) if w: self.project.unregister_widget(w) w.deleteLater() tw.clearContents() # Make a new batch tw.setRowCount(mmax + 1) # extra row for "Wall" tw.setColumnCount(mmax) tw.setHorizontalHeaderLabels(solids_names) tw.setVerticalHeaderLabels(solids_names + ['Wall']) arg = 1 # One-based key = 'des_en_input' for row in range(mmax): for col in range(mmax): if col < row: tw.setItem(row, col, make_item('--')) else: le = LineEdit() le.setMaximumWidth(150) le.key = key le.args = [arg] le.setdtype('dp') self.add_tooltip(le, key) tw.setCellWidget(row, col, le) val = self.project.get_value(key, args=[arg]) if val is not None: le.updateValue(key, val) self.project.register_widget(le, keys=[key], args=[arg]) arg += 1 arg = 1 key = 'des_en_wall_input' row = mmax for col in range(mmax): le = LineEdit() le.setMaximumWidth(150) le.key = key le.args = [arg] le.setdtype('dp') self.add_tooltip(le, key) tw.setCellWidget(row, col, le) val = self.project.get_value(key, args=[arg]) if val is not None: le.updateValue(key, val) self.project.register_widget(le, keys=[key], args=[arg]) arg += 1 self.fixup_solids_table(tw, stretch_column=mmax - 1) # This makes the table look a little nicer tw.setShowGrid(False) # Move column headers to left so they line up with lineedits for i in range(tw.columnCount()): item = tw.horizontalHeaderItem(i) if item: item.setTextAlignment(Qt.AlignLeft) #Specify tangential restitution coefficient # Specification available for Hertzian collision model # Sets keyword DES_ET_INPUT (DES_ET_WALL_INPUT) # Input given as an upper triangular matrix enabled = (des_coll_model == 'HERTZIAN') ui.label_des_et_input.setEnabled(enabled) tw = ui.tablewidget_des_et_input # note - this is too much of a duplicate of des_en_input above if not enabled: # Clear out old lineedit widgets for row in range(tw.rowCount()): for col in range(tw.columnCount()): w = tw.cellWidget(row, col) if w: self.project.unregister_widget(w) w.deleteLater() tw.clearContents() tw.setRowCount(0) tw.setColumnCount(0) if enabled: if (self.solids_dem_saved_solids_names != solids_names or tw.rowCount() != mmax + 1 or tw.columnCount() != mmax): # Clear out old lineedit widgets for row in range(tw.rowCount()): for col in range(tw.columnCount()): w = tw.cellWidget(row, col) if w: self.project.unregister_widget(w) w.deleteLater() tw.clearContents() # Make a new batch tw.setRowCount(mmax + 1) # extra row for "Wall" tw.setColumnCount(mmax) tw.setHorizontalHeaderLabels(solids_names) tw.setVerticalHeaderLabels(solids_names + ['Wall']) arg = 1 key = 'des_et_input' for row in range(mmax): for col in range(mmax): if col < row: tw.setItem(row, col, make_item('--')) else: le = LineEdit() le.setMaximumWidth(150) le.key = key le.args = [arg] le.setdtype('dp') self.add_tooltip(le, key) tw.setCellWidget(row, col, le) val = self.project.get_value(key, args=[arg]) if val is not None: le.updateValue(key, val) self.project.register_widget(le, keys=[key], args=[arg]) arg += 1 key = 'des_et_wall_input' row = mmax arg = 1 for col in range(mmax): le = LineEdit() le.setMaximumWidth(150) le.key = key le.args = [arg] le.setdtype('dp') tw.setCellWidget(row, col, le) val = self.project.get_value(key, args=[arg]) if val is not None: le.updateValue(key, val) self.project.register_widget(le, keys=[key], args=[arg]) arg += 1 self.fixup_solids_table(tw, stretch_column=mmax - 1) # This makes the table look a little nicer tw.setShowGrid(False) # Move column headers to left so they line up with lineedits for i in range(tw.columnCount()): item = tw.horizontalHeaderItem(i) if item: item.setTextAlignment(Qt.AlignLeft) #Select cohesion model # Selection always available # Available selections #None [DEFAULT] #Selection always available #Sets keyword USE_COHESION to false #Sets keyword VAN_DER_WAALS to false #Van der Waals #Selection always available #Sets keyword USE_COHESION to true #Sets keyword VAN_DER_WAALS to true use_cohesion = self.project.get_value('use_cohesion') van_der_waals = self.project.get_value('van_der_waals') cb = ui.combobox_cohesion_model if use_cohesion: if not van_der_waals: self.warn('inconsistent value for keyword van_der_waals') self.unset_keyword('van_der_waals') cb.setCurrentIndex(1) else: if van_der_waals: self.warn('inconsistent value for keyword van_der_waals') self.update_keyword('van_der_waals', True) cb.setCurrentIndex(0) #Specify Hamaker constant # Specification only available for Van der Waals cohesion model # Sets keyword HAMAKER_CONSTANT (WALL_HAMAKER_CONSTANT) #Specify outer cutoff # Specification only available for Van der Waals cohesion model # Sets keyword VDW_OUTER_CUTOFF (WALL_OUTER_CUTOFF) #Specify inner cutoff # Specification only available for Van der Waals cohesion model # Sets keyword VDW_INNER_CUTOFF (WALL_INNER_CUTOFF) #Specify asperities # Specification only available for Van der Waals cohesion model # Sets keyword ASPERITIES enabled = bool(van_der_waals) ui.groupbox_cohesion_parameters.setEnabled(enabled) # (settings handled by keyword widgets. TODO: # decide if we want to unset keywords if not enabled #List the following options under an 'Advanced' section header. #Select Neighbor Search Method # Selection always available # Available selection #Grid-based [DEFAULT] #Selection always available #Sets keyword DES_NEIGHBOR_SEARCH 4 #N-Square #Selection always available #Sets keyword DES_NEIGHBOR_SEARCH 1 des_neighbor_search = self.project.get_value('des_neighbor_search', default=4) if des_neighbor_search not in (1, 4): self.warn("Invalid des_neighbor_search %s" % des_neighbor_search) des_neighbor_search = 4 self.update_keyword('des_neighbor_search', des_neighbor_search) cb = ui.combobox_des_neighbor_search cb.setCurrentIndex(0 if des_neighbor_search == 4 else 1) #Specify maximum steps between neighbor search #Specification always available # Sets keyword NEIGHBOR_SEARCH_N #Specify factor defining particle neighborhood #Specification always available # Sets keyword FACTOR_RLM #Specify neighborhood search radius ratio #Specification always available #Sets keyword NEIGHBOR_SEARCH_RAD_RATIO #Specify search grid partitions (optional) #Specification always available #Sets keyword DESGRIDSEARCH_IMAX #Sets keyword DESGRIDSEARCH_JMAX #Sets keyword DESGRIDSEARCH_KMAX pass # handled by keyword widgets #Enable user scalar tracking #Selection always available #Does not directly set any keywords #Enables specification of number of user scalars # Sets keyword DES_USR_VAR_SIZE des_usr_var_size = self.project.get_value('des_usr_var_size', default=None) enabled = (des_usr_var_size is not None) cb = ui.checkbox_enable_des_usr_var_size cb.setChecked(enabled) ui.lineedit_keyword_des_usr_var_size.setEnabled(enabled) #Define minimum distance for contact conduction (optional) #Unavailable if not solving energy equations #Define fluid lens proportion constant (optional) # Unavailable if not solving energy equations enabled = self.project.get_value('energy_eq', default=True) for item in (ui.label_des_min_cond_dist, ui.lineedit_keyword_des_min_cond_dist, ui.label_des_min_cond_dist_units, ui.label_flpc, ui.lineedit_keyword_flpc): item.setEnabled(enabled) # Remember the names of solids phases, to track changes self.solids_dem_saved_solids_names = solids_names
def handle_iss_region_selection(self): ui = self.ui.internal_surfaces table = ui.tablewidget_regions row = get_selected_row(table) if row is None: indices = [] regions = [] else: (indices, regions) = table.item(row, 0).data(UserRole) self.iss_current_indices, self.iss_current_regions = indices, regions enabled = (row is not None) for item in (ui.toolbutton_delete, ui.bottom_frame): item.setEnabled(enabled) ui.bottom_frame.setEnabled(enabled) if not enabled: # Clear for widget in widget_iter(ui.bottom_frame): if isinstance(widget, LineEdit): widget.setText('') return IS0 = self.iss_current_indices[0] cb = ui.combobox_is_type key = 'is_type' is_type = self.project.get_value(key, args=[IS0]) if is_type not in IS_TYPES: self.error("Unknown IS_TYPE %s" % is_type) is_type = 'IMPERMEABLE' for IS in self.iss_current_indices: self.update_keyword(key, is_type, args=[IS]) cb.setCurrentIndex(IS_TYPES.index(is_type)) # Available selections: # Impermeable # Selection only available for plane regions # set keyword IS_TYPE(#) to 'IMPERMEABLE' # X-Axis Impermeable # Selection only available for volume regions # set keyword IS_TYPE(#) to 'X_IMPERMEABLE' # Y-Axis Impermeable # Selection only available for volume regions # set keyword IS_TYPE(#) to 'Y_IMPERMEABLE' # z-Axis Impermeable # Selection only available for volume regions # set keyword IS_TYPE(#) to 'Z_IMPERMEABLE' # Semi-permeable # Selection only available for plane regions # set keyword IS_TYPE(#) to 'SEMIPERMEABLE' # X-Axis semi-permeable # Selection only available for volume regions # set keyword IS_TYPE(#) to 'X_SEMIPERMEABLE' # Y-Axis semi-permeable # Selection only available for volume regions # set keyword IS_TYPE(#) to 'Y_SEMIPERMEABLE' # Z-Axis semi-permeable # Selection only available for volume regions # set keyword IS_TYPE(#) to 'Z_SEMIPERMEABLE' # DEFAULT - Impermeable plane = is_type in ('IMPERMEABLE', 'SEMIPERMEABLE') vol = not plane for (i, enable) in enumerate( (plane, vol, vol, vol, plane, vol, vol, vol)): get_combobox_item(cb, i).setEnabled(enable) self.setup_iss() # reinitialize all widgets in current tab ui.scrollarea_detail.ensureVisible(0, 0) # scroll to top
def handle_monitors_region_selection(self): ui = self.ui.monitors table = ui.tablewidget_regions row = get_selected_row(table) nrows = table.rowCount() if row is None: index = None region = None else: (index, region) = table.item(row, COLUMN_REGION).data(UserRole) self.monitors_current_index, self.monitors_current_region = index, region enabled = (row is not None) for item in (ui.toolbutton_delete, ui.bottom_frame): item.setEnabled(enabled) if not enabled: return # Set combobox to only allow appropriate monitor_type cb = ui.combobox_monitor_type mon = index monitor_type = self.project.get_value('monitor_type', args=[mon]) region_type = self.monitors_region_dict.get(region) if region_type is None: self.error("Invalid region %s" % region) return region_type = region_type.get('type') if region_type == 'point': valids = MONITOR_TYPES_POINT elif 'plane' in region_type: valids = MONITOR_TYPES_PLANE elif 'box' in region_type: valids = MONITOR_TYPES_VOLUME else: valids = [] for i in range(len(cb)): get_combobox_item(cb, i).setEnabled(i in valids) if monitor_type is None or monitor_type not in valids: # Default not specified in SRS, but 1 (sum) is valid for planes and volumes monitor_type = 0 if region_type == 'point' else 1 self.update_keyword('monitor_type', monitor_type, args=[mon]) cb.setCurrentIndex(monitor_type) cb.setToolTip(get_combobox_item(cb, monitor_type).toolTip()) enable_phase = self.monitor_requires_phase(mon) if enable_phase: # Disable all tabs except 'Phase' for i in range(ui.tab_layout.columnCount() - 1): # Skip 'Phase' item = ui.tab_layout.itemAtPosition(0, i) if not item: continue widget = item.widget() if not widget: continue widget.setEnabled(False) widget.setToolTip('') ui.pushbutton_phase.setEnabled(True) else: ui.pushbutton_fluid.setEnabled(True) for i in range(1, 1 + len(self.solids)): # Enable tabs for TFM solids item = ui.tab_layout.itemAtPosition(0, i) if not item: continue widget = item.widget() if not widget: continue enabled = self.project.get_value('solids_model', args=[i]) == 'TFM' widget.setEnabled(enabled) widget.setToolTip('TFM solids required' if not enabled else '') ui.pushbutton_scalar.setEnabled( self.project.get_value('nscalar', default=0) > 0) ui.pushbutton_phase.setEnabled(False) self.setup_monitors() # reinitialize all widgets ui.scrollarea_detail.ensureVisible(0, 0) # scroll to top