Source code for latom.surrogate.smt_surrogates

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

"""

import numpy as np
import matplotlib.pyplot as plt
from copy import deepcopy

from smt.sampling_methods import LHS, FullFactorial
from smt.surrogate_models import IDW, KPLS, KPLSK, KRG, LS, QP, RBF, RMTB, RMTC

from latom.utils.spacecraft import Spacecraft, ImpulsiveBurn
from latom.utils.keplerian_orbit import TwoDimOrb
from latom.nlp.nlp_2d import TwoDimAscConstNLP, TwoDimAscVarNLP, TwoDimAscVToffNLP, TwoDimDescTwoPhasesNLP,\
    TwoDimDescConstNLP, TwoDimDescVarNLP, TwoDimDescVLandNLP
from latom.guess.guess_2d import HohmannTransfer
from latom.plots.response_surfaces import RespSurf
from latom.data.smt.data_smt import dirname_smt
from latom.utils.pickle_utils import save, load


[docs]class SurrogateModel: """`SurrogateModel` class sets up a surrogate model object defined in the Surrogate Modelling Toolbox (SMT) [2]_ package to compute and exploit data for different transfer trajectories. The model inputs are the spacecraft specific impulse `Isp` and initial thrust/weight ratio `twr` while the model output is the propellant fraction `m_prop`. Parameters ---------- train_method : str Training method among ``IDW``, ``KPLS``, ``KPLSK``, ``KRG``, ``LS``, ``QP``, ``RBF``, ``RMTB``, ``RMTC`` rec_file : str or ``None``, optional Name of the file in `latom.data.smt` where the surrogate model is stored or ``None`` if a new model has to be built. Default is ``None`` Attributes ---------- limits : ndarray Sampling grid limits in terms of minimum and maximum `Isp` and `twr` x_samp : ndarray Sampling points as `Isp, twr` tuples m_prop : ndarray Propellant fraction on training points [-] failures : ndarray Matrix of boolean to verify each NLP solution has converged d : dict Dictionary that contain all the information to reconstruct a meta model trained : IDW, KPLS, KPLSK, KRG, LS, QP, RBF, RMTB or RMTC Surrogate model object defined by SMT References ---------- .. [2] M. A. Bouhlel and J. T. Hwang and N. Bartoli and R. Lafage and J. Morlier and J. R. R. A. Martins. A Python surrogate modeling framework with derivatives. Advances in Engineering Software, 2019. """ def __init__(self, train_method, rec_file=None): """Initializes `SurrogateModel` class. """ self.limits = self.x_samp = self.m_prop = self.failures = self.d = None self.trained = None if rec_file is not None: self.load(rec_file) self.train(train_method)
[docs] @staticmethod def abs_path(rec_file): """Returns the absolute path of the file where the surrogate model is stored. Parameters ---------- rec_file : str Name of the file in `latom.data.smt` where the surrogate model is stored Returns ------- fid : str Full path where the surrogate model is stored """ return '/'.join([dirname_smt, rec_file])
[docs] def load(self, rec_file): """Loads stored data to instantiate a surrogate model. Parameters ---------- rec_file : str Name of the file in `latom.data.smt` where the surrogate model is stored """ self.d = load(self.abs_path(rec_file)) self.limits = self.d['limits'] self.x_samp = self.d['x_samp'] self.m_prop = self.d['m_prop'] self.failures = self.d['failures']
[docs] def save(self, rec_file): """Saves data corresponding to a surrogate model instance. Parameters ---------- rec_file : str Name of the file in `latom.data.smt` where the surrogate model is stored """ d = {'limits': self.limits, 'x_samp': self.x_samp, 'm_prop': self.m_prop, 'failures': self.failures} save(d, self.abs_path(rec_file))
[docs] def compute_grid(self, isp_lim, twr_lim, nb_samp, samp_method='full', criterion='m'): """Compute the sampling grid fro given `Isp` and `twr` limits and sampling scheme. Parameters ---------- isp_lim : iterable Specific impulse lower and upper bounds [s] twr_lim : iterable Thrust/weight ratio lower and upper bounds [-] nb_samp : int Total number of samples. Must be a perfect square if ``full`` is chosen as `samp_method` samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``full`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively`` Default is ``m`` """ self.limits = np.vstack((np.asarray(isp_lim), np.asarray(twr_lim))) if samp_method == 'lhs': samp = LHS(xlimits=self.limits, criterion=criterion) elif samp_method == 'full': samp = FullFactorial(xlimits=self.limits) else: raise ValueError('samp_method must be either lhs or full') self.x_samp = samp(nb_samp) self.m_prop = np.zeros((nb_samp, 1)) self.failures = np.zeros((nb_samp, 1))
[docs] @staticmethod def solve(nlp, i): """Solve the i-th NLP problem. Parameters ---------- nlp : NLP NLP object i : int Current iteration Returns ------- m_prop : float Propellant fraction [-] f : bool Failure status """ print(f"\nIteration {i}\nIsp: {nlp.sc.Isp:.6f} s\ttwr: {nlp.sc.twr:.6f}") f = nlp.p.run_driver() print("\nFailure: {0}".format(f)) if isinstance(nlp.phase_name, str): phase_name = nlp.phase_name else: phase_name = nlp.phase_name[-1] m_prop = 1.0 - nlp.p.get_val(phase_name + '.timeseries.states:m')[-1, -1] nlp.cleanup() return m_prop, f
[docs] def train(self, train_method, **kwargs): """Trains the surrogate model with given training data. Parameters ---------- train_method : str Training method among ``IDW``, ``KPLS``, ``KPLSK``, ``KRG``, ``LS``, ``QP``, ``RBF``, ``RMTB``, ``RMTC`` kwargs : dict Additional keyword arguments supported by SMT objects """ if train_method == 'IDW': self.trained = IDW(**kwargs) elif train_method == 'KPLS': self.trained = KPLS(**kwargs) elif train_method == 'KPLSK': self.trained = KPLSK(**kwargs) elif train_method == 'KRG': self.trained = KRG(**kwargs) elif train_method == 'LS': self.trained = LS(**kwargs) elif train_method == 'QP': self.trained = QP(**kwargs) elif train_method == 'RBF': self.trained = RBF(**kwargs) elif train_method == 'RMTB': self.trained = RMTB(xlimits=self.limits, **kwargs) elif train_method == 'RMTC': self.trained = RMTC(xlimits=self.limits, **kwargs) else: raise ValueError('train_method must be one between IDW, KPLS, KPLSK, KRG, LS, QP, RBF, RMTB, RMTC') self.trained.set_training_values(self.x_samp, self.m_prop) self.trained.train()
[docs] def evaluate(self, isp, twr): """Evaluate the surrogate model in the given set of points. Parameters ---------- isp : float or iterable Specific impulse on evaluation points [s] twr : float or iterable Thrust/weight ratio on evaluation points [-] Returns ------- m_eval : float or iterable Propellant fraction on evaluation points [-] """ if isinstance(isp, float): isp = [isp] if isinstance(twr, float): twr = [twr] x_eval = np.hstack((np.reshape(isp, (len(isp), 1)), np.reshape(twr, (len(twr), 1)))) m_eval = self.trained.predict_values(x_eval) return m_eval
[docs] def compute_matrix(self, nb_eval=None): """Compute structured matrices for `Isp`, `twr` and `m_prop` to display the training data on a response surface. Parameters ---------- nb_eval : int or ``None`` Number of points included in the matrix if Latin Hypercube Sampling has been used or ``None``. Default is ``None`` Returns ------- isp : ndarray Matrix of specific impulses [s] twr : ndarray Matrix of thrust/weight ratios [-] m_mat : ndarray Matrix of propellant fractions [-] """ if nb_eval is not None: # LHS samp_eval = FullFactorial(xlimits=self.limits) x_eval = samp_eval(nb_eval) m_prop_eval = self.trained.predict_values(x_eval) else: # Full-Factorial nb_eval = np.size(self.m_prop) x_eval = deepcopy(self.x_samp) m_prop_eval = deepcopy(self.m_prop) isp = np.unique(x_eval[:, 0]) twr = np.unique(x_eval[:, 1]) n = int(np.sqrt(nb_eval)) m_mat = np.reshape(m_prop_eval, (n, n)) return isp, twr, m_mat
[docs] def plot(self, nb_eval=None, nb_lines=50, kind='prop'): """Plot the response surface corresponding to the loaded surrogate model. Parameters ---------- nb_eval : int or ``None`` Number of points included in the matrix if Latin Hypercube Sampling has been used or ``None``. Default is ``None`` 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` """ isp, twr, m_mat = self.compute_matrix(nb_eval=nb_eval) if kind == 'prop': surf_plot = RespSurf(isp, twr, m_mat, 'Propellant fraction', nb_lines=nb_lines) elif kind == 'final': surf_plot = RespSurf(isp, twr, (1 - m_mat), 'Final/initial mass ratio', nb_lines=nb_lines) else: raise ValueError('kind must be either prop or final') surf_plot.plot() plt.show()
[docs]class TwoDimAscConstSurrogate(SurrogateModel): """`TwoDimAscConstSurrogate` implements `SurrogateModel` for a two-dimensional ascent trajectory at constant thrust. """
[docs] def sampling(self, body, isp_lim, twr_lim, alt, theta, tof, t_bounds, method, nb_seg, order, solver, nb_samp, samp_method='lhs', criterion='m', snopt_opts=None, u_bound='lower'): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body isp_lim : iterable Specific impulse lower and upper limits [s] twr_lim : iterable Thrust/weight ratio lower and upper limits [-] alt : float Orbit altitude [m] theta : float Guessed spawn angle [rad] tof : float Guessed time of flight [s] 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 Total number of sampling points samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``lhs`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively``. Default is ``m`` 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 ``lower`` """ self.compute_grid(isp_lim, twr_lim, nb_samp, samp_method=samp_method, criterion=criterion) for i in range(nb_samp): sc = Spacecraft(self.x_samp[i, 0], self.x_samp[i, 1], g=body.g) nlp = TwoDimAscConstNLP(body, sc, alt, theta, (-np.pi/2, np.pi/2), tof, t_bounds, method, nb_seg, order, solver, 'powered', snopt_opts=snopt_opts, u_bound=u_bound) self.m_prop[i, 0], self.failures[i, 0] = self.solve(nlp, i)
[docs]class TwoDimAscVarSurrogate(SurrogateModel): """`TwoDimAscVarSurrogate` implements `SurrogateModel` for a two-dimensional ascent trajectory with variable thrust. """
[docs] def sampling(self, body, isp_lim, twr_lim, alt, t_bounds, method, nb_seg, order, solver, nb_samp, samp_method='lhs', criterion='m', snopt_opts=None, u_bound='lower'): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body isp_lim : iterable Specific impulse lower and upper limits [s] twr_lim : iterable Thrust/weight ratio lower and upper limits [-] 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 Total number of sampling points samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``lhs`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively``. Default is ``m`` 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 ``lower`` """ self.compute_grid(isp_lim, twr_lim, nb_samp, samp_method=samp_method, criterion=criterion) for i in range(nb_samp): sc = Spacecraft(self.x_samp[i, 0], self.x_samp[i, 1], g=body.g) nlp = TwoDimAscVarNLP(body, sc, alt, (-np.pi/2, np.pi/2), t_bounds, method, nb_seg, order, solver, 'powered', snopt_opts=snopt_opts, u_bound=u_bound) self.m_prop[i, 0], self.failures[i, 0] = self.solve(nlp, i)
[docs]class TwoDimAscVToffSurrogate(SurrogateModel): """`TwoDimAscVToffSurrogate` implements `SurrogateModel` for a two-dimensional ascent trajectory with variable thrust and minimum safe altitude. """
[docs] def sampling(self, body, isp_lim, twr_lim, alt, alt_safe, slope, t_bounds, method, nb_seg, order, solver, nb_samp, samp_method='lhs', criterion='m', snopt_opts=None, u_bound='lower'): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body isp_lim : iterable Specific impulse lower and upper limits [s] twr_lim : iterable Thrust/weight ratio lower and upper limits [-] alt : float Orbit altitude [m] alt_safe : float Asymptotic minimum safe altitude [m] slope : float Minimum safe altitude slope close to the launch site [-] 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 Total number of sampling points samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``lhs`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively``. Default is ``m`` 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 ``lower`` """ self.compute_grid(isp_lim, twr_lim, nb_samp, samp_method=samp_method, criterion=criterion) for i in range(nb_samp): sc = Spacecraft(self.x_samp[i, 0], self.x_samp[i, 1], g=body.g) nlp = TwoDimAscVToffNLP(body, sc, alt, alt_safe, slope, (-np.pi/2, np.pi/2), t_bounds, method, nb_seg, order, solver, 'powered', snopt_opts=snopt_opts, u_bound=u_bound) self.m_prop[i, 0], self.failures[i, 0] = self.solve(nlp, i)
[docs]class TwoDimDescConstSurrogate(SurrogateModel): """`TwoDimDescConstSurrogate` implements `SurrogateModel` for a two-dimensional descent trajectory at constant thrust. """
[docs] def sampling(self, body, isp_lim, twr_lim, alt, alt_p, theta, tof, t_bounds, method, nb_seg, order, solver, nb_samp, samp_method='lhs', criterion='m', snopt_opts=None, u_bound='upper'): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body isp_lim : iterable Specific impulse lower and upper limits [s] twr_lim : iterable Thrust/weight ratio lower and upper limits [-] alt : float Orbit altitude [m] alt_p : float Periapsis altitude where the final powered descent is initiated [m] theta : float Guessed spawn angle [rad] tof : float Guessed time of flight [s] 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 Total number of sampling points samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``lhs`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively``. Default is ``m`` 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 ``upper`` """ self.compute_grid(isp_lim, twr_lim, nb_samp, samp_method=samp_method, criterion=criterion) ht = HohmannTransfer(body.GM, TwoDimOrb(body.GM, a=(body.R + alt), e=0.0), TwoDimOrb(body.GM, a=(body.R + alt_p), e=0.0)) for i in range(nb_samp): sc = Spacecraft(self.x_samp[i, 0], self.x_samp[i, 1], g=body.g) deorbit_burn = ImpulsiveBurn(sc, ht.dva) nlp = TwoDimDescConstNLP(body, deorbit_burn.sc, alt_p, ht.transfer.vp, theta, (0, 3/2*np.pi), tof, t_bounds, method, nb_seg, order, solver, 'powered', snopt_opts=snopt_opts, u_bound=u_bound) self.m_prop[i, 0], self.failures[i, 0] = self.solve(nlp, i)
[docs]class TwoDimDescVarSurrogate(SurrogateModel): """`TwoDimDescVarSurrogate` implements `SurrogateModel` for a two-dimensional descent trajectory with variable thrust. """
[docs] def sampling(self, body, isp_lim, twr_lim, alt, t_bounds, method, nb_seg, order, solver, nb_samp, samp_method='lhs', criterion='m', snopt_opts=None, u_bound='upper'): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body isp_lim : iterable Specific impulse lower and upper limits [s] twr_lim : iterable Thrust/weight ratio lower and upper limits [-] 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 Total number of sampling points samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``lhs`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively``. Default is ``m`` 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 ``upper`` """ self.compute_grid(isp_lim, twr_lim, nb_samp, samp_method=samp_method, criterion=criterion) for i in range(nb_samp): sc = Spacecraft(self.x_samp[i, 0], self.x_samp[i, 1], g=body.g) nlp = TwoDimDescVarNLP(body, sc, alt, (0.0, 3/2*np.pi), t_bounds, method, nb_seg, order, solver, 'powered', snopt_opts=snopt_opts, u_bound=u_bound) self.m_prop[i, 0], self.failures[i, 0] = self.solve(nlp, i)
[docs]class TwoDimDescVLandSurrogate(SurrogateModel): """`TwoDimDescVLandSurrogate` implements `SurrogateModel` for a two-dimensional descent trajectory with variable thrust and constrained minimum altitude. """
[docs] def sampling(self, body, isp_lim, twr_lim, alt, alt_safe, slope, t_bounds, method, nb_seg, order, solver, nb_samp, samp_method='lhs', criterion='m', snopt_opts=None, u_bound='upper'): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body isp_lim : iterable Specific impulse lower and upper limits [s] twr_lim : iterable Thrust/weight ratio lower and upper limits [-] alt : float Orbit altitude [m] alt_safe : float Asymptotic minimum safe altitude [m] slope : float Minimum safe altitude slope close to the launch site [-] 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 Total number of sampling points samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``lhs`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively``. Default is ``m`` 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 ``upper`` """ self.compute_grid(isp_lim, twr_lim, nb_samp, samp_method=samp_method, criterion=criterion) for i in range(nb_samp): sc = Spacecraft(self.x_samp[i, 0], self.x_samp[i, 1], g=body.g) nlp = TwoDimDescVLandNLP(body, sc, alt, alt_safe, slope, (0.0, 3/2*np.pi), t_bounds, method, nb_seg, order, solver, 'powered', snopt_opts=snopt_opts, u_bound=u_bound) self.m_prop[i, 0], self.failures[i, 0] = self.solve(nlp, i)
[docs]class TwoDimDescVertSurrogate(SurrogateModel): """`TwoDimDescVertSurrogate` implements `SurrogateModel` for a two-dimensional descent trajectory at constant thrust with final vertical descent phase. """
[docs] def sampling(self, body, isp_lim, twr_lim, alt, alt_p, alt_switch, theta, tof, t_bounds, method, nb_seg, order, solver, nb_samp, samp_method='lhs', criterion='m', snopt_opts=None): """Compute a new set of training data starting from a given sampling grid. Parameters ---------- body : Primary Central attracting body isp_lim : iterable Specific impulse lower and upper limits [s] twr_lim : iterable Thrust/weight ratio lower and upper limits [-] alt : float Orbit altitude [m] alt_p : float Periapsis altitude where the final powered descent is initiated [m] alt_switch : float Altitude at which the final vertical descent is triggered [m] theta : float Guessed spawn angle [rad] tof : iterable Guessed time of flight for the two phases [s] 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 Total number of sampling points samp_method : str, optional Sampling scheme, ``lhs`` for Latin Hypercube Sampling or ``full`` for Full-Factorial Sampling. Default is ``lhs`` criterion : str, optional Criterion used to construct the LHS design among ``center``, ``maximin``, ``centermaximin``, ``correlation``, ``c``, ``m``, ``cm``, ``corr``, ``ese``. ``c``, ``m``, ``cm`` and ``corr`` are abbreviations of ``center``, ``maximin``, ``centermaximin`` and ``correlation``, ``respectively``. Default is ``m`` snopt_opts : dict or None, optional SNOPT optional settings expressed as key-value pairs. Default is None """ self.compute_grid(isp_lim, twr_lim, nb_samp, samp_method=samp_method, criterion=criterion) ht = HohmannTransfer(body.GM, TwoDimOrb(body.GM, a=(body.R + alt), e=0.0), TwoDimOrb(body.GM, a=(body.R + alt_p), e=0.0)) for i in range(nb_samp): sc = Spacecraft(self.x_samp[i, 0], self.x_samp[i, 1], g=body.g) deorbit_burn = ImpulsiveBurn(sc, ht.dva) nlp = TwoDimDescTwoPhasesNLP(body, deorbit_burn.sc, alt, alt_switch, ht.transfer.vp, theta, (0.0, np.pi), tof, t_bounds, method, nb_seg, order, solver, ('free', 'vertical'), snopt_opts=snopt_opts) self.m_prop[i, 0], self.failures[i, 0] = self.solve(nlp, i)