示例#1
0
    def initialize_states(self,ia0,xa0,ua0,xDC0,xQ0,xPLL0,wte0):
        """Initialize inverter states.

        Extended description of function.

        Args:
            ia0 (float): Initial current
            xa0 (float): Initial controller state
            ua0 (float): Initial controller state

        """        
       
        self.Vdc = self.Vdc_ref  #DC link voltage        
        self.Ppv = self.Ppv_calc(self.Vdc_actual) #PV module power output    
        
         #Initialize all states with steady state values at current operating point
        if self.STEADY_STATE_INITIALIZATION:
            #ia0,xa0,ua0,ib0,xb0,ub0,ic0,xc0,uc0,Vdc0,xDC0,xQ0,xPLL0,wte0
            self.steady_state_calc()
        else:
            #Phase a
            self.ia = ia0
            self.xa = xa0
            self.ua = ua0
            
            #DC link voltage and reactive power controller
            self.xDC = xDC0
            self.xQ = xQ0

            #PLL
            self.xPLL = xPLL0
            self.wte = wte0

            if type(self).__name__ == 'SolarPV_DER_ThreePhase':
                ib0 = utility_functions.Ub_calc(ia0)
                xb0 = utility_functions.Ub_calc(xa0)
                ub0 = utility_functions.Ub_calc(ua0)
                
                ic0 = utility_functions.Uc_calc(ia0)
                xc0 = utility_functions.Uc_calc(xa0)
                uc0 = utility_functions.Uc_calc(ua0)
        
                #Phase b
                self.ib = ib0
                self.xb = xb0  #Shift by -120 degrees
                self.ub = ub0

                #Phase c
                self.ic = ic0
                self.xc = xc0   #Shift by +120 degrees
                self.uc = uc0
示例#2
0
    def __init__(self,
                 events,
                 unbalance_ratio_b=1.0,
                 unbalance_ratio_c=1.0,
                 Z2_actual=1.61 + 1j * 5.54):
        """Creates an instance of `GridSimulation`.
        
        Args:
          events: An instance of `SimulationEvents`.
          unbalance_ratio_b,unbalance_ratio_c: Scalar specifying difference in Phase B and Phase C voltage magnitude compared to phase A.
          Z2_actual: Complex scalar specifying the impedance of the feeder connecting the DER with the voltage source.
        """

        #Increment count
        Grid.grid_count = Grid.grid_count + 1
        #Events object
        self.events = events

        #Object name
        self.name = 'grid_' + str(Grid.grid_count)

        #Voltage unbalance
        self.unbalance_ratio_b = unbalance_ratio_b
        self.unbalance_ratio_c = unbalance_ratio_c

        #Grid impedance
        self.Z2_actual = Z2_actual
        self.R2_actual = self.Z2_actual.real
        self.L2_actual = self.Z2_actual.imag / (2 * math.pi * 60.0)

        #Converting to per unit
        self.R2 = self.R2_actual / self.Zbase  #Transmission line resistance
        self.L2 = self.L2_actual / self.Lbase  #Transmission line resistance

        self.Z2 = self.Z2_actual / self.Zbase  #Transmission line impedance

        self.transmission_name = 'transmission_' + str(Grid.grid_count)
        #Grid voltage/frequency events
        self.Vagrid, self.wgrid = events.grid_events(
            t=0.0)  #Grid voltage and frequency set-point
        self.Vagrid = self.Vagrid * (self.Vgridrated / self.Vbase)
        self.Vbgrid = utility_functions.Ub_calc(self.Vagrid *
                                                self.unbalance_ratio_b)
        self.Vcgrid = utility_functions.Uc_calc(self.Vagrid *
                                                self.unbalance_ratio_c)
        #Actual Grid voltage
        self.vag = self.Vagrid
        self.vbg = utility_functions.Ub_calc(self.vag * self.unbalance_ratio_b)
        self.vcg = utility_functions.Uc_calc(self.vag * self.unbalance_ratio_c)
        self.Vgrms = self.Vgrms_calc()
示例#3
0
    def steady_state_model(self, t):
        """Grid voltage change."""

        Vagrid_new, wgrid_new = self.events.grid_events(t)
        Vagrid_new = Vagrid_new * (self.Vgridrated / self.Vbase)

        if abs(self.Vagrid -
               Vagrid_new) > 0.0 and t >= self._t_voltage_previous:
            utility_functions.print_to_terminal(
                "{}:Grid voltage changed from {:.3f} V to {:.3f} V at {:.3f} s"
                .format(self.name, self.Vagrid, Vagrid_new, t))

            self.Vagrid = Vagrid_new
            self.Vbgrid = utility_functions.Ub_calc(self.Vagrid *
                                                    self.unbalance_ratio_b)
            self.Vcgrid = utility_functions.Uc_calc(self.Vagrid *
                                                    self.unbalance_ratio_c)

            self._t_voltage_previous = t

        if abs(self.wgrid -
               wgrid_new) > 0.0 and t >= self._t_frequency_previous:
            utility_functions.print_to_terminal(
                "{}:Grid frequency changed from {:.3f} Hz to {:.3f} Hz at {:.3f} s"
                .format(self.name, self.wgrid / (2.0 * math.pi),
                        wgrid_new / (2.0 * math.pi), t))

            self.wgrid = wgrid_new
            self._t_frequency_previous = t

        self.vag = self.Vagrid
        self.vbg = self.Vbgrid
        self.vcg = self.Vcgrid
    def test_steady_state_calc(self):
        """Test PV-DER three phase mode."""

        events = SimulationEvents()

        voltage_list = [(self.Va, self.Vb, self.Vc),
                        (cmath.rect(206.852, math.radians(-36.9906)),
                         cmath.rect(206.128, math.radians(-157.745)),
                         cmath.rect(208.387, math.radians(82.7291))),
                        (169.18 + 118.52j,
                         utility_functions.Ub_calc(169.18 + 118.52j),
                         utility_functions.Uc_calc(169.18 + 118.52j))]

        for voltages in voltage_list:
            Va = voltages[0]
            Vb = voltages[1]
            Vc = voltages[2]

            print('Testing voltages:{}'.format(voltages))

            PVDER = SolarPV_DER_ThreePhase(
                events=events,
                Sinverter_rated=self.power_rating,
                Vrms_rated=self.Vrms,  #175
                gridVoltagePhaseA=Va,
                gridVoltagePhaseB=Vb,
                gridVoltagePhaseC=Vc,
                gridFrequency=self.wgrid,
                standAlone=False,
                STEADY_STATE_INITIALIZATION=True,
                verbosity='INFO')

            self.assertAlmostEqual(
                PVDER.Ppv,
                PVDER.S.real,
                delta=0.001,
                msg=
                'Inverter power output must be equal to PV module power output at steady-state!'
            )
            self.assertAlmostEqual(
                PVDER.S_PCC.imag,
                PVDER.Q_ref,
                delta=0.001,
                msg=
                'Inverter reactive power output must be equal to Q reference!')

            self.assertAlmostEqual(
                PVDER.Vdc,
                PVDER.Vdc_ref,
                delta=0.001,
                msg='DC link voltage should be equal to reference!')

            self.assertAlmostEqual(PVDER.ma + PVDER.mb + PVDER.mc,
                                   0.0 + 1j * 0.0,
                                   delta=0.001,
                                   msg='Duty cycles should sum to zero!')
            self.assertLess(
                abs(PVDER.ma),
                1.0,
                msg='Magnitude of duty cycle should be less than 1!')
示例#5
0
    def getDERRatedPower(self, powerRating, voltageRating):
        """Return actual real and reactive power rating of DER for given power and voltage rating.
        
        Args:
             powerRating (float): Rated power of DER in kW. 
             voltageRating (float): Rated voltage of DER in L-G RMS. 
        """

        DERFilePath = OpenDSSData.config['myconfig']['DERFilePath']
        DERModelType = OpenDSSData.config['myconfig']['DERModelType']

        Va = cmath.rect(voltageRating * math.sqrt(2), 0.0)
        Vb = utility_functions.Ub_calc(Va)
        Vc = utility_functions.Uc_calc(Va)

        PVDER_model = DERModel(modelType=DERModelType,
                               events=events,
                               configFile=DERFilePath,
                               powerRating=powerRating * 1e3,
                               VrmsRating=voltageRating,
                               gridVoltagePhaseA=Va,
                               gridVoltagePhaseB=Vb,
                               gridVoltagePhaseC=Vc,
                               gridFrequency=2 * math.pi * 60.0,
                               standAlone=False,
                               steadyStateInitialization=True)
        self.PV_model = PVDER_model.DER_model

        return DER_model.S_PCC.real * DER_model.Sbase, DER_model.S_PCC.imag * DER_model.Sbase
    def test_steady_state_calc(self):
        """Test PV-DER three phase mode."""

        events = SimulationEvents()

        voltage_list = [(self.Va, self.Vb, self.Vc),
                        (cmath.rect(206.852, math.radians(-36.9906)),
                         cmath.rect(206.128, math.radians(-157.745)),
                         cmath.rect(208.387, math.radians(82.7291))),
                        (169.18 + 118.52j,
                         utility_functions.Ub_calc(169.18 + 118.52j),
                         utility_functions.Uc_calc(169.18 + 118.52j))]

        for voltages in voltage_list:
            Va = voltages[0]
            Vb = voltages[1]
            Vc = voltages[2]

            print('Testing voltages:{}'.format(voltages))

            PVDER = SolarPVDERThreePhase(events=events,
                                         configFile=config_file,
                                         **{
                                             **self.flag_arguments,
                                             **self.ratings_arguments,
                                             **self.voltage_arguments
                                         })

            self.assertAlmostEqual(
                PVDER.Ppv,
                PVDER.S.real,
                delta=0.001,
                msg=
                'Inverter power output must be equal to PV module power output at steady-state!'
            )
            self.assertAlmostEqual(
                PVDER.S_PCC.imag,
                PVDER.Q_ref,
                delta=0.001,
                msg=
                'Inverter reactive power output must be equal to Q reference!')

            self.assertAlmostEqual(
                PVDER.Vdc,
                PVDER.Vdc_ref,
                delta=0.001,
                msg='DC link voltage should be equal to reference!')

            self.assertAlmostEqual(PVDER.ma + PVDER.mb + PVDER.mc,
                                   0.0 + 1j * 0.0,
                                   delta=0.001,
                                   msg='Duty cycles should sum to zero!')
            self.assertLess(
                abs(PVDER.ma),
                1.0,
                msg='Magnitude of duty cycle should be less than 1!')
 def update_voltages(self):
     """Update voltages."""
     
     #Update inverter terminal voltage
     self.vta = self.vta_calc()
     self.vtb = self.vtb_calc()
     self.vtc = self.vtc_calc()
             
     #Update PCC LV side voltage
     self.va = self.va_calc()
     self.vb = utility_functions.Ub_calc(self.va)
     self.vc = utility_functions.Uc_calc(self.va)
 def update_inverter_states(self,ia,xa,ua,Vdc,xDC,xQ,xPLL,wte):
     """Update inverter states"""
     
     self.ia = ia
     self.xa = xa
     self.ua = ua
     
     self.ib = utility_functions.Ub_calc(self.ia)
     self.xb = utility_functions.Ub_calc(self.xa)
     self.ub = utility_functions.Ub_calc(self.ua)        
     
     self.ic = utility_functions.Uc_calc(self.ia)
     self.xc = utility_functions.Uc_calc(self.xa)
     self.uc = utility_functions.Uc_calc(self.ua)        
     
     self.Vdc = Vdc
     self.xDC = xDC
     self.xQ = xQ
     
     self.xPLL = xPLL
     self.wte = wte
 def update_grid_measurements(self,gridVoltagePhaseA, gridVoltagePhaseB, gridVoltagePhaseC):
     """Update grid voltage and frequency in non-standalone model.
     Args:
          gridVoltagePhaseA (complex): Value of gridVoltagePhaseA
          gridVoltagePhaseB (complex): Value of gridVoltagePhaseB
          gridVoltagePhaseC (complex): Value of gridVoltagePhaseC             
     
     """
     
     self.PV_model.gridVoltagePhaseA = gridVoltagePhaseA
     
     if type(self.PV_model).__name__ == 'SolarPVDERThreePhase':
         self.PV_model.gridVoltagePhaseB = gridVoltagePhaseB
         self.PV_model.gridVoltagePhaseC = gridVoltagePhaseC
     elif type(self.PV_model).__name__ == 'SolarPVDERThreePhaseBalanced':
         self.PV_model.gridVoltagePhaseB = utility_functions.Ub_calc(gridVoltagePhaseA)
         self.PV_model.gridVoltagePhaseC = utility_functions.Uc_calc(gridVoltagePhaseA)
    def time_series_vgrid(self):
        """Time series grid frequency."""

        self.vag_t = []
        self.vbg_t = []
        self.vcg_t = []
        for i, t in enumerate(
                self.t
        ):  #Loop through grid events and calculate wgrid at each time step

            Vagrid_new, _ = self.simulation_events.grid_events(t)

            #Conversion of grid voltage setpoint
            self.grid_model.vag = Vagrid_new * (self.grid_model.Vgridrated /
                                                self.Vbase)
            self.grid_model.vbg = utility_functions.Ub_calc(
                self.grid_model.vag * self.grid_model.unbalance_ratio_b)
            self.grid_model.vcg = utility_functions.Uc_calc(
                self.grid_model.vag * self.grid_model.unbalance_ratio_c)

            self.vag_t.append(self.grid_model.vag)
            self.vbg_t.append(self.grid_model.vbg)
            self.vcg_t.append(self.grid_model.vcg)

        self.vag_t = np.asarray(self.vag_t)
        self.vbg_t = np.asarray(self.vbg_t)
        self.vcg_t = np.asarray(self.vcg_t)

        self.vagR_t = self.vag_t.real
        self.vagI_t = self.vag_t.imag

        self.vbgR_t = self.vbg_t.real
        self.vbgI_t = self.vbg_t.imag

        self.vcgR_t = self.vcg_t.real
        self.vcgI_t = self.vcg_t.imag

        if not self.LOOP_MODE:
            self.simulation_events.reset_event_counters(
            )  #reset event counters
    def collect_states(self,solution):
        """Collect states from ode solution."""
        
         #Phase a states
        self.iaR_t = solution[:,0]
        self.iaI_t = solution[:,1]
        self.xaR_t = solution[:,2]
        self.xaI_t = solution[:,3]
        self.uaR_t = solution[:,4]
        self.uaI_t = solution[:,5]              
        
        if type(self.PV_model).__name__ == 'SolarPVDERSinglePhase':
            #DC link voltage variables
            self.Vdc_t = solution[:,6]
            self.xDC_t = solution[:,7]
            self.xQ_t = solution[:,8]
            #PLL variables
            self.xPLL_t = solution[:,9]
            #Frequency integration to get angle
            self.wte_t = solution[:,10]

        elif type(self.PV_model).__name__ == 'SolarPVDERThreePhase':
            
            #Phase b states
            self.ibR_t = solution[:,6]
            self.ibI_t = solution[:,7]
            self.xbR_t = solution[:,8]
            self.xbI_t = solution[:,9]
            self.ubR_t = solution[:,10]
            self.ubI_t = solution[:,11]

            #Phase c states
            self.icR_t = solution[:,12]
            self.icI_t = solution[:,13]
            self.xcR_t = solution[:,14]
            self.xcI_t = solution[:,15]
            self.ucR_t = solution[:,16]
            self.ucI_t = solution[:,17]

            #DC link voltage variables
            self.Vdc_t = solution[:,18]
            self.xDC_t = solution[:,19]
            self.xQ_t = solution[:,20]

            #PLL variables
            self.xPLL_t = solution[:,21]
            #Frequency integration to get angle
            self.wte_t = solution[:,22]        
        
        elif type(self.PV_model).__name__ == 'SolarPVDER_SinglePhaseConstantVdc':
            self.Vdc_t = np.array([self.PV_model.Vdc]*len(self.iaR_t))
                        
            self.xP_t = solution[:,6] #Active power control variable
            self.xQ_t = solution[:,7] #Reactive power control variable
            
            self.xPLL_t = solution[:,8] #PLL variables            
            self.wte_t = solution[:,9] #Frequency integration to get angle
        
        elif type(self.PV_model).__name__ == 'SolarPVDERThreePhaseConstantVdc':
           #Phase b states
            self.ibR_t = solution[:,6]
            self.ibI_t = solution[:,7]
            self.xbR_t = solution[:,8]
            self.xbI_t = solution[:,9]
            self.ubR_t = solution[:,10]
            self.ubI_t = solution[:,11]

            #Phase c states
            self.icR_t = solution[:,12]
            self.icI_t = solution[:,13]
            self.xcR_t = solution[:,14]
            self.xcI_t = solution[:,15]
            self.ucR_t = solution[:,16]
            self.ucI_t = solution[:,17]
            
            self.Vdc_t = np.array([self.PV_model.Vdc]*len(self.iaR_t))
            
            self.xP_t = solution[:,18]  #Active power control variable
            self.xQ_t = solution[:,19]  #Reactive power control variable
            
            self.xPLL_t = solution[:,20] #PLL variables            
            self.wte_t = solution[:,21] #Frequency integration to get angle
            
        elif type(self.PV_model).__name__ == 'SolarPVDERThreePhaseBalanced':
            
            ia_t = self.iaR_t+self.iaI_t*1j
            xa_t = self.xaR_t+self.xaI_t*1j
            ua_t = self.uaR_t+self.uaI_t*1j
            
            ib_t = utility_functions.Ub_calc(ia_t)
            xb_t = utility_functions.Ub_calc(xa_t)
            ub_t = utility_functions.Ub_calc(ua_t)
            
            ic_t = utility_functions.Uc_calc(ia_t)
            xc_t = utility_functions.Uc_calc(xa_t)
            uc_t = utility_functions.Uc_calc(ua_t)            
            
            self.ibR_t = ib_t.real 
            self.ibI_t = ib_t.imag 
            self.xbR_t = xb_t.real 
            self.xbI_t = xb_t.imag 
            self.ubR_t = ub_t.real
            self.ubI_t = ub_t.imag 

            self.icR_t = ic_t.real 
            self.icI_t = ic_t.imag 
            self.xcR_t = xc_t.real 
            self.xcI_t = xc_t.imag 
            self.ucR_t = uc_t.real 
            self.ucI_t = uc_t.imag
            
            #DC link voltage variables
            self.Vdc_t = solution[:,6]
            self.xDC_t = solution[:,7]
            self.xQ_t = solution[:,8]
            #PLL variables
            self.xPLL_t = solution[:,9]
            #Frequency integration to get angle
            self.wte_t = solution[:,10]
    def initialize_y0_t(self):
        """Initialize y0_t."""
        
        self.iaR_t = np.array([self.PV_model.y0[0]])
        self.iaI_t = np.array([self.PV_model.y0[1]])
        self.xaR_t = np.array([self.PV_model.y0[2]])
        self.xaI_t = np.array([self.PV_model.y0[3]])
        self.uaR_t = np.array([self.PV_model.y0[4]])
        self.uaI_t = np.array([self.PV_model.y0[5]])
        
        if type(self.PV_model).__name__ == 'SolarPVDERSinglePhase':            
            self.Vdc_t = np.array([self.PV_model.y0[6]]) #DC link voltage variable
            
            self.xDC_t = np.array([self.PV_model.y0[7]]) #DC link voltage control variable
            self.xQ_t = np.array([self.PV_model.y0[8]]) #Reactive power control variable
            
            self.xPLL_t = np.array([self.PV_model.y0[9]]) #PLL variables            
            self.wte_t = np.array([self.PV_model.y0[10]]) #Frequency integration to get angle
        
        elif type(self.PV_model).__name__ == 'SolarPVDERThreePhase':
            self.ibR_t = np.array([self.PV_model.y0[6]])
            self.ibI_t = np.array([self.PV_model.y0[7]])
            self.xbR_t = np.array([self.PV_model.y0[8]])
            self.xbI_t = np.array([self.PV_model.y0[9]])
            self.ubR_t = np.array([self.PV_model.y0[10]])
            self.ubI_t = np.array([self.PV_model.y0[11]])

            self.icR_t = np.array([self.PV_model.y0[12]])
            self.icI_t = np.array([self.PV_model.y0[13]])
            self.xcR_t = np.array([self.PV_model.y0[14]])
            self.xcI_t = np.array([self.PV_model.y0[15]])
            self.ucR_t = np.array([self.PV_model.y0[16]])
            self.ucI_t = np.array([self.PV_model.y0[17]])

            self.Vdc_t = np.array([self.PV_model.y0[18]])
            
            self.xDC_t = np.array([self.PV_model.y0[19]])
            self.xQ_t = np.array([self.PV_model.y0[20]])
            
            self.xPLL_t = np.array([self.PV_model.y0[21]])
            self.wte_t = np.array([self.PV_model.y0[22]])
            
        elif type(self.PV_model).__name__ == 'SolarPVDERThreePhaseConstantVdc':
            self.ibR_t = np.array([self.PV_model.y0[6]])
            self.ibI_t = np.array([self.PV_model.y0[7]])
            self.xbR_t = np.array([self.PV_model.y0[8]])
            self.xbI_t = np.array([self.PV_model.y0[9]])
            self.ubR_t = np.array([self.PV_model.y0[10]])
            self.ubI_t = np.array([self.PV_model.y0[11]])

            self.icR_t = np.array([self.PV_model.y0[12]])
            self.icI_t = np.array([self.PV_model.y0[13]])
            self.xcR_t = np.array([self.PV_model.y0[14]])
            self.xcI_t = np.array([self.PV_model.y0[15]])
            self.ucR_t = np.array([self.PV_model.y0[16]])
            self.ucI_t = np.array([self.PV_model.y0[17]])
            
            self.Vdc_t = np.array([self.PV_model.Vdc]) #Voltage is constant
            
            self.xP_t = np.array([self.PV_model.y0[18]])  #Active power control variable
            self.xQ_t = np.array([self.PV_model.y0[19]])  #Reactive power control variable
            
            self.xPLL_t = np.array([self.PV_model.y0[20]]) #PLL variables            
            self.wte_t = np.array([self.PV_model.y0[21]]) #Frequency integration to get angle
        
        elif type(self.PV_model).__name__ == 'SolarPVDERThreePhaseBalanced':            
            
            ia_t = self.iaR_t+self.iaI_t*1j
            xa_t = self.xaR_t+self.xaI_t*1j
            ua_t = self.uaR_t+self.uaI_t*1j
            
            ib_t = utility_functions.Ub_calc(ia_t)
            xb_t = utility_functions.Ub_calc(xa_t)
            ub_t = utility_functions.Ub_calc(ua_t)
            
            ic_t = utility_functions.Uc_calc(ia_t)
            xc_t = utility_functions.Uc_calc(xa_t)
            uc_t = utility_functions.Uc_calc(ua_t)            
            
            self.ibR_t = ib_t.real 
            self.ibI_t = ib_t.imag 
            self.xbR_t = xb_t.real 
            self.xbI_t = xb_t.imag 
            self.ubR_t = ub_t.real
            self.ubI_t = ub_t.imag 

            self.icR_t = ic_t.real 
            self.icI_t = ic_t.imag 
            self.xcR_t = xc_t.real 
            self.xcI_t = xc_t.imag 
            self.ucR_t = uc_t.real 
            self.ucI_t = uc_t.imag
            
            self.Vdc_t = np.array([self.PV_model.y0[6]]) #DC link voltage variable
            
            self.xDC_t = np.array([self.PV_model.y0[7]]) #DC link voltage control variable
            self.xQ_t = np.array([self.PV_model.y0[8]]) #Reactive power control variable
            
            self.xPLL_t = np.array([self.PV_model.y0[9]]) #PLL variables            
            self.wte_t = np.array([self.PV_model.y0[10]]) #Frequency integration to get angle
        
        elif type(self.PV_model).__name__ == 'SolarPVDERSinglePhaseConstantVdc':        
            self.Vdc_t = np.array([self.PV_model.Vdc]) #Voltage is constant
            
            self.xP_t = np.array([self.PV_model.y0[6]])  #Active power control variable
            self.xQ_t = np.array([self.PV_model.y0[7]])  #Reactive power control variable
            
            self.xPLL_t = np.array([self.PV_model.y0[8]]) #PLL variables            
            self.wte_t = np.array([self.PV_model.y0[9]]) #Frequency integration to get angle
    def initialize_grid_measurements(self, DER_arguments):
        """Initialize inverter states.
        Args:
             gridVoltagePhaseA (complex): Value of gridVoltagePhaseA
             gridVoltagePhaseB (complex): Value of gridVoltagePhaseB
             gridVoltagePhaseC (complex): Value of gridVoltagePhaseC
             gridFrequency (float): Value of gridFrequency
        
        """

        if not self.standAlone:
            if 'gridFrequency' in DER_arguments:
                self.gridFrequency = DER_arguments['gridFrequency']
            else:
                raise ValueError(
                    'Grid voltage source Frequency need to be supplied if model is not stand alone!'
                )

            if templates.DER_design_template[
                    self.DER_model_type]['basic_specs'][
                        'n_phases'] >= 1:  #Check if model has one phase
                if 'gridVoltagePhaseA' in DER_arguments:
                    self.gridVoltagePhaseA = DER_arguments[
                        'gridVoltagePhaseA'] / self.Vbase
                else:
                    raise ValueError(
                        'Grid voltage source phase A need to be supplied if model is not stand alone!'
                    )

            if templates.DER_design_template[
                    self.DER_model_type]['basic_specs'][
                        'n_phases'] >= 2:  #Check if model has 2 phases
                if templates.DER_design_template[
                        self.DER_model_type]['basic_specs'][
                            'unbalanced']:  #Check if model is unbalanced
                    if 'gridVoltagePhaseB' in DER_arguments:
                        self.gridVoltagePhaseB = DER_arguments[
                            'gridVoltagePhaseB'] / self.Vbase
                    else:
                        raise ValueError(
                            'Grid voltage source phase B need to be supplied if model is not stand alone!'
                        )
                else:
                    self.gridVoltagePhaseB = utility_functions.Ub_calc(
                        self.gridVoltagePhaseA)

            if templates.DER_design_template[
                    self.DER_model_type]['basic_specs'][
                        'n_phases'] >= 3:  #Check if model has 3 phases
                if templates.DER_design_template[
                        self.DER_model_type]['basic_specs'][
                            'unbalanced']:  #Check if model is unbalanced
                    if 'gridVoltagePhaseC' in DER_arguments:
                        self.gridVoltagePhaseC = DER_arguments[
                            'gridVoltagePhaseC'] / self.Vbase
                    else:
                        raise ValueError(
                            'Grid voltage source phase C need to be supplied if model is not stand alone!'
                        )
                else:
                    self.gridVoltagePhaseC = utility_functions.Uc_calc(
                        self.gridVoltagePhaseA)

            if templates.DER_design_template[
                    self.DER_model_type]['basic_specs'][
                        'n_phases'] >= 4:  #Check if model has 3 phases
                raise ValueError('Model has more than 3 phases!')
    def initialize_states(self, DER_arguments):
        """Initialize inverter states.

        Args:
            ia0 (float): Initial current
            xa0 (float): Initial controller state
            ua0 (float): Initial controller state

        """

        if 'ia' in DER_arguments:
            ia0 = DER_arguments['ia']
        else:
            ia0 = self.DER_config['initial_states'][
                'iaR'] + 1j * self.DER_config['initial_states']['iaI']
        if 'xa' in DER_arguments:
            xa0 = DER_arguments['xa']
        else:
            xa0 = self.DER_config['initial_states'][
                'xaR'] + 1j * self.DER_config['initial_states']['xaI']
        if 'ua' in DER_arguments:
            ua0 = DER_arguments['ua']
        else:
            ua0 = self.DER_config['initial_states'][
                'uaR'] + 1j * self.DER_config['initial_states']['uaI']

        if 'xDC' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            if 'xDC' in DER_arguments:
                xDC0 = DER_arguments['xDC']
            else:
                xDC0 = self.DER_config['initial_states']['xDC']

        if 'xP' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            if 'xP' in DER_arguments:
                xP0 = DER_arguments['xP']
            else:
                xP0 = self.DER_config['initial_states']['xP']

        if 'xQ' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            if 'xQ' in DER_arguments:
                xQ0 = DER_arguments['xQ']
            else:
                xQ0 = self.DER_config['initial_states']['xQ']

        xPLL0 = self.DER_config['initial_states']['xPLL']
        wte0 = self.DER_config['initial_states']['wte']

        self.Vdc = self.Vdc_ref  #DC link voltage
        self.Ppv = self.Ppv_calc(self.Vdc_actual)  #PV module power output

        #Initialize all states with steady state values at current operating point
        if self.steady_state_initialization:
            self.steady_state_calc()
        else:
            #Phase a
            self.ia = ia0
            self.xa = xa0
            self.ua = ua0

            if 'xDC' in templates.DER_design_template[
                    self.DER_model_type]['initial_states']:
                self.xDC = xDC0  #DC link voltage controller
            if 'xP' in templates.DER_design_template[
                    self.DER_model_type]['initial_states']:
                self.xP = xP0  #Active power controller
            if 'xQ' in templates.DER_design_template[
                    self.DER_model_type]['initial_states']:
                self.xQ = xQ0  #Reactive power controller

            self.xPLL = xPLL0  #PLL
            self.wte = wte0

            if self.DER_model_type in templates.three_phase_models:
                ib0 = utility_functions.Ub_calc(ia0)
                xb0 = utility_functions.Ub_calc(xa0)
                ub0 = utility_functions.Ub_calc(ua0)

                ic0 = utility_functions.Uc_calc(ia0)
                xc0 = utility_functions.Uc_calc(xa0)
                uc0 = utility_functions.Uc_calc(ua0)

                #Phase b
                self.ib = ib0
                self.xb = xb0  #Shift by -120 degrees
                self.ub = ub0

                #Phase c
                self.ic = ic0
                self.xc = xc0  #Shift by +120 degrees
                self.uc = uc0
    def power_error_calc(self, x):
        """Function for power."""

        maR = x[0]
        maI = x[1]
        iaR = x[2]
        iaI = x[3]

        ma = maR + 1j * maI

        ia = self.ia = iaR + 1j * iaI

        vta = ma * (self.Vdc / 2)
        va = self.va_calc()

        St = (vta * ia.conjugate()) / 2
        S_PCC = (va * ia.conjugate()) / 2

        #Sloss_filter = ((abs(ia)/math.sqrt(2))**2)*self.Zf

        if self.DER_model_type in templates.three_phase_models:

            if not self.allow_unbalanced_m:
                mb = utility_functions.Ub_calc(ma)
                mc = utility_functions.Uc_calc(ma)

                ib = self.ib = utility_functions.Ub_calc(ia)
                ic = self.ic = utility_functions.Uc_calc(ia)

            elif self.allow_unbalanced_m:
                mbR = x[4]
                mbI = x[5]
                ibR = x[6]
                ibI = x[7]

                mcR = x[8]
                mcI = x[9]
                icR = x[10]
                icI = x[11]

                mb = mbR + 1j * mbI
                mc = mcR + 1j * mcI

                ib = self.ib = ibR + 1j * ibI
                ic = self.ic = icR + 1j * icI

            vtb = mb * (self.Vdc / 2)
            vtc = mc * (self.Vdc / 2)

            vb = self.vb_calc()
            vc = self.vc_calc()

            St = St + (vtb * ib.conjugate() + vtc * ic.conjugate()) / 2
            S_PCC = S_PCC + (vb * ib.conjugate() + vc * ic.conjugate()) / 2

            #Sloss_filter = Sloss_filter + ((abs(ib)/math.sqrt(2))**2 + (abs(ic)/math.sqrt(2))**2)*self.Zf

        P_error = (St.real - self.Ppv)**2
        Q_error = (S_PCC.imag - self.Q_ref)**2

        #Qloss_filter_expected = self.n_phases*((self.Ppv/(self.n_phases*self.Vrms_ref))**2)*self.Xf
        #Ploss_filter_expected = self.n_phases*((self.Ppv/(self.n_phases*self.Vrms_ref))**2)*self.Rf

        #P_PCC_error = ((S_PCC.real + Sloss_filter.real)   - self.Ppv)**2
        #S_error = (abs(St -(S_PCC+Sloss_filter)))**2
        #Q_error_filter_expected =  (St.imag - Qloss_filter_expected)**2

        if self.DER_model_type in templates.three_phase_models:
            del_1 = utility_functions.relative_phase_calc(ma, mb)
            del_2 = utility_functions.relative_phase_calc(ma, mc)
            del_3 = utility_functions.relative_phase_calc(mb, mc)

            if del_1 > math.pi:
                del_1 = abs(del_1 - 2 * math.pi)

            if del_2 > math.pi:
                del_2 = abs(del_2 - 2 * math.pi)

            if del_3 > math.pi:
                del_3 = abs(del_3 - 2 * math.pi)

            if self.allow_unbalanced_m:
                m_error = (abs((va + vb + vc) - (vta + vtb + vtc)))**2
            else:
                m_error = (del_1 - PHASE_DIFFERENCE_120)**2 + (del_2 - PHASE_DIFFERENCE_120)**2 + (del_3 - PHASE_DIFFERENCE_120)**2 +\
                          (abs(ma) - abs(mb))**2 + (abs(ma) - abs(mc))**2 + (abs(mb) - abs(mc))**2

            m_error = m_error

            i_error = (abs(ia + ib + ic) + abs(vta - va - ia * self.Zf) +
                       abs(vtb - vb - ib * self.Zf) +
                       abs(vtc - vc - ic * self.Zf))**2
        else:
            m_error = 0.0
            i_error = (abs(vta - va - ia * self.Zf))**2

        return P_error + Q_error + m_error + i_error  #+S_error + P_PCC_error
示例#16
0
 def steady_state_calc(self):
     """Find duty cycle and inverter current that minimize steady state error and return steady state values."""        
     
     self.logger.debug('Solving for steady state at current operating point.') 
     
     x0 = np.array([self.steadystate_values[self.parameter_ID]['maR0'],
                    self.steadystate_values[self.parameter_ID]['maI0'],
                    self.steadystate_values[self.parameter_ID]['iaR0'],
                    self.steadystate_values[self.parameter_ID]['iaI0']])        
             
     disp = bool(self.verbosity == 'DEBUG')
     result = minimize(self.power_error_calc, x0, method='nelder-mead',options={'xtol': 1e-8, 'disp': disp, 'maxiter':10000})
     
     if not result.success:
         raise ValueError('Steady state solution did not converge! Change operating point or disable steady state flag and try again.')
     
     ma0 = result.x[0] + 1j*result.x[1]
     self.ia = result.x[2] + 1j*result.x[3]
     self.ua = 0.0+0.0j
     self.xa = ma0
     self.vta = self.vta_calc()
     self.va = self.va_calc()
     
     self.xDC = self.ia.real
     self.xQ = self.ia.imag
     
     self.xPLL = 0.0
     self.wte = 2*math.pi
     
     if type(self).__name__ == 'SolarPV_DER_ThreePhase':
         mb0 = utility_functions.Ub_calc(ma0)
         mc0 = utility_functions.Uc_calc(ma0)
         
         #mb0 = result.x[4] + 1j*result.x[5]
         #mc0 = result.x[8] + 1j*result.x[9]
         
         self.xb = mb0
         self.xc = mc0
         
         self.ib = utility_functions.Ub_calc(self.ia)
         self.ic = utility_functions.Uc_calc(self.ia)
         
         #self.ib = result.x[6] + 1j*result.x[7]
         #self.ic = result.x[10] + 1j*result.x[11]
         
         self.ub = 0.0+0.0j
         self.uc = 0.0+0.0j            
         
         self.vtb = self.vtb_calc()
         self.vtc = self.vtc_calc()
         
         self.vb = self.vb_calc()
         self.vc = self.vc_calc()
     
     self.S =  self.S_calc()
     self.S_PCC = self.S_PCC_calc()
     self.Vtrms = self.Vtrms_calc()
     self.Vrms = self.Vrms_calc()
     self.Irms = self.Irms_calc()
     
     self.logger.debug('{}:Steady state values for operating point defined by Ppv:{:.2f} W, Vdc:{:.2f} V, va:{:.2f} V found at:'.format(self.name,self.Ppv*self.Sbase,self.Vdc*self.Vdcbase,self.va*self.Vbase))
         
     if self.verbosity == 'DEBUG':
         self.show_PV_DER_states(quantity='power')
         self.show_PV_DER_states(quantity='duty cycle')
         self.show_PV_DER_states(quantity='voltage')
         self.show_PV_DER_states(quantity='current')
示例#17
0
    def power_error_calc(self,x):
        """Function for power."""
        
        maR = x[0]
        maI = x[1]
        iaR = x[2]
        iaI = x[3]
        
        ma = maR + 1j*maI
        
        ia = self.ia = iaR + 1j*iaI
        
        vta = ma*(self.Vdc/2)
        va = self.va_calc()
        
        St = (vta*ia.conjugate())/2
        S_PCC = (va*ia.conjugate())/2

        Ploss_filter = ((abs(ia)/math.sqrt(2))**2)*self.Rf 
        Qloss_filter = ((abs(ia)/math.sqrt(2))**2)*self.Xf
    
        if type(self).__name__ == 'SolarPV_DER_ThreePhase':
            mb = utility_functions.Ub_calc(ma)
            mc = utility_functions.Uc_calc(ma)
            
            ib = self.ib = utility_functions.Ub_calc(ia)
            ic = self.ic = utility_functions.Uc_calc(ia)
                        
            #mbR = x[4]
            #mbI = x[5]
            #ibR = x[6]
            #ibI = x[7]
            
            #mcR = x[8]
            #mcI = x[9]
            #icR = x[10]
            #icI = x[11]            
            
            #mb = mbR + 1j*mbI
            #mc = mcR + 1j*mcI
            
            #ib = self.ib = ibR + 1j*ibI
            #ic = self.ic = icR + 1j*icI
            
            vtb = mb*(self.Vdc/2)
            vtc = mc*(self.Vdc/2)
            
            vb = self.vb_calc()
            vc = self.vc_calc()
            
            St = St + (vtb*ib.conjugate() + vtc*ic.conjugate())/2
            S_PCC = S_PCC + (vb*ib.conjugate() + vc*ic.conjugate())/2
            
            Ploss_filter = Ploss_filter + ((abs(ib)/math.sqrt(2))**2)*self.Rf + ((abs(ic)/math.sqrt(2))**2)*self.Rf
            Qloss_filter = Qloss_filter + ((abs(ib)/math.sqrt(2))**2)*self.Xf + ((abs(ic)/math.sqrt(2))**2)*self.Xf   
            
            Qloss_filter_expected = 3*((self.Ppv/(3*self.Vrms_ref))**2)*self.Xf
        
        #print('solver:',ma,mb,mc,Qloss_filter_expected)
        
        P_PCC_error = ((S_PCC.real + Ploss_filter)   - self.Ppv)**2 
        Q_PCC_error = (S_PCC.imag - self.Q_ref)**2   
        P_error = (St.real - self.Ppv)**2
        Q_error = (St.imag - Qloss_filter - self.Q_ref)**2
        
        Q_error_filter_expected = (St.imag - Qloss_filter_expected)**2
                
        del_1 = utility_functions.relative_phase_calc(ma,mb)
        del_2 = utility_functions.relative_phase_calc(ma,mc)
        del_3 = utility_functions.relative_phase_calc(mb,mc)
        
        if del_1 > math.pi:
            del_1 = abs(del_1 - 2*math.pi)
            
        if del_2 > math.pi:
            del_2 = abs(del_2 - 2*math.pi)
        
        if del_3> math.pi:
            del_3 = abs(del_3 - 2*math.pi)
        
        #m_error =  abs(ma+mb+mc)        
        m_error = (del_1 - PHASE_DIFFERENCE_120)**2 + (del_2 - PHASE_DIFFERENCE_120)**2 + (del_3 - PHASE_DIFFERENCE_120)**2 +\
                  (abs(ma) - abs(mb))**2 + (abs(ma) - abs(mc))**2 + (abs(mb) - abs(mc))**2 
        
        return P_PCC_error  + Q_PCC_error + P_error  + m_error + Q_error #+ Q_error_filter_expected
示例#18
0
    def ib_ref_activepower_control(self):
        """Phase B current reference for constant Vdc"""

        return utility_functions.Ub_calc(self.ia_ref)
    def ib_ref_calc(self):
        """Phase B current reference"""

        return utility_functions.Ub_calc(self.ia_ref)
    def steady_state_calc(self):
        """Find duty cycle and inverter current that minimize steady state error and return steady state values."""

        self.logger.debug(
            'Solving for steady state at current operating point.')

        if self.standAlone:
            x0 = [
                self.steadystate_values[self.parameter_ID]['maR0'],
                self.steadystate_values[self.parameter_ID]['maI0'],
                self.steadystate_values[self.parameter_ID]['iaR0'],
                self.steadystate_values[self.parameter_ID]['iaI0']
            ]

        else:
            va = self.va_calc()
            x0 = [
                va.real, va.imag,
                self.steadystate_values[self.parameter_ID]['iaR0'],
                self.steadystate_values[self.parameter_ID]['iaI0']
            ]

        if self.allow_unbalanced_m:
            self.logger.info(
                'Using unbalanced option - steady state duty cycles may be unbalanced.'
            )
            if self.standAlone:
                x0.extend([
                    self.steadystate_values[self.parameter_ID]['mbR0'],
                    self.steadystate_values[self.parameter_ID]['mbI0'],
                    self.steadystate_values[self.parameter_ID]['ibR0'],
                    self.steadystate_values[self.parameter_ID]['ibI0'],
                    self.steadystate_values[self.parameter_ID]['mcR0'],
                    self.steadystate_values[self.parameter_ID]['mcI0'],
                    self.steadystate_values[self.parameter_ID]['icR0'],
                    self.steadystate_values[self.parameter_ID]['icI0']
                ])
            else:
                vb = self.vb_calc()
                vc = self.vc_calc()

                x0.extend([
                    vb.real, vb.imag,
                    self.steadystate_values[self.parameter_ID]['ibR0'],
                    self.steadystate_values[self.parameter_ID]['ibI0'],
                    vc.real, vc.imag,
                    self.steadystate_values[self.parameter_ID]['icR0'],
                    self.steadystate_values[self.parameter_ID]['icI0']
                ])

        x0 = np.array(x0)

        self.solver_spec[self.steadystate_solver].update(
            {'disp': bool(self.verbosity == 'DEBUG')})
        result = minimize(self.power_error_calc,
                          x0,
                          method=self.steadystate_solver,
                          options=self.solver_spec[self.steadystate_solver])

        if not result.success:
            raise ValueError(
                'Steady state solution did not converge! Change operating point or disable steady state flag and try again.'
            )

        if 'xDC' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            self.xDC = self.ia.real
        if 'xP' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            self.xP = self.ia.real
        if 'xQ' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            self.xQ = self.ia.imag
        if 'xPLL' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            self.xPLL = 0.0
        if 'wte' in templates.DER_design_template[
                self.DER_model_type]['initial_states']:
            self.wte = 2 * math.pi

        if self.DER_model_type in templates.single_phase_models or self.DER_model_type in templates.three_phase_models:
            ma0 = result.x[0] + 1j * result.x[1]
            self.ia = result.x[2] + 1j * result.x[3]
            self.xa = ma0
            self.ua = 0.0 + 0.0j
            self.vta = self.vta_calc()
            self.va = self.va_calc()

        if self.DER_model_type in templates.three_phase_models:

            if not self.allow_unbalanced_m:
                mb0 = utility_functions.Ub_calc(ma0)
                mc0 = utility_functions.Uc_calc(ma0)

                self.ib = utility_functions.Ub_calc(self.ia)
                self.ic = utility_functions.Uc_calc(self.ia)

            else:
                mb0 = result.x[4] + 1j * result.x[5]
                mc0 = result.x[8] + 1j * result.x[9]
                self.ib = result.x[6] + 1j * result.x[7]
                self.ic = result.x[10] + 1j * result.x[11]

            self.xb = mb0
            self.xc = mc0

            self.ub = 0.0 + 0.0j
            self.uc = 0.0 + 0.0j

            self.vtb = self.vtb_calc()
            self.vtc = self.vtc_calc()

            self.vb = self.vb_calc()
            self.vc = self.vc_calc()

        self.S = self.S_calc()
        self.S_PCC = self.S_PCC_calc()
        self.Vtrms = self.Vtrms_calc()
        self.Vrms = self.Vrms_calc()
        self.Irms = self.Irms_calc()

        self.logger.debug(
            '{}:Steady state values for operating point defined by Ppv:{:.2f} W, Vdc:{:.2f} V, va:{:.2f} V found at:'
            .format(self.name, self.Ppv * self.Sbase, self.Vdc * self.Vdcbase,
                    self.va * self.Vbase))

        if self.verbosity == 'DEBUG':
            self.show_PV_DER_states(quantity='power')
            self.show_PV_DER_states(quantity='duty cycle')
            self.show_PV_DER_states(quantity='voltage')
            self.show_PV_DER_states(quantity='current')