validationtools.py 6.07 KB
Newer Older
1 2 3
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
4
from dataprocessing.readtools import *
5

6

Jan Dinkelbach's avatar
Jan Dinkelbach committed
7
def convert_neplan_to_modelica_timeseries(neplan_timeseries):
8 9 10 11 12 13 14 15 16
    """
    Mapping the variable names between modelica and neplan
        - Voltage: change *.U and *.ANGLEU to *.V and *.Vangle
        - Current: remove unnecessary current variables
    :param neplan_timeseries: result of neplan in timeseries
    :return: a mapped neplan_timeseries
    """
    line_del = []
    # remove all the line current
17

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
    # Find current of the same component, which means the current needn't to be validated
    for check in range(len(neplan_timeseries)):
        if neplan_timeseries[check].values[0] == '#':
            line_del.append(check)
        if '.P' in neplan_timeseries[check].name:
            line_del.append(check)
        if '.Q' in neplan_timeseries[check].name:
            line_del.append(check)
        for i in range(check + 1, len(neplan_timeseries)):
            if neplan_timeseries[check].name == neplan_timeseries[i].name:
                line_del.append(check)  # delete list of the unnecessary data
                line_del.append(i)
    line_del = sorted(set(line_del))
    for num_to_del in range(len(line_del)):
        del neplan_timeseries[line_del[len(line_del) - num_to_del - 1]]

    # Change the unit of variables to keep consistent with those in modelica
    for i in range(len(neplan_timeseries)):
        if 'ANGLE' in neplan_timeseries[i].name:
            neplan_timeseries[i].values = neplan_timeseries[i].values / 180 * cmath.pi  # unification of the unit
        elif '.U' in neplan_timeseries[i].name or '.I' in neplan_timeseries[i].name:
            neplan_timeseries[i].values = neplan_timeseries[i].values * 1000

    # Change the name of variables to keep consistent with those in modelica
    for i in range(len(neplan_timeseries)):
        neplan_timeseries[i].name = neplan_timeseries[i].name.replace(' ', '')
        neplan_timeseries[i].name = neplan_timeseries[i].name.replace('.ANGLEU', '.Vangle')
        neplan_timeseries[i].name = neplan_timeseries[i].name.replace('.U', '.Vpp')
        neplan_timeseries[i].name = neplan_timeseries[i].name.replace('.ANGLEI', '.Iangle')

    return neplan_timeseries

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
def convert_simulink_to_modelica_timeseries(simseri):
    res = []
    for check in range(len(simseri)):
        if 'U AB:' in simseri[check].name:
            simseri[check].name = simseri[check].name.replace('U AB:', '')
            simseri[check].name = simseri[check].name.replace('Vrms', 'Vpp')
            simseri[check].name = simseri[check].name.replace('VDegree', 'Vangle')
            simseri[check].name = simseri[check].name.replace(' ', '')
            simseri[check].name = simseri[check].name.replace('_', '')
            if 'Vangle' in simseri[check].name:
                simseri[check].values = (simseri[check].values - 30)/180 * cmath.pi
            res.append(simseri[check])
    return res


def compare_timeseries(ts1, ts2):
66
    """
67 68 69 70
    Compare the result from two timeseries.
    :param ts1: timeseries
    :param ts2: timeseries
    :return: an error dic
71
    """
72 73 74 75 76 77 78 79
    if len(ts1) > len(ts2):
        tmp = ts2
        ts2 = ts1
        ts1 = tmp
    for i in range(len(ts1)):
        ts1[i].name = ts1[i].name.upper()
    for i in range(len(ts2)):
        ts2[i].name = ts2[i].name.upper()
80 81

    timeseries_names = []  # list for names of components
82
    timeseries_error = []  # list for error
83 84
    len_ts1 = len(ts1)
    len_limit = len(ts2)
85 86

    # Match the components in result files, and compare them
87
    for i in range(len_ts1):
88
        flag_not_found = False
89
        for j in range(len_limit):
90 91 92 93
            if ts1[i].name == ts2[j].name:  # Find the same variable
                timeseries_names.append(ts1[i].name)
                timeseries_error.append(TimeSeries.rmse(ts2[j], ts1[i])/ts1[i].values[1])
                print(ts1[i].name)
Bichen Li's avatar
Bichen Li committed
94
                print(TimeSeries.rmse(ts2[j], ts1[i])/ts1[i].values[len(ts1[i].values) - 1])
95 96
                flag_not_found = True
        if flag_not_found is False:
97
            # No such variable in Modelica model, set the error to -1
98
            timeseries_names.append(ts1[i].name)
99
            timeseries_error.append(-1)
100 101
    return dict(zip(timeseries_names, timeseries_error))

102 103

def assert_modelia_results(net_name, error):
104
    """
105 106 107 108 109
    assert the result data of a net.
    :param net_name: name of the network
    :param modelica_res: timeseries of modelica result
    :param simulink_res: timeseries of reference result
    :return: outputs to command line which are the results of the assert
110 111 112
    """
    fail_list = []  # List for all the failed test
    #  the limitations are set to 0.5
113
    for name in error.keys():
114
        if abs(error[name]) > 0.01:
115 116 117
            fail_list.append(name)
        else:
            print("Test on %s Passed" % name)
118 119

    #  fail_list is 0, which means all the tests are passed
120
    if len(fail_list) is 0:
121
        print("\033[1;36;40mModel %s Passed\033[0m" % net_name)
122 123
    else:
        for name in fail_list:
124 125
            print("\033[1;31;40mTest on %s of %s Failed\033[0m" % (name, net_name))
        raise ValueError('Test on %s is not passed!' % net_name)
126 127


128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
def validate_modelica_res(net_name, modelica_res_path, reference_res_path):
    """
    Top level function for the validation of modelica, calls all the function needed to execute the validation.
    :param modelica_res_path: the path of the modelica result file, whose suffix should be .mat
    :param reference_res_path: the path of the reference result file, whose suffix should be .rep(simulink)/.rlf(neplan)
    :return: outputs to command line which are the results of the validation.
    """
    res_mod = read_timeseries_Modelica (modelica_res_path)
    if os.path.splitext(reference_res_path)[1] == '.rep':
        res_ref = convert_simulink_to_modelica_timeseries(read_timeseries_simulink_loadflow(reference_res_path))
    elif os.path.splitext(reference_res_path)[1] == '.rlf':
        res_ref = convert_neplan_to_modelica_timeseries(read_timeseries_NEPLAN_loadflow(reference_res_path))
    
    res_err = compare_timeseries(res_ref, res_mod)
    assert_modelia_results(net_name, res_err)