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

lna_opt.cc

Go to the documentation of this file.
00001 // Build a two-stage low noise amplifier, and optimize the component values.
00002 
00003 #include "supermix.h"
00004  
00005 int main()
00006 {
00007   device::T = 4.2 * Kelvin;
00008   device::Z0 = 50. * Ohm;
00009 
00010   // ==========================================================================
00011   // Building the circuit:
00012 
00013   fhx13x t1, t2;            // Field-effect transistors made by Fujitsu.
00014   t1.Ls.L = 0.05 * nHenry;  // adjusting the source inductance values a bit...
00015   t2.Ls.L = 0.05 * nHenry;
00016   inductor lg1, lg2;        // Gate tuning inductors.
00017 
00018   resistor rd1, rd2;        // Drain bias resistors.
00019   lg1.series();
00020   lg1.series();
00021   rd1.parallel();
00022   rd2.parallel();
00023   // The inductance and resistance values will be found by the optimizer
00024 
00025   circuit amp;
00026   int input = amp.add_port(lg1, 1);
00027   amp.connect(lg1, 2, t1, 1);
00028   amp.connect(t1, 2, rd1, 1);
00029   amp.connect(rd1, 2, lg2, 1);
00030   amp.connect(lg2, 2, t2, 1);
00031   amp.connect(t2, 2, rd2, 1);
00032   int output = amp.add_port(rd2, 2);
00033 
00034   // ==========================================================================
00035   // Setting up the error function for the optimization:
00036 
00037   error_func ef;
00038   lg1.L = ef.vary(  1.0,    3.0,    20.0,  nHenry );
00039   lg2.L = ef.vary(  0.2,    1.0,    10.0,  nHenry );
00040   rd1.R = ef.vary( 30.0,  100.0,   500.0,  Ohm    );
00041   rd2.R = ef.vary( 30.0,  100.0,   150.0,  Ohm    );
00042 
00043   sweeper gain_band, stability_band;
00044 
00045        gain_band.sweep( device::f, 4.0*GHz,  8.0*GHz, 0.25*GHz );
00046   stability_band.sweep( device::f, 0.1*GHz, 20.1*GHz, 0.50*GHz );
00047 
00048   // Optimize for stability.
00049   amp_k         stb1_term(amp);
00050   amp_mag_delta stb2_term(amp);
00051 
00052   // Keep the gain high.
00053   gain_dB  gain_term(amp, input, output);
00054   gain_term.above(20.0);
00055 
00056   // Optimize for flat gain.
00057   gain_dB  flatness_term(amp, input, output);
00058   flatness_term.flat();
00059 
00060   // Optimize the output match.
00061   gain_dB  out_match_term(amp, output, output);
00062   out_match_term.below(-15.0);
00063 
00064   // Optimize the input match.
00065   gain_dB  in_match_term(amp, input, input);
00066   in_match_term.below(-10.0);
00067 
00068   // Optimize for low noise.
00069   input_tn noise_term(amp, input, output);
00070   noise_term.match(0.0);
00071 
00072   ef.add_term( 10.0,       stb1_term,  stability_band );
00073   ef.add_term( 10.0,       stb2_term,  stability_band );
00074   ef.add_term(  1.5,       gain_term,       gain_band );
00075   ef.add_term( 20.0,   flatness_term,       gain_band );
00076   ef.add_term(  1.0,  out_match_term,       gain_band );
00077   ef.add_term(  1.0,   in_match_term,       gain_band );
00078   ef.add_term( 10.0,      noise_term,       gain_band );
00079 
00080   // ==========================================================================
00081   // Setting up the optimization algorithm:
00082 
00083   powell opt(ef);
00084   opt.verbose();
00085   opt.FTOL = 0.00001;
00086 
00087   // ==========================================================================
00088   // Perform the optimization, displaying the resulting optimized values:
00089 
00090   cout << endl << "2 stage cryogenic low-noise amplifier" << endl << endl;
00091   cout << "Starting optimization:" << endl << endl;
00092 
00093   double error_val = opt.minimize();
00094 
00095   cout << endl << "Final error function value: " << error_val  << endl ;
00096   cout << "Error function breakdown by term:" << endl;
00097   cout << ef.get_func_breakdown() << endl;
00098 
00099   cout << "Final parameters are:" << endl;
00100   cout << "lg1(nH)" << " " << "lg2(nH)" << " " << "rd1(O) " << " " << "rd2(O)";
00101 
00102   ef.get_parms_user().show() ;
00103 
00104 
00105   // ==========================================================================
00106   // Now display the response of our amplifier using the optimized values:
00107 
00108   cout << endl << "Response:" << endl << endl;
00109   cout << setw(8) << "Freq" << "  "  
00110        << setw(8) << "S21(dB)" << "  "  
00111        << setw(8) << "S22(dB)" << "  "  
00112        << setw(8) << "Tn(K)" << "  "  
00113        << setw(8) << "NF(dB)" << endl << endl;
00114 
00115   ampdata response;
00116 
00117   for(double freq = 1.0; freq <=12.0; freq += 0.5)
00118   {
00119     device::f = freq * GHz;
00120     response = amp.get_data();
00121 
00122     cout << fixed << setprecision(4) 
00123          << setw(8) << freq << "  "
00124          << setw(8) << response.SdB(output,input) << "  " 
00125          << setw(8) << response.SdB(output,output) << "  "
00126          << setw(8) << response.tn(output,input)/Kelvin << "  " 
00127          << setw(8) << response.NF(output,input) << "  ";
00128 
00129     if(response.unconditionally_stable()) cout << "Unconditionally Stable";
00130 
00131     cout << endl;
00132   }
00133 
00134   cout << endl;
00135 }

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