double Ln_Gamma_Function(double x) { // For a positive argument, 0 < x <= Gamma_Function_Max_Arg() // // then return log Gamma(x). // if (x <= Gamma_Function_Max_Arg()) return log(Gamma_Function(x)); // otherwise return result from asymptotic expansion of ln Gamma(x). // return (double) xLnGamma_Asymptotic_Expansion( (long double) x ); }
void Gamma_Distribution_Tables(double a, double start, double delta, int nsteps, double *density, double* distribution_function) { double x = start; int i; for (i = 0; i <= nsteps; i++) { if (x <= 0.0) { density[i] = 0.0; distribution_function[i] = 0.0; } else { if (a <= Gamma_Function_Max_Arg() ) density[i] = pow(x,a-1.0) * exp(-x) / Gamma_Function(a); else density[i] = exp( (a - 1.0) * log(x) - x - Ln_Gamma_Function(a) ); distribution_function[i] = Entire_Incomplete_Gamma_Function(x,a); } x += delta; } }
bool computeRootDensity(Crit3DCrop* myCrop, soil::Crit3DLayer* layers, int nrLayers, double soilDepth) { int i, j, layer; // Initialize for (i=0; i<nrLayers; i++) myCrop->roots.rootDensity[i]=0.0; if ((! myCrop->isLiving) || (myCrop->roots.rootLength <= 0 )) return true; if ((myCrop->roots.rootShape == CARDIOID_DISTRIBUTION) || (myCrop->roots.rootShape == CYLINDRICAL_DISTRIBUTION)) { double minimumThickness; int *atoms = (int *) calloc(nrLayers, sizeof(int)); int numberOfRootedLayers, numberOfTopUnrootedLayers, totalLayers; totalLayers = root::nrAtoms(layers, nrLayers, myCrop->roots.rootDepthMin, &minimumThickness, atoms); numberOfTopUnrootedLayers = int(round(myCrop->roots.rootDepthMin / minimumThickness)); numberOfRootedLayers = int(ceil(minValue(myCrop->roots.rootLength, soilDepth) / minimumThickness)); double *densityThinLayers = (double *) calloc(totalLayers+1, sizeof(double)); densityThinLayers[totalLayers] = 0.; for (i=0; i < totalLayers; i++) densityThinLayers[i] = 0.; if (myCrop->roots.rootShape == CARDIOID_DISTRIBUTION) { cardioidDistribution(myCrop->roots.shapeDeformation, numberOfRootedLayers, numberOfTopUnrootedLayers, totalLayers, densityThinLayers); } else if (myCrop->roots.rootShape == CYLINDRICAL_DISTRIBUTION) { cylindricalDistribution(myCrop->roots.shapeDeformation, numberOfRootedLayers, numberOfTopUnrootedLayers, totalLayers, densityThinLayers); } int counter =0; for (layer=0; layer<nrLayers; layer++) { for (j=counter; j<counter + atoms[layer]; j++) { if (j < totalLayers) myCrop->roots.rootDensity[layer] += densityThinLayers[j]; } counter = j; } free(atoms); free(densityThinLayers); } else if (myCrop->roots.rootShape == GAMMA_DISTRIBUTION) { double normalizationFactor ; double kappa, theta,a,b; double mean, mode; mean = myCrop->roots.rootLength * 0.5; mode = myCrop->roots.rootLength * 0.2; theta = mean - mode; kappa = mean / theta; // complete gamma function normalizationFactor = Gamma_Function(kappa); for (i=1 ; i<nrLayers ; i++) { b = maxValue(layers[i].depth + layers[i].thickness*0.5 - myCrop->roots.rootDepthMin,0); // right extreme if (b>0) { a = maxValue(layers[i].depth - layers[i].thickness*0.5 - myCrop->roots.rootDepthMin,0); //left extreme myCrop->roots.rootDensity[i] = Incomplete_Gamma_Function(b/theta,kappa) - Incomplete_Gamma_Function(a/theta,kappa); myCrop->roots.rootDensity[i] /= normalizationFactor; } } } double rootDensitySum = 0. ; for (i=0 ; i<nrLayers ; i++) { myCrop->roots.rootDensity[i] *= layers[i].soilFraction; rootDensitySum += myCrop->roots.rootDensity[i]; } for (i=0 ; i<nrLayers ; i++) { myCrop->roots.rootDensity[i] /= rootDensitySum; } myCrop->roots.firstRootLayer = 0; layer = 0; while ((myCrop->roots.rootDensity[layer] == 0) && (layer < nrLayers)) { layer++; (myCrop->roots.firstRootLayer)++; } myCrop->roots.lastRootLayer = myCrop->roots.firstRootLayer; while ((myCrop->roots.rootDensity[layer] != 0) && (layer < nrLayers)) { (myCrop->roots.lastRootLayer) = layer; layer++; } return true; }