Esempio n. 1
0
        public Task <double> GetVarianceForCombinationAsync(IPs latWeights, IPs lonWeights, ICellRequest cell, double baseNodeVariance)
        {
            Tuple <IPs, IPs, ICellRequest, double> capturedValues = Tuple.Create(latWeights, lonWeights, cell, baseNodeVariance);

            return(Task.Factory.StartNew(obj =>
            {
                Tuple <IPs, IPs, ICellRequest, double> arg = (Tuple <IPs, IPs, ICellRequest, double>)obj;

                var cell2 = arg.Item3;
                var name = cell2.VariableName;

                double[] targetLats, targetLons;

                if (cell2.LatMax == cell2.LatMin && cell2.LonMax == cell2.LonMin)
                {
                    targetLats = new double[] { cell2.LatMax };
                    targetLons = new double[] { cell2.LonMax };
                }
                else
                {
                    double latStep = (cell2.LatMax - cell2.LatMin) / (cellDevisionCount - 1);
                    double lonStep = (cell2.LonMax - cell2.LonMin) / (cellDevisionCount - 1);
                    targetLats = Enumerable.Range(0, cellDevisionCount).Select(j => cell2.LatMin + j * latStep).ToArray();
                    targetLons = Enumerable.Range(0, cellDevisionCount).Select(j => cell2.LonMin + j * lonStep).ToArray();
                }

                //coerce each target location to the closest data grid node. As closest data grid node is representative for its region. (indirect coercing of distance function by moving target locations)
                targetLats = Align(latAxis, targetLats);
                targetLons = Align(lonAxis, targetLons);

                var fieldDescription = dict.GetOrAdd(name, new Lazy <IGaussianFieldDescription>(() =>
                {
                    var v = variogramsFactory.Create(name);
                    if (v == null)
                    {
                        ts.TraceEvent(TraceEventType.Warning, 1, string.Format("Could not find spatial variogram for the \"{0}\" variable. Skipping uncertainty propagation analysis", name));
                    }
                    else
                    {
                        ts.TraceEvent(TraceEventType.Information, 2, string.Format("Loaded spatial variogram for \"{0}\" variable", name));
                    }
                    return v;
                }, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication)).Value;

                if (fieldDescription == null)
                {
                    return double.MaxValue;
                }

                var variogram = fieldDescription.Variogram;
                var spatPrecomputedSill = variogram.Sill;
                var spatPrecomputedNugget = variogram.Nugget;

                var coercedBaseVariance = double.IsNaN(arg.Item4) ? (spatPrecomputedNugget) : arg.Item4;
                var spatDistance = new Func <double, double, double, double, double>((lat1, lon1, lat2, lon2) => fieldDescription.Dist(lat1, lon1, lat2, lon2));
                var spatCovariogram = new Func <double, double>(distance => (spatPrecomputedSill - variogram.GetGamma(distance)));
                SpatialVarianceProperties svp = new SpatialVarianceProperties(spatPrecomputedSill - spatPrecomputedNugget + coercedBaseVariance, spatDistance, spatCovariogram);

                return GetSpatialVariance(arg.Item1, arg.Item2, latAxis, lonAxis, targetLats, targetLons, svp);     //basic scale_factor/add_offset data transform are assumed to be applied during variograms fitting
            }, capturedValues));
        }
Esempio n. 2
0
        private static double GetSpatialVariance(IPs latWeights, IPs lonWeights, double[] latNodes, double[] lonNodes, double[] targetLats, double[] targetLons, SpatialVarianceProperties varianceProps)
        {
            //Var(x) = Cov(0) + sum(sum(v_i*v_j*Cov(X_i,X_j)) - 2.0 * sum(v_i*Cov(X_i,X))) for semivariograms
            double spatCov0        = varianceProps.Cov0;
            var    spatCovariogram = varianceProps.Covariance;
            var    dist            = varianceProps.Distance;
            double acc             = spatCov0; //Cov(0)
            var    weights1        = latWeights.Weights;
            var    indices1        = latWeights.Indices;
            var    weights2        = lonWeights.Weights;
            var    indices2        = lonWeights.Indices;
            var    N1   = weights1.Length;
            var    N2   = weights2.Length;
            int    N_T  = N1 * N2;
            var    M1   = targetLats.Length;
            var    M2   = targetLons.Length;
            double sum2 = 0.0;

            Tuple <double, double, double>[] stratched = new Tuple <double, double, double> [N_T];
            for (int i = 0; i < N1; i++)
            {
                for (int j = 0; j < N2; j++)
                {
                    stratched[N2 * i + j] = Tuple.Create(weights1[i] * weights2[j], latNodes[indices1[i]], lonNodes[indices2[j]]);
                }
            }

            for (int i = 0; i < N_T; i++)
            {
                var    element_i = stratched[i];
                double weight_i  = element_i.Item1;
                double lat_i     = element_i.Item2;
                double lon_i     = element_i.Item3;
                acc += weight_i * weight_i * spatCov0;
                for (int j = i + 1; j < N_T; j++)
                {
                    var element_j = stratched[j];
                    // sum(sum(lambda.[i]*lambda.[j]*Cov(X_i,X_j))
                    acc += 2.0 * weight_i * element_j.Item1 * spatCovariogram(dist(lat_i, lon_i, element_j.Item2, element_j.Item3));
                }

                double cov_x_xi = 0.0;
                for (int k = 0; k < M1; k++) //average cov(x,x_i) as in block kriging for region requsts
                {
                    for (int l = 0; l < M2; l++)
                    {
                        cov_x_xi += spatCovariogram(dist(targetLats[k], targetLons[l], lat_i, lon_i));
                    }
                }
                //v_i*Cov(X_i,X)))
                sum2 += weight_i * cov_x_xi / (M1 * M2);
            }
            return(0.5 * acc - sum2); //as working with full variograms instead of semivariograms
        }