//-----------------------------------------------------------------------------
// Examine the values specified by the indices.  If any of the values
// are identical, then toss out the higher index.
bool MgFeatureNumericFunctions::FixIndicesByValue(const std::vector<double>& data, std::vector<int>& indices)
{
    if (indices.size() <= 1)
    {
        return false;
    }

    // We will create a new vector of indices that is possibly adjusted,
    // then replace the original vector with the new.  Since these vectors
    // have typically less than 10 entries, we won't deal with making the
    // adjustments in place.
    std::vector<int> newIndices;

    newIndices.push_back(indices[0]);

    for (unsigned int i = 1; i < indices.size(); ++i)
    {
        if ( ! doubles_equal(data[indices[i]], data[indices[i - 1]]) )
            newIndices.push_back(indices[i]);
    }

    bool changed = (newIndices.size() != indices.size());
    indices.clear();
    indices = newIndices;

    return changed;
}
Exemple #2
0
void MetamorphismCROCUS::metamorphism() {
   /* Empirical laws for dry snow metamorphism. From: Vionnet et al, 2012: table 1.
      TODO: Tgrad > 15 is ommitted here (no depth hoar formation)
      */
   const double dt = (double)_dm.getDt() / (double) sec_in_day; // time in days

   Grid& grid = _mstate.getGrid();
   int Np = grid.size();
   if (Np < 2) return; // can't compute gradients on single snow layer

   double Tgrad;
   for (int i = 0; i < Np; i++) {
      if (i == 0) {
         // SNOW BOTTOM, one-sided up
         Tgrad = std::abs((grid[1].T-grid[0].T)/(0.5*grid[0].dz+0.5*grid[1].dz));
      } else if (i == Np-1) {
         // SNOW TOP, one-sided down
         Tgrad = std::abs((grid[Np-1].T-grid[Np-2].T)/(0.5*grid[Np-1].dz+0.5*grid[Np-2].dz));
      } else {
         // central difference
         Tgrad = std::abs(grid[i+1].T-grid[i-1].T)/(0.5*grid[i+1].dz+grid[i].dz+grid[i-1].dz);
      }

      if (doubles_equal(grid[i].dnd, 0.0)) {
         // Non-dendritic snow
         if (Tgrad <= 5.) {
            grid[i].sph = grid[i].sph + dt * 1e9 * exp(-6000./grid[i].T);
         } else {
            grid[i].sph = grid[i].sph + dt * -2.e8 * exp(-6000./grid[i].T) * pow(Tgrad,0.4);
         }
      } else {
         // Dendritic snow
         if (Tgrad <= 5.) {
            grid[i].dnd = grid[i].dnd + dt * -2.e8 * exp(-6000./grid[i].T);
            grid[i].sph = grid[i].sph + dt * 1e9 * exp(-6000./grid[i].T);
         } else {
            grid[i].dnd = grid[i].dnd + dt * -2.e8 * exp(-6000./grid[i].T) * pow(Tgrad,0.4);
            grid[i].sph = grid[i].sph + dt * -2.e8 * exp(-6000./grid[i].T) * pow(Tgrad,0.4);
         }
      }
      // consistency checks
      grid[i].dnd = std::max(std::min(1.0, grid[i].dnd), 0.0);
      grid[i].sph = std::max(std::min(1.0, grid[i].sph), 0.0);
   }
}
Exemple #3
0
bool MockNamedValue::equals(const MockNamedValue& p) const
{
	if (type_ != p.type_) return false;

	if (type_ == "int")
		return value_.intValue_ == p.value_.intValue_;
	else if (type_ == "char*")
		return SimpleString(value_.stringValue_) == SimpleString(p.value_.stringValue_);
	else if (type_ == "void*")
		return value_.pointerValue_ == p.value_.pointerValue_;
	else if (type_ == "double")
		return (doubles_equal(value_.doubleValue_, p.value_.doubleValue_, 0.005));

	if (comparator_)
		return comparator_->isEqual(value_.objectPointerValue_, p.value_.objectPointerValue_);

	return false;
}
TEST(UtestShell, compareDoubles)
{
	double zero = 0.0;
	double not_a_number = zero / zero;
	CHECK(doubles_equal(1.0, 1.001, 0.01));
	CHECK(!doubles_equal(not_a_number, 1.001, 0.01));
	CHECK(!doubles_equal(1.0, not_a_number, 0.01));
	CHECK(!doubles_equal(1.0, 1.001, not_a_number));
	CHECK(!doubles_equal(1.0, 1.1, 0.05));

	double a = 1.2345678;
	CHECK(doubles_equal(a, a, 0.000000001));
}
Exemple #5
0
double ConfigParser::getDouble(const char* name, bool required, double minval, double maxval, double defval){
   const char * rtnnam = "ConfigParser::getDouble()";
   double tmp;
   if (required){
      double missval = -9999.;
      tmp = iniparser_getdouble(_dict, name, missval);
      if (doubles_equal(tmp, missval)){
         logger << "ERROR: " << rtnnam << " required value not found: " << name << std::endl;
         std::abort();
      }
   } else {
      tmp = iniparser_getdouble(_dict, name, defval);
   }
   if (tmp < minval || tmp > maxval) {
      logger << "ERROR: " << rtnnam << " value out of bounds " << name << std::endl;
      logger << "ERROR: " << rtnnam << " val = " << tmp << ", minval = " << minval << ", maxval = " << maxval << std::endl;
      std::abort();
   }
   logger << "INFO: " << name << " = " << tmp << std::endl;
   return tmp;
}
Exemple #6
0
void UtestShell::assertDoublesEqual(double expected, double actual, double threshold, const char* fileName, int lineNumber, const TestTerminator& testTerminator)
{
    getTestResult()->countCheck();
    if (!doubles_equal(expected, actual, threshold))
        failWith(DoublesEqualFailure(this, fileName, lineNumber, expected, actual, threshold), testTerminator);
}
Exemple #7
0
bool MockNamedValue::equals(const MockNamedValue& p) const
{
    if((type_ == "long int") && (p.type_ == "int"))
        return value_.longIntValue_ == p.value_.intValue_;
    else if((type_ == "int") && (p.type_ == "long int"))
        return value_.intValue_ == p.value_.longIntValue_;
    else if((type_ == "unsigned int") && (p.type_ == "int"))
        return (long)value_.unsignedIntValue_ == (long)p.value_.intValue_;
    else if((type_ == "int") && (p.type_ == "unsigned int"))
        return (long)value_.intValue_ == (long)p.value_.unsignedIntValue_;
    else if((type_ == "unsigned long int") && (p.type_ == "int"))
        return value_.unsignedLongIntValue_ == (unsigned long)p.value_.intValue_;
    else if((type_ == "int") && (p.type_ == "unsigned long int"))
        return (unsigned long)value_.intValue_ == p.value_.unsignedLongIntValue_;
    else if((type_ == "unsigned int") && (p.type_ == "long int"))
        return (long int)value_.unsignedIntValue_ == p.value_.longIntValue_;
    else if((type_ == "long int") && (p.type_ == "unsigned int"))
        return value_.longIntValue_ == (long int)p.value_.unsignedIntValue_;
    else if((type_ == "unsigned int") && (p.type_ == "unsigned long int"))
        return value_.unsignedIntValue_ == p.value_.unsignedLongIntValue_;
    else if((type_ == "unsigned long int") && (p.type_ == "unsigned int"))
        return value_.unsignedLongIntValue_ == p.value_.unsignedIntValue_;
    else if((type_ == "long int") && (p.type_ == "unsigned long int"))
        return (value_.longIntValue_ >= 0) && (value_.longIntValue_ == (long) p.value_.unsignedLongIntValue_);
    else if((type_ == "unsigned long int") && (p.type_ == "long int"))
        return (p.value_.longIntValue_ >= 0) && ((long)value_.unsignedLongIntValue_ == p.value_.longIntValue_);

    if (type_ != p.type_) return false;

    if (type_ == "bool")
        return value_.boolValue_ == p.value_.boolValue_;
    else if (type_ == "int")
        return value_.intValue_ == p.value_.intValue_;
    else if (type_ == "unsigned int")
        return value_.unsignedIntValue_ == p.value_.unsignedIntValue_;
    else if (type_ == "long int")
        return value_.longIntValue_ == p.value_.longIntValue_;
    else if (type_ == "unsigned long int")
        return value_.unsignedLongIntValue_ == p.value_.unsignedLongIntValue_;
    else if (type_ == "const char*")
        return SimpleString(value_.stringValue_) == SimpleString(p.value_.stringValue_);
    else if (type_ == "void*")
        return value_.pointerValue_ == p.value_.pointerValue_;
    else if (type_ == "const void*")
        return value_.constPointerValue_ == p.value_.constPointerValue_;
    else if (type_ == "void (*)()")
        return value_.functionPointerValue_ == p.value_.functionPointerValue_;
    else if (type_ == "double")
        return (doubles_equal(value_.doubleValue_, p.value_.doubleValue_, 0.005));
    else if (type_ == "const unsigned char*")
    {
        if (size_ != p.size_) {
            return false;
        }
        return SimpleString::MemCmp(value_.memoryBufferValue_, p.value_.memoryBufferValue_, size_) == 0;
    }

    if (comparator_)
        return comparator_->isEqual(value_.objectPointerValue_, p.value_.objectPointerValue_);

    return false;
}
//-------------------------------------------------------------------------
// Jenks' Optimization Method
//
//-------------------------------------------------------------------------
void MgFeatureNumericFunctions::GetJenksCategories(  VECTOR &inputData, int numPartsRequested,
                                                 double dataMin, double dataMax,
                                                 VECTOR &distValues )
{
    // numPartsRequested // 2 - 10; 5 is good
    int i = 0;  // index for numObservations (may be very large)
    int j = 0;  // index for numPartsRequested (about 4-8)
    int k = 0;

    // Sort the data values in ascending order
    std::sort(inputData.begin(), inputData.end());

    int numObservations = (int)inputData.size();  // may be very large
    // Possible improvement: Rework the code to use normal 0 based arrays.
    // Actually it doesn't matter much since we have to create two
    // matrices that themselves use more memory than the local copy
    // of inputData.
    //
    // In order to ease the use of original FORTRAN and the later BASIC
    // code, I will use 1 origin arrays and copy the inputData into
    // a local array;
    // I'll dimension the arrays one larger than necessary and use the
    // index values from the original code.
    //
    // The algorithm must calculate with floating point values.
    // If more optimization is attempted in the future, be aware of
    // problems with calculations using mixed numeric types.

    std::vector<double> data;
    data.push_back(0);  // dummy value at index 0
    std::copy(inputData.begin(), inputData.end(), std::back_inserter(data));
    // copy from parameter inputData so that data index starts from 1

    // Note that the Matrix constructors initialize all values to 0.
    // mat1 contains integer values used for indices into data
    // mat2 contains floating point values of data and bigNum
    MgMatrix<int>     mat1(numObservations + 1, numPartsRequested + 1);
    MgMatrix<double>  mat2(numObservations + 1, numPartsRequested + 1);

//  const double bigNum = 1e+14; // from original BASIC code;
//  const double bigNum = std::numeric_limits<double>::max();
    const double bigNum = DBL_MAX;   // compiler's float.h

    for (i = 1; i <= numPartsRequested; ++i)
    {
        mat1.Set(1, i, 1);
        for (j = 2; j <= numObservations; ++j)
        {
            mat2.Set(j, i, bigNum);
        }
    }

    std::vector<int> classBounds;
    classBounds.push_back(-2);  // dummy value
    for (i = 1; i <= numPartsRequested; ++i)
    {
        classBounds.push_back(-1);
    }

    for (int L = 2; L <= numObservations; ++L)
    {
        double s1 = 0;
        double s2 = 0;
        double v = 0;
        int w = 0;

        for (int m = 1; m <= L; ++m)
        {
            int i3 = L - m + 1;
            double val = data[i3];
            s2 += (double(val) * double(val));
            // if datatype of val is ever allowed to be same as template
            // parameter T, make sure multiplication is done in double.
            s1 += val;
            ++w;
            v = s2 - ((s1 * s1) / w);
            int i4 = i3 - 1;

            if (i4 > 0)
            {
                for (j = 2; j <= numPartsRequested; ++j)
                {
                    double tempnum = v + mat2.Get(i4, j - 1);
                    if (double(mat2.Get(L, j)) >= tempnum)
                    {
                        mat1.Set(L, j, i3);
                        mat2.Set(L, j, tempnum);
                    }
                }
            }
        }

        mat1.Set(L, 1, 1);
        mat2.Set(L, 1, v);
    }

    k = numObservations;
    for (j = numPartsRequested; j >= 1; --j)
    {
        if (k >= 0 && k <= numObservations)
        {
            classBounds[j] = mat1.Get(k, j);
            k = mat1.Get(k, j) - 1;
        }
    }

    std::vector<int> indices;

    indices.push_back(0);
    for (i = 2; i <= numPartsRequested; ++i)
    {
        int index = classBounds[i] - 1;
        if (index > indices.back())
        {
            indices.push_back(index);
        }
    }

    FixGroups(inputData, indices);

    double val = 0.0;
    int index = 0;
    int totIndex = (int)indices.size();

    for (int i = 1; i < totIndex; ++i)
    {
        index = indices[i] - 1;

        val = inputData[index];
        distValues.push_back(val);
    }

    index = numObservations - 1;
    val = inputData[index];
    distValues.push_back(val);

    int retCnt = (int)distValues.size();
    int inCnt = (int)inputData.size();

    if (retCnt > 0 && inCnt > 0)
    {
        if (!doubles_equal(distValues[0],inputData[0]))
        {
            distValues.insert(distValues.begin(), inputData[0]);
        }
    }

    return;
}
Exemple #9
0
void CompactionCROCUS::compactionWindDrift(){
   /* Compaction due to wind drift */
   Grid& grid = _mstate.getGrid();
   const int Np = grid.size();
   if (Np < 2) return; // no metamorphism
   static const double rho_min = 50.; // minimum density [kg/m3]
   static const double rho_max = 350.; // maximum density [kg/m3]
   static const double tau_ref = (double)48 * 3600; // reference time [s]
   const double U = _mstate.getMeteo().surfaceWind();
   const double dt = (double)_dm.getDt(); // time step [s]
   double layer_mass;
   double Frho;
   double MO; // mobility index
   double SI; // driftability index
   double tau; // time characteristic
   double zi = 0.; // pseudo-depth in m
   double gamma_drift;
   double u0, afac; // TUNING
   for (int i = grid.size()-1; i >= 0; i--) {
      Frho = 1.25 - 0.0042*(std::max(rho_min, grid[i].dens)-rho_min);
      if (doubles_equal(grid[i].dnd, 0.0)) {
         // Non-dendritic snow
         MO = 0.34 * (-0.583*grid[i].gs - 0.833*grid[i].sph + 0.833) + 0.66*Frho;
      } else { 
         // dendritic snow
         MO = 0.34 * (0.75*grid[i].dnd - 0.5*grid[i].sph + 0.5) + 0.66*Frho;
      }

      /* LvK: tuning */
//      static const double wind_fac = -0.085;
//      u0 = log((-1.-MO)/-2.868) / -0.085;
//      u0 = u0 - 2.;
//      afac = (-1. - MO) / exp(wind_fac * u0 ); // based on exponent factor, determine pre-factor by setting SI = 0 to the same U-value
//      SI = afac * exp(wind_fac*U) + 1 + MO; 
      /* LvK: end of Tuning */
      SI = -2.868 * exp(-0.085*U)+1.+MO;

      if (SI <= 0.0) break; // first non-mobile layer has been reached
      SI = std::min(SI, 3.25);
      zi += grid[i].dz * 0.5 *  (3.25 - SI);

      gamma_drift = std::max(0., SI*exp(-zi/0.1));
      tau = tau_ref / gamma_drift;
      if (doubles_equal(grid[i].dnd, 0.0)) {
         // Non-dendritic snow
         grid[i].sph = grid[i].sph + dt * (1-grid[i].sph)/tau;
         grid[i].gs = grid[i].gs + dt * 5e-4/tau;
      } else { 
         // dendritic snow
         grid[i].dnd = grid[i].dnd + dt * grid[i].dnd/(2*tau);
         grid[i].sph = grid[i].sph + dt * (1-grid[i].sph)/tau;
      }
      // consistency checks
      grid[i].dnd = std::max(std::min(1.0, grid[i].dnd), 0.0);
      grid[i].sph = std::max(std::min(1.0, grid[i].sph), 0.0);
      grid[i].gs = std::max(std::min(fs_gs_max, grid[i].gs), 0.0);

      layer_mass = grid[i].dz * grid[i].dens;
      // density evolution
      //logger << "DEBUG dens = " << grid[i].dens << ", U = " << U << ", zi = " << zi << ", drho / 24h = " << 24*3600 * std::max(0.0, rho_max - grid[i].dens)/tau << std::endl;
      grid[i].dens = grid[i].dens + dt * std::max(0.0, rho_max - grid[i].dens)/tau;
      grid[i].dz = layer_mass/grid[i].dens; // # mass conservation

      if (gamma_drift > 100.0) {
         logger << "warning: large gamma\n";
         logger << "i / Np = " << i << " / " << grid.size() << "\n";
         logger << "U = " << U << "\n";
         logger << "SI = " << SI << "\n";
         logger << "MO = " << MO << "\n";
         logger << "zi = " << zi << "\n";
         //logger << "dens_old = " << dens_old << "\n";
         //logger << "dens_new = " << grid[i].dens << "\n";
         //logger << "d= " << s_old << "\n";
         //logger << "s= " << d_old << "\n";
         //logger << "gs= " << gs_old << "\n";
      }
      logger.flush();  
      zi += grid[i].dz * 0.5 *  (3.25 - SI);
   }
}