

// Notes on C syntax:
// everything beginning with // is a comment statememt and not part of program
// *= multiplies the quantity on the left by that on the right.
// += Adds the quantity on the right to that on the left.
// switch(n) selects alternative blocks of code depending on the value of n. The alternative
// blocks of code are placed between case and break statements.
// while() repeats the following block of code as long as the expression in the brackets is true.
// ++ increments a value by one

int CBoat::PowerBalance(int mode)
{
//	THE PURPOSE OF THIS FUNCTION IS TO ADJUST THE AIR VELOCITY DOWNSTREAM OF THE AIRSCREW
//	UNTILL THE POWER ABSORBED BY THE AIRSCREW IS CLOSELY SIMILAR TO THAT EXTRACTED BY THE 
//	WATERSCREW.

//	The variable mode selects one of two methods of calculating the airscrew and waterscrew
//	power.
	

//	If mode is zero (the default) the blades are assumed to be twisted along their length such that the 
//	angle of attack of the fluid relative to the blade is constant along the blade length between
//	the blade tip and the hub which is taken to have a radius one quarter of the blade radius.
//	The inner one quarter of the blade length is assumed to have no lift or drag and is also neglected in
//  	the calculation of rotor disc area. 

//	If mode is one then the power is calculated assuming that the blade geometry and relative
//	fluid flow direction and speed are constant along the length of the rotor blades.

	int ntrys=0;
	double error = 1.0;
	AirscrewPower = 0.5;
	WaterscrewPower = 0.5;
	PercentDownstreamAirVel=10.0;
	while ((error > AirscrewPower*0.000001)&&(ntrys<1000))
	{
		ntrys++;
		PercentDownstreamAirVel *= sqrt(WaterscrewPower/AirscrewPower);
		CalculateAirscrewPower(mode);
		CalculateWaterscrewPower(mode);
		error = WaterscrewPower - AirscrewPower;
		if(error<0)error *= -1.0;
	}
	if (ntrys>998)ntrys=0;
	return ntrys;
}


void CBoat::CalculateAirscrewPower(int mode)
//	THE PURPOSE OF THIS FUNCTION IS TO CALCULATE THE POWER ABSORBED BY THE AIRSCREW GIVEN
//	A VALUE FOR THE DOWNSTEAM AIR VELOCITY SOME WAY BEHIND THE AIRSCREW.(DownstreamAirVel)
	//	The downstream air velocity is expressed as a fraction of wind speed (i.e. boat speed)
	//	Note that since the boat is traveling at the speed of the wind the air speed 
	//	relative to the boat at some way ahead of the airscrew is zero.
{
	int n;
	double AirscrewBladeLiftForce	= 0; //Force component perp to airflow onto blade, total for all blades
	double AirscrewBladeDragForce	= 0; //Force component in line with airflow onto blade, total for all blades
	double AirscrewTorque		= 0; //Torque, total for all blades
	double AirscrewBladeAxialForce	= 0; //Axial force, total for all blades
	double AirscrewBladeProjectedArea =0; //Total projected area for all blades, viewed along axis
	double AirscrewChord = 1.0; //Combined chord for all blades, taken to be constant with radius from axis.
	double rad; //radius from axis to middle of 'slice' of blade being analysed
	double dr; // radial dimension of slice of blade being analysed
	double LocalTangVel; // local tangental velocity of blade
	double LocalBetaAir; //local angle at which air approaches the airscrew blade
	double hubrad; //hub radius, blade part inside this radius is assumed to have no lift or drag.

	switch (mode)
	{
	case 0: //calculation if mode = zero (default calculation method)

	//	Calculate airvelocity at disc of the airscrew rel to axis system moving with boat.
	//  Note that the airspeed at the disc of the airscrew is the mean of upstream and
	//  downstream airspeed, that is it is half the value of DownstreamAirVel (Acutator disc theory)
	//  since the craft is travelling at the speed of the wind.
	//	Also note that DownstreamAirVel is expressed as a percentage of wind speed.
	AirAxialVelAtAirscrewDisc = 0.01*WindSpeed*PercentDownstreamAirVel*0.5;

	//	Determine angle (beta) at which air approaches the airscrew blade at the tip, 
	//	relative to the plane in which the blades rotate 
	BetaAir = AirscrewTipPitch - AirscrewBladeAngleAttack;

	//	Calculate the tangental speed of the airscrew blades at the tips. 
	AirscrewTipTangentalSpeed = AirAxialVelAtAirscrewDisc/Tangent(BetaAir);

	//	Calculate the rotational speed of the airscrew:
	AirscrewRadius = AirscrewDiameter * 0.5;
	AirscrewRadsPerSec = AirscrewTipTangentalSpeed / AirscrewRadius;

	//	Calculate disc area of airscrew:
	hubrad = AirscrewRadius*0.25;
	AirscrewDiscArea = PI*(AirscrewRadius*AirscrewRadius - hubrad*hubrad);

	//	Calculate airscrew mass flow rate, air density assumed 1.2kg/m3
	AirDensity = 1.2;
	AirscrewMassFlow = AirscrewDiscArea * AirDensity * AirAxialVelAtAirscrewDisc;

	//	axial force (Thrust) on Airscrew - from momentum theory - the airscrew accelerates 
	//	the air from rest to the downstream velocity. Note DownstreamAirVel is
	//	expressed as percentage of wind speed
	AirscrewAxialForce = AirscrewMassFlow * 0.01 * WindSpeed * PercentDownstreamAirVel;
	

	// Consider each slice of blade in turn
	dr = (AirscrewRadius-hubrad)/BLADE_STEPS;
	for (n = 0; n<BLADE_STEPS; n++)
	{
		rad=AirscrewRadius - (n+0.5)*dr;

		//Calculate local tangental vel of blade
		LocalTangVel = AirscrewTipTangentalSpeed * rad/AirscrewRadius;

		//Calculate local angle at which air approaches blade rel to plane in which blade rotates
		LocalBetaAir = atan2(AirAxialVelAtAirscrewDisc, LocalTangVel);

		//Calculate local blade pitch
		AirscrewLocalPitch[n]= LocalBetaAir+AirscrewBladeAngleAttack;

		//	Calculate the local velocity of the air relative to moving airscrew blade:
		AirVelRelBlade = LocalTangVel/cos(LocalBetaAir);

	//	Calculate combined forces on all airscrew blades (lift vector measured perp
	//	to air vel rel to each blade) assuming 1m total chord for all blades
		AirscrewBladeLiftForce  += AirscrewBladeLiftCoeff*0.5*AirDensity*dr*AirVelRelBlade*AirVelRelBlade;
		AirscrewBladeDragForce  += AirscrewBladeLiftCoeff*0.5*AirDensity*dr*AirVelRelBlade*AirVelRelBlade/AirscrewBladeLiftDragRatio;
		AirscrewBladeAxialForce += AirscrewBladeLiftForce*cos(LocalBetaAir) - AirscrewBladeDragForce*sin(LocalBetaAir);
		AirscrewTorque		+= rad * (AirscrewBladeDragForce*cos(LocalBetaAir)+AirscrewBladeLiftForce*sin(LocalBetaAir));

	//  Calculate projected blade area assuming 1m total chord for all blades
		AirscrewBladeProjectedArea += dr*cos(LocalBetaAir + AirscrewBladeAngleAttack);
	}
	// calculate actual total blade chord so that axial force matches that from momentum equation
	// AirscrewAxialForce was the actual axial force from mometum equation, AirscrewBladeAxialForce was from assumption that
	// total chord for all blades is 1.0m, hence we can calculate the actual total chord for all blades. 
	AirscrewChord = AirscrewAxialForce/AirscrewBladeAxialForce;

	// calcualate actual blade projected area and solidity ratio
	AirscrewBladeProjectedArea =  AirscrewBladeProjectedArea * AirscrewChord;
	AirscrewSolidity = AirscrewBladeProjectedArea * 100.0 /AirscrewDiscArea; 

	//Calculate actual airscrew torque
	AirscrewTorque *= AirscrewChord;

	//	Calculate airscrew shaft power
	AirscrewPower = AirscrewTorque*AirscrewRadsPerSec;
	
	// End of calculation for mode = zero
	break;





	case 1: //calculation if mode = one

	//	Calculate airvelocity at disc of the airscrew rel to axis system moving with boat.
	//  Note that the airspeed at the disc of the airscrew is the mean of upstream and
	//  downstream airspeed, that is it is half the value of DownstreamAirVel (Acutator disc theory)
	//	Also note that DownstreamAirVel is expressed as a percentage of wind speed.
	AirAxialVelAtAirscrewDisc = 0.01*WindSpeed*PercentDownstreamAirVel*0.5;

	//	Determine angle (beta) at which air approaches the airscrew blades, 
	//	relative to the plane in which the blades rotate 
	BetaAir = AirscrewTipPitch - AirscrewBladeAngleAttack;

	//	Calculate the tangental speed of the airscrew blades. 
	AirscrewTipTangentalSpeed = AirAxialVelAtAirscrewDisc/Tangent(BetaAir);

	//	Calculate the velocity of the air relative to moving airscrew blade:
	AirVelRelBlade = AirscrewTipTangentalSpeed/cos(BetaAir);

	//	Calculate the rotational speed of the airscrew:
	AirscrewRadius = AirscrewDiameter * 0.5;
	AirscrewRadsPerSec = AirscrewTipTangentalSpeed / AirscrewRadius;

	//	Calculate disc area of airscrew:
	AirscrewDiscArea = PI*AirscrewRadius*AirscrewRadius;

	//	Calculate airscrew mass flow rate, air density assumed 1.2kg/m3
	AirDensity = 1.2;
	AirscrewMassFlow = AirscrewDiscArea * AirDensity * AirAxialVelAtAirscrewDisc;

	//	axial force (Thrust) on Airscrew - from momentum theory - the airscrew accelerates 
	//	the air from rest to the downstream velocity. Note DownstreamAirVel is
	//	expressed as percentage of wind speed
	AirscrewAxialForce = AirscrewMassFlow * 0.01 * WindSpeed * PercentDownstreamAirVel;

	//	Calculate combined lift on all airscrew blades (lift vector measured perp
	//	to air vel rel to each blade)
	AirscrewBladeLift = AirscrewAxialForce / (cos(BetaAir)-sin(BetaAir)/AirscrewBladeLiftDragRatio);

	//	Calculate combined drag on all airscrew blades (drag vector measured in direction
	//	of air vel rel to each blade)
	AirscrewBladeDrag = AirscrewBladeLift / AirscrewBladeLiftDragRatio;

	//	Calculate combined tangental force on all airscrew blades
	AirscrewTangentalForce = AirscrewBladeDrag * cos(BetaAir) + AirscrewBladeLift * sin(BetaAir);

	//	Calculate airscrew shaft power
	AirscrewPower = AirscrewRadius*AirscrewTangentalForce*AirscrewRadsPerSec;

	//	THE FOLLOWING CALCS GIVE SUPPLEMENTARY INFO, THEY ARE NOT ESSENTIAL TO DETERMINE WATERSCREW POWER.

	//	Calculate linear pitch of airscrew (m per revolution) 
	AirscrewLinearPitch = PI*AirscrewDiameter*Tangent(AirscrewTipPitch);

	//	Calculate Blade Area of airscrew (total for all Blades)
	AirscrewBladeArea = AirscrewBladeLift/(0.5*AirDensity*AirscrewBladeLiftCoeff*AirVelRelBlade*AirVelRelBlade);

	//	Calculate Solidity ratio for waterscrew
	AirscrewSolidity = AirscrewBladeArea / AirscrewDiscArea;

	//	End of calculation for mode = 1
	break;
	}

}


void CBoat::CalculateWaterscrewPower(int mode)
//	THE PURPOSE OF THIS FUNCTION IS TO CALCULATE THE POWER PRODUCED BY THE WATERSCREW 
//	GIVEN A VALUE FOR THE DROP IN WATER VELOCITY ACCROSS THE WATERSCREW. (WaterVelDrop)
{
	int n;
	double WaterscrewBladeLiftForce	= 0;
	double WaterscrewBladeDragForce	= 0;
	double WaterscrewTorque		= 0;
	double WaterscrewBladeAxialForce	= 0;
	double WaterscrewBladeProjectedArea =0;
	double WaterscrewChord = 1.0;
	double rad; //radius from axis to middle of 'slice' of blade being analysed
	double dr; // radial increment
	double LocalTangVel; // local tangental velocity of blade
	double LocalBetaWater; //local angle at which water approaches the waterscrew blade
	double hubrad; //blade inside this radius is assumed to have no lift or drag.

	switch (mode)
	{
	case 0: //calculation if mode = zero  (the default mode)
//	Calculate waterspeed downstream of waterscrew. Note that waterspeed upstream is boat
//	speed which is equal to wind speed. WaterVelDrop is the drop in water speed accross the
//	waterscrew expressed as a percentage of the wind speed.
	DownstreamWaterVel = WindSpeed - 0.01 * WindSpeed * WaterscrewVelDrop;
	

//	Calculate the waterspeed at the disc of the water screw. This is taken as the mean
//	of the upstream and downstream waterspeeds (actuator disc theory)
	WaterAxialVelAtWaterscrewDisc = (WindSpeed + DownstreamWaterVel)*0.5;

//	Calculate angular vel of waterscrew from the angular vel of airscrew and the 
//	gear ratio of the transmission system:
	WaterscrewRadsPerSec = AirscrewRadsPerSec * GearRatio;

//	Calculate tangental speed of waterscrew blades at the tips
	WaterscrewRadius = 0.5 * WaterscrewDiameter;
	WaterscrewTipTangentalSpeed = WaterscrewRadius * WaterscrewRadsPerSec;

//	Calculate Mass flow of water through waterscrew
	WaterDensity = 1000.0;
	hubrad=WaterscrewRadius*0.25;
	WaterscrewDiscArea = PI * (WaterscrewRadius * WaterscrewRadius - hubrad*hubrad);
	WaterscrewMassFlow = WaterscrewDiscArea * WaterDensity * WaterAxialVelAtWaterscrewDisc;

//	Calculate axial force on waterscrew - momentum equation.WaterVelDrop is the drop in water
//	speed accross the waterscrew expressed as a percentage of the wind speed.
	WaterscrewAxialForce = WaterscrewMassFlow * WaterscrewVelDrop * 0.01 * WindSpeed;

//	Calculate direction of waterflow relative to tip of moving blade, (  atan2(x,y) calculates arc tan of x/y)   )
	BetaWater = atan2 (WaterAxialVelAtWaterscrewDisc , WaterscrewTipTangentalSpeed);

//	Calculate blade pitch angle at tips and linear pitch based on this angle 
	WaterscrewTipPitch = BetaWater - WaterscrewBladeAngleAttack;
	WaterscrewLinearPitch = PI*WaterscrewDiameter*Tangent(WaterscrewTipPitch);

	// Consider each slice of blade in turn
	dr = (WaterscrewRadius-hubrad)/BLADE_STEPS;
	for (n = 0; n<BLADE_STEPS; n++)
	{
		rad=WaterscrewRadius - (n+0.5)*dr;

		//Calculate local tangental vel of blade
		LocalTangVel = WaterscrewTipTangentalSpeed * rad/WaterscrewRadius;

		//Calculate local angle at which water approaches blade rel to plane in which blade rotates
		LocalBetaWater = atan2(WaterAxialVelAtWaterscrewDisc, LocalTangVel);

		//Calculate local blade pitch
		WaterscrewLocalPitch[n]= LocalBetaWater-WaterscrewBladeAngleAttack;

		//	Calculate the local velocity of the water relative to moving waterscrew blade:
		WaterVelRelBlade = WaterAxialVelAtWaterscrewDisc/sin(LocalBetaWater);

	//	Calculate combined forces on all waterscrew blades (lift vector measured perp
	//	to water vel rel to each blade) assuming 1m total chord for all blades
		WaterscrewBladeLiftForce  += WaterscrewBladeLiftCoeff*0.5*WaterDensity*dr*WaterVelRelBlade*WaterVelRelBlade;
		WaterscrewBladeDragForce  += WaterscrewBladeLiftCoeff*0.5*WaterDensity*dr*WaterVelRelBlade*WaterVelRelBlade/WaterscrewBladeLiftDragRatio;
		WaterscrewBladeAxialForce += WaterscrewBladeLiftForce*cos(LocalBetaWater) + WaterscrewBladeDragForce*sin(LocalBetaWater);
		WaterscrewTorque     += rad * (WaterscrewBladeLiftForce*sin(LocalBetaWater) - WaterscrewBladeDragForce*cos(LocalBetaWater));

	//  Calculate projected blade area assuming 1m total chord for all blades
		WaterscrewBladeProjectedArea += dr*cos(LocalBetaWater - WaterscrewBladeAngleAttack);
	}


	// calculate actual total blade chord
	WaterscrewChord = WaterscrewAxialForce/WaterscrewBladeAxialForce;

	// calcualate actual blade projected area and solidity ratio
	WaterscrewBladeProjectedArea =  WaterscrewBladeProjectedArea * WaterscrewChord;
	WaterscrewSolidity = WaterscrewBladeProjectedArea * 100.0 /WaterscrewDiscArea; 

	//Calculate actual waterscrew torque
	WaterscrewTorque *= WaterscrewAxialForce/WaterscrewBladeAxialForce;

	//	Calculate airscrew shaft power
	WaterscrewPower = WaterscrewTorque*WaterscrewRadsPerSec;

	//	Correct water screw power to allow for transmission losses to give power available to turn airscrew
	WaterscrewPower = WaterscrewPower * MechEfficiency;

	//	End of calculation for mode = zero
	break;


	case 1:
	//Calculation for mode = 1 
//	Calculate waterspeed downstream of waterscrew. Note that waterspeed upstream is boat
//	speed which is equal to wind speed. WaterVelDrop is the drop in water speed accross the
//	waterscrew expressed as a percentage of the wind speed.
	DownstreamWaterVel = WindSpeed - 0.01 * WindSpeed * WaterscrewVelDrop;
	

//	Calculate the waterspeed at the disc of the water screw. This is taken as the mean
//	of the upstream and downstream waterspeeds (actuator disc theory)
	WaterAxialVelAtWaterscrewDisc = (WindSpeed + DownstreamWaterVel)*0.5;

//	Calculate angular vel of waterscrew from the angular vel of airscrew and the 
//	gear ratio of the transmission system:
	WaterscrewRadsPerSec = AirscrewRadsPerSec * GearRatio;

//	Calculate tangental speed of waterscrew blades
	WaterscrewRadius = 0.5 * WaterscrewDiameter;
	WaterscrewTipTangentalSpeed = WaterscrewRadius * WaterscrewRadsPerSec;

//	Calculate direction of waterflow relative to moving blade, (  atan2(x,y) calculates arc tan of x/y)   )
	BetaWater = atan2 (WaterAxialVelAtWaterscrewDisc , WaterscrewTipTangentalSpeed);


//	Calculate vel of water relative to blades of water screw
	WaterVelRelBlade = WaterscrewTipTangentalSpeed / cos(BetaWater);

//	Calculate Mass flow of water throug waterscrew
	WaterDensity = 1000.0;
	WaterscrewDiscArea = PI * WaterscrewRadius * WaterscrewRadius;
	WaterscrewMassFlow = WaterscrewDiscArea * WaterDensity * WaterAxialVelAtWaterscrewDisc;

//	Calculate axial force on waterscrew - momentum equation.
	WaterscrewAxialForce = WaterscrewMassFlow * WaterscrewVelDrop * 0.01 * WindSpeed;

//	Calculate combined lift on all waterscrew blades (lift vector measured perp
//	to water vel rel to each blade) 
//	WaterscrewBladeLiftDragRatio = 20.0;
	WaterscrewBladeLift = WaterscrewAxialForce / (cos(BetaWater)+sin(BetaWater)/WaterscrewBladeLiftDragRatio);

//	Calculate combined drag on all waterscrew blades (drag vector measured in direction
//	of water vel rel to each blade)
	WaterscrewBladeDrag = WaterscrewBladeLift / WaterscrewBladeLiftDragRatio;

//	Calculate combined tangental force on all water screw blades (measured in plane of water
//	screw disc)
	WaterscrewTangentalForce = WaterscrewBladeLift * sin(BetaWater) - WaterscrewBladeDrag * cos(BetaWater);

//	Calculate water screw shaft power
	WaterscrewPower = WaterscrewRadius*WaterscrewTangentalForce*WaterscrewRadsPerSec;

//	Correct water screw power to allow for transmission losses to give power available to turn airscrew
	WaterscrewPower = WaterscrewPower * MechEfficiency;

//	THE FOLLOWING CALCS GIVE SUPPLEMENTARY INFO, THEY ARE NOT ESSENTIAL TO DETERMINE WATERSCREW POWER.

//	Calculate pitch of waterscrew  
	WaterscrewTipPitch = BetaWater - WaterscrewBladeAngleAttack;
	WaterscrewLinearPitch = PI*WaterscrewDiameter*Tangent(WaterscrewTipPitch);

//	Calculate Blade Area of waterscrew (total for all Blades)
	WaterscrewBladeArea = WaterscrewBladeLift/(0.5*WaterDensity*WaterscrewBladeLiftCoeff*WaterVelRelBlade*WaterVelRelBlade);

//	Calculate Solidity ratio for waterscrew
	WaterscrewSolidity = WaterscrewBladeArea / WaterscrewDiscArea;

//	End of calculation for mode = 1
	break;
	}
}





