Ejemplo n.º 1
0
class Power_CellVoltage(ExplicitComponent):
    """
    Compute the output voltage of the solar panels.
    """
    def __init__(self, n, filename=None):
        super(Power_CellVoltage, self).__init__()

        self.n = n

        if not filename:
            fpath = os.path.dirname(os.path.realpath(__file__))
            filename = fpath + '/data/Power/curve.dat'

        dat = np.genfromtxt(filename)

        nT, nA, nI = dat[:3]
        nT = int(nT)
        nA = int(nA)
        nI = int(nI)
        T = dat[3:3 + nT]
        A = dat[3 + nT:3 + nT + nA]
        I = dat[3 + nT + nA:3 + nT + nA + nI]  # noqa: E741
        V = dat[3 + nT + nA + nI:].reshape((nT, nA, nI), order='F')

        self.MBI = MBI(V, [T, A, I], [6, 6, 15], [3, 3, 3])

        self.x = np.zeros((84 * n, 3), order='F')
        self.xV = self.x.reshape((n, 7, 12, 3), order='F')
        self.dV_dL = np.zeros((n, 12), order='F')
        self.dV_dT = np.zeros((n, 12, 5), order='F')
        self.dV_dA = np.zeros((n, 7, 12), order='F')
        self.dV_dI = np.zeros((n, 12), order='F')

    def setup(self):
        n = self.n

        # Inputs
        self.add_input('LOS',
                       np.zeros((n)),
                       units=None,
                       desc='Line of Sight over Time')

        self.add_input('temperature',
                       np.zeros((5, n)),
                       units='degK',
                       desc='Temperature of solar cells over time')

        self.add_input(
            'exposedArea',
            np.zeros((7, 12, n)),
            units='m**2',
            desc='Exposed area to sun for each solar cell over time')

        self.add_input('Isetpt',
                       np.zeros((12, n)),
                       units='A',
                       desc='Currents of the solar panels')

        # Outputs
        self.add_output('V_sol',
                        np.zeros((12, n)),
                        units='V',
                        desc='Output voltage of solar panel over time')

    def setx(self, inputs):
        temperature = inputs['temperature']
        LOS = inputs['LOS']
        exposedArea = inputs['exposedArea']
        Isetpt = inputs['Isetpt']

        for p in range(12):
            i = 4 if p < 4 else (p % 4)
            for c in range(7):
                self.xV[:, c, p, 0] = temperature[i, :]
                self.xV[:, c, p, 1] = LOS * exposedArea[c, p, :]
                self.xV[:, c, p, 2] = Isetpt[p, :]

    def compute(self, inputs, outputs):
        """
        Calculate outputs.
        """
        self.setx(inputs)
        self.raw = self.MBI.evaluate(self.x)[:, 0].reshape((self.n, 7, 12),
                                                           order='F')
        outputs['V_sol'] = np.zeros((12, self.n))
        for c in range(7):
            outputs['V_sol'] += self.raw[:, c, :].T

    def compute_partials(self, inputs, partials):
        """
        Calculate and save derivatives. (i.e., Jacobian)
        """
        exposedArea = inputs['exposedArea']
        LOS = inputs['LOS']

        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] * exposedArea[c, p, :]
                self.dV_dT[:, p, i] += self.raw1[:, c, p]
                self.dV_dA[:, c, p] += self.raw2[:, c, p] * LOS
                self.dV_dI[:, p] += self.raw3[:, c, p]

    def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode):
        """
        Matrix-vector product with the Jacobian.
        """
        dV_sol = d_outputs['V_sol']

        if mode == 'fwd':
            if 'LOS' in d_inputs:
                dV_sol += self.dV_dL.T * d_inputs['LOS']

            if 'temperature' in d_inputs:
                for p in range(12):
                    i = 4 if p < 4 else (p % 4)
                    dV_sol[
                        p, :] += self.dV_dT[:, p,
                                            i] * d_inputs['temperature'][i, :]

            if 'Isetpt' in d_inputs:
                dV_sol += self.dV_dI.T * d_inputs['Isetpt']

            if 'exposedArea' in d_inputs:
                for p in range(12):
                    dV_sol[p, :] += \
                        np.sum(self.dV_dA[:, :, p] * d_inputs['exposedArea'][:, p, :].T, 1)
        else:
            for p in range(12):
                i = 4 if p < 4 else (p % 4)

                if 'LOS' in d_inputs:
                    d_inputs['LOS'] += self.dV_dL[:, p] * dV_sol[p, :]

                if 'temperature' in d_inputs:
                    d_inputs['temperature'][
                        i, :] += self.dV_dT[:, p, i] * dV_sol[p, :]

                if 'Isetpt' in d_inputs:
                    d_inputs['Isetpt'][p, :] += self.dV_dI[:, p] * dV_sol[p, :]

                if 'exposedArea' in d_inputs:
                    dexposedArea = d_inputs['exposedArea']
                    for c in range(7):
                        dexposedArea[c, p, :] += self.dV_dA[:, c,
                                                            p] * dV_sol[p, :]
Ejemplo n.º 2
0
class Solar_ExposedArea(Component):
    '''Exposed area calculation for a given solar cell
       p: panel ID [0,11]
       c: cell ID [0,6]
       a: fin angle [0,90]
       z: azimuth [0,360]
       e: elevation [0,180]
       LOS: line of sight with the sun [0,1]
    '''

    # Inputs
    finAngle = Float(0., iotype="in", copy=None)

    def __init__(self, n, raw1=None, raw2=None):
        super(Solar_ExposedArea, self).__init__()

        if raw1 is None:
            raw1 = np.genfromtxt('CADRE/data/Solar/Area10.txt')
        if raw2 is None:
            raw2 = np.loadtxt("CADRE/data/Solar/Area_all.txt")

        self.n = n
        self.nc = 7
        self.np = 12

        # Inputs
        self.add('azimuth', Array(np.zeros((n,)), size=(n,), dtype=np.float,
                                  iotype='in'))
        self.add('elevation', Array(np.zeros((n,)), size=(n,), dtype=np.float,
                                    iotype='in'))

        # Outputs
        self.add('exposedArea', Array(np.zeros((self.nc, self.np, self.n)),
                                      size=(self.nc, self.np, self.n),
                                      dtype=np.float, iotype='out',
                                      low=-5e-3, high=1.834e-1))

        self.na = 10
        self.nz = 73
        self.ne = 37
        angle = np.zeros(self.na)
        azimuth = np.zeros(self.nz)
        elevation = np.zeros(self.ne)

        index = 0
        for i in range(self.na):
            angle[i] = raw1[index]
            index += 1
        for i in range(self.nz):
            azimuth[i] = raw1[index]
            index += 1

        index -= 1
        azimuth[self.nz-1] = 2.0*np.pi
        for i in range(self.ne):
            elevation[i] = raw1[index]
            index += 1

        angle[0] = 0.0
        angle[-1] = np.pi/2.0
        azimuth[0] = 0.0
        azimuth[-1] = 2*np.pi
        elevation[0] = 0.0
        elevation[-1] = np.pi

        counter = 0
        data = np.zeros((self.na, self.nz, self.ne, self.np*self.nc))
        flat_size = self.na*self.nz*self.ne
        for p in range(self.np):
            for c in range(self.nc):
                data[:, :, :, counter] = \
                    raw2[7*p+c][119:119+flat_size].reshape((self.na,
                                                            self.nz,
                                                            self.ne))
                counter += 1

        self.MBI = MBI(data, [angle, azimuth, elevation],
                             [4, 10, 8],
                             [4, 4, 4])

        self.x = np.zeros((self.n, 3))
        self.Jfin = None
        self.Jaz = None
        self.Jel = None

    def setx(self):
        """ Sets our state array"""

        result = fixangles(self.n, self.azimuth, self.elevation)
        self.x[:, 0] = self.finAngle
        self.x[:, 1] = result[0]
        self.x[:, 2] = result[1]

    def linearize(self):
        """ Calculate and save derivatives. (i.e., Jacobian) """

        self.Jfin = self.MBI.evaluate(self.x, 1).reshape(self.n, 7, 12,
                                                         order='F')
        self.Jaz = self.MBI.evaluate(self.x, 2).reshape(self.n, 7, 12,
                                                        order='F')
        self.Jel = self.MBI.evaluate(self.x, 3).reshape(self.n, 7, 12,
                                                        order='F')

    def execute(self):
        """ Calculate output. """

        self.setx()
        P = self.MBI.evaluate(self.x).T
        self.exposedArea = P.reshape(7, 12, self.n, order='F')

    def apply_deriv(self, arg, result):
        """ Matrix-vector product with the Jacobian. """

        if 'exposedArea' in result:
            for c in range(7):
                if 'finAngle' in arg:
                    result['exposedArea'][c, :, :] += \
                        self.Jfin[:, c, :].T*arg['finAngle']
                if 'azimuth' in arg:
                    result['exposedArea'][c, :, :] += \
                        self.Jaz[:, c, :].T*arg['azimuth']
                if 'elevation' in arg:
                    result['exposedArea'][c, :, :] += \
                        self.Jel[:, c, :].T*arg['elevation']

    def apply_derivT(self, arg, result):
        """ Matrix-vector product with the transpose of the Jacobian. """

        if 'exposedArea' in arg:
            for c in range(7):
                
                # incoming arg is often sparse, so check it first
                if len(np.nonzero(arg['exposedArea'][c, :, :])[0]) == 0:
                    continue
                
                if 'finAngle' in result:
                    result['finAngle'] += \
                        np.sum(self.Jfin[:, c, :].T*arg['exposedArea'][c, :, :])
                    
                if 'azimuth' in result:
                    result['azimuth'] += \
                        np.sum(self.Jaz[:, c, :].T*arg['exposedArea'][c, :, :], 0)
                    
                if 'elevation' in result:
                    result['elevation'] += \
                        np.sum(self.Jel[:, c, :].T*arg['exposedArea'][c, :, :], 0)
Ejemplo n.º 3
0
class Solar_ExposedArea(Component):
    """Exposed area calculation for a given solar cell
    p: panel ID [0,11]
    c: cell ID [0,6]
    a: fin angle [0,90]
    z: azimuth [0,360]
    e: elevation [0,180]
    LOS: line of sight with the sun [0,1]
    """


    def __init__(self, n, raw1=None, raw2=None):
        super(Solar_ExposedArea, self).__init__()

        if raw1 is None:
            fpath = os.path.dirname(os.path.realpath(__file__))
            raw1 = np.genfromtxt(fpath + '/data/Solar/Area10.txt')
        if raw2 is None:
            fpath = os.path.dirname(os.path.realpath(__file__))
            raw2 = np.loadtxt(fpath + "/data/Solar/Area_all.txt")

        self.n = n
        self.nc = 7
        self.np = 12

        # Inputs
        self.add_param('finAngle', 0.0, units="rad",
                       desc="Fin angle of solar panel")

        self.add_param('azimuth', np.zeros((n, )), units='rad',
                       desc="Azimuth angle of the sun in the body-fixed frame "
                       "over time")

        self.add_param('elevation', np.zeros((n, )), units='rad',
                       desc='Elevation angle of the sun in the body-fixed '
                       'frame over time')

        # Outputs
        self.add_output('exposedArea', np.zeros((self.nc, self.np, self.n)),
                        desc="Exposed area to sun for each solar cell over time",
                        units='m**2', low=-5e-3, high=1.834e-1)

        self.na = 10
        self.nz = 73
        self.ne = 37
        angle = np.zeros(self.na)
        azimuth = np.zeros(self.nz)
        elevation = np.zeros(self.ne)

        index = 0
        for i in range(self.na):
            angle[i] = raw1[index]
            index += 1
        for i in range(self.nz):
            azimuth[i] = raw1[index]
            index += 1

        index -= 1
        azimuth[self.nz - 1] = 2.0 * np.pi
        for i in range(self.ne):
            elevation[i] = raw1[index]
            index += 1

        angle[0] = 0.0
        angle[-1] = np.pi / 2.0
        azimuth[0] = 0.0
        azimuth[-1] = 2 * np.pi
        elevation[0] = 0.0
        elevation[-1] = np.pi

        counter = 0
        data = np.zeros((self.na, self.nz, self.ne, self.np * self.nc))
        flat_size = self.na * self.nz * self.ne
        for p in range(self.np):
            for c in range(self.nc):
                data[:, :, :, counter] = \
                    raw2[7 * p + c][119:119 + flat_size].reshape((self.na,
                                                                  self.nz,
                                                                  self.ne))
                counter += 1

        self.MBI = MBI(data, [angle, azimuth, elevation],
                             [4, 10, 8],
                             [4, 4, 4])

        self.x = np.zeros((self.n, 3))
        self.Jfin = None
        self.Jaz = None
        self.Jel = None

    def solve_nonlinear(self, params, unknowns, resids):
        """ Calculate output. """

        self.setx(params)
        P = self.MBI.evaluate(self.x).T
        unknowns['exposedArea'] = P.reshape(7, 12, self.n, order='F')

    def setx(self, params):
        """ Sets our state array"""

        result = fixangles(self.n, params['azimuth'], params['elevation'])
        self.x[:, 0] = params['finAngle']
        self.x[:, 1] = result[0]
        self.x[:, 2] = result[1]

    def jacobian(self, params, unknowns, resids):
        """ Calculate and save derivatives. (i.e., Jacobian) """

        self.Jfin = self.MBI.evaluate(self.x, 1).reshape(self.n, 7, 12,
                                                         order='F')
        self.Jaz = self.MBI.evaluate(self.x, 2).reshape(self.n, 7, 12,
                                                        order='F')
        self.Jel = self.MBI.evaluate(self.x, 3).reshape(self.n, 7, 12,
                                                        order='F')

    def apply_linear(self, params, unknowns, dparams, dunknowns, dresids, mode):
        """ Matrix-vector product with the Jacobian. """

        deA = dresids['exposedArea']

        if mode == 'fwd':
            for c in range(7):

                if 'finAngle' in dparams:
                    deA[c, :, :] += \
                        self.Jfin[:, c, :].T * dparams['finAngle']

                if 'azimuth' in dparams:
                    deA[c, :, :] += \
                        self.Jaz[:, c, :].T * dparams['azimuth']

                if 'elevation' in dparams:
                    deA[c, :, :] += \
                        self.Jel[:, c, :].T * dparams['elevation']

        else:
            for c in range(7):

                # incoming arg is often sparse, so check it first
                if len(np.nonzero(dresids['exposedArea'][c, :, :])[0]) == 0:
                    continue

                if 'finAngle' in dparams:
                    dparams['finAngle'] += \
                        np.sum(
                            self.Jfin[:, c, :].T * deA[c, :, :])

                if 'azimuth' in dparams:
                    dparams['azimuth'] += \
                        np.sum(
                            self.Jaz[:, c, :].T * deA[c, :, :], 0)

                if 'elevation' in dparams:
                    dparams['elevation'] += \
                        np.sum(
                            self.Jel[:, c, :].T * deA[c, :, :], 0)
Ejemplo n.º 4
0
class Comm_GainPattern(ExplicitComponent):
    """
    Determines transmitter gain based on an external az-el map.
    """

    def __init__(self, n, rawG_file=None):
        super(Comm_GainPattern, self).__init__()

        self.n = n

        if not rawG_file:
            fpath = os.path.dirname(os.path.realpath(__file__))
            rawG_file = fpath + '/data/Comm/Gain.txt'

        rawGdata = np.genfromtxt(rawG_file)
        rawG = (10 ** (rawGdata / 10.0)).reshape((361, 361), order='F')

        pi = np.pi
        az = np.linspace(0, 2 * pi, 361)
        el = np.linspace(0, 2 * pi, 361)

        self.MBI = MBI(rawG, [az, el], [15, 15], [4, 4])
        self.x = np.zeros((self.n, 2), order='F')

    def setup(self):
        n = self.n

        # Inputs
        self.add_input('azimuthGS', np.zeros(n), units='rad',
                       desc='Azimuth angle from satellite to ground station in '
                            'Earth-fixed frame over time')

        self.add_input('elevationGS', np.zeros(n), units='rad',
                       desc='Elevation angle from satellite to ground station '
                            'in Earth-fixed frame over time')

        # Outputs
        self.add_output('gain', np.zeros(n), units=None,
                        desc='Transmitter gain over time')

    def compute(self, inputs, outputs):
        """
        Calculate outputs.
        """
        result = fixangles(self.n, inputs['azimuthGS'], inputs['elevationGS'])
        self.x[:, 0] = result[0]
        self.x[:, 1] = result[1]
        outputs['gain'] = self.MBI.evaluate(self.x)[:, 0]

    def compute_partials(self, inputs, partials):
        """
        Calculate and save derivatives. (i.e., Jacobian)
        """
        self.dg_daz = self.MBI.evaluate(self.x, 1)[:, 0]
        self.dg_del = self.MBI.evaluate(self.x, 2)[:, 0]

    def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode):
        """
        Matrix-vector product with the Jacobian.
        """
        dgain = d_outputs['gain']

        if mode == 'fwd':
            if 'azimuthGS' in d_inputs:
                dgain += self.dg_daz * d_inputs['azimuthGS']
            if 'elevationGS' in d_inputs:
                dgain += self.dg_del * d_inputs['elevationGS']
        else:
            if 'azimuthGS' in d_inputs:
                d_inputs['azimuthGS'] += self.dg_daz * dgain
            if 'elevationGS' in d_inputs:
                d_inputs['elevationGS'] += self.dg_del * dgain
Ejemplo n.º 5
0
class Power_CellVoltage(ExplicitComponent):
    """
    Compute the output voltage of the solar panels.
    """

    def __init__(self, n, filename=None):
        super(Power_CellVoltage, self).__init__()

        self.n = n

        if not filename:
            fpath = os.path.dirname(os.path.realpath(__file__))
            filename = fpath + '/data/Power/curve.dat'

        dat = np.genfromtxt(filename)

        nT, nA, nI = dat[:3]
        nT = int(nT)
        nA = int(nA)
        nI = int(nI)
        T = dat[3:3 + nT]
        A = dat[3 + nT:3 + nT + nA]
        I = dat[3 + nT + nA:3 + nT + nA + nI]  # noqa: E741
        V = dat[3 + nT + nA + nI:].reshape((nT, nA, nI), order='F')

        self.MBI = MBI(V, [T, A, I], [6, 6, 15], [3, 3, 3])

        self.x = np.zeros((84 * n, 3), order='F')
        self.xV = self.x.reshape((n, 7, 12, 3), order='F')
        self.dV_dL = np.zeros((n, 12), order='F')
        self.dV_dT = np.zeros((n, 12, 5), order='F')
        self.dV_dA = np.zeros((n, 7, 12), order='F')
        self.dV_dI = np.zeros((n, 12), order='F')

    def setup(self):
        n = self.n

        # Inputs
        self.add_input('LOS', np.zeros((n)), units=None,
                       desc='Line of Sight over Time')

        self.add_input('temperature', np.zeros((5, n)), units='degK',
                       desc='Temperature of solar cells over time')

        self.add_input('exposedArea', np.zeros((7, 12, n)), units='m**2',
                       desc='Exposed area to sun for each solar cell over time')

        self.add_input('Isetpt', np.zeros((12, n)), units='A',
                       desc='Currents of the solar panels')

        # Outputs
        self.add_output('V_sol', np.zeros((12, n)), units='V',
                        desc='Output voltage of solar panel over time')

    def setx(self, inputs):
        temperature = inputs['temperature']
        LOS = inputs['LOS']
        exposedArea = inputs['exposedArea']
        Isetpt = inputs['Isetpt']

        for p in range(12):
            i = 4 if p < 4 else (p % 4)
            for c in range(7):
                self.xV[:, c, p, 0] = temperature[i, :]
                self.xV[:, c, p, 1] = LOS * exposedArea[c, p, :]
                self.xV[:, c, p, 2] = Isetpt[p, :]

    def compute(self, inputs, outputs):
        """
        Calculate outputs.
        """
        self.setx(inputs)
        self.raw = self.MBI.evaluate(self.x)[:, 0].reshape((self.n, 7, 12),
                                                           order='F')
        outputs['V_sol'] = np.zeros((12, self.n))
        for c in range(7):
            outputs['V_sol'] += self.raw[:, c, :].T

    def compute_partials(self, inputs, partials):
        """
        Calculate and save derivatives. (i.e., Jacobian)
        """
        exposedArea = inputs['exposedArea']
        LOS = inputs['LOS']

        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] * exposedArea[c, p, :]
                self.dV_dT[:, p, i] += self.raw1[:, c, p]
                self.dV_dA[:, c, p] += self.raw2[:, c, p] * LOS
                self.dV_dI[:, p] += self.raw3[:, c, p]

    def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode):
        """
        Matrix-vector product with the Jacobian.
        """
        dV_sol = d_outputs['V_sol']

        if mode == 'fwd':
            if 'LOS' in d_inputs:
                dV_sol += self.dV_dL.T * d_inputs['LOS']

            if 'temperature' in d_inputs:
                for p in range(12):
                    i = 4 if p < 4 else (p % 4)
                    dV_sol[p, :] += self.dV_dT[:, p, i] * d_inputs['temperature'][i, :]

            if 'Isetpt' in d_inputs:
                dV_sol += self.dV_dI.T * d_inputs['Isetpt']

            if 'exposedArea' in d_inputs:
                for p in range(12):
                    dV_sol[p, :] += \
                        np.sum(self.dV_dA[:, :, p] * d_inputs['exposedArea'][:, p, :].T, 1)
        else:
            for p in range(12):
                i = 4 if p < 4 else (p % 4)

                if 'LOS' in d_inputs:
                    d_inputs['LOS'] += self.dV_dL[:, p] * dV_sol[p, :]

                if 'temperature' in d_inputs:
                    d_inputs['temperature'][i, :] += self.dV_dT[:, p, i] * dV_sol[p, :]

                if 'Isetpt' in d_inputs:
                    d_inputs['Isetpt'][p, :] += self.dV_dI[:, p] * dV_sol[p, :]

                if 'exposedArea' in d_inputs:
                    dexposedArea = d_inputs['exposedArea']
                    for c in range(7):
                        dexposedArea[c, p, :] += self.dV_dA[:, c, p] * dV_sol[p, :]
Ejemplo n.º 6
0
class PowerCellVoltage(ExplicitComponent):
    """
    Compute the output voltage of the solar panels.
    """
    def initialize(self):
        fpath = os.path.dirname(os.path.realpath(__file__))

        self.options.declare('num_nodes',
                             types=(int, ),
                             desc="Number of time points.")
        self.options.declare(
            'filename',
            fpath + '/../data/Power/curve.dat',
            desc="File containing surrogate model for voltage.")

    def setup(self):
        nn = self.options['num_nodes']
        filename = self.options['filename']

        dat = np.genfromtxt(filename)

        nT, nA, nI = dat[:3]
        nT = int(nT)
        nA = int(nA)
        nI = int(nI)
        T = dat[3:3 + nT]
        A = dat[3 + nT:3 + nT + nA]
        I = dat[3 + nT + nA:3 + nT + nA + nI]  # noqa: E741
        V = dat[3 + nT + nA + nI:].reshape((nT, nA, nI), order='F')

        self.MBI = MBI(V, [T, A, I], [6, 6, 15], [3, 3, 3])

        self.x = np.zeros((84 * nn, 3), order='F')
        self.xV = self.x.reshape((nn, 7, 12, 3), order='F')

        # Inputs
        self.add_input('LOS',
                       np.zeros((nn, )),
                       units=None,
                       desc='Line of Sight over Time')

        self.add_input('temperature',
                       np.zeros((nn, 5)),
                       units='degK',
                       desc='Temperature of solar cells over time')

        self.add_input(
            'exposed_area',
            np.zeros((nn, 7, 12)),
            units='m**2',
            desc='Exposed area to sun for each solar cell over time')

        self.add_input('Isetpt',
                       np.zeros((nn, 12)),
                       units='A',
                       desc='Currents of the solar panels')

        # Outputs
        self.add_output('V_sol',
                        np.zeros((nn, 12)),
                        units='V',
                        desc='Output voltage of solar panel over time')

        rows = np.arange(nn * 12)
        cols = np.tile(np.repeat(0, 12), nn) + np.repeat(np.arange(nn), 12)

        self.declare_partials('V_sol', 'LOS', rows=rows, cols=cols)

        row = np.tile(np.repeat(0, 5), 12) + np.repeat(np.arange(12), 5)
        rows = np.tile(row, nn) + np.repeat(12 * np.arange(nn), 60)
        col = np.tile(np.arange(5), 12)
        cols = np.tile(col, nn) + np.repeat(5 * np.arange(nn), 60)

        self.declare_partials('V_sol', 'temperature', rows=rows, cols=cols)

        row = np.tile(np.arange(12), 7)
        rows = np.tile(row, nn) + np.repeat(12 * np.arange(nn), 84)
        cols = np.arange(nn * 7 * 12)

        self.declare_partials('V_sol', 'exposed_area', rows=rows, cols=cols)

        row_col = np.arange(nn * 12)

        self.declare_partials('V_sol', 'Isetpt', rows=row_col, cols=row_col)

    def setx(self, inputs):
        temperature = inputs['temperature']
        LOS = inputs['LOS']
        exposed_area = inputs['exposed_area']
        Isetpt = inputs['Isetpt']

        for p in range(12):
            i = 4 if p < 4 else (p % 4)
            for c in range(7):
                self.xV[:, c, p, 0] = temperature[:, i]
                self.xV[:, c, p, 1] = LOS * exposed_area[:, c, p]
                self.xV[:, c, p, 2] = Isetpt[:, p]

    def compute(self, inputs, outputs):
        """
        Calculate outputs.
        """
        nn = self.options['num_nodes']

        self.setx(inputs)
        self.raw = self.MBI.evaluate(self.x)[:, 0].reshape((nn, 7, 12),
                                                           order='F')

        outputs['V_sol'] = np.zeros((nn, 12))
        for c in range(7):
            outputs['V_sol'] += self.raw[:, c, :]

    def compute_partials(self, inputs, partials):
        """
        Calculate and save derivatives. (i.e., Jacobian)
        """
        nn = self.options['num_nodes']

        exposed_area = inputs['exposed_area']
        LOS = inputs['LOS']

        raw1 = self.MBI.evaluate(self.x, 1)[:, 0].reshape((nn, 7, 12),
                                                          order='F')
        raw2 = self.MBI.evaluate(self.x, 2)[:, 0].reshape((nn, 7, 12),
                                                          order='F')
        raw3 = self.MBI.evaluate(self.x, 3)[:, 0].reshape((nn, 7, 12),
                                                          order='F')

        dV_dL = np.empty((nn, 12))
        dV_dT = np.zeros((nn, 12, 5))
        dV_dA = np.zeros((nn, 7, 12))
        dV_dI = np.empty((nn, 12))

        for p in range(12):
            i = 4 if p < 4 else (p % 4)
            for c in range(7):
                dV_dL[:, p] += raw2[:, c, p] * exposed_area[:, c, p]
                dV_dT[:, p, i] += raw1[:, c, p]
                dV_dA[:, c, p] += raw2[:, c, p] * LOS
                dV_dI[:, p] += raw3[:, c, p]

        partials['V_sol', 'LOS'] = dV_dL.flatten()
        partials['V_sol', 'temperature'] = dV_dT.flatten()
        partials['V_sol', 'exposed_area'] = dV_dA.flatten()
        partials['V_sol', 'Isetpt'] = dV_dI.flatten()
Ejemplo n.º 7
0
class Solar_ExposedArea(Component):

    '''Exposed area calculation for a given solar cell

       p: panel ID [0,11]

       c: cell ID [0,6]

       a: fin angle [0,90]

       z: azimuth [0,360]

       e: elevation [0,180]

       LOS: line of sight with the sun [0,1]
    '''

    # Inputs
    finAngle = Float(0., iotype="in", units="rad", desc="Fin angle of solar panel", copy=None)

    def __init__(self, n, raw1=None, raw2=None):
        super(Solar_ExposedArea, self).__init__()

        if raw1 is None:
            fpath = os.path.dirname(os.path.realpath(__file__))
            raw1 = np.genfromtxt(fpath + '/data/Solar/Area10.txt')
        if raw2 is None:
            fpath = os.path.dirname(os.path.realpath(__file__))
            raw2 = np.loadtxt(fpath + "/data/Solar/Area_all.txt")

        self.n = n
        self.nc = 7
        self.np = 12

        # Inputs
        self.add('azimuth', Array(np.zeros((n,)), size=(n,), dtype=np.float,
                                  units='rad',
                                  desc='Azimuth angle of the sun in the body-fixed frame over time',
                                  iotype='in'))
        self.add('elevation', Array(np.zeros((n,)), size=(n,), dtype=np.float,
                                    units='rad',
                                    desc='Elevation angle of the sun in the body-fixed frame over time',
                                    iotype='in'))

        # Outputs
        self.add('exposedArea', Array(np.zeros((self.nc, self.np, self.n)),
                                      size=(self.nc, self.np, self.n),
                                      dtype=np.float, iotype='out',
                                      desc="Exposed area to sun for each solar cell over time",
                                      units='m**2',
                                      low=-5e-3, high=1.834e-1))

        self.na = 10
        self.nz = 73
        self.ne = 37
        angle = np.zeros(self.na)
        azimuth = np.zeros(self.nz)
        elevation = np.zeros(self.ne)

        index = 0
        for i in range(self.na):
            angle[i] = raw1[index]
            index += 1
        for i in range(self.nz):
            azimuth[i] = raw1[index]
            index += 1

        index -= 1
        azimuth[self.nz - 1] = 2.0 * np.pi
        for i in range(self.ne):
            elevation[i] = raw1[index]
            index += 1

        angle[0] = 0.0
        angle[-1] = np.pi / 2.0
        azimuth[0] = 0.0
        azimuth[-1] = 2 * np.pi
        elevation[0] = 0.0
        elevation[-1] = np.pi

        counter = 0
        data = np.zeros((self.na, self.nz, self.ne, self.np * self.nc))
        flat_size = self.na * self.nz * self.ne
        for p in range(self.np):
            for c in range(self.nc):
                data[:, :, :, counter] = \
                    raw2[7 * p + c][119:119 + flat_size].reshape((self.na,
                                                                  self.nz,
                                                                  self.ne))
                counter += 1

        self.MBI = MBI(data, [angle, azimuth, elevation],
                             [4, 10, 8],
                             [4, 4, 4])

        self.x = np.zeros((self.n, 3))
        self.Jfin = None
        self.Jaz = None
        self.Jel = None

    def list_deriv_vars(self):
        input_keys = ('azimuth', 'elevation', 'finAngle',)
        output_keys = ('exposedArea',)
        return input_keys, output_keys

    def setx(self):
        """ Sets our state array"""

        result = fixangles(self.n, self.azimuth, self.elevation)
        self.x[:, 0] = self.finAngle
        self.x[:, 1] = result[0]
        self.x[:, 2] = result[1]

    def provideJ(self):
        """ Calculate and save derivatives (i.e., Jacobian). """

        self.Jfin = self.MBI.evaluate(self.x, 1).reshape(self.n, 7, 12,
                                                         order='F')
        self.Jaz = self.MBI.evaluate(self.x, 2).reshape(self.n, 7, 12,
                                                        order='F')
        self.Jel = self.MBI.evaluate(self.x, 3).reshape(self.n, 7, 12,
                                                        order='F')

    def execute(self):
        """ Calculate output. """

        self.setx()
        P = self.MBI.evaluate(self.x).T
        self.exposedArea = P.reshape(7, 12, self.n, order='F')

    def apply_deriv(self, arg, result):
        """ Matrix-vector product with the Jacobian. """

        if 'exposedArea' in result:
            for c in range(7):
                if 'finAngle' in arg:
                    result['exposedArea'][c, :, :] += \
                        self.Jfin[:, c, :].T * arg['finAngle']
                if 'azimuth' in arg:
                    result['exposedArea'][c, :, :] += \
                        self.Jaz[:, c, :].T * arg['azimuth']
                if 'elevation' in arg:
                    result['exposedArea'][c, :, :] += \
                        self.Jel[:, c, :].T * arg['elevation']

    def apply_derivT(self, arg, result):
        """ Matrix-vector product with the transpose of the Jacobian. """

        if 'exposedArea' in arg:
            for c in range(7):

                # incoming arg is often sparse, so check it first
                if len(np.nonzero(arg['exposedArea'][c, :, :])[0]) == 0:
                    continue

                if 'finAngle' in result:
                    result['finAngle'] += \
                        np.sum(
                            self.Jfin[:, c, :].T * arg['exposedArea'][c, :, :])

                if 'azimuth' in result:
                    result['azimuth'] += \
                        np.sum(
                            self.Jaz[:, c, :].T * arg['exposedArea'][c, :, :], 0)

                if 'elevation' in result:
                    result['elevation'] += \
                        np.sum(
                            self.Jel[:, c, :].T * arg['exposedArea'][c, :, :], 0)
Ejemplo n.º 8
0
class Solar_ExposedArea(Component):
    """Exposed area calculation for a given solar cell
    p: panel ID [0,11]
    c: cell ID [0,6]
    a: fin angle [0,90]
    z: azimuth [0,360]
    e: elevation [0,180]
    LOS: line of sight with the sun [0,1]
    """
    def __init__(self, n, raw1=None, raw2=None):
        super(Solar_ExposedArea, self).__init__()

        if raw1 is None:
            fpath = os.path.dirname(os.path.realpath(__file__))
            raw1 = np.genfromtxt(fpath + '/data/Solar/Area10.txt')
        if raw2 is None:
            fpath = os.path.dirname(os.path.realpath(__file__))
            raw2 = np.loadtxt(fpath + "/data/Solar/Area_all.txt")

        self.n = n
        self.nc = 7
        self.np = 12

        # Inputs
        self.add_param('finAngle',
                       0.0,
                       units="rad",
                       desc="Fin angle of solar panel")

        self.add_param('azimuth',
                       np.zeros((n, )),
                       units='rad',
                       desc="Azimuth angle of the sun in the body-fixed frame "
                       "over time")

        self.add_param('elevation',
                       np.zeros((n, )),
                       units='rad',
                       desc='Elevation angle of the sun in the body-fixed '
                       'frame over time')

        # Outputs
        self.add_output(
            'exposedArea',
            np.zeros((self.nc, self.np, self.n)),
            desc="Exposed area to sun for each solar cell over time",
            units='m**2',
            low=-5e-3,
            high=1.834e-1)

        self.na = 10
        self.nz = 73
        self.ne = 37
        angle = np.zeros(self.na)
        azimuth = np.zeros(self.nz)
        elevation = np.zeros(self.ne)

        index = 0
        for i in range(self.na):
            angle[i] = raw1[index]
            index += 1
        for i in range(self.nz):
            azimuth[i] = raw1[index]
            index += 1

        index -= 1
        azimuth[self.nz - 1] = 2.0 * np.pi
        for i in range(self.ne):
            elevation[i] = raw1[index]
            index += 1

        angle[0] = 0.0
        angle[-1] = np.pi / 2.0
        azimuth[0] = 0.0
        azimuth[-1] = 2 * np.pi
        elevation[0] = 0.0
        elevation[-1] = np.pi

        counter = 0
        data = np.zeros((self.na, self.nz, self.ne, self.np * self.nc))
        flat_size = self.na * self.nz * self.ne
        for p in range(self.np):
            for c in range(self.nc):
                data[:, :, :, counter] = \
                    raw2[7 * p + c][119:119 + flat_size].reshape((self.na,
                                                                  self.nz,
                                                                  self.ne))
                counter += 1

        self.MBI = MBI(data, [angle, azimuth, elevation], [4, 10, 8],
                       [4, 4, 4])

        self.x = np.zeros((self.n, 3))
        self.Jfin = None
        self.Jaz = None
        self.Jel = None

    def solve_nonlinear(self, params, unknowns, resids):
        """ Calculate output. """

        self.setx(params)
        P = self.MBI.evaluate(self.x).T
        unknowns['exposedArea'] = P.reshape(7, 12, self.n, order='F')

    def setx(self, params):
        """ Sets our state array"""

        result = fixangles(self.n, params['azimuth'], params['elevation'])
        self.x[:, 0] = params['finAngle']
        self.x[:, 1] = result[0]
        self.x[:, 2] = result[1]

    def jacobian(self, params, unknowns, resids):
        """ Calculate and save derivatives. (i.e., Jacobian) """

        self.Jfin = self.MBI.evaluate(self.x, 1).reshape(self.n,
                                                         7,
                                                         12,
                                                         order='F')
        self.Jaz = self.MBI.evaluate(self.x, 2).reshape(self.n,
                                                        7,
                                                        12,
                                                        order='F')
        self.Jel = self.MBI.evaluate(self.x, 3).reshape(self.n,
                                                        7,
                                                        12,
                                                        order='F')

    def apply_linear(self, params, unknowns, dparams, dunknowns, dresids,
                     mode):
        """ Matrix-vector product with the Jacobian. """

        deA = dresids['exposedArea']

        if mode == 'fwd':
            for c in range(7):

                if 'finAngle' in dparams:
                    deA[c, :, :] += \
                        self.Jfin[:, c, :].T * dparams['finAngle']

                if 'azimuth' in dparams:
                    deA[c, :, :] += \
                        self.Jaz[:, c, :].T * dparams['azimuth']

                if 'elevation' in dparams:
                    deA[c, :, :] += \
                        self.Jel[:, c, :].T * dparams['elevation']

        else:
            for c in range(7):

                # incoming arg is often sparse, so check it first
                if len(np.nonzero(dresids['exposedArea'][c, :, :])[0]) == 0:
                    continue

                if 'finAngle' in dparams:
                    dparams['finAngle'] += \
                        np.sum(
                            self.Jfin[:, c, :].T * deA[c, :, :])

                if 'azimuth' in dparams:
                    dparams['azimuth'] += \
                        np.sum(
                            self.Jaz[:, c, :].T * deA[c, :, :], 0)

                if 'elevation' in dparams:
                    dparams['elevation'] += \
                        np.sum(
                            self.Jel[:, c, :].T * deA[c, :, :], 0)
Ejemplo n.º 9
0
class Comm_GainPattern(ExplicitComponent):
    """
    Determines transmitter gain based on an external az-el map.
    """
    def __init__(self, n, rawG_file=None):
        super(Comm_GainPattern, self).__init__()

        self.n = n

        if not rawG_file:
            fpath = os.path.dirname(os.path.realpath(__file__))
            rawG_file = fpath + '/data/Comm/Gain.txt'

        rawGdata = np.genfromtxt(rawG_file)
        rawG = (10**(rawGdata / 10.0)).reshape((361, 361), order='F')

        pi = np.pi
        az = np.linspace(0, 2 * pi, 361)
        el = np.linspace(0, 2 * pi, 361)

        self.MBI = MBI(rawG, [az, el], [15, 15], [4, 4])
        self.MBI.seterr('raise')
        self.x = np.zeros((self.n, 2), order='F')

    def setup(self):
        n = self.n

        # Inputs
        self.add_input(
            'azimuthGS',
            np.zeros(n),
            units='rad',
            desc='Azimuth angle from satellite to ground station in '
            'Earth-fixed frame over time')

        self.add_input('elevationGS',
                       np.zeros(n),
                       units='rad',
                       desc='Elevation angle from satellite to ground station '
                       'in Earth-fixed frame over time')

        # Outputs
        self.add_output('gain',
                        np.zeros(n),
                        units=None,
                        desc='Transmitter gain over time')

        row_col = np.arange(n)

        self.declare_partials('gain',
                              'elevationGS',
                              rows=row_col,
                              cols=row_col)
        self.declare_partials('gain', 'azimuthGS', rows=row_col, cols=row_col)

    def compute(self, inputs, outputs):
        """
        Calculate outputs.
        """
        result = fixangles(self.n, inputs['azimuthGS'], inputs['elevationGS'])
        self.x[:, 0] = result[0]
        self.x[:, 1] = result[1]
        outputs['gain'] = self.MBI.evaluate(self.x)[:, 0]

    def compute_partials(self, inputs, partials):
        """
        Calculate and save derivatives. (i.e., Jacobian)
        """
        partials['gain', 'azimuthGS'] = self.MBI.evaluate(self.x, 1)[:, 0]
        partials['gain', 'elevationGS'] = self.MBI.evaluate(self.x, 2)[:, 0]
Ejemplo n.º 10
0
Archivo: comm.py Proyecto: thearn/CADRE
class Comm_GainPattern(Component):
    ''' Determines transmitter gain based on an external az-el map. '''

    def __init__(self, n, rawG=None):
        super(Comm_GainPattern, self).__init__()

        self.n = n

        if rawG is None:
            fpath = os.path.dirname(os.path.realpath(__file__))
            rawGdata = np.genfromtxt(fpath + '/data/Comm/Gain.txt')
            rawG = (10 ** (rawGdata / 10.0)).reshape((361, 361), order='F')

        # Inputs
        self.add_param('azimuthGS', np.zeros(n), units="rad",
                       desc="Azimuth angle from satellite to ground station in "
                       "Earth-fixed frame over time")

        self.add_param('elevationGS', np.zeros(n), units="rad",
                       desc="Elevation angle from satellite to ground station "
                       "in Earth-fixed frame over time")

        # Outputs
        self.add_output('gain', np.zeros(n), units="unitless",
                        desc="Transmitter gain over time")


        pi = np.pi
        az = np.linspace(0, 2 * pi, 361)
        el = np.linspace(0, 2 * pi, 361)

        self.MBI = MBI(rawG, [az, el], [15, 15], [4, 4])
        self.x = np.zeros((self.n, 2), order='F')

    def solve_nonlinear(self, params, unknowns, resids):
        """ Calculate output. """

        result = fixangles(self.n, params['azimuthGS'], params['elevationGS'])
        self.x[:, 0] = result[0]
        self.x[:, 1] = result[1]
        unknowns['gain'] = self.MBI.evaluate(self.x)[:, 0]

    def linearize(self, params, unknowns, resids):
        """ Calculate and save derivatives. (i.e., Jacobian) """

        self.dg_daz = self.MBI.evaluate(self.x, 1)[:, 0]
        self.dg_del = self.MBI.evaluate(self.x, 2)[:, 0]

    def apply_linear(self, params, unknowns, dparams, dunknowns, dresids, mode):
        """ Matrix-vector product with the Jacobian. """

        dgain = dresids['gain']

        if mode == 'fwd':
            if 'azimuthGS' in dparams:
                dgain += self.dg_daz * dparams['azimuthGS']
            if 'elevationGS' in dparams:
                dgain += self.dg_del * dparams['elevationGS']

        else:
            if 'azimuthGS' in dparams:
                dparams['azimuthGS'] += self.dg_daz * dgain
            if 'elevationGS' in dparams:
                dparams['elevationGS'] += self.dg_del * dgain
Ejemplo n.º 11
0
class CommGainPatternComp(ExplicitComponent):
    """
    Determines transmitter gain based on an external az-el map.
    """

    #
    # def __init__(self, num_nodes, rawG_file=None):
    #     super(CommGainPatternComp, self).__init__(num_nodes=num_nodes)
    #
    #     if not rawG_file:
    #         fpath = os.path.dirname(os.path.realpath(__file__))
    #         rawG_file = fpath + '/data/Comm/Gain.txt'
    #
    #     rawGdata = np.genfromtxt(rawG_file)
    #     rawG = (10 ** (rawGdata / 10.0)).reshape((361, 361), order='F')
    #
    #     pi = np.pi
    #     az = np.linspace(0, 2 * pi, 361)
    #     el = np.linspace(0, 2 * pi, 361)
    #
    #     self.MBI = MBI(rawG, [az, el], [15, 15], [4, 4])
    #     self.x = np.zeros((self.n, 2), order='F')

    def initialize(self):
        dir_path = os.path.dirname(os.path.realpath(__file__))
        parent_path = os.path.abspath(os.path.join(dir_path, os.pardir))

        rawG_file = os.path.join(parent_path, 'data/Comm/Gain.txt')

        self.options.declare('num_nodes', types=(int, ))
        self.options.declare('rawG_file', types=(str, ), default=rawG_file)

    def setup(self):

        nn = self.options['num_nodes']

        rawGdata = np.genfromtxt(self.options['rawG_file'])
        rawG = (10**(rawGdata / 10.0)).reshape((361, 361), order='F')

        pi = np.pi
        az = np.linspace(0, 2 * pi, 361)
        el = np.linspace(0, 2 * pi, 361)

        self.MBI = MBI(rawG, [az, el], [15, 15], [4, 4])
        self.MBI.seterr('raise')

        self.x = np.zeros((nn, 2), order='F')

        # Inputs
        self.add_input(
            'azimuthGS',
            np.zeros(nn),
            units='rad',
            desc='Azimuth angle from satellite to ground station in '
            'Earth-fixed frame over time')

        self.add_input('elevationGS',
                       np.zeros(nn),
                       units='rad',
                       desc='Elevation angle from satellite to ground station '
                       'in Earth-fixed frame over time')

        # Outputs
        self.add_output('gain',
                        np.zeros(nn),
                        units=None,
                        desc='Transmitter gain over time')

        row_col = np.arange(nn)

        self.declare_partials('gain',
                              'elevationGS',
                              rows=row_col,
                              cols=row_col)
        self.declare_partials('gain', 'azimuthGS', rows=row_col, cols=row_col)

    def compute(self, inputs, outputs):
        """
        Calculate outputs.
        """
        result = fixangles(self.options['num_nodes'], inputs['azimuthGS'],
                           inputs['elevationGS'])
        self.x[:, 0] = result[0]
        self.x[:, 1] = result[1]
        outputs['gain'] = self.MBI.evaluate(self.x)[:, 0]

    def compute_partials(self, inputs, partials):
        """
        Calculate and save derivatives. (i.e., Jacobian)
        """
        partials['gain', 'azimuthGS'] = self.MBI.evaluate(self.x, 1)[:, 0]
        partials['gain', 'elevationGS'] = self.MBI.evaluate(self.x, 2)[:, 0]
Ejemplo n.º 12
0
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')

        # Inputs
        self.add_param('LOS', np.zeros((n)), units='unitless',
                       desc="Line of Sight over Time")

        self.add_param('temperature', np.zeros((5, n)), units="degK",
                       desc="Temperature of solar cells over time")

        self.add_param('exposedArea', np.zeros((7, 12, n)), units="m**2",
                       desc="Exposed area to sun for each solar cell over time")

        self.add_param('Isetpt', np.zeros((12, n)), units="A",
                       desc="Currents of the solar panels")

        # Outputs
        self.add_output('V_sol', np.zeros((12, n)), units="V",
                        desc="Output voltage of solar panel over time")

        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(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')

    def setx(self, params):

        temperature = params['temperature']
        LOS = params['LOS']
        exposedArea = params['exposedArea']
        Isetpt = params['Isetpt']

        for p in range(12):
            i = 4 if p < 4 else (p % 4)
            for c in range(7):
                self.xV[:, c, p, 0] = temperature[i, :]
                self.xV[:, c, p, 1] = LOS * exposedArea[c, p, :]
                self.xV[:, c, p, 2] = Isetpt[p, :]

    def solve_nonlinear(self, params, unknowns, resids):
        """ Calculate output. """

        self.setx(params)
        self.raw = self.MBI.evaluate(self.x)[:, 0].reshape((self.n, 7, 12),
                                                           order='F')
        unknowns['V_sol'] = np.zeros((12, self.n))
        for c in range(7):
            unknowns['V_sol'] += self.raw[:, c, :].T

    def linearize(self, params, unknowns, resids):
        """ Calculate and save derivatives. (i.e., Jacobian) """

        exposedArea = params['exposedArea']
        LOS = params['LOS']

        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] * exposedArea[c, p,:]
                self.dV_dT[:, p, i] += self.raw1[:, c, p]
                self.dV_dA[:, c, p] += self.raw2[:, c, p] * LOS
                self.dV_dI[:, p] += self.raw3[:, c, p]

    def apply_linear(self, params, unknowns, dparams, dunknowns, dresids, mode):
        """ Matrix-vector product with the Jacobian. """

        dV_sol = dresids['V_sol']

        if mode == 'fwd':

            if 'LOS' in dparams:
                dV_sol += self.dV_dL.T * dparams['LOS']

            if 'temperature' in dparams:
                for p in range(12):
                    i = 4 if p < 4 else (p % 4)
                    dV_sol[p, :] += self.dV_dT[:, p, i] * dparams['temperature'][i,:]

            if 'Isetpt' in dparams:
                dV_sol += self.dV_dI.T * dparams['Isetpt']

            if 'exposedArea' in dparams:
                for p in range(12):
                    dV_sol[p, :] += \
                        np.sum(self.dV_dA[:,:, p] * dparams['exposedArea'][:, p,:].T, 1)

        else:
            for p in range(12):
                i = 4 if p < 4 else (p % 4)

                if 'LOS' in dparams:
                    dparams['LOS'] += self.dV_dL[:, p] * dV_sol[p,:]

                if 'temperature' in dparams:
                    dparams['temperature'][i,:] += self.dV_dT[:, p, i] * dV_sol[p,:]

                if 'Isetpt' in dparams:
                    dparams['Isetpt'][p,:] += self.dV_dI[:, p] * dV_sol[p,:]

                if 'exposedArea' in dparams:
                    dexposedArea = dparams['exposedArea']
                    for c in range(7):
                        dexposedArea[c, p, :] += self.dV_dA[:, c, p] * dV_sol[p,:]
Ejemplo n.º 13
0
class Solar_ExposedArea(ExplicitComponent):
    """
    Exposed area calculation for a given solar cell

    p: panel ID [0,11]
    c: cell ID [0,6]
    a: fin angle [0,90]
    z: azimuth [0,360]
    e: elevation [0,180]
    LOS: line of sight with the sun [0,1]
    """
    def __init__(self, n, raw1_file=None, raw2_file=None):
        super(Solar_ExposedArea, self).__init__()

        self.n = n
        self.raw1_file = raw1_file
        self.raw2_file = raw2_file

    def setup(self):
        n = self.n
        raw1_file = self.raw1_file
        raw2_file = self.raw2_file

        fpath = os.path.dirname(os.path.realpath(__file__))
        if not raw1_file:
            raw1_file = fpath + '/data/Solar/Area10.txt'
        if not raw2_file:
            raw2_file = fpath + '/data/Solar/Area_all.txt'

        raw1 = np.genfromtxt(raw1_file)
        raw2 = np.loadtxt(raw2_file)

        nc = self.nc = 7
        self.np = 12

        self.na = 10
        self.nz = 73
        self.ne = 37
        angle = np.zeros(self.na)
        azimuth = np.zeros(self.nz)
        elevation = np.zeros(self.ne)

        index = 0
        for i in range(self.na):
            angle[i] = raw1[index]
            index += 1
        for i in range(self.nz):
            azimuth[i] = raw1[index]
            index += 1

        index -= 1
        azimuth[self.nz - 1] = 2.0 * np.pi
        for i in range(self.ne):
            elevation[i] = raw1[index]
            index += 1

        angle[0] = 0.0
        angle[-1] = np.pi / 2.0
        azimuth[0] = 0.0
        azimuth[-1] = 2 * np.pi
        elevation[0] = 0.0
        elevation[-1] = np.pi

        counter = 0
        data = np.zeros((self.na, self.nz, self.ne, self.np * self.nc))
        flat_size = self.na * self.nz * self.ne
        for p in range(self.np):
            for c in range(nc):
                data[:, :, :, counter] = \
                    raw2[nc * p + c][119:119 + flat_size].reshape((self.na,
                                                                   self.nz,
                                                                   self.ne))
                counter += 1

        self.MBI = MBI(data, [angle, azimuth, elevation], [4, 10, 8],
                       [4, 4, 4])

        self.MBI.seterr('raise')

        self.x = np.zeros((self.n, 3))
        self.Jfin = None
        self.Jaz = None
        self.Jel = None

        # Inputs
        self.add_input('finAngle',
                       0.0,
                       units='rad',
                       desc='Fin angle of solar panel')

        self.add_input(
            'azimuth',
            np.zeros((n, )),
            units='rad',
            desc='Azimuth angle of the sun in the body-fixed frame over time')

        self.add_input(
            'elevation',
            np.zeros((n, )),
            units='rad',
            desc='Elevation angle of the sun in the body-fixed frame over time'
        )

        # Outputs
        self.add_output(
            'exposedArea',
            np.zeros((n, self.nc, self.np)),
            desc='Exposed area to sun for each solar cell over time',
            units='m**2',
            lower=-5e-3,
            upper=1.834e-1)

        self.declare_partials('exposedArea', 'finAngle')

        nn = self.nc * self.np
        rows = np.tile(np.arange(nn), n) + np.repeat(nn * np.arange(n), nn)
        cols = np.tile(np.repeat(0, nn), n) + np.repeat(np.arange(n), nn)

        self.declare_partials('exposedArea', 'azimuth', rows=rows, cols=cols)
        self.declare_partials('exposedArea', 'elevation', rows=rows, cols=cols)

    def compute(self, inputs, outputs):
        """
        Calculate outputs.
        """
        self.setx(inputs)
        P = self.MBI.evaluate(self.x)
        outputs['exposedArea'] = P.reshape(self.n, self.nc, self.np, order='F')

    def setx(self, inputs):
        """
        Sets our state array
        """
        result = fixangles(self.n, inputs['azimuth'], inputs['elevation'])
        self.x[:, 0] = inputs['finAngle']
        self.x[:, 1] = result[0]
        self.x[:, 2] = result[1]

    def compute_partials(self, inputs, partials):
        """
        Calculate and save derivatives. (i.e., Jacobian)
        """
        Jfin = self.MBI.evaluate(self.x, 1).reshape(self.n,
                                                    self.nc,
                                                    self.np,
                                                    order='F')
        Jaz = self.MBI.evaluate(self.x, 2).reshape(self.n,
                                                   self.nc,
                                                   self.np,
                                                   order='F')
        Jel = self.MBI.evaluate(self.x, 3).reshape(self.n,
                                                   self.nc,
                                                   self.np,
                                                   order='F')

        partials['exposedArea', 'finAngle'] = Jfin.flatten()
        partials['exposedArea', 'azimuth'] = Jaz.flatten()
        partials['exposedArea', 'elevation'] = Jel.flatten()