# EMTG: Evolutionary Mission Trajectory Generator
# An open-source global optimization tool for preliminary mission design
# Provided by NASA Goddard Space Flight Center
#
# Copyright (c) 2013 - 2020 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Other Rights Reserved.
#
# Licensed under the NASA Open Source License (the "License"); 
# You may not use this file except in compliance with the License. 
# You may obtain a copy of the License at:
# https://opensource.org/licenses/NASA-1.3
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
# express or implied.   See the License for the specific language
# governing permissions and limitations under the License.

#PyEMTG JourneyOptions class
#auto-generated by make_EMTG_missionoptions_journeyoptions.py

class JourneyOptions(object):

    #************************************************************************************constructor
    def __init__(self, inputFile = None, lineNumber = None):
        self.journey_name = "default" #Journey name
        self.journey_central_body = "Sun" #Journey central body name
        self.destination_list = [3, 4] #destination list, as indices from the Universe file
        self.sequence = [] #flyby sequence, as indices from the Universe file
        self.phase_type = 2 #phase type, #0: MGALTS, #1: FBLTS, #2: MGALT, #3: FBLT, #4: PSBI, #5: PSFB, #6: MGAnDSMs, #7: CoastPhase, #8: SundmanCoastPhase
        self.impulses_per_phase = 1 #impulses per phase
        self.force_unit_magnitude_control = 0 #Force unit magnitude control?,#0: free control magnitude,#1: force unit magnitude,#2: force zero magnitude
        self.force_fixed_inertial_control = 0 #Force fixed inertial control? All control vectors in a phase must be identical if this is selected.
        self.override_num_steps = 0 #Override this journey's number of steps?
        self.number_of_steps = 20 #Number of time steps for this journey, if overriden
        self.override_duty_cycle = 0 #Journey override global duty cycle
        self.duty_cycle = 1 #Journey duty cycle
        self.override_PropagatorType = 0 #override propagator type?
        self.propagatorType = 1 #propagator type
        self.override_integration_step_size = 0 #Override global integration step size?
        self.integration_step_size = 86400 #integration step size (s)
        self.override_flyby_altitude_bounds = 0 #Override journey flyby altitude?
        self.flyby_altitude_bounds = [300.0, 1.0e+6] #Lower and upper bound on journey flyby altitude (only applies to the departure flyby, if there is one)
        self.PeriapseArrival_override_altitude = 0 #Override journey flyby altitude?
        self.PeriapseArrival_altitude_bounds = [300.0, 1.0e+6] #Lower and upper bound on journey flyby altitude (km)
        self.PeriapseDeparture_altitude_bounds = [185.0, 185.0] #PeriapseDeparture altitude bounds (in km)
        self.num_interior_control_points = 1 #number of interior control points for parallel shooting phase types
        self.CoastPhaseMatchPointFraction = 0.5 #coast phase match point fraction
        self.CoastPhaseForwardIntegrationStepLength = 86400 #coast phase forward integration step length (seconds)
        self.CoastPhaseBackwardIntegrationStepLength = 86400 #coast phase backward integration step length (seconds)
        self.journey_end_TCM = 0 #Journey-end TCM magnitude (km/s)
        self.enable_periapse_burns = 0 #Enable periapse burns in ephemeris pegged flybys?
        self.bounded_departure_date = 0 #Bound the departure epoch?
        self.timebounded = 0 #0: unbounded, 1: bounded flight time, 2: bounded arrival date
        self.departure_date_bounds = [0.0, 0.0] #MJD
        self.wait_time_bounds = [0.0, 1000.0] #days
        self.flight_time_bounds = [0.0, 0.0] #days
        self.arrival_date_bounds = [51544.5, 60000.0] #MJD
        self.departure_type = 0 #journey departure type, #0: launch or direct insertion, #1: depart from parking orbit (you can use this one in place of a launch vehicle model, and the departure burn will be done with the EDS motor), #2: free direct departure, i.e. do not burn to get the departure v_infinity (used for when operations about a small body are not modeled but the departure velocity is known), #3: flyby (only valid for successive journeys), #4: flyby with fixed v-infinity-out (only valid for successive journeys), #5: spiral-out from circular orbit (low-thrust missions only), #6: zero-turn flyby (for small bodies)
        self.initial_impulse_bounds = [0.0, 6.97] #what are the bounds on the initial impulse for each journey in km/s
        self.force_free_point_direct_insertion_along_velocity_vector = 0 #Force free point direct insertion burn to be along the inertial velocity vector?
        self.departure_elements_vary_flag = [0,0,0,0,0,0] #one entry for each element
        self.departure_elements = [0.0,0.0,0.0,0.0,0.0,0.0] #cartesian state or SMA, ECC, INC, RAAN, AOP, TA
        self.departure_elements_bounds = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] #bounds on elements or state components, two entries for each element
        self.departure_elements_reference_epoch = 51544.5 #MJD
        self.departure_elements_state_representation = 0 #departure free point state representation (Cartesian, SphericalRADEC, SphericalAZFPA, COE)
        self.departure_elements_frame = 0 #reference frame for journey departure elements (0: J2000_ICRF, 1: J2000_BCI, 2: J2000_BCF, 3: TrueOfDate_BCI, 4: TrueOfDate_BCF, 5: Principle Axes, 6: Topocentric, 7: Polar, 8: SAM)
        self.AllowJourneyFreePointDepartureToPropagate = 0 #Allow journey departure free point boundary to propagate (otherwise it is a fixed waypoint)
        self.maximum_starting_mass_increment = 0 #negative number indicates mass drop
        self.minimum_starting_mass_increment = 0 #negative number indicates mass drop
        self.fixed_starting_mass_increment = 0 #negative number indicates mass drop
        self.fixed_ending_mass_increment = 0 #negative number indicates mass drop
        self.variable_mass_increment = 0 #Vary initial mass increment?
        self.constrain_initial_mass = 0 #Constrain initial mass?
        self.maximum_initial_mass = 0 #If initial mass for this journey is constrained, enter the constraint value here.
        self.departure_class = 0 #journey departure boundary class, #0: Ephemeris-pegged (default EMTG), #1: Free point, #2: Ephemeris-referenced, #3: Periapse
        self.departure_ellipsoid_axes = [1e-8,1e-8,1e-8] #journey departure ellipsoid axes (3)
        self.arrival_type = 3 #journey arrival type, #0: insertion into parking orbit (use chemical Isp), #1: rendezvous (use chemical Isp), #2: intercept with bounded V_infinity, #3: low-thrust rendezvous (does not work if terminal phase is not low-thrust), #4: match final v-infinity vector, #5: match final v-infinity vector (low-thrust), #6: capture spiral, #7: momentum transfer (kinetic impactor)
        self.arrival_elements_vary_flag = [0,0,0,0,0,0] #one entry for each element
        self.arrival_elements = [0.0,0.0,0.0,0.0,0.0,0.0] #cartesian state or SMA, ECC, INC, RAAN, AOP, TA
        self.arrival_elements_bounds = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] #bounds on elements or state components, two entries for each element
        self.arrival_elements_reference_epoch = 51544.5 #MJD
        self.arrival_elements_state_representation = 0 #arrival free point state representation (Cartesian, SphericalRADEC, SphericalAZFPA, COE)
        self.arrival_elements_frame = 0 #reference frame for journey arrival elements (0: J2000_ICRF, 1: J2000_BCI, 2: J2000_BCF, 3: TrueOfDate_BCI, 4: TrueOfDate_BCF, 5: Principle Axes, 6: Topocentric, 7: Polar, 8: SAM)
        self.AllowJourneyFreePointArrivalToPropagate = 0 #Allow journey arrival free point boundary to propagate (otherwise it is a fixed waypoint)
        self.final_velocity = [0.0, 20.0, 0.0] #Bounds on this journey's final velocity (in km/s)
        self.forced_terminal_coast = 0 #Journey forced terminal coast (in days)
        self.forced_initial_coast = 0 #Journey forced initial coast (in days)
        self.arrival_class = 0 #journey arrival boundary class, #0: Ephemeris-pegged (default EMTG), #1: Free point, #2: Ephemeris-referenced, #3: Periapse
        self.arrival_ellipsoid_axes = [1e-8,1e-8,1e-8] #journey arrival ellipsoid axes (3)
        self.zero_turn_flyby_distance = 1000 #encounter distance (from center of object) for a zero-turn flyby (km)
        self.terminal_intercept_flyby_distance = 1000 #encounter distance (from center of object) for an ephemeris-pegged intercept (km)
        self.escape_spiral_starting_radius = 6678 #Starting orbital radius for an Edelbaum escape spiral (km)
        self.escape_spiral_final_radius = 6678 #Final orbit radius for an Edelbaum escape spiral (km)
        self.capture_spiral_final_radius = 6678 #Final orbit radius for an Edelbaum capture spiral (km)
        self.capture_spiral_starting_radius = 6678 #Starting orbital radius for an Edelbaum capture spiral (km)
        self.FreePointArrival_print_target_spec = 1 #Print a target spec for free point arrival at the end of this journey?
        self.journey_end_deltav = 0 #Journey-end delta-v (km/s)
        self.journey_end_propulsion_system = 0 #Propulsion system for journey-end maneuver, #0: Monoprop chemical, #1: Biprop chemical, #2: Electric
        self.perturbation_bodies = [] #Universe file indices of each perturbation body
        self.stage_after_departure = 0 #Stage after departure?
        self.stage_before_arrival = 0 #Stage before arrival?
        self.stage_after_arrival = 0 #Stage after arrival?
        self.freeze_decision_variables = 0 #Freeze this journey's decision variables?
        self.ephemeris_pegged_orbit_insertion_SMA = 6678 #SMA (in km) for ephemeris pegged orbit insertion
        self.ephemeris_pegged_orbit_insertion_ECC = 0 #ECC for ephemeris pegged orbit insertion
        self.impact_momentum_enhancement_factor = 1 #Impact momentum enhancement factor for planetary defense (also called beta)
        self.perturb_drag = 0 #Aerodynamic drag?
        self.spacecraft_drag_area = 70 #spacecraft area (for aerodynamic drag, in m^2)
        self.coefficient_of_drag = 2.2 #coefficient of drag, i.e. Cd (unitless)
        self.AtmosphericDensityModelKey = "Exponential" #Atmospheric density model
        self.AtmosphericDensityModelDataFile = "c:/Utilities/DoesNotExist.emtg_densityopt" #File defining atmospheric density model
        
        #empty lists for constraint definitions and trialX
        self.ManeuverConstraintDefinitions = []
        self.BoundaryConstraintDefinitions = []
        self.PhaseDistanceConstraintDefinitions = []
        self.trialX = []

        if inputFile != None:
            self.parse_journey(inputFile, lineNumber)
   
    #************************************************************************************parse
    def parse_journey(self, inputFile, lineNumber = 0):
        while True:
            line = inputFile.readline()
            if not line:
                break
            #strip off the newline character
            line = line.rstrip("\n\r ")
            
            lineNumber += 1
            if line == "END_JOURNEY":
                break
            
            #if we got this far, then this is a line worth reading
            #Note that unlike EMTG proper, PyEMTG does NOT length or bounds-check input files. But if you try to run an invalid .emtgopt, EMTG will notify you and help you fix it.
            
            if line.strip('\r') != "":
                if line[0] != "#":
                    #this is an active line, so it is space delimited
                    linecell = [entry.rstrip(" \r\n") for entry in line.split(" ")]
                    
                    if linecell[0] == "journey_name":
                        self.journey_name = linecell[1]
                  
                    elif linecell[0] == "journey_central_body":
                        self.journey_central_body = linecell[1]
                  
                    elif linecell[0] == "destination_list":
                        self.destination_list = [int(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "sequence":
                        self.sequence = [int(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "phase_type":
                        self.phase_type = int(linecell[1])
                  
                    elif linecell[0] == "impulses_per_phase":
                        self.impulses_per_phase = int(linecell[1])
                  
                    elif linecell[0] == "force_unit_magnitude_control":
                        self.force_unit_magnitude_control = int(linecell[1])
                  
                    elif linecell[0] == "force_fixed_inertial_control":
                        self.force_fixed_inertial_control = int(linecell[1])
                  
                    elif linecell[0] == "override_num_steps":
                        self.override_num_steps = int(linecell[1])
                  
                    elif linecell[0] == "number_of_steps":
                        self.number_of_steps = int(linecell[1])
                  
                    elif linecell[0] == "override_duty_cycle":
                        self.override_duty_cycle = int(linecell[1])
                  
                    elif linecell[0] == "duty_cycle":
                        self.duty_cycle = float(linecell[1])
                  
                    elif linecell[0] == "override_PropagatorType":
                        self.override_PropagatorType = int(linecell[1])
                  
                    elif linecell[0] == "propagatorType":
                        self.propagatorType = int(linecell[1])
                  
                    elif linecell[0] == "override_integration_step_size":
                        self.override_integration_step_size = int(linecell[1])
                  
                    elif linecell[0] == "integration_step_size":
                        self.integration_step_size = float(linecell[1])
                  
                    elif linecell[0] == "override_flyby_altitude_bounds":
                        self.override_flyby_altitude_bounds = int(linecell[1])
                  
                    elif linecell[0] == "flyby_altitude_bounds":
                        self.flyby_altitude_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "PeriapseArrival_override_altitude":
                        self.PeriapseArrival_override_altitude = int(linecell[1])
                  
                    elif linecell[0] == "PeriapseArrival_altitude_bounds":
                        self.PeriapseArrival_altitude_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "PeriapseDeparture_altitude_bounds":
                        self.PeriapseDeparture_altitude_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "num_interior_control_points":
                        self.num_interior_control_points = int(linecell[1])
                  
                    elif linecell[0] == "CoastPhaseMatchPointFraction":
                        self.CoastPhaseMatchPointFraction = float(linecell[1])
                  
                    elif linecell[0] == "CoastPhaseForwardIntegrationStepLength":
                        self.CoastPhaseForwardIntegrationStepLength = float(linecell[1])
                  
                    elif linecell[0] == "CoastPhaseBackwardIntegrationStepLength":
                        self.CoastPhaseBackwardIntegrationStepLength = float(linecell[1])
                  
                    elif linecell[0] == "journey_end_TCM":
                        self.journey_end_TCM = float(linecell[1])
                  
                    elif linecell[0] == "enable_periapse_burns":
                        self.enable_periapse_burns = int(linecell[1])
                  
                    elif linecell[0] == "bounded_departure_date":
                        self.bounded_departure_date = int(linecell[1])
                  
                    elif linecell[0] == "timebounded":
                        self.timebounded = int(linecell[1])
                  
                    elif linecell[0] == "departure_date_bounds":
                        self.departure_date_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "wait_time_bounds":
                        self.wait_time_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "flight_time_bounds":
                        self.flight_time_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "arrival_date_bounds":
                        self.arrival_date_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "departure_type":
                        self.departure_type = int(linecell[1])
                  
                    elif linecell[0] == "initial_impulse_bounds":
                        self.initial_impulse_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "force_free_point_direct_insertion_along_velocity_vector":
                        self.force_free_point_direct_insertion_along_velocity_vector = int(linecell[1])
                  
                    elif linecell[0] == "departure_elements_vary_flag":
                        self.departure_elements_vary_flag = [int(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "departure_elements":
                        self.departure_elements = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "departure_elements_bounds":
                        self.departure_elements_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "departure_elements_reference_epoch":
                        self.departure_elements_reference_epoch = float(linecell[1])
                  
                    elif linecell[0] == "departure_elements_state_representation":
                        self.departure_elements_state_representation = int(linecell[1])
                  
                    elif linecell[0] == "departure_elements_frame":
                        self.departure_elements_frame = int(linecell[1])
                  
                    elif linecell[0] == "AllowJourneyFreePointDepartureToPropagate":
                        self.AllowJourneyFreePointDepartureToPropagate = int(linecell[1])
                  
                    elif linecell[0] == "maximum_starting_mass_increment":
                        self.maximum_starting_mass_increment = float(linecell[1])
                  
                    elif linecell[0] == "minimum_starting_mass_increment":
                        self.minimum_starting_mass_increment = float(linecell[1])
                  
                    elif linecell[0] == "fixed_starting_mass_increment":
                        self.fixed_starting_mass_increment = float(linecell[1])
                  
                    elif linecell[0] == "fixed_ending_mass_increment":
                        self.fixed_ending_mass_increment = float(linecell[1])
                  
                    elif linecell[0] == "variable_mass_increment":
                        self.variable_mass_increment = int(linecell[1])
                  
                    elif linecell[0] == "constrain_initial_mass":
                        self.constrain_initial_mass = int(linecell[1])
                  
                    elif linecell[0] == "maximum_initial_mass":
                        self.maximum_initial_mass = float(linecell[1])
                  
                    elif linecell[0] == "departure_class":
                        self.departure_class = int(linecell[1])
                  
                    elif linecell[0] == "departure_ellipsoid_axes":
                        self.departure_ellipsoid_axes = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "arrival_type":
                        self.arrival_type = int(linecell[1])
                  
                    elif linecell[0] == "arrival_elements_vary_flag":
                        self.arrival_elements_vary_flag = [int(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "arrival_elements":
                        self.arrival_elements = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "arrival_elements_bounds":
                        self.arrival_elements_bounds = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "arrival_elements_reference_epoch":
                        self.arrival_elements_reference_epoch = float(linecell[1])
                  
                    elif linecell[0] == "arrival_elements_state_representation":
                        self.arrival_elements_state_representation = int(linecell[1])
                  
                    elif linecell[0] == "arrival_elements_frame":
                        self.arrival_elements_frame = int(linecell[1])
                  
                    elif linecell[0] == "AllowJourneyFreePointArrivalToPropagate":
                        self.AllowJourneyFreePointArrivalToPropagate = int(linecell[1])
                  
                    elif linecell[0] == "final_velocity":
                        self.final_velocity = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "forced_terminal_coast":
                        self.forced_terminal_coast = float(linecell[1])
                  
                    elif linecell[0] == "forced_initial_coast":
                        self.forced_initial_coast = float(linecell[1])
                  
                    elif linecell[0] == "arrival_class":
                        self.arrival_class = int(linecell[1])
                  
                    elif linecell[0] == "arrival_ellipsoid_axes":
                        self.arrival_ellipsoid_axes = [float(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "zero_turn_flyby_distance":
                        self.zero_turn_flyby_distance = float(linecell[1])
                  
                    elif linecell[0] == "terminal_intercept_flyby_distance":
                        self.terminal_intercept_flyby_distance = float(linecell[1])
                  
                    elif linecell[0] == "escape_spiral_starting_radius":
                        self.escape_spiral_starting_radius = float(linecell[1])
                  
                    elif linecell[0] == "escape_spiral_final_radius":
                        self.escape_spiral_final_radius = float(linecell[1])
                  
                    elif linecell[0] == "capture_spiral_final_radius":
                        self.capture_spiral_final_radius = float(linecell[1])
                  
                    elif linecell[0] == "capture_spiral_starting_radius":
                        self.capture_spiral_starting_radius = float(linecell[1])
                  
                    elif linecell[0] == "FreePointArrival_print_target_spec":
                        self.FreePointArrival_print_target_spec = int(linecell[1])
                  
                    elif linecell[0] == "journey_end_deltav":
                        self.journey_end_deltav = float(linecell[1])
                  
                    elif linecell[0] == "journey_end_propulsion_system":
                        self.journey_end_propulsion_system = int(linecell[1])
                  
                    elif linecell[0] == "perturbation_bodies":
                        self.perturbation_bodies = [int(entry) for entry in linecell[1:]]
                  
                    elif linecell[0] == "stage_after_departure":
                        self.stage_after_departure = int(linecell[1])
                  
                    elif linecell[0] == "stage_before_arrival":
                        self.stage_before_arrival = int(linecell[1])
                  
                    elif linecell[0] == "stage_after_arrival":
                        self.stage_after_arrival = int(linecell[1])
                  
                    elif linecell[0] == "freeze_decision_variables":
                        self.freeze_decision_variables = int(linecell[1])
                  
                    elif linecell[0] == "ephemeris_pegged_orbit_insertion_SMA":
                        self.ephemeris_pegged_orbit_insertion_SMA = float(linecell[1])
                  
                    elif linecell[0] == "ephemeris_pegged_orbit_insertion_ECC":
                        self.ephemeris_pegged_orbit_insertion_ECC = float(linecell[1])
                  
                    elif linecell[0] == "impact_momentum_enhancement_factor":
                        self.impact_momentum_enhancement_factor = float(linecell[1])
                  
                    elif linecell[0] == "perturb_drag":
                        self.perturb_drag = int(linecell[1])
                  
                    elif linecell[0] == "spacecraft_drag_area":
                        self.spacecraft_drag_area = float(linecell[1])
                  
                    elif linecell[0] == "coefficient_of_drag":
                        self.coefficient_of_drag = float(linecell[1])
                  
                    elif linecell[0] == "AtmosphericDensityModelKey":
                        self.AtmosphericDensityModelKey = linecell[1]
                  
                    elif linecell[0] == "AtmosphericDensityModelDataFile":
                        self.AtmosphericDensityModelDataFile = linecell[1]
                  
                    elif linecell[0] == "BEGIN_MANEUVER_CONSTRAINT_BLOCK":
                        self.ManeuverConstraintDefinitions = []
                        while True:
                            entry = inputFile.readline()
                            lineNumber += 1
                            if "END_MANEUVER_CONSTRAINT_BLOCK" in entry:
                                break
                            self.ManeuverConstraintDefinitions.append(entry)
                    
                    elif linecell[0] == "BEGIN_BOUNDARY_CONSTRAINT_BLOCK":
                        self.BoundaryConstraintDefinitions = []
                        while True:
                            entry = inputFile.readline()
                            lineNumber += 1
                            if "END_BOUNDARY_CONSTRAINT_BLOCK" in entry:
                                break
                            self.BoundaryConstraintDefinitions.append(entry)
                    
                    elif linecell[0] == "BEGIN_PHASE_DISTANCE_CONSTRAINT_BLOCK":
                        self.PhaseDistanceConstraintDefinitions = []
                        while True:
                            entry = inputFile.readline()
                            lineNumber += 1
                            if "END_PHASE_DISTANCE_CONSTRAINT_BLOCK" in entry:
                                break
                            self.PhaseDistanceConstraintDefinitions.append(entry)
                    
                    elif linecell[0] == "BEGIN_TRIALX":
                        self.trialX = []
                        while True:
                            entry = inputFile.readline()
                            lineNumber += 1
                            if "END_TRIALX" in entry:
                                break
                            commalinecell = entry.split(',')
                            self.trialX.append(commalinecell)
                    
    #************************************************************************************write
    def write(self, optionsFileName, writeAll = False):
        with open(optionsFileName, "a+") as optionsFile:
            optionsFile.write("\n")
            optionsFile.write("\n")
            optionsFile.write("BEGIN_JOURNEY\n")
            optionsFile.write("\n")
            
            if (self.journey_name != "default" or writeAll):
                optionsFile.write("#Journey name\n")
                optionsFile.write("journey_name " + str(self.journey_name) + "\n")
    
            if (self.journey_central_body != "Sun" or writeAll):
                optionsFile.write("#Journey central body name\n")
                optionsFile.write("journey_central_body " + str(self.journey_central_body) + "\n")
    
            if (self.destination_list != [3, 4] or writeAll):
                optionsFile.write("#destination list, as indices from the Universe file\n")
                optionsFile.write("destination_list")
                for entry in self.destination_list:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.sequence != [] or writeAll):
                optionsFile.write("#flyby sequence, as indices from the Universe file\n")
                optionsFile.write("sequence")
                for entry in self.sequence:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.phase_type != 2 or writeAll):
                optionsFile.write("#phase type\n#0: MGALTS\n#1: FBLTS\n#2: MGALT\n#3: FBLT\n#4: PSBI\n#5: PSFB\n#6: MGAnDSMs\n#7: CoastPhase\n#8: SundmanCoastPhase\n")
                optionsFile.write("phase_type " + str(self.phase_type) + "\n")
    
            if (self.impulses_per_phase != 1 or writeAll):
                optionsFile.write("#impulses per phase\n")
                optionsFile.write("impulses_per_phase " + str(self.impulses_per_phase) + "\n")
    
            if (self.force_unit_magnitude_control != 0 or writeAll):
                optionsFile.write("#Force unit magnitude control?\n#0: free control magnitude\n#1: force unit magnitude\n#2: force zero magnitude\n")
                optionsFile.write("force_unit_magnitude_control " + str(self.force_unit_magnitude_control) + "\n")
    
            if (self.force_fixed_inertial_control != 0 or writeAll):
                optionsFile.write("#Force fixed inertial control? All control vectors in a phase must be identical if this is selected.\n")
                optionsFile.write("force_fixed_inertial_control " + str(int(self.force_fixed_inertial_control)) + "\n")
    
            if (self.override_num_steps != 0 or writeAll):
                optionsFile.write("#Override this journey's number of steps?\n")
                optionsFile.write("override_num_steps " + str(int(self.override_num_steps)) + "\n")
    
            if (self.number_of_steps != 20 or writeAll):
                optionsFile.write("#Number of time steps for this journey, if overriden\n")
                optionsFile.write("number_of_steps " + str(self.number_of_steps) + "\n")
    
            if (self.override_duty_cycle != 0 or writeAll):
                optionsFile.write("#Journey override global duty cycle\n")
                optionsFile.write("override_duty_cycle " + str(int(self.override_duty_cycle)) + "\n")
    
            if (self.duty_cycle != 1 or writeAll):
                optionsFile.write("#Journey duty cycle\n")
                optionsFile.write("duty_cycle " + str(self.duty_cycle) + "\n")
    
            if (self.override_PropagatorType != 0 or writeAll):
                optionsFile.write("#override propagator type?\n")
                optionsFile.write("override_PropagatorType " + str(int(self.override_PropagatorType)) + "\n")
    
            if (self.propagatorType != 1 or writeAll):
                optionsFile.write("#propagator type\n")
                optionsFile.write("propagatorType " + str(self.propagatorType) + "\n")
    
            if (self.override_integration_step_size != 0 or writeAll):
                optionsFile.write("#Override global integration step size?\n")
                optionsFile.write("override_integration_step_size " + str(int(self.override_integration_step_size)) + "\n")
    
            if (self.integration_step_size != 86400 or writeAll):
                optionsFile.write("#integration step size (s)\n")
                optionsFile.write("integration_step_size " + str(self.integration_step_size) + "\n")
    
            if (self.override_flyby_altitude_bounds != 0 or writeAll):
                optionsFile.write("#Override journey flyby altitude?\n")
                optionsFile.write("override_flyby_altitude_bounds " + str(int(self.override_flyby_altitude_bounds)) + "\n")
    
            if (self.flyby_altitude_bounds != [300.0, 1.0e+6] or writeAll):
                optionsFile.write("#Lower and upper bound on journey flyby altitude (only applies to the departure flyby, if there is one)\n")
                optionsFile.write("flyby_altitude_bounds")
                for entry in self.flyby_altitude_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.PeriapseArrival_override_altitude != 0 or writeAll):
                optionsFile.write("#Override journey flyby altitude?\n")
                optionsFile.write("PeriapseArrival_override_altitude " + str(int(self.PeriapseArrival_override_altitude)) + "\n")
    
            if (self.PeriapseArrival_altitude_bounds != [300.0, 1.0e+6] or writeAll):
                optionsFile.write("#Lower and upper bound on journey flyby altitude (km)\n")
                optionsFile.write("PeriapseArrival_altitude_bounds")
                for entry in self.PeriapseArrival_altitude_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.PeriapseDeparture_altitude_bounds != [185.0, 185.0] or writeAll):
                optionsFile.write("#PeriapseDeparture altitude bounds (in km)\n")
                optionsFile.write("PeriapseDeparture_altitude_bounds")
                for entry in self.PeriapseDeparture_altitude_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.num_interior_control_points != 1 or writeAll):
                optionsFile.write("#number of interior control points for parallel shooting phase types\n")
                optionsFile.write("num_interior_control_points " + str(self.num_interior_control_points) + "\n")
    
            if (self.CoastPhaseMatchPointFraction != 0.5 or writeAll):
                optionsFile.write("#coast phase match point fraction\n")
                optionsFile.write("CoastPhaseMatchPointFraction " + str(self.CoastPhaseMatchPointFraction) + "\n")
    
            if (self.CoastPhaseForwardIntegrationStepLength != 86400 or writeAll):
                optionsFile.write("#coast phase forward integration step length (seconds)\n")
                optionsFile.write("CoastPhaseForwardIntegrationStepLength " + str(self.CoastPhaseForwardIntegrationStepLength) + "\n")
    
            if (self.CoastPhaseBackwardIntegrationStepLength != 86400 or writeAll):
                optionsFile.write("#coast phase backward integration step length (seconds)\n")
                optionsFile.write("CoastPhaseBackwardIntegrationStepLength " + str(self.CoastPhaseBackwardIntegrationStepLength) + "\n")
    
            if (self.journey_end_TCM != 0 or writeAll):
                optionsFile.write("#Journey-end TCM magnitude (km/s)\n")
                optionsFile.write("journey_end_TCM " + str(self.journey_end_TCM) + "\n")
    
            if (self.enable_periapse_burns != 0 or writeAll):
                optionsFile.write("#Enable periapse burns in ephemeris pegged flybys?\n")
                optionsFile.write("enable_periapse_burns " + str(int(self.enable_periapse_burns)) + "\n")
    
            if (self.bounded_departure_date != 0 or writeAll):
                optionsFile.write("#Bound the departure epoch?\n")
                optionsFile.write("bounded_departure_date " + str(int(self.bounded_departure_date)) + "\n")
    
            if (self.timebounded != 0 or writeAll):
                optionsFile.write("#does the journey have time bounds?\n#0: unbounded\n#1: bounded flight time\n#2: bounded arrival date\n#3: bounded aggregate flight time\n")
                optionsFile.write("timebounded " + str(self.timebounded) + "\n")
    
            if (self.departure_date_bounds != [0.0, 0.0] or writeAll):
                optionsFile.write("#Journey departure epoch bounds (MJD, two entries)\n")
                optionsFile.write("departure_date_bounds")
                for entry in self.departure_date_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.wait_time_bounds != [0.0, 1000.0] or writeAll):
                optionsFile.write("#Journey wait time bounds (days)\n")
                optionsFile.write("wait_time_bounds")
                for entry in self.wait_time_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.flight_time_bounds != [0.0, 0.0] or writeAll):
                optionsFile.write("#Journey flight time bounds (days)\n")
                optionsFile.write("flight_time_bounds")
                for entry in self.flight_time_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.arrival_date_bounds != [51544.5, 60000.0] or writeAll):
                optionsFile.write("#Journey arrival date bounds (MJD, two entries)\n")
                optionsFile.write("arrival_date_bounds")
                for entry in self.arrival_date_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.departure_type != 0 or writeAll):
                optionsFile.write("#journey departure type\n#0: launch or direct insertion\n#1: depart from parking orbit (you can use this one in place of a launch vehicle model, and the departure burn will be done with the EDS motor)\n#2: free direct departure, i.e. do not burn to get the departure v_infinity (used for when operations about a small body are not modeled but the departure velocity is known)\n#3: flyby (only valid for successive journeys)\n#4: flyby with fixed v-infinity-out (only valid for successive journeys)\n#5: spiral-out from circular orbit (low-thrust missions only)\n#6: zero-turn flyby (for small bodies)\n")
                optionsFile.write("departure_type " + str(self.departure_type) + "\n")
    
            if (self.initial_impulse_bounds != [0.0, 6.97] or writeAll):
                optionsFile.write("#what are the bounds on the initial impulse for each journey in km/s\\\n#you can set a very high upper bound if you are using a launchy vehicle model - the optimizer will find the correct value\n")
                optionsFile.write("initial_impulse_bounds")
                for entry in self.initial_impulse_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.force_free_point_direct_insertion_along_velocity_vector != 0 or writeAll):
                optionsFile.write("#Force free point direct insertion burn to be along the inertial velocity vector?\n")
                optionsFile.write("force_free_point_direct_insertion_along_velocity_vector " + str(int(self.force_free_point_direct_insertion_along_velocity_vector)) + "\n")
    
            if (self.departure_elements_vary_flag != [0,0,0,0,0,0] or writeAll):
                optionsFile.write("#one entry for each element\n")
                optionsFile.write("departure_elements_vary_flag")
                for entry in self.departure_elements_vary_flag:
                    optionsFile.write(" " + str(int(entry)))
                optionsFile.write("\n")
    
            if (self.departure_elements != [0.0,0.0,0.0,0.0,0.0,0.0] or writeAll):
                optionsFile.write("#cartesian state or SMA, ECC, INC, RAAN, AOP, TA\n")
                optionsFile.write("departure_elements")
                for entry in self.departure_elements:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.departure_elements_bounds != [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] or writeAll):
                optionsFile.write("#bounds on elements or state components, two entries for each element\n")
                optionsFile.write("departure_elements_bounds")
                for entry in self.departure_elements_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.departure_elements_reference_epoch != 51544.5 or writeAll):
                optionsFile.write("#Reference epoch (MJD) for journey departure elements\n")
                optionsFile.write("departure_elements_reference_epoch " + str(self.departure_elements_reference_epoch) + "\n")
    
            if (self.departure_elements_state_representation != 0 or writeAll):
                optionsFile.write("#arrival free point state representation (Cartesian, SphericalRADEC, SphericalAZFPA, COE)\n")
                optionsFile.write("departure_elements_state_representation " + str(self.departure_elements_state_representation) + "\n")
    
            if (self.departure_elements_frame != 0 or writeAll):
                optionsFile.write("#reference frame for journey departure elements (0: J2000_ICRF, 1: J2000_BCI, 2: J2000_BCF, 3: TrueOfDate_BCI, 4: TrueOfDate_BCF, 5: Principle Axes, 6: Topocentric, 7: Polar, 8: SAM)\n")
                optionsFile.write("departure_elements_frame " + str(self.departure_elements_frame) + "\n")
    
            if (self.AllowJourneyFreePointDepartureToPropagate != 0 or writeAll):
                optionsFile.write("#Allow journey departure free point boundary to propagate (otherwise it is a fixed waypoint)\n")
                optionsFile.write("AllowJourneyFreePointDepartureToPropagate " + str(int(self.AllowJourneyFreePointDepartureToPropagate)) + "\n")
    
            if (self.maximum_starting_mass_increment != 0 or writeAll):
                optionsFile.write("#upper bound on starting mass increment (negative number indicates mass drop) [kg]\n")
                optionsFile.write("maximum_starting_mass_increment " + str(self.maximum_starting_mass_increment) + "\n")
    
            if (self.minimum_starting_mass_increment != 0 or writeAll):
                optionsFile.write("#lower bound on starting mass increment (negative number indicates mass drop) [kg]\n")
                optionsFile.write("minimum_starting_mass_increment " + str(self.minimum_starting_mass_increment) + "\n")
    
            if (self.fixed_starting_mass_increment != 0 or writeAll):
                optionsFile.write("#starting mass increment (negative number indicates mass drop) [kg]\n")
                optionsFile.write("fixed_starting_mass_increment " + str(self.fixed_starting_mass_increment) + "\n")
    
            if (self.fixed_ending_mass_increment != 0 or writeAll):
                optionsFile.write("#ending mass increment (negative number indicates mass drop) [kg]\n")
                optionsFile.write("fixed_ending_mass_increment " + str(self.fixed_ending_mass_increment) + "\n")
    
            if (self.variable_mass_increment != 0 or writeAll):
                optionsFile.write("#Vary initial mass increment?\n")
                optionsFile.write("variable_mass_increment " + str(int(self.variable_mass_increment)) + "\n")
    
            if (self.constrain_initial_mass != 0 or writeAll):
                optionsFile.write("#Constrain initial mass?\n")
                optionsFile.write("constrain_initial_mass " + str(int(self.constrain_initial_mass)) + "\n")
    
            if (self.maximum_initial_mass != 0 or writeAll):
                optionsFile.write("#If initial mass for this journey is constrained, enter the constraint value here.\n")
                optionsFile.write("maximum_initial_mass " + str(self.maximum_initial_mass) + "\n")
    
            if (self.departure_class != 0 or writeAll):
                optionsFile.write("#journey departure boundary class\n#0: Ephemeris-pegged (default EMTG)\n#1: Free point\n#2: Ephemeris-referenced\n#3: Periapse\n")
                optionsFile.write("departure_class " + str(self.departure_class) + "\n")
    
            if (self.departure_ellipsoid_axes != [1e-8,1e-8,1e-8] or writeAll):
                optionsFile.write("#journey departure ellipsoid axes (3)\n")
                optionsFile.write("departure_ellipsoid_axes")
                for entry in self.departure_ellipsoid_axes:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.arrival_type != 3 or writeAll):
                optionsFile.write("#journey arrival type\n#0: insertion into parking orbit (use chemical Isp)\n#1: rendezvous (use chemical Isp)\n#2: intercept with bounded V_infinity\n#3: low-thrust rendezvous (does not work if terminal phase is not low-thrust)\n#4: match final v-infinity vector\n#5: match final v-infinity vector (low-thrust)\n#6: capture spiral\n#7: momentum transfer (kinetic impactor)\n")
                optionsFile.write("arrival_type " + str(self.arrival_type) + "\n")
    
            if (self.arrival_elements_vary_flag != [0,0,0,0,0,0] or writeAll):
                optionsFile.write("#one entry for each element\n")
                optionsFile.write("arrival_elements_vary_flag")
                for entry in self.arrival_elements_vary_flag:
                    optionsFile.write(" " + str(int(entry)))
                optionsFile.write("\n")
    
            if (self.arrival_elements != [0.0,0.0,0.0,0.0,0.0,0.0] or writeAll):
                optionsFile.write("#cartesian state or SMA, ECC, INC, RAAN, AOP, TA\n")
                optionsFile.write("arrival_elements")
                for entry in self.arrival_elements:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.arrival_elements_bounds != [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] or writeAll):
                optionsFile.write("#bounds on elements or state components, two entries for each element\n")
                optionsFile.write("arrival_elements_bounds")
                for entry in self.arrival_elements_bounds:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.arrival_elements_reference_epoch != 51544.5 or writeAll):
                optionsFile.write("#Reference epoch (MJD) for journey arrival elements\n")
                optionsFile.write("arrival_elements_reference_epoch " + str(self.arrival_elements_reference_epoch) + "\n")
    
            if (self.arrival_elements_state_representation != 0 or writeAll):
                optionsFile.write("#arrival free point state representation (Cartesian, SphericalRADEC, SphericalAZFPA, COE)\n")
                optionsFile.write("arrival_elements_state_representation " + str(self.arrival_elements_state_representation) + "\n")
    
            if (self.arrival_elements_frame != 0 or writeAll):
                optionsFile.write("#reference frame for journey arrival elements (0: J2000_ICRF, 1: J2000_BCI, 2: J2000_BCF, 3: TrueOfDate_BCI, 4: TrueOfDate_BCF, 5: Principle Axes, 6: Topocentric, 7: Polar, 8: SAM)\n")
                optionsFile.write("arrival_elements_frame " + str(self.arrival_elements_frame) + "\n")
    
            if (self.AllowJourneyFreePointArrivalToPropagate != 0 or writeAll):
                optionsFile.write("#Allow journey arrival free point boundary to propagate (otherwise it is a fixed waypoint)\n")
                optionsFile.write("AllowJourneyFreePointArrivalToPropagate " + str(int(self.AllowJourneyFreePointArrivalToPropagate)) + "\n")
    
            if (self.final_velocity != [0.0, 20.0, 0.0] or writeAll):
                optionsFile.write("#Bounds on this journey's final velocity (in km/s)\n")
                optionsFile.write("final_velocity")
                for entry in self.final_velocity:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.forced_terminal_coast != 0 or writeAll):
                optionsFile.write("#Journey forced terminal coast (in days)\n")
                optionsFile.write("forced_terminal_coast " + str(self.forced_terminal_coast) + "\n")
    
            if (self.forced_initial_coast != 0 or writeAll):
                optionsFile.write("#Journey forced initial coast (in days)\n")
                optionsFile.write("forced_initial_coast " + str(self.forced_initial_coast) + "\n")
    
            if (self.arrival_class != 0 or writeAll):
                optionsFile.write("#journey arrival boundary class\n#0: Ephemeris-pegged (default EMTG)\n#1: Free point\n#2: Ephemeris-referenced\n#3: Periapse\n")
                optionsFile.write("arrival_class " + str(self.arrival_class) + "\n")
    
            if (self.arrival_ellipsoid_axes != [1e-8,1e-8,1e-8] or writeAll):
                optionsFile.write("#journey arrival ellipsoid axes (3)\n")
                optionsFile.write("arrival_ellipsoid_axes")
                for entry in self.arrival_ellipsoid_axes:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.zero_turn_flyby_distance != 1000 or writeAll):
                optionsFile.write("#encounter distance (from center of object) for a zero-turn flyby (km)\n")
                optionsFile.write("zero_turn_flyby_distance " + str(self.zero_turn_flyby_distance) + "\n")
    
            if (self.terminal_intercept_flyby_distance != 1000 or writeAll):
                optionsFile.write("#encounter distance (from center of object) for an ephemeris-pegged intercept (km)\n")
                optionsFile.write("terminal_intercept_flyby_distance " + str(self.terminal_intercept_flyby_distance) + "\n")
    
            if (self.escape_spiral_starting_radius != 6678 or writeAll):
                optionsFile.write("#Starting orbital radius for an Edelbaum escape spiral (km)\n")
                optionsFile.write("escape_spiral_starting_radius " + str(self.escape_spiral_starting_radius) + "\n")
    
            if (self.escape_spiral_final_radius != 6678 or writeAll):
                optionsFile.write("#Final orbit radius for an Edelbaum capture spiral (km)\n")
                optionsFile.write("escape_spiral_final_radius " + str(self.escape_spiral_final_radius) + "\n")
    
            if (self.capture_spiral_final_radius != 6678 or writeAll):
                optionsFile.write("#Final orbit radius for an Edelbaum capture spiral (km)\n")
                optionsFile.write("capture_spiral_final_radius " + str(self.capture_spiral_final_radius) + "\n")
    
            if (self.capture_spiral_starting_radius != 6678 or writeAll):
                optionsFile.write("#Starting orbital radius for an Edelbaum capture spiral (km)\n")
                optionsFile.write("capture_spiral_starting_radius " + str(self.capture_spiral_starting_radius) + "\n")
    
            if (self.FreePointArrival_print_target_spec != 1 or writeAll):
                optionsFile.write("#Print a target spec for free point arrival at the end of this journey?\n")
                optionsFile.write("FreePointArrival_print_target_spec " + str(int(self.FreePointArrival_print_target_spec)) + "\n")
    
            if (self.journey_end_deltav != 0 or writeAll):
                optionsFile.write("#Journey-end delta-v (km/s)\n")
                optionsFile.write("journey_end_deltav " + str(self.journey_end_deltav) + "\n")
    
            if (self.journey_end_propulsion_system != 0 or writeAll):
                optionsFile.write("#Propulsion system for journey-end maneuver\n#0: Monoprop chemical\n#1: Biprop chemical\n#2: Electric\n")
                optionsFile.write("journey_end_propulsion_system " + str(self.journey_end_propulsion_system) + "\n")
    
            if (self.perturbation_bodies != [] or writeAll):
                optionsFile.write("#Which bodies are used for third-body perturbation?\n#Expressed as indices in the Universe file\n")
                optionsFile.write("perturbation_bodies")
                for entry in self.perturbation_bodies:
                    optionsFile.write(" " + str(entry))
                optionsFile.write("\n")
    
            if (self.stage_after_departure != 0 or writeAll):
                optionsFile.write("#Stage after departure?\n")
                optionsFile.write("stage_after_departure " + str(int(self.stage_after_departure)) + "\n")
    
            if (self.stage_before_arrival != 0 or writeAll):
                optionsFile.write("#Stage before arrival?\n")
                optionsFile.write("stage_before_arrival " + str(int(self.stage_before_arrival)) + "\n")
    
            if (self.stage_after_arrival != 0 or writeAll):
                optionsFile.write("#Stage after arrival?\n")
                optionsFile.write("stage_after_arrival " + str(int(self.stage_after_arrival)) + "\n")
    
            if (self.freeze_decision_variables != 0 or writeAll):
                optionsFile.write("#Freeze this journey's decision variables?\n")
                optionsFile.write("freeze_decision_variables " + str(int(self.freeze_decision_variables)) + "\n")
    
            if (self.ephemeris_pegged_orbit_insertion_SMA != 6678 or writeAll):
                optionsFile.write("#SMA (in km) for ephemeris pegged orbit insertion\n")
                optionsFile.write("ephemeris_pegged_orbit_insertion_SMA " + str(self.ephemeris_pegged_orbit_insertion_SMA) + "\n")
    
            if (self.ephemeris_pegged_orbit_insertion_ECC != 0 or writeAll):
                optionsFile.write("#ECC for ephemeris pegged orbit insertion\n")
                optionsFile.write("ephemeris_pegged_orbit_insertion_ECC " + str(self.ephemeris_pegged_orbit_insertion_ECC) + "\n")
    
            if (self.impact_momentum_enhancement_factor != 1 or writeAll):
                optionsFile.write("#Impact momentum enhancement factor for planetary defense (also called beta)\n")
                optionsFile.write("impact_momentum_enhancement_factor " + str(self.impact_momentum_enhancement_factor) + "\n")
    
            if (self.perturb_drag != 0 or writeAll):
                optionsFile.write("#Aerodynamic drag?\n")
                optionsFile.write("perturb_drag " + str(int(self.perturb_drag)) + "\n")
    
            if (self.spacecraft_drag_area != 70 or writeAll):
                optionsFile.write("#spacecraft area (for aerodynamic drag, in m^2)\n")
                optionsFile.write("spacecraft_drag_area " + str(self.spacecraft_drag_area) + "\n")
    
            if (self.coefficient_of_drag != 2.2 or writeAll):
                optionsFile.write("#coefficient of drag, i.e. Cd (unitless)\n")
                optionsFile.write("coefficient_of_drag " + str(self.coefficient_of_drag) + "\n")
    
            if (self.AtmosphericDensityModelKey != "Exponential" or writeAll):
                optionsFile.write("#Atmospheric density model\n")
                optionsFile.write("AtmosphericDensityModelKey " + str(self.AtmosphericDensityModelKey) + "\n")
    
            if (self.AtmosphericDensityModelDataFile != "c:/Utilities/DoesNotExist.emtg_densityopt" or writeAll):
                optionsFile.write("#File defining atmospheric density model\n")
                optionsFile.write("AtmosphericDensityModelDataFile " + str(self.AtmosphericDensityModelDataFile) + "\n")
    
            optionsFile.write("\n")
            optionsFile.write("#Maneuver constraint code\n")
            optionsFile.write("#Works for absolute and relative epochs and also magnitudes\n")
            optionsFile.write("BEGIN_MANEUVER_CONSTRAINT_BLOCK\n")
            for ManeuverConstraintDefinition in self.ManeuverConstraintDefinitions:
                optionsFile.write(ManeuverConstraintDefinition + "\n")
            optionsFile.write("END_MANEUVER_CONSTRAINT_BLOCK\n")
            optionsFile.write("\n")
            
            optionsFile.write("\n")
            optionsFile.write("#Boundary constraint code\n")
            optionsFile.write("BEGIN_BOUNDARY_CONSTRAINT_BLOCK\n")
            for BoundaryConstraintDefinition in self.BoundaryConstraintDefinitions:
                optionsFile.write(BoundaryConstraintDefinition + "\n")
            optionsFile.write("END_BOUNDARY_CONSTRAINT_BLOCK\n")
            optionsFile.write("\n")
            
            optionsFile.write("\n")
            optionsFile.write("#Phase distance constraint code\n")
            optionsFile.write("BEGIN_PHASE_DISTANCE_CONSTRAINT_BLOCK\n")
            for PhaseDistanceConstraintDefinition in self.PhaseDistanceConstraintDefinitions:
                optionsFile.write(PhaseDistanceConstraintDefinition + "\n")
            optionsFile.write("END_PHASE_DISTANCE_CONSTRAINT_BLOCK\n")
            optionsFile.write("\n")
            
            if len(self.trialX) > 0:
                optionsFile.write("#trial decision vector\n")
                optionsFile.write("BEGIN_TRIALX\n")
                for entry in self.trialX:
                    optionsFile.write(entry[0] + "," + '%17.20f' % float(entry[1]) + "\n")
                optionsFile.write("END_TRIALX\n")
            optionsFile.write("\n")
            
            optionsFile.write("END_JOURNEY")
            
    #************************************************************************************convert decision vector
    def ConvertDecisionVector(self, ParallelShootingStateRepresentation, PeriapseBoundaryStateRepresentation):                          
        if ParallelShootingStateRepresentation == 1:#SphericalRADEC, so we need to convert any SphericalAZFPA segments to SphericalRADEC
            from math import sin, cos, atan2, asin                                                                          
            for Xindex in range(0, len(self.trialX)):                                                                       
                description = self.trialX[Xindex][0]                                                                        
                prefix = description.split(':')[0]                                                                          
                                                                                                                            
                if ('PSFB_Step' in description or 'PSBI_Step' in description) and 'left state AZ' in description:                                           
                    #extract the SphericalAZFPA state                                                                       
                    r = float(self.trialX[Xindex - 4][1])                                                                   
                    RA = float(self.trialX[Xindex - 3][1])                                                                  
                    DEC = float(self.trialX[Xindex - 2][1])                                                                 
                    v = float(self.trialX[Xindex - 1][1])                                                                   
                    AZ = float(self.trialX[Xindex][1])                                                                      
                    FPA = float(self.trialX[Xindex + 1][1])                                                                 
                    #convert to cartesian                                                                                   
                    cosRA = cos(RA)                                                                                         
                    sinRA = sin(RA)                                                                                         
                    cosDEC = cos(DEC)                                                                                       
                    sinDEC = sin(DEC)                                                                                       
                    cosAZ = cos(AZ)                                                                                         
                    sinAZ = sin(AZ)                                                                                         
                    cosFPA = cos(FPA)                                                                                       
                    sinFPA = sin(FPA)                                                                                       
                                                                                                                            
                    xdot = -v * (sinFPA*(sinAZ*sinRA + cosAZ * cosRA*sinDEC) - cosFPA * cosDEC*cosRA);                      
                    ydot =  v * (sinFPA*(cosRA*sinAZ - cosAZ * sinDEC*sinRA) + cosFPA * cosDEC*sinRA);                      
                    zdot =  v * (cosFPA*sinDEC + cosDEC * cosAZ*sinFPA);                                                    
                                                                                                                            
                    #compute vRA and vDEC                                                                                   
                    vRA = atan2(ydot, xdot)                                                                                 
                    vDEC = asin(zdot / v)                                                                                   
                                                                                                                            
                    #write vRA and vDEC into the decision vector                                                            
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace('AZ','vRA')                                     
                    self.trialX[Xindex][1] = str(vRA)                                                                       
                    self.trialX[Xindex + 1][0] = self.trialX[Xindex + 1][0].replace('FPA','vDEC')                           
                    self.trialX[Xindex + 1][1] = str(vDEC)                                                                  
        elif ParallelShootingStateRepresentation == 2:#SphericalAZFPA - convert all SphericalRADEC to this format                       
            from math import sin, cos, atan2, asin, acos, pi                                                                
            import numpy                                                                                                    
            for Xindex in range(0, len(self.trialX)):                                                                       
                description = self.trialX[Xindex][0]                                                                        
                prefix = description.split(':')[0]                                                                          
                                                                                                                            
                if ('PSFB_Step' in description or 'PSBI_Step' in description) and 'left state vRA' in description:                                          
                    #extract the SphericalAZFPA state                                                                       
                    r = float(self.trialX[Xindex - 4][1])                                                                   
                    RA = float(self.trialX[Xindex - 3][1])                                                                  
                    DEC = float(self.trialX[Xindex - 2][1])                                                                 
                    v = float(self.trialX[Xindex - 1][1])                                                                   
                    vRA = float(self.trialX[Xindex][1])                                                                     
                    vDEC = float(self.trialX[Xindex + 1][1])                                                                
                    #convert to cartesian                                                                                   
                    cosRA = cos(RA)                                                                                         
                    sinRA = sin(RA)                                                                                         
                    cosDEC = cos(DEC)                                                                                       
                    sinDEC = sin(DEC)                                                                                       
                    cosvRA = cos(vRA)                                                                                       
                    sinvRA = sin(vRA)                                                                                       
                    cosvDEC = cos(vDEC)                                                                                     
                    sinvDEC = sin(vDEC)                                                                                     
                                                                                                                            
                    x = r * cosRA * cosDEC                                                                                  
                    y = r * sinRA * cosDEC                                                                                  
                    z = r * sinDEC;                                                                                         
                    xdot = v * cosvRA * cosvDEC                                                                             
                    ydot = v * sinvRA * cosvDEC                                                                             
                    zdot = v * sinvDEC;                                                                                     
                                                                                                                            
                    #compute AZ and FPA                                                                                     
                    FPA = acos( (x*xdot + y*ydot + z*zdot) / r / v )                                                        
                                                                                                                            
                    #azimuth is complicated                                                                                 
                    xhat = numpy.matrix([cos(RA)*cos(DEC), sin(RA)*cos(DEC), sin(DEC)]).T                                   
                    yhat = numpy.matrix([cos(RA + pi / 2.0), sin(RA + pi / 2.0), 0.0]).T                                    
                    zhat = numpy.matrix([-cos(RA)*sin(DEC), -sin(RA)*sin(DEC), cos(DEC)]).T                                 
                    R = numpy.hstack([xhat, yhat, zhat]).T                                                                  
                    V = numpy.matrix([xdot, ydot, zdot]).T                                                                  
                    Vprime = R * V                                                                                          
                    AZ = atan2(Vprime[1], Vprime[2])                                                                        
                                                                                                                            
                    #write vRA and vDEC into the decision vector                                                            
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace('vRA','AZ')                                     
                    self.trialX[Xindex][1] = str(AZ)                                                                        
                    self.trialX[Xindex + 1][0] = self.trialX[Xindex + 1][0].replace('vDEC','FPA')                           
                    self.trialX[Xindex + 1][1] = str(FPA)                                                                   
                                                                                                                            
        if PeriapseBoundaryStateRepresentation == 1:#SphericalRADEC - convert all SphericalAZFPA to SphericalRADEC          
            from math import sin, cos, atan2, asin                                                                          
            for Xindex in range(0, len(self.trialX)):                                                                       
                description = self.trialX[Xindex][0]                                                                        
                prefix = description.split(':')[0]                                                                          
                                                                                                                            
                if 'Periapse' in description and 'event left state AZ' in description:                                      
                    #extract the SphericalAZFPA state                                                                       
                    r = float(self.trialX[Xindex - 4][1])                                                                   
                    RA = float(self.trialX[Xindex - 3][1])                                                                  
                    DEC = float(self.trialX[Xindex - 2][1])                                                                 
                    v = float(self.trialX[Xindex - 1][1])                                                                   
                    AZ = float(self.trialX[Xindex][1])                                                                      
                    FPA = float(self.trialX[Xindex + 1][1])                                                                 
                    #convert to cartesian                                                                                   
                    cosRA = cos(RA)                                                                                         
                    sinRA = sin(RA)                                                                                         
                    cosDEC = cos(DEC)                                                                                       
                    sinDEC = sin(DEC)                                                                                       
                    cosAZ = cos(AZ)                                                                                         
                    sinAZ = sin(AZ)                                                                                         
                    cosFPA = cos(FPA)                                                                                       
                    sinFPA = sin(FPA)                                                                                       
                                                                                                                            
                    xdot = -v * (sinFPA*(sinAZ*sinRA + cosAZ * cosRA*sinDEC) - cosFPA * cosDEC*cosRA);                      
                    ydot =  v * (sinFPA*(cosRA*sinAZ - cosAZ * sinDEC*sinRA) + cosFPA * cosDEC*sinRA);                      
                    zdot =  v * (cosFPA*sinDEC + cosDEC * cosAZ*sinFPA);                                                    
                                                                                                                            
                    #compute vRA and vDEC                                                                                   
                    vRA = atan2(ydot, xdot)                                                                                 
                    vDEC = asin(zdot / v)                                                                                   
                                                                                                                            
                    #write vRA and vDEC into the decision vector                                                            
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace('AZ','vRA')                                     
                    self.trialX[Xindex][1] = str(vRA)                                                                       
                    self.trialX[Xindex + 1][0] = self.trialX[Xindex + 1][0].replace('FPA','vDEC')                           
                    self.trialX[Xindex + 1][1] = str(vDEC)                                                                  
        elif PeriapseBoundaryStateRepresentation == 2:#SphericalAZFPA - convert all SphericalRADEC to this format           
            from math import sin, cos, atan2, asin, acos, pi                                                                
            import numpy                                                                                                    
            for Xindex in range(0, len(self.trialX)):                                                                       
                description = self.trialX[Xindex][0]                                                                        
                prefix = description.split(':')[0]                                                                          
                                                                                                                            
                if 'Periapse' in description and 'event left state vRA' in description:                                     
                    #extract the SphericalAZFPA state                                                                       
                    r = float(self.trialX[Xindex - 4][1])                                                                   
                    RA = float(self.trialX[Xindex - 3][1])                                                                  
                    DEC = float(self.trialX[Xindex - 2][1])                                                                 
                    v = float(self.trialX[Xindex - 1][1])                                                                   
                    vRA = float(self.trialX[Xindex][1])                                                                     
                    vDEC = float(self.trialX[Xindex + 1][1])                                                                
                    #convert to cartesian                                                                                   
                    cosRA = cos(RA)                                                                                         
                    sinRA = sin(RA)                                                                                         
                    cosDEC = cos(DEC)                                                                                       
                    sinDEC = sin(DEC)                                                                                       
                    cosvRA = cos(vRA)                                                                                       
                    sinvRA = sin(vRA)                                                                                       
                    cosvDEC = cos(vDEC)                                                                                     
                    sinvDEC = sin(vDEC)                                                                                     
                                                                                                                            
                    x = r * cosRA * cosDEC                                                                                  
                    y = r * sinRA * cosDEC                                                                                  
                    z = r * sinDEC;                                                                                         
                    xdot = v * cosvRA * cosvDEC                                                                             
                    ydot = v * sinvRA * cosvDEC                                                                             
                    zdot = v * sinvDEC;                                                                                     
                                                                                                                            
                    #compute AZ and FPA                                                                                     
                    FPA = acos( (x*xdot + y*ydot + z*zdot) / r / v )                                                        
                                                                                                                            
                    #azimuth is complicated                                                                                 
                    xhat = numpy.matrix([cos(RA)*cos(DEC), sin(RA)*cos(DEC), sin(DEC)]).T                                   
                    yhat = numpy.matrix([cos(RA + pi / 2.0), sin(RA + pi / 2.0), 0.0]).T                                    
                    zhat = numpy.matrix([-cos(RA)*sin(DEC), -sin(RA)*sin(DEC), cos(DEC)]).T                                 
                    R = numpy.hstack([xhat, yhat, zhat]).T                                                                  
                    V = numpy.matrix([xdot, ydot, zdot]).T                                                                  
                    Vprime = R * V                                                                                          
                    AZ = atan2(Vprime[1], Vprime[2])                                                                        
                                                                                                                            
                    #write vRA and vDEC into the decision vector                                                            
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace('vRA','AZ')                                     
                    self.trialX[Xindex][1] = str(AZ)                                                                        
                    self.trialX[Xindex + 1][0] = self.trialX[Xindex + 1][0].replace('vDEC','FPA')                           
                    self.trialX[Xindex + 1][1] = str(FPA)                                                                   
        
        if len(self.trialX) > 0:
            if self.phase_type == 2 and "FBLT" in self.trialX[0][0]: #if this is an MGALT journey and the guess is from FBLT
                print("converting journey ", self.journey_name, " from FBLT to MGALT")
                for Xindex in range(0, len(self.trialX)):
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace("FBLT","MGALT")
            
            elif self.phase_type == 3 and "MGALT" in self.trialX[0][0]: #if this is an FBLT journey and the guess is from MGALT
                print("converting journey ", self.journey_name, " from MGALT to FBLT")
                for Xindex in range(0, len(self.trialX)):
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace("MGALT","FBLT")
            
            elif self.phase_type == 4 and "PSFB" in self.trialX[0][0]: #if this is a PSBI journey and the guess is from PSFB
                print("converting journey ", self.journey_name, " from PSFB to PSBI")
                for Xindex in range(0, len(self.trialX)):
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace("PSFB","PSBI")
            
            elif self.phase_type == 5 and "PSBI" in self.trialX[0][0]: #if this is an PSFB journey and the guess is from PSBI
                print("converting journey ", self.journey_name, " from PSBI to PSFB")
                for Xindex in range(0, len(self.trialX)):
                    self.trialX[Xindex][0] = self.trialX[Xindex][0].replace("PSBI","PSFB")
        
        return                                                                                                              
