 % Delivered to the U.S. Government in Accordance with Contract FA8650-10-C-7080.
 %
 % EXPORT CONTROLLED
 % ECCN#   EAR99  
 % Warning:  This document contains technical data which is controlled under the
 % Bureau of Industry & Security’s Export Administration Regulations and may not be
 % exported or re-exported without authorization by the Bureau of Industry & Security.
 % Diversion contrary to US law is prohibited.
 %
 % (c) 2011 United Technologies Corp.
 % Developed with the sponsorship of the Defense Advanced Research Projects Agency (DARPA).
 %
 % Permission is hereby granted, free of charge, to any person obtaining a copy of this data,
 % including any software or models in source or binary form, as well as any drawings, 
 % specifications, and documentation (collectively "the Data"), to deal in the Data without 
 % restriction, including without limitation the rights to use, copy, modify, merge, publish,
 % distribute, sublicense, and/or sell copies of the Data, and to permit persons to whom the Data
 % is furnished to do so, subject to the following conditions:
 %  
 % The above copyright notice and this permission notice shall be included in all copies or
 % substantial portions of the Data.
 %  
 % THE DATA IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 % BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 % NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS, SPONSORS, DEVELOPERS, CONTRIBUTORS, OR
 % COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 % OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE DATA OR THE
 % USE OR OTHER DEALINGS IN THE DATA.

platform engine_logic_view_level_0 { 


	% note: level 0 here termed as the first level that allows enumeration of architectures, which 
	% may be called level 1 in some places.
	% All efficiency ranges, pressure ratio ranges and temperature limits are based roughly on values found in the 
	% In the Gasturb11 engine performance program by Dr. Jaochim Kurze/MTU.	
	% The input variation (assumptions) ideally must be calulated from historical data.


	library engine_logic_view_level_0_library {


		component PropellerSubsystem {

   			input var P_in: real: Pascal;
   			input var T_in: integer: Kelvin;
			input var M_in: real;`
			input var m_core: real:kg/s;
			input var MAX_Area_Req:real: m^2;
			input var Power_propulsor: real: Watt;
			
   			output var P_out: real: Pascal;
   			output var T_out: integer: Kelvin;
			output var BPR: real;
			output var A:real:m^2;
			output var Thrust_propeller: real: N;
			output var M_out: real;

						
			var U_flight: real: m/s = M_in*sqrt(gam_cold*R*T_in);
			var U_prop: real:m/s ;
			var ductedToCore: boolean;
     			var PressureRatio: real;    
   			var Propeller_efficiency: real; 
			var Transfer_efficiency: real;		
			var density: real: kg/m^3= P_in/(R*T_in);
			var T_propeller: real: N;
			var cost: real: USD;
		
			parameter cp_cold: real: J/kg/K=1005;		% Specific Heat at Constant Pressure of air in cold section (changes moderately with temperature)
			parameter gam_cold: real: J/kg/K=1.4;		% Ratio of Specific Heats of air in cold section (changes moderately with temperature)	
			parameter R: real: J/kg/K=287;			% Gas Constant
		
		   view logic {
  		        assumption {
				  if (P_in >=20000 && P_in<=50000) then {
				     M_in<=0.7;	
 			             M_in>=0.5
				  }
			          else (if P_in <103000) then {
				     M_in<= 0;			
			             M_in>=0.5;
				  }
				  T_in>=200;
				  T_in<=325;
				  
				}

					
  		        guarantee {
				  PressureRatio>=1.05;
				  PressureRatio<=1.3;


				  Propeller_efficiency>=0.6;
				  Propeller_efficiency<=0.9;

				  P_out = P_in;
				  T_out = T_in;

				  M_out = 0.5*(U_flight+U_prop)/(sqrt(gam1*R*Tac));	
				  U_prop= sqrt(2*P_in*(1+(gam_cold-1)/2*M_in^2)^(gam_cold/(gam_cold-1))*(PressureRatio-1)/(P_in/(R*T_in))+U_flight^2);
				  

				 if (ductedToCore) then
				{
				  	
					A = m_core*(1+BPR)/((Pac/(R*Tac))*0.5*(U_flight+U_prop));
			      	  	Power_Propulsor = 0.5*m_core*(1+BPR)*(U_prop^2-M_in^2*(gam_cold*R*T_in))/(Transfer_Efficiency*Propeller_Efficiency);				 
				  	Thto = m_core*(1+BPR)*(U_prop-U_flight);
				
				}

				 else

				{
				  	
					A = m_core*(BPR)/((Pac/(R*Tac))*0.5*(U_flight+U_prop));
			      	  	Power_Propulsor = 0.5*m_core*(BPR)*(U_prop^2-M_in^2*(gam_cold*R*T_in))/(Transfer_Efficiency*Propeller_Efficiency);				 
				  	Thto = m_core*(BPR)*(U_prop-U_flight);

				
				}


				  
				  A<=MAX_Area_req;

                                  if (!isParallel) then
					{		

						Transfer_efficiency<=1;
						Transfer_efficiency>=0.9;
	

					}
					else % parallel structure in propeller
					{

						Transfer_efficiency<=0.95;
						Transfer_efficiency>=0.7;

					}
                       }
		  }
		}

		component DiffuserSubsystem {
			input var P_in: real: Pascal;
			input var T_in: integer; Kelvin;
		        input var M_in: real;


 			output var T_out: integer: Kelvin;
 			output var P_out: integer: Kelvin;

			var PressureRatio: real;
			var cost: real: USD;


			parameter cp_cold: real: J/kg/K=1005;		% Specific Heat at Constant Pressure of air in cold section (changes moderately with temperature)
			parameter gam_cold: real: J/kg/K=1.4;		% Ratio of Specific Heats of air in cold section (changes moderately with temperature)		

			view logic {
				assumption {
				  if (P_in >=20000 && P_in<=50000) then {
				    M_in<=0.9;				
			            M_out>=0.5;
				  } else 
				  if (P_in <103000) then { 
				    M_in<= 0;			
			            M_out>=0.5;
				  }
					
				  T_in>=200;
				  T_in<=325;
				}
				guarantee {
				  
				  PressureRatio>=0.9;			
				  PressureRatio<=1.0;
				  P_out = P_in*PressureRatio*(1+(gam_cold-1)/2*M_in^2)^(gam_cold/(gam_cold-1));
				  
				  T_out = T_in*(1+(gam_cold-1)/2*M_in^2);						
					       
			        }
			}
		}

		component FanSubsystem {	
			input var P_in: real: Pascal;
			input var T_in: integer; Kelvin;
			input var Power_propulsor: real:Watt; 			

			var PressureRatio: real;
			var BPR: real;
			var m_core: real;
			var Transfer_efficiency: real;			
			var IsentropicEfficiency: real;
			var isParallel: boolean ;
			var ductedToCore: boolean;
			var cost: real: USD;

			output var T_out: integer: Kelvin;
 			output var P_out: integer: Pascal;
			
			parameter cp_cold: real: J/kg/K=1005;		% Specific Heat at Constant Pressure of air in cold section (changes moderately with temperature)
			parameter gam_cold: real: J/kg/K=1.4;		% Ratio of Specific Heats of air in cold section (changes moderately with temperature)	
	
				

			view logic {
				assumption {
				  T_in>=210;
				  T_in<=342;
				  P_in>=21352;
				  P_in<=122180;
				}

				guarantee {
				  
				  PressureRatio >=1.1;
				  PressureRatio <=2;
				  IsentropicEfficiency >= 0.75;
                                  IsentropicEfficiency <= 1.00;

				  P_out = PressureRatio*P_in;
				  T_out = (T_in*PressureRatio^((gam_cold-1)/gam_cold))-T_in)/IsentropicEfficiency+T_in;
				  BPR = Power_propulsor/Transfer_efficiency/(cp_cold*(T_out-T_in))/m_core-1;

							  
				  if (ductedToCore) then
					
				   {

					BPR = Power_propulsor/Transfer_efficiency/(cp_cold*(T_out-T_in))/m_core-1;
				   
				   }
				  
				 else
				   
				   {

					BPR = Power_propulsor/Transfer_efficiency/(cp_cold*(T_out-T_in))/m_core;

				   {
				 end
					
				  





                                  if (!isParallel) then % single fan structure
					{	

						Transfer_efficiency >=0.9;
						Power_transfer_efficiency <=1.0;
						 

					}
					else % parallel structures in fan
					{
						Transfer_efficiency>=0.7;
						Transfer_efficiency<=0.97; 
					
					}
			        }
			}
		}

		component CoreSubsystem { 
			input var P_in: real: Pascal;
			input var T_in: integer; Kelvin;
			input var fuel: real: kg/s;

 			var T_out_compressor: integer: Kelvin;
 			var P_out_compressor: integer: Kelvin;
			var Power_compressor: real;			
			var m_core: real: kg/s;
			var embedded:boolean;
			var lo: boolean;
			var M_in;
			var altitude;
			var cost: real: USD;
			var TSFC: 1/hr;

			var PressureRatio_combustor: real;
 			var T_out_combustor: real: Kelvin;
 			var P_out_combustor: real: Kelvin;		
			var IsentropicEfficiency_turbine: real;
			var PressureRatio_turbine: real;						
			var BPR: real;
			var engine_type: {turbojet, turbofan, turboprop};

			parameter T_max: real:Kelvin=1700;
			parameter cp_cold: real: J/kg/K=1005;		% Specific Heat at Constant Pressure of air in cold section (changes moderately with temperature)
			parameter gam_cold: real: J/kg/K=1.4;		% Ratio of Specific Heats of air in cold section (changes moderately with temperature)
			parameter cp_hot: real: J/kg/K=1244;		% Specific Heat at Constant Pressure of air in hot section (changes moderately with temperature)
			parameter gam_hot: real: K/kg/K=1.3;		% Ratio of Specific Heats of air in hot section (changes moderately with temperature)
			parameter c_fuel: real: J/kg=4.3*10^7;		% Heat of combustion of fuel	

 			
			output var PressureRatio_compressor:real;
			output var IsentropicEfficiency_compressor:real;
			output var T_out: integer: Kelvin;
 			output var P_out: integer: Kelvin;
			output var Power_propulsor;	


			view logic {
				assumption {
				   T_in>=210;
				   T_in<=442;
				   P_in>=23487;
				   P_in<=244360;
				   fuel/m_core <=(T_max-(T_in*PressureRatio_compressor^((gam_cold-1)/gam_cold))-T_in)/IsentropicEfficiency_compressor+T_in)*cp_hot/c_fuel;	
				}
				guarantee {
 
			           if (PressureRatio_compressor>=5 && PressureRatio_compressor<=15) then 
				   {
				  	IsentropicEfficiency_compressor>=0.5 and IsentropicEfficiency_compressor< 1.0;   				% For low pressure ratios it is possible to have a lower efficiency centrifugal compressors 
                                   }
			          else if (PressureRatio>=15 && PressureRatio<=30)
				   {
			          	IsentropicEfficiency_compressor>=0.75 and IsentropicEfficiency_compressor<1.0;     				
			           }

				   PressureRatio_combustor>=0.9;		
			 	   PressureRatio_combustor<1.0;


				   IsentropicEfficiency_turbine>=0.75 and IsentropicEfficiency_turbine<=1;
				   PressureRatio_turbine>=2;									
				   PressureRatio_Turbine<=40;									

			           P_out_compressor = PressureRatio_compressor*P_in;
				   T_out_compressor = (T_in*PressureRatio_compressor^((gam_cold-1)/gam_cold))-T_in)/IsentropicEfficiency_compressor+T_in;
				   Power_compressor >=cp_cold*(T_out_compressor-T_in);
				
				   P_out_combustor = P_out_compressor*PressureRatio_combustor;
				   T_out_combustor = T_out_compressor+fuel/m_core*c_fuel/cp_hot;

				   P_out = P_out_combustor*PressureRatio_Turbine;
				   T_out = T_out_combustor+(T_out_combustor-T_out_combustor*(P_out/P_out_combustor)^((gam_hot-1)/gam_hot))*IsentropicEfficiency_turbine;
				  
				   Power_propulsor =1/Transfer_efficiency*cp_hot*(T_out_combustor-T_out)*m_core-Power_compressor; 
	
				}
			}
		}
		

		component NozzleSubsystem {

			input var P_in: real: Pascal;
			input var T_in: real: Kelvin;
			input var P_amb: real: Pascal;
 	
			output var T_out: real: Kelvin;
 			output var P_out: real: Kelvin;
			output var A: real: m^2;
		
			var U_flight: real: m/s = M_in*sqrt(gam_cold*R*T_in);
			var U_core: real;
			var U_bypass: real;
			var m_core: real;
			var cost: real: USD;

			parameter cp_cold: real: J/kg/K=1005;		% Specific Heat at Constant Pressure of air in cold section (changes moderately with temperature)
			parameter gam_cold: real: J/kg/K=1.4;		% Ratio of Specific Heats of air in cold section (changes moderately with temperature)
			parameter cp_hot: real: J/kg/K=1244;		% Specific Heat at Constant Pressure of air in hot section (changes moderately with temperature)
			parameter gam_hot: real: K/kg/K=1.3;		% Ratio of Specific Heats of air in hot section (changes moderately with temperature)		
			parameter R: real: J/kg/K=287;			% Gas Constant	
			parameter isBypass: boolean;

			% Assume the pressure differential due to choking does not significantly impact thrust for civil applications
			
	
			view logic {
		           assumption {
				 if (isBypass) then {
                              	  %u_flight >=0;
				  %u_flight <250;
			  	  P_in >= 24000;						
				  P_in <= 250000;						
				  T_in >= 414;													
				  T_in <= 1000;							
				}
				else {
                              	  %u_flight >=0;
				  %u_flight <250;
				  P_in >= 23487;
				  P_in <= 244360;
				  T_in >= 216;
				  T_in <= 442;
				}
			   }

			   guarantee {
			        if (isBypass) then {
				  
				  if (P_in/P_amb<1.89) then {
				    P_out = P_amb;
				    T_out = T_in*(P_out/P_in)^((gam_cold-1)/gam_cold));
				    U_bypass = sqrt(2*cp_cold*(T_in-T_out));
				    A = m_core*BPR/((P_out/(R*T_out))/U_bypass;

				  } else {
				    %P_in/P_amb>=1.89;
				    T_out = T_in/(1+(gam_cold-1)/2);
				    P_out = P_int*(T_out/T_in)^(gam_cold/(gam_cold-1));
				    U_bypass = sqrt(gam_cold*R*T_out);
				    A = m_core*BPR/((P_out/(R*T_out))/U_bypass;
				  }
			       } else {

				 if (P_in/P_amb<1.89) then {				
				    P_out = P_amb;
				    T_out = T_in*(P_out/P_in)^((gam_hot-1)/gam_hot));
				    U_core = sqrt(2*cp_hot*(T_in-T_out));
				    A = m_core*/((P_out/(R*T_out))/U_core;

				 } else {
				    %P_in/P_amb>=1.89 
				    T_out = T_in/(1+(gam_hot-1)/2);
				    P_out = P_int*(T_out/T_in)^(gam_hot/(gam_hot-1));
				    U_core = sqrt(gam_hot*R*T_out);
				    A = m_core/((P_out/(R*T_out))/U_core;
				 }

			       }
															
			   }
		}



		rules {

		       guarantee {

			%#core =1
			exist (coresys instanceof CoreSubsystem);
			forall (coresys instanceof CoreSubsystem)
			    {
				if (exist coresys2 instanceof CoreSubsystem) then
					coresys2 = coresys
			    }


			% struct
			forall (coresys instanceof CoreSubsystem)
			  {
				if (coresys.enginetype = turbofan) then
				{
			          %possible arch1: 
				    exists (diffusersys instanceof DiffuserSubsystem AND corenoz instanceof NozzleSubsystem)
				      (	diffusersys.P_out = coresys.P_in AND diffusersys.T_out = coresys.T_in AND
					(if exists (comp instanceof component)(comp.P_out = coresys.P_in AND comp.T_out = coresys.T_in) then
					    comp = diffusersys;) AND
					coresys.P_out = corenoz.P_in AND coresys.T_out = corenoz.T_in AND
					exists (fansys instanceof FanSubsystem AND bpnoz instanceof NozzleSubsystem)
					 ( diffusersys.P_out = fansys.P_in AND diffusersys.T_out = fansys.T_in AND
					   fansys.P_out = bpnoz.P_in AND fansys.T_out = bpnoz.T_in
					   and fansys.ductedToCore = false  AND
					   (if exists (comp instanceof component)(coresys.P_out = comp.P_in AND coresys.T_out = comp.T_in) then
					    comp = corenoz OR comp = fansys;
					   ) AND
					   (if exists (comp instanceof component)(fansys.P_out = comp.P_in AND fansys.T_out = comp.T_in) then comp=bpnoz)	  
				         )
				      )  
				    OR
				   %possible arch2: 
				    exists (diffusersys instanceof DiffuserSubsystem AND fansys instanceof FanSubsystem AND
					    corenoz instance NozzleSubsystem and bpnoz instanceof NozzleSubsystem
					    )
				      (
					diffusersys.P_out = fansys.P_in AND diffuser.T_out = fansys.T_in AND
				        fansys.P_out = coresys.P_in AND fansys.T_out = coresys.T_in AND
					coresys.P_out = corenoz.P_in AND coresys.T_out = corenoz.T_in AND
					fansys.P_out = bpnoz.P_in AND fansys.T_out = bpnoz.T_in AND
					fansys.ductedToCore = true AND
					(
					  if exists (comp instanceof component) (diffuser.P_out = comp.P_in AND diffuser.T_out = comp.T_in) then comp=fan;
					) AND
                                        (
					  if exists (comp instanceof component) (fan.P_out = comp.P_in AND fan.T_out = comp.T_in) then 
						comp= core OR comp = bpnozzle;
					) AND
					(
					  if exists (comp instanceof component) (core.P_out = comp.P_in AND core.T_out = comp.T_in) then comp = corenoz;
					)
				      ) 

				}
				else if (coresys.enginetype = turboprop)
				{
			          %possible arch3: 
				  exists (diffuser instanceof DiffuserSubsystem AND core instanceof CoreSubsystem AND
					  corenoz instanceof NozzleSubsystem AND prop instanceof PropellerSubsystem
					 )
				     (
					diffuser.P_out = core.P_in AND diffuser.T_out = core.T_in AND
					core.P_out = corenoz.P_in AND core.T_out = corenoz.T_in AND
					prop.ductedToCore = false AND
					(if (exists (comp instanceof component)(diffuser.P_out = comp.P_in AND diffuser.T_out = comp.T_in) then comp=core; )
					AND
					(if (exists (comp instanceof component)(core.P_out=comp.P_in AND core.T_out = comp.T_in) then comp=corenoz; )
				     ) 
				  OR
			          %possible arch4: 
				  exists (prop instanceof PropellerSubsystem AND diffuser instanceof DiffuserSubsystem AND
					  core instanceof CoreSubsystem AND corenoz instanceof NozzleSubsystem
					 )
			      	    (
					prop.P_out = diffuser.P_in AND prop.T_out = diffuser.T_in AND 
					diffuser.P_out = core.P_in AND diffuser.T_out = core.T_in AND
					core.P_out = corenoz.P_in AND core.T_out = corenoz.T_in AND
					prop.ductedToCore = true AND
					(if (exists (comp instanceof component) (prop.P_out = comp.P_in AND prop.T_out = comp.T_in)) then comp=diffuser) AND
					(if (exists (comp instanceof component) (diffuser.P_out=comp.P_in AND diffuser.T_out = comp.T_in)) then comp=core) AND
					(if (exists (comp instanceof component) (core.P_out=comp.P_in AND core.T_out=comp.T_in)) then comp=corenoz )
				    ) 
				}
			  }


			%diffuser can only be in front of either a core or a fan
			forall (diffuser instanceof DiffuserSubsystem)
			 (
			     (
				exists (core instanceof CoreSubsystem)
				  (diffuser.P_out = core.P_in AND diffuser.T_out = core.T_in)
				OR
				exists (fan instanceof FanSubsystem)
				  (diffuser.P_out = fan.P_in AND diffuser.T_out = fan.T_in)
			      )
			      AND
			      forall (comp instanceof component AND diffuser.P_out = comp.P_in AND diffuser.T_out = comp.T_in)
				comp instanceof FanSubsystem OR comp instanceof CoreSubsystem
			 )

			forall (core instanceof CoreSubsystem)
			  if (core.TSFC_req < 0.6) {
  				(core.enginetype = turbofan AND 
				   %fansubsystem.isParellel = true and only 1 fansubsystem
				   exists (fan instanceof FanSubsystem)
				     (
					fan.isParallel = true AND
					forall (fan1 instanceof FanSubsystem) fan1=fan)
				     )
				)
				OR
				core.enginetype = turboprop
   			}

			forall (core instanceof CoreSubsystem)
                           if (core.M_in > 0.7 OR core.altitude >21000)
				core.enginetype != turboprop

			% embedded rule
			forall (core instanceof CoreSubsystem)
			 (
			    if (!core.embedded)
			      {
			         if (core.enginetype=turboprop)
                                 {
				   // TODO: all turboprop's have the same parameters. Should allow to be different: Check with Chuck 
				   exists (prop instanceof PropellerSubsystem)
				     core.BPR = (prop.density*prop.U_prop*prop.A-core.m_core)/core.m_core; 
					
				 }
				 else
			         if (core.enginetype=turbojet) then core.BPR=0;
				 else
				 {
				   forall (fan instanceof FanSubsystem)					
			             (if (fan.type = single) then
			                   core.BPR >=0;
			                   core.BPR <= 15;
				      else
					   core.BPR >=15;
					   core.BPR <=30;
				     )		
			         }
			      }
			    else
			      {
			        core.BPR <=BPR_embedded;     % define BPR_embedded as user-specified number
			        core.enginetype != turboprop;
		              }


			    if (core.lo) then core.embedded = true;	
		            if (core.TSFC_req<1.1) then core.enginetype !=turbojet;

			 )


  			%#nozzle=#fansubsystems+1
			forall (noz instanceof NozzleSubsystem AND fan instanceof FanSubsystem)
			     Sum(noz) = Sum(fan)+1;
			
		
		}

}

