예제 #1
0
 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)
예제 #2
0
    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)
예제 #3
0
    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())
예제 #4
0
 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
예제 #5
0
 def make_item(str):
     item = QTableWidgetItem(str)
     set_item_noedit(item)
     set_item_enabled(item, False)
     return item
예제 #6
0
    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
예제 #7
0
    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)