Example #1
0
def two_phase_single_channel(T_wall,
                             w_channel,
                             Nu_func_gas,
                             Nu_func_liquid,
                             T_inlet,
                             T_chamber,
                             p_ref,
                             m_dot,
                             h_channel,
                             fp: FluidProperties,
                             print_info=True):
    """ Function that calculates the total power consumption of a specific chamber, in order to optimize the chamber

    Args:
        T_wall (K): Wall temperature
        w_channel (m): Channel width
        Nu_func_gas (-): Nusselt function for gas phase
        Nu_func_liquid (-) Nusselt function for liquid phase
        T_inlet (K): Chamber inlet temperature
        T_chamber (K): Chamber outlet temperature (same as T_c in IRT)
        p_ref (Pa): Reference pressure for the Nusselt relation and flow similary parameters (same as inlet pressure as no pressure drop is assumed)
        m_dot (kg/s): Mass flow
        h_channel (m): Channel height
        w_channel_margin (m): The amount of margin around the chamber for structural reasons. Important because it also radiates heat
        fp (-  ): [description]
        print_info(Bool): for debugging purposes
    """

    # Calculate saturation temperature, to determine where transition from gas to liquid occurs
    T_sat = fp.get_saturation_temperature(p=p_ref)  # [K]
    # Sanity check on input
    assert (T_chamber > T_sat)
    assert (T_wall > T_chamber)

    # Calculate the two reference temperatures for the separated phases
    T_bulk_gas = (T_sat + T_chamber) / 2  # [K] Bulk temperature gas phase
    T_bulk_liquid_multi = (
        T_inlet +
        T_sat) / 2  # [K] Bulk temperature of liquid and multi-phase flow
    # Calculate the density at these reference points
    rho_bulk_gas = fp.get_density(T=T_bulk_gas, p=p_ref)  # [kg/m^3]
    rho_bulk_liquid_multi = fp.get_density(T=T_bulk_liquid_multi,
                                           p=p_ref)  # [kg/m^3]

    # Channel geometry
    A_channel = w_channel * h_channel  # [m^2] Area through which the fluid flows
    wetted_perimeter = wetted_perimeter_rectangular(
        w_channel=w_channel, h_channel=h_channel
    )  # [m] Distance of channel cross-section in contact with fluid
    D_hydraulic = hydraulic_diameter_rectangular(
        w_channel=w_channel, h_channel=h_channel)  # [m] Hydraulic diameter

    # Flow similarity parameters (for debugging and Nu calculatoin purposes)
    Re_bulk_gas = fp.get_Reynolds_from_mass_flow(
        m_dot=m_dot, p=p_ref, T=T_bulk_gas, L_ref=D_hydraulic,
        A=A_channel)  # [-] Bulk Reynolds number in the gas phase
    Re_bulk_liquid_multi = fp.get_Reynolds_from_mass_flow(
        m_dot=m_dot,
        p=p_ref,
        T=T_bulk_liquid_multi,
        L_ref=D_hydraulic,
        A=A_channel)  # [-] Bulk Reynolds number in the liquid/multi-phase
    Pr_bulk_gas = fp.get_Prandtl(
        T=T_bulk_gas, p=p_ref)  # [-] Prandtl number in the gas phase
    Pr_bulk_liquid_multi = fp.get_Prandtl(
        T=T_bulk_liquid_multi,
        p=p_ref)  # [-] Prandtl number in liquid/multi-phase
    Bo_sat = fp.get_Bond_number(
        p_sat=p_ref, L_ref=D_hydraulic
    )  # [-] Bond number at saturation pressure (assumed to be p_ref)

    # Calculate Nusselt number in both sections
    args_gas = {
        'Re': Re_bulk_gas,  # Arguments for Nusselt function (gas phase) 
        'Pr': Pr_bulk_gas,
        'Bo': Bo_sat,
    }

    args_liquid_multi = { # Arguments for Nusselt function (liquid/multi phase)
        'Re': Re_bulk_liquid_multi,
        'Pr': Pr_bulk_liquid_multi,
        'Bo': Bo_sat,
        }

    Nu_gas = Nu_func_gas(args=args_gas)
    Nu_liquid_multi = Nu_func_liquid(args=args_liquid_multi)
    # Calculate Stanton number in both sections
    St_gas = Stanton_from_Nusselt_and_velocity(
        Nu=Nu_gas,
        T_ref=T_bulk_gas,
        p_ref=p_ref,
        L_ref=D_hydraulic,
        m_dot=m_dot,
        A=A_channel,
        fp=fp)  # [-] Stanton number in gas phase
    St_liquid_multi = Stanton_from_Nusselt_and_velocity(
        Nu_liquid_multi,
        T_ref=T_bulk_liquid_multi,
        p_ref=p_ref,
        L_ref=D_hydraulic,
        m_dot=m_dot,
        A=A_channel,
        fp=fp)  # [-] Stanton number in liquid phase
    # Calculate velocity for convection parameter (bulk temp used as reference for phase)
    u_bulk_gas = velocity_from_mass_flow(
        A=A_channel, m_dot=m_dot,
        rho=rho_bulk_gas)  # [m/s] Velocity at the gas bulk reference state
    u_bulk_liquid_multi = velocity_from_mass_flow(
        A=A_channel, m_dot=m_dot, rho=rho_bulk_liquid_multi
    )  # [m/s] Velocity at the liquid/multi-phase bulk reference state
    # Convective parameter
    h_conv_gas = h_conv_from_Stanton(
        Stanton=St_gas, u=u_bulk_gas, T_ref=T_bulk_gas, p_ref=p_ref, fp=fp
    )  # [W/(m^2*K)] Convective heat transfer coefficient at bulk gas state
    h_conv_liquid_multi = h_conv_from_Stanton(
        Stanton=St_liquid_multi,
        u=u_bulk_liquid_multi,
        T_ref=T_bulk_liquid_multi,
        p_ref=p_ref,
        fp=fp
    )  # [W/(m^2*K)] Convective heat transfer coefficient at bulk liquid/multi-phase state
    # Required specific enthalpy change for heating the separate sections
    h_outlet = fp.get_enthalpy(
        T=T_chamber, p=p_ref)  # [J/kg] Specific enthalpy at the outlet
    h_sat_gas = fp.get_saturation_enthalpy_gas(
        p=p_ref)  # [J/kg] Specific enthalpy of saturated gas
    h_inlet = fp.get_enthalpy(T=T_inlet, p=p_ref)  # [J/kg]
    # Required specific enthalpy increases
    delta_h_gas = h_outlet - h_sat_gas  # [J/kg] Enthalpy increase needed to go from saturated gas to outlet enthalpy
    delta_h_liquid_multi = h_sat_gas - h_inlet  # [J/k] Enthalpy increase needed to go from inlet enthalpy to saturated gas
    # Required power for those enthalpy changes at the given mass flow
    Q_dot_gas = required_power(m_dot=m_dot, delta_h=delta_h_gas)  # [W]
    Q_dot_liquid_multi = required_power(m_dot=m_dot,
                                        delta_h=delta_h_liquid_multi)  # [W]
    # Required heater area to achieve the required power
    A_heater_gas = required_heater_area(Q_dot=Q_dot_gas,
                                        h_conv=h_conv_gas,
                                        T_wall=T_wall,
                                        T_ref=T_bulk_gas)  # [m^2]
    A_heater_liquid_multi = required_heater_area(
        Q_dot=Q_dot_liquid_multi,
        h_conv=h_conv_liquid_multi,
        T_wall=T_wall,
        T_ref=T_bulk_liquid_multi)  # [m^2]
    # Required length to achieve desired area
    L_channel_gas = A_heater_gas / wetted_perimeter  # [m] Length of channel after gas is saturated
    L_channel_liquid_multi = A_heater_liquid_multi / wetted_perimeter  # [m] Length of channel after heater
    L_channel = L_channel_gas + L_channel_liquid_multi  # [m]
    L_hydrodynamic_entrance = D_hydraulic * Re_bulk_liquid_multi * 0.04  # [m] Hydrodynamic entrance to estimate if the flow is fully developed

    assert (h_outlet > h_sat_gas)
    assert (h_sat_gas > h_inlet)

    if (print_info):
        print("\n--- SPECIFIC ENTHALPY AT DIFFERENT STATIONS ---")
        print("h_outlet: {:4.3f} J/kg".format(h_outlet))
        print("h_sat_gas: {:4.3f} J/kg".format(h_sat_gas))
        print("h_inlet: {:4.3f} J/kg".format(h_inlet))

        print("\n --- REQUIRED POWER ---")
        print("Q_dot_gas: {:2.5f} W".format(Q_dot_gas))
        print("Q_dot_liquid_multi: {:2.5f} W".format(Q_dot_liquid_multi))

        print("\n --- BULK GAS PHASE PARAMETERS --- ")
        print("u: {:3.2f} m/s".format(u_bulk_gas))
        print("Nu: {}".format(Nu_gas))
        print("Re: {}".format(Re_bulk_gas))
        print("Pr: {}".format(Pr_bulk_gas))
        print("St: {}".format(St_gas))
        print("Bo_sat: {}".format(Bo_sat))

        print("\n --- BULK LIQUID/MULTI-PHASE PARAMETERS ---")
        print("u: {:3.4f} m/s".format(u_bulk_liquid_multi))
        print("Nu: {}".format(Nu_liquid_multi))
        print("Re: {}".format(Re_bulk_liquid_multi))
        print("Pr: {}".format(Pr_bulk_liquid_multi))
        print("St: {}".format(St_liquid_multi))

        print("\n --- CHARACTERISTIC GEOMETRIC VALUES --- ")
        print("Hydrodynamic entance length: {:3.3f} micron".format(
            L_hydrodynamic_entrance * 1e6))
        print("Hydraulic diameter: {:3.3f} micron".format(D_hydraulic * 1e6))
        print("L/D: {:4.2f} ".format(L_channel / D_hydraulic))
        print("L/X_T {:4.2f}".format(L_channel / L_hydrodynamic_entrance))

        print("\n --- RESULTING GEOMETRY ---")
        print("Total length: {:3.3f} mm".format(L_channel * 1e3))
        print("Length (liquid/multi): {:3.3f} mm".format(
            L_channel_liquid_multi * 1e3))
        print("Length (gas): {:3.4f} mm".format(L_channel_gas * 1e3))
        print("Relative length (gas) {:3.3f} \%".format(L_channel_gas /
                                                        L_channel * 100))

        ## Return a dictionary with results and interesting intermediate values
    res = {
        "L_channel": L_channel,  # [m] Total length of channel
        "D_hydraulic": D_hydraulic,  # [m] Hydraulic diameter of channel
        "Nu_liquid_multi":
        Nu_liquid_multi,  # [-] Nusselt number of liquid/multi-phase flow
        "Pr_bulk_liquid_multi":
        Pr_bulk_liquid_multi,  # [-] Prandlt number of liquid/multi-phase flow
        "Re_bulk_liquid_multi":
        Re_bulk_liquid_multi,  # [-] Reynolds number of liquid/multi-phase flow
        "St_liquid_multi":
        St_liquid_multi,  # [-] Stanton number of liquid/multi-phase flow
        "h_conv_liquid_multi":
        h_conv_liquid_multi,  # [W/(m^2*K)] Heat transfer coefficient
        "A_heater_liquid_multi":
        A_heater_liquid_multi,  # [m^2] Required heater area for liquid/multi-phase flow
        "L_channel_liquid_multi":
        L_channel_liquid_multi,  # [m] Length of channel to get required heater area
        "u_bulk_liquid_multi":
        u_bulk_liquid_multi,  # [m/s] Bulk flow velocity of liquid/multi-phase flow
        "rho_bulk_liquid_multi":
        rho_bulk_liquid_multi,  # [kg/m^3] Bulk density of liquid/multi-phase flow
        "T_bulk_liquid_multi":
        T_bulk_liquid_multi,  # [K] Bulk temperature of liquid/multi-phase flow
        "delta_h_liquid_multi":
        delta_h_liquid_multi,  # [J/kg] Enthalpy change from inlet to saturated gas
        "Q_dot_liquid_multi":
        Q_dot_liquid_multi,  # [W] Power required for enthalpy change
        ## Same thing but for gas values
        "Nu_gas": Nu_gas,  # [-]
        "Pr_bulk_gas": Pr_bulk_gas,  # [-]
        "Re_bulk_gas": Re_bulk_gas,  # [-]
        "St_gas": St_gas,  # [-]
        "h_conv_gas": h_conv_gas,  # [W/(m^2*K)]
        "A_heater_gas": A_heater_gas,  # [m^2]
        "L_channel_gas": L_channel_gas,  # [m]
        "u_bulk_gas": u_bulk_gas,  # [m/s]
        "rho_bulk_gas": rho_bulk_gas,  # [kg/m^3]
        "T_bulk_gas": T_bulk_gas,  # [K]
        "delta_h_gas": delta_h_gas,  # [J/kg]
        "Q_dot_gas": Q_dot_gas,  # [W]
    }
    return res
Example #2
0
def chamber_performance_from_Nu(Nu_func, T_inlet, T_chamber, T_ref, T_wall,
                                p_ref, m_dot, A_channel, L_ref,
                                fp: FluidProperties):
    """ Function that calculates the power consumption and heating area for a specific chamber

    Args:
        Nu_func (-): Nusselt function, that implement the emperical relation of choice
        T_inlet (K): Chamber inlet temperature
        T_chamber (K): Chamber outlet temperature (same as T_chamber for IRT)
        T_ref (K): Reference temperature for the Nusselt relation and flow similary parameters
        T_wall (K): Wall temperature
        p_ref (Pa): Chamber pressure (no pressure drop assumed)
        m_dot (kg/s): Mass flow
        A_channel (m^2): Cross-sectional area of the chamber, through which the fluid flows
        L_ref (m): Reference length for Nusselt relation and flow similarty parameters
        fp (FluidProperties): Object from which Fluid Properties are determined

    Returns:
        dictionary with heater area, power required to heat up flow and Nusselt number
    """
    ## Make sure all parameters are calculated at the same reference state (including velocity!)
    # Pr and Re parameters needed for most Nusselt relation
    rho_ref = fp.get_density(T=T_ref, p=p_ref)  # [kg/m^3] Reference density
    u_ref = velocity_from_mass_flow(
        A=A_channel, m_dot=m_dot,
        rho=rho_ref)  # [m/s] Speed at reference state
    print("u_ref {} m/s".format(u_ref))
    Re_ref = fp.get_Reynolds_from_mass_flow(
        T=T_ref, p=p_ref, L_ref=L_ref, m_dot=m_dot,
        A=A_channel)  # [-] Reynolds number at reference state
    Pr_ref = fp.get_Prandtl(T=T_ref,
                            p=p_ref)  # [-] Prandtl number at reference state
    # Now the Nusselt can be determined
    Nusselt = Nu_func(args={
        'Re': Re_ref,
        'Pr': Pr_ref
    })  # [-] Nusselt number at given state (used for plotting purposes)
    Stanton = Stanton_from_Nusselt_func_and_velocity(
        Nu_func=Nu_func,
        m_dot=m_dot,
        A=A_channel,
        T_ref=T_ref,
        p_ref=p_ref,
        L_ref=L_ref,
        fp=fp)  # [-] Stanton number at reference state
    h_conv = h_conv_from_Stanton(Stanton=Stanton,
                                 u=u_ref,
                                 T_ref=T_ref,
                                 p_ref=p_ref,
                                 fp=fp)
    # Now determine how much energy must be convected
    delta_h = ideal_enthalpy_change(T_inlet=T_inlet,
                                    p_inlet=p_ref,
                                    T_outlet=T_chamber,
                                    p_outlet=p_ref,
                                    fp=fp)  # [J/kg]
    Q_dot = required_power(
        m_dot=m_dot, delta_h=delta_h)  # [W] Required power to achieve delta_h
    A_heater = required_heater_area(Q_dot=Q_dot,
                                    h_conv=h_conv,
                                    T_wall=T_wall,
                                    T_ref=T_ref)  # [m^2]
    assert (A_heater > 0)
    # Return a dictionary with interesting values
    return {
        'A_heater': A_heater,
        'Q_dot': Q_dot,
        'Nusselt': Nusselt,
        'Re_ref': Re_ref,
        'Pr_ref': Pr_ref
    }
Example #3
0
p_outlet = p_inlet  # [Pa] Outlet pressure (assumed roughly equal to inlet)
T_inlet = td['T_inlet']  # [K]

# Geometry calculations
D_h = hydraulic_diameter_rectangular(
    w_channel=w_channel, h_channel=h_channel)  # [m] Hydraulic diameter
A_channel = w_channel * h_channel
# Inlet conditions
rho_inlet = fp.get_density(T=T_inlet, p=p_inlet)  # [kg/m^3]
u_inlet = velocity_from_mass_flow(A=A_channel, m_dot=m_dot, rho=rho_inlet)
# Outlet conditions
rho_outlet = fp.get_density(T=T_outlet, p=p_outlet)
u_outlet = velocity_from_mass_flow(A=A_channel, m_dot=m_dot, rho=rho_outlet)
Re_outlet = fp.get_Reynolds_from_mass_flow(T=T_outlet,
                                           p=p_outlet,
                                           L_ref=D_h,
                                           m_dot=m_dot,
                                           A=A_channel)

print("\n\nTHRUSTER NAME: {}".format(td['name']))
print("\n --- GEOMETRY ---")
print("Channel length: {:4.3f} mm".format(L_channel * 1e3))
print("Hydraulic diameter: {:4.3f} um".format(D_h * 1e6))
print("L/D: {:3.2f} ".format(L_channel / D_h))

print("\n --- INLET FLOW CONDITIONS --- ")
print("Density: {:3.2f} kg/m^3".format(rho_inlet))

print("\n --- OUTLET FLOW CONDITIONS ---")
print("Mass flow: {:1.3f} mg/s".format(m_dot * 1e6))
print("Density: {:1.3f} kg/m^3".format(rho_outlet))
Example #4
0
T_liquid = 300  # [K]
T_gas = 500  # [K]
m_dot = 1e-6  # [kg/s] For Kandlikar relation.
#h_c = 100e-6 # [m] Channel depth/height

# Density is needed to reverse calculate the reference length for Re, so it can be applied in other flow similarity parameters
rho_liquid = fp.get_density(T=T_liquid, p=p)
mu_liquid = fp.get_viscosity(T=T_liquid, p=p)

# Range of Reynolds numbers to consider
Reynolds = np.logspace(start=0, stop=2.8)
D_hydraulic = np.logspace(start=-4.93, stop=-2.93)
A_channel = D_hydraulic**2
Reynolds_2 = fp.get_Reynolds_from_mass_flow(T=T_liquid,
                                            p=p,
                                            L_ref=D_hydraulic,
                                            m_dot=m_dot,
                                            A=A_channel)
# Range of hydraulic diameter that fit this Reynolds number
#w_channel = 2*m_dot/( Reynolds_100 * mu_liquid ) - h_c # [m]
#A_channel = h_c * w_channel # [m^2]
#D_hydraulic = basic.chamber.hydraulic_diameter_rectangular(w_channel=w_channel,h_channel=h_c) # [m]

#Reynolds_check = fp.get_Reynolds_from_mass_flow(T=T_liquid, p=p, L_ref=D_hydraulic, m_dot=m_dot, A=A_channel) # [-]
Bond = fp.get_Bond_number(p_sat=p, L_ref=D_hydraulic)  # [m]
# Prandtl number in both reference states
Pr_liquid = fp.get_Prandtl(T=T_liquid, p=p)  # [-]
Pr_gas = fp.get_Prandtl(T=T_gas, p=p)  # [-]
# Conductivity in reference state
conductivity_liquid = fp.get_thermal_conductivity(T=T_liquid, p=p)
Example #5
0
it_T = np.nditer(T_wall,
                 flags=['c_index'])  # [K] To iterate over all T_chamber values

for T in it_T:
    ## Make sure all parameters are calculated at the same reference state (including velocity)
    # Calculate all the bulk conditions required to determine the Nusselt number relation
    T_bulk = (T_inlet + T_chamber) / 2  # [K] Bulk temperature as reference
    rho_bulk = fp.get_density(
        T=T_bulk, p=p_inlet
    )  # [kg/m^3] Bulk density is required to get the correct velocity at the reference temperature
    u_bulk[it_T.index, :] = velocity_from_mass_flow(
        m_dot=m_dot, rho=rho_bulk,
        A=A_channel)  # [m/s] The velocity at the bulk reference state
    Re_bulk[it_T.index, :] = fp.get_Reynolds_from_mass_flow(T=T_bulk,
                                                            p=p_inlet,
                                                            L_ref=Dh_channel,
                                                            m_dot=m_dot,
                                                            A=A_channel)  # [-]
    Pr_bulk[it_T.index, :] = fp.get_Prandtl(T=T_bulk, p=p_inlet)  # [-]
    # Now the convection parameters can be determined, taking care that the reference temperature and flow conditions are evaluated in the same location
    Nusselt[it_T.index, :] = Nu_func(args={
        'Re': Re_bulk[it_T.index, :],
        'Pr': Pr_bulk[it_T.index, :]
    })  # [-] Not necessary, but useful for plots
    Stanton[it_T.index, :] = Stanton_from_Nusselt_func_and_velocity(
        Nu_func=Nu_func,
        m_dot=m_dot,
        A=A_channel,
        T_ref=T_bulk,
        p_ref=p_inlet,
        L_ref=Dh_channel,
Example #6
0
def optim_P_total(channel_amount, w_channel, h_channel, inlet_manifold_length_factor, inlet_manifold_width_factor, l_exit_manifold, w_channel_spacing, w_outer_margin, T_wall, p_ref, m_dot, \
    prepared_values, Nusselt_relations, pressure_drop_relations, convergent_half_angle, divergent_half_angle, F_desired, p_back, AR_exit, w_throat, emissivity_top, fp: FluidProperties, wall_args=None):
    # First calculate area ratio at entrance so it can be provided to contraction pressure drop function
    w_inlet_manifold = chamber.inlet_manifold_width(\
            channel_amount=channel_amount,
            w_channel=w_channel,
            w_channel_spacing=w_channel_spacing,
            inlet_manifold_width_factor=inlet_manifold_width_factor) # [m] Total width of inlet manifold
    area_ratio_contraction = chamber.area_ratio_contraction(\
        w_inlet_manifold=w_inlet_manifold,
        w_channel=w_channel,
        channel_amount=channel_amount) # [-] Area ratio of sudden contraction

    def x(T):
        wall_args[
            'T_wall_bottom'] = T  # [K] Add the bottom wall temperature in the wall argument dictionary
        # Calculate heat transfer to determine channel length
        res = oneD.rectangular_multi_channel_homogenous_calculation(\
            channel_amount=channel_amount,
            prepared_values=prepared_values,
            Nusselt_relations=Nusselt_relations,
            pressure_drop_relations=pressure_drop_relations,
            w_channel=w_channel,
            h_channel=h_channel,
            m_dot=m_dot,
            T_wall=T_wall,
            p_inlet=p_ref,
            fp=fp,
            area_ratio_contraction=area_ratio_contraction,
            wall_args=wall_args)

        #print(res['Q_total_bottom_plane_heat_balance'])
        return res['Q_total_bottom_plane_heat_balance']

    ## ROOT FINDING PROBLEM FOR T_WALL_BOTTOM
    # The proper bounds for the optimization are very sensitive to wall temperature and chamber temperature
    # It is hard to pick bounds that are valid for a wide range of those parameters
    # The problem is that that a too low lower bound results in model results that are wholly invalid and break the optimization
    # Too high a lower bound results in the solution not being within the bounds at all.
    # The quick and dirty solution here is to stepwise move the bounds down until the valid solution is between it.
    # The stepsize must be small enough to reliably avoid the scenario where the calculations are completely incorrect.
    delta_T_bounds = 25  # [K] The size of the bound shift could determine how low the bounds can go to the final chamber temperature without resulting into incorrection calculations

    ## The resultant channel length, pressure drops, etc, depends on bottom wall temperature. It must be iterated towards here.
    T_wall_bottom_min = T_wall - delta_T_bounds  # [K] Minimum temperature is in practice probably not lower than chamber temperature (not impossible, though)
    T_wall_bottom_max = T_wall
    bounds_are_correct = False  # [bool] Is False until a solution has been found
    # The bounds are correct once they get the opposite sign
    while not bounds_are_correct:
        a = x(T_wall_bottom_max)
        b = x(T_wall_bottom_min)
        # If the solutions have the same sign, subtract delta_T_bounds
        if np.sign(a) == np.sign(b):
            T_wall_bottom_min -= delta_T_bounds
            T_wall_bottom_max -= delta_T_bounds
        else:
            bounds_are_correct = True

    root_result = root_scalar(x,
                              bracket=([T_wall_bottom_min, T_wall_bottom_max]))

    if root_result.converged:
        T_wall_bottom = root_result.root  # [m^2]
        wall_args['T_wall_bottom'] = T_wall_bottom
        #print(" T_wall_bottom: {:3.2f} K".format(T_wall_bottom))
    else:
        raise Exception("No solution found for given temperature")

    res = oneD.rectangular_multi_channel_homogenous_calculation(\
            channel_amount=channel_amount,
            prepared_values=prepared_values,
            Nusselt_relations=Nusselt_relations,
            pressure_drop_relations=pressure_drop_relations,
            w_channel=w_channel,
            h_channel=h_channel,
            m_dot=m_dot,
            T_wall=T_wall,
            p_inlet=p_ref,
            fp=fp,
            area_ratio_contraction=area_ratio_contraction,
            wall_args=wall_args)

    # Check if these solutions are eventually valid
    assert (np.all(res['res_l']['delta_L'] >= 0))
    assert (np.all(res['res_tp']['delta_L'] >= 0))
    assert (np.all(res['res_g']['delta_L'] >= 0))

    l_channel = res['L_total']  # [m] Channel length
    p_chamber = res[
        'p_chamber']  # [Pa] Pressure out channel outlet/inlet of nozzle according to IRT
    T_chamber = res['T_chamber']

    # Nozzle performance must be recalculated, if pressure drop occured
    assert (pressure_drop_relations
            is not None)  # Just check is one was calculated

    if p_chamber <= 0:  # If pressure drop was so large p_chamber was negative, the solution is invalid, and NaNs must be returned
        # Return the same dictionary, but all NaN.
        return {
            'P_loss': np.nan,  # [W] Current approximation of heat loss
            'l_channel': np.nan,  # [m] Channel length
            'pressure_drop': np.nan,  # [Pa] Total pressure drop
            'dP_contraction': np.nan,  # [Pa] Pressure drop de to contraction
            'w_total': np.nan,  # [m] Total chip width
            'l_total': np.nan,  # [m] Total chip length
            'is_channel_choked': np.nan,
            'Re_channel_exit': np.nan,  # [-] Reynolds number at channel exit
        }
    # This only runs if pressure drop was not too large.
    # In that case the throat area must be recalculated still
    else:

        ep = engine_performance_from_F_and_T(F_desired=F_desired,
                                             p_chamber=p_chamber,
                                             T_chamber=T_chamber,
                                             AR_exit=AR_exit,
                                             p_back=p_back,
                                             fp=fp)

        # New throat widtl_inlet_manifoldmined from desired performance parameter
        w_throat_new = ep['A_throat'] / h_channel  # [m]
        # Check if new pressure, does not cause choked heating channels
        is_channel_choked = (
            w_channel * h_channel * channel_amount < ep['A_throat']
        )  # [bool] If combined channel area is smaller than throat, they are choked.
        # Check new Reynolds number at channel exit for laminar/turbulent flow assumptions
        hydraulic_diameter = chamber.hydraulic_diameter_rectangular(
            w_channel=w_channel, h_channel=h_channel)
        Re_channel_exit = fp.get_Reynolds_from_mass_flow(
            T=T_chamber,
            p=p_chamber,
            L_ref=hydraulic_diameter,
            m_dot=m_dot,
            A=h_channel * w_channel)

        l_outlet = chamber.outlet_length(\
            w_channel=w_channel,
            w_channel_spacing=w_channel_spacing,
            channel_amount=channel_amount,
            convergent_half_angle=convergent_half_angle,
            w_throat=w_throat_new,
            divergent_half_angle=divergent_half_angle,
            AR_exit=AR_exit,
            l_exit_manifold=l_exit_manifold
            )

        l_inlet_manifold = chamber.inlet_manifold_length(
            w_inlet_manifold=w_inlet_manifold,
            inlet_manifold_length_factor=inlet_manifold_length_factor)
        l_total = chamber.total_chip_length(l_inlet_manifold=l_inlet_manifold,
                                            l_channel=l_channel,
                                            l_outlet=l_outlet)
        w_total = chamber.total_chip_width(\
            w_inlet_manifold=w_inlet_manifold,
            w_outer_margin=w_outer_margin,
            w_throat=w_throat_new,
            AR_exit=AR_exit)

        A_chip = l_total * w_total  # [m^2]

        P_rad_loss_top = chamber.radiation_loss(
            T=T_wall, A=A_chip, emmisivity=emissivity_top
        )  # [W]  Radiation loss through top of chip
        P_rad_loss_bottom = chamber.radiation_loss(
            T=wall_args['T_wall_bottom'],
            A=A_chip,
            emmisivity=wall_args['emissivity_chip_bottom']
        )  # Radiation loss through bottom of chip
        P_loss = P_rad_loss_top + P_rad_loss_bottom  # [W] Total heat loss
        return {
            'P_loss': P_loss,  # [W] Current approximation of heat loss
            'l_channel': l_channel,  # [m] Channel length
            'pressure_drop': res['dP_total'],  # [Pa] Total pressure drop
            'dP_contraction':
            res['dP_contraction'],  # [Pa] Pressure drop due to contraction
            'w_total': w_total,  # [m] Total chip width
            'l_total': l_total,  # [m] Total chip length
            'is_channel_choked':
            is_channel_choked,  # [bool] 0 and 1 in this case, to check if channels are not too small
            'Re_channel_exit':
            Re_channel_exit,  # [-] Check Reynolds number to see if laminar flow assumptions still hold 
        }