Example #1
0
    def setUp(self):
        # calculate stage pressures
        cmp_p0 = 101.3  # kPa
        cmp_p2 = 10.0e3  # kPa
        cmp_p1 = (1.43 * cmp_p0 * cmp_p2)**0.5  # kPa

        exp_p0 = 7.0e3  # kPa
        exp_p2 = 101.3  # kPa
        exp_p1 = (1.43 * exp_p0 * exp_p2)**0.5  # kPa

        # test conditions
        T_atm_K = 293.15
        T_atm_C = T_atm_K - 273.15
        inputs = ICAES.get_default_inputs()
        inputs['p_atm'] = cmp_p0  # kPa
        inputs['T_atm'] = T_atm_C  # C
        inputs['depth'] = 900.0  # [m]
        inputs['PR_type'] = 'fixed'
        # inputs['n_stages_cmp'] = 2
        inputs['PR_cmp'] = [cmp_p1 / cmp_p0, cmp_p2 / cmp_p1]
        inputs['ML_cmp1'] = 1.0 * (1.65 / (cmp_p1 / 1000) - 0.05)
        inputs['ML_cmp2'] = 5.0 * (1.65 / (cmp_p2 / 1000) - 0.05)
        inputs['ML_cmp3'] = -1.0
        # inputs['n_stages_exp'] = 2
        inputs['PR_exp'] = [exp_p0 / exp_p1, exp_p1 / exp_p2]
        inputs['ML_exp1'] = 5.0 * (1.65 / (exp_p0 / 1000) - 0.05)
        inputs['ML_exp2'] = 1.0 * (1.65 / (exp_p1 / 1000) - 0.05)
        inputs['ML_exp3'] = -1.0
        self.sys = ICAES(inputs=inputs)

        # overwrite calculated air and water properties
        self.sys.M = 29.0
        self.sys.cp = 1.004
        self.sys.gamma = 1.4
        self.sys.c_water = 4.1816
        self.sys.T_store_init = T_atm_K  # [K]
        self.sys.T_store = T_atm_K  # [K]
        self.sys.T2 = T_atm_K  # [K]
        self.sys.T3 = T_atm_K  # [K]
        self.sys.m_store = self.sys.m_store * 1.2  # increase amount of air to stay within pressure limits

        # solve two timesteps (index 0 = compression, index 1 = expansion)
        self.sys.update(m_dot=10.0, delta_t=2.0)
        self.sys.update(m_dot=-10.0, delta_t=1.0)
        self.sys.data.to_csv('test_perf.csv')
Example #2
0
def parameter_sweep(sensitivity_input):
    start = time.time()

    # create system
    inputs = ICAES.get_default_inputs()
    for variable in sensitivity_input.index:
        inputs[variable] = sensitivity_input[variable]
    system = ICAES(inputs=inputs)

    # run single cycle and analyze
    system.single_cycle()
    results = system.analyze_performance()
    end = time.time()
    results['solve_time'] = end - start

    # combine inputs and results to return in single series
    single_output = pd.concat([sensitivity_input, results])
    return single_output
Example #3
0
def parameter_sweep(sweep_input):
    start = time.time()

    # create system
    inputs = ICAES.get_default_inputs()
    inputs['steps'] = sweep_input['steps']  # [kPa]
    inputs['p_store_min'] = sweep_input['p_min']  # [kPa]
    inputs['p_store_init'] = sweep_input['p_min']  # [kPa]
    inputs['p_store_max'] = sweep_input['p_max']  # [kPa]
    inputs['eta_storage'] = sweep_input['eta_storage']  # [-]
    inputs['V_res'] = sweep_input['V_res']  # [m3]
    inputs['phi'] = sweep_input['phi']  # porosity [-]
    inputs['Slr'] = sweep_input['Slr']  # liquid residual fraction [-]
    system = ICAES(inputs=inputs)

    # run single cycle and analyze
    system.single_cycle()
    results = system.analyze_performance()
    end = time.time()
    results['solve_time'] = end - start

    # combine inputs and results to return in single series
    single_output = pd.concat([sweep_input, results])
    return single_output
Example #4
0
from caes import ICAES, plot_series
import matplotlib.pyplot as plt

# create system
inputs = ICAES.get_default_inputs()
inputs['depth'] = 5550.0
system = ICAES(inputs=inputs)

# system.debug_perf()
#
# # run single cycle and analyze
system.single_cycle()
results = system.analyze_performance()
results.to_csv('single_cycle_performance.csv')
system.data.to_csv('single_cycle_timeseries.csv')
print(results)

# # plot results
system.plot_overview()
system.plot_pressures()
system.plot_pressure_losses()
Example #5
0
class TestICAES(unittest.TestCase):
    def setUp(self):
        # calculate stage pressures
        cmp_p0 = 101.3  # kPa
        cmp_p2 = 10.0e3  # kPa
        cmp_p1 = (1.43 * cmp_p0 * cmp_p2)**0.5  # kPa

        exp_p0 = 7.0e3  # kPa
        exp_p2 = 101.3  # kPa
        exp_p1 = (1.43 * exp_p0 * exp_p2)**0.5  # kPa

        # test conditions
        T_atm_K = 293.15
        T_atm_C = T_atm_K - 273.15
        inputs = ICAES.get_default_inputs()
        inputs['p_atm'] = cmp_p0  # kPa
        inputs['T_atm'] = T_atm_C  # C
        inputs['depth'] = 900.0  # [m]
        inputs['PR_type'] = 'fixed'
        # inputs['n_stages_cmp'] = 2
        inputs['PR_cmp'] = [cmp_p1 / cmp_p0, cmp_p2 / cmp_p1]
        inputs['ML_cmp1'] = 1.0 * (1.65 / (cmp_p1 / 1000) - 0.05)
        inputs['ML_cmp2'] = 5.0 * (1.65 / (cmp_p2 / 1000) - 0.05)
        inputs['ML_cmp3'] = -1.0
        # inputs['n_stages_exp'] = 2
        inputs['PR_exp'] = [exp_p0 / exp_p1, exp_p1 / exp_p2]
        inputs['ML_exp1'] = 5.0 * (1.65 / (exp_p0 / 1000) - 0.05)
        inputs['ML_exp2'] = 1.0 * (1.65 / (exp_p1 / 1000) - 0.05)
        inputs['ML_exp3'] = -1.0
        self.sys = ICAES(inputs=inputs)

        # overwrite calculated air and water properties
        self.sys.M = 29.0
        self.sys.cp = 1.004
        self.sys.gamma = 1.4
        self.sys.c_water = 4.1816
        self.sys.T_store_init = T_atm_K  # [K]
        self.sys.T_store = T_atm_K  # [K]
        self.sys.T2 = T_atm_K  # [K]
        self.sys.T3 = T_atm_K  # [K]
        self.sys.m_store = self.sys.m_store * 1.2  # increase amount of air to stay within pressure limits

        # solve two timesteps (index 0 = compression, index 1 = expansion)
        self.sys.update(m_dot=10.0, delta_t=2.0)
        self.sys.update(m_dot=-10.0, delta_t=1.0)
        self.sys.data.to_csv('test_perf.csv')
        # self.data.to_csv('single_cycle_timeseries.csv')

    # compresor tests
    def test_cmp_nLP(self):
        self.assertAlmostEqual(self.sys.data.loc[0, 'cmp_n0'], 1.046, places=3)

    def test_cmp_nHP(self):
        self.assertAlmostEqual(self.sys.data.loc[0, 'cmp_n1'], 1.092, places=3)

    def test_cmp_wLP(self):
        self.assertAlmostEqual(self.sys.data.loc[0, 'cmp_w_stg0'],
                               -219.737,
                               places=3)

    # expander tests
    def test_exp_nLP(self):
        self.assertAlmostEqual(self.sys.data.loc[1, 'exp_n1'], 1.039, places=3)

    def test_exp_nHP(self):
        self.assertAlmostEqual(self.sys.data.loc[1, 'exp_n0'], 1.062, places=3)

    def test_exp_wHP(self):
        self.assertAlmostEqual(self.sys.data.loc[1, 'exp_w_stg0'],
                               154.024,
                               places=3)
Example #6
0
    savename = "sweep_soln_settings.png"
    # ------------------
    # integer inputs
    # ------------------
    ncpus = 3  # int(os.getenv('NUM_PROCS'))
    # ------------------
    # numpy array inputs
    # ------------------
    # investigated
    steps = np.array([
        1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 8.0, 10.0, 25.0, 50.0, 75.0, 100.0,
        250.0, 500.0, 750.0, 1000.0
    ])  # number of solution time steps [-]

    # kept at default values
    p_mins = np.array([ICAES.get_default_inputs()['p_store_min']
                       ])  # minimum pressure [kPa]
    PRs = np.array([
        ICAES.get_default_inputs()['p_store_max'] /
        ICAES.get_default_inputs()['p_store_min']
    ])  # pressure ratio [-]
    eta_storages = np.array([ICAES.get_default_inputs()['eta_storage']
                             ])  # storage efficiency [fr]
    V_ress = np.array([ICAES.get_default_inputs()['V_res']
                       ])  # reservoir volume [m3]
    phis = np.array([ICAES.get_default_inputs()['phi']])  # porosity [-]
    Slrs = np.array([ICAES.get_default_inputs()['Slr']
                     ])  # liquid residual fraction [-]

    # ==============
    # run simulations
Example #7
0
h = 62.44  # thickness [m]
phi = 0.2292  # porosity
k = 38.33  # permeability [mD]
m_dot = 530.2402606  # mass flow rate [kg/s]
r_f = 174.6289785  # formation radius [m]
r_w = 0.41 / 2.0  # well radius [m]

df = pd.DataFrame()

for i in range(9):

    # get default inputs
    if i == 0:
        inputs = CAES.get_default_inputs()
    else:
        inputs = ICAES.get_default_inputs()

    # Common inputs
    inputs['depth'] = depth
    inputs['h'] = h
    inputs['phi'] = phi
    inputs['k'] = k
    inputs['r_f'] = r_f
    inputs['r_w'] = r_w
    inputs['m_dot'] = m_dot

    # options to include/exclude various loss mechanisms
    inputs['include_interstage_dp'] = False
    inputs['include_thermal_gradient'] = False
    inputs['include_air_leakage'] = False
    inputs['include_aquifer_dp'] = False
Example #8
0
        1.0e5,
        5.0e5,
        1.0e6,
        5.0e6,
        1.0e7,
        5.0e7,
        1.0e8,
        5.0e8,
        1.0e9,
        5.0e9,
    ])  # reservoir volume [m3]
    PRs = np.arange(1.1, 2.1, 0.1)  # pressure ratio [-]
    phis = np.array([1.0])  # porosity [-]
    Slrs = np.array([0.0])  # liquid residual fraction [-]
    # kept at default values
    steps = np.array([ICAES.get_default_inputs()['steps']
                      ])  # number of solution time steps [-]
    p_mins = np.array([ICAES.get_default_inputs()['p_store_min']
                       ])  # minimum pressure [kPa]
    eta_storages = np.array([ICAES.get_default_inputs()['eta_storage']
                             ])  # storage efficiency [fr]

    # ==============
    # run simulations
    # ==============

    # prepare dataframe to store inputs
    attributes = [
        'steps', 'p_min', 'PR', 'p_max', 'eta_storage', 'V_res', 'phi', 'Slr'
    ]
    sweep_inputs = pd.DataFrame(columns=attributes)
Example #9
0
def parameter_sweep(sweep_input, debug=True):
    start = time.time()

    # convert inputs to model units
    kW_out = sweep_input['capacity_MW'] * 1e3
    kWh_out = sweep_input['capacity_MW'] * sweep_input['duration_hr'] * 1e3
    if debug:
        print('\nStarting sizing')
        print("kW_out (desired)  : " + str(round(kW_out, 3)))
        print("kWh_out (desired) : " + str(round(kWh_out, 3)))
        print("\nDepth (m)        : " + str(sweep_input['depth_m']))
        print("Thickness (m)    : " + str(sweep_input['thickness_m']))
        print("Porosity (-)     : " + str(sweep_input['porosity']))
        print("Permeability (mD): " + str(sweep_input['permeability_mD']))

    # allowable calculation error
    error = 1e-6

    # maximum number of iterations
    count_max = 200

    # initial guesses
    m_dot = 10.0
    r_f = 10.0

    # initial results
    kW_out_actual = 0.0
    kWh_out_actual = 0.0

    count = 0
    while abs(kW_out_actual - kW_out) / kW_out + abs(
            kWh_out_actual - kWh_out) / kWh_out > error:
        if debug:
            print("\nIteration : " + str(count))
            print("m_dot       : " + str(round(m_dot, 3)))
            print("r_f         : " + str(round(r_f, 3)))

        # create system
        inputs = ICAES.get_default_inputs()
        # user inputs
        inputs['depth'] = sweep_input['depth_m']  # porosity depth [m]
        inputs['h'] = sweep_input['thickness_m']  # porosity thickness [m]
        inputs['phi'] = sweep_input['porosity']  # formation porosity [-]
        inputs['k'] = sweep_input[
            'permeability_mD']  # formation permeability [mD]

        # current guess/iteration
        inputs['m_dot'] = m_dot  # [kg/s]
        inputs['r_f'] = r_f  # [m]
        system = ICAES(inputs=inputs)

        # run single cycle and analyze
        system.single_cycle()
        results = system.analyze_performance()

        # extract results of interest
        kW_out_actual = results['kW_out_avg']
        kWh_out_actual = results['kWh_out']

        # update guesses
        tau = 0.5  # solver time constant
        m_dot = m_dot * (1.0 + tau * (kW_out - kW_out_actual) / kW_out
                         )  # m_dot linearly linked to kW
        r_f = r_f * (1.0 + tau**2 * (kWh_out - kWh_out_actual) / kWh_out_actual
                     )  # r_f exponentially linked to kWh

        count = count + 1
        if count > count_max:  # sizing unsuccessful
            results['errors'] = True
            break

        if debug:
            print("MW_out_avg   : " + str(round(kW_out_actual / 1e3, 3)))
            print("MWh_out      : " + str(round(kWh_out_actual / 1e3, 3)))

    end = time.time()
    results['solve_time'] = end - start
    results['iterations'] = count
    results['m_dot'] = m_dot
    results['r_f'] = r_f

    # print out RTE
    print(results['RTE'])

    # combine inputs and results to return in single series
    single_output = pd.concat([sweep_input, results])
    return single_output
Example #10
0
phi = 0.2292  # porosity
k = 38.33  # permeability [mD]
m_dot = 200.0  # mass flow rate [kg/s]
r_f = 100.0  # formation radius [m]
r_w = 0.41 / 2.0  # well radius [m]

depths = [1000.0, 2000.0, 3000.0, 4000.0, 5000.0]  # depth [m]
all_results = pd.DataFrame()

# iterate through depths
for depth in depths:

    # iterate through test cases
    for i in range(5):

        inputs = ICAES.get_default_inputs()
        inputs['depth'] = depth
        inputs['h'] = h
        inputs['phi'] = phi
        inputs['k'] = k
        inputs['r_f'] = r_f
        inputs['r_w'] = r_w
        inputs['m_dot'] = m_dot

        # ===========================
        # cases
        # ===========================
        if i == 0:
            casename = 'default'

        elif i == 1:  # i == 1