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

sdata_interp.cc

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 // sdata_interp.cc
00032 //
00033 // FRR 10/7/99
00034 //
00035 // 11/16/99: supports new circuit noise calculations
00036 //
00037 // ********************************************************************
00038 
00039 #include "sdata_interp.h"
00040 
00041 S_interp & S_interp::add_S(double f, const Matrix & S, double Zn)
00042 {
00043   if((S.Lmode != Index_1) && (S.Rmode != Index_1) && (S.Lsize != N) && (S.Rsize != N)) {
00044     error::warning("S_interp::add_S(): improperly sized S matrix argument");
00045     return *this;
00046   }
00047 
00048   if(Znorm_ <= 0.0) Znorm_ = device::Z0;
00049   if(Zn == Znorm_ || Zn <= 0.0)
00050     s.add(f,S);
00051   else
00052     s.add(f,S_renormalize(S,Znorm_,Zn));
00053   return *this;
00054 }
00055 
00056 
00057 S_interp & S_interp::add_S(double f, const sdata & Sd)
00058 {
00059   add_S(f, Sd.S, Sd.get_znorm());
00060   return *this;
00061 }
00062 
00063 
00064 S_interp & S_interp::add_SC(double f, const sdata & Sd)
00065 {
00066   if(Sd.size() != N || Sd.mode() != Index_1) {
00067     error::warning("S_interp::add_SC(): incompatible sdata argument");
00068     return *this;
00069   }
00070 
00071   if(Sd.get_znorm() == Znorm_ || Sd.get_znorm() == 0) {
00072     // no renormalization required
00073     s.add(f, Sd.S);
00074     c.add(f, Sd.C);
00075   }
00076   else {
00077     // must renormalize sdata first
00078     sdata temp(Sd, Znorm_);
00079     s.add(f, temp.S);
00080     c.add(f, temp.C);
00081   }
00082     
00083   noise_ = true;
00084   return *this; 
00085 }
00086 
00087 
00088 S_interp & S_interp::add_SC(double f, const Matrix & S, const Matrix & C, double Zn)
00089 {
00090   if((S.Lmode != Index_1) && (S.Rmode != Index_1) && (S.Lsize != N) && (S.Rsize != N)) {
00091     error::warning("S_interp::add_SC(): improperly sized S matrix argument");
00092     return *this;
00093   }
00094   if((C.Lmode != Index_1) && (C.Rmode != Index_1) && (C.Lsize != N) && (C.Rsize != N)) {
00095     error::warning("S_interp::add_SC(): improperly sized C matrix argument");
00096     return *this;
00097   }
00098 
00099   if(Znorm_ <= 0.0) Znorm_ = device::Z0;
00100   if(Zn == Znorm_ || Zn <= 0.0) {
00101     // renormalization not needed - just add the matrices to the interpolators
00102     s.add(f,S);
00103     c.add(f,C);
00104   }
00105   else {
00106     // need to renormalize first; use an sdata to accomplish this
00107     sdata temp(N);
00108     temp.set_znorm(Zn);
00109     temp.S = S;
00110     temp.C = C;
00111     temp.change_norm(Znorm_);
00112     s.add(f,temp.S);
00113     c.add(f,temp.C);
00114   }    
00115 
00116   return *this;
00117 }
00118 
00119 
00120 bool S_interp::touchstone(const char * name, double f_scale)
00121 {
00122   touchstone_read d;
00123   if(!d.open(name, N, f_scale)) return false;
00124 
00125   if(Znorm_ <= 0.0) Znorm_ = device::Z0;
00126   double f;
00127   Matrix S;
00128 
00129   // read in the S matrix data and rebuild the S interpolator
00130   while(d.Svalue(f,S)) add_S(f,S);
00131   s.build();
00132 
00133   // if a 2-port, there may also be noise data
00134   if(N == 2 && d.has_noise()) {
00135     noise_ = true;
00136 
00137     // here's where we fetch and convert the noise data:
00138     Matrix C(2);
00139     touchstone_read::noise N;
00140     double To = 290.0*Kelvin;
00141     double Zo = device::Z0;
00142     while(d.get_noise(f,N)) {
00143       S = s(f);
00144       // renormalize S to device::Z0 if necessary
00145       if (Znorm_ != Zo) S = S_renormalize(S,Zo,Znorm_);
00146 
00147       double Tmin = To * (pow(10.0, N.Fmin/10.0) - 1.0); // noise figure to T
00148       double t = (4.0*To*N.Reff/Zo)/norm(1 + N.Gopt);  // an intermediate calc
00149 
00150       C[1][1] = Tmin*(norm(S[1][1]) - 1) + t*norm(1 - S[1][1]*N.Gopt);
00151       C[2][2] = norm(S[2][1])*(Tmin + t*norm(N.Gopt));
00152       C[1][2] = zconj(S[2][1])*(S[1][1]*(Tmin + t*norm(N.Gopt)) - t*zconj(N.Gopt));
00153       C[2][1] = zconj(C[1][2]);
00154 
00155       // if necessary renormalize C to Znorm_
00156       if (Znorm_ != Zo) {
00157         Matrix F = identity_matrix(2,Index_1);
00158         double rho = sqrt(Znorm_ / Zo) ;
00159         double Sigma = 0.5*(1./rho + rho) ;
00160         double Delta = 0.5*(1./rho - rho) ;
00161         F = Sigma*F - Delta*S;
00162         C = F*C*dagger(F);
00163       }
00164 
00165       // put result into the interpolation
00166       c.add(f,C);
00167 
00168     } // while()
00169     c.build();
00170 
00171   } // if
00172 
00173   return d.good() && s.ready() && (!noise_ || c.ready());
00174 }
00175 
00176 
00177 // ********************************************************************
00178 
00179 sdata_interp::sdata_interp(int ports, const abstract_real_parameter & f)
00180   : nport(ports), pf(&f), S(ports)
00181 { 
00182   if(ports <= 0) error::fatal("sdata_interp: must be constructed with ports > 0");
00183   info.source = false;
00184 }
00185 
00186 
00187 bool sdata_interp::copy(const S_interp & s)
00188 {
00189   if (s.ports() != size()) {
00190     error::warning("sdata_interp::copy(): argument has incorrect number of ports.");
00191     return false;
00192   }
00193   else {
00194     S = s;
00195     return true;
00196   }
00197 }
00198 
00199 
00200 void sdata_interp::recalc_S()
00201 {
00202   if (!ready()) {
00203     error::warning("sdata_interp::recalc(): interpolator is empty or not ready");
00204     return;
00205   }
00206 
00207   // perform the interpolation and put in nport's sdata object
00208   if(S.fill(data,*pf)) {
00209     // data.C has been filled; adjust normalization and return
00210     data.change_norm(device::Z0);
00211   }
00212   else {
00213     // only data.S has been filled; data.C has stale values
00214     if(data.get_znorm() != device::Z0) {
00215       data.S = S_renormalize(data.S, device::Z0, data.get_znorm());
00216       data.set_znorm(device::Z0);
00217     }
00218   }
00219 }
00220 
00221 void sdata_interp::recalc()
00222 {
00223   // recalc_S() also interpolates C matrix if available
00224   recalc_S();
00225 
00226   // if recalc_S didn't generate a C matrix, then generate a passive one
00227   if(!S.has_noise()) data.passive_noise(device::f, device::T);
00228 }
00229 
00230 
00231 // ********************************************************************
00232 
00233 void S_to_sdata(sdata & SD, const Matrix & S, double Zn)
00234 {
00235   SD.S = S;
00236   SD.set_znorm(Zn);
00237   SD.passive_noise(device::f, device::T);
00238   SD.B = 0.0;
00239 }
00240 
00241 
00242 Matrix S_renormalize(const Matrix & S, double Znew, double Zold)
00243 {
00244   if(Znew == Zold)
00245     return S;
00246   else {
00247     // assumes S is square with indexing mode Index_1
00248     int N = S.Lmaxindex();
00249     double r = (Zold - Znew)/(Zold + Znew);
00250     Matrix i = identity_matrix(N);
00251     return solve((i + r*S), (r*i + S));
00252   }
00253 }

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