Пример #1
0
    def test_air_01(self):
        # From MECH2201 - A10 Q2

        s1 = fullyDefine_StateIGas(StateIGas(P=97, T=70), air)
        self.CompareResults(s1, {'mu': 1.015}, 3)

        s2 = fullyDefine_StateIGas(StateIGas(T=(1136.86 - 273), mu=0.0507), air)
        self.CompareResults(s2, {'P': 6435}, 3)

        s3 = fullyDefine_StateIGas(StateIGas(P=6435, T=(2046.35 - 273.15)), air)
        self.CompareResults(s3, {'mu': 0.09126}, 3)
Пример #2
0
    def test_air_01(self):
        # MECH2201 - A10 - Q1
        s1 = StateIGas(P=100, T=30, mu=0.45/0.517)
        s2 = StateIGas(P=1100)

        apply_isentropicIGasProcess(constant_c=False, fluid=air, state_in=s1, state_out=s2)
        self.CompareResults(s1, {'P_r': 1.4356}, 3)
        self.CompareResults(s1, {'mu_r': 606.08}, 3)
        self.CompareResults(s2, {'P_r': 15.9712}, 3)
        self.CompareResults(s2, {'T': 594.96-273}, 3)
        self.CompareResults(s2, {'mu_r': 108.22}, 3)
        self.CompareResults(s2, {'u': 430.94}, 3)
Пример #3
0
def apply_IGasLaw(state: StateIGas, R: float):
    """Uses Ideal Gas Law to find missing properties, if possible. If all variables in the Ideal Gas Law are already defined, checks consistency"""
    # P mu = R T
    IGasLaw_allProperties = ['P', 'mu', 'T']
    IGasLaw_availableProperties = [propertyName for propertyName in IGasLaw_allProperties if isNumeric(getattr(state, propertyName))]
    IGasLaw_missingProperties = [propertyName for propertyName in IGasLaw_allProperties if propertyName not in IGasLaw_availableProperties]

    if number_ofMissingProperties := len(IGasLaw_missingProperties) == 1:
        missingProperty = IGasLaw_missingProperties[0]
        if missingProperty == 'P':
            state.P = (R * to_Kelvin(state.T) / state.mu)
        elif missingProperty == 'mu':
            state.mu = (R * to_Kelvin(state.T) / state.P)
        elif missingProperty == 'T':
            state.T = to_deg_C(state.P * state.mu / R)
Пример #4
0
def interpolate_inIGasTable(mpDF: DataFrame, interpolate_by: str, interpolate_at: float) -> StateIGas:
    """Method to interpolate in the mpDF of an ideal gas, which should give T-dependent properties such as h, u, P_r, mu_r, s0."""

    queryPropt, queryValue = interpolate_by, interpolate_at

    exactMatch = mpDF.query('{0} == {1}'.format(queryPropt, queryValue))

    if exactMatch.empty:
        states_ordered_byPropt = mpDF.sort_values(queryPropt)
        proptVal_below, proptVal_above = get_surroundingValues(states_ordered_byPropt[queryPropt].to_list(), queryValue)
        state_below = StateIGas().init_fromDFRow( mpDF.query('{0} == {1}'.format(queryPropt, proptVal_below)) )
        state_above = StateIGas().init_fromDFRow( mpDF.query('{0} == {1}'.format(queryPropt, proptVal_above)) )

        state_atProptVal = interpolate_betweenPureStates(state_below, state_above, interpolate_at={queryPropt: queryValue})
        assert all([state_atProptVal.hasDefined(property) for property in StateIGas._properties_Tdependent])
        return state_atProptVal
Пример #5
0
def define_StateIGas(state: StateIGas, fluid: 'IdealGas'):
    """Tries to fill in the properties of an ideal gas state by applying the ideal gas law and looking up state on the provided mpDF."""

    if len(available_TDependentProperties := [propertyName for propertyName in fluid.mpDF.mp.availableProperties if propertyName in state._properties_all and isNumeric(getattr(state, propertyName))]) >= 1:
        refPropt_name = available_TDependentProperties[0]

        # Try finding exact state on mpDF
        state_at_refPropt = fluid.mpDF.cq.cQuery({refPropt_name: getattr(state, refPropt_name)})
        try:
            if state_at_refPropt.empty:
                # Interpolate in mpDF
                refPropt_valueBelow, refPropt_valueAbove = get_surroundingValues(fluid.mpDF[refPropt_name], value=getattr(state, refPropt_name))
                state_at_refPropt_valueBelow = StateIGas().init_fromDFRow(fluid.mpDF.cq.cQuery({refPropt_name: refPropt_valueBelow}))
                state_at_refPropt_valueAbove = StateIGas().init_fromDFRow(fluid.mpDF.cq.cQuery({refPropt_name: refPropt_valueAbove}))
                state_at_refPropt = interpolate_betweenPureStates(state_at_refPropt_valueBelow, state_at_refPropt_valueAbove, interpolate_at={refPropt_name: getattr(state, refPropt_name)})

            state.copy_fromState(state_at_refPropt)
        except NeedsExtrapolationError:
            pass
Пример #6
0
    def test_air_02(self):
        # MECH2201 - A10 - Q2

        s1 = StateIGas(P=97, T=70)
        fullyDefine_StateIGas(s1, air)
        self.CompareResults(s1, {'mu': 1.015}, 3)

        s2 = StateIGas(mu=s1.mu/20)

        # Tests finding T of state using ratio of mu1/mu2
        apply_isentropicIGasProcess(constant_c=True, fluid=air, state_in=s1, state_out=s2)
        self.CompareResults(s2, {'T': 1136.86-273, 'P': 6435}, 3)

        s3 = StateIGas(P=6435, T=2046.35-273)
        fullyDefine_StateIGas(s3, air)
        self.CompareResults(s3, {'mu': 0.09126}, 3)

        s4 = StateIGas(mu=20*s2.mu)
        apply_isentropicIGasProcess(constant_c=True, fluid=air, state_in=s3, state_out=s4)
        self.CompareResults(s4, {'T': 781.05-273}, 3)
Пример #7
0
def fullyDefine_StateIGas(state: StateIGas, fluid: 'IdealGas') -> StateIGas:
    """Tries to fill in the properties of an ideal gas state by applying the ideal gas law and looking up state on the provided mpDF."""
    apply_IGasLaw(state, fluid.R)

    # Do an ideal gas table look-up after applying ideal gas law above. The process above may first determine T and only then this table look-up can be done.
    # if len(available_TDependentProperties := [propertyName for propertyName in state.get_asList_definedPropertiesNames() if propertyName in fluid.mpDF.mp.availableProperties]) >= 1:
    if len(available_TDependentProperties := [propertyName for propertyName in StateIGas._properties_Tdependent if state.hasDefined(propertyName)]) >= 1:
        # Get tabulated T-dependent properties
        refPropt_name = available_TDependentProperties[0]
        state_at_refPropt = fluid.mpDF.cq.cQuery({refPropt_name: getattr(state, refPropt_name)})  # Try finding exact state on mpDF

        if state_at_refPropt.empty:
            try:
                # Interpolate in mpDF - ideal gas properties table
                interpolatedState = interpolate_inIGasTable(mpDF=fluid.mpDF, interpolate_by=refPropt_name, interpolate_at=getattr(state, refPropt_name))
                state.copy_fromState(interpolatedState)
            except NeedsExtrapolationError:
                print('fullyDefine_StateIGas: Extrapolation needed to find state at {0}={1}'.format(refPropt_name, getattr(state, refPropt_name)))
                pass
        else:
            state.init_fromDFRow(state_at_refPropt)  # Found exact match, initialize from DFRow
Пример #8
0
    def _get_state_in_from_state_out(self,
                                     device: WorkDevice,
                                     state_out: StateIGas,
                                     percentDifference: float = 0.1,
                                     iteration_T_steps: float = 2):
        """Finds state_in to the WorkDevice by iterating and trying to match the isentropic efficiency."""
        # TODO: Can add the process for constant c, non ideal gases

        state_in_guess = StateIGas(P=device.state_in.P)
        apply_isentropicIGasProcess(constant_c=self.constant_c,
                                    state_in=state_in_guess,
                                    state_out=state_out,
                                    fluid=self.workingFluid)
        state_in_guess.clearFields(keepFields=[
            'P', 'T'
        ])  # Iteration guess state has only T and P defined.

        compression = state_out.P > device.state_in.P
        iteration = 1
        while True:
            print(
                '_get_state_in_from_state_out: Solution iteration #{0} - state_in temperature guess: {1}'
                .format(iteration, state_in_guess.T))
            self.workingFluid.define(state_in_guess)
            state_out_ideal_guess = StateIGas(P=state_out.P)
            apply_isentropicIGasProcess(self.constant_c,
                                        fluid=self.workingFluid,
                                        state_in=state_in_guess,
                                        state_out=state_out_ideal_guess)

            if compression:
                eta_isentropic_guess = (state_out_ideal_guess.h -
                                        state_in_guess.h) / (state_out.h -
                                                             state_in_guess.h)
            else:  # expansion
                eta_isentropic_guess = (state_in_guess.h - state_out.h) / (
                    state_in_guess.h - state_out_ideal_guess.h)

            if isWithin(eta_isentropic_guess, percentDifference, '%',
                        device.eta_isentropic):
                print(
                    '_get_state_in_from_state_out: Solution satisfactory at iteration {0} - eta_isentropic Prescribed/Calculated: {1}/{2}\n\tstate_in: {3}'
                    .format(iteration, device.eta_isentropic,
                            eta_isentropic_guess, state_in_guess))
                break
            else:
                # Reset iteration guess state at each iteration to have T and P only.
                state_in_guess = StateIGas(
                    T=(state_in_guess.T - iteration_T_steps),
                    P=device.state_in.P
                )  # reduce temperature by K/°C and try again to see if this is the right state_in that gives the prescribed isentropic efficiency
                iteration += 1
        return state_in_guess
Пример #9
0
    def solve_workDevice(self, device: WorkDevice):
        """Determines outlet state based on available inlet state using isentropic efficiency."""
        # Find the state_out out of the device IN THIS FLOW - work devices may have multiple states_out (e.g. turbines with many extractions for reheat, regeneration).

        occurrences_ofDevice = [
            index for index, item in enumerate(self.items) if item is device
        ]
        states_afterDevice: List[StatePure] = [
            self.items[index + 1] for index in occurrences_ofDevice
            if index + 1 < len(self.items)
        ]  # state_afterDevice is a StatePure for sure after the check in _check_itemsConsistency

        # PRESSURE RATIO RELATION SETUP
        if not device._pressureRatioRelationSetup and len(
                states_afterDevice) == 1:
            self._add_pressureRatioRelation(device)

        # ISENTROPIC PROCESS RELATIONS
        if device.eta_isentropic == 1:
            self._set_endStateEntropiesEqual(device)

            if isinstance(self.workingFluid, IdealGas):
                for state_out in device.states_out:  # Can determine additional properties based on ideal gas isentropic process relations
                    apply_isentropicIGasProcess(constant_c=self.constant_c,
                                                state_in=device.state_in,
                                                state_out=state_out,
                                                fluid=self.workingFluid)

            self._defineStates_ifDefinable(
                device.endStates
            )  # if any states became definable with the above process

        # ISENTROPIC EFFICIENCY RELATIONS
        for state_out in states_afterDevice:
            if not isinstance(self.workingFluid, IdealGas) and (
                    device.state_in.hasDefined('h')
                    and state_out.hasDefined('P')
            ):  # Used to check if state_in also hadNumeric 's'
                # going to overwrite state_out - TODO: Need to copy in the first time, then verify in subseqs
                state_out.copy_fromState(
                    apply_isentropicEfficiency(
                        constant_c=self.constant_c,
                        state_in=device.state_in,
                        state_out_ideal=state_out,
                        eta_isentropic=device.eta_isentropic,
                        fluid=self.workingFluid))
            elif isinstance(self.workingFluid, IdealGas):

                # FIND state_out FROM state_in
                if not state_out.hasDefined(
                        'T'):  # common case: find state_out based on state_in
                    state_out_ideal = StateIGas().copy_fromState(state_out)
                    apply_isentropicIGasProcess(constant_c=self.constant_c,
                                                fluid=self.workingFluid,
                                                state_in=device.state_in,
                                                state_out=state_out_ideal)
                    state_out_actual = apply_isentropicEfficiency(
                        constant_c=self.constant_c,
                        state_in=device.state_in,
                        state_out_ideal=state_out_ideal,
                        eta_isentropic=device.eta_isentropic,
                        fluid=self.workingFluid)
                    if state_out_actual is not None:
                        state_out.copy_fromState(state_out_actual)

                # FIND state_in FROM state_out
                else:
                    if device.state_in.hasDefined(
                            'P') and state_out.hasDefined(
                                'P') and not device.state_in.hasDefined('T'):
                        print(
                            '\tReverse Isentropic Efficiency Calculation:\n\tstate_out: {0}\n\tstate_in: {1}'
                            .format(state_out, device.state_in))
                        device.state_in.copy_fromState(
                            self._get_state_in_from_state_out(
                                device, state_out))