//A Dynamic Model of a ThermoStat By Wyatt Houtz (Winter 1998-1999)
#include "iostream.h"  //For Buffer window
#include "fstream.h"   //For reading and writing to files
#include "iomanip.h"   //For formating output.

class Chaos {      //Chaos Class
	public:         //Variables accessible from outside the class
		typedef long double decimal;  //decimal = long int
		Chaos();	  //Default Constructor
		~Chaos();  //Default Destructor
		void EnterData(); //Enters data from the file to the class
		void Run();   //Runs through the system for current Tr, Te, Theta, & Omega
		void DataFile();  //exports all array values to a file
		void Extremes();   //Find the extrema of a current Run
		void MultipleRunFile();  //Exports high, and low values of a run.
		void Buffer(); //For display of initials
		void SBuffer(); //For display of initials (single run)
		decimal LeftStart_High, LeftStart_Low, LeftStart_Step;
		decimal LeftSlope, LeftStart, LeftEnd;
		decimal RightStart_High, RightStart_Low, RightStart_Step;
		decimal RightSlope, RightStart, RightEnd;
		decimal Hr_Low, Hr_High, Hr_Step, Hr, Ve, Vr;
		decimal Tau_Low, Tau_High, Tau_Step, Tau;
		decimal Theta_Low, Theta_High, Te_Low, Te_High;
		decimal Tr_Low, Tr_High, Omega_Low, Omega_High;
		decimal SRun, SLeft, SRight, STau, SHr;


	private:
		decimal Function_Left(decimal x); //left Hysteresis Function
		decimal Function_Right(decimal x); //Right Hysteresis Function
		decimal *TIME, *TR, *TE, *THETA, *OMEGA, dt;
		decimal Itheta, Itr, Ite, Iomega;
		decimal He, q;
		long int el, Total, SlowOmega, X, ChangeD;
		unsigned long int LastN, N;
		char Z[500]; //Nulls out rem's in Initials.txt;
		int Width; //For spacing

	};

Chaos::Chaos() {   //Constructor Initializes program

	EnterData();

	el = (long int) (Tau / dt + 1);  //el is for Delay
	Total = N + el;  //total number of values in each array
	LastN = Total - LastN;  //Used to reference LastN elements of the run.
	if (LastN < 0)
		LastN = 0;
	Width=16; //spaces each number takes up in the output file.
	ChangeD = 0;  //Number of time the function changes direction

	//Arrays for data.
	TIME = new decimal[Total];
	THETA = new decimal[Total];
	TR = new decimal[Total];
	TE = new decimal[Total];
	OMEGA = new decimal[Total];


	//Initializes arrays with specified values.
	for (long int k=0; k < el; k++) {
		THETA[k] = Itheta;
		TR[k] = Itr;
		TE[k] = Ite;
		OMEGA[k] = Iomega;
		}
	for (long int k=0; k < Total; k++) //An array to show the time progression
		TIME[k] = k * dt - el*dt;

	if (SRun == 0) {
		ofstream outfile("MResults.txt");   //Header information exported to file.
		outfile << "Hr"
				  << setw(Width) << "Tau"
				  << setw(Width) << "LeftStart"
				  << setw(Width) << "RightStart"
				  << setw(Width) << "Theta_Low"
				  << setw(Width) << "Theta_High"
				  << setw(Width) << "Te_Low"
				  << setw(Width) << "Te_High"
				  << setw(Width) << "Tr_Low"
				  << setw(Width) << "Tr_High"
				  << setw(Width) << "Omega_Low"
				  << setw(Width) << "Omega_High"
				  << setw(Width) << "ChangeD" << endl;
		outfile.close();
		}
	}

Chaos::~Chaos() {    //Deallocates arrays and returns memory used.
//	outfile.close();
	delete [ ] TIME;
	delete [ ] THETA;
	delete [ ] TR;
	delete [ ] TE;
	delete [ ] OMEGA;
	}

void Chaos::EnterData() {   //Enters initial from the data file.
	ifstream infile("Initials.txt", ios::in);
	infile >> q >> Z     //Z is a null variable, used to delimit variables
			 >> He >> Z
			 >> Hr_Low >> Z
			 >> Hr_High >> Z
			 >> Hr_Step >> Z
			 >> Tau_Low >> Z
			 >> Tau_High >> Z
			 >> Tau_Step >> Z
			 >> SlowOmega >> Z
			 >> Ve >> Z
			 >> Vr >> Z
			 >> Itheta >> Z
			 >> Ite >> Z
			 >> Itr >> Z
			 >> Iomega >> Z
			 >> LeftStart_Low >> Z
			 >> LeftStart_High >> Z
			 >> LeftStart_Step >> Z
			 >> LeftSlope >> Z
			 >> RightStart_Low >> Z
			 >> RightStart_High >> Z
			 >> RightStart_Step >> Z
			 >> RightSlope >> Z
			 >> N >> Z
			 >> dt >> Z
			 >> LastN >> Z
			 >> SRun >> Z
			 >> SLeft >> Z
			 >> SRight >> Z
			 >> STau >> Z
			 >> SHr >> Z;


	infile.close();
	
	}

void Chaos::Buffer() {
	cout << "Chaos Number Cruncher" << endl;
	cout << "Wyatt Houtz (c)1999" << endl;
	cout << "whoutz@oakland.edu" << endl;
	cout   << "\nq = " << q << endl;
	cout	 << "N = " << N << endl;
	cout	 << "He = " << He << endl;
	cout	 << "dt = " <<dt << endl;
	cout	 << "SlowOmega = " << SlowOmega << endl << endl;
	cout	 << "Initial:"
			 << "  Theta = " << Itheta
			 << "  Te = " << Ite
			 << "  Tr = " << Itr
			 << "  Omega = " << Iomega << endl;
	cout	 << setiosflags(ios::left) << "Hr:         "
			 << " Low = " << setw(7) << Hr_Low
			 << " High = " << setw(7) << Hr_High
			 << " Step = " << setw(7) << Hr_Step << endl;
	cout	 << setiosflags(ios::left) << "Tau:        "
			 << " Low = " << setw(7) << Tau_Low
			 << " High = " << setw(7) << Tau_High
			 << " Step = " << setw(7) << Tau_Step << endl;
	cout	 << setiosflags(ios::left) << "LeftStart:  "
			 << " Low = " << setw(7) << LeftStart_Low
			 << " High = " << setw(7) << LeftStart_High
			 << " Step = " << setw(7) << LeftStart_Step
			 << " Slope = " << setw(7) << LeftSlope << endl;
	cout	 << setiosflags(ios::left) << "RightStart: "
			 << " Low = " << setw(7) << RightStart_Low
			 << " High = " << setw(7) << RightStart_High
			 << " Step = " << setw(7) << RightStart_Step
			 << " Slope = " << setw(7) << RightSlope << endl;

	cout << endl << "    Running...   (please wait)" << endl << endl;
	}

void Chaos::SBuffer() {
	cout << "Chaos Number Cruncher" << endl;
	cout << "Wyatt Houtz (c)1999" << endl;
	cout << "whoutz@oakland.edu" << endl;
	cout   << "\nq = " << q << endl;
	cout	 << "N = " << N << endl;
	cout	 << "He = " << He << endl;
	cout	 << "dt = " <<dt << endl;
	cout	 << "SlowOmega = " << SlowOmega << endl;
	cout   << "Hr = " << SHr << endl;
	cout	 << "Tau = " << STau << endl;
	cout	 << "LeftStart = " << SLeft << endl
			 << "  Slope = " << setw(7) << LeftSlope << endl;
	cout	 << "RightStart: " << SRight << endl
			 << "  Slope = " << setw(7) << RightSlope << endl;
	cout	 << "Initial:"
			 << "  Theta = " << Itheta
			 << "  Te = " << Ite
			 << "  Tr = " << Itr
			 << "  Omega = " << Iomega << endl;

	cout << endl << "    Running...   (please wait)" << endl << endl;
	}

void Chaos::Run() {   //Solves the system for the set variables
	for (long int i = el; i < Total; i++) {
		THETA[i] = dt*He*TE[i-1] + THETA[i-1]*(1-dt*He);  //Theta

		if (THETA[i] == THETA[i - 1])                     //Omega starts
			OMEGA[i] = OMEGA[i - 1];
		else if (THETA[i] > THETA[i-1]) {
			if (Function_Right(THETA[i]) >= OMEGA[i - 1])
				OMEGA[i] = Function_Right(THETA[i]);
			else
				OMEGA[i] = OMEGA[i-1];
			}
		else if (THETA[i] < THETA[i-1]) {
			if (Function_Left(THETA[i]) <= OMEGA[i - 1])
				OMEGA[i] = Function_Left(THETA[i]);
			else
				OMEGA[i] = OMEGA[i-1];
			}

		TE[i] = (dt/Ve) * (q - (TE[i-1] - TE[i-el-1])                       //Te
				  - OMEGA[i-SlowOmega-1] * (TE[i-el-1] - TR[i-el-1]))
				  + TE[i-1];

		TR[i] = (dt/Vr) * (OMEGA[i-SlowOmega-1] * (TE[i-el-1] - TR[i-1]) - Hr*TR[i-1])
				  + TR[i-1];                                           //Tr
		}
	}

long double Chaos::Function_Left(decimal x) {  //Left Hysteresis Function
	LeftEnd = (decimal) (1/LeftSlope + LeftStart);
	if (x <= LeftStart)
		return 0;
	else if (x >= LeftEnd)
		return 1;
	else
		return LeftSlope * (x - LeftStart);
	}

long double Chaos::Function_Right(decimal x) {  //Right Hysteresis Function
	RightEnd = (decimal) (1/RightSlope + RightStart);
	if (x <= RightStart)
		return 0;
	else if (x >= RightEnd)
		return 1;
	else
		return RightSlope * (x - RightStart);
	}

void Chaos::Extremes() {	//finds extremes of Tr Te Omega Theta
	X = LastN;
	Theta_High = THETA[X];                //Theta
	Theta_Low = THETA[X];
	while (X < Total) {
		if (THETA[X] > Theta_High)
			Theta_High = THETA[X];
		else if (THETA[X] < Theta_Low)
			Theta_Low = THETA[X];
		X++;
		}

	X = LastN;
	Te_High = TE[X];                    //Te
	Te_Low = TE[X];
	while (X < Total) {
		if (TE[X] > Te_High)
			Te_High = TE[X];
		else if (TE[X] < Te_Low)
			Te_Low = TE[X];
		X++;
		}

	X = LastN;
	Tr_High = TR[X];                   //Tr
	Tr_Low = TR[X];
	while (X < Total) {
		if (TR[X] > Tr_High)
			Tr_High = TR[X];
		else if (TR[X] < Tr_Low)
			Tr_Low = TR[X];
		X++;
		}

	X = LastN;
	Omega_High = OMEGA[X];             //Omega
	Omega_Low = OMEGA[X];
	while (X < Total) {
		if (OMEGA[X] > Omega_High)
			Omega_High = OMEGA[X];
		else if (OMEGA[X] < Omega_Low)
			Omega_Low = OMEGA[X];
		X++;
		}

	ChangeD = 0;
	X = LastN;
	if (X < 3)
		X = 3;
	while (X < Total) {
		if ((OMEGA[X-1] > OMEGA[X-2]) && (OMEGA[X] < OMEGA[X-1]))
			ChangeD++;
		else if ((OMEGA[X-1] < OMEGA[X-2]) && (OMEGA[X] > OMEGA[X-1]))
			ChangeD++;
		X++;
		}
	}

void Chaos::MultipleRunFile() {    //Exports info to data file.
	ofstream outfile("MResults.txt", ios::app);
	outfile << setiosflags(ios::fixed)
			  << setiosflags(ios::showpoint)
			  << setiosflags(ios::left)
			  << setw(Width) << setprecision(5) << Hr
			  << setw(Width) << setprecision(5) << Tau
			  << setw(Width) << setprecision(5) << LeftStart
			  << setw(Width) << setprecision(5) << RightStart
			  << setw(Width) << setprecision(5) << Theta_Low
			  << setw(Width) << setprecision(5) << Theta_High
			  << setw(Width) << setprecision(5) << Te_Low
			  << setw(Width) << setprecision(5) << Te_High
			  << setw(Width) << setprecision(5) << Tr_Low
			  << setw(Width) << setprecision(5) << Tr_High
			  << setw(Width) << setprecision(5) << Omega_Low
			  << setw(Width) << setprecision(5) << Omega_High
			  << setw(Width) << setprecision(5) << ChangeD << endl;
	outfile.close();
	}

void Chaos::DataFile() {   //Returns results of one particular run.
	ofstream outfile("Results.txt");
	outfile << setiosflags(ios::fixed) << setiosflags(ios::showpoint)
			  << "Theta    "
			  << "Te       "
			  << "Tr       "
			  << "Omega    "
			  << "Time     " << endl;
	for (long int i = el; i < Total; i++) {
		outfile << setiosflags(ios::fixed) << setiosflags(ios::showpoint)
				  << setprecision(5) << THETA[i] << ", "
				  << setprecision(5) << TE[i] << ", "
				  << setprecision(5) << TR[i] << ", "
				  << setprecision(5) << OMEGA[i] << ", "
				  << setprecision(5) << TIME[i] << endl;
		}
	outfile.close();
	}

void main() {
	Chaos* X;  //Creates object X.
	X = new Chaos;

	if (X->SRun == 0) {
		X->Buffer();
		X->LeftStart = X->LeftStart_Low;
		while (X->LeftStart <= X->LeftStart_High) {
			X->RightStart = X->RightStart_Low;
			while (X->RightStart <= X->LeftStart)
				X->RightStart += X->RightStart_Step;
			while (X->RightStart <= X->RightStart_High) {
				X->Tau = X->Tau_Low;
				while (X->Tau <= X->Tau_High) {
					X->Hr = X->Hr_Low;
					while (X->Hr <= X->Hr_High) {
						X->Run();
						X->Extremes();
						X->MultipleRunFile();
						X->Hr += X->Hr_Step;
						}
					X->Tau += X->Tau_Step;
					}
				X->RightStart += X->RightStart_Step;
				}
			X->LeftStart += X->LeftStart_Step;
			}
		}

	if (X->SRun == 1) {
	Chaos* Y;  //Creates object Y.
		Y = new Chaos;
		Y->LeftStart = Y->SLeft;
		Y->RightStart = Y->SRight;
		Y->Tau = Y->STau;
		Y->Hr = Y->SHr;
		Y->SBuffer();
		Y->Run();
		Y->DataFile();
		}

	cout << "Complete";
	}
 Back