popt.cost_functions.ecalc_npv

Net present value.

  1"""Net present value."""
  2import numpy as np
  3import csv
  4from pathlib import Path
  5import pandas as pd
  6import sys
  7
  8HERE = Path().cwd()  # fallback for ipynb's
  9HERE = HERE.resolve()
 10
 11
 12def ecalc_npv(pred_data, **kwargs):
 13    """
 14    Net present value cost function using eCalc to calculate emmisions
 15
 16    Parameters
 17    ----------
 18    pred_data : array_like
 19        Ensemble of predicted data.
 20
 21    **kwargs : dict
 22        Other arguments sent to the npv function
 23
 24        keys_opt : list
 25            Keys with economic data.
 26
 27        report : list
 28            Report dates.
 29
 30    Returns
 31    -------
 32    objective_values : array_like
 33        Objective function values (NPV) for all ensemble members.
 34    """
 35
 36    from libecalc.application.energy_calculator import EnergyCalculator
 37    from libecalc.common.time_utils import Frequency
 38    from libecalc.presentation.yaml.model import YamlModel
 39
 40    # Get the necessary input
 41    keys_opt = kwargs.get('input_dict', {})
 42    report = kwargs.get('true_order', [])
 43
 44    # Economic values
 45    npv_const = {}
 46    for name, value in keys_opt['npv_const']:
 47        npv_const[name] = value
 48
 49    # Collect production data
 50    Qop = []
 51    Qgp = []
 52    Qwp = []
 53    Qwi = []
 54    Dd = []
 55    for i in np.arange(1, len(pred_data)):
 56
 57        Qop.append(np.squeeze(pred_data[i]['fopt']) - np.squeeze(pred_data[i - 1]['fopt']))
 58        Qgp.append(np.squeeze(pred_data[i]['fgpt']) - np.squeeze(pred_data[i - 1]['fgpt']))
 59        Qwp.append(np.squeeze(pred_data[i]['fwpt']) - np.squeeze(pred_data[i - 1]['fwpt']))
 60        Qwi.append(np.squeeze(pred_data[i]['fwit']) - np.squeeze(pred_data[i - 1]['fwit']))
 61        Dd.append((report[1][i] - report[1][i - 1]).days)
 62
 63    # Write production data to .csv file for eCalc input, for each ensemble member
 64    Qop = np.array(Qop).T
 65    Qwp = np.array(Qwp).T
 66    Qgp = np.array(Qgp).T
 67    Qwi = np.array(Qwi).T
 68    Dd = np.array(Dd)
 69    if len(Qop.shape) == 1:
 70        Qop = np.expand_dims(Qop,0)
 71        Qwp = np.expand_dims(Qwp, 0)
 72        Qgp = np.expand_dims(Qgp, 0)
 73        Qwi = np.expand_dims(Qwi, 0)
 74
 75    N = Qop.shape[0]
 76    T = Qop.shape[1]
 77    values = []
 78    em_values = []
 79    for n in range(N):
 80        with open('ecalc_input.csv', 'w') as csvfile:
 81            writer = csv.writer(csvfile, delimiter=',')
 82            writer.writerow(['dd/mm/yyyy', 'GAS_PROD', 'OIL_PROD', 'WATER_INJ'])
 83            for t in range(T):
 84                D = report[1][t]
 85                writer.writerow([D.strftime("%d/%m/%Y"), Qgp[n, t]/Dd[t], Qop[n, t]/Dd[t], Qwi[n, t]/Dd[t]])
 86
 87        # Config
 88        model_path = HERE / "ecalc_config.yaml"  # "drogn.yaml"
 89        yaml_model = YamlModel(path=model_path, output_frequency=Frequency.NONE)
 90        # comps = {c.name: id_hash for (id_hash, c) in yaml_model.graph.components.items()}
 91
 92        # Compute energy, emissions
 93        model = EnergyCalculator(graph=yaml_model.graph)
 94        consumer_results = model.evaluate_energy_usage(yaml_model.variables)
 95        emission_results = model.evaluate_emissions(yaml_model.variables, consumer_results)
 96
 97        # Extract
 98        # energy = results_as_df(yaml_model, consumer_results, lambda r: r.component_result.energy_usage)
 99        emissions = results_as_df(yaml_model, emission_results, lambda r: r['co2_fuel_gas'].rate)
100        emissions_total = emissions.sum(1).rename("emissions_total")
101        emissions_total.to_csv(HERE / "emissions.csv")
102        Qem = emissions_total.values * Dd  # total number of tons
103        em_values.append(Qem)
104
105        value = (Qop[n, :] * npv_const['wop'] + Qgp[n, :] * npv_const['wgp'] - Qwp[n, :] * npv_const['wwp'] -
106                 Qwi[n, :] * npv_const['wwi'] - Qem * npv_const['wem']) / (
107            (1 + npv_const['disc']) ** (Dd / 365))
108        values.append(np.sum(value))
109
110    # Save emissions for later analysis
111    np.savez('em_values.npz', em_values=np.array([em_values]))
112
113    if 'obj_scaling' in npv_const:
114        return np.array(values) / npv_const['obj_scaling']
115    else:
116        return np.array(values)
117
118
119def results_as_df(yaml_model, results, getter) -> pd.DataFrame:
120    """Extract relevant values, as well as some meta (`attrs`)."""
121    df = {}
122    attrs = {}
123    res = None
124    for id_hash in results:
125        res = results[id_hash]
126        res = getter(res)
127        component = yaml_model.graph.get_node(id_hash)
128        df[component.name] = res.values
129        attrs[component.name] = {'id_hash': id_hash,
130                                 'kind': type(component).__name__,
131                                 'unit': res.unit}
132    if res is None:
133        sys.exit('No emission results from eCalc!')
134    df = pd.DataFrame(df, index=res.timesteps)
135    df.index.name = "dates"
136    df.attrs = attrs
137    return df
HERE = PosixPath('/home/runner/work/PET/PET')
def ecalc_npv(pred_data, **kwargs):
 13def ecalc_npv(pred_data, **kwargs):
 14    """
 15    Net present value cost function using eCalc to calculate emmisions
 16
 17    Parameters
 18    ----------
 19    pred_data : array_like
 20        Ensemble of predicted data.
 21
 22    **kwargs : dict
 23        Other arguments sent to the npv function
 24
 25        keys_opt : list
 26            Keys with economic data.
 27
 28        report : list
 29            Report dates.
 30
 31    Returns
 32    -------
 33    objective_values : array_like
 34        Objective function values (NPV) for all ensemble members.
 35    """
 36
 37    from libecalc.application.energy_calculator import EnergyCalculator
 38    from libecalc.common.time_utils import Frequency
 39    from libecalc.presentation.yaml.model import YamlModel
 40
 41    # Get the necessary input
 42    keys_opt = kwargs.get('input_dict', {})
 43    report = kwargs.get('true_order', [])
 44
 45    # Economic values
 46    npv_const = {}
 47    for name, value in keys_opt['npv_const']:
 48        npv_const[name] = value
 49
 50    # Collect production data
 51    Qop = []
 52    Qgp = []
 53    Qwp = []
 54    Qwi = []
 55    Dd = []
 56    for i in np.arange(1, len(pred_data)):
 57
 58        Qop.append(np.squeeze(pred_data[i]['fopt']) - np.squeeze(pred_data[i - 1]['fopt']))
 59        Qgp.append(np.squeeze(pred_data[i]['fgpt']) - np.squeeze(pred_data[i - 1]['fgpt']))
 60        Qwp.append(np.squeeze(pred_data[i]['fwpt']) - np.squeeze(pred_data[i - 1]['fwpt']))
 61        Qwi.append(np.squeeze(pred_data[i]['fwit']) - np.squeeze(pred_data[i - 1]['fwit']))
 62        Dd.append((report[1][i] - report[1][i - 1]).days)
 63
 64    # Write production data to .csv file for eCalc input, for each ensemble member
 65    Qop = np.array(Qop).T
 66    Qwp = np.array(Qwp).T
 67    Qgp = np.array(Qgp).T
 68    Qwi = np.array(Qwi).T
 69    Dd = np.array(Dd)
 70    if len(Qop.shape) == 1:
 71        Qop = np.expand_dims(Qop,0)
 72        Qwp = np.expand_dims(Qwp, 0)
 73        Qgp = np.expand_dims(Qgp, 0)
 74        Qwi = np.expand_dims(Qwi, 0)
 75
 76    N = Qop.shape[0]
 77    T = Qop.shape[1]
 78    values = []
 79    em_values = []
 80    for n in range(N):
 81        with open('ecalc_input.csv', 'w') as csvfile:
 82            writer = csv.writer(csvfile, delimiter=',')
 83            writer.writerow(['dd/mm/yyyy', 'GAS_PROD', 'OIL_PROD', 'WATER_INJ'])
 84            for t in range(T):
 85                D = report[1][t]
 86                writer.writerow([D.strftime("%d/%m/%Y"), Qgp[n, t]/Dd[t], Qop[n, t]/Dd[t], Qwi[n, t]/Dd[t]])
 87
 88        # Config
 89        model_path = HERE / "ecalc_config.yaml"  # "drogn.yaml"
 90        yaml_model = YamlModel(path=model_path, output_frequency=Frequency.NONE)
 91        # comps = {c.name: id_hash for (id_hash, c) in yaml_model.graph.components.items()}
 92
 93        # Compute energy, emissions
 94        model = EnergyCalculator(graph=yaml_model.graph)
 95        consumer_results = model.evaluate_energy_usage(yaml_model.variables)
 96        emission_results = model.evaluate_emissions(yaml_model.variables, consumer_results)
 97
 98        # Extract
 99        # energy = results_as_df(yaml_model, consumer_results, lambda r: r.component_result.energy_usage)
100        emissions = results_as_df(yaml_model, emission_results, lambda r: r['co2_fuel_gas'].rate)
101        emissions_total = emissions.sum(1).rename("emissions_total")
102        emissions_total.to_csv(HERE / "emissions.csv")
103        Qem = emissions_total.values * Dd  # total number of tons
104        em_values.append(Qem)
105
106        value = (Qop[n, :] * npv_const['wop'] + Qgp[n, :] * npv_const['wgp'] - Qwp[n, :] * npv_const['wwp'] -
107                 Qwi[n, :] * npv_const['wwi'] - Qem * npv_const['wem']) / (
108            (1 + npv_const['disc']) ** (Dd / 365))
109        values.append(np.sum(value))
110
111    # Save emissions for later analysis
112    np.savez('em_values.npz', em_values=np.array([em_values]))
113
114    if 'obj_scaling' in npv_const:
115        return np.array(values) / npv_const['obj_scaling']
116    else:
117        return np.array(values)

Net present value cost function using eCalc to calculate emmisions

Parameters
  • pred_data (array_like): Ensemble of predicted data.
  • **kwargs (dict): Other arguments sent to the npv function

    keys_opt : list Keys with economic data.

    report : list Report dates.

Returns
  • objective_values (array_like): Objective function values (NPV) for all ensemble members.
def results_as_df(yaml_model, results, getter) -> pandas.core.frame.DataFrame:
120def results_as_df(yaml_model, results, getter) -> pd.DataFrame:
121    """Extract relevant values, as well as some meta (`attrs`)."""
122    df = {}
123    attrs = {}
124    res = None
125    for id_hash in results:
126        res = results[id_hash]
127        res = getter(res)
128        component = yaml_model.graph.get_node(id_hash)
129        df[component.name] = res.values
130        attrs[component.name] = {'id_hash': id_hash,
131                                 'kind': type(component).__name__,
132                                 'unit': res.unit}
133    if res is None:
134        sys.exit('No emission results from eCalc!')
135    df = pd.DataFrame(df, index=res.timesteps)
136    df.index.name = "dates"
137    df.attrs = attrs
138    return df

Extract relevant values, as well as some meta (attrs).