Source code for CADRE.power

''' Power discipline for CADRE '''

import numpy as np

from openmdao.main.api import Component
from openmdao.lib.datatypes.api import Array

import MBI
import os


[docs]class Power_CellVoltage(Component): ''' Compute the output voltage of the solar panels. ''' def __init__(self, n, dat=None): super(Power_CellVoltage, self).__init__() self.n = n if dat is None: fpath = os.path.dirname(os.path.realpath(__file__)) dat = np.genfromtxt(fpath + '/data/Power/curve.dat') self.add( 'LOS', Array(np.zeros((n)), size=(n, ), dtype=np.float, iotype="in", units='unitless', desc="Line of Sight over Time")) self.add( 'temperature', Array(np.zeros((5, n)), size=(5, n,), dtype=np.float, units="degK", desc="Temperature of solar cells over time", iotype="in")) self.add( 'exposedArea', Array(np.zeros((7, 12, n)), size=(7, 12, n), dtype=np.float, desc="Exposed area to sun for each solar cell over time", units="m**2", iotype="in")) self.add( 'Isetpt', Array(np.zeros((12, n)), size=(12, n), dtype=np.float, units="A", desc="Currents of the solar panels", iotype="in")) self.add( 'V_sol', Array(np.zeros((12, n)), size=(12, n), dtype=np.float, units="V", desc="Output voltage of solar panel over time", iotype="out")) nT, nA, nI = dat[:3] T = dat[3:3 + nT] A = dat[3 + nT:3 + nT + nA] I = dat[3 + nT + nA:3 + nT + nA + nI] V = dat[3 + nT + nA + nI:].reshape((nT, nA, nI), order='F') self.MBI = MBI.MBI(V, [T, A, I], [6, 6, 15], [3, 3, 3]) self.x = np.zeros((84 * self.n, 3), order='F') self.xV = self.x.reshape((self.n, 7, 12, 3), order='F') self.dV_dL = np.zeros((self.n, 12), order='F') self.dV_dT = np.zeros((self.n, 12, 5), order='F') self.dV_dA = np.zeros((self.n, 7, 12), order='F') self.dV_dI = np.zeros((self.n, 12), order='F')
[docs] def list_deriv_vars(self): input_keys = ('LOS', 'temperature', 'exposedArea', 'Isetpt',) output_keys = ('V_sol',) return input_keys, output_keys
[docs] def setx(self): for p in range(12): i = 4 if p < 4 else (p % 4) for c in range(7): self.xV[:, c, p, 0] = self.temperature[i,:] self.xV[:, c, p, 1] = self.LOS * self.exposedArea[c, p,:] self.xV[:, c, p, 2] = self.Isetpt[p,:]
[docs] def execute(self): self.setx() self.raw = self.MBI.evaluate(self.x)[:, 0].reshape((self.n, 7, 12), order='F') self.V_sol = np.zeros((12, self.n)) for c in range(7): self.V_sol += self.raw[:, c,:].T
[docs] def provideJ(self): self.raw1 = self.MBI.evaluate(self.x, 1)[:, 0].reshape((self.n, 7, 12), order='F') self.raw2 = self.MBI.evaluate(self.x, 2)[:, 0].reshape((self.n, 7, 12), order='F') self.raw3 = self.MBI.evaluate(self.x, 3)[:, 0].reshape((self.n, 7, 12), order='F') self.dV_dL[:] = 0.0 self.dV_dT[:] = 0.0 self.dV_dA[:] = 0.0 self.dV_dI[:] = 0.0 for p in range(12): i = 4 if p < 4 else (p % 4) for c in range(7): self.dV_dL[:, p] += self.raw2[:, c, p] * self.exposedArea[c, p,:] self.dV_dT[:, p, i] += self.raw1[:, c, p] self.dV_dA[:, c, p] += self.raw2[:, c, p] * self.LOS self.dV_dI[:, p] += self.raw3[:, c, p]
[docs] def apply_deriv(self, arg, result): if 'V_sol' in result: if 'LOS' in arg: result['V_sol'] += self.dV_dL.T * arg['LOS'] if 'temperature' in arg: for p in range(12): i = 4 if p < 4 else (p % 4) result['V_sol'][p,:] += self.dV_dT[:, p, i] * arg['temperature'][i,:] if 'Isetpt' in arg: result['V_sol'] += self.dV_dI.T * arg['Isetpt'] if 'exposedArea' in arg: for p in range(12): result['V_sol'][p,:] += \ np.sum(self.dV_dA[:,:, p] * arg['exposedArea'][:, p,:].T, 1)
[docs] def apply_derivT(self, arg, result): if 'V_sol' in arg: for p in range(12): i = 4 if p < 4 else (p % 4) if 'LOS' in result: result['LOS'] += self.dV_dL[:, p] * arg['V_sol'][p,:] if 'temperature' in result: result['temperature'][i,:] += self.dV_dT[:, p, i] * arg['V_sol'][p,:] if 'Isetpt' in result: result['Isetpt'][p,:] += self.dV_dI[:, p] * arg['V_sol'][p,:] if 'exposedArea' in result: for c in range(7): result['exposedArea'][c, p,:] += self.dV_dA[:, c, p] * arg['V_sol'][p,:]
[docs]class Power_SolarPower(Component): ''' Compute the output power of the solar panels. ''' def __init__(self, n=2): super(Power_SolarPower, self).__init__() self.n = n self.add( 'Isetpt', Array( np.zeros((12, n)), size=(12, n), dtype=np.float, units="A", desc="Currents of the solar panels", iotype="in" ) ) self.add( 'V_sol', Array(np.zeros((12, n)), size=(12, n), dtype=np.float, units="V", desc="Output voltage of solar panel over time", iotype="in")) self.add('P_sol', Array(np.zeros((n, )), size=(n,), dtype=np.float, iotype="out", units="W", desc="Solar panels power over time"))
[docs] def list_deriv_vars(self): input_keys = ('Isetpt', 'V_sol',) output_keys = ('P_sol',) return input_keys, output_keys
[docs] def provideJ(self): """ Calculate and save derivatives (i.e., Jacobian). """ # Derivatives are simple return
[docs] def execute(self): self.P_sol = np.zeros((self.n)) for p in range(12): self.P_sol += self.V_sol[p,:] * self.Isetpt[p,:]
[docs] def apply_deriv(self, arg, result): if 'P_sol' in result: if 'V_sol' in arg: for p in range(12): result['P_sol'] += arg['V_sol'][p,:] * self.Isetpt[p,:] if 'Isetpt' in arg: for p in range(12): result['P_sol'] += arg['Isetpt'][p,:] * self.V_sol[p,:]
[docs] def apply_derivT(self, arg, result): if 'P_sol' in arg: for p in range(12): if 'V_sol' in result: result['V_sol'][p,:] += arg['P_sol'] * self.Isetpt[p,:] if 'Isetpt' in result: result['Isetpt'][p,:] += self.V_sol[p,:] * arg['P_sol']
[docs]class Power_Total(Component): ''' Compute the battery power which is the sum of the loads. This includes a 2-Watt constant power usage that accounts for the scientific instruments on the satellite and small actuator inputs in response to disturbance torques. ''' def __init__(self, n=2): super(Power_Total, self).__init__() self.n = n self.add( 'P_sol', Array(np.zeros((n, ), order='F'), size=(n,), dtype=np.float, units='W', desc='Solar panels power over time', iotype="in")) self.add( 'P_comm', Array(np.zeros((n, ), order='F'), size=(n,), dtype=np.float, units='W', desc='Communication power over time', iotype="in")) self.add( 'P_RW', Array(np.zeros((3, n, ), order='F'), size=(3, n,), dtype=np.float, units='W', desc='Power used by reaction wheel over time', # qqq ? iotype="in")) self.add( 'P_bat', Array(np.zeros((n, ), order='F'), size=(n,), dtype=np.float, units='W', desc='Battery power over time', iotype="out"))
[docs] def list_deriv_vars(self): input_keys = ('P_sol', 'P_comm', 'P_RW',) output_keys = ('P_bat',) return input_keys, output_keys
[docs] def provideJ(self): """ Calculate and save derivatives (i.e., Jacobian). """ # Derivatives are simple return
[docs] def execute(self): self.P_bat = self.P_sol - 5 * self.P_comm - np.sum(self.P_RW, 0) - 2.0
[docs] def apply_deriv(self, arg, result): if 'P_sol' in arg: result['P_bat'] += arg['P_sol'] if 'P_comm' in arg: result['P_bat'] -= 5 * arg['P_comm'] if 'P_RW' in arg: for k in range(3): result['P_bat'] -= arg['P_RW'][k,:]
[docs] def apply_derivT(self, arg, result): if 'P_bat' in arg: if 'P_sol' in result: result['P_sol'] += arg['P_bat'][:] if 'P_comm' in result: result['P_comm'] -= 5 * arg['P_bat'] if 'P_RW' in result: for k in range(3): result['P_RW'][k,:] -= arg['P_bat']