//RectWaveGuide_State.java

import java.util.*;

public class RectWaveGuide_State {
    public boolean IsTEmode;
    public double a, b; // waveguide width
    public double a_minimum, a_maximum;
    public double epsilon_r;
    public double mu_r; 
    public double frequency;
    public double frequency_minimum, frequency_maximum;
    public double angular_frequency;
    public double cut_off_wavelength, guide_wavelength;
    public double minimum_prop_frequency, cut_off_frequency_for_mode;
    public double a_to_b_ratio;
    public double a_to_b_ratio_minimum, a_to_b_ratio_maximum;
    public double phase_velocity, group_velocity, light_velocity;
    public double K, Kc, Beta, Kx, Ky, Kz;
    public double impedance_TE, impedance_TM;
    public Complex BetaC, ZeroC;
    public int mode_number1, mode_number2;
    public int max_modes_excited_m0,max_modes_excited_0n, TotalModes;
    //public int max_modes_this_m, max_modes_this_n;
    public double Z, medium_impedance;
    //public static final double epsilon0 = 8.8541878176E-12; //Units: F/m
    // Approximate epsilon for phase velocity 3 x 10^8 m/s
    public static final double epsilon0 = 8.841941286E-12; 
    public static final double mu0 = 1.25663706144E-6; //Units H/m
    
    public boolean LicenseExpired;
    public int this_month, today_week, this_year, this_hour, this_minute, today_month, 
	       today_year,this_zone, saving_time;       
    GregorianCalendar Greg = new GregorianCalendar();
    
    public RectWaveGuide_State(){
	IsTEmode = true;
	a = 2.0E-2; //2 cm
	a_minimum = 0.0;//
	a_maximum = 10.0E-2;//10.0 cm
	
	a_to_b_ratio = 2.22;
	a_to_b_ratio_minimum = 1.0;
	a_to_b_ratio_maximum = 6.0;
	
	epsilon_r = 1.0;
	mu_r = 1.0;
	
	frequency = 10.0E9;
	frequency_minimum = 0.0;
	frequency_maximum = 20.0E9;
	
	impedance_TE=Math.sqrt(mu0*mu_r/(epsilon0*epsilon_r));
	impedance_TM=Math.sqrt(mu0*mu_r/(epsilon0*epsilon_r));
	
	ZeroC = new Complex(0.0,0.0);
	
	mode_number1 = 1;
	mode_number2 = 0;
	
	this_month = Greg.get(Calendar.MONTH);
	//System.out.println("  This is the month = "+this_month);
	today_week = Greg.get(Calendar.DAY_OF_WEEK);
	//System.out.println("  This is the day_week = "+today_week);
	this_year = Greg.get(Calendar.YEAR);
	this_hour = Greg.get(Calendar.HOUR_OF_DAY);
	//System.out.println("  This is the year = "+this_year);
	this_minute = Greg.get(Calendar.MINUTE);
	//System.out.println("  This is the minute = "+this_minute);
	today_month = Greg.get(Calendar.DAY_OF_MONTH);
	//System.out.println("  This is the day_month = "+today_month);
	today_year = Greg.get(Calendar.DAY_OF_YEAR);
	//System.out.println("  This is the day_year = "+today_year);
	this_zone = Greg.get(Calendar.ZONE_OFFSET);
	//System.out.println("  This is the zone_offset = "+this_zone/3600000);
	saving_time = Greg.get(Calendar.DST_OFFSET);
	//System.out.println("  This is the dst_offset = "+saving_time/3600000);

	ignition();
    }
    
    public void ignition(){
	
	angular_frequency = 2.0 * Math.PI * frequency;
	light_velocity = 1.0/(Math.sqrt(epsilon0*epsilon_r*mu0*mu_r));
        	
	b = a / a_to_b_ratio;
	
	//Kc is Cutoff wavenumber, Table 4.2, p.151, Pozar
	Kc = Math.sqrt(Math.pow(mode_number1*Math.PI/a,2.0)+Math.pow(mode_number2*Math.PI/b,2.0));
	
	
	//K Wavenumber of material filling the transmission line or waveguide region, Table 4.2, p.151, Pozar
	K = angular_frequency * Math.sqrt(epsilon0 * mu0 * epsilon_r * mu_r);
	
	
	//Beta is the propagation constant Table 4.2, p.151,  Pozar
	if(K >= Kc){
	    Beta = Math.sqrt(K * K - Kc * Kc);
	    BetaC = ZeroC;
	}
	else {
	    Beta = 0.0;
	    BetaC = new Complex(0.0,Math.sqrt(Kc * Kc - K * K));
	}
	
	//Kz is Beta;
	Kz = Beta;
	
	//Kx, Page 129, Kong
	Kx = 2.0 * Math.PI / a;
	
	//Ky, Page 130, Kong
	Ky = 2.0 * Math.PI / b; 
	
        // MODIFY HERE TO CHANGE REFERENCE PIVOT MODE SPECTRUM DIAGRAM ------------
        // 
	/*
        if(IsTEmode){// uses TE10 as reference
	  minimum_prop_frequency  = 1.0/(2.0 * a * Math.sqrt(epsilon0 * mu0 * epsilon_r * mu_r));
	}
	else{// uses TM11 as reference
	  minimum_prop_frequency =  Math.sqrt(Math.pow(1.0/a,2.0)+Math.pow(1.0/b,2.0))
	  			    /(2.0 * Math.sqrt(epsilon0 * mu0 * epsilon_r * mu_r));
	}
	*/
        
        // use TE20 as reference -  USEFUL TO VISUALIZE THE MONOMODE BANDWIDTH
        minimum_prop_frequency  = 1.0/(a * Math.sqrt(epsilon0 * mu0 * epsilon_r * mu_r));
        
        //----------------------------------------------------------------------
        
	//Equation 4.84, p.144, Pozar
	cut_off_frequency_for_mode = 
		Math.sqrt(Math.pow(mode_number1/a,2.0)+Math.pow(mode_number2/b,2.0))
		/(2.0 * Math.sqrt(epsilon0 * mu0 * epsilon_r * mu_r));
	
	double factorimp;
	factorimp=Math.sqrt(1-Math.pow((cut_off_frequency_for_mode/frequency),2.0));
	impedance_TE=Math.sqrt(mu0*mu_r/(epsilon0*epsilon_r))/factorimp;
	impedance_TM=Math.sqrt(mu0*mu_r/(epsilon0*epsilon_r))*factorimp;
	
	//phase velocity, Equation 4.51, p.136, Pozar
	if(Beta > 0.0){
	    phase_velocity = angular_frequency / Beta;
	}
	else{
	    phase_velocity = 0.0;
	}
	
	//group velocity 
	group_velocity = (light_velocity/phase_velocity)*light_velocity;
	
	//wavelength of the cutoff frequency, Equation 4.53, p.137, Pozar
	cut_off_wavelength = 2.0 * Math.PI/Kc;
	
	//guide_wavelength is the distance between equi-phase planes, Equation 4.52, p.136, Pozar 
	guide_wavelength = 2.0 * Math.PI / Beta;
	
	//maximum number of modes excited
	max_modes_excited_m0 = (int)(2.0*frequency /light_velocity * a)+5;
	max_modes_excited_0n = (int)(2.0*frequency /light_velocity * b)+5;
	/*max_modes_this_m = (int)(Math.sqrt(Math.pow(max_modes_excited_m0,2.0)-
					   Math.pow(mode_number2*a_to_b_ratio,2.0)));
			    
	max_modes_this_n = (int)(Math.sqrt((Math.pow(max_modes_excited_m0,2.0)-
					    Math.pow(mode_number1,2.0))/a_to_b_ratio));
			    
	*/
	//medium impedance
	medium_impedance = Math.sqrt(mu0 * mu_r/(epsilon0 * epsilon_r));
	
	//Table 4.2, page 151, Pozar
	if(IsTEmode){
	    Z = K * medium_impedance / Beta;
	}
	else{
	    Z = Beta * medium_impedance / K;
	}
	//Calculate propagating modes
	int skip1 = max_modes_excited_m0-5;
	int skip2 = max_modes_excited_0n-5;
	int counter_modes =0;
	int i;
	int j;
	double test;
	double vel;
	vel = 1/Math.sqrt(epsilon0 * mu0 * epsilon_r * mu_r);
	
	for(i=1;i<=skip1;i++){
	    for(j=1;j<=skip2;j++){
	    test = 0.5*vel*Math.sqrt(Math.pow(i/a,2.0)+Math.pow(j/b,2.0));
		
		if(test<frequency){
		    counter_modes +=2;
		    //System.out.println(i+"  "+j+"  "+test+"  "+frequency+"   "+counter_modes);
		}
	    }
	}
	TotalModes = counter_modes+skip1+skip2;
	//System.out.println(TotalModes+"  "+skip1+"  "+skip2);
	
    }
    
    public double getPoyntingMagnitude(double x, double y){
	double pmag=0.0;
	double tmp3, tmp4;
	double arg1, arg2;
	
	arg1 = mode_number1*Math.PI*x/a;
	arg2 = mode_number2*Math.PI*y/b;
	
	try{
	    if(IsTEmode){
		tmp4 = angular_frequency * mu0 * mu_r/(Kc*Kc);
		tmp3 = (Beta*mode_number2*mode_number2*Math.PI/(Kc*Kc*b*b))*(Math.cos(arg1)*Math.cos(arg1)*Math.sin(arg2)*Math.sin(arg2))+
		       (Beta*mode_number1*mode_number1*Math.PI/(Kc*Kc*a*a))*(Math.sin(arg1)*Math.sin(arg1)*Math.cos(arg2)*Math.cos(arg2));
		pmag = tmp4 * tmp3;
                //System.out.println("pmag = "+pmag);
	    }
	    else{
		tmp4 = angular_frequency * epsilon0 * epsilon_r/(Kc*Kc);
		tmp3 = (Beta*mode_number1*mode_number1*Math.PI/(Kc*Kc*b*b))*(Math.cos(arg1)*Math.cos(arg1)*Math.sin(arg2)*Math.sin(arg2))+
		       (Beta*mode_number2*mode_number2*Math.PI/(Kc*Kc*a*a))*(Math.sin(arg1)*Math.sin(arg1)*Math.cos(arg2)*Math.cos(arg2));
		pmag = tmp4 * tmp3;
	    }
	}
	catch(Exception ec){
	    pmag = 0.0;
	}
	return pmag;
    }
    
    public double getEFieldX(double x, double y){
	double tmp1;
	double arg1, arg2;
	
	arg1 = mode_number1*Math.PI*x/a;
	arg2 = mode_number2*Math.PI*y/b;
	
	try{
	    if(IsTEmode){
		tmp1 = mode_number2*Math.PI/b*Math.cos(arg1)*Math.sin(arg2); // Ex
	    }
	    else{
		tmp1 = mode_number1*Math.PI/b*Math.cos(arg1)*Math.sin(arg2); // Ex
            }
	}
	catch(Exception ec){
	    tmp1 = 0.0;
	}
	return tmp1;
    }
    
    public double getHFieldX(double x, double y){
	double tmp1;
	double arg1, arg2;
	
	arg1 = mode_number1*Math.PI*x/a;
	arg2 = mode_number2*Math.PI*y/b;
	
	try{
	    if(IsTEmode){
		tmp1 = -mode_number1*Math.PI/b*Math.sin(arg1)*Math.cos(arg2); // Hx                
	    }
	    else{
		tmp1 = -mode_number2*Math.PI/b*Math.sin(arg1)*Math.cos(arg2); // Hx
	    }
	}
	catch(Exception ec){
	    tmp1 = 0.0;
	}
	return tmp1;
    }
    
    public double getEFieldY(double x, double y){
	
	double tmp2;
	double arg1, arg2;
	
	arg1 = mode_number1*Math.PI*x/a;
	arg2 = mode_number2*Math.PI*y/b;
	
	try{
	    if(IsTEmode){
		tmp2 = -mode_number1*Math.PI/a*Math.sin(arg1)*Math.cos(arg2);// Ey                
	    }
	    else{
		tmp2 = -mode_number2*Math.PI/a*Math.sin(arg1)*Math.cos(arg2);// Ey
	    }
	}
	catch(Exception ec){
	    tmp2 = 0.0;
	}
	return tmp2;
    }
    
    public double getHFieldY(double x, double y){
	
	double tmp2;
	double arg1, arg2;
	
	arg1 = mode_number1*Math.PI*x/a;
	arg2 = mode_number2*Math.PI*y/b;
	
	try{
	    if(IsTEmode){
		tmp2 = -mode_number2*Math.PI/a*Math.cos(arg1)*Math.sin(arg2);// Hy                
	    }
	    else{
		tmp2 = +mode_number1*Math.PI/a*Math.cos(arg1)*Math.sin(arg2);// Hy
	    }
	}
	catch(Exception ec){
	    tmp2 = 0.0;
	}
	return tmp2;
    }
    
    public double getEFieldMagnitude(double x, double y){
	double fmag=0.0;
	double tmp1, tmp2;
	double arg1, arg2;
	
	arg1 = mode_number1*Math.PI*x/a;
	arg2 = mode_number2*Math.PI*y/b;
	
	try{
	    if(IsTEmode){
		tmp1 = mode_number2*Math.PI/b*Math.sin(arg2)*Math.cos(arg1); // Ex
		tmp2 = -mode_number1*Math.PI/a*Math.sin(arg1)*Math.cos(arg2);// Ey
                fmag = Math.sqrt(tmp1*tmp1 + tmp2*tmp2);                
	    }
	    else{
		tmp1 = -mode_number2*Math.PI/b*Math.sin(arg1)*Math.cos(arg2); // Hx
		tmp2 = mode_number1*Math.PI/a*Math.sin(arg2)*Math.cos(arg1);// Hy
		fmag = Math.sqrt(tmp1*tmp1 + tmp2*tmp2);
	    }
	}
	catch(Exception ec){
	    fmag = 0.0;
	}
	return fmag;
    }
    
    public double getHFieldMagnitude(double x, double y){
	double fmag=0.0;
	double tmp1, tmp2;
	double arg1, arg2;
	
	arg1 = mode_number1*Math.PI*x/a;
	arg2 = mode_number2*Math.PI*y/b;
	
	try{
	    if(IsTEmode){
		tmp1 = -mode_number2*Math.PI/b*Math.sin(arg2)*Math.cos(arg1); // Ex
		tmp2 = mode_number1*Math.PI/a*Math.sin(arg1)*Math.cos(arg2);// Ey
                fmag = Math.sqrt(tmp1*tmp1 + tmp2*tmp2);                
	    }
	    else{
		tmp1 = mode_number2*Math.PI/b*Math.sin(arg1)*Math.cos(arg2); // Hx
		tmp2 = -mode_number1*Math.PI/a*Math.sin(arg2)*Math.cos(arg1);// Hy
		fmag = Math.sqrt(tmp1*tmp1 + tmp2*tmp2);
	    }
	}
	catch(Exception ec){
	    fmag = 0.0;
	}
	return fmag;
    }
    
    //public int getTotalModes(int x){
	    
    //}
    
}