/* Copyright (C) 2001 Gopal Narayanan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "rectwaveguide.h" /*char *drawing_filename;*/ /*char *image_dir;*/ gboolean widthfixed, heightfixed; /* * get_rectwaveguide_sub * get and assign rectwaveguide substrate parameters * into rectwaveguide structure */ /* * returns k */ gfloat kval (rectwaveguide *rw) { gfloat mur, er, f; gfloat kval; mur = rw->mur; er = rw->er; f = rw->f; kval = 2. * M_PI * f * sqrt(mur * er)/C0; return kval; } /* * given mode numbers m and n * returns cutoff kc value */ gfloat kc (rectwaveguide *rw, int m, int n) { gfloat a, b; gfloat kcval; a = rw->a; b = rw->b; kcval = sqrt(pow((m*M_PI/a),2.0) + pow((n*M_PI/b),2.0)); return kcval; } /* * given mode numbers m and n * returns cutoff fc value */ gfloat fc (rectwaveguide *rw, int m, int n) { gfloat mur, er; gfloat fcval; mur = rw->mur; er = rw->er; fcval = (kc(rw, m, n) * C0)/ (2 * M_PI * sqrt(mur * er)); return fcval; } /* * alphac - returns attenuation due to conductor losses for all propagating * modes in the waveguide */ gfloat alphac (rectwaveguide *rw) { gfloat a, b, sigma, mur, f; gfloat Rs, k, f_c; gfloat ac; short m, n, mmax, nmax; a = rw->a; b = rw->b; mur = rw->mur; sigma = rw->sigma; f = rw->f; Rs = sqrt((M_PI * f * mur* MU0)/sigma); k = kval(rw); ac = 0.0; mmax = (int) floor (f/fc(rw,1,0)); nmax = mmax; /* below from Ramo, Whinnery & Van Duzer */ /* TE(m,n) modes */ for (n = 0; n<= nmax; n++){ for (m = 1; m <= mmax; m++){ f_c = fc(rw, m, n); if (f > f_c) { switch (n) { case 0: ac += (Rs/(b * 120.0 * M_PI * sqrt(1.0 - pow((f_c/f),2.0)))) * (1.0 + ((2 * b/a)*pow((f_c/f),2.0))); break; default: ac += ((2. * Rs)/(b * 120.0 * M_PI * sqrt(1.0 - pow((f_c/f),2.0)))) * (((1. + (b/a))*pow((f_c/f),2.0)) + ((1. - pow((f_c/f),2.0)) * (((b/a)*(((b/a)*pow(m,2.)) + pow(n,2.)))/ (pow((b*m/a),2.0) + pow(n,2.0))))); break; } } } } /* TM(m,n) modes */ for (n = 1; n<= nmax; n++) { for (m = 1; m<= mmax; m++) { f_c = fc(rw, m, n); if (f > f_c) { ac += ((2. * Rs)/(b * 120.0 * M_PI * sqrt(1.0 - pow((f_c/f),2.0)))) * (((pow(m,2.0)*pow((b/a),3.0)) + pow(n,2.))/ ((pow((m*b/a),2.)) + pow(n,2.0))); } } } ac = ac * 20.0 * log10(exp(1.)); /* convert from Np/m to db/m */ return ac; } /* * alphac_cutoff - returns attenuation for a cutoff wg */ gfloat alphac_cutoff (rectwaveguide *rw) { gfloat acc; acc = sqrt(pow(kc(rw,1,0),2.0) - pow(kval(rw),2.0)); acc = 20 * log10(exp(1.0)) * acc; return acc; } /* * returns attenuation due to dielectric losses */ gfloat alphad(rectwaveguide *rw) { gfloat tand; gfloat k, beta; gfloat ad; tand = rw->tand; k = kval(rw); beta = sqrt(pow(k,2.) - pow(kc(rw,1,0),2.0)); ad = (pow(k,2.0) * tand)/(2.0 * beta); ad = ad * 20.0 * log10(exp(1.)); /* convert from Np/m to db/m */ return ad; } void get_rectwaveguide_sub (trans_win *rwin, rectwaveguide *rw) { if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->subparam_text[0])), "%g", &rw->er) != 1) error_mes("Error: rw->er"); if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->subparam_text[1])), "%g", &rw->mur) != 1) error_mes("Error: rw->mur"); if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->subparam_text[2])), "%g", &rw->sigma) != 1) error_mes("Error: rw->sigma"); if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->subparam_text[3])), "%g", &rw->tand) != 1) error_mes("Error: rw->tand"); if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->subparam_text[4])), "%g", &rw->tanm) != 1) error_mes("Error: rw->tanm"); } /* * get_rectwaveguide_comp * get and assign rectwaveguide component parameters * into rectwaveguide structure */ void get_rectwaveguide_comp (trans_win *rwin, rectwaveguide *rw) { short curr_unit; if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->component_param_text[0])), "%g", &rw->f) != 1) error_mes("Error: rw->f"); curr_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->component_param_combo[0])->entry))); rw->f = rw->f * conv_freq[curr_unit][FREQ_HZ]; } /* * get_rectwaveguide_elec * get and assign rectwaveguide electrical parameters * into rectwaveguide structure */ void get_rectwaveguide_elec (trans_win *rwin, rectwaveguide *rw) { short curr_unit; if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->electrical_param_text[0])), "%g", &rw->Z0) != 1) error_mes("Error: rw->Z0"); curr_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->electrical_param_combo[0])->entry))); rw->Z0 = rw->Z0 * conv_res[curr_unit][RES_OHM]; if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->electrical_param_text[1])), "%g", &rw->ang_l) != 1) error_mes("Error: rw->ang_l"); curr_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->electrical_param_combo[1])->entry))); rw->ang_l = rw->ang_l * conv_ang[curr_unit][ANG_RAD]; } /* * get_rectwaveguide_phys * get and assign rectwaveguide physical parameters * into rectwaveguide structure */ void get_rectwaveguide_phys (trans_win *rwin, rectwaveguide *rw) { short curr_unit; if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->physical_param_text[0])), "%g", &rw->a) != 1) error_mes("Error: rw->a"); curr_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->physical_param_combo[0])->entry))); rw->a = rw->a * conv_length[curr_unit][LENGTH_M]; if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->physical_param_text[1])), "%g", &rw->b) != 1) error_mes("Error: rw->b"); curr_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->physical_param_combo[1])->entry))); rw->b = rw->b * conv_length[curr_unit][LENGTH_M]; if (sscanf (gtk_entry_get_text(GTK_ENTRY (rwin->physical_param_text[2])), "%g", &rw->l) != 1) error_mes("Error: rw->l"); curr_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->physical_param_combo[2])->entry))); rw->l = rw->l * conv_length[curr_unit][LENGTH_M]; } /* * analyze_rectwaveguide - analysis function */ void analyze_rectwaveguide (GtkWidget *parent, trans_win *rwin) { gchar *text, *results, *temp; rectwaveguide *rw; short required_unit; gfloat lambda_g; gfloat k; gfloat beta; short m, n, mmax, nmax; gfloat f; gfloat a,b; /*allocate memory for text */ if ((text = (char *) malloc(10*sizeof(char))) == NULL){ perror("text error: malloc"); exit(-1); } /*allocate memory for pointer rw */ if ((rw = g_malloc(sizeof *rw)) != NULL) { /* Get and assign substrate parameters */ get_rectwaveguide_sub(rwin, rw); /* Get and assign component parameters */ get_rectwaveguide_comp(rwin, rw); /* Get and assign physical parameters */ get_rectwaveguide_phys(rwin, rw); f = rw->f; a = rw->a; b = rw->b; k = kval(rw); if (kc(rw,1,0) <= k) { /*propagating modes */ beta = sqrt(pow(k,2.) - pow(kc(rw,1,0),2.0)); lambda_g = (2. * M_PI)/beta; /* rw->Z0 = (k * 120. * M_PI)/beta; */ rw->Z0 = 2.0 * 120.0 * M_PI * (b/a) * 1/ sqrt(1.0 - pow((fc(rw,1,0)/f),2.0)); /* calculate electrical angle */ lambda_g = (2. * M_PI)/beta; rw->ang_l = (2.0 * M_PI * rw->l)/lambda_g; /* in radians */ rw->atten_cond = alphac (rw) * rw->l; rw->atten_dielectric = alphad (rw) * rw->l; rw->er_eff = (1.0 - pow((fc(rw,1,0)/rw->f),2.0)); } else { /*evanascent modes */ rw->Z0 = 0; rw->ang_l = 0; rw->er_eff = 0; rw->atten_dielectric = 0.0; rw->atten_cond = alphac_cutoff (rw) * rw->l; } required_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->electrical_param_combo[0])->entry))); sprintf(text,"%g", (float) (rw->Z0 * conv_res[RES_OHM][required_unit])); gtk_entry_set_text (GTK_ENTRY (rwin->electrical_param_text[0]), text); required_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->electrical_param_combo[1])->entry))); sprintf(text,"%g", (float) (rw->ang_l * conv_ang[ANG_RAD][required_unit])); gtk_entry_set_text (GTK_ENTRY (rwin->electrical_param_text[1]), text); free(text); if ((text = (char *) malloc(1000*sizeof(char))) == NULL){ perror("results text error: malloc"); exit(-1); } if ((results = (char *) malloc(1000*sizeof(char))) == NULL){ perror("results text error: malloc"); exit(-1); } if ((temp = (char *) malloc(1000*sizeof(char))) == NULL){ perror("results text error: malloc"); exit(-1); } sprintf(results, "\nEffective dielectic constant, er_eff = %.4g\n", rw->er_eff); required_unit = getunit(gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (rwin->physical_param_combo[2])->entry))); sprintf(text,"Conductor Losses = %.4g dB\n", rw->atten_cond); strcat(results,text); sprintf(text, "Dielectric Losses = %.4g dB\n", rw->atten_dielectric); strcat(results, text); if (f >= (2.*fc(rw,1,0))) { /* multiple modes possible in waveguide */ strcpy(text, "\nWarning: The following additional \nTE modes can propagate:\n"); strcat(results, text); /* mmax = floor(f/fc(rw,1,0));*/ mmax = 5; nmax = mmax; strcpy(text, " "); for (m = 2; m<= mmax; m++) { for (n=0; n<= nmax; n++) { if (f >= (fc(rw,m,n))){ sprintf(temp,"TE(%u,%u) ",m, n); strcat(text,temp); } } } strcat(results,text); strcat(results,"\n"); } if (f >= fc(rw,1,1)){ /*TM(1,1) mode possible*/ strcpy(text, "\nWarning: The following additional \nTM modes can propagate:\n"); strcat(results, text); /* mmax = floor(f/fc(rw,1,1));*/ mmax = 5; nmax = mmax; strcpy(text, " "); for (m = 1; m<= mmax; m++) { for (n=1; n<= nmax; n++) { if (f >= (fc(rw,m,n))){ sprintf(temp,"TM(%u,%u) ",m, n); strcat(text,temp); } } } strcat(results,text); strcat(results,"\n"); } gtk_label_set (GTK_LABEL (rwin->results_text), results); free(results); free(text); free(temp); if (statusexists){ if (statusint != CONSISTENT) { gtk_label_set_text (GTK_LABEL (rwin->status), "Values are consistent"); } } statusint = CONSISTENT; } else { perror("malloc rw"); exit(-1); } } /* * synthesize_rectwaveguide - synthesis function */ void synthesize_rectwaveguide (GtkWidget *parent, trans_win *rwin) { gchar *text, *results, *temp; rectwaveguide *rw; short required_unit; gfloat lambda_g; gfloat a, b, f; gfloat Z0; gfloat beta, k; short m, n, mmax, nmax; /*allocate memory for text */ if ((text = (char *) malloc(10*sizeof(char))) == NULL){ perror("text error: malloc"); exit(-1); } /*allocate memory for pointer rw */ if ((rw = g_malloc(sizeof *rw)) != NULL) { /* Get and assign substrate parameters */ get_rectwaveguide_sub(rwin, rw); /* Get and assign component parameters */ get_rectwaveguide_comp(rwin, rw); /* Get and assign electrical parameters */ get_rectwaveguide_elec(rwin, rw); /* Get and assign physical parameters */ get_rectwaveguide_phys(rwin, rw); f = rw->f; a = rw->a; b = rw->b; Z0 = rw->Z0; if (widthfixed) { /* solve for b */ rw->b = Z0 * a * sqrt(1.0 - pow((fc(rw,1,0)/f),2.0))/ (2. * 120. * M_PI); required_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->physical_param_combo[1])->entry))); sprintf(text,"%g", (float) (rw->b * conv_length[LENGTH_M][required_unit])); gtk_entry_set_text (GTK_ENTRY (rwin->physical_param_text[1]), text); } else { /* solve for a */ rw->a = sqrt(pow((2.0 * 120. * M_PI * b/Z0), 2.0) + pow((C0/(2.0 * f)),2.0)); required_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->physical_param_combo[0])->entry))); sprintf(text,"%g", (float) (rw->a * conv_length[LENGTH_M][required_unit])); gtk_entry_set_text (GTK_ENTRY (rwin->physical_param_text[0]), text); } k = kval (rw); beta = sqrt(pow(k,2.) - pow(kc(rw,1,0),2.0)); lambda_g = (2. * M_PI)/beta; rw->l = (rw->ang_l * lambda_g)/(2.0 * M_PI); /* in m */ required_unit = getunit (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(rwin->physical_param_combo[2])->entry))); sprintf(text,"%g", (float) (rw->l * conv_length[LENGTH_M][required_unit])); gtk_entry_set_text (GTK_ENTRY (rwin->physical_param_text[2]), text); if (kc(rw,1,0) <= k) { /*propagating modes */ beta = sqrt(pow(k,2.) - pow(kc(rw,1,0),2.0)); lambda_g = (2. * M_PI)/beta; rw->atten_cond = alphac (rw) * rw->l; rw->atten_dielectric = alphad (rw) * rw->l; rw->er_eff = (1.0 - pow((fc(rw,1,0)/rw->f),2.0)); } else { /*evanascent modes */ rw->Z0 = 0; rw->ang_l = 0; rw->er_eff = 0; rw->atten_dielectric = 0.0; rw->atten_cond = alphac_cutoff (rw) * rw->l; } free(text); if ((text = (char *) malloc(500*sizeof(char))) == NULL){ perror("results text error: malloc"); exit(-1); } if ((results = (char *) malloc(500*sizeof(char))) == NULL){ perror("results text error: malloc"); exit(-1); } if ((temp = (char *) malloc(1000*sizeof(char))) == NULL){ perror("results text error: malloc"); exit(-1); } sprintf(results, "\nEffective dielectic constant, er_eff = %.4g\n", rw->er_eff); required_unit = getunit(gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (rwin->physical_param_combo[2])->entry))); sprintf(text,"Conductor Losses = %.4g dB\n", rw->atten_cond); strcat(results,text); sprintf(text, "Dielectric Losses = %.4g dB\n", rw->atten_dielectric); strcat(results, text); if (f >= (2.*fc(rw,1,0))) { /* multiple modes possible in waveguide */ strcpy(text, "\nWarning: The following additional \nTE modes can propagate:\n"); strcat(results, text); /* mmax = floor(f/fc(rw,1,0));*/ mmax = 5; nmax = mmax; strcpy(text, " "); for (m = 2; m<= mmax; m++) { for (n=0; n<= nmax; n++) { if (f >= (fc(rw,m,n))){ sprintf(temp,"TE(%u,%u) ",m, n); strcat(text,temp); } } } strcat(results,text); strcat(results,"\n"); } if (f >= fc(rw,1,1)){ /*TM(1,1) mode possible*/ strcpy(text, "\nWarning: The following additional \nTM modes can propagate:\n"); strcat(results, text); /* mmax = floor(f/fc(rw,1,1));*/ mmax = 5; nmax = mmax; strcpy(text, " "); for (m = 1; m<= mmax; m++) { for (n=1; n<= nmax; n++) { if (f >= (fc(rw,m,n))){ sprintf(temp,"TM(%u,%u) ",m, n); strcat(text,temp); } } } strcat(results,text); strcat(results,"\n"); } gtk_label_set (GTK_LABEL (rwin->results_text), results); free(results); free(text); free(temp); if (statusexists){ if (statusint != CONSISTENT) { gtk_label_set_text (GTK_LABEL (rwin->status), "Values are consistent"); } } statusint = CONSISTENT; } else { perror("malloc rw"); exit(-1); } } void fixwidth (GtkWidget *parent, trans_win *rwin) { gtk_label_set_text (GTK_LABEL (GTK_BIN (parent)->child), "Fixed"); gtk_widget_set_sensitive (GTK_WIDGET (parent), FALSE); gtk_label_set_text (GTK_LABEL (GTK_BIN (rwin->physical_param_fix[1])->child), "Fix"); gtk_widget_set_sensitive (GTK_WIDGET (rwin->physical_param_fix[1]), TRUE); widthfixed = TRUE; heightfixed = FALSE; } void fixheight (GtkWidget *parent, trans_win *rwin) { gtk_label_set_text (GTK_LABEL (GTK_BIN (parent)->child), "Fixed"); gtk_widget_set_sensitive (GTK_WIDGET (parent), FALSE); gtk_label_set_text (GTK_LABEL (GTK_BIN (rwin->physical_param_fix[0])->child), "Fix"); gtk_widget_set_sensitive (GTK_WIDGET (rwin->physical_param_fix[0]), TRUE); widthfixed = FALSE; heightfixed = TRUE; } /* * the window aspect */ void rectwaveguide_win (GtkWidget *parent) /*rectwaveguide_win (trans_gui *tg)*/ { short row; /* if there is a window that already exists kill it first */ if (main_body_window != NULL) { gtk_widget_destroy(main_body_window); g_free (twin); twin = g_malloc(sizeof(*twin)); } setup_transgui(RECTWAVEGUIDE, parent, twin); gtk_label_set_text (GTK_LABEL (GTK_BIN (twin->physical_param_fix[0])->child), "Fixed"); gtk_widget_set_sensitive (GTK_WIDGET (twin->physical_param_fix[0]), FALSE); widthfixed = TRUE; heightfixed = FALSE; for (row = 0; row<=1; row++) { switch(row) { case 0: gtk_signal_connect (GTK_OBJECT (twin->physical_param_fix[row]), "clicked", GTK_SIGNAL_FUNC (fixwidth), twin); break; case 1: gtk_signal_connect (GTK_OBJECT (twin->physical_param_fix[row]), "clicked", GTK_SIGNAL_FUNC (fixheight), twin); break; } } gtk_signal_connect (GTK_OBJECT (twin->Analbutton), "clicked", GTK_SIGNAL_FUNC (analyze_rectwaveguide), twin); gtk_signal_connect (GTK_OBJECT (twin->Synbutton), "clicked", GTK_SIGNAL_FUNC (synthesize_rectwaveguide), twin); if (statusint == INCONSISTENT) { analyze_rectwaveguide(parent, (trans_win *) twin); } for (row = 0; row<=1; row++){ gtk_signal_connect (GTK_OBJECT (twin->electrical_param_text[row]), "changed", GTK_SIGNAL_FUNC (setstatus), twin); } }