Piston expanderΒΆ

This example explains how to use properly PDSim to simulate a piston expander. The same methodology can be readily applied to other positive displacement machines.

## COMMON IMPORTS ##
from __future__ import division, print_function
#from __future__ import division
from math import pi, cos, sin
from time import clock
import os, sys
import matplotlib.pyplot as plt, numpy as np
%matplotlib inline
#From PDSim we import the different elements that allows us to built a positive displacement simulation code.
from PDSim.flow.flow import FlowPath
from PDSim.flow import flow_models
from PDSim.misc.datatypes import empty_arraym
from PDSim.core.containers import ControlVolume, Tube
from PDSim.core.core import PDSimCore
from PDSim.plot.plots import debug_plots
# We need also to import CoolProp as property library to define suction and discharge states of the expander
# (or compressor).
from CoolProp import State
from CoolProp import CoolProp as CP
# We create a class derived from PDSimCore that holds the piston expander model

class PistonExpander(PDSimCore):

    #: Displacement of the cylinder above the dead volume [m^3]
    Vdisp = 20e-6

    #: Dead volume of the cylinder at TDC [m^3]
    Vdead = 3e-6

    #: Rotational speed [rad/s]
    omega = 377

    def __init__(self):
        #Initialize the base class that PistonExpander is derived from
        PDSimCore.__init__(self)

    # We define the working chamber volume as function of the crank angle and its derivative.
    # In this case we assume a simplified mathematical formulation
    def V_dV(self, theta):

        V = self.Vdead+self.Vdisp/2*(1-cos(theta))
        dVdtheta = self.Vdisp/2*sin(theta)
        return V, dVdtheta

    # We define the suction and discharge port area profiles as well as the flow model through such ports.
    def Suction(self, FlowPath):
        if 0 <= self.theta <= pi/4:
            FlowPath.A = pi*0.006**2/4*(1-cos(8*self.theta))/2
            mdot = flow_models.IsentropicNozzle(FlowPath.A,
                                                FlowPath.State_up,
                                                FlowPath.State_down)
        else:
            FlowPath.A = 0.0
            mdot = 0
        return mdot

    def Discharge(self, FlowPath):
        if pi <= self.theta <= 7*pi/4:
            FlowPath.A = pi*0.006**2/4*(1-cos(4*self.theta))/2
            mdot = flow_models.IsentropicNozzle(FlowPath.A,
                                            FlowPath.State_up,
                                            FlowPath.State_down)
        else:
            FlowPath.A = 0.0
            mdot = 0
        return mdot

    # We define a tube flow model to connect the inlet of the expander shell with the actual suction port.
    # Similar model is applied on the discharge side.
    def TubeCode(self, Tube):

        Tube.Q = flow_models.IsothermalWallTube(Tube.mdot,
                                                Tube.State1,
                                                Tube.State2,
                                                Tube.fixed,
                                                Tube.L,
                                                Tube.ID,
                                                T_wall = self.Tlumps[0])

    # In this case we neglect the in-chamber heat transfer which eventually can be added
    # depending on the type of machine
    def heat_transfer_callback(self, theta):
        return empty_arraym(self.CVs.N)

    # We also neglect the mechanical losses for simplicity
    def mechanical_losses(self):
        return 0

    # We define the heat transfer between the expander shell and the ambient by defining
    # a constant heat transfer coefficient
    def ambient_heat_transfer(self):
        return self.h_shell*self.A_shell*(self.Tamb-self.Tlumps[0]) #[kW]

    # At this point we are able to define an overall energy balance of the expander shell
    # with a single lumped temperature
    def lump_energy_balance_callback(self):

        #Mechanical losses are added to the lump
        self.Wdot_mechanical = self.mechanical_losses() #[kW]
        #Heat transfer between the shell and the ambient
        self.Qamb = self.ambient_heat_transfer() #[kW]
        return self.Wdot_mechanical + self.Qamb

    # Callback function for the stepsize of the solver
    def step_callback(self,theta,h,Itheta):
        self.theta = theta
        return False, h
# We have completely defined the class that hold the general piston expander model.
# Now we can actually define a function to run the model
def Expander():

    expander = PistonExpander() #Instantiate the class

    # We specify the working fluid, the inlet state conditions (temperature and pressure in this case),
    # the outlet state for which the the pressure is specified and the temperature is guessed.
    # Last, we need to provide a guess for the inlet mass flow rate. The model calculate the actual
    # mass flow rate through the machine as well as the discharge temperature.
    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)

    # The piston expander has only one working chamber and therefore we add one control volume
    expander.add_CV(ControlVolume(key='A',
                                  initialState=inletState.copy(),
                                  VdVFcn=expander.V_dV,)
                    )

    # We define the necessary constants for ambient heat transfer
    expander.h_shell = 0.010               #[kW/m2/K]
    expander.A_shell = pi*10*2*(0.0254**2) #[m2]
    expander.Tamb = 298                    #[K]
    expander.Wdot_parasitic = 0.01         #Parasitic losses [kW]

    """
    We add the inlet and outlet tubes. The states of the tube are defines as:

            inlet tube:
            __________________
     inlet.1                    inlet.2
            __________________


            outlet tube:
            __________________
    outlet.2                   outlet.1
            __________________
    """
    #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)
                      )

    # We define flow paths to connect the nodes of the tubes with the suction or discharge states
    expander.add_flow(FlowPath(key1='inlet.2',key2='A',MdotFcn=expander.Suction))
    expander.add_flow(FlowPath(key1='outlet.1',key2='A',MdotFcn=expander.Discharge))

    # We connect together the energy balance of the expander shell
    t1=clock()
    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)

    # We choose the solver and the integration options
    expander.EulerN = 5000
    expander.solve(key_inlet='inlet.1',
                   key_outlet='outlet.2',
                   solver_method = 'Euler',
                   OneCycle = False,
                   eps_cycle = 1e-10,
                   UseNR = True,
                   plot_every_cycle = False,
                   eps_energy_balance = 1e-3
                   )

    print('time taken',clock()-t1,'s')

    return expander
#Finally, we can run the piston expander model and have access to the variables for plotting
piston = Expander()

#We plot out the PV diagram
p = piston.p.T     #[kPa]
V = piston.V.T*1e6 #[cm^3]

plt.plot(V,p, 'b-',lw = 2)
plt.plot([0,100],[piston.inlet_state.p,piston.inlet_state.p],'k--',lw = 2)
plt.plot([0,100],[piston.outlet_state.p,piston.outlet_state.p],'k--',lw = 2)
plt.xlabel(r'V [cm$^3$]',fontsize = 10)
plt.ylabel(r'p [kPa]',fontsize = 10)
plt.xlim(0,30)
lb = plt.ylim(0,600)
Elapsed time for cycle is 0.745907 s
new outlet T 200.0
===========
|| # 000 ||
===========
||.............|..........@.........................|| energy balance kW  0.0397258663612  Tlumps:  [201.35118811149215] K
||.............|.......................@............|| discharge state 2.09678044086 h_pump_set:  186.277460765 kJ/kg 207.245265174 kJ/kg
||.............|...................@................|| cycle-cycle     0.623900308467
||..................................|............@..|| mdot [%] 60.7758205466 || in: 0.622516084475 g/s || out: 1.00085534285 g/s
Elapsed time for cycle is 0.859858 s
new outlet T 200.0
===========
|| # 001 ||
===========
||.............|..........@.........................|| energy balance kW  0.0391781406638  Tlumps:  [269.005356433448] K
||.............|......................@.............|| discharge state 1.76899659402 h_pump_set:  189.485665291 kJ/kg 207.175631231 kJ/kg
||.............|..........@.........................|| cycle-cycle     0.0335523453722
||..................................|.@.............|| mdot [%] 1.92080012938 || in: 0.968599924008 g/s || out: 0.987204792602 g/s
Elapsed time for cycle is 0.923891 s
new outlet T 200.0
===========
|| # 002 ||
===========
||.............|......@.............................|| energy balance kW  0.0117534421992  Tlumps:  [289.3016069300344] K
||.............|.....................@..............|| discharge state 1.12436278208 h_pump_set:  192.374656794 kJ/kg 203.618284615 kJ/kg
||.............|.........@..........................|| cycle-cycle     0.0262131590058
||..................................|@..............|| mdot [%] 1.42665306839 || in: 0.962284699273 g/s || out: 0.976013163462 g/s
Elapsed time for cycle is 0.938694 s
new outlet T 200.0
===========
|| # 003 ||
===========
||.............|...@................................|| energy balance kW  0.00352603265975  Tlumps:  [295.3904820790103] K
||.............|....................@...............|| discharge state 0.855529491072 h_pump_set:  193.985604662 kJ/kg 202.540899573 kJ/kg
||.............|.......@............................|| cycle-cycle     0.0144403928697
||.................................@|...............|| mdot [%] 0.775941181966 || in: 0.962208391489 g/s || out: 0.969674562655 g/s
Elapsed time for cycle is 0.93103 s
new outlet T 200.0
===========
|| # 004 ||
===========
||.............@....................................|| energy balance kW  0.00105780979792  Tlumps:  [297.2171446237031] K
||.............|...................@................|| discharge state 0.744045547694 h_pump_set:  194.773385003 kJ/kg 202.21384048 kJ/kg
||.............|.....@..............................|| cycle-cycle     0.00701231794461
||...............................@..|...............|| mdot [%] 0.373995653406 || in: 0.962964356947 g/s || out: 0.966565801786 g/s
Elapsed time for cycle is 0.943734 s
new outlet T 200.0
===========
|| # 005 ||
===========
||.........@...|....................................|| energy balance kW  0.000317342939377  Tlumps:  [297.7651433871109] K
||.............|...................@................|| discharge state 0.698114238224 h_pump_set:  195.133211866 kJ/kg 202.114354248 kJ/kg
||.............|..@.................................|| cycle-cycle     0.00319218883001
||.............................@....|...............|| mdot [%] 0.169632287943 || in: 0.963508236518 g/s || out: 0.965142657584 g/s
Elapsed time for cycle is 0.882774 s
new outlet T 200.0
===========
|| # 006 ||
===========
||.....@.......|....................................|| energy balance kW  9.52028818131e-05  Tlumps:  [297.92954301613327] K
||.............|...................@................|| discharge state 0.679271810564 h_pump_set:  195.291271822 kJ/kg 202.083989928 kJ/kg
||.............|@...................................|| cycle-cycle     0.00140015412911
||..........................@.......|...............|| mdot [%] 0.0742824072185 || in: 0.963800255235 g/s || out: 0.964516189266 g/s
Elapsed time for cycle is 0.724196 s
new outlet T 200.0
===========
|| # 007 ||
===========
||..@..........|....................................|| energy balance kW  2.85608645439e-05  Tlumps:  [297.97886290483996] K
||.............|...................@................|| discharge state 0.671560860338 h_pump_set:  195.359067115 kJ/kg 202.074675718 kJ/kg
||...........@.|....................................|| cycle-cycle     0.000600195892795
||........................@.........|...............|| mdot [%] 0.0318203289228 || in: 0.963940258198 g/s || out: 0.964246987159 g/s
Elapsed time for cycle is 0.735495 s
new outlet T 200.0
===========
|| # 008 ||
===========
|@.............|....................................|| energy balance kW  8.56825936319e-06  Tlumps:  [297.993658871452] K
||.............|...................@................|| discharge state 0.668409425287 h_pump_set:  195.387704612 kJ/kg 202.071798865 kJ/kg
||.........@...|....................................|| cycle-cycle     0.000253473561329
||.....................@............|...............|| mdot [%] 0.0134346660797 || in: 0.964003593401 g/s || out: 0.964133104064 g/s
Elapsed time for cycle is 0.681379 s
new outlet T 200.0
===========
|| # 009 ||
===========
|@.............|....................................|| energy balance kW  2.57047780895e-06  Tlumps:  [297.9980976614356] K
||.............|...................@................|| discharge state 0.667122366825 h_pump_set:  195.399678597 kJ/kg 202.070902265 kJ/kg
||......@......|....................................|| cycle-cycle     0.00010597600267
||..................@...............|...............|| mdot [%] 0.00561642717751 || in: 0.964031288467 g/s || out: 0.964085432582 g/s
Elapsed time for cycle is 0.700249 s
[[207.24652935772232, 0.66659694024247074]]
new outlet T 204.802203356
===========
|| # 010 ||
===========
|@.............|....................................|| energy balance kW  7.71143342677e-07  Tlumps:  [297.9994292984307] K
||.............|...................@................|| discharge state 0.666596940242 h_pump_set:  195.40465022 kJ/kg 202.070619623 kJ/kg
||...@.........|....................................|| cycle-cycle     4.40011138478e-05
||...............@..................|...............|| mdot [%] 0.00233187245291 || in: 0.964043142102 g/s || out: 0.964065622359 g/s
Elapsed time for cycle is 0.700286 s
[[207.24652935772232, 0.66659694024247074], [212.24652935772235, 1.1895260785492952]]
new outlet T 196.609739158
===========
|| # 011 ||
===========
|@.............|....................................|| energy balance kW  2.31343002798e-07  Tlumps:  [297.9998287895292] K
||.............|.....................@..............|| discharge state 1.18952607855 h_pump_set:  195.406958574 kJ/kg 207.302219359 kJ/kg
||@............|....................................|| cycle-cycle     1.68415066436e-05
||............@.....................|...............|| mdot [%] 0.00082576392666 || in: 0.964048144045 g/s || out: 0.964056104807 g/s
Elapsed time for cycle is 0.651824 s
[[207.24652935772232, 0.66659694024247074], [212.24652935772235, 1.1895260785492952], [203.7162669038015, 0.29711186836821357]]
new outlet T 194.56437027
===========
|| # 012 ||
===========
|@.............|....................................|| energy balance kW  6.94029008418e-08  Tlumps:  [297.99994863685873] K
||.............|................@...................|| discharge state 0.297111868368 h_pump_set:  195.407343747 kJ/kg 198.37846243 kJ/kg
|@.............|....................................|| cycle-cycle     1.02394213599e-05
||...........@......................|...............|| mdot [%] 0.000618256257656 || in: 0.964049141703 g/s || out: 0.964055101997 g/s
Elapsed time for cycle is 0.658138 s
[[207.24652935772232, 0.66659694024247074], [212.24652935772235, 1.1895260785492952], [203.7162669038015, 0.29711186836821357], [201.58627878860665, 0.07439899569092745]]
new outlet T 194.051934858
===========
|| # 013 ||
===========
|@.............|....................................|| energy balance kW  2.08208702641e-08  Tlumps:  [297.9999845910576] K
||.............|............@.......................|| discharge state 0.0743989956909 h_pump_set:  195.407619317 kJ/kg 196.151609274 kJ/kg
|@.............|....................................|| cycle-cycle     4.08303597068e-06
||........@.........................|...............|| mdot [%] 0.000237867292796 || in: 0.964051841314 g/s || out: 0.964054134478 g/s
Elapsed time for cycle is 0.747643 s
[[207.24652935772232, 0.66659694024247074], [212.24652935772235, 1.1895260785492952], [203.7162669038015, 0.29711186836821357], [201.58627878860665, 0.07439899569092745], [201.05262426282943, 0.018601363677024096]]
new outlet T 193.923812345
===========
|| # 014 ||
===========
|@.............|....................................|| energy balance kW  6.24626107692e-09  Tlumps:  [297.9999953773173] K
||.............|........@...........................|| discharge state 0.018601363677 h_pump_set:  195.407761034 kJ/kg 195.593774671 kJ/kg
|@.............|....................................|| cycle-cycle     1.65779344151e-06
||.....@............................|...............|| mdot [%] 9.36479001012e-05 || in: 0.964052698993 g/s || out: 0.964053601808 g/s
Elapsed time for cycle is 0.715754 s
[[207.24652935772232, 0.66659694024247074], [212.24652935772235, 1.1895260785492952], [203.7162669038015, 0.29711186836821357], [201.58627878860665, 0.07439899569092745], [201.05262426282943, 0.018601363677024096], [200.9191951877022, 0.0046478926818735999]]
new outlet T 193.89180427
===========
|| # 015 ||
===========
|@.............|....................................|| energy balance kW  1.87387831616e-09  Tlumps:  [297.9999986131952] K
||.............|....@...............................|| discharge state 0.00464789268187 h_pump_set:  195.407826217 kJ/kg 195.454305144 kJ/kg
|@.............|....................................|| cycle-cycle     6.76573460572e-07
||...@..............................|...............|| mdot [%] 3.73674747811e-05 || in: 0.964052989575 g/s || out: 0.964053349817 g/s
Elapsed time for cycle is 0.732679 s
[[207.24652935772232, 0.66659694024247074], [212.24652935772235, 1.1895260785492952], [203.7162669038015, 0.29711186836821357], [201.58627878860665, 0.07439899569092745], [201.05262426282943, 0.018601363677024096], [200.9191951877022, 0.0046478926818735999], [200.88586133001644, 0.0011607770190977362]]
new outlet T 193.883813235
===========
|| # 016 ||
===========
|@.............|....................................|| energy balance kW  5.6216349024e-10  Tlumps:  [297.9999995839586] K
||.............@....................................|| discharge state 0.0011607770191 h_pump_set:  195.407854662 kJ/kg 195.419462432 kJ/kg
|@.............|....................................|| cycle-cycle     2.76466275199e-07
||@.................................|...............|| mdot [%] 1.50391833875e-05 || in: 0.964053093316 g/s || out: 0.964053238301 g/s
Elapsed time for cycle is 0.690022 s
[[207.24652935772232, 0.66659694024247074], [212.24652935772235, 1.1895260785492952], [203.7162669038015, 0.29711186836821357], [201.58627878860665, 0.07439899569092745], [201.05262426282943, 0.018601363677024096], [200.9191951877022, 0.0046478926818735999], [200.88586133001644, 0.0011607770190977362], [200.87753929978396, 0.00028969352339913712]]
new outlet T 193.881820071
===========
|| # 017 ||
===========
|@.............|....................................|| energy balance kW  1.68649037855e-10  Tlumps:  [297.9999998751876] K
||.........@...|....................................|| discharge state 0.000289693523399 h_pump_set:  195.407866731 kJ/kg 195.410763667 kJ/kg
|@.............|....................................|| cycle-cycle     1.12969822708e-07
|@..................................|...............|| mdot [%] 6.08527463974e-06 || in: 0.964053131953 g/s || out: 0.964053190618 g/s
Ntheta is 5001
mdot*(h2-h1),P-v,Qamb -0.103633647535 -0.108996854511 1.68649037855e-10
Mass flow rate is 0.964053131953 g/s
Volumetric efficiency is 14.1673251431 %
Adiabatic efficiency is 138.475331247 %
time taken 14.0073186183 s
../_images/PistonExpander_IJR_7_1.png