//NewGuide_State.java
/*
 * State routine - calculate/update numerical values for microstrip
 * authors: Umberto Ravaioli
 * version 1.0 - Copyright: Amanogawa.com - All Rights Reserved
 */

import java.io.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.net.URL;
import java.text.*;
import java.util.*;
import java.util.Map;
import java.util.Hashtable;
import java.util.jar.Attributes;

public class NewGuide_State {
    public double a, b, w, a_mil, b_mil, w_mil; // waveguide dimensions
    public double a_minimum, a_maximum, a_mil_minimum, a_mil_maximum;
    public double epsilon_r, epsilon_r0, epsilon_eff, epsilon_eff_f;
    public double epsilon_eff_fmax, epsilon_eff_fmin;
    public double mu_r, mu_r0, lambda_0; 
    public double sigma2, sigma_metal, rho_metal, Resistance, P_factor, Q_factor, Q_rad, F_rad;
    public double alpha_d, alpha_c, alpha_c2, alpha_r, loss_tangent, skin_depth;
    public double frequency, frequency_t, frequency_c, frequency_surf;
    public double frequency_minimum, frequency_maximum;
    public double angular_frequency;
    public double guide_wavelength0, guide_wavelength;
    public double minimum_prop_frequency, cut_off_frequency_for_mode;
    public double b_minimum, b_maximum, b_mil_minimum, b_mil_maximum, maximum_h;
    public double w_minimum, w_maximum, w_mil_minimum, w_mil_maximum;
    public double delta_frequency, delta_geometry;
    public double phase_velocity, phase_velocity0, light_velocity, light_velocity0;
    public double K;
    public Complex ZeroC;
    public double ratio, ratio_eff, compratio;
    public double Z0_0, Z0, medium_impedance, Z0_max, Z0_min, Z0g_max, Z0g_min;
    public double x[], F_array[], G_array[];
    public double x_freq[], x_geom[];
    public int	 x_safe[];
    public boolean IsImpedanceOn;
    public boolean IsWarningOn1;
    public boolean IsWarningOn2;
    public boolean IsSafetyOn;
    public boolean IsPrintSafetyOn;
    public boolean IsMilsOn;
    public boolean OptionOne, OptionTwo, OptionThree, OptionFour;
    
    public static final double mil_factor = 0.0254; // 1 mil = 0.0254 mm
    //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; //8.8541878176E-12; //Units: F/m 

    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 Font ttfFont, sanSerifFont, serifFont, symbolFont;

    
    public NewGuide_State(){
	
	a = 0.635; // mm
	a_minimum = 0.0;//
	a_maximum = 2.0;// 2.0 mm
	
	b = 0.005; //mm
	b_minimum = 0.0;
	b_maximum = 0.01;
	
	w = 0.6;
	w_minimum = 0.0;
	w_maximum = 5.0;
	
	a_mil = a/mil_factor;
	a_mil_minimum = a_minimum/mil_factor;
	a_mil_maximum = a_maximum/mil_factor;
	
	b_mil = b/mil_factor;
	b_mil_minimum = b_minimum/mil_factor;
	b_mil_maximum = b_maximum/mil_factor;
	
	w_mil = w/mil_factor;
	w_mil_minimum = w_minimum/mil_factor;
	w_mil_maximum = w_maximum/mil_factor;
	
	epsilon_r = 9.8;
	epsilon_r0 = 1.0;
	mu_r = 1.0;
	mu_r0 = 1.0;
	
	//loss_tangent = 0.0001;
        rho_metal = 1.725e-8;
	sigma_metal = 5.8e7;
	sigma2 = 0.0;
	
	frequency = 1.0E9;
	frequency_minimum = 0.0;
	frequency_maximum = 20.0E9;
	angular_frequency = 2.0 * Math.PI * frequency;
	loss_tangent = sigma2/(angular_frequency*epsilon_r*epsilon0);
	//sigma2 = loss_tangent * (angular_frequency*epsilon_r*epsilon0);
	skin_depth = 1.0/Math.sqrt(Math.PI*frequency*mu0*sigma_metal);
	
	delta_frequency = (frequency_maximum - frequency_minimum)/10000;
	delta_geometry = (w_maximum - w_minimum)/10000;
	
	Z0 = 50.0;
	
	lambda_0 = 1.0/Math.sqrt(epsilon0*mu0)/frequency;
	
	ZeroC = new Complex(0.0,0.0);
	
	IsImpedanceOn = true;
	IsWarningOn1 = false;
	IsWarningOn2 = false;
	IsSafetyOn = false;
	IsMilsOn = false;
	IsPrintSafetyOn = false;
        
        OptionOne = true;
        OptionTwo = false;
        OptionThree = false;
        OptionFour = false;
	
        // Set up calendar - used for checking today's date
        // compared with date from line.java in Microstrip.java 
	this_month = Greg.get(Calendar.MONTH);
	today_week = Greg.get(Calendar.DAY_OF_WEEK);
	this_year = Greg.get(Calendar.YEAR);
	this_hour = Greg.get(Calendar.HOUR_OF_DAY);
	this_minute = Greg.get(Calendar.MINUTE);
	today_month = Greg.get(Calendar.DAY_OF_MONTH);
	today_year = Greg.get(Calendar.DAY_OF_YEAR);
	this_zone = Greg.get(Calendar.ZONE_OFFSET);
	saving_time = Greg.get(Calendar.DST_OFFSET);
	
	ignition();
	scan_coefficients();

    }
    
    public void ignition(){
	IsWarningOn1 = false;
	IsWarningOn1 = false;
	IsSafetyOn = false;
	IsPrintSafetyOn = false;
	
        sigma_metal = 1.0/rho_metal;
        
        /*
        if(sigma_metal <= 1.0E3){
            sigma_metal = MaestroA.rounder(sigma_metal,4);
        }
        else if(sigma_metal > 1.0E3 && sigma_metal <= 10E6){
            sigma_metal = MaestroA.rounder(sigma_metal,8);
        }
        else if(sigma_metal > 1.0E6 && sigma_metal <= 10E9){
            sigma_metal = MaestroA.rounder(sigma_metal,12);
        }
         */
                
	angular_frequency = 2.0 * Math.PI * frequency;
	light_velocity = 1.0/(Math.sqrt(epsilon0*epsilon_r*mu0*mu_r));
	light_velocity0 = 1.0/(Math.sqrt(epsilon0*epsilon_r0*mu0*mu_r0));
	lambda_0 = light_velocity0/frequency;
	
	if(!IsMilsOn){
	    a_mil = a/mil_factor;
	    a_mil_minimum = a_minimum/mil_factor;
	    a_mil_maximum = a_maximum/mil_factor;
	
	    b_mil = b/mil_factor;
	    b_mil_minimum = b_minimum/mil_factor;
	    b_mil_maximum = b_maximum/mil_factor;
	
	    w_mil = w/mil_factor;
	    w_mil_minimum = w_minimum/mil_factor;
	    w_mil_maximum = w_maximum/mil_factor;
	}
	if(IsMilsOn){
	    a = a_mil*mil_factor;
	    a_minimum = a_mil_minimum*mil_factor;
	    a_maximum = a_mil_maximum*mil_factor;
	
	    b = b_mil*mil_factor;
	    b_minimum = b_mil_minimum*mil_factor;
	    b_maximum = b_mil_maximum*mil_factor;
	
	    w = w_mil*mil_factor;
	    w_minimum = w_mil_minimum*mil_factor;
	    w_maximum = w_mil_maximum*mil_factor;
	}
	

	// Wavenumber of material filling the transmission line or waveguide region
	K = angular_frequency * Math.sqrt(epsilon0 * mu0 * epsilon_r * mu_r);
	
	//medium impedance
	medium_impedance = Math.sqrt(mu0 * mu_r/(epsilon0 * epsilon_r));
	ratio = w/a;
	compratio = 1.0/(2.0*Math.PI);
	delta_frequency = (frequency_maximum - frequency_minimum)/10000;
	delta_geometry = (w_maximum - w_minimum)/10000;
	//sigma2 = loss_tangent * (angular_frequency*epsilon_r*epsilon0);
	
	loss_tangent = sigma2/(angular_frequency*epsilon_r*epsilon0);
	skin_depth = 1.0/Math.sqrt(Math.PI*frequency*mu0*sigma_metal);
	
	if(b>=a && b>0.0){IsWarningOn1 = true;}else{IsWarningOn1 = false;}
	if(b>=(0.5*w) && b>0.0){IsWarningOn2 =true;}else{IsWarningOn2 = false;}
	
	int flag = 0;
	int flag2 = 0;
	
	if(ratio >= compratio){
	    if(b > 0.0){
	      
		ratio_eff = ratio + (1.25/Math.PI)*(b/a)*(1.0+Math.log(2.0*a/b));
	       
	    }
	    else{
		ratio_eff = ratio;
	    }
	    flag = 1;
	}
	else{
	    if(b > 0.0){
		ratio_eff = ratio + (1.25/Math.PI)*(b/a)*(1.0+Math.log(4.0*Math.PI*(w/b)));
	    }
	    else{
		ratio_eff = ratio;
	    }
	    flag = 2;
	}
	
	if(w == 0.0 && b > 0.0){ ratio = 0.0; ratio_eff = 0.0;}
	
	//if(ratio_eff < 0.0){IsWarningOn = true;}
	
	if(ratio_eff <= 1.0){
		//epsilon_eff = 0.5*(epsilon_r + 1.0) 
		  //  + 0.5*(epsilon_r - 1.0) * ( 1.0/Math.sqrt(1.0 + 12.0/ratio_eff) + 0.04*Math.pow((1.0 - ratio_eff),2));
		epsilon_eff = 0.5*(epsilon_r + 1.0) 
		    + 0.5*(epsilon_r - 1.0) * ( 1.0/Math.sqrt(1.0 + 12.0/ratio_eff) + 0.04*Math.pow((1.0 - ratio_eff),2));
		Z0_0 = 60.0/Math.sqrt(epsilon_eff)*Math.log(8.0/ratio_eff + 0.25*ratio_eff);
		flag2 = 1;
	}
	else{
		epsilon_eff = 0.5*(epsilon_r + 1.0) 
		    + 0.5*(epsilon_r - 1.0) * ( 1.0/Math.sqrt(1.0 + 12.0/ratio_eff) );
		
		Z0_0 = 120.0*Math.PI/(Math.sqrt(epsilon_eff)*(ratio_eff + 1.393+0.667*Math.log(ratio_eff + 1.444)));
		flag2 = 2;	  
	}
	
	if(a == 0.0 && w == 0.0){ 
	    epsilon_eff = 1.0;
	    Z0_0 = 0.0;
	}
	frequency_c = 0.3*1.0E9*Math.sqrt(10.0*Z0_0/(a*Math.sqrt(epsilon_r - 1.0)));
	
	frequency_t = Z0_0/(2.0*mu0*a/1000.0);//convert from [mm] to [m] !!!
	
	frequency_surf = 1.0E9*150.0* Math.atan(epsilon_r)*Math.sqrt(2)/
			(Math.PI*a*Math.sqrt(epsilon_r-1.0));
			
	maximum_h = 1.0E9*150.0* Math.atan(epsilon_r)*Math.sqrt(2)/
			(Math.PI*frequency*Math.sqrt(epsilon_r-1.0));
	
	if(a == 0.0 && w == 0.0){
	    epsilon_eff_f = epsilon_eff;
	}
	else{
	    epsilon_eff_f = epsilon_r-((epsilon_r-epsilon_eff)/(1+(epsilon_eff/epsilon_r)
					*Math.pow(frequency/frequency_t,2)));
	}
	
	Z0 = Z0_0 * Math.sqrt(epsilon_eff/epsilon_eff_f);
	
	phase_velocity = 1.0/Math.sqrt(epsilon0*epsilon_eff_f*mu_r*mu0);
	phase_velocity0 = 1.0/Math.sqrt(epsilon0*epsilon_eff*mu_r*mu0);
	guide_wavelength = phase_velocity/frequency;
	guide_wavelength0 = phase_velocity0/frequency;
	
	epsilon_eff_fmax = epsilon_r-((epsilon_r-epsilon_eff)/(1+(epsilon_eff/epsilon_r)
					*Math.pow(frequency_maximum/frequency_t,2)));
	epsilon_eff_fmin = epsilon_r-((epsilon_r-epsilon_eff)/(1+(epsilon_eff/epsilon_r)
					*Math.pow(frequency_minimum/frequency_t,2)));
	
	if(IsImpedanceOn){
	    Z0_min = (double)((int)(Z0_0 * Math.sqrt(epsilon_eff/epsilon_eff_fmax)))-1.0;
	
	    if(Z0_min < 0.0){Z0_min = 0.0;}
	    if(w == 0.0){Z0_min = 0.0;}
	
	    //Z0_max = (double)((int)Z0_0)+1.0;
	    Z0_max = (double)((int)(Z0_0 * Math.sqrt(epsilon_eff/epsilon_eff_fmin)))+1.0;
	}
	else{
	
	    Z0_min = (double)((int)epsilon_eff);
	    Z0_max = (double)((int)epsilon_eff_fmax)+1.0;
	    
	}
	
	Resistance = Math.sqrt(Math.PI*frequency*mu0/sigma_metal);
	P_factor = 1.0 - Math.pow((ratio_eff*0.25),2);
	Q_factor = 1.0 + 1.0/ratio_eff + 1.0/(Math.PI*ratio_eff)*(Math.log(2*a/b)-b/a);
      
      double A_factor, B_factor;
      B_factor = 0.0; alpha_c2 = 0.0;
      if(ratio_eff>compratio){
	    B_factor = a*0.001; 
      }
      else if(ratio_eff<=compratio){
	    B_factor = 2*Math.PI*w*0.001;
      }   
      A_factor = 1.0+1.0/ratio_eff*(1.0 + 1.0/Math.PI *Math.log(2.0*B_factor/(b*0.001)));
      
      //Conductor loss - attenuation constant (db/m)
      if(b == 0.0 ){
	alpha_c = 0.0;
      }
      else if(a == 0.0 || w == 0.0){
	alpha_c = 0.0;
      }
      
      else{
	
	if(ratio_eff >=2.0 && a > 0.0){
	    alpha_c = 8.68*Resistance*Q_factor/(Z0_0*a*0.001)/Math.pow((ratio_eff+
		2.0/Math.PI*Math.log(2.0*Math.PI*(ratio_eff*0.5+0.94))),2)*
		(ratio_eff+ratio_eff/Math.PI/(ratio_eff*0.5+0.94));
	}
	else if(ratio_eff > compratio && ratio_eff <= 2.0 && a > 0.0){
	    alpha_c = 8.68*Resistance*Q_factor*P_factor/(2.0*Math.PI*Z0_0*a*0.001);
	}
	else if(ratio_eff <= compratio && a > 0.0){
	    alpha_c = 8.68*Resistance*P_factor/(2.0*Math.PI*Z0_0*a*0.001)*
		(1.0 + 1.0/ratio_eff + 1.0/(Math.PI*ratio_eff)*(Math.log(4.0*Math.PI*w/b)-b/w));
	}
      }
      if(ratio_eff < 0.0){IsPrintSafetyOn = true;}
      
	
      //Dielectric loss - attenuation constant (db/m)
	alpha_d = 4.34*Math.sqrt(mu0/epsilon0)*sigma2*(epsilon_eff - 1.0)/
						(Math.sqrt(epsilon_eff)*(epsilon_r - 1.0));
	double alpha2_d = 27.3*epsilon_r/(epsilon_r-1.0)*(epsilon_eff-1.0)/Math.sqrt(epsilon_eff)*
		  loss_tangent/lambda_0;  
      
      //Radiation loss - attenuation constant (db/m)
	F_rad = (epsilon_eff_f+1.0)/epsilon_eff_f - 
		Math.pow((epsilon_eff_f-1.0),2)/(2*Math.pow(epsilon_eff_f,2.0/3.0))*
		Math.log((Math.sqrt(epsilon_eff_f)+1.0)/(Math.sqrt(epsilon_eff_f)-1.0));				
	Q_rad = Z0_0*lambda_0/(480.0*Math.PI*F_rad*0.001*a);
	alpha_r = 8.686*Math.PI/(Q_rad*guide_wavelength);
	
    }
    
// Calculates arrays for plots    
public void scan_coefficients(){
	x = new double[10001];
	x_freq = new double[10001];
	x_geom = new double[10001];
	x_safe = new int[10001];
	F_array = new double[10001];
	G_array = new double[10001];
	
	double temp_eff;
	
	for(int i=0;i<10001;i++){
	    x_freq[i] = frequency_minimum+(double)i*delta_frequency;
	    x_geom[i] = w_minimum+(double)i*delta_geometry;
	}
	
	for(int i = 0; i<10001; i++){
	    temp_eff = epsilon_r-((epsilon_r-epsilon_eff)/(1+(epsilon_eff/epsilon_r)*Math.pow(x_freq[i]/frequency_t,2)));
	    x[i] = x_freq[i];
	    
	    if(IsImpedanceOn){
		F_array[i] = Z0_0 * Math.sqrt(epsilon_eff/temp_eff); 
	    }
	    else{
		F_array[i] = temp_eff; 
	    }
	}
	
	for(int i = 0; i<10001; i++){
	  
	    double tratio, compratio, tratio_eff, tepsilon_eff, tZ0_0, f_t;
	    tratio = x_geom[i]/a;
	    compratio = 1.0/(2.0*Math.PI);
	    if(tratio >= compratio){
		if(b > 0.0){
			tratio_eff = tratio + (1.25/Math.PI)*(b/a)*(1.0+Math.log(2.0*a/b));
	        }
		else{
		    tratio_eff = tratio;
		}
	    }
	    else{
		if(b > 0.0){
		    tratio_eff = tratio + (1.25/Math.PI)*(b/a)*
				(1.0+Math.log(4.0*Math.PI*(x_geom[i]/b)));
		}
		else{
		    tratio_eff = tratio;
		}
	    }
	    if(x_geom[i] == 0.0 && b > 0.0){tratio = 0.0; tratio_eff = 0.0;}
	    
	    if(tratio_eff <0.0 ){
		IsSafetyOn = true;
		 x_safe[i]=1;
	    }
	    else{
		x_safe[i] = 0;
	    }
	    
	    
	    if(tratio_eff <= 1.0){
		tepsilon_eff = 0.5*(epsilon_r + 1.0) + 0.5*(epsilon_r - 1.0) * 
			    ( 1.0/Math.sqrt(1.0 + 12.0/tratio_eff) + 0.04*Math.pow((1.0 - tratio_eff),2));
		tZ0_0 = 60.0/Math.sqrt(tepsilon_eff)*Math.log(8.0/tratio_eff + 0.25*tratio_eff);
	    }
	    else{
		tepsilon_eff = 0.5*(epsilon_r + 1.0) 
		    + 0.5*(epsilon_r - 1.0) * ( 1.0/Math.sqrt(1.0 + 12.0/tratio_eff) );
		
		tZ0_0 = 120.0*Math.PI/(Math.sqrt(tepsilon_eff)*
		     (tratio_eff + 1.393+0.667*Math.log(tratio_eff + 1.444)));  
	    }
	
	    if(a == 0.0 && x_geom[i] == 0.0){ 
		tepsilon_eff = 1.0;
		tZ0_0 = 0.0;
	    }
	
	    f_t = tZ0_0/(2.0*mu0*a/1000);//convert from [mm] to [m] !!!
	
	    if(a == 0.0 && x_geom[i] == 0.0){
		temp_eff = tepsilon_eff;
	    }
	    else{
		temp_eff = epsilon_r-((epsilon_r-tepsilon_eff)/(1+(tepsilon_eff/epsilon_r)
					*Math.pow(frequency/f_t,2)));
	    }
	
	    
	    x[i] = x_geom[i];
	    
	    if(IsImpedanceOn){
		G_array[i] = tZ0_0 * Math.sqrt(tepsilon_eff/temp_eff); 
	    }
	    else{
		G_array[i] = temp_eff; 
	    }
	}
	int imax=-1;
	for(int i = 0; i<10001; i++){
	   if(x_safe[i] == 1){
		imax = i;
	   }
	}
	
	if(IsImpedanceOn){
	    
	   if(IsSafetyOn){
		for(int i = 0; i<imax+1; i++){
		    G_array[i]=G_array[10000];
		}
		Z0g_max = (double)((int)G_array[imax+1])+1;
	    }
	    else{
		if(w_minimum == 0.0){
		    G_array[0] = G_array[1];
		    Z0g_max = (double)((int)G_array[1])+1;
		}
	        else{
		    Z0g_max = (double)((int)G_array[0])+1;
		}
	    }
	    Z0g_min = (double)((int)G_array[10000])-1;
	}
	else{
	    Z0g_max = (double)((int)G_array[10000])+1;
	    if(IsSafetyOn){
		for(int i = 0; i<imax+1; i++){
		//for(int i = 1; i<imax+1; i++){
		    G_array[i]=G_array[imax+1];
		}
		Z0g_min = 1.0;
	    }
	    else{
		Z0g_min = 1.0;
	    }
	}
	
    }
  }
    
    
