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

sdata.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 // sdata.cc
00031 //
00032 // Change history:
00033 // 11/2/00:  Added passive_noise_temp()
00034 // 10/28/99: Fixed normalization Z == 0 handling in ydata and zdata
00035 // 10/22/99: Changes to handling of z_norm and device::Z0; fixed math
00036 //           in conversion constructors
00037 // 10/8/99:  Slight speedup in sdata::change_norm()
00038 // 11/11/98: Changed table access to new syntax 
00039 // 10/7/98:  Speeded up sdata conversion constructors 
00040 // 9/25/98:  Speeded up sdata::passive_noise() 
00041 // 9/15/98:  Fixed a nasty bug: wrong argument order in 
00042 //           passive noise calculations. 
00043 // 8/27/98:  Added SdB, tn, and NF (JSW) 
00044 // 7/28/98:  added <math.h> to includes, since SIScmplx.h doesn't
00045 // 7/8/98:   Added sdata::reindex(); ydata_ptr 
00046 // 6/22/98:  Added indexing mode flexibility, changed size to 
00047 //           size() 
00048 // 2/10/98:  Modified definitions of current, voltage noise 
00049 //           correlation matrices to be in "ordinary" rather 
00050 //           than temperature units. (J.Z.)
00051 
00052 #include "units.h"
00053 #include "error.h"
00054 #include "nport.h"
00055 #include "Amath.h"
00056 #include <math.h>
00057 
00058 //
00059 // passive_noise_temp()
00060 //
00061 
00062 double passive_noise_temp(double freq, double Temp)
00063 {
00064   if(Temp < 0.0)
00065   {
00066     error::warning("Can't compute passive noise for negative temperature.");
00067     Temp = -Temp;
00068   }
00069 
00070   if(freq < 0.0)
00071   {
00072     error::warning("Can't compute passive noise for negative frequency.");
00073     freq = -freq;
00074   }
00075 
00076   if(Temp < Tiny) Temp = Tiny;
00077   double h_f_over_2_kB = 0.5 * hPlanck * freq / BoltzK;
00078  
00079   // in the limit freq -> 0, d is simply the temperature:
00080   return (freq == 0.0) ? Temp : h_f_over_2_kB / tanh(h_f_over_2_kB / Temp);
00081 }  
00082 
00083 
00084 //
00085 // sdata member functions
00086 //
00087 
00088 sdata::sdata(int s, v_index_mode t) :
00089   z_norm(0.0), S(s,t), C(s,t), B(s,t)  // if s < 0, size 0 objects are created (cf table.cc)
00090 {
00091   if(s<0) error::fatal("Cannot create sdata for negative number of ports.");
00092 }
00093 
00094 sdata::sdata(const sdata &sd) :
00095   z_norm(sd.z_norm), S(sd.S), C(sd.C), B(sd.B)
00096 { }
00097 
00098 sdata::sdata(const sdata &sd, double z0) :
00099   z_norm(sd.z_norm), S(sd.S), C(sd.C), B(sd.B)
00100 { change_norm(z0); }
00101 
00102 sdata::sdata(const zdata &zd, double z0) :
00103   z_norm(z0), S(0), C(0), B(0)
00104 {
00105   S.resize(zd.Z); C.resize(zd.Z); B.resize(zd.Vs);
00106 
00107   if(z0 <= 0.) {
00108     error::warning(
00109     "Zero or negative normalization impedance passed to sdata constructor !");
00110     z_norm = z0 = device::Z0 ;   // just use default normalization
00111   }
00112   if(S.Lmaxindex() != S.Rmaxindex()) {
00113     error::fatal(
00114     "sdata constructor: zdata::Z matrix must be square.");
00115   }
00116 
00117   // use special fast matrix math subroutines
00118   Matrix Temp; Temp.resize(zd.Z);
00119   IplusM(Temp, z_norm, zd.Z);  // Temp = Z + z_norm*I
00120 
00121   IplusM(S, -z_norm, zd.Z);    // S = Z - z_norm*I (temporarily)
00122   S = solve(Temp, S);          // S = (Z + z_norm*I)^(-1) (Z - z_norm*I)
00123 
00124   B = solve(Temp, zd.Vs);
00125   B *= sqrt(z_norm);           // B = sqrt(z_norm) (Z + z_norm*I)^(-1) Vs
00126 
00127   IminusM(Temp, 1, S);         // Temp = I - S
00128   MAMdagger(C, Temp, zd.C);    // C = (I - S) * Cz * dagger(I - S)
00129   C *= 1.0/(4*z_norm*BoltzK);
00130 }
00131 
00132 sdata::sdata(const ydata &yd, double z0) :
00133   z_norm(z0), S(0), C(0), B(0)
00134 {
00135   S.resize(yd.Y); C.resize(yd.Y); B.resize(yd.Is);
00136 
00137   if(z0 <= 0.) {
00138     error::warning(
00139     "Zero or negative normalization impedance passed to sdata constructor !");
00140     z_norm = device::Z0 ;
00141   }
00142   if(S.Lmaxindex() != S.Rmaxindex()) {
00143     error::fatal(
00144     "sdata constructor: ydata::Y matrix must be square.");
00145   }
00146 
00147   // use special fast matrix math subroutines
00148   Matrix Temp; Temp.resize(yd.Y);
00149   IplusM(Temp, 1/z_norm, yd.Y);  // Temp = I/z_norm + Y
00150 
00151   IminusM(S, 1/z_norm, yd.Y);    // S = I/z_norm - Y (temporarily)
00152   S = solve(Temp, S);            // S = (I/z_norm + Y)^(-1) (I/z_norm - Y)
00153 
00154   B = solve(Temp, yd.Is);
00155   B *= -1.0/sqrt(z_norm);        // B = -sqrt(z_norm) (I + z_norm Y)^(-1) Is
00156 
00157   IplusM(Temp, 1, S);            // Temp = I + S
00158   MAMdagger(C, Temp, yd.C);      // C = (I + S) * Cy * dagger(I + S)
00159   C *= z_norm/(4*BoltzK);
00160 }
00161 
00162 sdata::sdata(const ydata_ptr &yp, double z0) :
00163   z_norm(z0), S(0), C(0), B(0)
00164 {
00165   if(z0 <= 0.) {
00166     error::warning(
00167     "Zero or negative normalization impedance passed to sdata constructor !");
00168     z_norm = device::Z0 ;
00169   }
00170   if(yp.pY == 0) {
00171     error::warning(
00172     "Initializing sdata object from an uninitialized ydata_ptr object !");
00173     return;
00174   }
00175 
00176   S.resize(*(yp.pY)); C.resize(*(yp.pY)); B.reallocate(yp.pY->Rsize, yp.pY->Rmode);
00177   if(S.Lmaxindex() != S.Rmaxindex()) {
00178     error::fatal(
00179     "sdata constructor: ydata_ptr::pY must point to a square matrix.");
00180   }
00181 
00182   Matrix Temp; Temp.resize(S);
00183   IplusM(Temp, 1/z_norm, (*yp.pY));  // Temp = I/z_norm + Y
00184 
00185   IminusM(S, 1/z_norm, (*yp.pY));    // S = I/z_norm - Y (temporarily)
00186   S = solve(Temp, S);                // S = (I/z_norm + Y)^(-1) (I/z_norm - Y)
00187 
00188   if(yp.pIs) {
00189     B = solve(Temp, (*yp.pIs));
00190     B *= -1.0/sqrt(z_norm);          // B = -sqrt(z_norm) (I + z_norm Y)^(-1) Is
00191   }
00192 
00193   if(yp.pC) {
00194     IplusM(Temp, 1, S);              // Temp = I + S
00195     MAMdagger(C, Temp, (*yp.pC));    // C = Temp * C * dagger(Temp)
00196     C *= z_norm/(4*BoltzK);
00197   }
00198 }
00199 
00200 sdata & sdata::resize(int n)
00201 {
00202   if(n < 0) {
00203     error::warning(
00204     "Cannot resize sdata to a size < 0. Using size = 0 !") ;
00205     n = 0;
00206   }
00207   S.resize(n); C.resize(n); B.resize(n);
00208   return *this;
00209 }
00210 
00211 double sdata::SdB(int i, int j) const
00212 {
00213   return 10.0 * log10(norm(S.read(i, j)));
00214 }
00215 
00216 double sdata::tn(int i, int j) const
00217 {
00218   return abs(C.read(i, i)) / norm(S.read(i, j));
00219 }
00220 
00221 double sdata::NF(int i, int j) const
00222 {
00223   return 10.0 * log10(1.0 + tn(i, j)/(290.0*Kelvin));
00224 }
00225 
00226 sdata & sdata::set_znorm(double z)
00227 {
00228   if(z < 0.) {
00229     error::warning(
00230     "Cannot set sdata to a normalization impedance < 0. Using absolute value !") ;
00231     z = -z;
00232   }
00233 
00234   z_norm = z;
00235   return *this;
00236 }
00237 
00238 sdata & sdata::change_norm(double new_z0)
00239 {
00240   if(new_z0 <= 0.) {
00241     error::warning(
00242     "Cannot change_norm sdata to a normalization impedance <= 0. !") ;
00243     return *this;
00244   }
00245   if((new_z0 == z_norm)||(z_norm == 0.0))
00246     return *this;   // no action required
00247 
00248   // if we get here, then new_z0 > 0 and new_z0 != z_norm != 0
00249   if(S.Lmaxindex() != S.Rmaxindex()) {
00250     error::fatal(
00251     "sdata::change_norm(): S matrix must be square.");
00252   }
00253 
00254   double rho = sqrt(new_z0/z_norm) ;
00255   z_norm = new_z0 ;
00256   double Sigma = 0.5*(1./rho + rho) ;
00257   double Delta = 0.5*(1./rho - rho) ;
00258 
00259   Matrix I = identity_matrix(S) ;
00260   Matrix Factor = Sigma*I - Delta*S ;
00261   B = Factor * B ;
00262   C = Factor * C * dagger(Factor) ;
00263   Factor += (2*Delta) * S ;    // now Factor == Sigma*I + Delta*S
00264   S = solve(Factor, Delta*I + Sigma*S);
00265   return *this;
00266 }
00267 
00268 
00269 sdata & sdata::passive_noise(double freq, double Temp)
00270 {
00271   if(Temp < 0.0)
00272   {
00273     error::warning("Can't compute passive noise for negative temperature.");
00274     Temp = -Temp;
00275   }
00276 
00277   if(freq < 0.0)
00278   {
00279     error::warning("Can't compute passive noise for negative frequency.");
00280     freq = -freq;
00281   }
00282 
00283   if(Temp < Tiny) Temp = Tiny;
00284   double h_f_over_2_kB = 0.5 * hPlanck * freq / BoltzK;
00285  
00286   // in the limit freq -> 0, d is simply the temperature:
00287   double d = (freq == 0.0) ? Temp : h_f_over_2_kB / tanh(h_f_over_2_kB / Temp);
00288   // C = d*(I - S*dagger(S));  this is calculated in the code that follows:
00289 
00290   // size the C matrix and set some index limits
00291   int min = S.Lminindex(), max = S.Lmaxindex();
00292   if ((min != S.Rminindex())||(max != S.Rmaxindex()))
00293     // then S isn't square
00294     error::fatal("S matrix isn't square in sdata::passive_noise.");
00295   C.resize(S);
00296   int len = max - min + 1; len = (len < 0) ? 0 : len;   // length of a row of S
00297   complex *ai, *aj;
00298   double neg_d = -d;
00299   for (int i = min; i <= max; ++i) {
00300     ai = & S[i][min];
00301     C[i][i] = d*(complex(1) - Adot(ai,ai,len));
00302     for (int j = i + 1; j <= max; ++j) {
00303       aj = & S[j][min];
00304       C[j][i] = conj( C[i][j] = neg_d * Adot(aj,ai,len) );
00305     }
00306   }
00307 
00308   return *this;
00309 }
00310 
00311 //*************************************************************
00312 // zdata member functions
00313 //
00314 
00315 zdata::zdata(int s, v_index_mode t) :
00316   Z(s,t), C(s,t), Vs(s,t)    // vector and table classes handle s < 0 gracefully
00317 {
00318   if(s<0) error::fatal("Cannot create zdata for negative number of ports.");
00319 }
00320 
00321 zdata::zdata(const zdata &zd) :
00322   Z(zd.Z), C(zd.C), Vs(zd.Vs)
00323 { }
00324 
00325 zdata::zdata(const sdata &sd) :
00326   Z(0), C(0), Vs(0)
00327 {
00328   double z0 = sd.get_znorm() ;
00329   if(z0 < 0.) {
00330     error::warning(
00331     "Normalization impedance < 0. in sdata to zdata constructor!");
00332   }
00333   else {
00334     if (z0 == 0.0) z0 = device::Z0;  // z0 == 0 means impedance doesn't matter
00335     Matrix I = identity_matrix(sd.size(),sd.mode()) ;
00336     Matrix Temp = inverse(I - sd.S) ;
00337     if (Temp.maxindex() < sd.size()) {
00338       // then (I - sd.S) is singular;
00339       error::warning(
00340       "Impedance representation does not exist in sdata to zdata constructor!");
00341     }
00342     else {
00343       Z = z0*(Temp * (I + sd.S)) ;
00344       C = (4.0 * BoltzK *z0)*(Temp * sd.C * dagger(Temp)) ;
00345       Vs = (2.0 * sqrt(z0))*(Temp * sd.B) ;
00346     }
00347   }
00348 }
00349 
00350 zdata::zdata(const ydata &yd) :
00351   Z(0), C(0), Vs(0)
00352 {
00353   Z = inverse(yd.Y) ;
00354   if (Z.maxindex() < yd.size()) {
00355     // then yd.Y is singular;
00356     error::warning(
00357     "Impedance representation does not exist in ydata to zdata constructor!");
00358   }
00359   else {
00360     C = Z * yd.C * dagger(Z) ;
00361     Vs = -Z * yd.Is ;
00362   }
00363 }
00364 
00365 zdata & zdata::passive_noise(double freq, double Temp)
00366 {
00367   if(Temp < 0.0)
00368   {
00369     error::warning("Can't compute passive noise for negative temperature.");
00370     Temp = -Temp;
00371   }
00372 
00373   if(freq < 0.0)
00374   {
00375     error::warning("Can't compute passive noise for negative frequency.");
00376     freq = -freq;
00377   }
00378 
00379   if(Temp < Tiny) Temp = Tiny;
00380   double h_f_over_2 = 0.5 * hPlanck * freq ;
00381   double h_f_over_2_kB = h_f_over_2 / BoltzK;
00382  
00383   // in the limit freq -> 0, d is simply the temperature:
00384   double d = (freq == 0.0) ? BoltzK*Temp : 
00385                              h_f_over_2 / tanh(h_f_over_2_kB / Temp);
00386 
00387   C = (2.0 * d) * (Z + dagger(Z)) ;
00388   return *this;
00389 }
00390 
00391 
00392 //*************************************************************
00393 // ydata member functions
00394 //
00395 
00396 ydata::ydata(int s, v_index_mode t) :
00397   Y(s,t), C(s,t), Is(s,t)
00398 {
00399   if(s<0) error::fatal("Cannot create ydata for negative number of ports.");
00400 }
00401 
00402 ydata::ydata(const ydata &yd) :
00403   Y(yd.Y), C(yd.C), Is(yd.Is)
00404 { }
00405 
00406 ydata::ydata(const sdata &sd) :
00407   Y(0), C(0), Is(0)
00408 {
00409   double z0 = sd.get_znorm() ;
00410   if(z0 < 0.) {
00411     error::warning(
00412     "Normalization impedance < 0. in sdata to ydata constructor!");
00413   }
00414   else {
00415     if (z0 == 0.0) z0 = device::Z0;  // z0 == 0 means impedance doesn't matter
00416     Matrix I = identity_matrix(sd.size(),sd.mode()) ;
00417     Matrix Temp = inverse(I + sd.S) ;
00418     if (Temp.maxindex() < sd.size()) {
00419       // then (I + sd.S) is singular;
00420       error::warning(
00421       "Admittance representation does not exist in sdata to ydata constructor!");
00422     }
00423     else {
00424       Y = (1.0 / z0)*(Temp * (I - sd.S)) ;
00425       C = (4.0 *BoltzK / z0)*(Temp * sd.C * dagger(Temp)) ;
00426       Is = (-2.0 / sqrt(z0))*(Temp * sd.B) ;
00427     }
00428   }
00429 }
00430 
00431 ydata::ydata(const zdata &zd) :
00432   Y(0), C(0), Is(0)
00433 {
00434   Y = inverse(zd.Z) ;
00435   if (Y.maxindex() < zd.size()) {
00436     // then Y is singular;
00437     error::warning(
00438     "Admittance representation does not exist in zdata to ydata constructor!");
00439   }
00440   else {
00441     C = Y * zd.C * dagger(Y) ;
00442     Is = -Y * zd.Vs ;
00443   }
00444 }
00445 
00446 ydata & ydata::passive_noise(double freq, double Temp)
00447 {
00448   if(Temp < 0.0)
00449   {
00450     error::warning("Can't compute passive noise for negative temperature.");
00451     Temp = -Temp;
00452   }
00453 
00454   if(freq < 0.0)
00455   {
00456     error::warning("Can't compute passive noise for negative frequency.");
00457     freq = -freq;
00458   }
00459 
00460   if(Temp < Tiny) Temp = Tiny;
00461   double h_f_over_2 = 0.5 * hPlanck * freq ;
00462   double h_f_over_2_kB = h_f_over_2 / BoltzK;
00463  
00464   // in the limit freq -> 0, d is simply the temperature:
00465   double d = (freq == 0.0) ? BoltzK*Temp : 
00466                              h_f_over_2 / tanh(h_f_over_2_kB / Temp);
00467 
00468   C = (2.0 * d) * (Y + dagger(Y));
00469   return *this;
00470 }

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