boundary_grid.h

00001 
00005 #pragma once
00006 
00007 #include <usml/ocean/boundary_model.h>
00008 #include <usml/ocean/reflect_loss_rayleigh.h>
00009 
00010 namespace usml {
00011 namespace ocean {
00012 
00030 template< class DATA_TYPE, int NUM_DIMS > class boundary_grid
00031     : public boundary_model
00032 {
00033     //**************************************************
00034     // height model
00035 
00036 private:
00037 
00039     data_grid<DATA_TYPE, NUM_DIMS>* _height;
00040 
00041 public:
00042 
00052     virtual void height(const wposition& location, matrix<double>* rho,
00053         wvector* normal = NULL, bool quick_interp = false) {
00054         switch (NUM_DIMS) {
00055 
00056         //***************
00057         // 1-D grids
00058 
00059         case 1:
00060             if(quick_interp) { this->_height->interp_type(0, GRID_INTERP_LINEAR); }
00061             else{ this->_height->interp_type(0, GRID_INTERP_PCHIP); }
00062             if (normal) {
00063 
00064                 matrix<double> gtheta(location.size1(), location.size2());
00065                 matrix<double> t(location.size1(), location.size2());
00066                 this->_height->interpolate(location.theta(), rho, &gtheta);
00067                 t = min(element_div(gtheta,*rho),1.0);  // slope = tan(angle)
00068                 normal->theta(                          // normal = -sin(angle)
00069                     element_div( -t, sqrt(1.0+abs2(t)) ));
00070                 normal->phi(scalar_matrix<double>(location.size1(),location.size2(),0.0));
00071                 normal->rho( sqrt(1.0-abs2(normal->theta())) ) ; // r=sqrt(1-t^2)
00072             } else {
00073                 this->_height->interpolate(location.theta(), rho);
00074             }
00075             break;
00076 
00077             //***************
00078             // 2-D grids
00079 
00080         case 2:
00081             if(quick_interp) {
00082                 this->_height->interp_type(0, GRID_INTERP_LINEAR);
00083                 this->_height->interp_type(1, GRID_INTERP_LINEAR);
00084             } else{
00085                 this->_height->interp_type(0, GRID_INTERP_PCHIP);
00086                 this->_height->interp_type(1, GRID_INTERP_PCHIP);
00087             }
00088             if (normal) {
00089                 matrix<double> gtheta(location.size1(), location.size2());
00090                 matrix<double> gphi(location.size1(), location.size2());
00091                 matrix<double> t(location.size1(), location.size2());
00092                 matrix<double> p(location.size1(), location.size2());
00093                 this->_height->interpolate(location.theta(), location.phi(),
00094                     rho, &gtheta, &gphi);
00095 
00096                 t = element_div(gtheta, *rho);  // slope = tan(angle)
00097                 p = element_div(gphi, element_prod(*rho, sin(location.theta())));
00098                 normal->theta(                  // normal = -sin(angle)
00099                     element_div( -t, sqrt(1.0+abs2(t)) ));
00100                 normal->phi(
00101                     element_div( -p, sqrt(1.0+abs2(p)) ));
00102                 normal->rho(sqrt(               // r=sqrt(1-t^2-p^2)
00103                                 1.0 - abs2(normal->theta()) - abs2(normal->phi()) ));
00104             } else {
00105                 this->_height->interpolate(location.theta(), location.phi(),
00106                     rho);
00107             }
00108             break;
00109 
00110             //***************
00111             // error
00112 
00113         default:
00114             throw std::invalid_argument("dataset must be 1-D or 2-D");
00115             break;
00116         }
00117     }
00118 
00128     virtual void height(const wposition1& location, double* rho,
00129         wvector1* normal = NULL, bool quick_interp = false) {
00130         switch (NUM_DIMS) {
00131 
00132         //***************
00133         // 1-D grids
00134 
00135         case 1:
00136             if(quick_interp) { this->_height->interp_type(0, GRID_INTERP_LINEAR); }
00137             else{ this->_height->interp_type(0, GRID_INTERP_PCHIP); }
00138             if (normal) {
00139                 double theta = location.theta();
00140                 double gtheta;
00141                 *rho = this->_height->interpolate(&theta, &gtheta);
00142                 const double t = gtheta / (*rho);       // slope = tan(angle)
00143                 normal->theta(-t / sqrt(1.0 + t * t));  // normal = -sin(angle)
00144                 normal->phi(0.0);
00145                 const double N = normal->theta() * normal->theta() ;
00146                 normal->rho( sqrt(1.0-N) );                             // r=sqrt(1-t^2)
00147             } else {
00148                 double theta = location.theta();
00149                 *rho = this->_height->interpolate(&theta);
00150             }
00151             break;
00152 
00153             //***************
00154             // 2-D grids
00155 
00156         case 2:
00157             if(quick_interp) {
00158                 this->_height->interp_type(0, GRID_INTERP_LINEAR);
00159                 this->_height->interp_type(1, GRID_INTERP_LINEAR);
00160             } else{
00161                 this->_height->interp_type(0, GRID_INTERP_PCHIP);
00162                 this->_height->interp_type(1, GRID_INTERP_PCHIP);
00163             }
00164             if (normal) {
00165                 double loc[2] = { location.theta(), location.phi() };
00166                 double grad[2];
00167                 *rho = this->_height->interpolate(loc, grad);
00168                 const double t = grad[0] / (*rho);      // slope = tan(angle)
00169                 const double p = grad[1] / ((*rho) * sin(location.theta()));
00170                 normal->theta(-t / sqrt(1.0 + t * t));  // normal = -sin(angle)
00171                 normal->phi(-p / sqrt(1.0 + p * p));
00172                 const double N = normal->theta() * normal->theta()
00173                                + normal->phi()  * normal->phi();
00174                 normal->rho( sqrt(1.0-N) );                             // r=sqrt(1-t^2-p^2)
00175             } else {
00176                 double loc[2] = { location.theta(), location.phi() };
00177                 *rho = this->_height->interpolate(loc);
00178             }
00179             break;
00180 
00181             //***************
00182             // error
00183 
00184         default:
00185             throw std::invalid_argument("bathymetry must be 1-D or 2-D");
00186             break;
00187         }
00188     }
00189 
00190     //**************************************************
00191     // initialization
00192 
00204     boundary_grid(data_grid<DATA_TYPE, NUM_DIMS>* height,
00205         reflect_loss_model* reflect_loss = NULL) :
00206         boundary_model(reflect_loss), _height(height) {
00207         this->_height->interp_type(0,GRID_INTERP_PCHIP);
00208         this->_height->interp_type(1,GRID_INTERP_PCHIP);
00209         this->_height->edge_limit(0,true);
00210         this->_height->edge_limit(1,true);
00211         if ( reflect_loss == NULL ) {
00212             this->reflect_loss( new reflect_loss_rayleigh(
00213                 reflect_loss_rayleigh::SAND) ) ;
00214         }
00215     }
00216 
00220     virtual ~boundary_grid() {
00221         delete _height;
00222     }
00223 
00224 };
00225 
00226 }  // end of namespace ocean
00227 }  // end of namespace usml

Generated on 4 May 2015 for USML by  doxygen 1.6.1