class BsplineParameters(ExplicitComponent): """ Creates a Bspline interpolant for several CADRE variables so that their time histories can be shaped with m control points instead of n time points. """ def __init__(self, n, m): super(BsplineParameters, self).__init__() self.n = n self.m = m self.deriv_cached = False def setup(self): m = self.m n = self.n # Inputs self.add_input('t1', 0., units='s', desc='Start time') self.add_input('t2', 43200., units='s', desc='End time') self.add_input('CP_P_comm', np.zeros((m, )), units='W', desc='Communication power at the control points') self.add_input('CP_gamma', np.zeros((m, )), units='rad', desc='Satellite roll angle at control points') self.add_input( 'CP_Isetpt', np.zeros((m, 12)), units='A', desc='Currents of the solar panels at the control points') # Outputs self.add_output('P_comm', np.ones((n, )), units='W', desc='Communication power over time') self.add_output('Gamma', 0.1 * np.ones((n, )), units='rad', desc='Satellite roll angle over time') self.add_output('Isetpt', 0.2 * np.ones((n, 12)), units='A', desc='Currents of the solar panels over time') self.declare_partials('P_comm', 'CP_P_comm') self.declare_partials('Gamma', 'CP_gamma') rowm = np.repeat(0, m) colm = 12 * np.arange(m) rown = np.tile(rowm, n) + np.repeat(12 * np.arange(n), m) coln = np.tile(colm, n) rows = np.tile(rown, 12) + np.repeat(np.arange(12), n * m) cols = np.tile(coln, 12) + np.repeat(np.arange(12), n * m) self.declare_partials('Isetpt', 'CP_Isetpt', rows=rows, cols=cols) def compute(self, inputs, outputs): """ Calculate outputs. """ # Only need to do this once. if self.deriv_cached is False: t1 = inputs['t1'] t2 = inputs['t2'] n = self.n self.B = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(0, 0) self.Bdot = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(1, 0) self.BT = self.B.transpose() self.BdotT = self.Bdot.transpose() self.deriv_cached = True outputs['P_comm'] = self.B.dot(inputs['CP_P_comm']) outputs['Gamma'] = self.B.dot(inputs['CP_gamma']) for k in range(12): outputs['Isetpt'][:, k] = self.B.dot(inputs['CP_Isetpt'][:, k]) def compute_partials(self, inputs, partials): """ Calculate and save derivatives. (i.e., Jacobian) """ B = self.B partials['P_comm', 'CP_P_comm'] = B partials['Gamma', 'CP_gamma'] = B # TODO : need to fix the time issue so that we can declare very sparse derivatives. partials['Isetpt', 'CP_Isetpt'] = np.tile(B.todense().flat, 12)
class BsplineParameters(ExplicitComponent): """ Creates a Bspline interpolant for several CADRE variables so that their time histories can be shaped with m control points instead of n time points. """ def __init__(self, n, m): super(BsplineParameters, self).__init__() self.n = n self.m = m self.deriv_cached = False def setup(self): m = self.m n = self.n # Inputs self.add_input('t1', 0., units='s', desc='Start time') self.add_input('t2', 43200., units='s', desc='End time') self.add_input('CP_P_comm', np.zeros((m, )), units='W', desc='Communication power at the control points') self.add_input('CP_gamma', np.zeros((m, )), units='rad', desc='Satellite roll angle at control points') self.add_input('CP_Isetpt', np.zeros((12, m)), units='A', desc='Currents of the solar panels at the control points') # Outputs self.add_output('P_comm', np.ones((n, )), units='W', desc='Communication power over time') self.add_output('Gamma', 0.1*np.ones((n,)), units='rad', desc='Satellite roll angle over time') self.add_output('Isetpt', 0.2*np.ones((12, n)), units='A', desc='Currents of the solar panels over time') def compute(self, inputs, outputs): """ Calculate outputs. """ # Only need to do this once. if self.deriv_cached is False: t1 = inputs['t1'] t2 = inputs['t2'] n = self.n self.B = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(0, 0) self.Bdot = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(1, 0) self.BT = self.B.transpose() self.BdotT = self.Bdot.transpose() self.deriv_cached = True outputs['P_comm'] = self.B.dot(inputs['CP_P_comm']) outputs['Gamma'] = self.B.dot(inputs['CP_gamma']) for k in range(12): outputs['Isetpt'][k, :] = self.B.dot(inputs['CP_Isetpt'][k, :]) def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): """ Matrix-vector product with the Jacobian. """ if mode == 'fwd': if 'P_comm' in d_outputs and 'CP_P_comm' in d_inputs: d_outputs['P_comm'] += self.B.dot(d_inputs['CP_P_comm']) if 'Gamma' in d_outputs and 'CP_gamma' in d_inputs: d_outputs['Gamma'] += self.B.dot(d_inputs['CP_gamma']) if 'Isetpt' in d_outputs and 'CP_Isetpt' in d_inputs: for k in range(12): d_outputs['Isetpt'][k, :] += self.B.dot(d_inputs['CP_Isetpt'][k, :]) else: if 'P_comm' in d_outputs and 'CP_P_comm' in d_inputs: d_inputs['CP_P_comm'] += self.BT.dot(d_outputs['P_comm']) if 'Gamma' in d_outputs and 'CP_gamma' in d_inputs: d_inputs['CP_gamma'] += self.BT.dot(d_outputs['Gamma']) if 'Isetpt' in d_outputs and 'CP_Isetpt' in d_inputs: for k in range(12): d_inputs['CP_Isetpt'][k, :] += self.BT.dot(d_outputs['Isetpt'][k, :])
class BsplineParameters(Component): '''Creates a Bspline interpolant for several CADRE variables so that their time histories can be shaped with m control points instead of n time points.''' def __init__(self, n, m): super(BsplineParameters, self).__init__() self.n = n self.m = m # Inputs self.add_param('t1', 0., units='s', desc='Start time') self.add_param('t2', 43200., units='s', desc='End time') self.add_param('CP_P_comm', np.zeros((self.m, )), units='W', desc='Communication power at the control points') self.add_param('CP_gamma', np.zeros((self.m, )), units='rad', desc='Satellite roll angle at control points') self.add_param('CP_Isetpt', np.zeros((12,self.m)), units='A', desc='Currents of the solar panels at the control points') # Outputs self.add_output('P_comm', np.ones((n, )), units='W', desc='Communication power over time') self.add_output('Gamma', 0.1*np.ones((n,)), units='rad', desc='Satellite roll ang le over time') self.add_output('Isetpt', 0.2*np.ones((12, n)), units="A", desc="Currents of the solar panels over time") self.deriv_cached = False def solve_nonlinear(self, params, unknowns, resids): """ Calculate output. """ # Only need to do this once. if self.deriv_cached == False: t1 = params['t1'] t2 = params['t2'] n = self.n self.B = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(0, 0) self.Bdot = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(1, 0) self.BT = self.B.transpose() self.BdotT = self.Bdot.transpose() self.deriv_cached = True unknowns['P_comm'] = self.B.dot(params['CP_P_comm']) unknowns['Gamma'] = self.B.dot(params['CP_gamma']) for k in range(12): unknowns['Isetpt'][k, :] = self.B.dot(params['CP_Isetpt'][k, :]) def apply_linear(self, params, unknowns, dparams, dunknowns, dresids, mode): """ Matrix-vector product with the Jacobian. """ if mode == 'fwd': if 'P_comm' in dresids and 'CP_P_comm' in dparams: dresids['P_comm'] += self.B.dot(dparams['CP_P_comm']) if 'Gamma' in dresids and 'CP_gamma' in dparams: dresids['Gamma'] += self.B.dot(dparams['CP_gamma']) if 'Isetpt' in dresids and 'CP_Isetpt' in dparams: for k in range(12): dresids['Isetpt'][k, :] += self.B.dot(dparams['CP_Isetpt'][k, :]) else: if 'P_comm' in dresids and 'CP_P_comm' in dparams: dparams['CP_P_comm'] += self.BT.dot(dresids['P_comm']) if 'Gamma' in dresids and 'CP_gamma' in dparams: dparams['CP_gamma'] += self.BT.dot(dresids['Gamma']) if 'Isetpt' in dresids and 'CP_Isetpt' in dparams: for k in range(12): dparams['CP_Isetpt'][k, :] += self.BT.dot(dresids['Isetpt'][k, :])
class BsplineParameters(ExplicitComponent): """ Creates a Bspline interpolant for several CADRE variables so that their time histories can be shaped with m control points instead of n time points. """ def __init__(self, n, m): super(BsplineParameters, self).__init__() self.n = n self.m = m self.deriv_cached = False def setup(self): m = self.m n = self.n # Inputs self.add_input('t1', 0., units='s', desc='Start time') self.add_input('t2', 43200., units='s', desc='End time') self.add_input('CP_P_comm', np.zeros((m, )), units='W', desc='Communication power at the control points') self.add_input('CP_gamma', np.zeros((m, )), units='rad', desc='Satellite roll angle at control points') self.add_input( 'CP_Isetpt', np.zeros((12, m)), units='A', desc='Currents of the solar panels at the control points') # Outputs self.add_output('P_comm', np.ones((n, )), units='W', desc='Communication power over time') self.add_output('Gamma', 0.1 * np.ones((n, )), units='rad', desc='Satellite roll angle over time') self.add_output('Isetpt', 0.2 * np.ones((12, n)), units='A', desc='Currents of the solar panels over time') def compute(self, inputs, outputs): """ Calculate outputs. """ # Only need to do this once. if self.deriv_cached is False: t1 = inputs['t1'] t2 = inputs['t2'] n = self.n self.B = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(0, 0) self.Bdot = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(1, 0) self.BT = self.B.transpose() self.BdotT = self.Bdot.transpose() self.deriv_cached = True outputs['P_comm'] = self.B.dot(inputs['CP_P_comm']) outputs['Gamma'] = self.B.dot(inputs['CP_gamma']) for k in range(12): outputs['Isetpt'][k, :] = self.B.dot(inputs['CP_Isetpt'][k, :]) def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): """ Matrix-vector product with the Jacobian. """ if mode == 'fwd': if 'P_comm' in d_outputs and 'CP_P_comm' in d_inputs: d_outputs['P_comm'] += self.B.dot(d_inputs['CP_P_comm']) if 'Gamma' in d_outputs and 'CP_gamma' in d_inputs: d_outputs['Gamma'] += self.B.dot(d_inputs['CP_gamma']) if 'Isetpt' in d_outputs and 'CP_Isetpt' in d_inputs: for k in range(12): d_outputs['Isetpt'][k, :] += self.B.dot( d_inputs['CP_Isetpt'][k, :]) else: if 'P_comm' in d_outputs and 'CP_P_comm' in d_inputs: d_inputs['CP_P_comm'] += self.BT.dot(d_outputs['P_comm']) if 'Gamma' in d_outputs and 'CP_gamma' in d_inputs: d_inputs['CP_gamma'] += self.BT.dot(d_outputs['Gamma']) if 'Isetpt' in d_outputs and 'CP_Isetpt' in d_inputs: for k in range(12): d_inputs['CP_Isetpt'][k, :] += self.BT.dot( d_outputs['Isetpt'][k, :])
class BsplineParameters(Component): '''Creates a Bspline interpolant for several CADRE variables so that their time histories can be shaped with m control points instead of n time points.''' def __init__(self, n, m): super(BsplineParameters, self).__init__() self.n = n self.m = m # Inputs self.add_param('t1', 0., units='s', desc='Start time') self.add_param('t2', 43200., units='s', desc='End time') self.add_param('CP_P_comm', np.zeros((self.m, )), units='W', desc='Communication power at the control points') self.add_param('CP_gamma', np.zeros((self.m, )), units='rad', desc='Satellite roll angle at control points') self.add_param( 'CP_Isetpt', np.zeros((12, self.m)), units='A', desc='Currents of the solar panels at the control points') # Outputs self.add_output('P_comm', np.ones((n, )), units='W', desc='Communication power over time') self.add_output('Gamma', 0.1 * np.ones((n, )), units='rad', desc='Satellite roll ang le over time') self.add_output('Isetpt', 0.2 * np.ones((12, n)), units="A", desc="Currents of the solar panels over time") self.deriv_cached = False def solve_nonlinear(self, params, unknowns, resids): """ Calculate output. """ # Only need to do this once. if self.deriv_cached == False: t1 = params['t1'] t2 = params['t2'] n = self.n self.B = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(0, 0) self.Bdot = MBI(np.zeros(n), [np.linspace(t1, t2, n)], [self.m], [4]).getJacobian(1, 0) self.BT = self.B.transpose() self.BdotT = self.Bdot.transpose() self.deriv_cached = True unknowns['P_comm'] = self.B.dot(params['CP_P_comm']) unknowns['Gamma'] = self.B.dot(params['CP_gamma']) for k in range(12): unknowns['Isetpt'][k, :] = self.B.dot(params['CP_Isetpt'][k, :]) def apply_linear(self, params, unknowns, dparams, dunknowns, dresids, mode): """ Matrix-vector product with the Jacobian. """ if mode == 'fwd': if 'P_comm' in dresids and 'CP_P_comm' in dparams: dresids['P_comm'] += self.B.dot(dparams['CP_P_comm']) if 'Gamma' in dresids and 'CP_gamma' in dparams: dresids['Gamma'] += self.B.dot(dparams['CP_gamma']) if 'Isetpt' in dresids and 'CP_Isetpt' in dparams: for k in range(12): dresids['Isetpt'][k, :] += self.B.dot( dparams['CP_Isetpt'][k, :]) else: if 'P_comm' in dresids and 'CP_P_comm' in dparams: dparams['CP_P_comm'] += self.BT.dot(dresids['P_comm']) if 'Gamma' in dresids and 'CP_gamma' in dparams: dparams['CP_gamma'] += self.BT.dot(dresids['Gamma']) if 'Isetpt' in dresids and 'CP_Isetpt' in dparams: for k in range(12): dparams['CP_Isetpt'][k, :] += self.BT.dot( dresids['Isetpt'][k, :])