def enable_row(self, i, enable): tw = self.ui.table enable = enable and tw.item(i, 2).data( UserRole) # Initial enable setting tw.item(i, 2).setText('Yes' if enable else 'No') for j in (0, 1, 2): set_item_enabled(tw.item(i, j), enable)
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 make_item(val, enabled): item = QTableWidgetItem('' if val is None else str(val)) set_item_noedit(item) set_item_enabled(item, enabled) return item
def make_item(str): item = QTableWidgetItem(str) set_item_noedit(item) set_item_enabled(item, False) return item
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 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)