r'''Wrapper for the various effectiveness-NTU method function calls,
    which can solve a heat exchanger. The heat capacities and mass flows
    of each stream and the type of the heat exchanger are always required.
    As additional inputs, one combination of the following inputs is required:
        
    * Three of the four inlet and outlet stream temperatures.
    * Temperatures for the cold outlet and hot inlet and UA
    * Temperatures for the cold outlet and hot outlet and UA
    * Temperatures for the cold inlet and hot inlet and UA
    * Temperatures for the cold inlet and hot outlet and UA
      
    Parameters
    ----------
    mh : float
        Mass flow rate of hot stream, [kg/s]
    mc : float
        Mass flow rate of cold stream, [kg/s]
    Cph : float
        Averaged heat capacity of hot stream, [J/kg/K]
    Cpc : float
        Averaged heat capacity of cold stream, [J/kg/K]
    subtype : str, optional
        The subtype of exchanger; one of 'counterflow', 'parallel', 'crossflow'
        'crossflow, mixed Cmin', 'crossflow, mixed Cmax', 'boiler', 'condenser',
        'S&T', or 'nS&T' where n is the number of shell and tube exchangers in 
        a row
    Thi : float, optional
        Inlet temperature of hot fluid, [K]
    Tho : float, optional
        Outlet temperature of hot fluid, [K]
    Tci : float, optional
        Inlet temperature of cold fluid, [K]
    Tco : float, optional
        Outlet temperature of cold fluid, [K]
    UA : float, optional
        Combined Area-heat transfer coefficient term, [W/K]

    Returns
    -------
    results : dict
        * Q : Heat exchanged in the heat exchanger, [W]
        * UA : Combined area-heat transfer coefficient term, [W/K]
        * Cr : The heat capacity rate ratio, of the smaller fluid to the larger
          fluid, [W/K]
        * Cmin : The heat capacity rate of the smaller fluid, [W/K]
        * Cmax : The heat capacity rate of the larger fluid, [W/K]
        * effectiveness : The thermal effectiveness of the heat exchanger, [-]
        * NTU : Thermal Number of Transfer Units [-]
        * Thi : Inlet temperature of hot fluid, [K]
        * Tho : Outlet temperature of hot fluid, [K]
        * Tci : Inlet temperature of cold fluid, [K]
        * Tco : Outlet temperature of cold fluid, [K]
    
    See also
    --------
    effectiveness_from_NTU
    NTU_from_effectiveness

    Examples
    --------
    Solve a heat exchanger to determine UA and effectiveness given the
    configuration, flows, subtype, the cold inlet/outlet temperatures, and the
    hot stream inlet temperature.
    
    >>> pprint(effectiveness_NTU_method(mh=5.2, mc=1.45, Cph=1860., Cpc=1900, 
    ... subtype='crossflow, mixed Cmax', Tci=15, Tco=85, Thi=130))
    {'Cmax': 9672.0,
     'Cmin': 2755.0,
     'Cr': 0.2848428453267163,
     'NTU': 1.1040839095588,
     'Q': 192850.0,
     'Tci': 15,
     'Tco': 85,
     'Thi': 130,
     'Tho': 110.06100082712986,
     'UA': 3041.751170834494,
     'effectiveness': 0.6086956521739131}
    
    Solve the same heat exchanger with the UA specified, and known inlet
    temperatures:
        
    >>> pprint(effectiveness_NTU_method(mh=5.2, mc=1.45, Cph=1860., Cpc=1900, 
    ... subtype='crossflow, mixed Cmax', Tci=15, Thi=130, UA=3041.75))
    {'Cmax': 9672.0,
     'Cmin': 2755.0,
     'Cr': 0.2848428453267163,
     'NTU': 1.1040834845735028,
     'Q': 192849.96310220254,
     'Tci': 15,
     'Tco': 84.99998660697007,
     'Thi': 130,
     'Tho': 110.06100464203861,
     'UA': 3041.75,
     'effectiveness': 0.6086955357127832}

def effectiveness_NTU_method(mh, mc, Cph, Cpc, subtype='counterflow', Thi=None, 
                             Tho=None, Tci=None, Tco=None, UA=None):
    r'''Wrapper for the various effectiveness-NTU method function calls,
    which can solve a heat exchanger. The heat capacities and mass flows
    of each stream and the type of the heat exchanger are always required.
    As additional inputs, one combination of the following inputs is required:
        
    * Three of the four inlet and outlet stream temperatures.
    * Temperatures for the cold outlet and hot inlet and UA
    * Temperatures for the cold outlet and hot outlet and UA
    * Temperatures for the cold inlet and hot inlet and UA
    * Temperatures for the cold inlet and hot outlet and UA
      
    Parameters
    ----------
    mh : float
        Mass flow rate of hot stream, [kg/s]
    mc : float
        Mass flow rate of cold stream, [kg/s]
    Cph : float
        Averaged heat capacity of hot stream, [J/kg/K]
    Cpc : float
        Averaged heat capacity of cold stream, [J/kg/K]
    subtype : str, optional
        The subtype of exchanger; one of 'counterflow', 'parallel', 'crossflow'
        'crossflow, mixed Cmin', 'crossflow, mixed Cmax', 'boiler', 'condenser',
        'S&T', or 'nS&T' where n is the number of shell and tube exchangers in 
        a row
    Thi : float, optional
        Inlet temperature of hot fluid, [K]
    Tho : float, optional
        Outlet temperature of hot fluid, [K]
    Tci : float, optional
        Inlet temperature of cold fluid, [K]
    Tco : float, optional
        Outlet temperature of cold fluid, [K]
    UA : float, optional
        Combined Area-heat transfer coefficient term, [W/K]

    Returns
    -------
    results : dict
        * Q : Heat exchanged in the heat exchanger, [W]
        * UA : Combined area-heat transfer coefficient term, [W/K]
        * Cr : The heat capacity rate ratio, of the smaller fluid to the larger
          fluid, [W/K]
        * Cmin : The heat capacity rate of the smaller fluid, [W/K]
        * Cmax : The heat capacity rate of the larger fluid, [W/K]
        * effectiveness : The thermal effectiveness of the heat exchanger, [-]
        * NTU : Thermal Number of Transfer Units [-]
        * Thi : Inlet temperature of hot fluid, [K]
        * Tho : Outlet temperature of hot fluid, [K]
        * Tci : Inlet temperature of cold fluid, [K]
        * Tco : Outlet temperature of cold fluid, [K]
    
    See also
    --------
    effectiveness_from_NTU
    NTU_from_effectiveness

    Examples
    --------
    Solve a heat exchanger to determine UA and effectiveness given the
    configuration, flows, subtype, the cold inlet/outlet temperatures, and the
    hot stream inlet temperature.
    
    >>> pprint(effectiveness_NTU_method(mh=5.2, mc=1.45, Cph=1860., Cpc=1900, 
    ... subtype='crossflow, mixed Cmax', Tci=15, Tco=85, Thi=130))
    {'Cmax': 9672.0,
     'Cmin': 2755.0,
     'Cr': 0.2848428453267163,
     'NTU': 1.1040839095588,
     'Q': 192850.0,
     'Tci': 15,
     'Tco': 85,
     'Thi': 130,
     'Tho': 110.06100082712986,
     'UA': 3041.751170834494,
     'effectiveness': 0.6086956521739131}
    
    Solve the same heat exchanger with the UA specified, and known inlet
    temperatures:
        
    >>> pprint(effectiveness_NTU_method(mh=5.2, mc=1.45, Cph=1860., Cpc=1900, 
    ... subtype='crossflow, mixed Cmax', Tci=15, Thi=130, UA=3041.75))
    {'Cmax': 9672.0,
     'Cmin': 2755.0,
     'Cr': 0.2848428453267163,
     'NTU': 1.1040834845735028,
     'Q': 192849.96310220254,
     'Tci': 15,
     'Tco': 84.99998660697007,
     'Thi': 130,
     'Tho': 110.06100464203861,
     'UA': 3041.75,
     'effectiveness': 0.6086955357127832}
    '''
    Cmin = calc_Cmin(mh=mh, mc=mc, Cph=Cph, Cpc=Cpc)
    Cmax = calc_Cmax(mh=mh, mc=mc, Cph=Cph, Cpc=Cpc)
    Cr = calc_Cr(mh=mh, mc=mc, Cph=Cph, Cpc=Cpc)
    Cc = mc*Cpc
    Ch = mh*Cph
    if UA is not None:
        NTU = NTU_from_UA(UA=UA, Cmin=Cmin)
        effectiveness = eff = effectiveness_from_NTU(NTU=NTU, Cr=Cr, subtype=subtype)
        
        possible_inputs = [(Tci, Thi), (Tci, Tho), (Tco, Thi), (Tco, Tho)]
        if not any([i for i in possible_inputs if None not in i]):
            raise Exception('One set of (Tci, Thi), (Tci, Tho), (Tco, Thi), or (Tco, Tho) are required along with UA.')
        
        if Thi and Tci:
            Q = eff*Cmin*(Thi - Tci)
        elif Tho and Tco :
            Q = eff*Cmin*Cc*Ch*(Tco - Tho)/(eff*Cmin*(Cc+Ch) - Ch*Cc)
        elif Thi and Tco:
            Q = Cmin*Cc*eff*(Tco-Thi)/(eff*Cmin - Cc)
        elif Tho and Tci:
            Q = Cmin*Ch*eff*(Tci-Tho)/(eff*Cmin - Ch)
        # The following is not used as it was decided to require complete temperature information
#        elif Tci and Tco:
#            Q = Cc*(Tco - Tci)
#        elif Tho and Thi:
#            Q = Ch*(Thi-Tho)
        # Compute the remaining temperatures with the fewest lines of code
        if Tci and not Tco:
            Tco = Tci + Q/(Cc)
        else:
            Tci = Tco - Q/(Cc)
        if Thi and not Tho:
            Tho = Thi - Q/(Ch)
        else:
            Thi = Tho + Q/(Ch)        
    
    elif UA is None:
        # Case where we're solving for UA
        # Three temperatures are required
        # Ensures all four temperatures are set and Q is calculated
        if Thi is not None and Tho is not None:
            Q = mh*Cph*(Thi-Tho)
            if Tci is not None and Tco is None:
                Tco = Tci + Q/(mc*Cpc)
            elif Tco is not None and Tci is None:
                Tci = Tco - Q/(mc*Cpc)
            elif Tco is not None and Tci is not None:
                Q2 = mc*Cpc*(Tco-Tci)
                if abs((Q-Q2)/Q) > 0.01:
                    raise Exception('The specified heat capacities, mass flows, and temperatures are inconsistent')
            else:
                raise Exception('At least one temperature is required to be specified on the cold side.')
                
        elif Tci is not None and Tco is not None:
            Q = mc*Cpc*(Tco-Tci)
            if Thi is not None and Tho is None:
                Tho = Thi - Q/(mh*Cph)
            elif Tho is not None and Thi is None:
                Thi = Tho + Q/(mh*Cph)
            else:
                raise Exception('At least one temperature is required to be specified on the cold side.')
        else:
            raise Exception('Three temperatures are required to be specified '
                            'when solving for UA')

        effectiveness = Q/Cmin/(Thi-Tci)
        NTU = NTU_from_effectiveness(effectiveness, Cr, subtype=subtype)
        UA = UA_from_NTU(NTU, Cmin)    
    return {'Q': Q, 'UA': UA, 'Cr':Cr, 'Cmin': Cmin, 'Cmax':Cmax, 
            'effectiveness': effectiveness, 'NTU': NTU, 'Thi': Thi, 'Tho': Tho,
            'Tci': Tci, 'Tco': Tco}