Main Page | Namespace List | Class List | File List | Namespace Members | Class Members | File Members

variogram.cpp

Go to the documentation of this file.
00001 
00006 #include "variogram.h"
00007 #include "vario_model.h"
00008 #include <math.h>
00009 #include <gsl/gsl_rng.h>
00010 #include <gsl/gsl_randist.h>
00011 #include <gsl/gsl_vector.h>
00012 #include <gsl/gsl_blas.h>
00013 #include <gsl/gsl_multifit_nlin.h>
00014 
00020 CVariogram::CVariogram(void)
00021 {
00022         m_pDistance = NULL;
00023         m_pVariogram = NULL;
00024         m_samples = 0;
00025 
00026         m_sill = 0.0;
00027         m_range = 0.0;
00028         m_nugget = 0.0;
00029         m_power = 0.0;
00030 
00031         m_model = VARIO_NONE;
00032 }
00033 
00039 CVariogram::~CVariogram(void)
00040 {
00041         destroy();
00042 }
00043 
00051 bool CVariogram::allocate(size_t smpl)
00052 {
00053         destroy();
00054         
00055         m_pDistance = new double[smpl];
00056         m_pVariogram = new double[smpl];
00057 
00058         if (m_pDistance == NULL || m_pVariogram == NULL)
00059         {
00060                 destroy();
00061                 return false;
00062         }
00063         m_samples = smpl;
00064 
00065         return true;
00066 }
00067 
00073 void CVariogram::destroy(void)
00074 {
00075         if (m_pDistance != NULL)
00076         {
00077                 delete[] m_pDistance;
00078                 m_pDistance = NULL;
00079         }
00080         if (m_pVariogram != NULL)
00081         {
00082                 delete[] m_pVariogram;
00083                 m_pVariogram = NULL;
00084         }
00085 
00086         m_model = VARIO_NONE;
00087         m_nugget = 0.0;
00088         m_sill = 0.0;
00089         m_range = 0.0;
00090         m_power = 0.0;
00091 }
00092 
00100 bool CVariogram::setSample(const std::vector<CVariogram::VarioItm> &vecSample)
00101 {
00102         if (vecSample.empty())
00103                 return false;
00104 
00105         if (!allocate(vecSample.size()))
00106                 return false;
00107 
00108         for (size_t i = 0;i < samples();i++)
00109         {
00110                 m_pDistance[i] = vecSample[i].distance;
00111                 m_pVariogram[i] = vecSample[i].dissimilarity;
00112         }
00113         
00114         sortByDistance();
00115         m_model = VARIO_NONE;
00116 
00117         return true;
00118 }
00119 
00133 bool CVariogram::setModel(int model, double nugget, double sill, double range, double power, double step, double maxdist)
00134 {
00135         if (model >= CVariogram::VARIO_NUM)
00136                 return false;
00137 
00138         if (!allocate(static_cast<size_t>(fabs(maxdist / step))))
00139                 return false;
00140 
00141         m_model = model;
00142         m_nugget = nugget;
00143         m_sill = sill;
00144         m_range = range;
00145         m_power = power;
00146 
00147         for (size_t i = 0;i < samples();i++)
00148         {
00149                 m_pDistance[i] = step * i;
00150                 m_pVariogram[i] = getModelData(step * i);
00151         }
00152         return true;
00153 }
00154 
00164 bool CVariogram::getSample(size_t smpl, double &dist, double &vario) const
00165 {
00166         if (smpl >= samples())
00167                 return false;
00168 
00169         dist = m_pDistance[smpl];
00170         vario = m_pVariogram[smpl];
00171         return true;
00172 }
00173 
00180 size_t CVariogram::countLessDist(double cap) const
00181 {
00182         if (!isActive())
00183                 return 0;
00184 
00185         size_t cnt =0;
00186         while (++cnt < m_samples && m_pDistance[cnt] < cap);
00187         return cnt;
00188 }
00189 
00201 int CVariogram::estimateModel(int model, double &nugget, double &sill, double &range, double power, double maxdist)
00202 {
00203         double init_guess[3] = {sill, range, nugget};
00204 
00205         gsl_vector_view x;
00206         gsl_vector *g;
00207 
00208         // パラメータセッティング
00209         if (power < 0.0 || power > 2.0)
00210                 return GSL_FAILURE;
00211 
00212         LSFParam para;
00213         para.dist = m_pDistance;
00214         para.vario = m_pVariogram;
00215         para.n = countLessDist(maxdist);
00216         para.power = power;
00217 
00218         // 最適化対象関数の登録
00219         gsl_multifit_function_fdf f;
00220 
00221         m_model = model;
00222         switch (model)
00223         {
00224         case VARIO_SPH:
00225                 f.f = &sph_f;
00226                 f.df = &sph_df;
00227                 f.fdf = &sph_fdf;
00228                 break;
00229         case VARIO_STB:
00230                 f.f = &stb_f;
00231                 f.df = &stb_df;
00232                 f.fdf = &stb_fdf;
00233                 break;
00234         default:
00235                 m_model = VARIO_NONE;
00236                 return GSL_FAILURE;
00237         }
00238 
00239         f.n = para.n;
00240         f.params = &para;
00241         switch (model)
00242         {
00243         case VARIO_SPH:
00244         case VARIO_STB:
00245                 f.p = 3;
00246                 break;
00247         default:
00248                 break;
00249         }
00250 
00251         x = gsl_vector_view_array(init_guess, f.p);
00252         g = gsl_vector_alloc(f.p);
00253 
00254         // initialize NLSF solver
00255         const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder;
00256         gsl_multifit_fdfsolver *s = gsl_multifit_fdfsolver_alloc(T, f.n, f.p);
00257         gsl_multifit_fdfsolver_set(s, &f, &x.vector);
00258 
00259         int status;
00260         size_t iter =0;
00261 
00262         // iteration
00263         do
00264         {
00265                 iter++;
00266                 status = gsl_multifit_fdfsolver_iterate(s);
00267 
00268                 if (status > 0)
00269                         break;
00270 
00271                 // convergence check by variation
00272 //              status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4);
00273 
00274                 // convergence check by gradient
00275                 gsl_multifit_gradient(s->J, s->f, g);
00276                 status = gsl_multifit_test_gradient(g, 0.01);
00277 
00278         } while (status == GSL_CONTINUE && iter < 500);
00279 
00280         if (iter >= 500)
00281         {
00282                 GSL_ERROR_VAL("Variogram Estimator: Didn't converge...\n", status, false);
00283         }
00284 
00285         m_nugget = 0.0;
00286         m_sill = 0.0;
00287         m_range = 0.0;
00288         m_power = 0.0;
00289 
00290         switch (model)
00291         {
00292         case VARIO_SPH:
00293         case VARIO_STB:
00294                 m_nugget = gsl_vector_get(s->x, 2);
00295                 m_sill = gsl_vector_get(s->x, 0);
00296                 m_range = fabs(gsl_vector_get(s->x, 1));
00297                 break;
00298 
00299         default:
00300                 break;
00301         }
00302 
00303         nugget = m_nugget;
00304         sill = m_sill;
00305         range = m_range;
00306         power = m_power;
00307 
00308         gsl_vector_free(g);
00309         gsl_multifit_fdfsolver_free(s);
00310 
00311         return status;
00312 }
00313 
00320 double CVariogram::getModelData(double dist) const
00321 {
00322         switch (m_model)
00323         {
00324         case VARIO_SPH:
00325                 return spherical(m_nugget, m_sill, m_range, dist);
00326         case VARIO_STB:
00327                 return stable(m_nugget, m_sill, m_range, m_power, dist);
00328         default:
00329                 break;
00330         }
00331         return -1;
00332 }
00333 
00340 double CVariogram::getModelCovariance(double dist) const
00341 {
00342         switch (m_model)
00343         {
00344         case VARIO_SPH:
00345                 return m_sill - spherical(m_nugget, m_sill, m_range, dist);
00346         case VARIO_STB:
00347                 return m_sill - stable(m_nugget, m_sill, m_range, m_power, dist);
00348         default:
00349                 break;
00350         }
00351 
00352         // if variogram does not has boundary ...
00353         return -1.0;
00354 }
00355 
00362 bool CVariogram::sortByDistance(void)
00363 {
00364         if (!isActive())
00365                 return false;
00366 
00367         for (size_t i = 0;i < m_samples;i++)
00368         {
00369                 for (size_t j = i + 1;j < m_samples;j++)
00370                 {
00371                         if (m_pDistance[i] > m_pDistance[j])
00372                         {
00373                                 std::swap(m_pDistance[i], m_pDistance[j]);
00374                                 std::swap(m_pVariogram[i], m_pVariogram[j]);
00375                         }
00376                 }
00377         }
00378         return true;
00379 }

Generated on Thu Aug 11 13:01:33 2005 for Kriging sample by  doxygen 1.4.3