Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

error_terms.h

Go to the documentation of this file.
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 // error_terms.h
00032 //
00033 // Concrete classes for calculating error function terms to be used with
00034 // class error_func, in error_func.h. All are derived from abstract error
00035 // term classes also defined in that header file. 
00036 //
00037 // Class:           Derived from:             Used to optimize:
00038 //  gain_dB          error_term_mode           gain in dB
00039 //  s_mag                  "                   S parameter magnitude
00040 //  input_tn               "                   input noise temperature 
00041 //  amp_k                  "                   amplifier stability "k"
00042 //  amp_mag_delta          "                   amplifier stability "delta"
00043 //  two_match        error_term                match two circuit S matrices
00044 //  fts_match        scaled_match_error_term   match FTS response to data
00045 //  iv_match         error_term                match mixer pumped IV to data
00046 //
00047 // 4/21/99 by John Ward
00048 //
00049 // Based on err_term.h written 7/22/98 by J.Z.
00050 //
00051 // 9/15/00:  Tweaks to the code.
00052 //
00053 // ************************************************************************
00054 // classes gain_dB, s_mag, and input_tn
00055 //
00056 // These classes are convenient for optimizing the gain, the input or
00057 // output match, or the noise performance of a circuit. Each requires that
00058 // an nport (circuit) be provided as the first argument in its constructor.
00059 // Addtional arguments may be provided, but are optional. The default
00060 // behavior of each of these classes assumes:
00061 //
00062 //   Input port number  =  1      change using member function in(int port)
00063 //   Output port number =  2      change using member function out(int port)
00064 //   Error term mode    =  MATCH  change using error_term_mode functions
00065 //   Error term target  =  0.0    change using error_term_mode functions
00066 //
00067 // The error_term_mode member functions are described in file error_func.h.
00068 //
00069 // Here are a few examples. Note that here we only provide the circuit as the
00070 // constructor argument. Changes to the ports and/or mode are done using
00071 // member function calls. If you wish to use additional arguments with the
00072 // constructor, consult the actual class declarations in this file.
00073 //
00074 // circuit ckt;        // this is the circuit to be optimized. Assume it is
00075 //                     // a 2-port with input at port 1 and output at port 2.
00076 //
00077 // gain_dB   gain(ckt);
00078 // gain.above(+20);    // This term generates an error if gain < 20 dB.
00079 //
00080 // gain_dB   flat(ckt);
00081 // flat.flat();        // Error proportional to the variation around the mean
00082 //                     // gain in dB.
00083 //
00084 // input_tn  noise(ckt);
00085 // noise.below(4*Kelvin); // Error if input noise > 4K
00086 //
00087 // gain_dB   in_match(ckt);
00088 // in_match.in(1).out(1).below(-20); // Error if input reflection > -20 dB.
00089 //
00090 // When concatenating member function calls using ".", always put in() and
00091 // out() calls before calls to error_term_mode functions which set the mode
00092 // and/or target (otherwise the compiler will complain... try it and see!).
00093 //
00094 // ************************************************************************
00095 // classes amp_k and amp_mag_delta
00096 //
00097 // These two error term classes are used to optimize the stability of a
00098 // 2-port amplifier design. Each requires that an nport (circuit) be
00099 // provided as the first argument in its constructor. Addtional arguments
00100 // may be provided, but are optional. Both use the functionality of class
00101 // ampdata (see ampdata.h) to perform their calculations.
00102 //
00103 // Class amp_k compares the 2-port stability factor "K", which must be > 1
00104 // for an unconditionally stable design, to a specified target. The default
00105 // amp_k object assumes:
00106 //
00107 //   Input port number  =  1      change using member function in(int port)
00108 //   Output port number =  2      change using member function out(int port)
00109 //   Error term mode    =  ABOVE  change using error_term_mode functions
00110 //   Error term target  =  3.0    change using error_term_mode functions
00111 //
00112 // Class amp_mag_delta compares the magnitude of the determinant of the
00113 // 2-port scattering matrix, which must be < 1 for an unconditionally stable
00114 // design, to a specified target. The default amp_mag_delta object assumes: 
00115 //
00116 //   Input port number  =  1      change using member function in(int port)
00117 //   Output port number =  2      change using member function out(int port)
00118 //   Error term mode    =  BELOW  change using error_term_mode functions
00119 //   Error term target  =  0.5    change using error_term_mode functions
00120 //
00121 // ************************************************************************
00122 // class two_match
00123 //
00124 // Class two_match simply takes the matrix difference of the scattering
00125 // matrices returned by two nports, then totals the squared magnitudes of
00126 // the elements of the difference. Its constructor requires two nport
00127 // arguments.
00128 //
00129 // ************************************************************************
00130 // classes fts_match and iv_match 
00131 //
00132 // These classes are used to compare the predictions of an SIS mixer
00133 // model to measured FTS (Fourier Transform Spectrometer) or DC IV curve
00134 // file data. Each has a fairly complicated constructor argument list
00135 // which must include a mixer object (see mixer.h) one or more parameter
00136 // objects, and a data file name, as well as additional options. When
00137 // constructed, the error term reads in the file data and builds an
00138 // internal real_interp (real_interp.h) interpolator of the data. When
00139 // the error term value is calculated, it sets the operating state of
00140 // the mixer by calling mixer::balance(), calculates the total DC bias
00141 // current for the mixer junctions (see junction.h) and compares the
00142 // calculation with the interpolated file data.
00143 //
00144 // Both classes include a public member variable named "measured", which
00145 // is the real_interp object used to interpolate the file data. This
00146 // interpolator is made public so that the user may adjust its behavior
00147 // using its own member functions (see interpolate.h). If the measured
00148 // data has a significant amount of noise, for example, it would be
00149 // prudent to use linear rater than spline interpolation (the default).
00150 // This interpolation mode may be set for an error term "term" by calling:
00151 //
00152 //   term.measured.linear().build();
00153 //
00154 // which rebuilds the interpolation tables for linear interpolation.
00155 //
00156 //
00157 // USAGE: fts_match
00158 //
00159 // fts_match is derived from class scaled_match_error_term. Here's what it
00160 // does:
00161 //   1. At construction, read in the file data and build an interpolation
00162 //      of it as a function of mixer LO frequency.
00163 //   2. When reset(), set the LO power to zero, call mixer's balance() to
00164 //      set its operating state, and get and save the total junction dark
00165 //      current. Restore the LO power variable to its previous state.
00166 //   3. When get() is called, set the LO power to a small value specified
00167 //      at construction. Call the mixer's balance() and again get the total
00168 //      junction current. Subtract off the dark current; the result is the
00169 //      simulated response from the mixer model. Interpolate the FTS data
00170 //      for the current LO frequency and compare the simulated and
00171 //      interpolated values using the scaled_match_error_term algorithm
00172 //      (see error_func.h).
00173 //
00174 // Here's an example of how to create an fts_match error term:
00175 //
00176 //   fts_match fts_term(mix, LO_f, LO_p, name, GHz, 1*Nano*Watt);
00177 //     // mix:  the mixer object
00178 //     // LO_f: a parameter object which contains the LO frequency
00179 //     // LO_p: a parameter object which controls the LO power
00180 //     // name: a char pointer to the data file name (C-style string)
00181 //     // GHz:  a double value which gives the frequency units in the file
00182 //     //       (in this case, the file uses GHz as its units)
00183 //     // 1*Nano*Watt: a double value for the LO power to set when
00184 //              simulating the FTS response with the mixer.
00185 //
00186 // The last two arguments are optional. If omitted, GHz and 10*Nano*Watt
00187 // are assumed.
00188 //
00189 // The measured FTS data must be in a 2 column file, frequency and
00190 // response. Units for frequency can be set with the constructor, as shown.
00191 // The units for the response are arbitrary.
00192 //
00193 // The abstract_real_parameter LO_f will only be accessed using its get()
00194 // function; it will not be written to. The parameter LO_p, on the other
00195 // hand, will be set by the error term whenever the term's reset() or get()
00196 // is executed. The LO_p parameter will be copied and restored to its
00197 // original state by the the functions, however, so other parts of the
00198 // program should not be affected.
00199 //
00200 // The mixer object mix will be modified whenever the term's reset() or
00201 // get() is executed. On reset(), mix.balance() will be called with LO_p
00202 // set to0. On get(), mix.balance() will be called with LO_p set to the LO
00203 // power value specified at construction. Consequently, every call to the
00204 // term's reset() or get() will change the operating state of the junctions
00205 // used by the mixer mix.
00206 //
00207 // Additional member functions of fts_match:
00208 //
00209 //   pump(double p);
00210 //     sets the LO power to p whenever get() is called.
00211 //
00212 //   f_correct(bool f);
00213 //   f_correct();        // same as f_correct(true)
00214 //     sets an internal flag which affects the comparison to the measured
00215 //     data. If f is true, then apply a frequency correction to the
00216 //     simulated response by multiplying the response value by the value of
00217 //     the LO frequency. If f is false, then don't apply the frequency
00218 //     correction (the default behavior). This feature is included because
00219 //     some FTS laboratory data acquisition software applies such a
00220 //     correction to the measured data set. If this compensation has been
00221 //     applied to the data set in the file, then call this member function
00222 //     before performing  error function calculations to compensate for
00223 //     this adjustment to the data.
00224 //
00225 //
00226 // USAGE: iv_match
00227 //
00228 // iv_match is derived from class error_term. Here's what it does:
00229 //   1. At construction, read in the file data and build an interpolation
00230 //      of it as a function of mixer DC bias voltage.
00231 //   2. When get() is called, call the mixer's balance() and get the total
00232 //      junction current. Interpolate the IV file data for the current
00233 //      bias voltage and return the square of the difference between the
00234 //      calculated and interpolated currents.
00235 //
00236 // Here's an example of how to create an iv_match error term:
00237 //
00238 //   iv_match iv_term(mix, V_bias, name, mVolt, Micro*Amp);
00239 //     // mix:    the mixer object
00240 //     // V_bias: a parameter object which contains the DC bias voltage
00241 //     // name:  a char pointer to the data file name (C-style string)
00242 //     // mVolt: a double value which gives the voltage units in the file
00243 //     //       (in this case, the file uses millivolts as its units)
00244 //     // Micro*Amp: a double value which gives the file's current units
00245 //     //       (in this case, the file uses microamps as its units) 
00246 //
00247 // The last two arguments are optional. If omitted, mVolt and Micro*Amp
00248 // are assumed.
00249 //
00250 // The measured IV data must be in a 2 column file, bias voltage
00251 // and bias current.  Units for voltage and current can be set with the
00252 // constructor. Measured data offset error corrections can be specified
00253 // using member functions described below.
00254 //
00255 // The abstract_real_parameter V_bias will only be accessed using its get()
00256 // function; it will not be written to.
00257 //
00258 // The mixer object mix may be modified whenever the term's get() is
00259 // executed. On get(), mix.balance() will be called. Consequently, every
00260 // call to the get() may change the operating state of the junctions
00261 // used by the mixer mix.
00262 //
00263 // Additional member functions of iv_match:
00264 //
00265 //   v_offset(v);
00266 //   i_offset(i);
00267 //     set voltage (v_offset) or current (i_offset) offset corrections
00268 //     to be applied to the file data. The sign convention on the offset
00269 //     corrections is as follows: the measured data point is the true
00270 //     data value + offset, so that:
00271 //               I(V) == I_measured(V + V_offset) - I_offset
00272 //     The argument may be either a double value or a pointer to an
00273 //     abstract_real_parameter object, so that the offsets can shadow
00274 //     external parameter objects (and thusly be controlled by the
00275 //     optimizer). The default offsets are 0.
00276 //
00277 // ************************************************************************
00278  
00279 #ifndef ERROR_TERMS_H
00280 #define ERROR_TERMS_H
00281 
00282 #include "error_func.h"
00283 #include "nport.h"
00284 #include "sdata.h"
00285 
00286 // The following are required for class fts_match:
00287 #include "mixer.h"
00288 #include "real_interp.h"
00289 
00290 
00291 // ************************************************************************
00292 //
00293 // Gain in dB
00294 //
00295 // ************************************************************************
00296 class gain_dB : public error_term_mode
00297 {
00298 public:
00299   gain_dB(nport & ckt,                        // Circuit to optimize
00300           int input = 1,                      // Input port index
00301           int output = 2,                     // Output port index
00302           error_term_mode::mode etm = MATCH,  // Mode
00303           double tar = 0.0) :                 // Target value
00304     error_term_mode(etm, tar),
00305     in_port(input),
00306     out_port(output),
00307     np(&ckt)
00308   { }
00309 
00310   gain_dB & in(int i)  { in_port = i; return *this; }
00311   gain_dB & out(int i) { out_port = i; return *this; }
00312 
00313   double get(state_tag);
00314 
00315 private:
00316   int in_port, out_port ;
00317   nport *np;
00318 };
00319 
00320 
00321 // ************************************************************************
00322 //
00323 // magnitude of S parameter
00324 //
00325 // ************************************************************************
00326 class s_mag : public error_term_mode
00327 {
00328 public:
00329   s_mag(nport & ckt,                        // Circuit to optimize
00330         int input = 1,                      // Input port index
00331         int output = 2,                     // Output port index
00332         error_term_mode::mode etm = MATCH,  // Mode
00333         double tar = 0.0) :                 // Target value
00334     error_term_mode(etm, tar),
00335     in_port(input),
00336     out_port(output),
00337     np(&ckt)
00338   { }
00339 
00340   s_mag & in(int i) { in_port = i ; return *this ; }
00341   s_mag & out(int i) { out_port = i ; return *this ; }
00342 
00343   double get(state_tag);
00344 
00345 private:
00346   int in_port, out_port ;
00347   nport *np;
00348 
00349 } ;
00350 
00351 
00352 // ************************************************************************
00353 //
00354 // input noise temperature
00355 //
00356 // ************************************************************************
00357 class input_tn : public error_term_mode
00358 {
00359 public:
00360   input_tn(nport & ckt,                        // Circuit to optimize
00361            int input = 1,                      // Input port index
00362            int output = 2,                     // Output port index
00363            error_term_mode::mode etm = MATCH,  // Mode
00364            double tar = 0.0) :                 // Target value
00365     error_term_mode(etm, tar),
00366     in_port(input),
00367     out_port(output),
00368     np(&ckt)
00369   { }
00370 
00371   input_tn & in(int i) { in_port = i ; return *this ; }
00372   input_tn & out(int i) { out_port = i ; return *this ; }
00373 
00374   double get(state_tag);
00375 
00376 private:
00377   int in_port, out_port ;
00378   nport *np;
00379 
00380 } ;
00381 
00382 
00383 // ************************************************************************
00384 //
00385 // Amplifier "k," useful for optimizing for unconditional stability.
00386 //
00387 // ************************************************************************
00388 class amp_k: public error_term_mode
00389 {
00390 public:
00391   amp_k(nport & ckt,                        // Circuit to optimize
00392         int input = 1,                      // Input port index
00393         int output = 2,                     // Output port index
00394         error_term_mode::mode etm = ABOVE,  // Mode should usually be ABOVE
00395         double tar = 3.0) :                 // Target value
00396     error_term_mode(etm, tar),
00397     in_port(input),
00398     out_port(output),
00399     np(&ckt)
00400   { }
00401 
00402   amp_k & in(int i) { in_port = i ; return *this ; }
00403   amp_k & out(int i) { out_port = i ; return *this ; }
00404 
00405   double get(state_tag);
00406 
00407 private:
00408   int in_port, out_port ;
00409   nport *np;
00410 
00411 } ;
00412 
00413 
00414 // ************************************************************************
00415 //
00416 // Amplifier "delta," useful for optimizing for unconditional stability.
00417 //
00418 // ************************************************************************
00419 class amp_mag_delta: public error_term_mode
00420 {
00421 public:
00422   amp_mag_delta(nport & ckt,                        // Circuit to optimize
00423                 int input = 1,                      // Input port index
00424                 int output = 2,                     // Output port index
00425                 error_term_mode::mode etm = BELOW,  // Mode usually BELOW
00426                 double tar = 0.5) :                 // Target value
00427     error_term_mode(etm, tar),
00428     in_port(input),
00429     out_port(output),
00430     np(&ckt)
00431   { }
00432 
00433   amp_mag_delta & in(int i) { in_port = i ; return *this ; }
00434   amp_mag_delta & out(int i) { out_port = i ; return *this ; }
00435 
00436   double get(state_tag);
00437 
00438 private:
00439   int in_port, out_port ;
00440   nport *np;
00441 
00442 } ;
00443 
00444 
00445 // ************************************************************************
00446 //
00447 // match the S-matrices of two circuits
00448 //
00449 // ************************************************************************
00450 class two_match : public error_term
00451 {
00452 public:
00453   two_match(nport &ckt1, nport &ckt2) : np1(&ckt1), np2(&ckt2) { }
00454 
00455   double get(state_tag);
00456 
00457 private:
00458   nport *np1, *np2;
00459 
00460 } ;
00461 
00462 
00463 // ************************************************************************
00464 //
00465 // Match a simulated mixer response to a measured FTS curve.
00466 //
00467 // ************************************************************************
00468 class fts_match : public scaled_match_error_term
00469 {
00470 public:
00471 
00472   // The constructor.
00473   // The data file must have 2 columns, frequency and measured response.
00474   fts_match(mixer &m,                  // The mixer to simulate.
00475             const abstract_real_parameter
00476               &freq,                   // Parameter controlling the LO frequency.
00477             parameter &pow,            // Parameter controlling the LO power.
00478             const char*const filename, // File holding measured FTS response.
00479             double units=GHz,          // Units of frequency used in data file.
00480             double pump=10.*Nano*Watt) // Value of LO power to simulate FTS.
00481     :
00482     measured(freq, filename, units), mix(&m), f(false), LO_power(&pow),
00483     LO_freq(&freq), pumped_power(pump), dark_current(0), currents(0)
00484     { }
00485 
00486   // Set a different value for the pump LO power
00487   fts_match & pump(double p) { pumped_power = p; return *this; }
00488 
00489   // Set the frequency "correction" factor flag; If true, the
00490   // calculated response is multiplied by the LO frequency to
00491   // compensate for a similar factor in the measued data.
00492   fts_match & f_correct(bool flag = true) { f = flag; return *this; }
00493 
00494   // The measured curve is interpolated from the data read from the file
00495   // as a function of LO frequency. This is a public member variable, so
00496   // the user can access it to set special options, the interpolation
00497   // mode, etc.
00498   real_interp measured;
00499 
00500   // Reset the base class; calculate and save the dark current.
00501   void reset();
00502 
00503   // Return the measured FTS response at the LO frequency.
00504   double get_a(state_tag) { return measured; }
00505 
00506   // Return the simulated FTS response = pumped current - dark current.
00507   double get_b(state_tag);
00508 
00509 private:
00510   mixer *mix;   // The mixer.
00511   bool  f;      // If true, measured response has a freq "correction" factor.
00512 
00513   // Setting this parameter sets the LO power in the mixer.
00514   parameter *LO_power;
00515 
00516   // This parameter tells us the LO frequency
00517   const abstract_real_parameter *LO_freq;
00518 
00519   // Value of the LO power to use for simulating the FTS response.
00520   double pumped_power;
00521 
00522   // The dark current is calculated by method reset().
00523   double dark_current;
00524 
00525   // Hold the mixer's junction DC currents
00526   Vector currents;
00527 };
00528 
00529 
00530 // ************************************************************************
00531 //
00532 // Match a simulated mixer IV curve to a measured IV curve
00533 // (pumped or unpumped IV data can be matched)
00534 //
00535 // The error term value is the square of the difference between the
00536 // file's bias current and the calculated bias current at the specified
00537 // bias voltage.
00538 //
00539 // ************************************************************************
00540 class iv_match : public error_term
00541 {
00542 public:
00543 
00544   // The constructor.
00545   // The data file must have 2 columns, frequency and measured response.
00546   iv_match(mixer &m,                  // The mixer to simulate.
00547            const abstract_real_parameter
00548              &bias,                   // Parameter controlling bias voltage
00549            const char *const filename,// File holding measured pumped IV.
00550            double V_units=mVolt,      // Units of file's bias voltage data
00551            double I_units=Micro*Amp)  // Units of file's current data
00552     :
00553     measured(bias, filename, V_units, I_units), mix(&m), V(&bias),
00554     V_off(0.0), I_off(0.0)
00555     { }
00556 
00557   // The measured curve is interpolated from the data read from the file
00558   // as a function of bias voltage. This is a public member variable, so
00559   // the user can access it to set special options, the interpolation
00560   // mode, etc.
00561   real_interp measured;
00562 
00563   // Set offset errors for the measured data. A measured value is given by
00564   // the actual value + the offset. Note that you can give a pointer to an
00565   // abstract_real_parameter so that the offsets can shadow external
00566   // parameters (and be determined by the optimizer). Be sure to include
00567   // units when providing a value!
00568   iv_match & v_offset(double v) { V_off = v; return *this; }  // bias voltage
00569   iv_match & i_offset(double i) { I_off = i; return *this; }  // bias current
00570   iv_match & v_offset(const abstract_real_parameter *pv)
00571     { V_off = pv; return *this; }
00572   iv_match & i_offset(const abstract_real_parameter *pi)
00573     { I_off = pi; return *this; }
00574 
00575   // Return the measured pumped IV at the bias voltage corrected for offsets
00576   double get_a() { return measured(V_off + *V) - I_off; }
00577 
00578   // Return the simulated pumped IV at the bias voltage
00579   double get_b();
00580 
00581   // Return the error term value
00582   double get(state_tag);
00583 
00584 private:
00585   mixer *mix;   // The mixer.
00586 
00587   // This parameter tells us the bias voltage
00588   const abstract_real_parameter *V;
00589 
00590   // These are offset errors in the measured data, using the formula:
00591   //  (measured value) = (real value) + (offset)
00592   parameter V_off;  // measured bias voltage offset error
00593   parameter I_off;  // measured bias current offset error
00594 
00595   // Hold the mixer's junction DC currents
00596   Vector currents;
00597 };
00598 
00599 #endif /* ERROR_TERMS_H */
00600 

Please direct comments and corrections to supermix@submm.caltech.edu
Go to the supermix home page
Generated by doxygen1.2.7