// sofcla.h
//
// define some of the classes used in sofea.cpp

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <math.h>

int EndOfFile=0;
#define MAXRUNS 5000
#define MAXELEM 5000	// can be increased as required
#define MAXOUT 200

//#define PI 3.14159265359

//-----------NODE--------------------------------------------------------
class Node
{
public:			// Caution No private because couldn't use some other function!!
				// So to change
	long number;
	double nx[6];			// Node coordinates x,y,z and rotations rx,ry,rz (for inclined support etc)
	double u[6];				// Node displacements and rotations
	long DOF;					// Number of DOF for this node
	int ActiveDOF[6];			// Active DOF in x,y,z,rotx,roty,rotz 0:inactive, 1:active
	int FixedDOF[6];			// Fixed DOF in x,y,z,rotx,roty,rotz 0:inactive, 1:active
	double DispBC[6];			// Value of Disp Boundary Condition in x,y,z,rotx,roty,rotz
	double ForceBC[6];			// Value of Force/Moment Boundary Condition in x,y,z,rotx,roty,rotz
	long CumSum;				// "Address" in the vectors.
	void Node::Init(void);
	int connected;
	double *Stress;
	double *Strain;
	void CalcStress();
};

void Node::Init(void)		// function to initialize data during the file reading
{
	int i;
	DOF = 0;
	CumSum=0;
	connected = 0;
	Stress = new double [3];
	Strain = new double [3];

	for (i=0; i<3; i++) Stress[i] = 0.0;
	for (i=0; i<3; i++) Strain[i] = 0.0;

	for(i=0;i<6;i++) { 
		nx[i]=0.0;
		u[i]=0.0;
		ActiveDOF[i]=0; 
		FixedDOF[i]=0; 
		DispBC[i]=0.0;
		ForceBC[i]=0.0;
		}
}

void Node::CalcStress()
{
	int i;
	for (i=0; i<3;i++){
		Strain[i] = Strain[i]/connected;
		Stress[i] = Stress[i]/connected;
	}
}



//----------MATERIAL----------------------------------------------------------

class Material
{
public:
	Material (long num);
	long number;
	double Ex[MAXRUNS];		// Material properties...
	double Nuxy[MAXRUNS];
	double Alphax[MAXRUNS];
	double Density[MAXRUNS];
	
};

Material::Material (long num)
{
	number = num;
	for (int i=0; i<MAXRUNS; i++){
		Ex[i]= 0;
		Nuxy[i] = 0;
		Density[i]=0;
		Alphax[i] =0;
	}
}

//----------Cross Section Property------------------------------------------

class CrossSection
{
public:
	long number;
	double Area;
	double Ixx, Iyy, Izz;
	double Height;
	double Thickness;
	CrossSection(long num);
};

CrossSection::CrossSection(long num)
{
	number = num;
	Area = 0;
	Izz = 0;
	Height = 0;
	Thickness = 0;
}

//----- Gauss Integration Points 2x2 ---------

class Gauss22
{
public:
	double Rg[4];
	double Sg[4];
	Gauss22(void);
	double *N;
};

Gauss22::Gauss22(void)
{
	double g;
	g=1.0/sqrt(3);
	
	Rg[0]=-g;
	Rg[1]=g;
	Rg[2]=g;
	Rg[3]=-g;

	Sg[0]=-g;
	Sg[1]=-g;
	Sg[2]=g;
	Sg[3]=g;
	N = new double [4];
	double sq3;
	sq3 = sqrt(3);
	N[0] = 0.25*(1+sq3)*(1+sq3);
	N[1] = 0.25*(1-sq3)*(1+sq3);
	N[2] = 0.25*(1-sq3)*(1-sq3);
	N[3] = 0.25*(1+sq3)*(1-sq3);
}

//-------------- Maximum Class for max mo value etc ---------//

class Maximum
{
public:
	double Ex;
	double Nuxy;
	double Density;
	double Alphax;
	double *Strain;				//3 element array of max strains
	double *Stress;				//3 element array of max stresses
	long *StrainNode;		//Stores number of nodes where max strains occur
	long *StressNode;		//Stores numbers of nodes where max stresses occur
	long ExLoop;
	long NuxyLoop;
	long DensityLoop;
	long AlphaxLoop;
	Maximum();
	void CompareMP(double ex, double nuxy, double dens, double alpx, long loop);
	void CompareS(double *Stn, long *StnN, double *Sts, long *StsN);
};

Maximum::Maximum()
{
	int i;
	Ex = 0;
	Nuxy = 0;
	Density = 0;
	Alphax = 0;
	ExLoop = 0;
	NuxyLoop=0;
	DensityLoop = 0;
	AlphaxLoop = 0;
	Strain = new double[3];
	Stress = new double[3];
	StrainNode = new long[3];
	StressNode = new long[3];
	for (i=0;i<3;i++){
		Strain[i] = 0.0;
		Stress[i] = 0.0;
		StrainNode[i] = 0;
		StressNode[i] = 0;
	}

}

void Maximum::CompareMP(double ex, double nuxy, double dens, double alpx, long loop)
{
	if (ex > Ex){ Ex = ex;
		ExLoop = loop;
	}
	if (nuxy > Nuxy) {	Nuxy = nuxy;
		NuxyLoop = loop;
	}
	if (dens > Density){	Density = dens;
		DensityLoop = loop;
	}
	if (alpx > Alphax) { 	Alphax = alpx;
		AlphaxLoop = loop;
	}
}

void Maximum::CompareS(double *Stn, long *StnN, double *Sts, long *StsN)
{
	int i;
	for (i=0;i<3;i++){
		if (Stn[i] > Strain[i]) {
			Strain[i] = Stn[i];
			StrainNode[i] = StnN[i];
		}
		if (Sts[i] > Stress[i]) {
			Stress[i] = Sts[i];
			StressNode[i] = StsN[i];
		}
	}
}

