示例#1
0
class ThermodynamicalProcess(ThermodynamicalCycle):
    ############# Inputs #############
    fluidSource = F.SubModelGroup(TC.FluidSource, 'FG', label='Initial State')
    fluidSink = F.SubModelGroup(TC.FluidSink, 'FG', label='Final State')
    inputs = F.SuperGroup([fluidSource, fluidSink])

    # Model View
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs],
                            autoFetch=True)

    ############# Results #############
    w = F.Quantity('SpecificEnergy',
                   default=(0, 'kJ/kg'),
                   label='specific work')
    qIn = F.Quantity('SpecificEnergy',
                     default=(0, 'kJ/kg'),
                     label='specific heat in')
    delta_h = F.Quantity('SpecificEnthalpy', label='enthalpy change (fluid)')
    WDot = F.Quantity('Power', default=(0, 'kW'), label='power')
    QDotIn = F.Quantity('HeatFlowRate',
                        default=(0, 'kW'),
                        label='heat flow rate in')
    deltaHDot = F.Quantity('Power', label='enthalpy change (fluid)')
    # Specific energy quantities
    specificEnergyResults = F.FieldGroup(
        [w, delta_h, qIn], label="Heat/work (specific quantities)")
    # Energy flow quantities
    energyFlowResults = F.FieldGroup([WDot, deltaHDot, QDotIn],
                                     label="Heat/work flows")
    energyBalanceResults = F.SuperGroup(
        [specificEnergyResults, energyFlowResults], label="Energy balance")

    # Model View
    resultView = F.ModelView(
        ioType="output",
        superGroups=['resultDiagrams', 'resultStates', energyBalanceResults])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    ############# Methods ###############
    def postProcess(self, component):
        super(ThermodynamicalProcess, self).postProcess(300)
        component.postProcess()
        self.w = component.w
        self.qIn = component.qIn
        self.delta_h = component.delta_h
        self.WDot = component.WDot
        self.QDotIn = component.QDotIn
        self.deltaHDot = component.deltaHDot
示例#2
0
class SolverSettings(NumericalModel):
    tFinal = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(0, 'day'),
                        maxValue=(1000, 'day'),
                        label='simulation time')
    tPrint = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(1e-5, 'day'),
                        maxValue=(100, 'day'),
                        label='print interval')

    absTol = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-5, 'day'),
                        label='absolute tolerance')
    relTol = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-3, 'day'),
                        label='relative tolerance')

    FG = F.FieldGroup([tFinal, tPrint, absTol, relTol], label='Solver')
    SG = F.SuperGroup([FG], label='Settings')

    modelBlocks = []
示例#3
0
class RegenerativeRankineCycle(RankineCycle):
	label = "Regenerative Rankine cycle"
	figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/RankineCycle_Recuperator.svg",  height = 300)
	description = F.ModelDescription("Rankine cycle with recuperator, \
		using the temperature of the hot steam before the condenser to pre-heat the fluid before entering the boiler", show = True)
	#================ Inputs ================#
	#---------------- Fields ----------------#
	# FieldGroup
	recuperator = F.SubModelGroup(TC.HeatExchangerTwoStreams, 'FG', label = 'Recuperator')
	inputs = F.SuperGroup(['workingFluidGroup', 'pump', recuperator, 'boiler', 'turbine', 'condenser'], label = 'Cycle defininition')
	#--------------- Model view ---------------#

	#================ Results ================#
	#---------------- Energy flows -----------#
	recuperatorHeat = F.Quantity('HeatFlowRate', default = (0, 'kW'), label = 'recuperator heat rate')
	flowFieldGroup = F.FieldGroup(['pumpPower', recuperatorHeat, 'boilerHeat', 'turbinePower', 'condenserHeat'], label = 'Energy flows')
	#---------------- Scheme -----------------#
	scheme_Rankine_recup = F.Image(default="static/ThermoFluids/img/ModuleImages/RankineCycle_Recuperator.png")
	SchemeVG = F.ViewGroup([scheme_Rankine_recup], label="Process Scheme")
	SchemeSG = F.SuperGroup([SchemeVG], label="Scheme")
	
	resultView = F.ModelView(ioType = "output", superGroups = ['resultDiagrams', SchemeSG, 'resultStates', 'resultEnergy', 'solverStats'])
	#================ Methods ================#
	def compute(self):
		self.initCompute(self.fluidName)
		# Connect components
		self.connectPorts(self.condenser.outlet, self.pump.inlet)
		self.connectPorts(self.pump.outlet, self.recuperator.inlet1)
		self.connectPorts(self.recuperator.outlet1, self.boiler.inlet)
		self.connectPorts(self.boiler.outlet, self.turbine.inlet)
		self.connectPorts(self.turbine.outlet, self.recuperator.inlet2)
		self.connectPorts(self.recuperator.outlet2, self.condenser.inlet)
		# Initial guess
		for fl in self.flows:
			fl.mDot = self.mDot
		self.condenser.outlet.state.update_pq(self.pLow, 0)
		self.boiler.outlet.state.update_pq(self.pHigh, 1)
		self.turbine.compute(self.pLow)
		# Cycle iterations
		self.solver.run()
		# Results
		self.postProcess()
		
	def computeCycle(self):
		self.pump.compute(self.pHigh)
		self.recuperator.compute()
		self.recuperator.computeStream1()
		self.boiler.compute()	
		self.turbine.compute(self.pLow)
		self.recuperator.computeStream2()
		self.condenser.compute()
		
	def postProcess(self):
		super(RegenerativeRankineCycle, self).postProcess()
		self.recuperatorHeat = self.recuperator.QDot 

	def SteamPlant(self):
		RankineCycle.SteamPlant(self)
		self.pLow = (2, 'bar')
		self.boiler.TOutlet = (600, 'degC')
示例#4
0
class LiquefactionCycle(ThermodynamicalCycle):
    abstract = True
    #================ Inputs ================#
    fluidName = F.Choices(Fluids, default='R134a', label='liquefied fluid')
    mDot = F.Quantity('MassFlowRate',
                      default=(1, 'kg/min'),
                      label='inlet flow rate')
    pIn = F.Quantity('Pressure',
                     default=(1, 'bar'),
                     label='inlet gas pressure')
    TIn = F.Quantity('Temperature',
                     default=(15, 'degC'),
                     label='inlet gas temperature')
    pHigh = F.Quantity('Pressure',
                       default=(40, 'bar'),
                       label='compressor high pressure')
    pLiquid = F.Quantity('Pressure',
                         default=(2, 'bar'),
                         label='liquid pressure')
    TAmbient = F.Quantity(
        'Temperature',
        default=(15, 'degC'),
        label='ambient temperature',
        description='used as reference temperature to calculate exergy')
    workingFluidGroup = F.FieldGroup(
        ['fluidName', 'mDot', pIn, TIn, pHigh, pLiquid, TAmbient],
        label='Cycle parameters')
    #================ Results ================#
    liqEnergy = F.Quantity('SpecificEnergy',
                           default=(1, 'kJ/kg'),
                           label='liquefaction energy')
    minLiqEnergy = F.Quantity(
        'SpecificEnergy',
        default=(1, 'kJ/kg'),
        label='min. liquefaction energy',
        description=
        'minimum energy required for liquefaction in an ideal carnot cycle; \
			equal to the difference in exergies between initial and final state')
    etaSecondLaw = F.Quantity(
        'Efficiency',
        label='figure of merit (FOM)',
        description=
        'minimum energy required for liquefaction to the actual energy required \
			in the cycle; equivalent to second law efficiency')
    efficiencyFieldGroup = F.FieldGroup(
        [liqEnergy, minLiqEnergy, etaSecondLaw], label='Efficiency')
示例#5
0
class CycleIterator(NumericalModel):
    hTolerance = F.Quantity('SpecificEnthalpy',
                            default=1.0,
                            label='enthalpy tolerance')
    maxNumIter = F.Quantity(default=500,
                            label='max iterations',
                            description='maximum number of iterations')
    convSettings = F.FieldGroup([hTolerance, maxNumIter],
                                label='Convergence settings')
    solverSettings = F.SuperGroup([convSettings], label='Solver')
    modelBlocks = []

    def run(self):
        self.converged = False
        self.ncp = len(self.cycle.fp)
        self.old_h = np.zeros((self.ncp))
        self.old_T = np.zeros((self.ncp))
        self.old_p = np.zeros((self.ncp))
        self.hHistory = []
        self.change_h = np.zeros((self.ncp))
        self.change_hHistory = []
        i = 0
        self.cycle.computeCycle()
        while (i < self.maxNumIter):
            self.saveOldValues()
            self.cycle.computeCycle()
            self.checkConvergence()
            if (self.converged):
                break
            i += 1

        if (not self.converged):
            raise E.ConvergenceError(
                'Solution did not converge, delta_h = {:e}'.format(
                    self.change_hHistory[-1]))

    def saveOldValues(self):
        for i in range(self.ncp):
            self.old_h[i] = self.cycle.fp[i].h
            self.old_T[i] = self.cycle.fp[i].T
            self.old_p[i] = self.cycle.fp[i].p
        #self.hHistory.append(self.old_h)

    def computeChange(self):
        for i in range(self.ncp):
            self.change_h[i] = self.cycle.fp[i].h - self.old_h[i]
        change = np.sqrt(np.sum(self.change_h**2))
        self.hHistory.append([x for x in self.change_h])
        self.change_hHistory.append(change)
        return change

    def checkConvergence(self):
        self.converged = self.computeChange() < self.hTolerance
        return self.converged

    def printValues(self):
        print[fp.T for fp in self.cycle.fp]
        print[fl.mDot for fl in self.cycle.flows]
示例#6
0
class FiniteVolumeSolverSettings(NumericalModel):
    tolerance = F.Quantity(default=1e-6, label='tolerance')
    maxNumIterations = F.Integer(default=100, label='max number iterations')
    relaxationFactor = F.Quantity(default=1.0, label='relaxation factor')

    FG = F.FieldGroup([tolerance, maxNumIterations, relaxationFactor],
                      label='Settings')

    modelBlocks = []
示例#7
0
class ChannelGroupGeometry(NumericalModel):
    number = F.Integer(default=0,
                       minValue=0,
                       maxValue=30,
                       label='number',
                       description='number of channels')
    radialPosition = F.Quantity('Length',
                                default=(0., 'mm'),
                                minValue=(0, 'mm'),
                                label='radial position',
                                description='radial position of the channels')
    startingAngle = F.Quantity('Angle',
                               default=(0., 'deg'),
                               minValue=(-1e6, 'deg'),
                               label='starting angle',
                               description='starting angle of the first')

    cellSize = F.Quantity('Length',
                          default=(0., 'mm'),
                          label='mesh cell size',
                          description='mesh cell size near the channels')
    meshFineness = F.Integer(default=1,
                             minValue=1,
                             maxValue=10,
                             label='mesh fineness',
                             description='mesh fineness near the channels')

    externalDiameter = F.Quantity(
        'Length',
        default=(0., 'mm'),
        label='external diameter',
        description='external diameter of the channels')
    sections = F.RecordArray((
        ('internalDiameter',
         F.Quantity('Length',
                    default=(0, 'mm'),
                    minValue=(0, 'mm'),
                    label='internal diameter')),
        ('length', F.Quantity('Length', default=(0.2, 'm'), label='length')),
    ),
                             label='sections',
                             numRows=5)

    channelName = F.String()

    FG = F.FieldGroup([
        number, radialPosition, startingAngle, externalDiameter, sections,
        meshFineness
    ],
                      label='Parameters')

    modelBlocks = []

    def compute(self):
        self.cellSize = self.externalDiameter / (self.meshFineness * 2.5)
        self.length = np.sum(self.sections['length'])
示例#8
0
class Controller(NumericalModel):
    initialState = F.Choices(
        OrderedDict((
            (TC.FUELING, 'fueling'),
            (TC.EXTRACTION, 'extraction'),
        )),
        label='start with',
        description='start the simulation with fueling or extraction')
    tWaitBeforeExtraction = F.Quantity(
        'Time',
        default=(0., 's'),
        minValue=(0., 's'),
        maxValue=(1.e6, 's'),
        label='&#964 (extraction)',
        description='waiting time before each extraction')
    tWaitBeforeFueling = F.Quantity(
        'Time',
        default=(0., 's'),
        minValue=(0., 's'),
        maxValue=(1.e6, 's'),
        label='&#964 (fueling)',
        description='waiting time before each fueling')
    pMin = F.Quantity(
        'Pressure',
        default=(0., 'bar'),
        label='minimum pressure</sub>',
        description='minimum pressure in the gas storage for starting fueling')
    pMax = F.Quantity(
        'Pressure',
        default=(0., 'bar'),
        label='maximum pressure',
        description='maximum pressure in the gas storage for stopping fueling')
    mDotExtr = F.Quantity('MassFlowRate',
                          default=(0., 'kg/h'),
                          label='extraction mass flow rate',
                          description='extraction mass flow rate')
    nCompressor = F.Quantity('AngularVelocity',
                             default=(0., 'rev/s'),
                             minValue=(0, 'rev/s'),
                             maxValue=(1e4, 'rev/s'),
                             label='compressor speed',
                             description='compressor speed')

    FG = F.FieldGroup([
        initialState, pMin, pMax, mDotExtr, nCompressor, tWaitBeforeExtraction,
        tWaitBeforeFueling
    ],
                      label='Parameters')

    SG = F.SuperGroup([FG], label="Parameters")

    modelBlocks = []
示例#9
0
class BlockGeometry(NumericalModel):
    diameter = F.Quantity('Length',
                          default=(0., 'mm'),
                          label='diameter',
                          description='block diameter')
    length = F.Quantity('Length',
                        default=(0., 'm'),
                        label='length',
                        description='block length')

    FG = F.FieldGroup([diameter, length], label='Block geometry')

    modelBlocks = []
示例#10
0
class TankRes(NumericalModel):
    compositeMass = F.Quantity('Mass',
                               default=(0., 'kg'),
                               label='composite mass',
                               description='composite mass')
    linerMass = F.Quantity('Mass',
                           default=(0., 'kg'),
                           label='liner mass',
                           description='liner mass')

    FG = F.FieldGroup([linerMass, compositeMass], label='Pressure vessel')

    modelBlocks = []
示例#11
0
class FluidSource_TP(CycleComponent):
    T = F.Quantity('Temperature', label='temperature')
    p = F.Quantity('Pressure', label='pressure')
    mDot = F.Quantity('MassFlowRate', label='mass flow rate')
    FG = F.FieldGroup([T, p, mDot], label='Compressor')
    modelBlocks = []
    #================== Ports =================#
    outlet = F.Port(P.ThermodynamicPort)

    #================== Methods =================#
    def compute(self):
        self.outlet.flow.mDot = self.mDot
        self.outlet.state.update_Tp(self.T, self.p)
示例#12
0
class ThrottleValve(CycleComponent2FlowPorts):
    FG = F.FieldGroup([])
    modelBlocks = []

    #================== Methods =================#
    def compute(self, pOut):
        if (pOut > self.inlet.state.p):
            raise ValueError(
                'Outlet pressure must be lower than inlet pressure')
        CycleComponent2FlowPorts.compute(self)
        self.outlet.state.update_ph(pOut, self.inlet.state.h)
        self.w = 0
        self.qIn = 0
        self.delta_h = 0
示例#13
0
class BlockProperties(NumericalModel):
    material = F.ObjectReference(Solids,
                                 default='Aluminium6061',
                                 label='material',
                                 description='block material')
    divisionStep = F.Quantity('Length',
                              default=(0., 'm'),
                              minValue=(1, 'mm'),
                              label='division step (axial)',
                              description='axial division step')

    FG = F.FieldGroup([material, divisionStep], label='Block properties')

    modelBlocks = []
示例#14
0
class FlowJunction(CycleComponent):
    FG = F.FieldGroup([])
    modelBlocks = []
    #================== Ports =================#
    inletMain = F.Port(P.ThermodynamicPort)
    inlet2 = F.Port(P.ThermodynamicPort)
    outlet = F.Port(P.ThermodynamicPort)

    #================== Methods =================#
    def compute(self):
        HDotIn = self.inletMain.flow.mDot * self.inletMain.state.h \
         + self.inlet2.flow.mDot * self.inlet2.state.h
        mDotIn = self.inletMain.flow.mDot + self.inlet2.flow.mDot
        hOut = HDotIn / mDotIn
        self.outlet.state.update_ph(self.inletMain.state.p, hOut)
        self.outlet.flow.mDot = mDotIn
示例#15
0
class Turbine(CycleComponent2FlowPorts):
    eta = F.Quantity(default=1, minValue=0, maxValue=1, label='efficiency')
    FG = F.FieldGroup([eta], label='Turbine')
    modelBlocks = []

    #================== Methods =================#
    def compute(self, pOut):
        if (pOut > self.inlet.state.p):
            raise ValueError(
                'Outlet pressure must be lower than inlet pressure')
        CycleComponent2FlowPorts.compute(self)
        self.outlet.state.update_ps(pOut, self.inlet.state.s)
        wIdeal = self.outlet.state.h - self.inlet.state.h
        self.w = wIdeal * self.eta
        self.qIn = 0
        self.delta_h = self.w + self.qIn
        self.outlet.state.update_ph(pOut, self.inlet.state.h + self.delta_h)
示例#16
0
class IncompressibleSolutionFlowInput(FluidFlowInput):
    solName = F.Choices(IncompressibleSolutions,
                        default='MEG',
                        label='fluid (name)',
                        description='fluid (incompressible solutions)')
    solMassFraction = F.Quantity(
        'Fraction',
        default=(0, '%'),
        label='fluid (mass fraction)',
        description='mass fraction of the substance other than water')

    incomSolFG = F.FieldGroup(
        [solName, solMassFraction, 'flowRateChoice', 'mDot', 'VDot', 'T', 'p'],
        label='Parameters')

    def createFluidState(self):
        return CP5.FluidStateFactory.createIncompressibleSolution(
            self.solName, self.solMassFraction)
示例#17
0
class Compressor(NumericalModel):
    etaS = F.Quantity('Efficiency',
                      default=(0., '-'),
                      label='isentropic efficiency',
                      description='isentropic efficiency')
    fQ = F.Quantity('Fraction',
                    default=(0., '-'),
                    label='heat loss fraction',
                    description='heat loss fraction to ambient')
    V = F.Quantity('Volume',
                   default=(0., 'L'),
                   maxValue=(1e6, 'L'),
                   label='displacement volume',
                   description='displacement volume')

    FG = F.FieldGroup([etaS, fQ, V], label='Parameters')

    modelBlocks = []
示例#18
0
class Compressor(CycleComponent2FlowPorts):
    modelType = F.Choices(OrderedDict((
        ('S', 'isentropic'),
        ('T', 'isothermal'),
    )),
                          label='compressor model')
    etaS = F.Quantity('Efficiency',
                      label='isentropic efficiency',
                      show="self.modelType == 'S'")
    fQ = F.Quantity('Fraction',
                    default=0.,
                    label='heat loss factor',
                    show="self.modelType == 'S'")
    etaT = F.Quantity('Efficiency',
                      label='isosthermal efficiency',
                      show="self.modelType == 'T'")
    dT = F.Quantity('TemperatureDifference',
                    default=0,
                    label='temperature increase',
                    show="self.modelType == 'T'")
    FG = F.FieldGroup([modelType, etaS, fQ, etaT, dT], label='Compressor')
    modelBlocks = []

    #================== Methods =================#
    def compute(self, pOut):
        CycleComponent2FlowPorts.compute(self)
        if (pOut < self.inlet.state.p):
            raise ValueError(
                'Outlet pressure must be higher than inlet pressure')
        if (self.modelType == 'S'):
            self.outlet.state.update_ps(pOut, self.inlet.state.s)
            wIdeal = self.outlet.state.h - self.inlet.state.h
            self.w = wIdeal / self.etaS
            self.qIn = -self.fQ * self.w
            self.delta_h = self.w + self.qIn
            self.outlet.state.update_ph(pOut,
                                        self.inlet.state.h + self.delta_h)
        else:
            self.outlet.state.update_Tp(self.inlet.state.T + self.dT, pOut)
            self.qIn = (self.outlet.state.s -
                        self.inlet.state.s) * self.inlet.state.T
            wIdeal = self.outlet.state.h - self.inlet.state.h - self.qIn
            self.w = wIdeal / self.etaT
            self.qIn -= (self.w - wIdeal)
示例#19
0
class FluidStateSource(NumericalModel):
    sourceTypeTxt = F.Choices(OrderedDict((
        ('TP', 'temperature, pressure'),
        ('PQ', 'pressure, vapour quality'),
        ('TQ', 'temperature, vapour quality'),
    )),
                              label='state variables',
                              description='choose the initial state variables')

    @property
    def sourceType(self):
        if self.sourceTypeTxt == 'TP':
            return DM.FluidStateSource.TP
        if self.sourceTypeTxt == 'PQ':
            return DM.FluidStateSource.PQ
        if self.sourceTypeTxt == 'TQ':
            return DM.FluidStateSource.TQ
        else:
            raise ValueError('Unsupported source type of FluidStateSource.')

    T = F.Quantity(
        'Temperature',
        default=(0., 'degC'),
        label='temperature',
        description='temperature',
        show="self.sourceTypeTxt == 'TP' || self.sourceTypeTxt == 'TQ'")
    p = F.Quantity(
        'Pressure',
        default=(0., 'bar'),
        label='pressure',
        description='pressure',
        show="self.sourceTypeTxt == 'TP' || self.sourceTypeTxt == 'PQ'")
    q = F.Quantity(
        'VaporQuality',
        default=(0., '-'),
        minValue=0,
        maxValue=1,
        label='vapour quality',
        description='vapour quality',
        show="self.sourceTypeTxt == 'TQ' || self.sourceTypeTxt == 'PQ'")

    FG = F.FieldGroup([sourceTypeTxt, T, p, q], label='Parameters')

    modelBlocks = []
示例#20
0
class SectionResultsSettings(NumericalModel):
    setTRange = F.Boolean(
        False,
        label='set temperature range',
        description=
        'set temperature range (Tmin, Tmax) of the section results plots')
    Tmin = F.Quantity('Temperature',
                      default=(0, 'K'),
                      label='min temperature',
                      description='minimum temperature',
                      show='self.setTRange')
    Tmax = F.Quantity('Temperature',
                      default=(0, 'K'),
                      label='max temperature',
                      description='maximum temperature',
                      show='self.setTRange')

    FG = F.FieldGroup([setTRange, Tmin, Tmax], label='Settings')

    modelBlocks = []
示例#21
0
class FlowSplitter(CycleComponent):
    frac1 = F.Quantity('Fraction', label='fraction to outlet 1')
    frac2 = F.Quantity('Fraction', label='fraction to outlet 2')
    FG = F.FieldGroup([frac1, frac2])
    modelBlocks = []
    #================== Ports =================#
    inlet = F.Port(P.ThermodynamicPort)
    outlet1 = F.Port(P.ThermodynamicPort)
    outlet2 = F.Port(P.ThermodynamicPort)

    #================== Methods =================#
    def compute(self):
        self.outlet1.flow.mDot = self.inlet.flow.mDot * self.frac1 / (
            self.frac1 + self.frac2)
        self.outlet2.flow.mDot = self.inlet.flow.mDot * self.frac2 / (
            self.frac1 + self.frac2)
        self.outlet1.state.update_Trho(self.inlet.state.T,
                                       self.inlet.state.rho)
        self.outlet2.state.update_Trho(self.inlet.state.T,
                                       self.inlet.state.rho)
示例#22
0
class Condenser(IsobaricHeatExchanger):
    computeMethod = F.Choices(OrderedDict((
        ('dT', 'sub-cooling'),
        ('Q', 'vapor quality'),
        ('eta', 'thermal efficiency'),
        ('T', 'temperature'),
        ('H', 'enthalpy'),
    )),
                              label='compute outlet by')
    dTOutlet = F.Quantity('TemperatureDifference',
                          default=(-10, 'degC'),
                          minValue=-1e10,
                          maxValue=-1e-3,
                          label='outlet subcooling',
                          show='self.computeMethod == "dT"')
    FG = F.FieldGroup([
        'computeMethod', 'etaThermal', 'TExt', 'dTOutlet', 'TOutlet',
        'qOutlet', 'hOutlet'
    ],
                      label='Condenser')
    modelBlocks = []
示例#23
0
class PhaseSeparator(CycleComponent):
    FG = F.FieldGroup([])
    modelBlocks = []
    #================== Ports =================#
    inlet = F.Port(P.ThermodynamicPort)
    outletLiquid = F.Port(P.ThermodynamicPort)
    outletVapor = F.Port(P.ThermodynamicPort)

    #================== Methods =================#
    def compute(self):
        if (0 < self.inlet.state.q < 1):
            fq = self.inlet.state.q
        else:
            fq = 1.0

        self.outletLiquid.state.update_pq(self.inlet.state.p, 0)
        self.outletLiquid.flow.mDot = (1 - fq) * self.inlet.flow.mDot
        #self.outletLiquid.flow.HDot = self.outletLiquid.flow.mDot * self.outletLiquid.state.h

        self.outletVapor.state.update_pq(self.inlet.state.p, 1)
        self.outletVapor.flow.mDot = fq * self.inlet.flow.mDot
示例#24
0
class HeatFlowChannels(NumericalModel):
    QDotPrimaryChannels = F.Quantity(
        'HeatFlowRate',
        default=(1.0, 'kW'),
        label='Primary channels',
        description='heat flow rate to the primary channels')
    QDotSecondaryChannels = F.Quantity(
        'HeatFlowRate',
        default=(1.0, 'kW'),
        label='Secondary channels',
        description='heat flow rate to the secondary channels')
    QDotExternalChannel = F.Quantity(
        'HeatFlowRate',
        default=(1.0, 'kW'),
        label='External channel',
        description='heat flow rate from the external channel')

    FG = F.FieldGroup(
        [QDotPrimaryChannels, QDotSecondaryChannels, QDotExternalChannel],
        label='Parameters')

    modelBlocks = []
示例#25
0
class Cooler(NumericalModel):
    workingState = F.Choices(OrderedDict((
        (0, 'no'),
        (1, 'yes'),
    )),
                             label='enable cooler',
                             description='enable cooler')

    epsilon = F.Quantity('Efficiency',
                         default=(0., '-'),
                         label='effectiveness',
                         description='effectiveness',
                         show="self.workingState")
    TCooler = F.Quantity('Temperature',
                         default=(0., 'degC'),
                         label='coolant temperature',
                         description='coolant temperature',
                         show="self.workingState")

    FG = F.FieldGroup([workingState, epsilon, TCooler], label='Parameters')

    modelBlocks = []
示例#26
0
class Expansion(ThermodynamicalProcess):
    label = "Expansion"
    description = F.ModelDescription(
        "Parameteric model for expansion process: isentropic and isenthalpic",
        show=True)
    figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/Expansion.svg")
    turbine = F.SubModelGroup(TC.Turbine,
                              'FG',
                              label='Turbine',
                              show="self.processType == 'S'")
    throttleValve = F.SubModelGroup(TC.ThrottleValve, 'FG', show="false")
    processType = F.Choices(options=OrderedDict((
        ('S', 'isentropic'),
        ('H', 'isenthalpic'),
    )),
                            default='S',
                            label="process type")
    processTypeFG = F.FieldGroup([processType], label="Process type")
    inputs = F.SuperGroup(
        ['fluidSource', 'fluidSink', processTypeFG, turbine, throttleValve])

    def __init__(self):
        self.fluidSource.p1 = (10, 'bar')
        self.fluidSource.p2 = (10, 'bar')
        self.fluidSink.p = (1, 'bar')

    def compute(self):
        if (self.processType == 'S'):
            component = self.turbine
        elif (self.processType == 'H'):
            component = self.throttleValve
        self.initCompute(self.fluidSource.fluidName)
        # Connect components
        self.connectPorts(self.fluidSource.outlet, component.inlet)
        self.connectPorts(component.outlet, self.fluidSink.inlet)
        self.fluidSource.compute()
        component.compute(self.fluidSink.p)
        self.postProcess(component)
示例#27
0
class ExternalChannelGeometry(NumericalModel):
    widthAxial = F.Quantity(
        'Length',
        default=(0., 'mm'),
        label='width (axial)',
        description='axial width of the spiral rectangular channel')
    heightRadial = F.Quantity(
        'Length',
        default=(0., 'mm'),
        label='radial height',
        description='radial height of the spiral rectangular channel')
    coilPitch = F.Quantity(
        'Length',
        default=(0., 'mm'),
        label='coil pitch',
        description='coil pitch of the spiral rectangular channel')

    cellSize = F.Quantity(
        'Length',
        default=(0., 'mm'),
        label='mesh cell size',
        description='mesh cell size near the outer block circle')
    meshFineness = F.Integer(
        default=1,
        minValue=1,
        maxValue=10,
        label='mesh fineness',
        description='mesh fineness near the outer side of the block')

    FG = F.FieldGroup([widthAxial, heightRadial, coilPitch, meshFineness],
                      label='Channel geometry')

    modelBlocks = []

    def compute(self, blockDiameter):
        self.averageCoilDiameter = blockDiameter + self.heightRadial
        self.cellSize = self.averageCoilDiameter / (self.meshFineness * 10.)
示例#28
0
class FluidFlowInput(NumericalModel):
    fluidName = F.Choices(Fluids, default='ParaHydrogen', label='fluid')
    flowRateChoice = F.Choices(OrderedDict((
        ('V', 'volume'),
        ('m', 'mass'),
    )),
                               label='flow rate based on')
    mDot = F.Quantity('MassFlowRate',
                      minValue=(0, 'kg/h'),
                      default=(1., 'kg/h'),
                      label='mass flow',
                      description='mass flow rate',
                      show='self.flowRateChoice == "m"')
    VDot = F.Quantity('VolumetricFlowRate',
                      minValue=(0., 'm**3/h'),
                      default=(1., 'm**3/h'),
                      label='volume flow',
                      description='volume flow rate',
                      show='self.flowRateChoice == "V"')
    T = F.Quantity('Temperature', default=(300., 'K'), label='temperature')
    p = F.Quantity('Pressure', default=(1., 'bar'), label='pressure')
    FG = F.FieldGroup([fluidName, flowRateChoice, mDot, VDot, T, p],
                      label='Parameters')

    modelBlocks = []

    def createFluidState(self):
        return CP.FluidState(self.fluidName)

    def compute(self):
        self.fState = self.createFluidState()
        self.fState.update_Tp(self.T, self.p)
        if (self.flowRateChoice == 'm'):
            self.VDot = self.mDot / self.fState.rho
        else:
            self.mDot = self.VDot * self.fState.rho
示例#29
0
class FluidFlowOutput(NumericalModel):
    VDot = F.Quantity('VolumetricFlowRate',
                      minValue=(0., 'm**3/h'),
                      default=(1., 'm**3/h'),
                      label='volume flow',
                      description='volume flow rate')
    mDot = F.Quantity('MassFlowRate',
                      minValue=(0, 'kg/h'),
                      default=(1., 'kg/h'),
                      label='mass flow',
                      description='mass flow rate')
    T = F.Quantity('Temperature', default=(300., 'K'), label='temperature')
    p = F.Quantity('Pressure', default=(1., 'bar'), label='pressure')

    FG = F.FieldGroup([mDot, VDot, T, p], label='Parameters')

    modelBlocks = []

    def compute(self, fState, mDot):
        self.fState = fState
        self.T = fState.T
        self.p = fState.p
        self.mDot = mDot
        self.VDot = mDot / fState.rho
示例#30
0
class ThermodynamicalProcessTwoStreams(ThermodynamicalCycle):
    ############# Inputs #############
    fluidSource1 = F.SubModelGroup(TC.FluidSource, 'FG', label='Inlet 1')
    fluidSource2 = F.SubModelGroup(TC.FluidSource, 'FG', label='Inlet 2')
    fluidSink1 = F.SubModelGroup(TC.FluidSink, 'FG', label='Outlet 1')
    fluidSink2 = F.SubModelGroup(TC.FluidSink, 'FG', label='Outlet 2')
    inputs = F.SuperGroup([fluidSource1, fluidSource2, fluidSink1, fluidSink2])

    # Model View
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs],
                            autoFetch=True)

    ############# Results #############
    QDot = F.Quantity('HeatFlowRate',
                      default=(0, 'kW'),
                      label='heat flow rate in')
    NTU = F.Quantity(label='NTU')
    Cr = F.Quantity(label='capacity ratio')
    energyResults = F.FieldGroup([QDot, NTU, Cr], label="Energy")
    energyBalanceResults = F.SuperGroup([energyResults],
                                        label="Energy balance")

    # Model View
    resultView = F.ModelView(
        ioType="output", superGroups=['resultStates', energyBalanceResults])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    ############# Methods ###############
    def postProcess(self, component):
        super(ThermodynamicalProcessTwoStreams, self).postProcess(300)
        self.QDot = component.QDot
        self.NTU = component.NTU
        self.Cr = component.Cr