Source code for latom.surrogate.om_metamodels_llo2heo

"""
@authors: Alberto FOSSA' Giuliana Elena MICELI

"""

import numpy as np

from latom.nlp.nlp_heo_2d import TwoDim3PhasesLLO2HEONLP
from latom.analyzer.analyzer_heo_2d import TwoDimLLO2ApoAnalyzer, TwoDimLLO2ApoContinuationAnalyzer
from latom.surrogate.om_metamodels import MetaModel
from latom.utils.pickle_utils import save
from latom.utils.spacecraft import Spacecraft
from latom.plots.response_surfaces import RespSurf


[docs]class TwoDimLLO2ApoMetaModel(MetaModel): """`TwoDimLLO2ApoMetaModel` implements `MetaModel` for a two-dimensional escape burn from an LLO to an intermediate ballistic arc to reach the specified HEO apoapsis radius. """
[docs] @staticmethod def solve(body, sc, alt, t_bounds, method, nb_seg, order, solver, snopt_opts=None, u_bound=None, **kwargs): """Solve the NLP for the i-th `twr` and k-th `Isp` values. Parameters ---------- body : Primary Central attracting body sc : Spacecraft Spacecraft object characterized by the i-th `twr` and k-th `Isp` values alt : float Orbit altitude [m] t_bounds : iterable Time of flight lower and upper bounds expressed as fraction of `tof` method : str Transcription method used to discretize the continuous time trajectory into a finite set of nodes, allowed ``gauss-lobatto``, ``radau-ps`` and ``runge-kutta`` nb_seg : int Number of segments in which the phase is discretized order : int Transcription order within the phase, must be odd solver : str NLP solver, must be supported by OpenMDAO snopt_opts : dict or None, optional SNOPT optional settings expressed as key-value pairs. Default is None u_bound : str, optional Specify the bounds on the radial velocity along the transfer as ``lower``, ``upper`` or ``None``. Default is ``None`` Other Parameters ---------------- rp : float HEO periapsis radius [m] t : float HEO period [s] Returns ------- m_prop : float Propellant fraction [-] f : bool Failure status """ tr = TwoDimLLO2ApoAnalyzer(body, sc, alt, kwargs['rp'], kwargs['t'], t_bounds, method, nb_seg, order, solver, snopt_opts=snopt_opts) f = tr.run_driver() tr.get_solutions(explicit=False, scaled=False) tr.nlp.cleanup() m_prop = 1. - tr.insertion_burn.mf/tr.sc.m0 return m_prop, f
[docs]class TwoDimLLO2ApoContinuationMetaModel(MetaModel): """`TwoDimLLO2ApoContinuationMetaModel` implements `MetaModel` for a two-dimensional escape burn from an LLO to an intermediate ballistic arc to reach the specified HEO apoapsis radius. For each `Isp` value in the sampling grid, the training data are computed using a continuation method for decreasing `twr` values. Parameters ---------- distributed : bool, optional ``True`` if the component has variables that are distributed across multiple processes, ``False`` otherwise. Default is ``False`` extrapolate : bool, optional Sets whether extrapolation should be performed when an input is out of bounds. Default is ``False`` method : str, optional Spline interpolation method to use for all outputs among ``cubic``, ``slinear``, ``lagrange2``, ``lagrange3``, ``akima``, ``scipy_cubic``, ``scipy_slinear``, ``scipy_quintic``. Default is ``scipy_cubic`` training_data_gradients : bool, optional Sets whether gradients with respect to output training data should be computed. Default is ``True`` vec_size : int, optional Number of points to evaluate at once. Default is ``1`` rec_file : str or ``None``, optional Name of the file in `latom.data.metamodels` where the meta model is stored or ``None`` if a new model has to be built. Default is ``None`` Attributes ---------- energy : ndarray Spacecraft specific energy at the end of the transfer on all training points [m^2/s^2] """ def __init__(self, distributed=False, extrapolate=False, method='scipy_cubic', training_data_gradients=True, vec_size=1, rec_file=None): self.energy = None MetaModel.__init__(self, distributed=distributed, extrapolate=extrapolate, method=method, training_data_gradients=training_data_gradients, vec_size=vec_size, rec_file=rec_file)
[docs] def load(self, rec_file): """Loads stored data to instantiate a meta model. Parameters ---------- rec_file : str Name of the file in `latom.data.metamodels` where the meta model is stored """ MetaModel.load(self, rec_file) self.energy = self.d['energy']
[docs] def save(self, rec_file): """Saves data corresponding to a meta model instance. Parameters ---------- rec_file : str Name of the file in `latom.data.metamodels` where the meta model is stored """ d = {'Isp': self.Isp, 'twr': self.twr, 'm_prop': self.m_prop, 'failures': self.failures, 'energy': self.energy} save(d, self.abs_path(rec_file))
[docs] def compute_grid(self, twr_lim, isp_lim, nb_samp): """Computes a regular sampling grid in the input space `twr, Isp`. Parameters ---------- twr_lim : iterable Thrust/weight ratio lower and upper limits [-] isp_lim : iterable Specific impulse lower and upper limits [s] nb_samp : iterable Number of samples along the `twr` and `Isp` axes """ MetaModel.compute_grid(self, twr_lim, isp_lim, nb_samp) self.energy = np.zeros(nb_samp)
[docs] def sampling(self, body, twr_lim, isp_lim, alt, t_bounds, method, nb_seg, order, solver, nb_samp, snopt_opts=None, u_bound=None, rec_file=None, **kwargs): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body twr_lim : iterable Thrust/weight ratio lower and upper limits [-] isp_lim : iterable Specific impulse lower and upper limits [s] alt : float Orbit altitude [m] t_bounds : iterable Time of flight lower and upper bounds expressed as fraction of `tof` method : str Transcription method used to discretize the continuous time trajectory into a finite set of nodes, allowed ``gauss-lobatto``, ``radau-ps`` and ``runge-kutta`` nb_seg : int or iterable Number of segments in which each phase is discretized order : int or iterable Transcription order within each phase, must be odd solver : str NLP solver, must be supported by OpenMDAO nb_samp : iterable Number of samples along the `twr` and `Isp` axes snopt_opts : dict or None, optional SNOPT optional settings expressed as key-value pairs. Default is None u_bound : str, optional Specify the bounds on the radial velocity along the transfer as ``lower``, ``upper`` or ``None``. Default is ``None`` rec_file : str, optional Name of the file in `latom.data.metamodels` where the meta model will be stored. Default is ``None`` Other Parameters ---------------- rp : float HEO periapsis radius [m] t : float HEO period [s] log_scale : bool ``True`` if `twr` values are given in logarithmic scale as `log(twr)` """ self.compute_grid(twr_lim, isp_lim, nb_samp) twr_flip = np.flip(self.twr) for j in range(nb_samp[1]): # loop over specific impulses print(f"\nMajor Iteration {j}\nSpecific impulse: {self.Isp[j]:.6f} s\n") if kwargs['log_scale']: sc = Spacecraft(self.Isp[j], np.exp(twr_flip[0]), g=body.g) else: sc = Spacecraft(self.Isp[j], twr_flip[0], g=body.g) tr = TwoDimLLO2ApoContinuationAnalyzer(body, sc, alt, kwargs['rp'], kwargs['t'], t_bounds, twr_flip, method, nb_seg, order, solver, snopt_opts=snopt_opts, log_scale=kwargs['log_scale']) tr.run_continuation() self.m_prop[:, j] = np.flip(tr.m_prop_list) self.energy[:, j] = np.flip(tr.energy_list) self.setup() if rec_file is not None: self.save(rec_file)
[docs] def plot(self, nb_lines=50, kind='prop', log_scale=False): """Plot the response surface corresponding to the loaded meta model. Parameters ---------- nb_lines : int, optional Number of contour lines. Default is ``50`` kind : str ``prop`` to display the propellant fraction `m_prop`, ``final`` to display the final spacecraft mass `1 - m_prop` log_scale : bool, optional Set to ``True`` if the `twr` values are in logarithmic scale. Default is ``False`` """ en = RespSurf(self.Isp, self.twr, self.energy, 'Specific energy [m^2/s^2]', nb_lines=nb_lines, log_scale=log_scale) en.plot() MetaModel.plot(self, nb_lines=nb_lines, kind=kind, log_scale=log_scale)
[docs]class TwoDim3PhasesLLO2HEOMetaModel(MetaModel): """`TwoDim3PhasesLLO2HEOMetaModel` implements `MetaModel` for a two-dimensional transfer from an LLO to an HEO modeled as a three-phases trajectory. """
[docs] @staticmethod def solve(body, sc, alt, t_bounds, method, nb_seg, order, solver, snopt_opts=None, u_bound=None, **kwargs): """Solve the NLP for the i-th `twr` and k-th `Isp` values. Parameters ---------- body : Primary Central attracting body sc : Spacecraft Spacecraft object characterized by the i-th `twr` and k-th `Isp` values alt : float Orbit altitude [m] t_bounds : iterable Time of flight lower and upper bounds expressed as fraction of `tof` method : str Transcription method used to discretize the continuous time trajectory into a finite set of nodes, allowed ``gauss-lobatto``, ``radau-ps`` and ``runge-kutta`` nb_seg : int Number of segments in which the phase is discretized order : int Transcription order within the phase, must be odd solver : str NLP solver, must be supported by OpenMDAO snopt_opts : dict or None, optional SNOPT optional settings expressed as key-value pairs. Default is None u_bound : str, optional Specify the bounds on the radial velocity along the transfer as ``lower``, ``upper`` or ``None``. Default is ``None`` Other Parameters ---------------- rp : float HEO periapsis radius [m] t : float HEO period [s] phase_name : iterable Names for the three phases within OpenMDAO Returns ------- m_prop : float Propellant fraction [-] f : bool Failure status """ nlp = TwoDim3PhasesLLO2HEONLP(body, sc, alt, kwargs['rp'], kwargs['t'], (-np.pi/2, np.pi/2), t_bounds, method, nb_seg, order, solver, kwargs['phase_name'], snopt_opts=snopt_opts) f = nlp.p.run_driver() nlp.cleanup() m_prop = 1. - nlp.p.get_val(nlp.phase_name[-1] + '.timeseries.states:m')[-1, -1] return m_prop, f