00001 // SuperMix version 1.0 C++ source file 00002 // 00003 // Copyright (c) 1999 California Institute of Technology. 00004 // All rights reserved. 00005 // 00006 // Redistribution and use in source and binary forms for noncommercial 00007 // purposes are permitted provided that the above copyright notice and 00008 // this paragraph are duplicated in all such forms and that any 00009 // documentation and other materials related to such distribution and 00010 // use acknowledge that the software was developed by California 00011 // Institute of Technology. Redistribution and/or use in source or 00012 // binary forms is not permitted for any commercial purpose. Use of 00013 // this software does not include a permitted use of the Institute's 00014 // name or trademark for any purpose. 00015 // 00016 // DISCLAIMER: 00017 // THIS SOFTWARE AND/OR RELATED MATERIALS ARE PROVIDED "AS-IS" WITHOUT 00018 // WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR 00019 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE (AS SET 00020 // FORTH IN UCC 23212-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE 00021 // LICENSED PRODUCT, HOWEVER USED. IN NO EVENT SHALL CALTECH/JPL BE 00022 // LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING BUT NOT LIMITED TO 00023 // INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING ECONOMIC 00024 // DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF 00025 // WHETHER CALTECH/JPL SHALL BE ADVISED, HAVE REASON TO KNOW, OR IN 00026 // FACT SHALL KNOW OF THE POSSIBILITY. THE USER BEARS ALL RISK 00027 // RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND/OR RELATED 00028 // MATERIALS. 00029 // 00030 // ******************************************************************** 00031 // io.h 00032 // classes and functions to aid in reading and writing formatted data 00033 // 00034 // F.R. 9/27/99 00035 // 00036 // 10/2/00: Added cabability to read HFSS-output Touchstone files with 00037 // more than 4 ports. 00038 // 00039 // ******************************************************************** 00040 00041 #ifndef IO_H 00042 #define IO_H 00043 00044 #include <string> 00045 #include <vector> 00046 #include <iostream> 00047 #include <fstream> 00048 #include "matmath.h" 00049 #include "units.h" 00050 00051 // ******************************************************************** 00052 class data_parser 00053 { 00054 public: 00055 00056 // Constructor can take a reference to the input stream. 00057 data_parser(); 00058 data_parser(istream &); 00059 00060 // Set or change the input stream. 00061 data_parser & input(istream & i) { pin = &i ; return *this ; } 00062 00063 // Parse the next line of data; return the number of doubles found. 00064 // parse() has a voracious appetite for doubles but complete indifference 00065 // to anything else on a line. To qualify as a double, a token must look 00066 // like what you would think of as a double. It must be separated from 00067 // any previous token by some white space, but need not be separated from 00068 // any following token by white space. Consequently the string "-2Volts" 00069 // contains the double -2.0, while "Perfect-10.0" contains no doubles, since 00070 // "-10.0" is not preceded by white space. A comment character on the line 00071 // causes parse to stop looking for doubles following it. 00072 unsigned parse(); 00073 00074 // Like parse, except first skip any lines without uncommented numbers; 00075 // returns 0 if end of file or error encountered. 00076 unsigned skip_parse(); 00077 00078 // Parse the string supplied as an argument as though it were input. 00079 unsigned parse(const std::string &); 00080 unsigned parse(const char * const); 00081 00082 00083 // A STL vector<double> containing the uncommented doubles found by 00084 // the latest call to parse(). 00085 const std::vector<double> & data() { return data_ ; } 00086 00087 // The latest input line read by parse(), parsed into a STL vector of C++ 00088 // string tokens which were found separated by one or more whitespace char's 00089 // in the line. Whitespace chars are those identified as such by the C macro 00090 // isspace(). 00091 const std::vector<string> & tokens(); 00092 00093 00094 // Convert the data in data() into the supplied container. 00095 // Returns number of elements stored to the container (0 if an error). 00096 // Uses Complex::dtoz() to convert doubles to Complex. Optionally scales 00097 // converted values by multiplying by "units" following conversion. 00098 00099 int convert(real_vector &, double units = 1.0); // Starts with index = 1 in the 00100 int convert(complex_vector &, double units = 1.0); // receiving containers. 00101 00102 00103 // Convert the data in data() into the supplied double and container; 00104 // returns number of elements stored to the container (0 if an error). 00105 // Uses Complex::dtoz() to convert doubles to Complex. data()[0] (the first value 00106 // found on the line) goes into the double, the rest into the container. Optionally 00107 // scales converted values by multiplying by "u1" for the double, "u2" for the 00108 // values in the container following conversion. There must be at least two 00109 // doubles in data() for a conversion to be performed. 00110 00111 int convert(double &, real_vector &, double u1 = 1.0, double u2 = 1.0); 00112 int convert(double &, complex_vector &, double u1 = 1.0, double u2 = 1.0); 00113 00114 00115 // String containing the entire line text found by parse(). 00116 const std::string & line() { return line_ ; } 00117 00118 // String containing the comment text found by parse(). The comment delimiter 00119 // is the first character of the string. 00120 const std::string & comment() { return comment_ ; } 00121 00122 00123 // String containing the comment delimiter chars recognized by parse(). 00124 // Since the reference returned is not const, you can change this string, 00125 // changing the subsequent behavior of parse(). 00126 std::string & delim() { return delim_ ; } 00127 00128 // String constaining the default comment delimiter chars, '#' and '!'. 00129 // Each newly created data_parser object will use this string to initialize 00130 // delim(). You can change this string. 00131 static std::string & default_delim() { return def_delim_ ; } 00132 00133 00134 private: 00135 istream * pin ; // pointer to the input stream 00136 std::string line_ ; // hold the line being parsed 00137 std::string comment_ ; // hold the comment found in current line 00138 std::string delim_ ; // hold a list of comment delimiter chars 00139 std::vector<string> tokens_ ; // hold the tokens found on the line 00140 std::vector<double> data_ ; // hold the numbers found on the line 00141 static std::string def_delim_ ; // hold the default comment delimiters 00142 00143 }; 00144 00145 00146 // ******************************************************************** 00147 // class touchstone_base 00148 // 00149 // Base class containing common elements of the touchstone file classes 00150 // touchstone_read and touchstone_write 00151 00152 class touchstone_base 00153 { 00154 public: 00155 00156 // the recognized matrix types 00157 enum types { S, Y, Z }; 00158 00159 }; 00160 00161 00162 // ******************************************************************** 00163 // class touchstone_read 00164 // 00165 // This class can input frequency response data from most properly-formatted 00166 // Touchstone files, and many "improperly" formatted ones.. It understands 00167 // S, Z, and Y type matrix data in any of MA, DB, or RI number formats. 00168 // 00169 // It can interpret files which are minor generalizations of the strict 00170 // Touchstone format: it ignores lines containing no doubles (as interpreted by 00171 // data_parser::parse(), see above), even if they do not use a comment delimiter 00172 // ('!'), and can handle numbers of ports exceeding 4 by looking for a 00173 // generalization of the Touchstone format of 4-port data. The genereralized 00174 // data format for an N-port (with N > 4) may be either of the following 2 00175 // formats: 00176 // 00177 // Format 1 (all S parameters for a row on a single line): 00178 // 00179 // freq1 S(1,1) S(1,2) S(1,3) S(1,4) ... S(1,N) 00180 // S(2,1) S(2,2) S(2,3) S(2,4) ... S(2,N) 00181 // S(3,1) S(3,2) S(3,3) S(3,4) ... S(3,N) 00182 // ... 00183 // S(N,1) S(N,2) S(N,3) S(N,4) ... S(N,N) 00184 // 00185 // freq2 S(1,1) S(1,2) S(1,3) S(1,4) ... S(1,N) 00186 // S(2,1) S(2,2) S(2,3) S(2,4) ... S(2,N) 00187 // ... 00188 // 00189 // Format 2 (at least 4 S parameters per line; a single row's data wraps): 00190 // 00191 // freq1 S(1,1) S(1,2) S(1,3) S(1,4) 00192 // S(1,5) S(1,6) S(1,7) S(1,8) 00193 // ... S(1,N-1) S(1,N) 00194 // S(2,1) S(2,2) S(2,3) S(2,4) 00195 // S(2,5) S(2,6) S(2,7) S(2,8) 00196 // ... S(2,N-1) S(2,N) 00197 // ... 00198 // S(N,1) S(N,2) S(N,3) S(N,4) 00199 // S(N,5) S(N,6) S(N,7) S(N,8) 00200 // ... 00201 // ... S(N,N-1) S(N,N) 00202 // 00203 // freq2 S(1,1) S(1,2) S(1,3) S(1,4) 00204 // S(1,5) S(1,6) S(1,7) S(1,8) 00205 // ... S(1,N-1) S(1,N) 00206 // ... 00207 // 00208 // Each freq value is a single number; the S matrix values are each a pair 00209 // of numbers. Format 2 is output by programs such as HFSS and HPADS. 00210 00211 class touchstone_read : public touchstone_base 00212 { 00213 public: 00214 00215 // ------------------- 00216 // Create object and open a file: 00217 00218 touchstone_read(); // the only constructor is the default. 00219 00220 // Open the named file. Look for and interpret a specification line, if present. 00221 // Any previously-opened file is first closed. Returns false if unable to open or 00222 // can't find any numerical data in the file. f_scale gives the default scaling 00223 // for the file's frequency data; it will be overridden by the file's specification 00224 // line frequency scaling, if present. In the event a specification line is not 00225 // present (specification lines begin with "# "), uses the default format which would 00226 // have a specification line of: "# <f_scale> S MA R 50" (f_scale frequency scale, 00227 // S parameter in Magnitude-Degree, 50 Ohm normalization). Note that white space must 00228 // separate the '#' and the rest of the specification line. 00229 bool open(const char * const name, int ports = 2, double f_scale = GHz); 00230 00231 00232 // ------------------- 00233 // Get the matrix data: 00234 00235 // Returns the type of matrix data in the file. Returns S if something went wrong. 00236 typedef touchstone_base::types types; 00237 types type() const { return type_ ; } 00238 00239 // Fills in the frequency and Matrix data from the next data line of the file. 00240 // Returns false when no more Matrix data could be read from file, or data improperly 00241 // formatted, or no file has been specified with open(); f and M will not be 00242 // modified in this case. The data returned in the Matrix argument to value() 00243 // will be properly converted to supermix internal values using this impedance. In 00244 // the case of types Y and Z, the matrix elements are individually scaled using z() 00245 // to accomplish this conversion. In the case of type S, the matrix data is 00246 // renormalized to the normalizing impedance in the current value of device::Z0. 00247 bool value(double & f, Matrix & M); 00248 00249 // Svalue() is like value, except that if the file contains Y or Z data, it converts 00250 // the data to the equivalent S matrix normalized to device::Z0. 00251 bool Svalue(double & f, Matrix & S); 00252 00253 // Yvalue() is like Svalue, except that it returns the equivalent Y matrix. 00254 bool Yvalue(double & f, Matrix & Y); 00255 00256 // Zvalue() is like Svalue, except that it returns the equivalent Z matrix. 00257 bool Zvalue(double & f, Matrix & Z); 00258 00259 00260 // ------------------- 00261 // Get the noise data: 00262 00263 // Container for noise data read from a file 00264 struct noise { 00265 double Fmin; // min noise figure in dB 00266 complex Gopt; // optimum source reflection coefficient (Gamma) 00267 double Reff; // effective noise resistance 00268 }; 00269 00270 // Returns true if noise data is detected in the file. 00271 bool has_noise() const { return (N == 2) && noise_ ; } 00272 00273 // If the next lines in the file contain noise data (file must be for a 2-port), 00274 // fill in the members of N with that data. f will get the frequency of the data. 00275 // If there is no properly formatted noise data remaining, returns false. f and N will 00276 // not be modified in this case. N.Gopt will contain the source Gamma properly 00277 // renormalized to device::Z0; N.Reff will be a real (unnormalized) resistance. 00278 bool get_noise(double & f, noise & N); 00279 00280 00281 // ------------------- 00282 // Other functions: 00283 00284 // Returns false if data format was improper on latest call to open() or value(). 00285 // If a call to value() returns false, but good() returns true, then the end of 00286 // the matrix data values has been reached. Returns false if open() has not been called. 00287 bool good() const { return (N != 0); } 00288 00289 // Returns the normalizing impedance of the data in the file. The data 00290 // returned in the Matrix argument to value() will be properly converted to 00291 // supermix internal values using this impedance. In the case of types Y and Z, 00292 // the matrix elements are individually scaled using z() to accomplish this 00293 // conversion. In the case of type S, the matrix data is renormalized to the 00294 // normalizing impedance in the current value of device::Z0. 00295 double z() const { return z_ ; } 00296 00297 // Verbosity. The default is for verbose behavior to be enabled. If verbose, then 00298 // warnings will be issued for problems encountered. If quiet, then no warnings will 00299 // be issued, so the return values of functions will give the only indications of 00300 // bad behavior. 00301 touchstone_read & verbose() { verbose_ = true; return *this; } 00302 touchstone_read & quiet() { verbose_ = false; return *this; } 00303 00304 // ------------------- 00305 // A static (global) function to determine the number of ports in a Touchstone file 00306 00307 // Examine the named file. If it is a properly-formatted Touchstone file, return the 00308 // number of ports for the device described by the file. Return 0 if the file is not 00309 // a proper Touchstone file. This function only checks the specification line format 00310 // and examines the first data set in the file, so its checks are not at all 00311 // comprehensive. It should correctly interpret an "extended" Touchstone format for 00312 // files with more than 4 ports. 00313 static int ports(const char * const name); 00314 00315 private: 00316 00317 touchstone_read(const touchstone_read &); // no copy constructor! 00318 void operator = (const touchstone_read &); // no assignment operator! 00319 00320 std::string name_; // the name of the file opened 00321 ifstream s; // the stream for this file 00322 data_parser d; // the data parser object used to parse the file 00323 int N; // number of ports in the data (0 if something went wrong) 00324 bool end_; // true when the end of the matrix data has been seen. 00325 bool noise_; // true when noise data is available 00326 bool verbose_; // warning behavior 00327 00328 double f_units; // units for file frequency data 00329 double z_; // normalizing impedance of file data 00330 types type_; // the type of matrix in the file 00331 double f_last; // the latest frequency seen 00332 00333 Matrix normalize(const Matrix &); // use type_ and z_ to normalize data 00334 00335 Complex::io_mode mode; // the input mode (format) of the S data 00336 Complex::io_mode old_mode; // saves the io_mode at entry to value() 00337 00338 }; 00339 00340 #endif /* IO_H */
Please direct comments and corrections to
supermix@submm.caltech.edu
Go to the supermix home page
Generated by
1.2.7