Ejemplo n.º 1
0
        public Matrix <double> Update(Matrix <double> E, double[,] HE, double[] observations, double[,] obsCoVar, double inflationFactor, double dampning)
        {
            Matrix <double> XXX = E;
            int             m_ensembleMembers       = XXX.ColumnCount;
            int             n_elementsinStateVector = XXX.RowCount;
            int             p_DA_obs = observations.Length;

            double tolerance = 1.5;

            var             M = Matrix <double> .Build;
            Vector <double> x = XXX.RowSums().Divide(m_ensembleMembers); //ensemble mean

            //substract ensemble mean to get ensemble anomelis (XXX = A)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] -= x[n];
                }
            }


            //get HA
            //double[,] HE = new double[p_DA_obs, m_ensembleMembers];
            double[] hx     = new double[p_DA_obs]; //mean of y
            double[] dytemp = new double[p_DA_obs]; //innovation, dy = y - Hx(p x 1)

            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    hx[i] += HE[i, j];
                }
                hx[i]     = hx[i] / m_ensembleMembers;
                dytemp[i] = observations[i] - hx[i];
            }
            Vector <double> dy = Vector <double> .Build.Dense(dytemp);



            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    HE[i, j] -= hx[i];// substract mean to get anomalies at h
                }
            }

            Matrix <double> HA = M.DenseOfArray(HE);

            for (int i = 0; i < p_DA_obs; i++)
            {
                double stdObs  = Math.Sqrt(obsCoVar[i, i]);//Does not take covar into account.
                double uplim   = dy[i] + tolerance * stdObs;
                double downlim = dy[i] - tolerance * stdObs;

                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    if (HE[i, j] > uplim)
                    {
                        HE[i, j] -= uplim;
                    }
                    else if (HE[i, j] < downlim)
                    {
                        HE[i, j] -= downlim;
                    }
                    else
                    {
                        HE[i, j] = 0;
                    }
                }
            }
            Matrix <double> HAx = M.DenseOfArray(HE);

            Matrix <double> ObsCoVar = M.DenseOfArray(obsCoVar);

            KK = new KalmanGain(n_elementsinStateVector, p_DA_obs);
            KK.CaclulateGain(XXX, HA, ObsCoVar);
            XXX = XXX.Subtract((KK.K.Multiply(HAx)).Multiply(dampning));  //XXX contains updated A
            XXX = XXX.Multiply(inflationFactor);
            // XXX = XXX.Subtract(KK.K.Multiply(HA));
            //Vector<double> Obs = Vector<double>.Build.Dense(observations);


            Vector <double> dx = KK.K.Multiply(dampning) * dy;

            //add ensemble mean to ensemble anomelis (XXX = A + dx + x)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] += (x[n] + dx[n]);
                }
            }
            return(XXX);
        }
Ejemplo n.º 2
0
        public Matrix <double> Update(Matrix <double> E, double[,] HE, double[] observations, double[,] obsCoVar, double rFactor, double dampning)
        {
            Matrix <double> XXX = E;
            int             m_ensembleMembers       = XXX.ColumnCount;
            int             n_elementsinStateVector = XXX.RowCount;
            int             p_DA_obs = observations.Length;


            var             M = Matrix <double> .Build;
            Vector <double> x = XXX.RowSums().Divide(m_ensembleMembers); //ensemble mean

            //substract ensemble mean to get ensemble anomelis (XXX = A)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] -= x[n];
                }
            }


            //get HA
            //double[,] HE = new double[p_DA_obs, m_ensembleMembers];
            double[] hx     = new double[p_DA_obs]; //mean of y
            double[] dytemp = new double[p_DA_obs]; //innovation, dy = y - Hx(p x 1)

            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    hx[i] += HE[i, j];
                }
                hx[i]     = hx[i] / m_ensembleMembers;
                dytemp[i] = observations[i] - hx[i];
            }
            Vector <double> dy = Vector <double> .Build.Dense(dytemp);


            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    HE[i, j] -= hx[i];    // substract mean to get anomalies at h
                }
            }



            Matrix <double> HA = M.DenseOfArray(HE);


            double[] dd = new double[HA.RowCount * HA.ColumnCount];
            MathNet.Numerics.Distributions.Normal.Samples(dd, 0, 1.0);
            Matrix <double> D        = (M.Dense(HA.RowCount, HA.ColumnCount, dd));
            Matrix <double> ObsCoVar = M.DenseOfArray(obsCoVar);

            D = D.TransposeThisAndMultiply((ObsCoVar.PointwiseSqrt()).Multiply(rFactor)).Transpose();


            // from SAKOV's assimilate.m
            // D = randn(p, m) * sqrt(r * rfactor);
            //  % Subtract the ensemble mean from D to ensure that update of the
            //  % anomalies does not perturb the ensemble mean. This reduces the
            //  % variance of each sample by a factor of 1 - 1 / m(I think).
            //  %
            //   d = mean(D')';
            //   D = sqrt(m / (m - 1)) * (D - repmat(d, 1, m));

            //   A = A + K * (D - HA);
            KK = new KalmanGain(n_elementsinStateVector, p_DA_obs);
            KK.CaclulateGain(XXX, HA, ObsCoVar);

            //XXX = XXX.Subtract(KK.K.Multiply(HA.Subtract(D)));//XXX contains updated A



            // XXX = XXX.Multiply(inflationFactor);
            // XXX = XXX.Subtract(KK.K.Multiply(HA));
            //Vector<double> Obs = Vector<double>.Build.Dense(observations);


            Vector <double> dx = KK.K.Multiply(dampning) * dy;


            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] = XXX[n, i] * (x[n] + dx[n]) / x[n];//XXX contains updated A (scaled by change (unchanged std/mean)
                }
            }



            //add ensemble mean to ensemble anomelis (XXX = A + dx + x)
            //MB: a faster way?

            //Calculate var and K at observed locations h
            // double[] VarAtH = new double[p_DA_obs];
            //double[] KAtH = new double[p_DA_obs];

            /*           for (int i = 0; i < p_DA_obs; i++)
             *         {
             *             for (int j = 0; j < m_ensembleMembers; j++)
             *             {
             *                 VarAtH[i] += HE[i, j]* HE[i, j];// substract mean to get anomalies at h . beeeregn var
             *             }
             *             VarAtH[i] = VarAtH[i] / (m_ensembleMembers-1);
             *             //KAtH[i] = VarAtH[i] / (VarAtH[i] + obsCoVar[i,i]);
             *         }
             */

//sektion for ekstra inflationsstoej.
            //  double[] dd2 = new double[HA.RowCount * HA.ColumnCount];
            // MathNet.Numerics.Distributions.Normal.Samples(dd2, 0, 1.0);
            //  Matrix<double> D2 = (M.Dense(HA.RowCount, HA.ColumnCount, dd));
            //D2 = D2.TransposeThisAndMultiply(ObsCoVar.PointwiseSqrt()).Transpose();lkj
            //XXX = XXX.Subtract(KK.K.Multiply(D2));//hvor D2 er støj der fordeles med K som en slags inflation der IKKE påvirker K.


            for (int n = 0; n < n_elementsinStateVector; n++)
            {
                //double tempInflate = (1 + (inflationFactor - 1) * (Math.Abs((KK.K[n, 0] / (KAtH[0]+1)) * dy[0] / (Math.Sqrt(VarAtH[0])+Math.Sqrt(obsCoVar[0, 0])))));//mangler af justify addition of obs std (perhabs som sum of variances) til sidst og  Kalman konstanten 1
                // tempInflate = 1;
                for (int i = 0; i < m_ensembleMembers; i++)
                {
                    //inflate first
                    //double tempInflate = (1 + (inflationFactor - 1) * (KK.K[n, 0] / KAtH[0]) * (dy[0] / Math.Sqrt(VarAtH[0])));
                    //   XXX[n, i] = XXX[n, i] * tempInflate; // virker kun med en obs .Skift 100 ud med custom factor.
                    //then recontruct ensamble



                    XXX[n, i] += (x[n] + dx[n]);
                }
            }
            return(XXX);
        }
Ejemplo n.º 3
0
        public Matrix <double> Update(Matrix <double> E, double[,] HE, double[] observations, double[,] obsCoVar, double inflationFactor, double dampning)
        {
            Matrix <double> XXX = E;
            int             m_ensembleMembers       = XXX.ColumnCount;
            int             n_elementsinStateVector = XXX.RowCount;
            int             p_DA_obs  = observations.Length;
            double          stdObs    = Math.Sqrt(obsCoVar[0, 0]);// only implemented for a single obs
            double          tolerance = 1.5;

            var             M = Matrix <double> .Build;
            Vector <double> x = XXX.RowSums().Divide(m_ensembleMembers); //ensemble mean

            //substract ensemble mean to get ensemble anomelis (XXX = A)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] -= x[n];
                }
            }


            //get HA
            //double[,] HE = new double[p_DA_obs, m_ensembleMembers];
            double[] hx     = new double[p_DA_obs]; //mean of y
            double[] dytemp = new double[p_DA_obs]; //innovation, dy = y - Hx(p x 1)

            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    hx[i] += HE[i, j];
                }
                hx[i]     = hx[i] / m_ensembleMembers;
                dytemp[i] = observations[i] - hx[i];
            }
            Vector <double> dy = Vector <double> .Build.Dense(dytemp);

            double uplim   = dy[0] + tolerance * stdObs;
            double downlim = dy[0] - tolerance * stdObs;

            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    HE[i, j] -= hx[i];// substract mean to get anomalies at h
                }
            }

            Matrix <double> HA = M.DenseOfArray(HE);

            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    if (HE[i, j] > uplim)
                    {
                        HE[i, j] -= uplim;
                    }
                    else if (HE[i, j] < downlim)
                    {
                        HE[i, j] -= downlim;
                    }
                    else
                    {
                        HE[i, j] = 0;
                    }
                }
            }
            Matrix <double> HAx = M.DenseOfArray(HE);

            Matrix <double> ObsCoVar = M.DenseOfArray(obsCoVar);

            KK = new KalmanGain(n_elementsinStateVector, p_DA_obs);
            KK.CaclulateGain(XXX, HA, ObsCoVar);

            //calculate dampening from dy and std HE


            double[] VarAtH = new double[p_DA_obs];
            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    VarAtH[i] += HE[i, j] * HE[i, j];          // substract mean to get anomalies at h . beeeregn var
                }
                VarAtH[i] = VarAtH[i] / (m_ensembleMembers - 1);
            }
            double dy_std = Math.Abs(dy[0]) / Math.Sqrt(VarAtH[0]);

            if (dy_std > tolerance)
            {
                //        dampning = 1 / (1 + (dy_std - tolerance)*(dy_std - tolerance));// NOTE: Only implementet for single obs loc so far!
            }


            XXX = XXX.Subtract((KK.K.Multiply(HAx)).Multiply(dampning));             //XXX contains updated A
            XXX = XXX.Multiply(inflationFactor);
            // XXX = XXX.Subtract(KK.K.Multiply(HA));
            //Vector<double> Obs = Vector<double>.Build.Dense(observations);


            //   Vector<double> dx = KK.K * dy;

            //add ensemble mean to ensemble anomelis (XXX = A + dx + x)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    //XXX[n, i] += (x[n] + dx[n]);
                    XXX[n, i] += x[n];
                }
            }
            return(XXX);
        }
Ejemplo n.º 4
0
        public Matrix <double> Update(Matrix <double> E, double[,] HE, double[] observations, double[,] obsCoVar, double inflationFactor, double dampning)
        {
            Matrix <double> XXX = E;
            int             m_ensembleMembers       = XXX.ColumnCount;
            int             n_elementsinStateVector = XXX.RowCount;
            int             p_DA_obs = observations.Length;


            var             M = Matrix <double> .Build;
            Vector <double> x = XXX.RowSums().Divide(m_ensembleMembers); //ensemble mean

            //substract ensemble mean to get ensemble anomelis (XXX = A)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] -= x[n];
                }
            }


            //get HA
            //double[,] HE = new double[p_DA_obs, m_ensembleMembers];
            double[] hx     = new double[p_DA_obs]; //mean of y
            double[] dytemp = new double[p_DA_obs]; //innovation, dy = y - Hx(p x 1)

            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    hx[i] += HE[i, j];
                }
                hx[i]     = hx[i] / m_ensembleMembers;
                dytemp[i] = observations[i] - hx[i];
            }
            Vector <double> dy = Vector <double> .Build.Dense(dytemp);


            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    HE[i, j] -= hx[i];// substract mean to get anomalies at h
                }
            }

            Matrix <double> HA = M.DenseOfArray(HE);


            double[] dd = new double[HA.RowCount * HA.ColumnCount];
            MathNet.Numerics.Distributions.Normal.Samples(dd, 0, 1.0);
            Matrix <double> D        = (M.Dense(HA.RowCount, HA.ColumnCount, dd));
            Matrix <double> ObsCoVar = M.DenseOfArray(obsCoVar);



            //   A = A + 0.5*K * (HA);
            KK = new KalmanGain(n_elementsinStateVector, p_DA_obs);
            KK.CaclulateGain(XXX, HA, ObsCoVar);
            XXX = XXX.Subtract((KK.K.Multiply(HA)).Multiply(0.5 * dampning));//XXX contains updated A
            XXX = XXX.Multiply(inflationFactor);
            // XXX = XXX.Subtract(KK.K.Multiply(HA));
            //Vector<double> Obs = Vector<double>.Build.Dense(observations);


            Vector <double> dx = KK.K.Multiply(dampning) * dy;

            //add ensemble mean to ensemble anomelis (XXX = A + dx + x)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] += (x[n] + dx[n]);
                }
            }
            return(XXX);
        }
Ejemplo n.º 5
0
        public Matrix <double> Update(Matrix <double> E, double[,] HE, double[] observations, double[,] obsCoVar, double inflationFactor, double dampning)
        {
            Matrix <double> XXX = E;
            int             m_ensembleMembers       = XXX.ColumnCount;
            int             n_elementsinStateVector = XXX.RowCount;
            int             p_DA_obs = observations.Length;


            var             M = Matrix <double> .Build;
            Vector <double> x = XXX.RowSums().Divide(m_ensembleMembers); //ensemble mean

            //substract ensemble mean to get ensemble anomelis (XXX = A)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] -= x[n];
                }
            }


            //get HA
            //double[,] HE = new double[p_DA_obs, m_ensembleMembers];
            double[] hx     = new double[p_DA_obs]; //mean of y
            double[] dytemp = new double[p_DA_obs]; //innovation, dy = y - Hx(p x 1)

            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    hx[i] += HE[i, j];
                }
                hx[i]     = hx[i] / m_ensembleMembers;
                dytemp[i] = observations[i] - hx[i];
            }
            Vector <double> dy = Vector <double> .Build.Dense(dytemp);


            for (int i = 0; i < p_DA_obs; i++)
            {
                for (int j = 0; j < m_ensembleMembers; j++)
                {
                    HE[i, j] -= hx[i];    // substract mean to get anomalies at h
                }
            }

            Matrix <double> HA = M.DenseOfArray(HE);


            double[] dd = new double[HA.RowCount * HA.ColumnCount];
            MathNet.Numerics.Distributions.Normal.Samples(dd, 0, 1.0);
            Matrix <double> D        = (M.Dense(HA.RowCount, HA.ColumnCount, dd));
            Matrix <double> ObsCoVar = M.DenseOfArray(obsCoVar);

            D = D.TransposeThisAndMultiply(ObsCoVar.PointwiseSqrt()).Transpose();


            // from SAKOV's assimilate.m
            // D = randn(p, m) * sqrt(r * rfactor);
            //  % Subtract the ensemble mean from D to ensure that update of the
            //  % anomalies does not perturb the ensemble mean. This reduces the
            //  % variance of each sample by a factor of 1 - 1 / m(I think).
            //  %
            //   d = mean(D')';
            //   D = sqrt(m / (m - 1)) * (D - repmat(d, 1, m));

            //   A = A + K * (D - HA);
            KK = new KalmanGain(n_elementsinStateVector, p_DA_obs);
            KK.CaclulateGain(XXX, HA, ObsCoVar);
            XXX = XXX.Subtract(KK.K.Multiply(HA.Subtract(D)).Multiply(dampning));    //XXX contains updated A
            XXX = XXX.Multiply(inflationFactor);
            // XXX = XXX.Subtract(KK.K.Multiply(HA));
            //Vector<double> Obs = Vector<double>.Build.Dense(observations);


            Vector <double> dx = KK.K.Multiply(dampning) * dy;

            //add ensemble mean to ensemble anomelis (XXX = A + dx + x)
            //MB: a faster way?
            for (int i = 0; i < m_ensembleMembers; i++)
            {
                for (int n = 0; n < n_elementsinStateVector; n++)
                {
                    XXX[n, i] += (x[n] + dx[n]);
                }
            }
            return(XXX);
        }