Qucs-core  0.0.19
touchstone_producer.cpp
Go to the documentation of this file.
00001 /*
00002  * touchstone_producer.cpp - the Touchstone data file producer
00003  *
00004  * Copyright (C) 2007 Stefan Jahn <stefan@lkcc.org>
00005  *
00006  * This is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this package; see the file COPYING.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  * $Id$
00022  *
00023  */
00024 
00025 #if HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <time.h>
00032 #include <ctype.h>
00033 #include <string.h>
00034 
00035 #include "touchstone_producer.h"
00036 #include "matrix.h"
00037 #include "matvec.h"
00038 #include "constants.h"
00039 
00040 using namespace qucs;
00041 
00042 /* Global variables. */
00043 /* dataset * qucs_data = NULL;   -- already defined in CSV producer */
00044 /* FILE * touchstone_out = NULL; -- already defined in Touchstone lexer */
00045 
00046 struct touchstone_data_t {
00047   char parameter;      // type of variable
00048   int ports;           // number of S-parameter ports
00049   double resistance;   // reference impedance
00050   const char * format; // data format
00051   qucs::vector * vd;         // appropriate dependency vector
00052   matvec * mv;         // appropriate data matrix vector
00053   qucs::vector * fmin;       // minimum noise figure
00054   qucs::vector * sopt;       // optimum input refelction for minimum noise figure
00055   qucs::vector * rn;         // effective noise resistance
00056   qucs::vector * vf;         // dependency vector for noise
00057 }
00058 touchstone_data;
00059 
00060 /* Definition of line separator. */
00061 #ifdef __MINGW32__
00062 #define touchstone_crlf "\n"
00063 #else
00064 #define touchstone_crlf "\r\n"
00065 #endif
00066 
00067 /* The Touchstone noise data printer. */
00068 void touchstone_print_noise (void) {
00069   if (touchstone_data.vf != NULL && touchstone_data.sopt != NULL &&
00070       touchstone_data.rn != NULL && touchstone_data.fmin != NULL) {
00071     // blank line separator
00072     fprintf (touchstone_out, touchstone_crlf);
00073     // noise data
00074     for (int i = 0; i < touchstone_data.vf->getSize (); i++) {
00075       nr_double_t f = real (touchstone_data.vf->get (i));
00076       fprintf (touchstone_out, "%." "20" "e"
00077                " %+." "20" "e"
00078                " %+." "20" "e" " %+." "20" "e"
00079                " %+." "20" "e"
00080                touchstone_crlf, f,
00081                10.0 * std::log10 (real (touchstone_data.fmin->get (i))),
00082                abs (touchstone_data.sopt->get (i)),
00083                rad2deg (arg (touchstone_data.sopt->get (i))),
00084                real (touchstone_data.rn->get (i)) /
00085                touchstone_data.resistance);
00086     }
00087   }
00088 }
00089 
00090 /* The Touchstone data printer. */
00091 void touchstone_print (void) {
00092   // header line
00093   fprintf (touchstone_out, "# %s %c %s R %g" touchstone_crlf,
00094            "HZ", touchstone_data.parameter, touchstone_data.format,
00095            touchstone_data.resistance);
00096   // one-port file
00097   if (touchstone_data.ports == 1) {
00098     for (int i = 0; i < touchstone_data.vd->getSize (); i++) {
00099       matrix S = touchstone_data.mv->get (i);
00100       nr_double_t f = real (touchstone_data.vd->get (i));
00101       fprintf (touchstone_out, "%." "20" "e"
00102                " %+." "20" "e" " %+." "20" "e"
00103                touchstone_crlf, f, real (S(0,0)), imag (S(0,0)));
00104     }
00105   }
00106   // two-port file
00107   else if (touchstone_data.ports == 2) {
00108     for (int i = 0; i < touchstone_data.vd->getSize (); i++) {
00109       matrix S = touchstone_data.mv->get (i);
00110       nr_double_t f = real (touchstone_data.vd->get (i));
00111       fprintf (touchstone_out, "%." "20" "e"
00112                " %+." "20" "e" " %+." "20" "e"
00113                " %+." "20" "e" " %+." "20" "e"
00114                " %+." "20" "e" " %+." "20" "e"
00115                " %+." "20" "e" " %+." "20" "e"
00116                touchstone_crlf, f,
00117                real (S(0,0)), imag (S(0,0)),
00118                real (S(1,0)), imag (S(1,0)),
00119                real (S(0,1)), imag (S(0,1)),
00120                real (S(1,1)), imag (S(1,1)));
00121     }
00122   }
00123   // three-port file
00124   else if (touchstone_data.ports == 3) {
00125     for (int i = 0; i < touchstone_data.vd->getSize (); i++) {
00126       matrix S = touchstone_data.mv->get (i);
00127       nr_double_t f = real (touchstone_data.vd->get (i));
00128       fprintf (touchstone_out, "%." "20" "e"
00129                " %+." "20" "e" " %+." "20" "e"
00130                " %+." "20" "e" " %+." "20" "e"
00131                " %+." "20" "e" " %+." "20" "e"
00132                touchstone_crlf "      %"  "20" "s"
00133                " %+." "20" "e" " %+." "20" "e"
00134                " %+." "20" "e" " %+." "20" "e"
00135                " %+." "20" "e" " %+." "20" "e"
00136                touchstone_crlf "      %"  "20" "s"
00137                " %+." "20" "e" " %+." "20" "e"
00138                " %+." "20" "e" " %+." "20" "e"
00139                " %+." "20" "e" " %+." "20" "e"
00140                touchstone_crlf,
00141                f,
00142                real (S(0,0)), imag (S(0,0)),
00143                real (S(0,1)), imag (S(0,1)),
00144                real (S(0,2)), imag (S(0,2)), " ",
00145                real (S(1,0)), imag (S(1,0)),
00146                real (S(1,1)), imag (S(1,1)),
00147                real (S(1,2)), imag (S(1,2)), " ",
00148                real (S(2,0)), imag (S(2,0)),
00149                real (S(2,1)), imag (S(2,1)),
00150                real (S(2,2)), imag (S(2,2)));
00151     }
00152   }
00153   // four-port and above files
00154   else if (touchstone_data.ports >= 4) {
00155     for (int i = 0; i < touchstone_data.vd->getSize (); i++) {
00156       matrix S = touchstone_data.mv->get (i);
00157       nr_double_t f = real (touchstone_data.vd->get (i));
00158       int cs = S.getCols ();
00159       int rs = S.getRows ();
00160       fprintf (touchstone_out, "%." "20" "e", f);
00161       for (int r = 0; r < rs; r++) {
00162         if (r >= 1)
00163           fprintf (touchstone_out, "      %"  "20" "s", " ");
00164         for (int c = 0; c < cs; c++) {
00165           if (c > 1 && (c & 3) == 0)
00166             fprintf (touchstone_out, "      %"  "20" "s", " ");
00167           fprintf (touchstone_out, " %+." "20" "e" " %+." "20" "e",
00168                    real (S(r,c)), imag (S(r,c)));
00169           if ((c > 1 && (c & 3) == 3) || (c == cs - 1))
00170             fprintf (touchstone_out, touchstone_crlf);
00171         }
00172       }
00173     }
00174   }
00175 }
00176 
00177 /* The function finds an appropriate S-parameters or other parameter
00178    type (G, H, Y, Z, etc.) matrix from the given dataset and stores it
00179    into the global Touchstone structure. */
00180 void touchstone_find_data (dataset * data, const char * name) {
00181   qucs::vector * v;
00182   char * n;
00183   const char * vn;
00184   char * vd = NULL, * vf = NULL;
00185   strlist * deps;
00186   int r, c, rs = -1, cs  = -1, s = 0;
00187 
00188   // find parameter matrix data and its dimensions
00189   for (v = data->getVariables (); v != NULL; v = (::vector *) v->getNext ()) {
00190     vn = v->getName ();
00191     // requested matrix vector name found?
00192     if (strstr (vn, name) == vn) {
00193       if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) {
00194         if (rs < r) rs = r;
00195         if (cs < c) cs = c;
00196         s = v->getSize ();
00197         free (n);
00198         if ((deps = v->getDependencies ()) != NULL) {
00199           vd = deps->get (0);
00200         }
00201       }
00202     }
00203     // minimum noise figure?
00204     if (!strcmp (vn, "Fmin")) {
00205       touchstone_data.fmin = v;
00206       if ((deps = v->getDependencies ()) != NULL) vf = deps->get (0);
00207     }
00208     // optimal input reflection for minimum noise figure?
00209     else if (!strcmp (vn, "Sopt")) {
00210       touchstone_data.sopt = v;
00211       if ((deps = v->getDependencies ()) != NULL) vf = deps->get (0);
00212     }
00213     // effective noise resitance?
00214     else if (!strcmp (vn, "Rn")) {
00215       touchstone_data.rn = v;
00216       if ((deps = v->getDependencies ()) != NULL) vf = deps->get (0);
00217     }
00218   }
00219 
00220   // matrix entries found
00221   if (rs >= 0 && cs >= 0 && vd != NULL) {
00222     int ss = rs > cs ? rs : cs;
00223     // fill in number of ports
00224     touchstone_data.ports = ss + 1;
00225     // create quadratic matrix vector
00226     matvec * mv = new matvec (s, ss + 1, ss + 1);
00227     mv->setName (name);
00228     // fill in matrix vectors
00229     for (v = data->getVariables (); v; v = (::vector *) v->getNext ()) {
00230       vn = v->getName ();
00231       if (strstr (vn, name) == vn) {
00232         if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) {
00233           mv->set (*v, r, c);
00234           free (n);
00235         }
00236       }
00237     }
00238     // store in global structure
00239     touchstone_data.mv = mv;
00240     touchstone_data.parameter = toupper (mv->getName ()[0]);
00241     // look for dependency (frequency) vector
00242     for (v = data->getDependencies (); v; v = (::vector *) v->getNext ()) {
00243       if (vd && !strcmp (v->getName (), vd)) {
00244         touchstone_data.vd = v;
00245       }
00246       if (vf && !strcmp (v->getName (), vf)) {
00247         touchstone_data.vf = v;
00248       }
00249     }
00250   }
00251 }
00252 
00253 /* This is the overall Touchstone producer. */
00254 void touchstone_producer (const char * variable) {
00255 
00256   // apply data variable name
00257   if (variable == NULL) {
00258     variable = "S";
00259   }
00260 
00261   // initialize global Touchstone structure
00262   touchstone_data.mv = NULL;
00263   touchstone_data.vd = NULL;
00264   touchstone_data.format = "RI";
00265   touchstone_data.resistance = 50.0;
00266   touchstone_data.fmin = NULL;
00267   touchstone_data.sopt = NULL;
00268   touchstone_data.rn = NULL;
00269   touchstone_data.vf = NULL;
00270 
00271   // look for appropriate matrix data
00272   touchstone_find_data (qucs_data, variable);
00273 
00274   // print matrix data if available
00275   if (touchstone_data.mv != NULL) {
00276     touchstone_print ();
00277     delete touchstone_data.mv;
00278     touchstone_print_noise ();
00279   }
00280   else {
00281     fprintf (stderr, "no such data variable `%s' found\n", variable);
00282   }
00283 }