]> SALOME platform Git repositories - modules/adao.git/commitdiff
Salome HOME
Improvement and extension of EnKF algorithm (VAR)
authorJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Sat, 2 Jan 2021 19:50:34 +0000 (20:50 +0100)
committerJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Sat, 2 Jan 2021 19:50:34 +0000 (20:50 +0100)
src/daComposant/daAlgorithms/EnsembleKalmanFilter.py
src/daComposant/daCore/NumericObjects.py

index d242b6b6017a508110ddaba44e40fb74a68dd8c4..b1019eedd237cf02fe6eceb00ad6428a26198806 100644 (file)
@@ -37,6 +37,7 @@ class ElementaryAlgorithm(BasicObjects.Algorithm):
                 "StochasticEnKF",
                 "ETKF",
                 "ETKF-KFF",
+                "ETKF-VAR",
                 ],
             )
         self.defineRequiredParameter(
@@ -158,6 +159,8 @@ class ElementaryAlgorithm(BasicObjects.Algorithm):
             NumericObjects.senkf(self, Xb, Y, U, HO, EM, CM, R, B, Q)
         elif self._parameters["Minimizer"] in ["ETKF", "ETKF-KFF"]:
             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="KalmanFilterFormula")
+        elif self._parameters["Minimizer"] == "ETKF-VAR":
+            NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="Variational")
         else:
             raise ValueError("Error in Minimizer name: %s"%self._parameters["Minimizer"])
         #
index 15300a9704989247adc111518786507c4e0a1b19..8e847b3a2a46606a8441290e886ce1f6bba4a093 100644 (file)
@@ -26,7 +26,7 @@ __doc__ = """
 __author__ = "Jean-Philippe ARGAUD"
 
 import os, time, copy, types, sys, logging
-import math, numpy, scipy
+import math, numpy, scipy, scipy.optimize
 from daCore.BasicObjects import Operator
 from daCore.PlatformInfo import PlatformInfo
 mpr = PlatformInfo().MachinePrecision()
@@ -914,6 +914,30 @@ def etkf(selfA, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="KalmanFilterFormula"):
             #
             Xn = Xfm.reshape((__n,-1)) + EaX @ ( vw.reshape((__m,-1)) + numpy.sqrt(__m-1) * Tdemi @ mU )
         #--------------------------
+        elif KorV == "Variational":
+            RI     = R.getI()
+            HXfm = H((Xfm, Un)) # Eventuellement Hfm
+            def CostFunction(w):
+                _A  = Ynpu.reshape((__p,-1)) - HXfm.reshape((__p,-1)) - (EaHX @ w).reshape((__p,-1))
+                _J  = 0.5 * (__m-1) * w.T @ w + 0.5 * _A.T * RI * _A
+                return float(_J)
+            def GradientOfCostFunction(w):
+                _A  = Ynpu.reshape((__p,-1)) - HXfm.reshape((__p,-1)) - (EaHX @ w).reshape((__p,-1))
+                _GradJ = (__m-1) * w.reshape((__m,1)) - EaHX.T * RI * _A
+                return numpy.ravel(_GradJ)
+            vw = scipy.optimize.fmin_cg(
+                f           = CostFunction,
+                x0          = numpy.zeros(__m),
+                fprime      = GradientOfCostFunction,
+                args        = (),
+                disp        = False,
+                )
+            #
+            Pta = numpy.linalg.inv( (__m-1)*numpy.eye(__m) + EaHX.T * RI * EaHX )
+            EWa = numpy.real(scipy.linalg.sqrtm((__m-1)*Pta)) # Partie imaginaire ~= 10^-18
+            #
+            Xn = Xfm.reshape((__n,-1)) + EaX @ (vw.reshape((__m,-1)) + EWa)
+        #--------------------------
         else:
             raise ValueError("KorV has to be chosen as either \"KalmanFilterFormula\" or \"Variational\".")
         #