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 = ¶
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
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
00263 do
00264 {
00265 iter++;
00266 status = gsl_multifit_fdfsolver_iterate(s);
00267
00268 if (status > 0)
00269 break;
00270
00271
00272
00273
00274
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
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 }