Beispiel #1
0
def Compressor(**kwargs):

    recip=PURecip()                     #Instantiate the model
    recip.Vdead = 0.5e-6                #Dead volume [m3]
    recip.Vdisp = 8e-6                  #Displacement/rev [m3]
    recip.omega = 377                   #Frequency, rad/sec (60Hz)

    recip.d_discharge=0.0059;           #discharge port diameter [m]
    recip.d_suction=recip.d_discharge;  #suction diameter [m]
    recip.A_discharge=pi*recip.d_discharge**2/4
    recip.A_suction=pi*recip.d_suction**2/4
        
    #These are parameters needed for the ambient heat transfer model
    recip.h_shell = 0.010               #[kW/m2/K]
    recip.A_shell = pi*10*2*(0.0254**2) #[m2]
    recip.Tamb = 298                    #[K] 
    
    #Parameters for the mechanical losses model (simplified)
    recip.Wdot_parasitic = 0.01         #Parasitic losses [kW]
    
    Ref='Air'
    inletState=State.State(Ref,dict(T=298.15, P=101.325))
    outletState=State.State(Ref,{'T':400,'P':inletState.p*4})
    mdot_guess = inletState.rho*recip.Vdisp*recip.omega/(2*pi)
    
    #First add the control volumes.
    recip.add_CV( ControlVolume(key='A',
                               initialState=outletState.copy(),
                               VdVFcn=recip.V_dV,
                               becomes='A') )
    
    #Add the inlet tube
    recip.add_tube( Tube(key1='inlet.1',key2='inlet.2',L=0.03,ID=0.01,
                         mdot=mdot_guess, State1=inletState.copy(),
                         fixed=1,TubeFcn=recip.TubeCode) )
    
    #Add the outlet tube
    recip.add_tube( Tube(key1='outlet.1',key2='outlet.2',L=0.03,ID=0.01,
                         mdot=mdot_guess, State2=outletState.copy(),
                         fixed=2,TubeFcn=recip.TubeCode) )
    
    #Add the flow paths that link flow nodes together
    recip.add_flow(FlowPath(key1='inlet.2',key2='A',MdotFcn=recip.Suction))
    recip.add_flow(FlowPath(key1='outlet.1',key2='A',MdotFcn=recip.Discharge))
    
    recip.connect_callbacks(endcycle_callback=recip.endcycle_callback, # Provided by PDSimCore
                            heat_transfer_callback=recip.heat_transfer_callback,
                            lumps_energy_balance_callback = recip.lump_energy_balance_callback
                            )
    
    t1=clock()
    recip.solve(key_inlet='inlet.1',
                key_outlet='outlet.2',
                solver_method = kwargs.get('solver_method', 'Euler'),
                OneCycle = False,
                UseNR = False
                )
    print('time taken',clock()-t1,'s')
Beispiel #2
0
def Compressor():
    recip = Recip()

    recip.piston_stroke = 0.02  #Piston stroke, m
    recip.piston_diameter = 0.02  #Piston diameter, m
    recip.piston_length = 0.02  #Piston Length, m
    recip.omega = 377  #Frequency, rad/sec (60Hz)
    recip.crank_length = 0.01  #length of crank, m
    recip.connecting_rod_length = 0.04  #length of connecting rod, m
    recip.x_TDC = 0.003  #Distance to the TDC position of the piston from the valve plate

    recip.d_discharge = 0.0059
    #discharge port diameter in meters
    recip.d_suction = recip.d_discharge
    #suction diameter in meters

    #These are parameters needed for the ambient heat transfer model
    recip.h_shell = 0.010  #[kW/m2/K]
    recip.A_shell = pi * 10 * 2 * (0.0254**2)  #[m2]
    recip.Tamb = 298  #[K]

    recip.mu_oil = 0.0086
    recip.delta_gap = 10e-6
    recip.eta_motor = 0.95

    recip.shell_volume = 100e-6
    #Calculate Vdisp
    recip.pre_solve()
    recip.Vdisp = recip.Vdisp()

    Ref = 'R410A'
    inletState = State.State(Ref, dict(T=289.15, D=33.1))
    p_outlet = inletState.p * 2.5
    T2s = recip.guess_outlet_temp(inletState, p_outlet)
    outletState = State.State(Ref, {'T': T2s, 'P': p_outlet})
    mdot_guess = inletState.rho * recip.Vdisp * recip.omega / (2 * pi)

    #First add the control volumes.
    recip.add_CV(
        ControlVolume(key='A',
                      initialState=outletState.copy(),
                      VdVFcn=recip.V_dV,
                      becomes='A'))
    recip.add_CV(
        ControlVolume(key='shell',
                      initialState=inletState.copy(),
                      VdVFcn=recip.V_shell,
                      becomes='shell'))

    recip.add_tube(
        Tube(key1='inlet.1',
             key2='inlet.2',
             L=0.03,
             ID=0.02,
             mdot=mdot_guess,
             State1=inletState.copy(),
             fixed=1,
             TubeFcn=recip.TubeCode))
    recip.add_tube(
        Tube(key1='outlet.1',
             key2='outlet.2',
             L=0.03,
             ID=0.02,
             mdot=mdot_guess,
             State2=outletState.copy(),
             fixed=2,
             TubeFcn=recip.TubeCode))

    recip.add_flow(FlowPath(key1='shell', key2='inlet.2', MdotFcn=recip.Inlet))
    recip.add_flow(FlowPath(key1='inlet.2', key2='A', MdotFcn=recip.Suction))
    recip.add_flow(FlowPath(key1='outlet.1', key2='A',
                            MdotFcn=recip.Discharge))
    recip.add_flow(
        FlowPath(key1='shell', key2='A', MdotFcn=recip.PistonLeakage))

    E = 1.93e11  # Youngs Modulus, [Pa]
    h_valve = 0.0001532  # Valve thickness, [m]
    l_valve = 0.018  # Total length of valve, [m]
    a_valve = 0.0140  # Distance from anchor to force, [m]
    rho_valve = 8000  # Density of spring steel, [kg/m^3]
    C_D = 1.17  # Drag coefficient [-]
    d_valve = 0.007  # Valve Diameter [m]
    x_stopper = 0.0018  # Stopper location [m]

    I = (d_valve * h_valve**3) / 12  # Moment of Inertia for valve, [m^4]
    k_valve = (6 * E * I) / (a_valve**2 *
                             (3 * l_valve - a_valve))  # Valve stiffness
    m_eff = (
        1 / 3
    ) * rho_valve * l_valve * d_valve * h_valve  # Effective mass of valve reeds, [kg]
    x_tr_suction = 0.25 * (recip.d_suction**2 / d_valve)
    x_tr_discharge = 0.25 * (recip.d_discharge**2 / d_valve)

    #The suction valve parameters
    recip.suction_valve = ValveModel(d_valve=d_valve,
                                     d_port=recip.d_suction,
                                     C_D=C_D,
                                     rho_valve=rho_valve,
                                     x_stopper=x_stopper,
                                     m_eff=m_eff,
                                     k_valve=k_valve,
                                     x_tr=x_tr_suction,
                                     key_up='inlet.2',
                                     key_down='A')
    recip.add_valve(recip.suction_valve)

    #The discharge valve parameters
    recip.discharge_valve = ValveModel(d_valve=d_valve,
                                       d_port=recip.d_discharge,
                                       C_D=C_D,
                                       rho_valve=rho_valve,
                                       x_stopper=x_stopper,
                                       m_eff=m_eff,
                                       k_valve=k_valve,
                                       x_tr=x_tr_discharge,
                                       key_up='A',
                                       key_down='outlet.1')
    recip.add_valve(recip.discharge_valve)

    recip.connect_callbacks(
        endcycle_callback=recip.endcycle_callback,
        heat_transfer_callback=recip.heat_transfer_callback,
        lumps_energy_balance_callback=recip.lump_energy_balance_callback)

    t1 = timeit.default_timer()
    recip.solve(key_inlet='inlet.1',
                key_outlet='outlet.2',
                solver_method='RK45',
                OneCycle=False,
                UseNR=True,
                eps_cycle=3e-2,
                eps_energy_balance=3e-2)
    print('time taken', timeit.default_timer() - t1)

    if plotting:
        debug_plots(recip, family='Recip Compressor')

    del recip.FlowStorage
    from PDSim.misc.hdf5 import HDF5Writer
    h5 = HDF5Writer()
    h5.write_to_file(recip, 'recipsample.h5')
Beispiel #3
0
def Expander(**kwargs):

    expander = PistonExpander()  #Instantiate the class

    Ref = 'Nitrogen'
    inletState = State.State(Ref, dict(T=298.15, P=501.325))
    outletState = State.State(Ref, dict(T=200, P=inletState.p / 10))
    mdot_guess = inletState.rho * expander.Vdisp * expander.omega / (2 * pi)

    #First add the control volume.
    expander.add_CV(
        ControlVolume(
            key='A',
            initialState=inletState.copy(),
            VdVFcn=expander.V_dV,
        ))

    #These are parameters needed for the ambient heat transfer model
    expander.h_shell = 0.010  #[kW/m2/K]
    expander.A_shell = pi * 10 * 2 * (0.0254**2)  #[m2]
    expander.Tamb = 298  #[K]

    #Parameters for the mechanical losses model (simplified)
    expander.Wdot_parasitic = 0.01  #Parasitic losses [kW]

    #Add the inlet tube
    expander.add_tube(
        Tube(key1='inlet.1',
             key2='inlet.2',
             L=0.03,
             ID=0.01,
             mdot=mdot_guess,
             State1=inletState.copy(),
             fixed=1,
             TubeFcn=expander.TubeCode))

    #Add the outlet tube
    expander.add_tube(
        Tube(key1='outlet.1',
             key2='outlet.2',
             L=0.03,
             ID=0.01,
             mdot=mdot_guess,
             State2=outletState.copy(),
             fixed=2,
             TubeFcn=expander.TubeCode))

    #Add the flow paths that link flow nodes together
    expander.add_flow(
        FlowPath(key1='inlet.2', key2='A', MdotFcn=expander.Suction))
    expander.add_flow(
        FlowPath(key1='outlet.1', key2='A', MdotFcn=expander.Discharge))

    t1 = clock()
    expander.EulerN = 4000
    expander.RK45_eps = 1e-10
    expander.connect_callbacks(
        step_callback=expander.step_callback,
        endcycle_callback=expander.endcycle_callback,  # Provided by PDSimCore
        heat_transfer_callback=expander.heat_transfer_callback,
        lumps_energy_balance_callback=expander.lump_energy_balance_callback)
    expander.solve(key_inlet='inlet.1',
                   key_outlet='outlet.2',
                   solver_method=kwargs.get('solver_method', 'Euler'),
                   OneCycle=False,
                   UseNR=True,
                   plot_every_cycle=False)
    print('time taken', clock() - t1, 's')
Beispiel #4
0
    def auto_add_CVs(self,inletState,outletState):
        """
        Adds all the control volumes for the scroll expander.
        
        Parameters
        ----------
        inletState
            A :class:`State <CoolProp.State.State>` instance for the inlet to the scroll set.  Can be approximate
        outletState
            A :class:`State <CoolProp.State.State>` instance for the outlet to the scroll set.  Can be approximate
            
        Notes
        -----
        Uses the indices of 
        
        ============= ===================================================================
        CV            Description
        ============= ===================================================================
        ``da``        Discharge Area
        ``d1``        Discharge chamber on side 1
        ``d2``        Discharge chamber on side 2
        ``s1``        Suction chamber on side 1
        ``s2``        Suction chamber on side 2
        ``ss``        Central suction chamber
        ``sss``       Merged suction chamber
        ``e1.i``      The i-th expansion chamber on side 1 (i=1 for outermost chamber)
        ``e2.i``      The i-th expansion chamber on side 2 (i=1 for outermost chamber)
        ============= ===================================================================
        """
        
        #Add all the control volumes that are easy.  Suction area and suction chambers
        self.add_CV(ControlVolume(key='da', initialState = outletState.copy(),
                                VdVFcn=self.V_da))
        self.add_CV(ControlVolume(key='d1', initialState = outletState.copy(),
                                VdVFcn=self.V_d1,becomes='none'))
        self.add_CV(ControlVolume(key='d2', initialState = outletState.copy(),
                                VdVFcn=self.V_d2,becomes='none'))
        
        #Discharge chambers are also easy.  Assume that you start with 'ddd' chamber merged.
        # No problem if this isn't true.
        self.add_CV(ControlVolume(key = 's1', initialState = inletState.copy(),
                                  VdVFcn = self.V_s1, exists = False, discharge_becomes = 'e1.'+str(scroll_geo.nC_Max(self.geo))))
        self.add_CV(ControlVolume(key = 's2', initialState = inletState.copy(),
                                  VdVFcn = self.V_s2, exists = False, discharge_becomes = 'e2.'+str(scroll_geo.nC_Max(self.geo))))
        self.add_CV(ControlVolume(key = 'ss', initialState = inletState.copy(),
                                  VdVFcn = self.V_ss, exists = False, discharge_becomes = 'sss'))
        self.add_CV(ControlVolume(key = 'sss', initialState = inletState.copy(),
                                  VdVFcn = self.V_sss))

        #Add each pair of expansion chambers
        nCmax = scroll_geo.nC_Max(self.geo)
        # Must have at least one pair
        assert (nCmax>=1)
        
        # Innermost pair at nCmax - 1 starts at inlet state
        
        for alpha in range(nCmax,0,-1): 
            keye1 = 'e1.'+str(alpha)
            keye2 = 'e2.'+str(alpha)
            if alpha == nCmax:
                #It is the outermost pair of compression chambers
                initState = CPState(inletState.Fluid,
                                        dict(T=inletState.T,
                                             D=inletState.rho)
                                        )
            else:
                #It is not the first CV, more involved analysis
                #Assume isentropic compression from the inlet state at the end of the suction process
                T1 = inletState.T
                s1 = inletState.s
                rho1 = inletState.rho
                V1 = self.V_sss(2*pi-self.theta_d-1e-14)[0]
                V2 = self.V_e1(0, alpha)[0]*2
                # Mass is constant, so rho1*V1 = rho2*V2
                rho2 = rho1 * V1 / V2
                # Now don't know temperature or pressure, but you can assume
                # it is isentropic to find the temperature
                T2 = optimize.newton(lambda T: PropsSI('S','T',T,'D',rho2,inletState.Fluid)-s1*1000, T1)
                initState = CPState(inletState.Fluid,dict(T=T2,D=rho2)).copy()
            
            # Expansion chambers do not change definition at discharge angle
            disc_becomes_e1 = keye1
            disc_becomes_e2 = keye2
            
            if alpha > 1:
                exists = False # Starts out not being in existence, comes into 
                               # existence at the discharge angle
            else:
                exists = True 
                               
            if alpha == nCmax:
                # It is the innermost pair of chambers, becomes a discharge
                # chamber at the end of the rotation
                becomes_e1 = 'e1.'+str(alpha-1)
                becomes_e2 = 'e2.'+str(alpha-1)
            else:
                # It is not the innermost pair of chambers, becomes another 
                # set of compression chambers at the end of the rotation
                becomes_e1 = 'd1'
                becomes_e2 = 'd2'
                               
            self.add_CV(ControlVolume(key = keye1,
                                      initialState = initState.copy(),
                                      VdVFcn = self.V_e1,
                                      VdVFcn_kwargs = {'alpha':alpha},
                                      discharge_becomes = disc_becomes_e1,
                                      becomes = becomes_e1,
                                      exists = exists))
            
            self.add_CV(ControlVolume(key = keye2,
                                      initialState = initState.copy(),
                                      VdVFcn = self.V_e2,
                                      VdVFcn_kwargs = {'alpha':alpha},
                                      discharge_becomes = disc_becomes_e2,
                                      becomes = becomes_e2,
                                      exists = exists))
def Compressor(**kwargs):

    recip = PURecip()  #Instantiate the model
    recip.Vdead = 8e-8  #Dead volume [m3]
    recip.Vdisp = 8e-6  #Displacement/rev [m3]
    recip.omega = 377  #Frequency, rad/sec (60Hz)
    recip.d_discharge = 0.0059
    #Discharge port diameter [m]
    recip.d_suction = recip.d_discharge
    #Suction diameter [m]
    recip.A_discharge = pi * recip.d_discharge**2 / 4
    recip.A_suction = pi * recip.d_suction**2 / 4
    recip.RK45_eps = 1e-8
    recip.h_shell = 0.010  #[kW/m2/K]
    recip.A_shell = pi * 10 * 2 * (0.0254**2)  #[m2]
    recip.Tamb = 293  #[K]
    recip.plot_names = 'recip_plot_buttons'
    recip.Wdot_parasitic = 0  #Parasitic losses [kW]
    Ref = 'R134a'
    inletState = State.State(Ref, dict(T=293.15, D=23.75))

    outletState = State.State(Ref, {'T': 400, 'P': inletState.p * 2.5})
    mdot_guess = inletState.rho * recip.Vdisp * recip.omega / (2 * pi)

    #First add the control volumes.
    recip.add_CV(
        ControlVolume(key='A',
                      initialState=outletState.copy(),
                      VdVFcn=recip.V_dV,
                      becomes='A'))

    #Add the inlet tube
    recip.add_tube(
        Tube(key1='inlet.1',
             key2='inlet.2',
             L=0.03,
             ID=0.01,
             mdot=mdot_guess,
             State1=inletState.copy(),
             fixed=1,
             TubeFcn=recip.TubeCode))

    #Add the outlet tube
    recip.add_tube(
        Tube(key1='outlet.1',
             key2='outlet.2',
             L=0.03,
             ID=0.01,
             mdot=mdot_guess,
             State2=outletState.copy(),
             fixed=2,
             TubeFcn=recip.TubeCode))

    #Add the flow paths that link flow nodes together
    recip.add_flow(FlowPath(key1='inlet.2', key2='A', MdotFcn=recip.Suction))

    recip.add_flow(FlowPath(key1='outlet.1', key2='A',
                            MdotFcn=recip.Discharge))

    E = 1.93e11  #Youngs Modulus, [Pa]
    h_valve = 0.0001532  #Valve thickness, [m]
    l_valve = 0.018  #Total length of valve, [m]
    a_valve = 0.0140  #Distance from anchor to force, [m]
    rho_valve = 8000  #Density of spring steel, [kg/m^3]
    C_D = 1.17  #Drag coefficient [-]
    d_valve = 0.0059  #Valve Diameter [m]
    x_stopper = 0.0018  #Stopper location [m]

    I = (d_valve * h_valve**3) / 12  #Moment of Intertia for valve,[m^4]
    k_valve = (6 * E * I) / (a_valve**2 *
                             (3 * l_valve - a_valve))  #Valve stiffness
    m_eff = (
        1 / 3
    ) * rho_valve * l_valve * d_valve * h_valve  #Effective mass of valve reeds
    x_tr_suction = 0.25 * (recip.d_suction**2 / d_valve)
    x_tr_discharge = 0.25 * (recip.d_discharge**2 / d_valve)

    #The suction valve parameters
    recip.suction_valve = ValveModel(d_valve=d_valve,
                                     d_port=recip.d_suction,
                                     C_D=C_D,
                                     rho_valve=rho_valve,
                                     x_stopper=x_stopper,
                                     m_eff=m_eff,
                                     k_valve=k_valve,
                                     x_tr=x_tr_suction,
                                     key_up='inlet.2',
                                     key_down='A')
    recip.add_valve(recip.suction_valve)

    #The discharge valve parameters
    recip.discharge_valve = ValveModel(d_valve=d_valve,
                                       d_port=recip.d_discharge,
                                       C_D=C_D,
                                       rho_valve=rho_valve,
                                       x_stopper=x_stopper,
                                       m_eff=m_eff,
                                       k_valve=k_valve,
                                       x_tr=x_tr_discharge,
                                       key_up='A',
                                       key_down='outlet.1')
    recip.add_valve(recip.discharge_valve)

    recip.connect_callbacks(
        endcycle_callback=recip.endcycle_callback,  # Provided by PDSimCore
        heat_transfer_callback=recip.heat_transfer_callback,
        lumps_energy_balance_callback=recip.lump_energy_balance_callback)

    t1 = clock()
    recip.precond_solve(
        key_inlet='inlet.1',
        key_outlet='outlet.2',
        solver_method='RK45',
        OneCycle=False,
        UseNR=True,
    )
    print('time taken', clock() - t1)
    debug_plots(recip)
    del recip.FlowStorage
    # from PDSim.plot.plots import debug_plots
    # debug_plots(recip)
    return recip
Beispiel #6
0
def Compressor(ScrollClass,
               *,
               Te=273,
               Tc=300,
               OneCycle=False,
               Ref='R410A',
               HDF5file='scroll_compressor_disc.h5',
               Nports=4):

    ScrollComp = ScrollClass()
    #This runs if the module code is run directly

    ScrollComp.set_scroll_geo(83e-6, 3.3, 0.005,
                              0.006)  #Set the scroll wrap geometry
    ScrollComp.set_disc_geo('2Arc', r2=0)
    ScrollComp.geo.delta_flank = 10e-6
    ScrollComp.geo.delta_radial = 10e-6

    ScrollComp.geo.delta_suction_offset = 0.0e-3
    ScrollComp.geo.phi_ie_offset = 0.0

    ScrollComp.omega = 3000 / 60 * 2 * pi
    ScrollComp.Tamb = 298.0

    # Temporarily set the bearing dimensions
    ScrollComp.mech = struct()
    ScrollComp.mech.D_upper_bearing = 0.04
    ScrollComp.mech.L_upper_bearing = 0.04
    ScrollComp.mech.c_upper_bearing = 20e-6
    ScrollComp.mech.D_crank_bearing = 0.04
    ScrollComp.mech.L_crank_bearing = 0.04
    ScrollComp.mech.c_crank_bearing = 20e-6
    ScrollComp.mech.D_lower_bearing = 0.025
    ScrollComp.mech.L_lower_bearing = 0.025
    ScrollComp.mech.c_lower_bearing = 20e-6
    ScrollComp.mech.thrust_ID = 0.05
    ScrollComp.mech.thrust_friction_coefficient = 0.028  # From Chen thesis
    ScrollComp.mech.orbiting_scroll_mass = 2.5
    ScrollComp.mech.L_ratio_bearings = 3
    ScrollComp.mech.mu_oil = 0.008

    ScrollComp.h_shell = 0.02  # kW/m^2/K
    ScrollComp.A_shell = 0.05  # m^2
    ScrollComp.HTC = 0.050  # Heat transfer coefficient between scroll and gas in chambers, in kW/m^2/K

    ScrollComp.motor = Motor()
    ScrollComp.motor.set_eta(0.9)
    ScrollComp.motor.suction_fraction = 1.0

    Tin = Te + 11.1
    temp = State.State(Ref, {'T': Te, 'Q': 1})
    pe = temp.p
    temp.update(dict(T=Tc, Q=1))
    pc = temp.p
    inletState = State.State(Ref, {'T': Tin, 'P': pe})

    T2s = ScrollComp.guess_outlet_temp(inletState, pc)
    outletState = State.State(Ref, {'T': T2s, 'P': pc})

    mdot_guess = inletState.rho * ScrollComp.Vdisp * ScrollComp.omega / (2 *
                                                                         pi)

    ScrollComp.add_tube(
        Tube(key1='inlet.1',
             key2='inlet.2',
             L=0.3,
             ID=0.02,
             mdot=mdot_guess,
             State1=inletState.copy(),
             fixed=1,
             TubeFcn=ScrollComp.TubeCode))
    ScrollComp.add_tube(
        Tube(key1='outlet.1',
             key2='outlet.2',
             L=0.3,
             ID=0.02,
             mdot=mdot_guess,
             State2=outletState.copy(),
             fixed=2,
             TubeFcn=ScrollComp.TubeCode))

    ScrollComp.auto_add_CVs(inletState, outletState)
    ScrollComp.add_CV(
        ControlVolume(
            key='discplenum',
            initialState=outletState.copy(),
            VdVFcn=lambda theta:
            (1e-4, 0
             )  # Constant volume, outputs of function are volume, dV/dtheta
        ))

    ScrollComp.auto_add_leakage(flankFunc=ScrollComp.FlankLeakage,
                                radialFunc=ScrollComp.RadialLeakage)

    FP = FlowPath(
        key1='inlet.2',
        key2='sa',
        MdotFcn=IsentropicNozzleWrapper(),
    )
    FP.A = pi * 0.01**2 / 4
    ScrollComp.add_flow(FP)
    FP = FlowPath(
        key1='outlet.1',
        key2='discplenum',
        MdotFcn=IsentropicNozzleWrapper(),
    )
    FP.A = pi * 0.01**2 / 4
    ScrollComp.add_flow(FP)

    ScrollComp.add_flow(
        FlowPath(key1='sa',
                 key2='s1',
                 MdotFcn=ScrollComp.SA_S1,
                 MdotFcn_kwargs=dict(X_d=0.7)))
    ScrollComp.add_flow(
        FlowPath(key1='sa',
                 key2='s2',
                 MdotFcn=ScrollComp.SA_S2,
                 MdotFcn_kwargs=dict(X_d=0.7)))

    ScrollComp.add_flow(
        FlowPath(key1='discplenum',
                 key2='dd',
                 MdotFcn=ScrollComp.DISC_DD,
                 MdotFcn_kwargs=dict(X_d=0.7)))

    ScrollComp.add_flow(
        FlowPath(key1='discplenum',
                 key2='ddd',
                 MdotFcn=ScrollComp.DISC_DD,
                 MdotFcn_kwargs=dict(X_d=0.7)))
    #     ScrollComp.add_flow(FlowPath(key1 = 'outlet.1',
    #                                  key2 = 'd1',
    #                                  MdotFcn = ScrollComp.DISC_D1,
    #                                  MdotFcn_kwargs = dict(X_d = 0.7)
    #                                  )
    #                         )
    #
    #     FP = FlowPath(key1='outlet.1',
    #                   key2='dd',
    #                   MdotFcn=IsentropicNozzleWrapper(),
    #                   )
    #     FP.A = pi*0.006**2/4
    #     ScrollComp.add_flow(FP)
    #
    #     FP = FlowPath(key1='outlet.1',
    #                   key2='ddd',
    #                   MdotFcn=IsentropicNozzleWrapper(),
    #                   )
    #     FP.A = pi*0.006**2/4
    #     ScrollComp.add_flow(FP)

    # ***************
    # Discharge Ports
    # ***************

    sim = ScrollComp
    for involute in ['i', 'o']:

        # Define the parameters for the ports
        if involute == 'i':
            phi_list = np.linspace(sim.geo.phi_fie - 2 * np.pi - 0.1,
                                   sim.geo.phi_fis + np.pi / 2, Nports)
        elif involute == 'o':
            phi_list = np.linspace(sim.geo.phi_foe - 2 * np.pi - 0.1,
                                   sim.geo.phi_fos + np.pi / 2, Nports)
        else:
            raise ValueError(involute)
        involute_list = [involute] * len(phi_list)
        D_list = [sim.geo.t] * len(
            phi_list)  # All ports are thickness of scroll in diameter
        offset_list = [
            d * 0.5 for d in D_list
        ]  # Distance of translation of center of port normal to wall
        X_d_list = [1.0] * len(phi_list)  # Flow coefficient for forward flow
        X_d_backflow_list = [0.0] * len(phi_list)  # Backflow coefficient

        # Add the ports to the model
        sim.fixed_scroll_ports = []
        for i in range(Nports):
            p = Port()
            p.phi = phi_list[i]
            p.involute = involute_list[i]
            p.offset = offset_list[i]
            p.D = D_list[i]
            p.parent = 'discplenum'
            p.X_d = X_d_list[i]
            p.X_d_backflow = X_d_backflow_list[i]
            sim.fixed_scroll_ports.append(p)

        # Calculate the areas between each port and every control volume
        #
        # Can turn on plotting (plot=True) to see the flow areas.
        sim.calculate_port_areas(plot=False)

        # Iterate over the ports, connecting them to discharge plenum
        for port in sim.fixed_scroll_ports:

            # Iterate over the chambers each port is connected to at least
            # at some point
            for partner in port.area_dict:

                # Create a spline interpolator object for the area between port and the partner chamber
                A_interpolator = interp.splrep(port.theta,
                                               port.area_dict[partner],
                                               k=2,
                                               s=0)

                # Add the flow path connecting the working chamber and discharge plenum
                #
                # It is a simplified nozzle model, allowing for flow out the nozzle,
                # according to the flow area at the given crank angle, but no backflow.
                # This represents an idealized case.
                sim.add_flow(
                    FlowPath(key1='discplenum',
                             key2=partner,
                             MdotFcn=sim.INTERPOLATING_NOZZLE_FLOW,
                             MdotFcn_kwargs=dict(
                                 X_d=port.X_d,
                                 X_d_backflow=port.X_d_backflow,
                                 upstream_key=partner,
                                 A_interpolator=A_interpolator)))

    ScrollComp.add_flow(
        FlowPath(key1='d1', key2='dd', MdotFcn=ScrollComp.D_to_DD))
    ScrollComp.add_flow(
        FlowPath(key1='d2', key2='dd', MdotFcn=ScrollComp.D_to_DD))

    #Connect the callbacks for the step, endcycle, heat transfer and lump energy balance
    ScrollComp.connect_callbacks(
        step_callback=ScrollComp.step_callback,
        endcycle_callback=ScrollComp.endcycle_callback,
        heat_transfer_callback=ScrollComp.heat_transfer_callback,
        lumps_energy_balance_callback=ScrollComp.lump_energy_balance_callback)

    t1 = timeit.default_timer()
    ScrollComp.RK45_eps = 1e-6
    ScrollComp.eps_cycle = 3e-3
    try:
        ScrollComp.solve(
            key_inlet='inlet.1',
            key_outlet='outlet.2',
            solver_method='RK45',
            OneCycle=OneCycle,
            plot_every_cycle=False,
            #hmin = 1e-3
            eps_cycle=3e-3)
    except BaseException as E:
        print(E)
        raise

    print('time taken', timeit.default_timer() - t1)

    del ScrollComp.FlowStorage
    from PDSim.misc.hdf5 import HDF5Writer
    h5 = HDF5Writer()
    h5.write_to_file(ScrollComp, HDF5file)

    if '--plot' in sys.argv:
        debug_plots(ScrollComp, family='Scroll Compressor')

    return ScrollComp