Background Errors
Although several implementations of background error formulation and associated covariance matrix might be available for a given model, it is unlikely an inheritance structure between them will bring much benefit. The interface is described without inheritance but like for any of the Fortran entities, the inheritance structure is not visible from the abstract (non-Fortran) layer and can be used if it proves useful.
The background error can be nonlinear. The linearize method is responsible for generating the covariance matrix object associated to the current error.
type :: bkg_error
contains
procedure :: create ! Constructor
procedure :: delete ! Destructor
procedure :: linearize ! Generate covariance matrix
procedure :: print ! Prints human readable info
end type bkg_error
subroutine create(self, config, geom, bg)
class(bkg_error), intent(inout) :: self
type(config), intent(in) :: config
type(geometry), intent(in) :: geom
type(fields), intent(in) :: bg ! Background state
end subroutine create
subroutine delete(self)
class(bkg_error), intent(inout) :: self
end subroutine delete
function linearize(self, config, fg)
class(b_error_covariance), pointer :: linearize
class(bkg_error), intent(in) :: self
type(config), intent(in) :: config
type(fields), intent(in) :: fg ! First-guess state
end function linearize
subroutine print(self)
class(bkg_error), intent(in) :: self
end subroutine print
Once the Observation Errors have been defined, the Observation Error Covariance matrix is easier to define.
type :: b_error_covariance
contains
procedure :: create ! Constructor
procedure :: delete ! Destructor
procedure :: multiply ! Multiply by B
procedure :: inv_mult ! Multiply by B^{-1}
procedure :: randomize ! Returns random vector scaled by B
procedure :: print ! Prints human readable info
end type b_error_covariance
subroutine create(self, geom, config)
type(b_error_covariance), intent(inout) :: self
type(geometry), intent(in) :: geom
type(config), intent(in) :: config
end subroutine create
subroutine delete(self)
type(b_error_covariance), intent(inout) :: self
end subroutine delete
subroutine multiply(self, dx, dz)
type(b_error_covariance), intent(in) :: self
type(fields), intent(in) :: dx ! input values
type(fields), intent(inout) :: dz ! output values, dz = B * dx
end subroutine multiply
subroutine inv_mult(self, dx, dz)
type(b_error_covariance), intent(in) :: self
type(fields), intent(in) :: dx ! input values
type(fields), intent(inout) :: dz ! output values, dz = B^{-1} * dx
end subroutine inv_mult
subroutine random(self, dx)
type(b_error_covariance), intent(in) :: self
type(fields), intent(inout) :: dx ! scaled random output values
end subroutine random
subroutine print(self)
type(b_error_covariance), intent(in) :: self
end subroutine print
The same interface can also be used to represent any model space error covariance, in particular the model error covariance matrix.
Observation Errors
The abstract base class at the Fortran level is not in principle needed by a system like JEDI which relies on its own mechanism for handling observation types. However, it is convenient for two reasons: it defines an interface that guaranties compatibility for higher level code and it avoids duplication of common code between types.
In principle, the same observation error covariance matrix can be used for several observation types. For example, a diagonal R can be written once and used several times. For that reason, the inheritance structure for R is distinct from that of the observation operators. Handling of observations errors is split in two classes, one for QC and other nonlinear functions, one for the observation error covariance matrix itself.
type, abstract :: obs_error
contains
procedure(obserr_create), deferred :: create ! Constructor
procedure(obserr_delete), deferred :: delete ! Destructor
procedure(obserr_qc), deferred :: quality_control ! Apply QC
procedure(obserr_covar), deferred :: linearize ! Generate covariance matrix
procedure(obserr_print), deferred :: print ! Prints human readable info
end type obs_error
abstract interface
subroutine obserr_create(self, config, obsdb, yobs)
class(obs_error), intent(inout) :: self
type(config), intent(in) :: config
type(obs_space), intent(in) :: obsdb
type(obs_data), intent(in) :: yobs ! Observation values
end subroutine obserr_create
end interface
abstract interface
subroutine obserr_delete(self)
class(obs_error), intent(inout) :: self
end subroutine obserr_delete
end interface
abstract interface
subroutine obserr_qc(self, ???, ???) ! What does QC need?
class(obs_error), intent(in) :: self
end subroutine obserr_qc
end interface
abstract interface
function obserr_linearize(self, config)
class(obs_error_covariance), pointer :: obserr_linearize
class(obs_error), intent(in) :: self
type(config), intent(in) :: config
type(obs_data), intent(in) :: yobs ! Equivalent obs values at first guess
end function obserr_linearize
end interface
abstract interface
subroutine obserr_print(self)
class(obs_error), intent(in) :: self
end subroutine obserr_print
end interface
The interface to the quality control method still needs to be defined. What inputs are needed?
Once the Observation Errors have been defined, the Observation Error Covariance matrix is easier to define.
Note: the observation error covariance matrix interfaces exactly correspond to the background error covariance matrix interfaces where the geometry has been replaced by the obs_space and the fields by obs_vectors.
type :: obs_error_covariance
contains
procedure :: create ! Constructor
procedure :: delete ! Destructor
procedure :: multiply ! Multiply by R
procedure :: inv_mult ! Multiply by R^{-1}
procedure :: randomize ! Returns random vector scaled by R
procedure :: print ! Prints human readable info
end type obs_error_covariance
subroutine create(self, obsdb, config)
type(obs_error_covariance), intent(inout) :: self
type(obs_space), intent(in) :: obsdb
type(config), intent(in) :: config
end subroutine create
subroutine delete(self)
type(obs_error_covariance), intent(inout) :: self
end subroutine delete
subroutine multiply(self, dy, dz)
type(obs_error_covariance), intent(in) :: self
type(obs_vector), intent(in) :: dy ! input values
type(obs_vector), intent(inout) :: dz ! output values, dz = R * dy
end subroutine multiply
subroutine inv_mult(self, dy, dz)
type(obs_error_covariance), intent(in) :: self
type(obs_vector), intent(in) :: dy ! input values
type(obs_vector), intent(inout) :: dz ! output values, dz = R^{-1} * dy
end subroutine inv_mult
subroutine random(self, dy)
type(obs_error_covariance), intent(in) :: self
type(obs_vector), intent(inout) :: dy ! scaled random output values
end subroutine random
subroutine print(self)
type(obs_error_covariance), intent(in) :: self
end subroutine print