Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

refractive_atmosphere.h

Go to the documentation of this file.
00001 /*
00002 Arroyo - software for the simulation of electromagnetic wave propagation
00003 through turbulence and optics.
00004 
00005 Copyright (c) 2000-2004 California Institute of Technology.  Written by
00006 Dr. Matthew Britton.  For comments or questions about this software,
00007 please contact the author at mbritton@astro.caltech.edu.
00008 
00009 This program is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as  published by the
00011 Free Software Foundation; either version 2 of the License, or (at your
00012 option) any later version.
00013 
00014 This program is provided "as is" and distributed in the hope that it
00015 will be useful, but WITHOUT ANY WARRANTY; without even the implied
00016 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  In no
00017 event shall California Institute of Technology be liable to any party
00018 for direct, indirect, special, incidental or consequential damages,
00019 including lost profits, arising out of the use of this software and its
00020 documentation, even if the California Institute of Technology has been
00021 advised of the possibility of such damage.   The California Institute of
00022 Technology has no obligation to provide maintenance, support, updates,
00023 enhancements or modifications.  See the GNU General Public License for
00024 more details.
00025 
00026 You should have received a copy of the GNU General Public License along
00027 with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00029 */
00030 
00031 #ifndef REFRACTIVE_ATMOSPHERE_H
00032 #define REFRACTIVE_ATMOSPHERE_H
00033 
00034 #include <three_frame.h>
00035 #include <region_base.h>
00036 #include <computational_geometry.h>
00037 #include "AO_sim_base.h"
00038 #include "fits_header_data.h"
00039 #include "pixel_array.h"
00040 #include "power_spectrum.h"
00041 #include "propagation_plan.h"
00042 #include "aperture.h"
00043 #include "emitter.h"
00044 #include "special_functions.h"
00045 
00046 namespace Arroyo {
00047 
00048   using std::vector;
00049   using std::ostream;
00050 
00051   class subharmonic_method;
00052 
00059 
00060   class refractive_atmospheric_model :
00061     virtual public AO_sim_base {
00062 
00063     private:
00064     
00065     static const bool factory_registration;
00066 
00069     string unique_name() const {return(string("refractive atmospheric model"));};
00070 
00071     protected:
00072 
00074     vector<power_spectrum *> power_spectra_;
00075 
00077     vector<double> layer_heights_;
00078 
00080     three_frame ground_ref_frame_;
00081 
00087     void read_common_data(const iofits & iof);
00088 
00094     void write_common_data(iofits & iof) const;
00095 
00096     public:
00097   
00100     refractive_atmospheric_model(){};
00101 
00104     refractive_atmospheric_model(const refractive_atmospheric_model & ref_atm_model);
00105 
00108     refractive_atmospheric_model(const char * filename);
00109 
00112     refractive_atmospheric_model(const iofits & iof);
00113 
00121     refractive_atmospheric_model(const vector<power_spectrum *> & power_spectra, 
00122                                  const vector<double> & layer_heights,
00123                                  const three_frame & ground_ref_frame);
00124 
00127     ~refractive_atmospheric_model();
00128 
00131     refractive_atmospheric_model & 
00132       operator=(const refractive_atmospheric_model & ref_atm_model);
00133 
00138     virtual refractive_atmospheric_model * clone() const {
00139       return new refractive_atmospheric_model(*this);
00140     };
00141 
00144     void read(const char * filename);
00145 
00148     void read(const iofits & iof);
00149 
00152     void write(const char * filename) const;
00153 
00156     void write(iofits & iof) const;
00157 
00160     void print(ostream & os, const char * prefix="") const;
00161 
00164     long get_number_of_layers() const {return layer_heights_.size();};
00165 
00168     vector<double> get_layer_heights() const {return layer_heights_;};
00169 
00173     vector<power_spectrum *> get_power_spectra() const {
00174       vector<power_spectrum *> pspec(this->power_spectra_.size());
00175       for(int i=0; i<pspec.size(); i++)
00176         pspec[i] = power_spectrum::power_spectrum_factory(this->power_spectra_[i]);
00177       return(pspec);
00178     };
00179 
00182     three_frame get_three_frame() const {return this->ground_ref_frame_;};
00183 
00193     double turbulence_moment(double moment, 
00194                              double zenith_angle_degrees=0) const;
00195 
00209     double velocity_moment(const vector<three_vector> & layer_wind_velocities_meters_per_sec,
00210                            double moment, 
00211                            double azimuth_angle_degrees=0,
00212                            double zenith_angle_degrees=0) const;
00213 
00222     double fried_parameter(double wavelength_meters, 
00223                            double zenith_angle_degrees=0, 
00224                            double guide_star_height_meters=-1) const;
00225 
00234     double seeing(double wavelength_meters, 
00235                   double zenith_angle_degrees=0) const;
00236 
00245     double isoplanatic_angle(double wavelength_meters, 
00246                              double zenith_angle_degrees=0) const;
00247 
00256     double isokinetic_angle(double wavelength_meters,
00257                             double aperture_diameter_meters,
00258                             double zenith_angle_degrees=0) const;
00259 
00272     double greenwood_frequency(vector<three_vector> & layer_wind_velocities_meters_per_sec,
00273                                double wavelength_meters, 
00274                                double azimuth_angle_degrees=0,
00275                                double zenith_angle_degrees=0) const;
00276 
00285     double d_0(double guide_star_height_meters,
00286                double wavelength_meters,
00287                double zenith_angle_degrees=0) const;
00288 
00289 
00292     double Tyler_F_1(double x) const;
00293 
00296     double Tyler_H(double & rho, 
00297              double & omega,
00298              vector<double> & numerator_args,
00299              vector<double> & denominator_args) const;
00300 
00303     double Tyler_K_1(double rho, double q) const;
00304 
00307     double Tyler_F_2(double q, 
00308                double omega, 
00309                int nsamples_in_integration) const;
00310       
00313     double Tyler_G_hat(double rho) const;
00314 
00317     double Tyler_G_1(three_vector r1,
00318                three_vector r2) const;
00319 
00322     double Tyler_G_2(three_vector r, 
00323                double q, 
00324                three_vector omega, 
00325                int nsamples_in_integration) const;
00326 
00329     double Tyler_G_3(double q, 
00330                double omega,
00331                int nsamples_in_integration) const;
00332     
00335     double Tyler_G_4(three_vector r1, 
00336                three_vector r2, 
00337                double q, 
00338                three_vector omega, 
00339                int nsamples_in_integration) const;
00340     
00343     void Tyler_get_constants(const emitter & emtr_a,
00344                        const emitter & emtr_b,
00345                        const three_frame & tf,
00346                        double aperture_diameter_meters,
00347                        double & secant_zenith_angle,
00348                        double & max_range_meters,
00349                        double & min_range_meters,
00350                        three_vector & little_omega) const;
00351     
00356     vector<double> get_cn2_coefficients() const;
00357 
00362     double caliph_A(const emitter & emtr_a,
00363                     const emitter & emtr_b,
00364                     double aperture_diameter_meters,
00365                     const three_vector & rho) const;
00366 
00369     template<class T>
00370     pixel_array<T> caliph_A(const emitter & emtr_a,
00371                             const emitter & emtr_b,
00372                             double aperture_diameter_meters,
00373                             double pixel_scale_meters) const;
00374 
00379     double caliph_B(const emitter & emtr_a,
00380                     const emitter & emtr_b,
00381                     double aperture_diameter_meters,
00382                     const three_vector & rho) const;
00383 
00386     template<class T>
00387     pixel_array<T> caliph_B(const emitter & emtr_a,
00388                             const emitter & emtr_b,
00389                             double aperture_diameter_meters,
00390                             double pixel_scale_meters) const;
00391 
00397     double caliph_C(const emitter & emtr_a,
00398                     const emitter & emtr_b,
00399                     double aperture_diameter_meters,
00400                     const three_vector & rho_1,
00401                     const three_vector & rho_2) const;
00402 
00405     template<class T>
00406     pixel_array<T> caliph_C(const emitter & emtr_a,
00407                             const emitter & emtr_b,
00408                             double aperture_diameter_meters,
00409                             double pixel_scale_meters) const;
00410 
00413     double caliph_D(const emitter & emtr_a,
00414                     const emitter & emtr_b,
00415                     double aperture_diameter_meters,
00416                     int nsteps_in_integration) const;
00417 
00420     double caliph_E(const emitter & emtr_a,
00421                     const emitter & emtr_b,
00422                     double aperture_diameter_meters,
00423                     int nsteps_in_integration) const;
00424 
00427     double caliph_F(const emitter & emtr_a,
00428                     const emitter & emtr_b,
00429                     double aperture_diameter_meters,
00430                     int nsteps_in_integration) const;
00431 
00434     double caliph_F_bar(const emitter & emtr_a,
00435                         const emitter & emtr_b,
00436                         double aperture_diameter_meters,
00437                         int nsteps_in_integration) const;
00438 
00439     /*
00442     double tmp_tyler_G_1_plus(const emitter & emtr_a,
00443                               const emitter & emtr_b,
00444                               double aperture_diameter_meters,
00445                               const three_vector & rho) const;
00446 
00449     double tmp_tyler_G_1_minus(const emitter & emtr_a,
00450                                const emitter & emtr_b,
00451                                double aperture_diameter_meters,
00452                                const three_vector & rho) const;
00453 
00456     double caliph_G_3(const emitter & emtr_a,
00457                       const emitter & emtr_b,
00458                       double aperture_diameter_meters,
00459                       int nsteps_in_integration) const;
00460     */
00461 
00466     double caliph_G(const emitter & emtr_a,
00467                     const emitter & emtr_b,
00468                     double aperture_diameter_meters,
00469                     const three_vector & rho) const;
00470 
00473     template<class T>
00474     pixel_array<T> caliph_G(const emitter & emtr_a,
00475                             const emitter & emtr_b,
00476                             double aperture_diameter_meters,
00477                             double pixel_scale_meters) const;
00478 
00483     double caliph_H(const emitter & emtr_a,
00484                     const emitter & emtr_b,
00485                     double aperture_diameter_meters,
00486                     const three_vector & rho) const;
00487 
00490     template<class T>
00491     pixel_array<T> caliph_H(const emitter & emtr_a,
00492                             const emitter & emtr_b,
00493                             double aperture_diameter_meters,
00494                             double pixel_scale_meters) const;
00495 
00500     double caliph_I(const emitter & emtr_a,
00501                     const emitter & emtr_b,
00502                     double aperture_diameter_meters,
00503                     const three_vector & rho) const;
00504 
00507     template<class T>
00508     pixel_array<T> caliph_I(const emitter & emtr_a,
00509                             const emitter & emtr_b,
00510                             double aperture_diameter_meters,
00511                             double pixel_scale_meters) const;
00512 
00517     double caliph_J(const emitter & emtr_a,
00518                     const emitter & emtr_b,
00519                     double aperture_diameter_meters,
00520                     const three_vector & rho) const;
00521 
00524     template<class T>
00525     pixel_array<T> caliph_J(const emitter & emtr_a,
00526                             const emitter & emtr_b,
00527                             double aperture_diameter_meters,
00528                             double pixel_scale_meters) const;
00529     
00532     double caliph_K(const emitter & emtr_a,
00533                     const emitter & emtr_b,
00534                     double aperture_diameter_meters,
00535                     int nsteps_in_integration) const;
00536 
00539     double caliph_L(const emitter & emtr_a,
00540                     const emitter & emtr_b,
00541                     double aperture_diameter_meters,
00542                     int nsteps_in_integration) const;
00543 
00546     double caliph_M(const emitter & emtr_a,
00547                     const emitter & emtr_b,
00548                     double aperture_diameter_meters) const;
00549 
00562     double aperture_averaged_phase_covariance(const emitter & emtr_a,
00563                                               const emitter & emtr_b,
00564                                               const aperture & ap,
00565                                               double wavelength_meters,
00566                                               int nsteps_in_integration=1000) const;
00567 
00580     double aperture_averaged_tilt_phase_covariance(const emitter & emtr_a,
00581                                                    const emitter & emtr_b,
00582                                                    const aperture & ap,
00583                                                    double wavelength_meters,
00584                                                    int nsteps_in_integration=1000) const;
00585       
00596     double aperture_averaged_parallel_tilt_phase_covariance(const emitter & emtr_a,
00597                                                             const emitter & emtr_b,
00598                                                             const aperture & ap,
00599                                                             double wavelength_meters,
00600                                                             int nsteps_in_integration=1000) const;
00601       
00612     double aperture_averaged_perpendicular_tilt_phase_covariance(const emitter & emtr_a,
00613                                                                  const emitter & emtr_b,
00614                                                                  const aperture & ap,
00615                                                                  double wavelength_meters,
00616                                                                  int nsteps_in_integration=1000) const;
00617     
00633     double phase_covariance(const emitter & emtr_a,
00634                             const three_point & pupil_location_one,
00635                             const emitter & emtr_b,     
00636                             const three_point & pupil_location_two,
00637                             const aperture & ap,
00638                             double wavelength_meters,
00639                             int nsteps_in_integration=1000) const;
00640     
00656     double tilt_phase_covariance(const emitter & emtr_a,
00657                                  const three_point & pupil_location_one,
00658                                  const emitter & emtr_b,
00659                                  const three_point & pupil_location_two,
00660                                  const aperture & ap,
00661                                  double wavelength_meters,
00662                                  int nsteps_in_integration=1000) const;
00663 
00681     template<class T>
00682       diffractive_wavefront_header<T> get_diffractive_wavefront_header(double wavelength, 
00683                                                                        double pixscale,
00684                                                                        const emitter * emtr,
00685                                                                        const aperture * ap,
00686                                                                        bool layer_foreshortening, 
00687                                                                        propagation_plan * pplan) const;
00688 
00689 
00716     template<class T, class U>
00717       void get_refractive_atmospheric_layers(const vector<double> & layer_pixscales,
00718                                              const subharmonic_method & subm,
00719                                              const vector<diffractive_wavefront_header<T> > dwfhdrs,
00720                                              const vector<three_vector> layer_wind_vectors,
00721                                              double time_interval,
00722                                              bool layer_axes_wind_vector_aligned,
00723                                              bool layer_foreshortening,
00724                                              vector<refractive_atmospheric_layer<U> > & ref_atm_layers) const;
00725 
00726     static int verbose_level;
00727 
00728   };
00729 
00730   // useful anonymous namespace functions for the turbulence
00731   // computations below
00732   namespace {
00733 
00734     void check_wavelength(double wavelength_meters){
00735       if(wavelength_meters<=0){
00736         cerr << "check_wavelength error\n"
00737              << "wavelength " 
00738              << wavelength_meters
00739              << " out of range\n";
00740         throw(string("check_wavelength"));
00741       }
00742     }
00743 
00744     void check_zenith(double zenith_angle_degrees){
00745       if(zenith_angle_degrees<0 ||
00746          zenith_angle_degrees>=90){
00747         cerr << "check_zenith error\n"
00748              << "zenith angle " 
00749              << zenith_angle_degrees
00750              << " out of range\n";
00751         throw(string("check_zenith"));
00752       }
00753     }
00754     
00755     void check_wavelength_zenith(double wavelength_meters, 
00756                                  double zenith_angle_degrees){
00757       check_wavelength(wavelength_meters);
00758       check_zenith(zenith_angle_degrees);
00759     }
00760 
00761     /*
00762     double get_cn2_coefficient(const power_spectrum & pspec){
00763       try{
00764         const isotropic_power_law_spectrum<power_law, null_inner_scale> & iso_pspec = 
00765           dynamic_cast<const isotropic_power_law_spectrum<power_law, null_inner_scale> &>(pspec);
00766         // Defined in Sasiela eq 2.18
00767         double fac = 5*gamma_function(5/6.)/pow(2,4/3.)/pow(M_PI,3/2.)/9./gamma_function(2/3.);
00768         return(iso_pspec.get_power_law().get_coefficient()/2./M_PI/fac);
00769       } catch(...) {
00770         cerr << "get_cn2_coefficient error - power spectrum not Komolgorov\n";
00771         pspec.print(cerr, "pspectrum ");
00772       }
00773     }
00774     */
00775 
00776     double get_cn2_coefficient(double power_law_coefficient){
00777       static double fac = 2*M_PI*5*gamma_function(5/6.)/pow(2,4/3.)/pow(M_PI,3/2.)/9./gamma_function(2/3.);
00778       return(power_law_coefficient/fac);
00779     }
00780   }
00781 
00782 
00783 
00784   template<class T>
00785   pixel_array<T> refractive_atmospheric_model::caliph_A(const emitter & emtr_a,
00786                                                         const emitter & emtr_b,
00787                                                         double aperture_diameter_meters,
00788                                                         double pixel_scale_meters) const {
00789     
00790     if(aperture_diameter_meters<=0){
00791       cerr << "refractive_atmospheric_model::caliph_A error - \n"
00792            << "invalid aperture diameter "
00793            << aperture_diameter_meters
00794            << " passed to this function\n";
00795       throw(string("refractive_atmospheric_model::caliph_A"));
00796     }
00797                                
00798     if(pixel_scale_meters<=0){
00799       cerr << "refractive_atmospheric_model::caliph_A error -\n"
00800            << "pixel scale "
00801            << pixel_scale_meters
00802            << " out of range\n";
00803       throw(string("refractive_atmospheric_model::caliph_A"));
00804     }
00805 
00806     T * data;
00807     vector<long> axes(2,(long)ceil(aperture_diameter_meters/pixel_scale_meters));
00808     try{
00809       data = new T[axes[0]*axes[1]];
00810     } catch(...) {
00811       cerr << "refractive_atmospheric_model::caliph_A - error allocating memory\n";
00812       throw(string("refractive_atmospheric_model::caliph_A"));
00813     }
00814 
00815     try{
00816       double secant_zenith_angle;
00817       double max_range_meters;
00818       double min_range_meters;
00819       three_vector little_omega;
00820       
00821       Tyler_get_constants(emtr_a,
00822                     emtr_b,
00823                     this->ground_ref_frame_,
00824                     aperture_diameter_meters,
00825                     secant_zenith_angle,
00826                     max_range_meters,
00827                     min_range_meters,
00828                     little_omega);
00829 
00830       double val;
00831 
00832       double Q;
00833 
00834       double x_halfpix=0, y_halfpix=0;
00835       int x_extrapix=1, y_extrapix=1;
00836       if(axes[1]%2==0){
00837         x_halfpix = .5;
00838         x_extrapix = 0;
00839       }
00840       if(axes[0]%2==0){
00841         y_halfpix = .5;
00842         y_extrapix = 0;
00843       }
00844 
00845       three_vector pixel_vector;
00846       double normalization_factor = 2*pixel_scale_meters/aperture_diameter_meters;
00847       int index;
00848 
00849       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
00850         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
00851           pixel_vector = 
00852             this->ground_ref_frame_.x()*((i+x_halfpix)*normalization_factor) +
00853             this->ground_ref_frame_.y()*((j+y_halfpix)*normalization_factor);
00854 
00855           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
00856 
00857           if(pixel_vector.length_squared()>1)
00858             data[index]=0;
00859           else {
00860             val = 0;
00861             for(int k=0; k<this->power_spectra_.size(); k++){
00862               if(layer_heights_[k]>min_range_meters) continue;
00863               
00864               Q = (1 - layer_heights_[k]*secant_zenith_angle/min_range_meters) /
00865                 (1 - layer_heights_[k]*secant_zenith_angle/max_range_meters);
00866               
00867               val += secant_zenith_angle*get_cn2_coefficient(power_spectra_[k]->get_coefficient()) * 
00868                 pow((1 - layer_heights_[k]*secant_zenith_angle/max_range_meters),5/3.) *
00869                 pow(Q,5/3.) *
00870                 Tyler_F_1((pixel_vector + 
00871                      (little_omega*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)))).length()
00872                     /Q);
00873             }
00874             data[index] = val;
00875           }
00876         }
00877       }
00878     } catch(...) {
00879       cerr << "refractive_atmospheric_model::caliph_A error\n";
00880       throw(string("refractive_atmospheric_model::caliph_A"));
00881     }
00882 
00883     pixel_array<T> pixarr(axes,data);
00884     delete [] data;
00885     return(pixarr);
00886   }
00887 
00888   template<class T>
00889   pixel_array<T> refractive_atmospheric_model::caliph_B(const emitter & emtr_a,
00890                                                         const emitter & emtr_b,
00891                                                         double aperture_diameter_meters,
00892                                                         double pixel_scale_meters) const {
00893     
00894     if(aperture_diameter_meters==0){
00895       cerr << "refractive_atmospheric_model::caliph_B error - \n"
00896            << "invalid aperture diameter "
00897            << aperture_diameter_meters
00898            << " passed to this function\n";
00899       throw(string("refractive_atmospheric_model::caliph_B"));
00900     }
00901                                
00902     if(pixel_scale_meters<=0){
00903       cerr << "refractive_atmospheric_model::caliph_B error -\n"
00904            << "pixel scale "
00905            << pixel_scale_meters
00906            << " out of range\n";
00907       throw(string("refractive_atmospheric_model::caliph_B"));
00908     }
00909 
00910     T * data;
00911     vector<long> axes(2,(long)ceil(aperture_diameter_meters/pixel_scale_meters));
00912     try{
00913       data = new T[axes[0]*axes[1]];
00914     } catch(...) {
00915       cerr << "refractive_atmospheric_model::caliph_B - error allocating memory\n";
00916       throw(string("refractive_atmospheric_model::caliph_B"));
00917     }
00918 
00919     try{
00920       double secant_zenith_angle;
00921       double max_range_meters;
00922       double min_range_meters;
00923       three_vector little_omega;
00924       
00925       Tyler_get_constants(emtr_a,
00926                     emtr_b,
00927                     this->ground_ref_frame_,
00928                     aperture_diameter_meters,
00929                     secant_zenith_angle,
00930                     max_range_meters,
00931                     min_range_meters,
00932                     little_omega);
00933 
00934       double val;
00935 
00936       double Q;
00937 
00938       double x_halfpix=0, y_halfpix=0;
00939       int x_extrapix=1, y_extrapix=1;
00940       if(axes[1]%2==0){
00941         x_halfpix = .5;
00942         x_extrapix = 0;
00943       }
00944       if(axes[0]%2==0){
00945         y_halfpix = .5;
00946         y_extrapix = 0;
00947       }
00948 
00949       three_vector pixel_vector;
00950       double normalization_factor = 2*pixel_scale_meters/aperture_diameter_meters;
00951       int index;
00952 
00953       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
00954         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
00955           pixel_vector = 
00956             this->ground_ref_frame_.x()*((i+x_halfpix)*normalization_factor) +
00957             this->ground_ref_frame_.y()*((j+y_halfpix)*normalization_factor);
00958 
00959           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
00960           if(pixel_vector.length_squared()>1)
00961             data[index]=0;
00962           else {
00963             val = 0;
00964             for(int k=0; k<this->power_spectra_.size(); k++){
00965               if(layer_heights_[k]>min_range_meters) continue;
00966               
00967               Q = (1 - layer_heights_[k]*secant_zenith_angle/min_range_meters) /
00968                 (1 - layer_heights_[k]*secant_zenith_angle/max_range_meters);
00969               
00970               val += secant_zenith_angle*get_cn2_coefficient(power_spectra_[k]->get_coefficient()) * 
00971                 pow((1 - layer_heights_[k]*secant_zenith_angle/max_range_meters),5/3.) *
00972                 Tyler_F_1(((Q*pixel_vector) - 
00973                      (little_omega*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)))).length());
00974             }
00975             data[index] = val;
00976           }
00977         }
00978       }
00979     } catch(...) {
00980       cerr << "refractive_atmospheric_model::caliph_B error\n";
00981       throw(string("refractive_atmospheric_model::caliph_B"));
00982     }
00983     pixel_array<T> pixarr(axes,data);
00984     delete [] data;
00985     return(pixarr);
00986   }
00987 
00988   template<class T>
00989   pixel_array<T> refractive_atmospheric_model::caliph_C(const emitter & emtr_a,
00990                                                         const emitter & emtr_b,
00991                                                         double aperture_diameter_meters,
00992                                                         double pixel_scale_meters) const {
00993     
00994     if(aperture_diameter_meters==0){
00995       cerr << "refractive_atmospheric_model::caliph_C error - \n"
00996            << "invalid aperture diameter "
00997            << aperture_diameter_meters
00998            << " passed to this function\n";
00999       throw(string("refractive_atmospheric_model::caliph_C"));
01000     }
01001                                
01002     if(pixel_scale_meters<=0){
01003       cerr << "refractive_atmospheric_model::caliph_C error -\n"
01004            << "pixel scale "
01005            << pixel_scale_meters
01006            << " out of range\n";
01007       throw(string("refractive_atmospheric_model::caliph_C"));
01008     }
01009 
01010     T * data;
01011     vector<long> axes(2,(long)ceil(aperture_diameter_meters/pixel_scale_meters));
01012     try{
01013       data = new T[axes[0]*axes[1]];
01014     } catch(...) {
01015       cerr << "refractive_atmospheric_model::caliph_C - error allocating memory\n";
01016       throw(string("refractive_atmospheric_model::caliph_C"));
01017     }
01018 
01019     try{
01020       double secant_zenith_angle;
01021       double max_range_meters;
01022       double min_range_meters;
01023       three_vector little_omega;
01024       
01025       Tyler_get_constants(emtr_a,
01026                     emtr_b,
01027                     this->ground_ref_frame_,
01028                     aperture_diameter_meters,
01029                     secant_zenith_angle,
01030                     max_range_meters,
01031                     min_range_meters,
01032                     little_omega);
01033 
01034       double val;
01035 
01036       double Q;
01037 
01038       double x_halfpix=0, y_halfpix=0;
01039       int x_extrapix=1, y_extrapix=1;
01040       if(axes[1]%2==0){
01041         x_halfpix = .5;
01042         x_extrapix = 0;
01043       }
01044       if(axes[0]%2==0){
01045         y_halfpix = .5;
01046         y_extrapix = 0;
01047       }
01048 
01049       three_vector pixel_vector;
01050       double normalization_factor = 2*pixel_scale_meters/aperture_diameter_meters;
01051       int index;
01052 
01053       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01054         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01055           pixel_vector = 
01056             this->ground_ref_frame_.x()*((i+x_halfpix)*normalization_factor) +
01057             this->ground_ref_frame_.y()*((j+y_halfpix)*normalization_factor);
01058 
01059           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01060 
01061           if(pixel_vector.length_squared()>1)
01062             data[index]=0;
01063           else {
01064             val = 0;
01065             for(int k=0; k<this->power_spectra_.size(); k++){
01066               if(layer_heights_[k]>min_range_meters) continue;
01067               
01068               Q = (1 - layer_heights_[k]*secant_zenith_angle/min_range_meters) /
01069                 (1 - layer_heights_[k]*secant_zenith_angle/max_range_meters);
01070               
01071               val += secant_zenith_angle*get_cn2_coefficient(power_spectra_[k]->get_coefficient()) * 
01072                 pow((1 - layer_heights_[k]*secant_zenith_angle/max_range_meters),5/3.) *
01073                 pow((pixel_vector*(1 - Q) +
01074                      (little_omega*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)))).length(),5/3.);
01075 
01076             }
01077             data[index] = val;
01078             if(!finite(val)){
01079               cerr << "refractive_atmospheric_model::caliph_C error - value " 
01080                    << val 
01081                    << " not finite\n";
01082               throw(string("refractive_atmospheric_model::caliph_C"));
01083             }
01084           }
01085         }
01086       }
01087     } catch(...) {
01088       cerr << "refractive_atmospheric_model::caliph_C error\n";
01089       throw(string("refractive_atmospheric_model::caliph_C"));
01090     }
01091     pixel_array<T> pixarr(axes,data);
01092     delete [] data;
01093     return(pixarr);
01094   }
01095 
01096   template<class T>
01097   pixel_array<T> refractive_atmospheric_model::caliph_G(const emitter & emtr_a,
01098                                                         const emitter & emtr_b,
01099                                                         double aperture_diameter_meters,
01100                                                         double pixel_scale_meters) const {
01101 
01102     if(aperture_diameter_meters==0){
01103       cerr << "refractive_atmospheric_model::caliph_G error - \n"
01104            << "invalid aperture diameter "
01105            << aperture_diameter_meters
01106            << " passed to this function\n";
01107       throw(string("refractive_atmospheric_model::caliph_G"));
01108     }
01109                                
01110     if(pixel_scale_meters<=0){
01111       cerr << "refractive_atmospheric_model::caliph_G error -\n"
01112            << "pixel scale "
01113            << pixel_scale_meters
01114            << " out of range\n";
01115       throw(string("refractive_atmospheric_model::caliph_G"));
01116     }
01117 
01118     T * data;
01119     vector<long> axes(2,(long)ceil(aperture_diameter_meters/pixel_scale_meters));
01120     try{
01121       data = new T[axes[0]*axes[1]];
01122     } catch(...) {
01123       cerr << "refractive_atmospheric_model::caliph_G - error allocating memory\n";
01124       throw(string("refractive_atmospheric_model::caliph_G"));
01125     }
01126 
01127     try{
01128       double secant_zenith_angle;
01129       double max_range_meters;
01130       double min_range_meters;
01131       three_vector little_omega;
01132       
01133       Tyler_get_constants(emtr_a,
01134                     emtr_b,
01135                     this->ground_ref_frame_,
01136                     aperture_diameter_meters,
01137                     secant_zenith_angle,
01138                     max_range_meters,
01139                     min_range_meters,
01140                     little_omega);
01141 
01142       double ghat_arg;
01143       double val;
01144 
01145       double Q;
01146 
01147       double x_halfpix=0, y_halfpix=0;
01148       int x_extrapix=1, y_extrapix=1;
01149       if(axes[1]%2==0){
01150         x_halfpix = .5;
01151         x_extrapix = 0;
01152       }
01153       if(axes[0]%2==0){
01154         y_halfpix = .5;
01155         y_extrapix = 0;
01156       }
01157 
01158       three_vector pixel_vector;
01159       double normalization_factor = 2*pixel_scale_meters/aperture_diameter_meters;
01160       int index;
01161 
01162       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01163         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01164           pixel_vector = 
01165             this->ground_ref_frame_.x()*((i+x_halfpix)*normalization_factor) +
01166             this->ground_ref_frame_.y()*((j+y_halfpix)*normalization_factor);
01167 
01168           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01169 
01170           if(pixel_vector.length_squared()>1)
01171             data[index]=0;
01172           else {
01173             val = 0;
01174             for(int k=0; k<this->power_spectra_.size(); k++){
01175               if(layer_heights_[k]>min_range_meters) continue;
01176               
01177               Q = (1 - layer_heights_[k]*secant_zenith_angle/min_range_meters) /
01178                 (1 - layer_heights_[k]*secant_zenith_angle/max_range_meters);
01179               
01180               ghat_arg = 
01181                 ((pixel_vector*Q) - (little_omega*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)))).length();
01182 
01183               val += secant_zenith_angle*get_cn2_coefficient(power_spectra_[k]->get_coefficient()) * 
01184                 pow((1 - layer_heights_[k]*secant_zenith_angle/max_range_meters),5/3.) *
01185                 Q * Tyler_G_hat(ghat_arg);
01186             }
01187 
01188             data[index] = 4*val;
01189           }
01190         }
01191       }
01192     } catch(...) {
01193       cerr << "refractive_atmospheric_model::caliph_G error\n";
01194       throw(string("refractive_atmospheric_model::caliph_G"));
01195     }
01196     pixel_array<T> pixarr(axes,data);
01197     delete [] data;
01198     return(pixarr);
01199   }
01200 
01201   template<class T>
01202   pixel_array<T> refractive_atmospheric_model::caliph_H(const emitter & emtr_a,
01203                                                         const emitter & emtr_b,
01204                                                         double aperture_diameter_meters,
01205                                                         double pixel_scale_meters) const {
01206     
01207     if(aperture_diameter_meters==0){
01208       cerr << "refractive_atmospheric_model::caliph_H error - \n"
01209            << "invalid aperture diameter "
01210            << aperture_diameter_meters
01211            << " passed to this function\n";
01212       throw(string("refractive_atmospheric_model::caliph_H"));
01213     }
01214                                
01215     if(pixel_scale_meters<=0){
01216       cerr << "refractive_atmospheric_model::caliph_H error -\n"
01217            << "pixel scale "
01218            << pixel_scale_meters
01219            << " out of range\n";
01220       throw(string("refractive_atmospheric_model::caliph_H"));
01221     }
01222 
01223     T * data;
01224     vector<long> axes(2,(long)ceil(aperture_diameter_meters/pixel_scale_meters));
01225     try{
01226       data = new T[axes[0]*axes[1]];
01227     } catch(...) {
01228       cerr << "refractive_atmospheric_model::caliph_H - error allocating memory\n";
01229       throw(string("refractive_atmospheric_model::caliph_H"));
01230     }
01231 
01232     try{
01233       double secant_zenith_angle;
01234       double max_range_meters;
01235       double min_range_meters;
01236       three_vector little_omega;
01237       
01238       Tyler_get_constants(emtr_a,
01239                     emtr_b,
01240                     this->ground_ref_frame_,
01241                     aperture_diameter_meters,
01242                     secant_zenith_angle,
01243                     max_range_meters,
01244                     min_range_meters,
01245                     little_omega);
01246 
01247       double ghat_arg;
01248       double val;
01249 
01250       double Q;
01251 
01252       double x_halfpix=0, y_halfpix=0;
01253       int x_extrapix=1, y_extrapix=1;
01254       if(axes[1]%2==0){
01255         x_halfpix = .5;
01256         x_extrapix = 0;
01257       }
01258       if(axes[0]%2==0){
01259         y_halfpix = .5;
01260         y_extrapix = 0;
01261       }
01262 
01263       three_vector pixel_vector;
01264       double normalization_factor = 2*pixel_scale_meters/aperture_diameter_meters;
01265       int index;
01266 
01267       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01268         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01269           pixel_vector = 
01270             this->ground_ref_frame_.x()*((i+x_halfpix)*normalization_factor) +
01271             this->ground_ref_frame_.y()*((j+y_halfpix)*normalization_factor);
01272 
01273           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01274 
01275           if(pixel_vector.length_squared()>1)
01276             data[index]=0;
01277           else {
01278             val = 0;
01279             for(int k=0; k<this->power_spectra_.size(); k++){
01280               if(layer_heights_[k]>min_range_meters) continue;
01281               
01282               Q = (1 - layer_heights_[k]*secant_zenith_angle/min_range_meters) /
01283                 (1 - layer_heights_[k]*secant_zenith_angle/max_range_meters);
01284               
01285               ghat_arg = 
01286                 ((pixel_vector*Q) - (little_omega*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)))).length();
01287 
01288               val += secant_zenith_angle*get_cn2_coefficient(power_spectra_[k]->get_coefficient()) * 
01289                 pow((1 - layer_heights_[k]*secant_zenith_angle/max_range_meters),5/3.) *
01290                 little_omega.length()*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters))
01291                 * Tyler_G_hat(ghat_arg);
01292             }
01293             data[index] = 4*val;
01294           }
01295         }
01296       }
01297     } catch(...) {
01298       cerr << "refractive_atmospheric_model::caliph_H error\n";
01299       throw(string("refractive_atmospheric_model::caliph_H"));
01300     }
01301     pixel_array<T> pixarr(axes,data);
01302     delete [] data;
01303     return(pixarr);
01304   }
01305 
01306   template<class T>
01307   pixel_array<T> refractive_atmospheric_model::caliph_I(const emitter & emtr_a,
01308                                                         const emitter & emtr_b,
01309                                                         double aperture_diameter_meters,
01310                                                         double pixel_scale_meters) const {
01311     
01312     if(aperture_diameter_meters==0){
01313       cerr << "refractive_atmospheric_model::caliph_I error - \n"
01314            << "invalid aperture diameter "
01315            << aperture_diameter_meters 
01316            << " passed to this function\n";
01317       throw(string("refractive_atmospheric_model::caliph_I"));
01318     }
01319                                
01320     if(pixel_scale_meters<=0){
01321       cerr << "refractive_atmospheric_model::caliph_I error -\n"
01322            << "pixel scale "
01323            << pixel_scale_meters
01324            << " out of range\n";
01325       throw(string("refractive_atmospheric_model::caliph_I"));
01326     }
01327 
01328     T * data;
01329     vector<long> axes(2,(long)ceil(aperture_diameter_meters/pixel_scale_meters));
01330     try{
01331       data = new T[axes[0]*axes[1]];
01332     } catch(...) {
01333       cerr << "refractive_atmospheric_model::caliph_I - error allocating memory\n";
01334       throw(string("refractive_atmospheric_model::caliph_I"));
01335     }
01336 
01337     try{
01338       double secant_zenith_angle;
01339       double max_range_meters;
01340       double min_range_meters;
01341       three_vector little_omega;
01342       
01343       Tyler_get_constants(emtr_a,
01344                     emtr_b,
01345                     this->ground_ref_frame_,
01346                     aperture_diameter_meters,
01347                     secant_zenith_angle,
01348                     max_range_meters,
01349                     min_range_meters,
01350                     little_omega);
01351 
01352       double ghat_arg;
01353       double val;
01354 
01355       double Q;
01356       
01357       double x_halfpix=0, y_halfpix=0;
01358       int x_extrapix=1, y_extrapix=1;
01359       if(axes[1]%2==0){
01360         x_halfpix = .5;
01361         x_extrapix = 0;
01362       }
01363       if(axes[0]%2==0){
01364         y_halfpix = .5;
01365         y_extrapix = 0;
01366       }
01367 
01368       three_vector pixel_vector;
01369       double normalization_factor = 2*pixel_scale_meters/aperture_diameter_meters;
01370       int index;
01371 
01372       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01373         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01374           pixel_vector = 
01375             this->ground_ref_frame_.x()*((i+x_halfpix)*normalization_factor) +
01376             this->ground_ref_frame_.y()*((j+y_halfpix)*normalization_factor);
01377 
01378           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01379 
01380           if(pixel_vector.length_squared()>1)
01381             data[index]=0;
01382           else {
01383             val = 0;
01384             for(int k=0; k<this->power_spectra_.size(); k++){
01385               if(layer_heights_[k]>min_range_meters) continue;
01386               
01387               Q = (1 - layer_heights_[k]*secant_zenith_angle/min_range_meters) /
01388                 (1 - layer_heights_[k]*secant_zenith_angle/max_range_meters);
01389               
01390               ghat_arg = 
01391                 (pixel_vector + (little_omega*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)))).length()/Q;
01392 
01393               val += secant_zenith_angle*get_cn2_coefficient(power_spectra_[k]->get_coefficient()) * 
01394                 pow((1 - layer_heights_[k]*secant_zenith_angle/max_range_meters),5/3.) *
01395                 pow(Q,2/3.) * 
01396                 Tyler_G_hat(ghat_arg);
01397             }
01398             data[index] = 4*val;
01399           }
01400         }
01401       }
01402     } catch(...) {
01403       cerr << "refractive_atmospheric_model::caliph_I error\n";
01404       throw(string("refractive_atmospheric_model::caliph_I"));
01405     }
01406     pixel_array<T> pixarr(axes,data);
01407     delete [] data;
01408     return(pixarr);
01409   }
01410 
01411   template<class T>
01412   pixel_array<T> refractive_atmospheric_model::caliph_J(const emitter & emtr_a,
01413                                                         const emitter & emtr_b,
01414                                                         double aperture_diameter_meters,
01415                                                         double pixel_scale_meters) const {
01416     
01417     if(aperture_diameter_meters==0){
01418       cerr << "refractive_atmospheric_model::caliph_J error - \n"
01419            << "invalid aperture diameter "
01420            << aperture_diameter_meters
01421            << " passed to this function\n";
01422       throw(string("refractive_atmospheric_model::caliph_J"));
01423     }
01424                                
01425     if(pixel_scale_meters<=0){
01426       cerr << "refractive_atmospheric_model::caliph_J error -\n"
01427            << "pixel scale "
01428            << pixel_scale_meters
01429            << " out of range\n";
01430       throw(string("refractive_atmospheric_model::caliph_J"));
01431     }
01432 
01433     T * data;
01434     vector<long> axes(2,(long)ceil(aperture_diameter_meters/pixel_scale_meters));
01435     try{
01436       data = new T[axes[0]*axes[1]];
01437     } catch(...) {
01438       cerr << "refractive_atmospheric_model::caliph_J - error allocating memory\n";
01439       throw(string("refractive_atmospheric_model::caliph_J"));
01440     }
01441 
01442     try{
01443       double secant_zenith_angle;
01444       double max_range_meters;
01445       double min_range_meters;
01446       three_vector little_omega;
01447       
01448       Tyler_get_constants(emtr_a,
01449                     emtr_b,
01450                     this->ground_ref_frame_,
01451                     aperture_diameter_meters,
01452                     secant_zenith_angle,
01453                     max_range_meters,
01454                     min_range_meters,
01455                     little_omega);
01456 
01457       double ghat_arg;
01458       double val;
01459 
01460       double Q;
01461 
01462       double x_halfpix=0, y_halfpix=0;
01463       int x_extrapix=1, y_extrapix=1;
01464       if(axes[1]%2==0){
01465         x_halfpix = .5;
01466         x_extrapix = 0;
01467       }
01468       if(axes[0]%2==0){
01469         y_halfpix = .5;
01470         y_extrapix = 0;
01471       }
01472 
01473       three_vector pixel_vector;
01474       double normalization_factor = 2*pixel_scale_meters/aperture_diameter_meters;
01475       int index;
01476 
01477       for(int i=-axes[1]/2; i<axes[1]/2+x_extrapix; i++){
01478         for(int j=-axes[0]/2; j<axes[0]/2+y_extrapix; j++){
01479           pixel_vector = 
01480             this->ground_ref_frame_.x()*((i+x_halfpix)*normalization_factor) +
01481             this->ground_ref_frame_.y()*((j+y_halfpix)*normalization_factor);
01482 
01483           index = (i+axes[1]/2)*axes[0]+j+axes[0]/2;
01484 
01485           if(pixel_vector.length_squared()>1)
01486             data[index]=0;
01487           else {
01488             val = 0;
01489             for(int k=0; k<this->power_spectra_.size(); k++){
01490               if(layer_heights_[k]>min_range_meters) continue;
01491               
01492               Q = (1 - layer_heights_[k]*secant_zenith_angle/min_range_meters) /
01493                 (1 - layer_heights_[k]*secant_zenith_angle/max_range_meters);
01494               
01495               ghat_arg = 
01496                 (pixel_vector + (little_omega*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)))).length()/Q;
01497 
01498               val += secant_zenith_angle*get_cn2_coefficient(power_spectra_[k]->get_coefficient()) * 
01499                 pow((1 - layer_heights_[k]*secant_zenith_angle/max_range_meters),5/3.) *
01500                 pow(Q, 2/3.) *
01501                 little_omega.length()*(layer_heights_[k]/(1-layer_heights_[k]/max_range_meters)) * 
01502                 Tyler_G_hat(ghat_arg);
01503             }
01504             data[index] = 4*val;
01505           }
01506         }
01507       }
01508     } catch(...) {
01509       cerr << "refractive_atmospheric_model::caliph_J error\n";
01510       throw(string("refractive_atmospheric_model::caliph_J"));
01511     }
01512     pixel_array<T> pixarr(axes,data);
01513     delete [] data;
01514     return(pixarr);
01515   }
01516 
01517   template<class T>
01518   diffractive_wavefront_header<T> 
01519   refractive_atmospheric_model::get_diffractive_wavefront_header(double wavelength, 
01520                                                                  double pixscale,
01521                                                                  const emitter * emtr,
01522                                                                  const aperture * ap,
01523                                                                  bool layer_foreshortening, 
01524                                                                  propagation_plan * pplan) const {
01525 
01526     // Define the wavefront reference frame.  The choice of transverse axes
01527     // depends on whether we choose to foreshorten the layer 
01528     three_vector emitter_direction_vector = -1*emtr->get_emission_vector(*ap);
01529 
01530     double cos_angle = dot_product(-1*emitter_direction_vector, ap->z());
01531     three_frame wf_frame(*ap-(layer_heights_[0]/cos_angle)*emitter_direction_vector,
01532                          -1*ground_ref_frame_.x(), 
01533                          -1*ground_ref_frame_.y(), 
01534                          -1*ground_ref_frame_.z());
01535     if(layer_foreshortening) {
01536       three_vector axis_in_layer = cross_product(ground_ref_frame_.z(), emitter_direction_vector);
01537       if(axis_in_layer.length()>three_frame::precision){
01538         wf_frame = three_frame(*ap-(layer_heights_[0]/cos_angle)*emitter_direction_vector,
01539                                cross_product(axis_in_layer, emitter_direction_vector),
01540                                axis_in_layer, 
01541                                emitter_direction_vector);
01542       }
01543     } else {
01544       three_vector rotation_vector = cross_product(emitter_direction_vector, 
01545                                                    wf_frame.z());
01546       if(rotation_vector.length()!=0){
01547         three_rotation trot(wf_frame, 
01548                             rotation_vector, 
01549                             rotation_vector.length());
01550         trot.transform(wf_frame);
01551       }
01552     }
01553 
01554     // Get the aperture covering region for this frame, and
01555     // round its dimensions up to an integral number of wavefront
01556     // pixels
01557     rectangular_region wf_region = ap->get_covering_region(wf_frame);
01558     wf_region = rectangular_region(wf_region, pixscale);
01559 
01560     // Find the size of the wavefront array for which we need 
01561     // valid data.
01562     vector<three_point> region_corners = wf_region.get_corners();
01563     long dimen = (long)ceil((region_corners[1]-region_corners[0]).length()/pixscale);
01564     if((region_corners[3]-region_corners[0]).length() >
01565        (region_corners[1]-region_corners[0]).length())
01566       dimen = (long)ceil((region_corners[3]-region_corners[0]).length()/pixscale);
01567 
01568     vector<long> wf_axes(2, dimen);
01569 
01570     // set up the curvature and pixel scale
01571     double curvature = 0;
01572     double init_pixscale = pixscale;
01573     const spherical_wave_emitter * swe;
01574     if(swe=dynamic_cast<const spherical_wave_emitter *>(emtr)){
01575       curvature = 1/(wf_frame-*swe).length();
01576       init_pixscale *= (wf_frame-*swe).length()/(*ap-*swe).length();
01577     }
01578 
01579     // Declare the wavefront header
01580     diffractive_wavefront_header<T> dwf(wf_axes, wf_frame, wavelength, init_pixscale);
01581 
01582     dwf.set_curvature(curvature);
01583 
01584     // Declare a wavefront header for which we have added in the 
01585     // padding required by the propagation plan
01586     diffractive_wavefront_header<T> padded_dwf = pplan->pad(dwf, layer_heights_[0]);
01587 
01588     return(padded_dwf);
01589   }
01590 
01591   template<class T, class U>
01592   void refractive_atmospheric_model::
01593   get_refractive_atmospheric_layers(const vector<double> & layer_pixscales,
01594                                     const subharmonic_method & subm,
01595                                     const vector<diffractive_wavefront_header<T> > dwfhdrs,
01596                                     const vector<three_vector> layer_wind_vectors,
01597                                     double time_interval,
01598                                     bool layer_axes_wind_vector_aligned,
01599                                     bool layer_foreshortening,
01600                                     vector<refractive_atmospheric_layer<U> > & ref_atm_layers) const {
01601 
01602     if(time_interval < 0){
01603       cerr << "refractive_atmospheric_model::get_refractive_atmospheric_layers error - "
01604            << "time interval " << time_interval << " provided to this function "
01605            << "is less than or equal to zero\n";
01606       throw(string("refractive_atmospheric_model::get_refractive_atmospheric_layers"));
01607     }
01608 
01609     if(layer_pixscales.size() != power_spectra_.size()){
01610       cerr << "refractive_atmospheric_model::get_refractive_atmospheric_layers error - "
01611            << layer_pixscales.size() << " layer pixel scales were provided, but there are "
01612            << power_spectra_.size() << " layers in the model\n";
01613       throw(string("refractive_atmospheric_model::get_refractive_atmospheric_layers"));
01614     }
01615 
01616     if(layer_wind_vectors.size()!=this->get_number_of_layers()){
01617       cerr << "refractive_atmospheric_model::get_refractive_atmospheric_layers error - "
01618            << "number of layer wind vectors " << layer_wind_vectors.size()
01619            << " does not match the number of layers " << this->get_number_of_layers()
01620            << " in the atmospheric model\n";
01621       throw(string("refractive_atmospheric_model::get_refractive_atmospheric_layers"));
01622     }
01623 
01624     // Here for each layer we do the following:
01625     // Get a random wind vector
01626     // Initialize the three_frame of the layer
01627     // Initialize the rectangular_region that will serve to define the size of the layer
01628     int nlayers = power_spectra_.size();
01629     vector<three_frame> layer_three_frames(nlayers, ground_ref_frame_);
01630     vector<rectangular_region> layer_rec_regions;
01631     double windspeed, x_wind_cmpnt, y_wind_cmpnt, angle;
01632     for(int i=0; i<nlayers; i++){
01633 
01634       if(refractive_atmospheric_model::verbose_level) 
01635         cout << "refractive_atmospheric_model::get_refractive_atmospheric_layers - initializing layer three frame...";
01636 
01637       // If the layer axes are to be aligned with the wind vector, we
01638       // redefine the layer three frame to have this alignment.
01639       if(layer_axes_wind_vector_aligned){
01640         layer_three_frames[i] = three_frame(ground_ref_frame_,
01641                                             cross_product(layer_wind_vectors[i], ground_ref_frame_.z()), 
01642                                             layer_wind_vectors[i], 
01643                                             ground_ref_frame_.z());
01644       } 
01645 
01646       // Bump the layer three frame up to the correct altitude
01647       layer_three_frames[i] += layer_heights_[i]*ground_ref_frame_.z();
01648 
01649       if(refractive_atmospheric_model::verbose_level) cout << " initializing rectangular region...";
01650 
01651       // Initialize the layer's rectangular region by translating the
01652       // first wavefront down to the layer height, and then finding
01653       // the rectangular region that will encompass this wavefront
01654       diffractive_wavefront_header<T> tmp_header = dwfhdrs[0];
01655       if(refractive_atmospheric_model::verbose_level) cout << "getting distance...";
01656       tmp_header.three_point::operator=(get_ray_plane_intersection(tmp_header, tmp_header.z(), 
01657                                                                    layer_three_frames[i], layer_three_frames[i].z()));
01658 
01659       if(refractive_atmospheric_model::verbose_level) cout << "making rec region...";
01660       layer_rec_regions.push_back(tmp_header.get_covering_region(layer_three_frames[i], layer_foreshortening));
01661       
01662       if(refractive_atmospheric_model::verbose_level) cout << "initialization complete\n";
01663     }
01664 
01665     // Here for each layer we loop over the wavefront headers finding the
01666     // rectangular region containing the wavefront at the layer height
01667     // and forming the union with the region from the previous iteration
01668     vector<three_point> tp;
01669     ref_atm_layers.clear();
01670     vector<long> layer_axes(2);
01671     diffractive_wavefront_header<T> tmp_header;
01672     for(int i=0; i<nlayers; i++){
01673       if(refractive_atmospheric_model::verbose_level) cout << "Layer " << i << " constructing rectangular region...";
01674       for(int j=1; j<dwfhdrs.size(); j++){
01675 
01676 
01677         tmp_header = dwfhdrs[j];
01678         tmp_header.three_point::operator=(get_ray_plane_intersection(dwfhdrs[j], dwfhdrs[j].z(), 
01679                                                                      layer_three_frames[i], layer_three_frames[i].z()));
01680  
01681         layer_rec_regions[i] = 
01682           region_union(layer_rec_regions[i], 
01683                        tmp_header.get_covering_region(layer_three_frames[i], layer_foreshortening));
01684       }
01685 
01686       if(refractive_atmospheric_model::verbose_level) cout << " enlarging region for simulation...";
01687 
01688       // Next we will enlarge the rectangular regions to account for the
01689       // duration of the simulation and the wind speed of the layers.
01690       three_vector lateral_displacement = time_interval*layer_wind_vectors[i];
01691       tp = layer_rec_regions[i].get_corners();
01692       for(int j=0; j<4; j++) tp[j] -= lateral_displacement;
01693       layer_rec_regions[i] = region_union(layer_rec_regions[i], rectangular_region(tp));
01694 
01695       if(refractive_atmospheric_model::verbose_level)
01696         layer_rec_regions[i].print(cout, "lrr ");
01697 
01698       if(refractive_atmospheric_model::verbose_level) cout << " rounding up region...";
01699 
01700       // Round the rectangular regions up to size evenly 
01701       // divisible by the layer pixel scale
01702       layer_rec_regions[i] = rectangular_region(layer_rec_regions[i], layer_pixscales[i]);
01703       layer_three_frames[i].three_point::operator=(layer_rec_regions[i].get_center());
01704 
01705       if(refractive_atmospheric_model::verbose_level)
01706         layer_three_frames[i].print(cout, "layer three frame ");
01707 
01708       // Define the layer axes.  If layer_axes_wind_vector_aligned ==
01709       // true, we choose the convention that axes[0] is along the wind
01710       // vector.  If layer_axes_wind_vector_aligned == false, we
01711       // choose the convention that axes[0] is along the x axis defined
01712       // by the ground_ref_frame_
01713       //
01714       // Note - here we add one more pixel to the axes to beat rounding
01715       // issues.  We also pad by 10 percent to avoid ringing at the edges
01716       // due to the subharmonic correction
01717 
01718       if(refractive_atmospheric_model::verbose_level) cout << " getting layer axes...";
01719       double padding_factor = 1.2;
01720       tp = layer_rec_regions[i].get_corners();
01721       three_vector tva = tp[1]-tp[0];
01722       three_vector tvb = tp[3]-tp[0];
01723       layer_axes[0] = (long)(padding_factor*(1+ceil(tvb.length()/layer_pixscales[i])));
01724       layer_axes[1] = (long)(padding_factor*(1+ceil(tva.length()/layer_pixscales[i])));
01725       if(layer_axes_wind_vector_aligned){
01726         if(cross_product(tva, layer_wind_vectors[i]).length()<three_frame::precision){
01727           layer_axes[0] = (long)(padding_factor*(1+ceil(tva.length()/layer_pixscales[i])));
01728           layer_axes[1] = (long)(padding_factor*(1+ceil(tvb.length()/layer_pixscales[i])));
01729         }
01730       } else {
01731         if(cross_product(tva, ground_ref_frame_.x()).length()<three_frame::precision){
01732           layer_axes[0] = (long)(padding_factor*(1+ceil(tva.length()/layer_pixscales[i])));
01733           layer_axes[1] = (long)(padding_factor*(1+ceil(tvb.length()/layer_pixscales[i])));
01734         }
01735       }
01736 
01737       // Finally we're ready to make the layers.  
01738       if(refractive_atmospheric_model::verbose_level)
01739         cout << "making layer " << ref_atm_layers.size()
01740                 << " of size " << layer_axes[0] << " x " << layer_axes[1] 
01741                 << " with pixscale " << layer_pixscales[i] << endl;
01742 
01743       /*
01744       refractive_atmospheric_layer<T> ral;
01745       power_spectra_[i]->get_refractive_atmospheric_layer(
01746                         layer_axes, layer_pixscales[i], subm, ral);
01747       ref_atm_layers.push_back(ral);
01748       */
01749       //ref_atm_layers.push_back(power_spectra_[i]->get_refractive_atmospheric_layer(
01750       //                        layer_axes, layer_pixscales[i], subm));
01751 
01752 
01753       ref_atm_layers.push_back(refractive_atmospheric_layer<U>(power_spectra_[i],
01754                                                                subm,
01755                                                                layer_axes, 
01756                                                                layer_pixscales[i]));
01757       ref_atm_layers[i].set_wind_vector(layer_wind_vectors[i]);
01758       ref_atm_layers[i].three_frame::operator=(layer_three_frames[i]);
01759       ref_atm_layers[i].set_foreshortening(false);
01760     }
01761   }
01762 
01763   /*
01764 
01767 
01768   class refractive_atmosphere :
01769     //public atmosphere 
01770     virtual public AO_sim_base, 
01771     public fits_header_data {
01772 
01773     private:
01774     
01775     static const bool factory_registration;
01776 
01777     protected:
01778   
01780     vector<refractive_atmospheric_layer > ref_atm_layers;
01781 
01782     public:
01783 
01786     refractive_atmosphere(){};
01787 
01790     refractive_atmosphere(const refractive_atmosphere & ref_atm);
01791 
01794     refractive_atmosphere(const char * filename);
01795 
01798     refractive_atmosphere(const iofits & iof);
01799 
01802     refractive_atmosphere(const refractive_atmospheric_model & ref_atm_model, 
01803                           double pixel_scale, 
01804                           const vector<long> & axes,
01805                           const subharmonic_method & subm);
01806 
01809     refractive_atmosphere(const vector<refractive_atmospheric_layer> & ref_atm_layers);
01810 
01813     ~refractive_atmosphere(){};
01814 
01817     refractive_atmosphere & operator=(const refractive_atmosphere & ref_atm);
01818 
01821     void read(const char * filename);
01822 
01825     void read(const iofits & iof);
01826 
01829     void write(const char * filename) const;
01830 
01833     void write(iofits & iof) const;
01834 
01837     void print(ostream & os, const char * prefix="") const;
01838 
01841     long size() const {return(ref_atm_layers.size());};
01842  
01843     static int verbose_level;
01844  
01845   };
01846 
01847   */
01848 
01849 }
01850 
01851 #endif

Generated on Thu Nov 29 17:16:30 2007 for arroyo by  doxygen 1.3.9.1