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 // mixer.h 00032 // 00033 // mixer.h holds the classes used to build up a full mixer device 00034 // from separate linear circuits and nonlinear junctions. 00035 // 00036 // Includes the following classes: mixer; mixer_currents 00037 // 00038 // 3/16/99: Added mixer::freq() 00039 // 12/28/99: Reduced default max iteration count in balance() 00040 // 7/27/99: Changed mixer_currents to be a data_ptr_nport 00041 // 7/22/99: Changed reference to newt_raph.h to newton.h 00042 // 12/29/98: Added mixer::get_term_data(). 00043 // 12/17/98: Use new mixer::analyzer class for small signal calculations. 00044 // mixer is now derived from data_ptr_nport 00045 // 12/15/98: Split out definition of mixer::balancer to mixer_helper.h 00046 // 10/5/98: Adding code for smart rebuilding of data structures in 00047 // balancer 00048 // 9/14/98: Improved auto_balance(), added initialize_mode(). 00049 // Implemented copy constructor and operator =. 00050 // 9/9/98: removed check of LO from flag_mixer_incomplete() 00051 // 9/4/98: Fixed a nasty bug: added const to mixer::get_last_data() 00052 // 8/28/98: Fixed mixer::port() so it always uses IF circuit (not bias 00053 // circuit if device::f == 0, as it did before); added size(). 00054 // 8/27/98: Added mixer_currents 00055 // 8/27/98: mixer::set_LO can now shadow a parameter 00056 // 7/27/98: Added I_junc() and V_junc(); LO freq is now a parameter 00057 // 7/22/98: Added the balancer class to mixer; implemented in balance.cc 00058 // 7/21/98: changed flag_balance_invalid() to flag_state_invalid(); 00059 // adding full balance() routines 00060 // 7/20/98: Minor interface refinements. 00061 // 7/17/98: Added private LO_saved; more large signal functions. 00062 // 7/15/98: Many changes to the interface and the private variables 00063 // 00064 // F. Rice 7/9/98 00065 // 00066 // ******************************************************************** 00067 00068 #ifndef MIXER_H 00069 #define MIXER_H 00070 00071 #include "circuit.h" 00072 #include "sources.h" 00073 #include "junction.h" 00074 00075 00076 // ******************************************************************** 00077 // mixer 00078 // 00079 // A basic device which can perform harmonic balance and small signal 00080 // analysis of a multijunction mixer circuit. 00081 // 00082 // This mixer can only handle junction::Y_type nonlinear elements. 00083 // 00084 // The IF frequency for the small signal analysis should be set in 00085 // device::f. The device performs the small signal analysis when asked 00086 // to return its device parameters as an nport; the resulting sdata 00087 // holds the small signal response of the mixer. 00088 // 00089 // Note that this object will never return a nonzero source vector 00090 // in its small signal analysis result. 00091 // 00092 // F. Rice 7/9/98 00093 // 00094 // ******************************************************************** 00095 00096 #include <vector> 00097 #include <pair.h> 00098 #include "newton.h" 00099 00100 class mixer : public data_ptr_nport 00101 { 00102 00103 // The results of the small signal mixer analysis are returned as S 00104 // parameters using class data_ptr_nport's get_data(), etc., functions, 00105 // so a mixer acts like just another circuit element. 00106 00107 public: 00108 00109 // Constructor: it only reserves space in its internal tables for the 00110 // fundamental USB and LSB. Call harmonics() to include more harmonics 00111 // in the analysis. 00112 00113 mixer(); 00114 00115 // Copy constructor and operator =: Since the target and source mixers will 00116 // use the same junction devices following these operations, you should call 00117 // auto_balance(mixer::Always) to ensure that the junctions will be balanced 00118 // appropriately. It is also recommended that you call initialize_mode(1) to 00119 // make harmonic balance calculations more robust. 00120 00121 mixer(const mixer &); 00122 mixer & operator = (const mixer &); 00123 00124 00125 // Flags which indicate the readiness of the mixer to perform accurate 00126 // calculations. A NONZERO RETURN VALUE IS BAD; A ZERO RETURN VALUE IS GOOD. 00127 00128 // a fatal error if set when attempting a mixer calculation: 00129 00130 int flag_mixer_incomplete() const; // all required elements haven't been set, 00131 // or they don't have enough ports. 00132 00133 // a fatal error during small signal analysis if auto balance is inactive: 00134 00135 int flag_state_invalid() const; // at least one junction has an invalid 00136 // operating state. 00137 00138 // would indicate that any small signal calculations are inaccurate: 00139 00140 int flag_balance_inaccurate() const; // something major changed since the last 00141 // balance: circuit references, LO freq, 00142 // or initialize_operating_state() was done. 00143 00144 00145 // Set or read the maximum number of harmonics to be used by the mixer. 00146 00147 mixer & harmonics (int); // set maximum harmonic number (1 is LO frequency) 00148 00149 int harmonics() const { return max_harmonics; } 00150 00151 00152 // Manipulate the junctions attached to the mixer. The first junction added 00153 // will be connected to each of the RF, IF and DC circuits' port 1; the next 00154 // junction to the circuits' port 2, etc. Externally available ports of the RF 00155 // and IF circuits are through port numbers greater than the total number of 00156 // junctions in the mixer. Refer to the description of port(). 00157 00158 mixer & add_junction( junction & ); // add another junction device. 00159 00160 int junctions() const { return num_junctions; } // junctions added so far 00161 00162 mixer & void_junctions(); // remove all previously attached junctions 00163 00164 00165 // Set the Local Oscillator frequency and the linear circuit elements: 00166 00167 parameter LO; // the public variable which holds the LO 00168 // frequency for the mixer. If LO's value is 00169 // currently different from the value used at the 00170 // time of the last operating state calc, then 00171 // flag_balance_inaccurate() will be set. 00172 00173 mixer & set_LO( double f ) { LO = f; return *this; } // set LO frequency 00174 00175 mixer & set_LO( abstract_real_parameter * pf ) { LO = pf; return *this; } 00176 // set LO frequency to shadow a parameter. 00177 00178 mixer & set_bias( nport & ); // set the DC bias circuit. It must have the same 00179 // number of ports as the number of junctions to 00180 // be used. 00181 00182 mixer & set_if( nport & ); // set the IF circuit. It must have more ports 00183 // than the number of junctions to be used. 00184 00185 mixer & set_rf( nport & ); // set the RF circuit. It must have more ports 00186 // than the number of junctions to be used. 00187 // Setting a new RF circuit erases any previous 00188 // balance terminator settings. 00189 00190 mixer & set_balance_terminator( nport &, int ); // provide a terminator for a 00191 // port of the RF circuit to be used during 00192 // harmonic balance. This is usually an LO power 00193 // source. The int argument gives the port index 00194 // on the RF circuit. The default is a device::Z0 00195 // termination. Warns the user if the RF circuit 00196 // hasn't been set, or the port doesn't exist. 00197 // Balance terminator assignments may be cleared 00198 // by setting the RF circuit using set_rf(). 00199 00200 00201 // The mixer constructs a composite circuit of all linear and junction elements 00202 // during the small signal analysis. The following functions provide a map of 00203 // the ports of the individual linear elements to the resulting ports of the 00204 // final mixer circuit. 00205 // Port ordering is: 00206 // (1) all open IF circuit ports 00207 // (2) RF circuit at harmonic = 1: first open port at USB, then at LSB 00208 // (3) all succeeding RF circuit open ports, USB then LSB at each port 00209 // (4) same as (2) and (3) at harmonic = 2 00210 // (5) continue for all higher harmonics 00211 00212 int port( int p, int h ); // returns the mixer port index for port p of the 00213 // circuit at harmonic h. h = 0 is the IF 00214 // circuit, h > 0 are upper sidebands of the RF 00215 // circuit, h < 0 are lower sidebands. returns 0 00216 // if the port p doesn't exist or is already 00217 // connected to a nonlinear junction. 00218 00219 double freq( int port ); // returns the frequency associated with the port 00220 // of the mixer. If the port is associated with 00221 // harmonic h, returns: fabs(device::f + h*LO) 00222 00223 int size(); // since mixer is an nport, it must calculate its 00224 // size. This is the size of the small-signal 00225 // object. returns 0 if the mixer is incomplete. 00226 00227 00228 // The functions to control the harmonic balance of the mixer circuit. These 00229 // functions control how the operating states of the junctions are set. 00230 00231 mixer & initialize_operating_state(); // Just set a rough operating state for 00232 // the junctions assuming the junctions behave as 00233 // open circuits when calculating the input 00234 // voltages. No harmonic balance iterations are 00235 // performed. Will not correct 00236 // flag_balance_inaccurate(). 00237 00238 int balance() // perform a harmonic balance, determining the 00239 { return balance_(); } // operating states of all junctions. 00240 // Returns 0 if successful, 1 if a balance could 00241 // not be achieved. Will correct 00242 // flag_balance_inaccurate() if successful. 00243 00244 mixer & initialize_mode(int f); // If set to 0 (default), then balance() uses 00245 // the current junction operating states as the 00246 // initial guess for the nonlinear routine. If 00247 // set to nonzero, then balance() will first 00248 // call initialize_operating_state() before 00249 // executing the nonlinear routine. 00250 00251 mixer & initialize_operating_state(const Matrix & V); // Use the values in V 00252 // to set the operating states of the junctions. 00253 // V must have Index_C in both axes, with each 00254 // row providing the state vector for 00255 // call_large_signal() for its junction. The 1st 00256 // junction added is addressed by row 0, etc. 00257 // Uses the current LO frequency, and harmonics 00258 // equal to the larger of harmonics() or 00259 // V.Rmaxindex(). If V contains enough data to 00260 // set all junctions, then this routine will 00261 // correct flag_balance_inaccurate(). 00262 00263 mixer & save_operating_state(Matrix & V); // saves the state vector of each 00264 // junction into the matrix V, in a form suitable 00265 // for use as an argument to 00266 // initialize_operating_state(). 00267 00268 mixer & auto_balance(int f); // Set auto balance mode (default 0 - Off). 00269 // If set to a value different from 0, then 00270 // get_data() may attempt to balance the mixer 00271 // before returning the small-signal response. 00272 // See the following enumeration for valid values 00273 // and their effects. If f is not 0, 1, or 2, then 00274 // the auto balance mode is left unchanged. 00275 00276 enum { Off = 0, // Turn off auto balance feature (default). 00277 Always = 1, // get_data() always rebalances the mixer. 00278 Smart = 2 // get_data() only rebalances the mixer if 00279 }; // flag_state_invalid() or flag_balance_inaccurate() 00280 00281 00282 mixer & balance_parameters( // control parameters for the harmonic balance 00283 // nonlinear solver (defaults in parentheses). The 00284 // defaults should be adequate. 00285 int max_iterations, // maximum number of balance iterations (100) 00286 double tol_1, // max absolute error of any individual voltage (1.0e-6) 00287 double tol_m, // max sum of squares of all junction voltages (1.0e-8) 00288 double tol_x, // single step relative change convergence test (1.0e-7) 00289 double alpha // relative convergence speed minimum value (1.0e-4) 00290 ); 00291 00292 00293 int balance_iterations() // the number of iterations required by the most 00294 { return balance_.iterations(); } // recent harmonic balance. 00295 00296 00297 // Results of the operating state calculations. The values returned are 00298 // obtained by calling the junctions' I() and V() member functions. They 00299 // may not be accurate if flag_state_invalid() or flag_balance_inaccurate() 00300 // are set. 00301 00302 Vector I_junc(int m); // the currents through the junctions at 00303 // harmonic m of the LO frequency (0 is DC, 1 is 00304 // the LO freq). The index into the vector 00305 // selects the junction: 1 is the first junction 00306 // added to the mixer, etc. m must be nonnegative. 00307 00308 Vector V_junc(int m); // like I_junc(), except return the voltages 00309 // at harmonic m. 00310 00311 00312 // The normal small signal analysis results are returned by calling get_data() for 00313 // a mixer object. In addition, the following function is provided to aid in Y-factor 00314 // determinations: 00315 00316 const sdata & get_term_data(); // Terminate the RF circuit using supplied balance 00317 // terminators and/or default Z0 terminations, then 00318 // perform the small signal analysis. The sdata result 00319 // will connect the open IF ports at the frequency 00320 // given by device::f. The source vector of the result 00321 // will always be all 0's, even if there are embedded 00322 // sources in the circuits or terminators. 00323 00324 00325 00326 // Bring in the private members and member class definitions: 00327 00328 #include "mixer_helper.h" 00329 00330 }; // mixer 00331 00332 // ******************************************************************** 00333 // mixer_currents 00334 // 00335 // mixer_currents is used to construct an equivalent nport device 00336 // representing current sinks, one per junction in the mixer 00337 // circuit, which can be used with an inst_circuit object (c.f. 00338 // instrument.h) to determine the voltages or currents in the linear 00339 // circuitry of the mixer. 00340 // 00341 // F. Rice 8/27/98 00342 // 00343 // ******************************************************************** 00344 00345 #include "sources.h" 00346 #include "parameter/scaled_real_parameter.h" 00347 00348 class mixer_currents : public data_ptr_nport 00349 { 00350 public: 00351 // the constructor requires that the number of junctions to be 00352 // modeled be incuded, as well as the mixer object itself: 00353 00354 mixer_currents(mixer & m, int num_junctions); 00355 00356 // specify the harmonic of the LO to use; the mixer_currents 00357 // source frequency will be set to shadow this number times the mixer 00358 // object's LO frequency parameter. The default is 0 (DC bias). 00359 00360 mixer_currents & set_harmonic(int h); 00361 00362 00363 // the nport interface: 00364 00365 inline int size() { return n; } 00366 00367 private: 00368 mixer & mix; 00369 int n, h; 00370 std::vector <current_sink> junctions; 00371 scaled_real_parameter freq; 00372 circuit c; 00373 00374 void recalc(); 00375 00376 }; 00377 00378 #endif /* MIXER_H */
Please direct comments and corrections to
supermix@submm.caltech.edu
Go to the supermix home page
Generated by
1.2.7