Пример #1
0
def fleet_test():
    Fleet = BatteryInverterFleet()

    t = numpy.linspace(0, 24, 97)

    requests = []
    ts = datetime.utcnow()
    dt = 1/4 #hours
    for i in t:
        req = FleetRequest(ts,dt,float(10*numpy.sin(2*numpy.pi*i/24)),0.0)
        requests.append(req)

    # print the initial SoC
    print("SoC =", str(Fleet.soc))
    FORCAST = Fleet.forecast(requests) # generate a forecast 
    print("SoC =", str(Fleet.soc))
    # make sure that the forecast function does not change the SoC

    # print the forecasted achivable power schedule
    for i in range(97):
        rsp = FORCAST[i]
        print("P =", str(rsp.P_injected))

    # process the requests 
    for req in requests:
        Fleet.process_request(req.sim_step, req.P_req, req.Q_req)
        print("SoC =", str(Fleet.soc)) # show that process_request function updates the SoC
    def __init__(self, *args, **kwargs):
        self.sim_time_step = timedelta(hours=1)

        #self.fleet = BatteryInverterFleet('C:\\Users\\jingjingliu\\gmlc-1-4-2\\battery_interface\\src\\fleets\\battery_inverter_fleet\\config_CRM.ini')
        self.grid = GridInfo('Grid_Info_DATA_2.csv')
        self.fleet = BatteryInverterFleet(
            GridInfo=self.grid
        )  #establish the battery inverter fleet with a grid
Пример #3
0
def integration_test():

    # Establish the test variables
    n = 24
    dt = 1
    SoC0 = 50
#    t = numpy.linspace(0, (n - 1), n)
#    EffMatrix = numpy.zeros((n, n))
    ts = datetime.utcnow()
#    print(n)

    Fleet = BatteryInverterFleet()
    Fleet.soc = SoC0  # initialize SoC
    Power = numpy.zeros(n)  # initialize Power
    Power = Fleet.max_power_charge
#    Power = Fleet.max_power_discharge
    # simulate the system with SoC0 and Power requests
    for T in numpy.arange(0, n):
        req = FleetRequest(ts,dt,Power[T],0.0)
        Fleet.process_request(req)
    
    SoCFin = Fleet.soc  # get final SoC
    [P2, Cost, Able] = Fleet.cost(SoCFin, SoC0, dt)  # retreeve how much power it would take to return to SoC0
    P2Charge = max(P2,0)
    P2Discharge = min(P2,0)
Пример #4
0
def integration_test():

    # Establish the test variables
    n = 24
    dt = 1
    SoC0 = 50
#    t = numpy.linspace(0, (n - 1), n)
    EffMatrix = numpy.zeros((n, n))
    ts = datetime.utcnow()
    print(n)

    for i in numpy.arange(0, n):
        for j in numpy.arange(0, n):
            if i != j:
                Fleet = BatteryInverterFleet()
                Fleet.soc = SoC0  # initialize SoC
                Power = numpy.zeros(n)  # initialize Power
                Power[i] = Fleet.max_power_charge
                Power[j] = Fleet.max_power_discharge
                # simulate the system with SoC0 and Power requests
                for T in numpy.arange(0, n):
                    req = FleetRequest(ts,dt,Power[T],0.0)
                    Fleet.process_request(req.sim_step, req.P_req, req.Q_req)
                
                SoCFin = Fleet.soc  # get final SoC
                [P2, Cost, Able] = Fleet.cost(SoCFin, SoC0, dt)  # retreeve how much power it would take to return to SoC0
                P2Charge = max(P2,0)
                P2Discharge = min(P2,0)
                EffMatrix[i, j] = -(Power[j] +P2Discharge)/ (
                            Power[i] + P2Charge)  # calculate efficiency      DISCHARGE_ENERGY / CHARGE_ENERGY
                if P2<0:
                    print('err')
                if Able == 0:
                    EffMatrix[i, j] = 0

    print(EffMatrix)
class TradRegService():
    """
    This class implements FleetInterface so that it can communicate with a fleet
    """
    def __init__(self, *args, **kwargs):
        self.sim_time_step = timedelta(hours=1)

        #self.fleet = BatteryInverterFleet('C:\\Users\\jingjingliu\\gmlc-1-4-2\\battery_interface\\src\\fleets\\battery_inverter_fleet\\config_CRM.ini')
        self.grid = GridInfo('Grid_Info_DATA_2.csv')
        self.fleet = BatteryInverterFleet(
            GridInfo=self.grid
        )  #establish the battery inverter fleet with a grid

    def request_loop(
        self,
        filename='08 2017.csv'
    ):  ### (TODO) add keywords for date and start hour, duration. add serv_type 'trad_reg'(default), 'dynm_reg'

        start_time = parser.parse("2017-08-01 16:00:00")
        end_time = parser.parse("2017-08-01 21:00:00")
        # Read Regulation control signal (RegA) from file: 2-sec interval.
        df_RegA = pd.read_csv(filename, usecols=[0, 1], header=0)

        # March through time (btw. start_time & end_time), store requested MW and responded MW every 2-sec in lists.
        requests = []
        responses = []
        for row in df_RegA.iterrows():
            ts = row[1][0]  # extract time stamp w/i a tuple.
            ts = parser.parse(
                "2017-08-01 " + ts
            )  # combine time stamp with date. ### hard-coded right now, extract date from column name later.
            if start_time <= ts < end_time:
                sim_step = timedelta(
                    seconds=2
                )  ### doesn't seem to be useful, but don't delete w/o confirmation.
                p = row[1][1] * (
                    self.fleet.max_power_discharge * self.fleet.num_of_devices
                ) * 0.2  ### need to multiple a "AReg" value from the fleet - "Assigned Regulation (MW)"

                request, response = self.request(ts, sim_step, p)
                requests.append(request)
                responses.append(response)

        #print(requests)
        #print(responses)

        # # Store the responses in a text file.
        # with open('results.txt', 'w') as the_file:
        # ### should add a step to clean the file first.
        #     for r in responses:
        #         ts = r.ts
        #         p_togrid = r.P_togrid
        #         p_service = r.P_service
        #         print(p_service)
        #         the_file.write("{p_togrid},{p_service}\n".format(p_togrid=p_togrid, p_service=p_service))

        # Calculate hourly performance score and store in a dictionary.
        hourly_results = {}
        cur_time = start_time  # need another loop if later want to calculate hourly score for multiple hours.
        one_hour = timedelta(hours=1)
        while cur_time < end_time - timedelta(minutes=65):

            # Generate 1-hour worth (65 min) request and response arrays for calculating scores.
            cur_end_time = cur_time + timedelta(minutes=65)
            request_array_2s = [
                r.P_req for r in requests
                if cur_time <= r.ts_req <= cur_end_time
            ]
            response_array_2s = [
                r.P_service for r in responses
                if cur_time <= r.ts <= cur_end_time
            ]
            request_array_2s = np.asarray(request_array_2s)
            response_array_2s = np.asarray(response_array_2s)
            # Slice arrays at 10s intervals - resulted arrays have 390 data points.
            request_array_10s = request_array_2s[::5]
            response_array_10s = response_array_2s[::5]

            # Calculate performance scores for current hour and store in a dictionary keyed by starting time.
            hourly_results[cur_time] = {}
            hourly_results[cur_time]['perf_score'] = self.perf_score(
                request_array_10s, response_array_10s)
            hourly_results[cur_time]['hr_int_MW'] = self.Hr_int_reg_MW(
                request_array_2s)
            hourly_results[cur_time]['RMCP'] = self.get_RMCP()
            hourly_results[cur_time][
                'reg_clr_pr_credit'] = self.Reg_clr_pr_credit(
                    hourly_results[cur_time]['RMCP'],
                    hourly_results[cur_time]['perf_score'][0],
                    hourly_results[cur_time]['hr_int_MW'])

            # Move to the next hour.
            cur_time += one_hour

        P_request = [r.P_req for r in requests]
        P_responce = [r.P_service for r in responses]
        SOC = [r.soc for r in responses]
        n = len(P_request)
        t = np.asarray(range(n)) * (2 / 3600)
        plt.figure(1)
        plt.subplot(211)
        plt.plot(t, P_request, label='P Request')
        plt.plot(t, P_responce, label='P Responce')
        plt.ylabel('Power (kW)')
        plt.legend(loc='upper right')
        plt.subplot(212)
        plt.plot(t, SOC, label='SoC')
        plt.ylabel('SoC (%)')
        plt.xlabel('Time (hours)')
        plt.legend(loc='lower right')
        plt.show()

        return hourly_results

    def request(
            self,
            ts,
            sim_step,
            p,
            q=0.0):  # added input variables; what's the purpose of sim_step??
        fleet_request = FleetRequest(ts=ts, sim_step=sim_step, p=p, q=0.0)
        fleet_response = self.fleet.process_request(fleet_request)
        #print(fleet_response.P_service)
        return fleet_request, fleet_response

    # Score the performance of device fleets (based on PJM Manual 12).
    # Take 65 min worth of 2s data (should contain 1,950 data values).
    def perf_score(self, request_array, response_array):
        max_corr_array = []
        max_index_array = []
        prec_score_array = []

        # In each 5-min of the hour, use max correlation to define "delay", "correlation" & "delay" scores.
        # There are twelve (12) 5-min in each hour.
        for i in range(12):

            # Takes 5-min of the input signal data.
            x = request_array[30 * i:30 * (i + 1)]
            #         print('x:', x)
            y = response_array[30 * i:30 * (i + 1)]

            # Refresh the array in each 5-min run.
            corr_score = []

            # If the regulation signal is nearly constant, then correlation score is calculated as:
            # 1 - absoluate of difference btw slope of request and response signals (determined by linear regression).
            std_dev = np.std(x)
            if std_dev < 0.001:  #need to vet the threshold later, not specified in PJM manual.
                axis = np.array(np.arange(30.))
                coeff_x = np.polyfit(axis, x,
                                     1)  # linear regression when degree = 1.
                coeff_y = np.polyfit(axis, y, 1)
                slope_x = coeff_x[0]
                slope_y = coeff_y[0]
                corr_score_val = 1 - abs(
                    slope_x - slope_y)  # from PJM manual 12.
                max_index_array = np.append(max_index_array, 0)
                max_corr_array = np.append(
                    max_corr_array, corr_score_val
                )  # r cannot be calc'd for constant values in one or both arrays.

            else:
                # Calculate correlation btw the 5-min input signal and thirty 5-min response signals,
                # each is delayed at an additional 10s than the previous one; store results.
                # There are thirty (30) 10s in each 5min.
                for j in range(31):
                    y_ = response_array[30 * i + j:30 * (i + 1) + j]

                    #             # for debug use
                    #             print('y:', y)
                    #             x_axis_x = np.arange(x.size)
                    #             plt.plot(x_axis_x, x, "b")
                    #             plt.plot(x_axis_x, y, "r")
                    #             plt.show()

                    # Calculate Pearson Correlation Coefficient btw input and response for the 10s step.
                    corr_r = np.corrcoef(x, y_)[0, 1]
                    # Correlation scores stored in an numpy array.
                    corr_score = np.append(corr_score, corr_r)
                    #         print('corr_score:', corr_score)

                # locate the 10s moment(step) at which correlation score was maximum among the thirty calculated; store it.
                max_index = np.where(corr_score == max(corr_score))[0][0]
                max_index_array = np.append(max_index_array,
                                            max_index)  # array
                # Find the maximum score in the 5-min; store it.
                max_corr_array = np.append(
                    max_corr_array, corr_score[max_index]
                )  # this is the correlation score array

                # Calculate the coincident delay score associated with max correlation in each 5min period.
                delay_score = np.absolute(
                    (10 * max_index_array - 5 * 60) / (5 * 60))  # array

                # Calculate error at 10s intervals and store in an array.
                error = np.absolute(y - x) / (np.absolute(x).mean())
                # Calculate 5-min average Precision Score as the average error.
                prec_score = 1 - 1 / 30 * error.sum()
                prec_score_array = np.append(prec_score_array, prec_score)

            #     # for debug use
            #     print('delay_score:', delay_score)
            #     print('max_index_array:', max_index_array)
            #     print('max_corr_array:', max_corr_array)

        # calculate average "delay", "correlation" and "precision" scores for the hour.
        Delay_score = delay_score.mean()
        Corr_score = max_corr_array.mean()
        Prec_score = prec_score_array.mean()

        #     # for debug use
        #     x_axis_error = np.arange(error.size)
        #     plt.scatter(x_axis_error, error)
        #     plt.show()

        # Calculate the hourly overall Performance Score.
        Perf_score = (Delay_score + Corr_score + Prec_score) / 3

        # # Plotting and Printing results
        # x_axis_sig = np.arange(request_array[0:360].size)
        # x_axis_score = np.arange(max_corr_array.size)
        #
        # plt.figure(1)
        # plt.subplot(211)
        # plt.plot(x_axis_sig, request_array[0:360], "b")
        # plt.plot(x_axis_sig, response_array[0:360], "r")
        # plt.legend(('RegA signal', 'CReg response'), loc='lower right')
        # plt.show()
        #
        # plt.figure(2)
        # plt.subplot(212)
        # plt.plot(x_axis_score, max_corr_array, "g")
        # plt.plot(x_axis_score, delay_score, "m")
        # plt.legend(('Correlation score', 'Delay score'), loc='lower right')
        # plt.show()
        #
        # print('Delay_score:', Delay_score)
        # print('Corr_score:', Corr_score)
        # print('Prec_score:', Prec_score)
        # print('Perf_score:', Perf_score)

        return (Perf_score, Delay_score, Corr_score, Prec_score)

    # calculate "Hourly-integrated Regulation MW".
    # based on PJM Manual 28 (need to verify definition, not found in manual).
    def Hr_int_reg_MW(self, input_sig):
        # Take one hour of 2s RegA data
        RegA_array = input_sig[1:1800]
        #     print(RegA_array)
        #     x_axis = np.arange(RegA_array.size)
        #     plt.plot(x_axis, RegA_array,"b")
        #     plt.show()
        Hourly_Int_Reg_MW = np.absolute(RegA_array).sum() * 2 / 3600
        print(Hourly_Int_Reg_MW)

        return Hourly_Int_Reg_MW

    # looks up the regulation market clearing price (RMCP).
    # the RMCP and its components are stored in a 1-dimensional array.
    # Use Aug 1st, 2017, 4-5PM data.
    def get_RMCP(
            self
    ):  ### needs to be expanded to include date and time in keywords.
        raw_pr_dataframe = pd.read_excel(
            'historical-ancillary-service-data-2017.xls',
            sheetname='August_2017',
            header=0)
        #     print(raw_pr_dataframe)

        raw_pr_array = raw_pr_dataframe.values  # convert from pandas dataframe to numpy array.
        RMCP = raw_pr_array[80][4]  # Regulation Market Clearing Price.
        RMCCP = raw_pr_array[80][
            6]  # Regulation Market Capability Clearing Price.
        RMPCP = raw_pr_array[80][
            7]  # Regulation Market Performance Clearing Price.

        return (RMCP, RMPCP, RMCCP)

    # calculates hourly "Regulation Market Clearing Price Credit" for a device fleet for the regulation service provided.
    # based on PJM Manual 28.
    def Reg_clr_pr_credit(self, RM_pr, pf_score, reg_MW):
        # Arguments:
        # RM_pr - RMCP price components for the hour.
        # pf_score - performance score for the hour.
        # reg_MW - "Hourly-integrated Regulation MW" for the hour.

        # prepare key parameters for calculation.
        RMCCP = RM_pr[1]
        RMPCP = RM_pr[2]

        # "mileage ratio" equals "1" for traditional regulation (i.e. RegA); is >1 for dynamic regulation.
        mi_ratio = 1

        print("Hr_int_reg_MW:", reg_MW)
        print("Pf_score:", pf_score)
        print("RMCCP:", RMCCP)
        print("RMPCP:", RMPCP)

        # calculate "Regulation Market Clearing Price Credit" and two components.
        # minimum perf score is 0.25, otherwise forfeit regulation credit (and lost opportunity) for the hour (m11 3.2.10).
        if pf_score < 0.25:
            Reg_RMCCP_Credit = 0
            Reg_RMPCP_Credit = 0
        else:
            Reg_RMCCP_Credit = reg_MW * pf_score * RMCCP
            Reg_RMPCP_Credit = reg_MW * pf_score * mi_ratio * RMPCP
        Reg_Clr_Pr_Credit = Reg_RMCCP_Credit + Reg_RMPCP_Credit

        print("Reg_Clr_Pr_Credit:", Reg_Clr_Pr_Credit)
        print("Reg_RMCCP_Credit:", Reg_RMCCP_Credit)
        print("Reg_RMPCP_Credit:", Reg_RMPCP_Credit)

        # "Lost opportunity cost credit" (for energy sources providing regulation) is not considered,
        # because it does not represent economic value of the provided service.

        return (Reg_Clr_Pr_Credit, Reg_RMCCP_Credit, Reg_RMPCP_Credit)

    def change_config(self):
        fleet_config = FleetConfig(is_P_priority=True,
                                   is_autonomous=False,
                                   autonomous_threshold=0.1)
        self.fleet.change_config(fleet_config)
Пример #6
0
                for T in numpy.arange(0, n):
                    Power[T] = responses[T].P_service

                SoCFin = responses[n - 1].soc  # get final SoC
                [P2, Cost, Able] = Fleet.cost(
                    SoCFin, SoC0, del_t
                )  # calculate how much power it would take to return to SoC0

                P2Charge = max(P2, 0)
                P2Discharge = min(P2, 0)
                if (Power[i] + P2Charge) != 0:
                    EffMatrix[i, j] = -(Power[j] + P2Discharge) / (
                        Power[i] + P2Charge
                    )  # calculate efficiency      DISCHARGE_ENERGY / CHARGE_ENERGY
                else:
                    EffMatrix[i, j] = 0
                if Able == 0:
                    EffMatrix[i, j] = 0

    print(EffMatrix)
    with open('EffMatrix.csv', 'w') as csvfile:
        writer = csv.writer(csvfile, delimiter=",")
        writer.writerows(EffMatrix)


if __name__ == '__main__':
    Grid = GridInfo('Grid_Info_DATA_2.csv')
    Fleet = BatteryInverterFleet(Grid, 'ERM')
    fleet_test(Fleet)