Skip to content
Snippets Groups Projects
Commit 84c33e44 authored by Axel Schnitger's avatar Axel Schnitger
Browse files

Merge branch 'release2' into 'master'

Release2

See merge request geoq/gracetools!1
parents 138f3ee4 51ae6426
No related branches found
No related tags found
No related merge requests found
Showing
with 2035 additions and 78 deletions
......@@ -228,3 +228,5 @@ TSWLatexianTemp*
# End of https://www.gitignore.io/api/latex
variational.pdf
input_data/
results/
......@@ -3,7 +3,8 @@
## Overview
GRACETOOLS is a collection of MATLAB scripts that can be used for gravity field
recovery using GRACE type satellite observations.
recovery using GRACE type satellite observations. There are two releases so
far.
**Features**
......@@ -19,10 +20,19 @@ recovery using GRACE type satellite observations.
<!-- vim-markdown-toc GitLab -->
- [Requirements](#requirements)
- [Installation](#installation)
- [Download](#download)
- [Get the Scripts](#get-the-scripts)
- [Get the Data](#get-the-data)
- [Usage](#usage)
- [Release 1](#release-1)
- [Performance](#performance)
- [Reference](#reference)
- [Release 2](#release-2)
- [Performance](#performance-1)
- [Reference](#reference-1)
- [Files](#files)
- [From `function_gfr`](#from-function_gfr)
- [From `function_eba`](#from-function_eba)
- [Contributors](#contributors)
<!-- vim-markdown-toc -->
......@@ -38,7 +48,9 @@ Please reference this article if you use GRACETOOLS:
MATLAB and the [Parallel Computing
Toolbox](https://de.mathworks.com/help/distcomp/).
## Installation
## Download
### Get the Scripts
Download GRACETOOLS as a zip file and extract it somewhere on your computer.
......@@ -50,12 +62,7 @@ Or clone the repository with `git clone`:
$ git clone git@gitlab.aei.uni-hannover.de:geoq/gracetools.git
```
## Usage
The main m-files to run are:
- `gfr_parallel.m`
- `continue_gfr_par_from_iteration.m`
### Get the Data
You need an example dataset to run these scripts. If you're on Linux or MacOS
use the `get_input_data.sh` script to get the dataset:
......@@ -73,8 +80,8 @@ now unnecessary `input_data.zip` file. For completeness here are the terminal
commands:
```
$ mv ~/Downloads/input_data.zip input_data/
$ cd input_data/
$ mv ~/Downloads/input_data.zip path/to/GRACETOOLS/input_data/
$ cd path/to/GRACETOOLS/input_data/
$ unzip input_data.zip
$ rm -f input_data.zip
```
......@@ -83,6 +90,8 @@ The directory structure of `input_data/` should look like this:
```
input_data
├── EGM96.gfc
├── GGM05S.gfc
├── MockData_do10_nod4
│ ├── 2005-05-01
│ │ ├── GNV1B_2005-05-01_A_02.asc
......@@ -100,17 +109,110 @@ input_data
│ ├── GNV1B_2005-05-04_A_02.asc
│ ├── GNV1B_2005-05-04_B_02.asc
│ └── KBR1B_2005-05-04_X_02.asc
├── EGM96.gfc
└── GGM05S.gfc
└── MockData_do20_nod12
├── 2005-05-01
│ ├── GNV1B_2005-05-01_A_02.asc
│ ├── GNV1B_2005-05-01_B_02.asc
│ └── KBR1B_2005-05-01_X_02.asc
├── 2005-05-02
│ ├── GNV1B_2005-05-02_A_02.asc
│ ├── GNV1B_2005-05-02_B_02.asc
│ └── KBR1B_2005-05-02_X_02.asc
├── 2005-05-03
│ ├── GNV1B_2005-05-03_A_02.asc
│ ├── GNV1B_2005-05-03_B_02.asc
│ └── KBR1B_2005-05-03_X_02.asc
├── 2005-05-04
│ ├── GNV1B_2005-05-04_A_02.asc
│ ├── GNV1B_2005-05-04_B_02.asc
│ └── KBR1B_2005-05-04_X_02.asc
├── 2005-05-05
│ ├── GNV1B_2005-05-05_A_02.asc
│ ├── GNV1B_2005-05-05_B_02.asc
│ └── KBR1B_2005-05-05_X_02.asc
├── 2005-05-06
│ ├── GNV1B_2005-05-06_A_02.asc
│ ├── GNV1B_2005-05-06_B_02.asc
│ └── KBR1B_2005-05-06_X_02.asc
├── 2005-05-07
│ ├── GNV1B_2005-05-07_A_02.asc
│ ├── GNV1B_2005-05-07_B_02.asc
│ └── KBR1B_2005-05-07_X_02.asc
├── 2005-05-08
│ ├── GNV1B_2005-05-08_A_02.asc
│ ├── GNV1B_2005-05-08_B_02.asc
│ └── KBR1B_2005-05-08_X_02.asc
├── 2005-05-09
│ ├── GNV1B_2005-05-09_A_02.asc
│ ├── GNV1B_2005-05-09_B_02.asc
│ └── KBR1B_2005-05-09_X_02.asc
├── 2005-05-10
│ ├── GNV1B_2005-05-10_A_02.asc
│ ├── GNV1B_2005-05-10_B_02.asc
│ └── KBR1B_2005-05-10_X_02.asc
├── 2005-05-11
│ ├── GNV1B_2005-05-11_A_02.asc
│ ├── GNV1B_2005-05-11_B_02.asc
│ └── KBR1B_2005-05-11_X_02.asc
├── 2005-05-12
│ ├── GNV1B_2005-05-12_A_02.asc
│ ├── GNV1B_2005-05-12_B_02.asc
│ └── KBR1B_2005-05-12_X_02.asc
└── states0_perfect.mat
```
## Performance
## Usage
### Release 1
The main m-files in the first release (`release1/`) are:
- `gfr_parallel.m`
- `save_vars2continue_itr.m`
- `continue_gfr_par_from_iteration.m`
First run `gfr_parallel.m`. Use `save_vars2continue_itr.m` to save all necessary
variables in the `results/` subdirectory. You can continue the estimation from
the last iteration with `continue_gfr_par_from_iteration.m`.
#### Performance
With an older Intel i5 (4 cores) a test case with degree and order 10 with 4
days of observation, each iteration takes about 10 min.
#### Reference
- Darbeheshti N., Wöske F., Weigelt M., McCullough C., Wu H. (2018) GRACETOOLS - GRACE gravity field recovery tools, Geosciences 2018, 8(9), 350; https://doi.org/10.3390/geosciences8090350.
### Release 2
The main m-files in the second release (`release2/`) are:
- `gfr_eba.m` - GFR with energy balance approach
- `gfr_pos.m` - GFR with variational equations using positions
- `gfr_pos_rrho.m` - GFR with variational equations using positions and range rates
- `gfr_rrho.m` - GFR with variational equations using range rates
- `gfr_rrho_tickonov.m`- GFR with variational equations using range rates and Tickonov regularization
Navigate to the `release2/` subdirectory and run the scripts. Results will be
stored in the `results` subdirectory.
#### Performance
With an older Intel i5 (4 cores) a test case with degree and order 20 with 12
days of observation, each iteration takes about 20 min.
#### Reference
- Darbeheshti N., Wöske F., Weigelt M., Wu H., Mccullough C. (2020) Comparison of Spacewise and Timewise Methods for GRACE Gravity Field Recovery. In: Montillet JP., Bos M. (eds) Geodetic Time Series Analysis in Earth Sciences. Springer Geophysics. Springer, Cham, https://doi.org/10.1007/978-3-030-21718-1_10
- [IUGG Talk Montreal 2019](https://seafile.projekt.uni-hannover.de/f/2668157cf326417485c7/)
## Files
### From `function_gfr`
- `batch_processor_partitioned.m` - batch processing algorithm for GRACE
range-rate observations
- `cs2sc.m`- converts the square containing spherical harmonics coefficients
......@@ -162,6 +264,13 @@ days of observation, each iteration takes about 10min.
- `vec2cs.m`- rearranges a vector shaped set of spherical harmonic coefficients
into cs-format
### From `function_eba`
- `calculatePnm.m` - Calculation of normalized Legendre Functions using stable recursion formulas
- `designmatrixn.m` - Calculation of normalized Legendre Functions using stable recursion formulas
- `potential_EBAs.m` - Calculates the potential along the GRACE simulated orbit
- `sortCoefficients.m` - Sorts spherical harmonic coefficients
## Contributors
- [Neda Darbeheshti](mailto:neda.darbeheshti@aei.mpg.de)
......
function Pnm = calculatePnm(theta, n_max)
%
% Calculation of normalized Legendre Functions using stable recursion
% formulas.
%
% --Input--
% theta Co-Latitude (1x1)
% n_max Maximum degree (1x1)
%
% --Output--
% Pnm Legendre functions (n_max x n_max)
%
% Author: Anne Springer
% Date: 2015-08-24
%
t = cos(theta);
Pnm = zeros(n_max+1, n_max+1);
Pnm(1,1) = 1;
an = sqrt(3);
for n = 1:n_max
if n>1
an = sqrt((2*n+1)/(2*n));
end
% P_{n,n}
Pnm(n+1, n+1) = an * sqrt(1-t^2)*Pnm(n,n);
% P_{n,n-1}
bn = sqrt((2*n + 1)*(2*n - 1)/((n+(n-1))*(n-(n-1))));
Pnm(n+1, n) = bn*Pnm(n,n)*t;
% P_{n,m}
for m = 0:n-2
bnm = sqrt((2*n + 1)*(2*n - 1)/((n+m)*(n-m)));
cnm = sqrt((2*n+1)*(n-m-1)*(n+m-1)/((2*n-3)*(n+m)*(n-m))) ;
Pnm(n+1, m+1) = bnm*t*Pnm(n, m+1) - cnm*Pnm(n-1, m+1);
end
end
\ No newline at end of file
function A = designmatrixn(longitude,latitude,height,n_max,GM,R)
%
% Calculation of normalized Legendre Functions using stable recursion
% formulas.
%
% --Input--
% longitude Longitudes (n x 1) in Radian
% latitudes Latitudes (n x 1) in Radian
% height Heights (n x 1)
% n_max Maximum degree (1 x 1)
% GM Gravitational constant times mass of the Earth
% R Radius of the Earth
%
% --Output--
% A Design matrix (n x n_max)
%
% Author: Anne Springer
% Date: 2015-08-24
%
% Degree and order
idx = tril(ones(n_max+1))~=0;
degree = repmat((0:n_max)',1,n_max+1);
degree = degree(idx);
order = repmat(0:n_max,n_max+1,1);
order = order(idx);
% Design matrix
A = zeros(length(longitude),length(degree)*2-(n_max+1));
for i = 1:length(A)
Pnm = calculatePnm((pi/2-latitude(i)), n_max);
Pnm = Pnm(idx);
factor = GM/R*(R/height(i)).^(degree+1);
cos_ = cos(order*longitude(i));
sin_ = sin(order*longitude(i));
A(i,:) = [factor.*cos_.*Pnm; factor(n_max+2:end).*sin_(n_max+2:end).*Pnm(n_max+2:end)]';
end
function v12sst = potential_EBAs(rho_dot,s_ea,s_eb,we)
% POTENTIAL_EBAS.m calculates the potential along the GRACE simulated orbit.
% rho_dot is the range rate
% s_ea and s_eb are the state vectors, position and velocity in itrf
% we is the mean Earth rotation rate
%
% Written by Neda Darbeheshti, AEI Hannover, 2018-12.
global e12 en er
xdot12=s_eb(:,4:6)-s_ea(:,4:6);
sumxdot=s_eb(:,4:6)+s_ea(:,4:6);
%unit vectors
e12=s_eb(:,1:3)-s_ea(:,1:3);
e12 = bsxfun(@rdivide,e12,sqrt(sum(e12.^2,2)));
en = [s_ea(:,2).*s_eb(:,3)-s_ea(:,3).*s_eb(:,2) s_ea(:,3).*s_eb(:,1)-s_ea(:,1).*s_eb(:,3) s_ea(:,1).*s_eb(:,2)-s_ea(:,2).*s_eb(:,1)];
en = bsxfun(@rdivide,en,sqrt(sum(en.^2,2)));
er = [e12(:,2).*en(:,3)-e12(:,3).*en(:,2) e12(:,3).*en(:,1)-e12(:,1).*en(:,3) e12(:,1).*en(:,2)-e12(:,2).*en(:,1)];
er = bsxfun(@rdivide,er,sqrt(sum(er.^2,2)));
e3=[0 0 1];
% calculate potential along each vector
for i=1:length(rho_dot)
v12sst_rho(i)=.5*rho_dot(i)*e12(i,:)*sumxdot(i,:)';
v12sst_n(i)=.5*en(i,:)*xdot12(i,:)'*en(i,:)*sumxdot(i,:)';
v12sst_r(i)=.5*er(i,:)*xdot12(i,:)'*er(i,:)*sumxdot(i,:)';
v12sst_rota(i)=-we^2/2*(norm(cross(e3,s_eb(i,1:3)))^2-norm(cross(e3,s_ea(i,1:3)))^2);
end
% sum all potentials
v12sst=v12sst_n+v12sst_r+v12sst_rho+v12sst_rota;
end
function [cnm, snm] = sortCoefficients(x, n_max)
%
% SORTCOEFFICIENTS.m sorts spherical harmonic coefficients
%
% --Input--
% x Parameter vector containing the estimated spherical
% harmonic coefficients (n x 1)
% n_max Maximum degree (1x1)
%
% --Output--
% cnm, snm Potential coefficients divided into sine component and
% cosine component
%
% Author: Anne Springer
% Date: 2015-08-24
%
% Degree and order
idx = tril(ones(n_max+1))~=0;
degree = repmat((0:n_max)',1,n_max+1);
degree = degree(idx);
order = repmat(0:n_max,n_max+1,1);
order = order(idx);
% Cosine coefficients
cnm = zeros(n_max+1);
for i = 1:length(degree)
cnm(degree(i)+1, order(i)+1) = x(i);
end
% Sine coefficients
snm = zeros(n_max+1);
for j = 1:length(degree(n_max+2:end))
snm(degree(j+n_max+1)+1, order(j+n_max+1)+1) = x(i+j);
end
end
function C = threeDmulti_rot(A,B,type)
% This function multiplies 3 dimensional rotation matrices in form A(3*3*n)
% with position vectors in form B(n*3). This is mainly used in coordinate
% transformation between intertial and earth-fixed frames.
%
% Input: R = rotation matrices [3x3xN]
% B = vectors to be rotated [Nx3]
% type = 'forward' or 'backward' ('backward' for inverse rotation);
% default is 'forward'
%
% Output: C = rotated vectors [Nx3]
%
% Example: R = RotmatICRF2SF(SCA1B_A(:,2:5));
% v = acc_ICRF;
% --> acc_SF = threeDmulti_rot(R,v);
%
% Written by Majid Naeimi, 7 April 2015, IfE, Hanover, Germany
% Last updated by Henry Wegener, AEI Hannover, 2016-07-08.
if ~( size(A,1) == 3 && size(A,2) == 3 && size(B,2) == 3 )
error('Dimensions of input arguments are incorrect. Rotation matrices (first argument) must be of size 3x3xN \n Input vectors (second argument) must be of size Nx3 !')
elseif ( size(A,3) > 1 && size(B,1) == 1 )
B = repmat(B,size(A,3),1);
elseif ~( size(A,3) == size(B,1) )
error('Length of vector (second argument) must be the same as for the matrices OR it must be 1 !');
end
if ( nargin == 2 )
type = 'forward';
end
Ap = reshape(A,9,[]);
switch type
case 'forward'
C = [Ap(1,:)'.*B(:,1)+Ap(4,:)'.*B(:,2)+Ap(7,:)'.*B(:,3) Ap(2,:)'.*B(:,1)+Ap(5,:)'.*B(:,2)+Ap(8,:)'.*B(:,3) Ap(3,:)'.*B(:,1)+Ap(6,:)'.*B(:,2)+Ap(9,:)'.*B(:,3)];
case 'backward'
C = [Ap(1,:)'.*B(:,1)+Ap(2,:)'.*B(:,2)+Ap(3,:)'.*B(:,3) Ap(4,:)'.*B(:,1)+Ap(5,:)'.*B(:,2)+Ap(6,:)'.*B(:,3) Ap(7,:)'.*B(:,1)+Ap(8,:)'.*B(:,2)+Ap(9,:)'.*B(:,3)];
otherwise
error(['Unknown type: ',type,'. type must be either "forward" (for forward rotation) \n or "backward" (for inverse rotation)!'])
end
end
\ No newline at end of file
function batch_processor_partitioned_pos(Mday,nods,FolderName,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state,timeKBR,obs_gnv,x0x)
% Batch processing algorithm for GRACE using positions observations.
% seperation between local and global parameters, which are estimated for
% different arcs (eg. initial states daily and spherical harmonics
% coefficients for the whole time. Using Partitioned Normal Equations
% based on:
% - Gunter's MSc(2000)thesis, page 27
% - Statistical Orbit Determination (Tapley et al., 2004), page 196-197
%
% Input: Mday = current arc number/index
% FolderName = folder/path where intermediate results are saved
% lmaxcs = order of spherical harmonic coefficients to be estimated
% mKBR = number of observations in each arc
% field = gravity field
% data_plm = Legendre polynomial, see initplm
% GM = GM of gravity field
% ae = Earth radius of gravity field
% lmaxf = parameters of background gravity field
% state = initial states for arc [12x1]
% timeKBR = times of observations
% observation = vector of observations (eg. range rates)
% x0x = state deviation [12x1]
%
% Output: function has no output, output is saved in file for easy
% paralleization
%
% Exampel: see gfr_pos.m
%
% Main functions
% - deriv: calculates all partials
% - hmat: makes observation-state mapping matrices Hxtilde and HcTilde
% Other functions
% - vec2cs: reformatting spherical harmonics coefficients
% - cs2sc: reformatting spherical harmonics coefficients
% - initplm: initialzes Legendre polynomial calculation
%
% Written by Florian Wöske, ZARM Uni Bremen, 2018-12.
% Adapted by Neda Darbeheshti, AEI, 2019-06.
%% set some initial parameters
% Minimum degree and order of coefficients to be estimated
lmincs=2;
noc=lmaxcs^2-lmincs^2+2*lmaxcs+1;%total number of coefficients to be estimated
% Load P0:A priori state variance???covariance matrix
P0x=eye(12);
P0c=eye(noc);
x0c = zeros(noc,1);
% numbers of observations for each time step
no = size(obs_gnv,2)-1; %(3 or 6 positions)
% All parameters mneeded in derivs function are put in a struct, making it
% easy to change or add the parameters of derivs
deriv_params.field = field;
deriv_params.data_plm = data_plm;
deriv_params.GM = GM;
deriv_params.ae = ae;
deriv_params.lmaxf = lmaxf;
deriv_params.lmaxcs = lmaxcs;
deriv_params.noc = noc;
%% set integration parameters
% integration method (1: Runge-Kutta 4, 2: RK DP8, 3: ABM)
% RK4 needs 4 calls of deriv function, medium integration accuracy, DP8
% needs 13 calls of deriv, high accuracy also with bigger step size. ABM
% needs to be initialized with a single step integration method like RK or
% DP, as for all multistep integrators. After initialization it needs just
% 2 calls of DERIV and has a high accuracy. Multistep methods with high
% orders tend to get unstable when not decreasing step sizes.
int_meth = 3;
% id ABM integrator, order of ABM scheme (implemented: 1 to 12)
abm_order = 8;
lengthX0=12*(12+noc)+12;
% Define the state transition matrix:
phibuff = eye(12+noc);% a replacement for phi as a square matrix
phi = reshape(phibuff(1:12,1:end),12,(12+noc));%phi not to be a square matrix to save some space
% Form the extended state vector:
X0 = [state;reshape(phi,numel(phi),1)];
% new
X = X0;
%Eqs. (6.3.22), (6.3.23), and (6.3.25)from Tapley's book
Mxx=eye(12) / P0x;
Mxc=zeros(12,noc);
Mcc=eye(noc) / P0c;
Nx=P0x \ x0x;
Nc=P0c \ x0c;
% alloc. vars.
i_call = 0;
dXdt=zeros(abm_order, lengthX0);
%% The if loop limits saving of'ygnv_save','Hx_save','Hc_save' just for last day
if Mday==nods
ygnv_save = zeros(mKBR,no);
Hx_save = zeros(mKBR,no,12);
Hc_save = zeros(mKBR,no,noc);
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ygnv = obs_gnv(ii,2:end)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde,Y_star_gnv]= hmat_pos(X,noc,no);
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
y= Ygnv - Y_star_gnv;
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*Hx;
Mxc=Mxc + Hx'*Hc;
Mcc=Mcc + Hc'*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*y;
Nc = Nc + Hc'*y;
% Store data:
ygnv_save(ii,:) = y;
Hx_save(ii,:,:)=Hx;
Hc_save(ii,:,:)=Hc;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc','ygnv_save','Hx_save','Hc_save','-v7.3');
else
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ygnv = obs_gnv(ii,2:end)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde,Y_star_gnv]= hmat_pos(X,noc,no);
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
y= Ygnv - Y_star_gnv;
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*Hx;
Mxc=Mxc + Hx'*Hc;
Mcc=Mcc + Hc'*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*y;
Nc = Nc + Hc'*y;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc');
end
function batch_processor_partitioned_pos_rrho(Mday,nods,FolderName,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state,timeKBR,obs_gnv,obs_kbr,WMAT)
% Batch processing algorithm for GRACE using positions and range-rate observations.
% seperation between local and global parameters, which are estimated for
% different arcs (eg. initial states daily and spherical harmonics
% coefficients for the whole time. Using Partitioned Normal Equations
% based on:
% - Gunter's MSc(2000)thesis, page 27
% - Statistical Orbit Determination (Tapley et al., 2004), page 196-197
%
% Input: Mday = current arc number/index
% FolderName = folder/path where intermediate results are saved
% lmaxcs = order of spherical harmonic coefficients to be estimated
% mKBR = number of observations in each arc
% field = gravity field
% data_plm = Legendre polynomial, see initplm
% GM = GM of gravity field
% ae = Earth radius of gravity field
% lmaxf = parameters of background gravity field
% state = initial states for arc [12x1]
% timeKBR = times of observations
% observation = vector of observations (eg. range rates)
% x0x = state deviation [12x1]
%
% Output: function has no output, output is saved in file for easy
% paralleization
%
% Exampel: see gfr_pos_rrho.m
%
% Main functions
% - deriv: calculates all partials
% - hmat: makes observation-state mapping matrices Hxtilde and HcTilde
% Other functions
% - vec2cs: reformatting spherical harmonics coefficients
% - cs2sc: reformatting spherical harmonics coefficients
% - initplm: initialzes Legendre polynomial calculation
%
% Written by Florian Wöske, ZARM Uni Bremen, 2018-12.
% Adapted by Neda Darbeheshti, AEI, 2019-06.
%% set some initial parameters
% Minimum degree and order of coefficients to be estimated
lmincs=2;
noc=lmaxcs^2-lmincs^2+2*lmaxcs+1;%total number of coefficients to be estimated
% numbers of observations for each time step
no = size(obs_gnv,2); %(3 or 6 positions, positios + velocities)
% All parameters mneeded in derivs function are put in a struct, making it
% easy to change or add the parameters of derivs
deriv_params.field = field;
deriv_params.data_plm = data_plm;
deriv_params.GM = GM;
deriv_params.ae = ae;
deriv_params.lmaxf = lmaxf;
deriv_params.lmaxcs = lmaxcs;
deriv_params.noc = noc;
%% set integration parameters
% integration method (1: Runge-Kutta 4, 2: RK DP8, 3: ABM)
% RK4 needs 4 calls of deriv function, medium integration accuracy, DP8
% needs 13 calls of deriv, high accuracy also with bigger step size. ABM
% needs to be initialized with a single step integration method like RK or
% DP, as for all multistep integrators. After initialization it needs just
% 2 calls of DERIV and has a high accuracy. Multistep methods with high
% orders tend to get unstable when not decreasing step sizes.
int_meth = 3;
% id ABM integrator, order of ABM scheme (implemented: 1 to 12)
abm_order = 8;
lengthX0=12*(12+noc)+12;
% Define the state transition matrix:
phibuff = eye(12+noc);% a replacement for phi as a square matrix
phi = reshape(phibuff(1:12,1:end),12,(12+noc));%phi not to be a square matrix to save some space
% Form the extended state vector:
X0 = [state;reshape(phi,numel(phi),1)];
% new
X = X0;
Mxx=zeros(12);
Mxc = zeros(12,noc);
Mcc = zeros(noc);
Nx = zeros(12,1);
Nc = zeros(noc,1);
% alloc. vars.
i_call = 0;
dXdt=zeros(abm_order, lengthX0);
%% The if loop limits saving of'ygnv_save','ykbr_save','Hx_save','Hc_save' just for last day
if Mday==nods
ykbr_save = zeros(mKBR,1);
ygnv_save = zeros(mKBR,no);
Hx_save = zeros(mKBR,no+1,12);
Hc_save = zeros(mKBR,no+1,noc);
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ykbr = obs_kbr(ii,:)';
Ygnv = obs_gnv(ii,:)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde_kbr,Y_star_kbr]= hmat(X,noc);
% Get the Htilde Matrix:
[Htilde_gnv,Y_star_gnv]= hmat_pos(X,noc,no);
%builld Htilde
Htilde=[Htilde_kbr; Htilde_gnv];
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
ykbr = Ykbr - Y_star_kbr(2,:);
ygnv = Ygnv - Y_star_gnv;
%builld y
y=[ykbr;ygnv];
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*WMAT*Hx;
Mxc=Mxc + Hx'*WMAT*Hc;
Mcc=Mcc + Hc'*WMAT*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*WMAT*y;
Nc = Nc + Hc'*WMAT*y;
% Store data:
ykbr_save(ii) = ykbr;
ygnv_save(ii,:) = ygnv;
Hx_save(ii,:,:)=Hx;
Hc_save(ii,:,:)=Hc;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc','ykbr_save','ygnv_save','Hx_save','Hc_save','-v7.3');
else
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ykbr = obs_kbr(ii,:)';
Ygnv = obs_gnv(ii,:)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde_kbr,Y_star_kbr]= hmat(X,noc);
% Get the Htilde Matrix:
[Htilde_gnv,Y_star_gnv]= hmat_pos(X,noc,no);
%builld Htilde
Htilde=[Htilde_kbr; Htilde_gnv];
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
ykbr = Ykbr - Y_star_kbr(2,:);
ygnv = Ygnv - Y_star_gnv;
%builld y
y=[ykbr;ygnv];
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*WMAT*Hx;
Mxc=Mxc + Hx'*WMAT*Hc;
Mcc=Mcc + Hc'*WMAT*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*WMAT*y;
Nc = Nc + Hc'*WMAT*y;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc');
end
function batch_processor_partitioned_rrho(Mday,nods,FolderName,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state,timeKBR,obs_kbr,x0x)
% Batch processing algorithm for GRACE using range-rate observations.
% seperation between local and global parameters, which are estimated for
% different arcs (eg. initial states daily and spherical harmonics
% coefficients for the whole time. Using Partitioned Normal Equations
% based on:
% - Gunter's MSc(2000)thesis, page 27
% - Statistical Orbit Determination (Tapley et al., 2004), page 196-197
%
% Input: Mday = current arc number/index
% FolderName = folder/path where intermediate results are saved
% lmaxcs = order of spherical harmonic coefficients to be estimated
% mKBR = number of observations in each arc
% field = gravity field
% data_plm = Legendre polynomial, see initplm
% GM = GM of gravity field
% ae = Earth radius of gravity field
% lmaxf = parameters of background gravity field
% state = initial states for arc [12x1]
% timeKBR = times of observations
% observation = vector of observations (eg. range rates)
% x0x = state deviation [12x1]
%
% Output: function has no output, output is saved in file for easy
% paralleization
%
% Exampel: see gfr_rrho.m
%
% Main functions
% - deriv: calculates all partials
% - hmat: makes observation-state mapping matrices Hxtilde and HcTilde
% Other functions
% - vec2cs: reformatting spherical harmonics coefficients
% - cs2sc: reformatting spherical harmonics coefficients
% - initplm: initialzes Legendre polynomial calculation
%
% Written by Florian Wöske, ZARM Uni Bremen, 2018-12.
% Adapted by Neda Darbeheshti, AEI, 2019-06.
%% set some initial parameters
% Minimum degree and order of coefficients to be estimated
lmincs=2;
noc=lmaxcs^2-lmincs^2+2*lmaxcs+1;%total number of coefficients to be estimated
% Load P0:A priori state variance covariance matrix
P0x=eye(12);
P0c=eye(noc);
x0c = zeros(noc,1);
% All parameters mneeded in derivs function are put in a struct, making it
% easy to change or add the parameters of derivs
deriv_params.field = field;
deriv_params.data_plm = data_plm;
deriv_params.GM = GM;
deriv_params.ae = ae;
deriv_params.lmaxf = lmaxf;
deriv_params.lmaxcs = lmaxcs;
deriv_params.noc = noc;
%% set integration parameters
% integration method (1: Runge-Kutta 4, 2: RK DP8, 3: ABM)
% RK4 needs 4 calls of deriv function, medium integration accuracy, DP8
% needs 13 calls of deriv, high accuracy also with bigger step size. ABM
% needs to be initialized with a single step integration method like RK or
% DP, as for all multistep integrators. After initialization it needs just
% 2 calls of DERIV and has a high accuracy. Multistep methods with high
% orders tend to get unstable when not decreasing step sizes.
int_meth = 3;
% id ABM integrator, order of ABM scheme (implemented: 1 to 12)
abm_order = 8;
lengthX0=12*(12+noc)+12;
% Define the state transition matrix:
phibuff = eye(12+noc);% a replacement for phi as a square matrix
phi = reshape(phibuff(1:12,1:end),12,(12+noc));%phi not to be a square matrix to save some space
% Form the extended state vector:
X0 = [state;reshape(phi,numel(phi),1)];
% new
X = X0;
%Eqs. (6.3.22), (6.3.23), and (6.3.25)from Tapley's book
Mxx=eye(12) / P0x;
Mxc=zeros(12,noc);
Mcc=eye(noc) / P0c;
Nx=P0x \ x0x;
Nc=P0c \ x0c;
% alloc. vars.
i_call = 0;
dXdt=zeros(abm_order, lengthX0);
%% The if loop limits saving of'ykbr_save','Hx_save','Hc_save' just for last day
if Mday==nods
ykbr_save = zeros(mKBR,1);
Hx_save = zeros(mKBR,12);
Hc_save = zeros(mKBR,noc);
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ykbr = obs_kbr(ii,:)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde,Y_star_kbr]= hmat(X,noc);
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
y= Ykbr - Y_star_kbr(2,:);
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*Hx;
Mxc=Mxc + Hx'*Hc;
Mcc=Mcc + Hc'*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*y;
Nc = Nc + Hc'*y;
% Store data:
ykbr_save(ii) = y;
Hx_save(ii,:,:)=Hx;
Hc_save(ii,:,:)=Hc;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc','ykbr_save','Hx_save','Hc_save','-v7.3');
else
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ykbr = obs_kbr(ii,:)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde,Y_star_kbr]= hmat(X,noc);
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
y = Ykbr - Y_star_kbr(2,:);
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*Hx;
Mxc=Mxc + Hx'*Hc;
Mcc=Mcc + Hc'*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*y;
Nc = Nc + Hc'*y;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc');
end
\ No newline at end of file
function batch_processor_partitioned_rrho_tickonov(Mday,nods,FolderName,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state,timeKBR,obs_kbr,x0x)
% Batch processing algorithm for GRACE using range-rate observations with Tickonov regularization.
% seperation between local and global parameters, which are estimated for
% different arcs (eg. initial states daily and spherical harmonics
% coefficients for the whole time. Using Partitioned Normal Equations
% based on:
% - Gunter's MSc(2000)thesis, page 27
% - Statistical Orbit Determination (Tapley et al., 2004), page 196-197
%
% Input: Mday = current arc number/index
% FolderName = folder/path where intermediate results are saved
% lmaxcs = order of spherical harmonic coefficients to be estimated
% mKBR = number of observations in each arc
% field = gravity field
% data_plm = Legendre polynomial, see initplm
% GM = GM of gravity field
% ae = Earth radius of gravity field
% lmaxf = parameters of background gravity field
% state = initial states for arc [12x1]
% timeKBR = times of observations
% observation = vector of observations (eg. range rates)
% x0x = state deviation [12x1]
%
% Output: function has no output, output is saved in file for easy
% paralleization
%
% Exampel: see gfr_rrho_tickonov.m
%
% Main functions
% - deriv: calculates all partials
% - hmat: makes observation-state mapping matrices Hxtilde and HcTilde
% Other functions
% - vec2cs: reformatting spherical harmonics coefficients
% - cs2sc: reformatting spherical harmonics coefficients
% - initplm: initialzes Legendre polynomial calculation
%
% Written by Florian Wöske, ZARM Uni Bremen, 2018-12.
% Adapted by Neda Darbeheshti, AEI, 2019-06.
%% set some initial parameters
% Minimum degree and order of coefficients to be estimated
lmincs=2;
noc=lmaxcs^2-lmincs^2+2*lmaxcs+1;%total number of coefficients to be estimated
% Load P0:A priori state variance covariance matrix
P0x=eye(12);
P0c=eye(noc);
x0c = zeros(noc,1);
% All parameters mneeded in derivs function are put in a struct, making it
% easy to change or add the parameters of derivs
deriv_params.field = field;
deriv_params.data_plm = data_plm;
deriv_params.GM = GM;
deriv_params.ae = ae;
deriv_params.lmaxf = lmaxf;
deriv_params.lmaxcs = lmaxcs;
deriv_params.noc = noc;
%% set integration parameters
% integration method (1: Runge-Kutta 4, 2: RK DP8, 3: ABM)
% RK4 needs 4 calls of deriv function, medium integration accuracy, DP8
% needs 13 calls of deriv, high accuracy also with bigger step size. ABM
% needs to be initialized with a single step integration method like RK or
% DP, as for all multistep integrators. After initialization it needs just
% 2 calls of DERIV and has a high accuracy. Multistep methods with high
% orders tend to get unstable when not decreasing step sizes.
int_meth = 3;
% id ABM integrator, order of ABM scheme (implemented: 1 to 12)
abm_order = 8;
lengthX0=12*(12+noc)+12;
% Define the state transition matrix:
phibuff = eye(12+noc);% a replacement for phi as a square matrix
phi = reshape(phibuff(1:12,1:end),12,(12+noc));%phi not to be a square matrix to save some space
% Form the extended state vector:
X0 = [state;reshape(phi,numel(phi),1)];
% new
X = X0;
%new Tickonov regularisation by Florian
x_d = 1e-6;
v_d = 0.1;
Mxx = diag([x_d x_d x_d v_d v_d v_d x_d x_d x_d v_d v_d v_d]);
Mxc = zeros(12,noc);
Mcc = zeros(noc);
Nx = zeros(12,1);
Nc = zeros(noc,1);
% alloc. vars.
i_call = 0;
dXdt=zeros(abm_order, lengthX0);
%% The if loop limits saving of'ykbr_save','Hx_save','Hc_save' just for last day
if Mday==nods
ykbr_save = zeros(mKBR,1);
Hx_save = zeros(mKBR,12);
Hc_save = zeros(mKBR,noc);
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ykbr = obs_kbr(ii,:)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde,Y_star_kbr]= hmat(X,noc);
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
y= Ykbr - Y_star_kbr(2,:);
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*Hx;
Mxc=Mxc + Hx'*Hc;
Mcc=Mcc + Hc'*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*y;
Nc = Nc + Hc'*y;
% Store data:
ykbr_save(ii) = y;
Hx_save(ii,:,:)=Hx;
Hc_save(ii,:,:)=Hc;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc','ykbr_save','Hx_save','Hc_save','-v7.3');
else
%Run through each observation:
for ii = 1:mKBR
% Read observation:
Ykbr = obs_kbr(ii,:)';
if ii > 1
i_call = i_call+1; %count number of odeint evaluations
[X, dXdt] = odeint(@deriv, X, dXdt, timeKBR(ii-1), 5, i_call, int_meth, abm_order, deriv_params);
end
% Extract the state transition matrix:
phi = reshape(X(12+1:end), 12, 12+noc);
[a,b] = size(phi);
phibuff(1:a,1:b) = phi;
% Get the Htilde Matrix:
[Htilde,Y_star_kbr]= hmat(X,noc);
% Time update:
H = Htilde*phibuff;
Hx = H(:,1:12);
Hc = H(:,13:end);
% Calculate the observation deviation:
y = Ykbr - Y_star_kbr(2,:);
% accumulate Lambda:
%L = L + H'*WMAT*H;
Mxx=Mxx + Hx'*Hx;
Mxc=Mxc + Hx'*Hc;
Mcc=Mcc + Hc'*Hc;
% accumulate N:
%N = N + H'*WMAT*y;
Nx = Nx + Hx'*y;
Nc = Nc + Hc'*y;
end
invMxx=Mxx\eye(size(Mxx));
% save in a file
FileName= ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File= fullfile(FolderName, FileName);
save(File,'invMxx','Mxc','Mcc','Nx','Nc');
end
\ No newline at end of file
function [Hi_tilda, Y_star] = hmat_pos(X0,NOCs,no)
% This function makes the Htilde matrix.
% References:-McCullough CM (2017) Gravity Field Estimation for Next Generation Satellite
% Missions, page 97, equation (4.4)
% Liu(2008), page 28, equation (2.51)
% -Statistical Orbit Determination (Tapley et al., 2004)
%
% Input: X0 = state vector including [RA; RdotA; PHI]
% NOCs = total number of coefficients to be estimated
% no = number of observations:3 (for positions) or 6 for (positios + velocities)
%
% Outputs: Hi_tilda = [dRA/dRA; dRA/dRdotA; dRA/dRB; dRA/dRdotB; dRA/dKlm]
%
%
% Written by Florian Wöske, ZARM Uni Bremen,2018-11
%% calculate gnv partials w.r.t SHC
% Extract the current state transition matrix:
phi = reshape(X0(12+1:end), 12, 12+NOCs);
% Extract the partials from the current state transition matrix:
% if no == 3 always positions
dr1_dklm=phi(1:3,13:end);
if no == 6
dr2_dklm=phi(7:9,13:end);
end
I = eye(3,3);
Z = zeros(3,3);
% fill Hi_tilda matrix
if no == 3
Hi_tilda=[I, Z, Z, Z, dr1_dklm];
% observation is directly x,y,z
Y_star = X0(1:3);
elseif no == 6
Hi_tilda=[I, Z, Z, Z, dr1_dklm; Z, Z, I, Z, dr2_dklm];
% observation is directly x,y,z
Y_star =[X0(1:3); X0(7:9)];
end
end
%% Save all important variables of a gravity estimation
% this can be used to save all important results, as well as to continue
% the estimation from the last iteration by eg. using
% continue_gfr_par_from_iteration.m .
% All variable are saved in one .mat file, and can be directly loaded in
% continue_gfr_par_from_iteration.m.
%%
% Filename and path of file to save
FileName= ['results/','GFR_itr_',num2str(ItrNo_max), '_do_', num2str(lmaxcs), '_nods_', num2str(nods), '_','tno_', num2str(tno),'_', datestr(now, 'dd-mmm-yyyy'),'.mat'];
% save all necessary variables in one file
save(FileName,'xhat_save','chat_save','eps_save','chat_dv_save','dv_save','state0','x0x','field', 'field_cs', 'field_vec0', 'mKBR', 'GM', 'ae', 't0', 'nods', 'lmaxcs', 'lmaxf', 'data_folder', 'state00', 't_itr_nod','tno');
% actual time
c = clock;
str_display_out = ['results saved as: ', FileName,', Time: ',num2str(c(1)),'-',num2str(c(2)),'-',num2str(c(3)),', ',num2str(c(4)),':',num2str(c(5)),':',num2str(c(6)) ];
disp(str_display_out);
#!/bin/bash
#
# This script downloads the input data. You need wget und unzip to run it.
#
# ./get_input_data.sh
#
URL="https://seafile.projekt.uni-hannover.de/f/3ee8fef6c6cb485489b4/?dl=1"
INPUT_DATA=input_data.zip
downloadData(){
download_data(){
echo "Downloading data from $URL..."
wget --content-disposition "url?raw=1" -U mozilla "$URL" -O $INPUT_DATA
echo "Done."
}
setUp(){
set_up(){
echo "Start extracting data file..."
unzip $INPUT_DATA -d input_data/
echo "Done."
......@@ -19,7 +23,7 @@ setUp(){
echo "Done."
}
cleanUp(){
clean_up(){
echo "Removing subdirectories from input directory."
rm -rf input_data/*
echo "Done."
......@@ -28,7 +32,7 @@ cleanUp(){
echo "Done."
}
getData(){
get_data(){
if [[ -d input_data/ ]]; then
echo "Directory 'input_data/' already exists."
if [[ -f input_data/EGM96.gfc ]]; then
......@@ -36,9 +40,9 @@ getData(){
read -r -p "Cleanup and download again? [y/N]" response
case $response in
[yY][eE][sS]|[yY])
cleanUp
downloadData
setUp
clean_up
download_data
set_up
;;
*)
echo "Aborting."
......@@ -46,18 +50,17 @@ getData(){
;;
esac
else
downloadData
setUp
download_data
set_up
fi
else
downloadData
setUp
download_data
set_up
fi
}
main(){
getData
get_data
}
main
......@@ -6,7 +6,6 @@
%
% Written by Florian Wöske, ZARM Uni Bremen, 2018-07
%%
% variables that are continued, and thus need to be known:
% xhat_save (12, nods, ItrNo_max+1)
......@@ -27,31 +26,32 @@
% additional needed variables:
% mKBR, GM, ae, t0, nods, lmaxcs, lmaxf
% filename of file with saved variables:
FileName = 'GFR_Iteration_12_do_10_nods_4_2005-05-04_011.mat';
% Result file from gfr_parallel.m:
GFR_Iteration_Result = 'results/GFR_Iteration_12_do_10_nods_4_2005-05-04_011.mat';
%% variable inputs
% add folder with all functions
FolderName = pwd;
addpath(genpath(FolderName));
Release1_Path = pwd;
addpath(genpath(Release1_Path));
% folder to save intermediate results
mkdir('results/OutputArcParall');
mkdir('results/OutputNormalEqu');
% add folder name containing functions and input data (observations, ref.
% field, initial values...)
Input_Data_Path = fullfile(Release1_Path, '/../input_data');
addpath(genpath(Input_Data_Path));
% Define the whole number of iterations for batch processor (previous + new
% iterations)
ItrNo_max = 12;
% add folder name containing functions and input data (observations, ref.
% field, initial values...)
DataFolder='input_data';
addpath(genpath(DataFolder));
%% load data from previous iteration
% load data
load(FileName);
load(GFR_Iteration_Result);
% last iteration:
itr_prev = size(xhat_save,3)-1;
......@@ -68,7 +68,6 @@ n_back= ((lmaxf+1)^2 + lmaxf+1)/2;
ggm05s = importGravityField('GGM05S.gfc');
ggm05s = ggm05s(1:n_back,:); % cut to desired length
% extend variables for additional iterations:
xhat_save_prev = xhat_save;
chat_save_prev = chat_save;
......@@ -111,7 +110,7 @@ for Mday = 1:nods
% load KBR data
data_KBR = ['KBR1B_', date, '_X_02.asc'];
data_file = fullfile(data_folder, date, data_KBR);
data_file = fullfile(Input_Observation_Path, date, data_KBR);
KBRL1Bi = readKBR(data_file);
KBRL1B(:,:,Mday) = KBRL1Bi(1:mKBR,1:4);
......@@ -119,13 +118,12 @@ end
%% iteration loop
for ItrNo = (itr_prev+1):ItrNo_max
% batch over all days
parfor Mday = 1:nods
tic
batch_processor_partitioned(Mday,FolderName,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),KBRL1B(:,1,Mday),KBRL1B(:,3,Mday),x0x(:,Mday))
batch_processor_partitioned(Mday,Release1_Path,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),KBRL1B(:,1,Mday),KBRL1B(:,3,Mday),x0x(:,Mday))
toc
end
......@@ -144,7 +142,7 @@ for ItrNo = (itr_prev+1):ItrNo_max
irhodot_deviation = zeros(mKBR,nods);
for Mday = 1:nods
FileName = ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File = fullfile(FolderName,'results/OutputArcParall', FileName);
File = fullfile(Release1_Path,'results/OutputArcParall', FileName);
arcstru=load(File);
invMxx(:,:,Mday) = arcstru.invMxx;
iMxc(:,:,Mday) = arcstru.Mxc;
......@@ -215,7 +213,7 @@ for ItrNo = (itr_prev+1):ItrNo_max
% % save final monthly gravity solution in a file
% FileName= ['gfr_NODs',num2str(nods,'%.2d'),'_DO',num2str(lmaxcs,'%.2d'),'_ItrNo',num2str(ItrNo,'%.2d'),'.gfc'];
% File = fullfile(FolderName,'results/OutputNormalEqu', FileName);
% File = fullfile(Release1_Path,'results/OutputNormalEqu', FileName);
% fileID = fopen(File,'w');
% for i=1:length(ordering2)
% fprintf(fileID,'%4i %4i %17.16e %17.16e\n',ordering2(i,:));
......
......@@ -18,13 +18,22 @@ format longg;
%% variable inputs
% add folder with all functions
FolderName = pwd;
addpath(genpath(FolderName));
Release1_Path = pwd;
addpath(genpath(Release1_Path));
% EBA_Path = fullfile(Release1_Path,'/../function_eba/');
% addpath(genpath(EBA_Path));
GFR_Path = fullfile(Release1_Path,'/../function_gfr/');
addpath(genpath(GFR_Path));
% folder to save intermediate results
mkdir('results/OutputArcParall');
mkdir('results/OutputNormalEqu');
% folder where observation data are stored
Input_Observation_Path = fullfile(Release1_Path,'/../input_data','MockData_do10_nod4');
addpath(genpath(Input_Observation_Path));
% Define the number of iterations for batch processor,
ItrNo_max = 5;
......@@ -37,10 +46,6 @@ lmaxf = 10;
% number of days
nods = 4;
% folder where observation data are stored
data_folder = fullfile(FolderName,'input_data','MockData_do10_nod4');
addpath(genpath(data_folder));
% number of observations in each arc (one day, 17280 is the standard)
mKBR = 17280;
......@@ -55,14 +60,14 @@ GM = 0.3986004415E+15;
ae = 0.6378136300E+07;
% reference for comparison
ggm05s = readGFC('GGM05S.gfc');
ggm05s = readGFC('../input_data/GGM05S.gfc');
ggm05s = ggm05s(1:n_back,:); % cut to desired length
ggm05s_cs = vec2cs([ggm05s(:,1) ggm05s(:,2)]',ggm05s(:,3),ggm05s(:,4));
% d_vec_i = ggm05s(:,3:4)-gravityf(:,3:4);
% d_vec_i = [ggm05s(:,1:2) d_vec_i];
% Load a-priori/ reference gravity field
egm96 = readGFC('EGM96.gfc');
egm96 = readGFC('../input_data/EGM96.gfc');
egm96 = egm96(1:n_back,:); % cut to desired length
egm96_cs = vec2cs([egm96(:,1) egm96(:,2)]',egm96(:,3),egm96(:,4));
......@@ -101,22 +106,21 @@ for Mday = 1:nods
% load KBR data
data_KBR = ['KBR1B_', date, '_X_02.asc'];
data_file = fullfile(data_folder, date, data_KBR);
data_file = fullfile(Input_Observation_Path, date, data_KBR);
KBRL1Bi = readKBR(data_file);
KBRL1B(:,:,Mday) = KBRL1Bi(1:mKBR,1:4);
% load GNV data GRACE A
data_GNV = ['GNV1B_', date, '_A_02.asc'];
data_file = fullfile(data_folder, date, data_GNV);
data_file = fullfile(Input_Observation_Path, date, data_GNV);
GNVi = readGNV(data_file);
state0(1:6,Mday) = GNVi(1,2:7);
% load GNV data GRACE B
data_GNV = ['GNV1B_', date, '_B_02.asc'];
data_file = fullfile(data_folder, date, data_GNV);
data_file = fullfile(Input_Observation_Path, date, data_GNV);
GNVi = readGNV(data_file);
state0(7:12,Mday) = GNVi(1,2:7);
end
% save initial state vector for comparisons
......@@ -140,7 +144,7 @@ for ItrNo = 0:ItrNo_max
% batch over all days
parfor Mday = 1:nods
tic
batch_processor_partitioned(Mday,FolderName,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),KBRL1B(:,1,Mday),KBRL1B(:,3,Mday),x0x(:,Mday))
batch_processor_partitioned(Mday,Release1_Path,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),KBRL1B(:,1,Mday),KBRL1B(:,3,Mday),x0x(:,Mday))
toc
end
......@@ -159,7 +163,7 @@ for ItrNo = 0:ItrNo_max
irhodot_deviation = zeros(mKBR,nods);
for Mday = 1:nods
FileName = ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File = fullfile(FolderName,'results/OutputArcParall', FileName);
File = fullfile(Release1_Path,'results/OutputArcParall', FileName);
arcstru=load(File);
invMxx(:,:,Mday) = arcstru.invMxx;
iMxc(:,:,Mday) = arcstru.Mxc;
......@@ -200,8 +204,6 @@ for ItrNo = 0:ItrNo_max
% title(['Range-rate residuals, Itr',num2str(ItrNo,'%.2d'),',Day',num2str(Mday,'%.2d')])
end
% save xhat and chat of iterations
xhat_save(:,:,ItrNo+1) = xhat;
chat_save(:,ItrNo+1) = chat;
......@@ -232,7 +234,7 @@ for ItrNo = 0:ItrNo_max
% % save final monthly gravity solution in a file
% FileName= ['gfr_NODs',num2str(nods,'%.2d'),'_DO',num2str(lmaxcs,'%.2d'),'_ItrNo',num2str(ItrNo,'%.2d'),'.gfc'];
% File = fullfile(FolderName,'results/OutputNormalEqu', FileName);
% File = fullfile(Release1_Path,'results/OutputNormalEqu', FileName);
% fileID = fopen(File,'w');
% for i=1:length(ordering2)
% fprintf(fileID,'%4i %4i %17.16e %17.16e\n',ordering2(i,:));
......@@ -258,7 +260,6 @@ for ItrNo = 0:ItrNo_max
dv_save(ItrNo+1,:) = dv_geoidn_no_plot(d_vec,lmaxcs);
fprintf('done with iteration %d \n', ItrNo)
end
% plot chat from all iterations:
......@@ -267,6 +268,7 @@ for i = 1:ItrNo_max+1
semilogy(2:lmaxcs,chat_dv_save(i,:),'.-','LineWidth',2,'MarkerSize',20);
hold on
end
fs = 12;
set(gcf,'PaperPositionMode','auto')
set(gca,'FontSize',fs);
......@@ -291,6 +293,7 @@ legend('ggm05s', 'estimated field', 'ggm05 - estimated field')
% plot gravity field error from each iteration additional to initial fields and
% initial error
figure;
dv_geoidn(ggm05s,lmaxcs);
hold on
......
......@@ -6,7 +6,7 @@
%%
% Filename and path of file to save
FileName= ['GFR_Iteration_',num2str(ItrNo_max), '_do_', num2str(lmaxcs), '_nods_', num2str(nods), '_', date, '_011.mat'];
FileName= ['results/','GFR_Iteration_',num2str(ItrNo_max), '_do_', num2str(lmaxcs), '_nods_', num2str(nods), '_', date, '_011.mat'];
% save all necessary variables in one file
save(FileName,'xhat_save','chat_save','eps_save','chat_dv_save','dv_save','state0','x0x','field', 'field_cs', 'err_vec', 'field_vec0', 'mKBR', 'GM', 'ae', 't0', 'nods', 'lmaxcs', 'lmaxf', 'data_folder','state00');
save(FileName,'xhat_save','chat_save','eps_save','chat_dv_save','dv_save','state0','x0x','field', 'field_cs', 'err_vec', 'field_vec0', 'mKBR', 'GM', 'ae', 't0', 'nods', 'lmaxcs', 'lmaxf', 'Input_Observation_Path','state00');
%% GRACE gravity field recovery (GFR) using Energy Balance Approach (EBA)
% This is the main m-file preforming the gravity field estimation.
% All necessary parameters and data are specified in the following.
%
% Written by Neda Darbeheshti, AEI, 2019-06.
clear all
format longg;
%% variable inputs
global e12 en er
% add folder with all functions
Release2_Path = pwd;
addpath(genpath(Release2_Path));
EBA_Path = fullfile(Release2_Path,'/../function_eba/');
addpath(genpath(EBA_Path));
GFR_Path = fullfile(Release2_Path,'/../function_gfr/');
addpath(genpath(GFR_Path));
% folder where observation data are stored
% Use twelve days of data
Input_Observation_Path = fullfile(Release2_Path,'/../input_data','MockData_do20_nod12');
% Use four days of data (optional)
% Input_Observation_Path = fullfile(Release2_Path,'/../input_data','MockData_do10_nod4');
addpath(genpath(Input_Observation_Path));
% order of spherical harmonic coefficients to be estimated
n_max = 20;
% number of days
nod = 12;
% number of observations in each arc (one day, 17280 is the standard)
mKBR = 17280;
%% fixed inputs
% GM and Earth radius of gravity field
a = 6378136.3; %m
GM = 3.9860044150e+14;
we0=7.29211514670698*10^(-5); % rad/s
% size of gravity fields in vec format
length_N=(n_max/2+1)*(n_max+1)*2-(n_max+1);
% initialize for normal equations
N = zeros(length_N+1,length_N+1);
n0 = zeros(length_N+1,1);
% initialze one column for energy constant
A0 = ones(3600*24/5,1);
%% load observations data for all days from files
t0 = [2005 05 01 0 0 2];
t0i = t0;
tic
figure
for day=1:nod
if day >1
t0i(3)=t0i(3)+1;
end
date = time2str(t0i);
% load GNV data GRACE A
data_GNV = ['GNV1B_', date, '_A_02.asc'];
data_file = fullfile(Input_Observation_Path, date, data_GNV);
GNVA = readGNV(data_file);
% load GNV data GRACE B
data_GNV = ['GNV1B_', date, '_B_02.asc'];
data_file = fullfile(Input_Observation_Path, date, data_GNV);
GNVB = readGNV(data_file);
% load KBR data
data_KBR = ['KBR1B_', date, '_X_02.asc'];
data_file = fullfile(Input_Observation_Path, date, data_KBR);
KBRB = readKBR(data_file);
% transformation to the Earth_fixed frame
RotMat= Ri2e(GNVA(:,1));
RotMat_dot= Ri2e_dot(GNVA(:,1));
rA_e = threeDmulti_rot(RotMat,GNVA(:,2:4),'forward');
vA_e = threeDmulti_rot(RotMat,GNVA(:,5:7),'forward')+threeDmulti_rot(RotMat_dot,GNVA(:,2:4),'forward');
rB_e = threeDmulti_rot(RotMat,GNVB(:,2:4),'forward');
vB_e = threeDmulti_rot(RotMat,GNVB(:,5:7),'forward')+threeDmulti_rot(RotMat_dot,GNVB(:,2:4),'forward');
% check if the transformation is correct
plot3(vA_e(:,1),vA_e(:,2),vA_e(:,3))
hold on
% state vector
sa = [rA_e vA_e];
sb = [rB_e vB_e];
% calculate potential observable
v12sst0g = potential_EBAs(KBRB(:,3),sa,sb,we0);
[lon1, lat1, h1] = cart2sph(sa(:,1),sa(:,2),sa(:,3));
[lon2, lat2, h2] = cart2sph(sb(:,1),sb(:,2),sb(:,3));
%% Computation of design matrix A
A2g = designmatrixn(lon2,lat2,h2,n_max,GM,a);
A1g = designmatrixn(lon1,lat1,h1,n_max,GM,a);
A = A2g-A1g;
A = [A, A0];
% Update N:normal equation matrix
N = N + A'*A;
% Update n0:normal equation vector
n0 = n0+ A'*v12sst0g';
fprintf('done with day %d \n', day)
end
%% Cholesky decomposition
L = chol(N, 'lower');
z0 = L\n0;
x0 = L'\z0;
%% estimate residuals
yhat = A*x0;
eps = v12sst0g'-yhat;
toc
%% writing degree variances
[cnm, snm] = sortCoefficients(x0,n_max);
kk = 0;
for i=1:length(cnm)
for j=1:length(snm)
if j<=i
kk=kk+1;
xegm(kk,1)=i-1;
xegm(kk,2)=j-1;
xegm(kk,3)=cnm(i,j);
xegm(kk,4)=snm(i,j);
end
end
end
%% save results in a file
FileName=[Release2_Path,'/results/EBA','_do_', num2str(n_max), '_nods_', num2str(nod),'_',datestr(now, 'dd-mmm-yyyy'),'.mat'];
save(FileName,'xegm','eps','GM','a','n_max','e12', 'en', 'er','rA_e');
%% GRACE gravity field recovery (GFR) using positions
% This is the main m-file preforming the gravity field estimation. It is
% optimised for parallel computing using local and global parameters for
% different arcs. All necessary parameters and data are specified in the
% following. You have to set a number of iterations you want to perform.
% save_vars_for_plotting.m saves all the necessary variables for plotting.
%
% Written by Florian Wöske, ZARM Uni Bremen, 2018-12.
% Adapted by Neda Darbeheshti, AEI, 2019-06.
clear all
% close all;
% clc;
format longg;
nods = 1;
% check if Matlab toolbox licence is available, if not end job
[status,errmsg] = license('checkout', 'Distrib_Computing_Toolbox');
if status ~= 0 || nods == 1
%% variable inputs
% add folder name containing functions and input data (observations, ref.
% field, initial values...)
Release2_Path = pwd;
addpath(genpath(Release2_Path));
EBA_Path = fullfile(Release2_Path,'/../function_eba/');
addpath(genpath(EBA_Path));
GFR_Path = fullfile(Release2_Path,'/../function_gfr/');
addpath(genpath(GFR_Path));
Input_Data_Path = [Release2_Path,'/../input_data'];
addpath(genpath(Input_Data_Path));
% folder where observation data are stored
Input_Observation_Path = [Input_Data_Path, '/MockData_do20_nod12'];
% Define the number of iterations for batch processor,
ItrNo_max = 1;
% order of spherical harmonic coefficients to be estimated
lmaxcs = 20;
% parameters of background gravity field
lmaxf = 20;
% number of days
nods = 12;
% number of GNV observations per time step(eg. 3A positions + 3B positions)
no = 6;
% total number of observatrion per time step
tno=6;
% Name of Run/ and simulation extention of results file name
name_ext_str = 'test_new';
% GNV Observation in ECI or ECEF (0, 1)
obs_frame = 0;
% number of observations in each arc (one day, 17280 is the standard)
mKBR = 17280;
% mKBR = 20;
% a guide to relationship between order of spherical harmonic coefficients and number of days
% Degree 10 1 day Degree 70 30 days
% Degree 50 7 days Degree 120 16 days(from Gunter 2000)
%% fixed inputs
% n: size of gravity fields in vec format, estimated and background
n_est = ((lmaxcs+1)^2 + lmaxcs+1)/2;
n_back = ((lmaxf+1)^2 + lmaxf+1)/2;
GM = 0.3986004415E+15;
ae = 0.6378136300E+07;
% reference for comparison
ggm05s = importGravityField('GGM05S.gfc');
ggm05s = ggm05s(1:n_back,:); % cut to desired length
ggm05s_cs = vec2cs([ggm05s(:,1) ggm05s(:,2)]',ggm05s(:,3),ggm05s(:,4));
% Load a-priori/ reference gravity field
egm96 = importGravityField('EGM96.gfc');
egm96 = egm96(1:n_back,:); % cut to desired length
egm96_cs = vec2cs([egm96(:,1) egm96(:,2)]',egm96(:,3),egm96(:,4));
% reformatting spherical harmonics coefficients
field_cs = egm96_cs;
field_sc = cs2sc(field_cs(1:lmaxf+1,1:lmaxf+1),0);
field = field_sc(:)';
[outC1,outS1,nm1] = cs2vec(field_cs,false);
field_vec0 = [nm1',outC1',outS1'];
err_vec = egm96;
err_vec(:,3:4) = ggm05s(:,3:4) - egm96(:,3:4);
% initialzes Legendre polynomial calculation
data_plm = initplm(lmaxf,2);
% folder to save intermediate results
tc = clock;
tcs = num2str(round(tc(6)));
Temp_Directory = [Release2_Path,'/jn', tcs, '_' name_ext_str,'/OutputArcParall'];
mkdir(Temp_Directory); % add time tag to counter same name_ext_str
%% load observations data and initial states for all days from files
t0 = [2005 05 01 0 0 2];
date0 = time2str(t0);
if no == 3 % just position observations
GNVL1B = zeros(mKBR,4,nods);
else % position and velocity observations
GNVL1B = zeros(mKBR,7,nods);
end
state0 = zeros(12,nods);
% State deviation:
x0x = zeros(12,nods);
t0i = t0;
for Mday = 1:nods
if Mday >1
t0i(3)=t0i(3)+1;
end
date = time2str(t0i);
% load GNV data GRACE A
data_GNV = [date, '/GNV1B_', date, '_A_02.asc'];
data_file = fullfile(Input_Observation_Path, data_GNV);
GNVi = readGNV(data_file);
if obs_frame == 1 % trafo to eci frame
RotMat_1 = Ri2e(data_GNV(1,1,Mday));
RotMat_dot_1 = Ri2e_dot(data_GNV(1,1,Mday));
v_eci_1 = RotMat_1'*GNVi(1,5:7)' + RotMat_dot_1'*GNVi(1,2:4)';
r_eci_1 = RotMat_1'*data_GNV(1,2:4,Mday)';
state0(1:6,Mday) = [r_eci_1; v_eci_1];
else
state0(1:6,Mday) = GNVi(1,2:7);
GNVL1B(:,1:4,Mday) = GNVi(1:mKBR,1:4);
end
% load GNV data GRACE B
data_GNV = [date, '/GNV1B_', date, '_B_02.asc'];
data_file = fullfile(Input_Observation_Path, data_GNV);
GNVi = readGNV(data_file);
if obs_frame == 1 % trafo to eci frame
RotMat_1 = Ri2e(data_GNV(1,1,Mday));
RotMat_dot_1 = Ri2e_dot(data_GNV(1,1,Mday));
v_eci_1 = RotMat_1'*GNVi(1,5:7)' + RotMat_dot_1'*GNVi(1,2:4)';
r_eci_1 = RotMat_1'*data_GNV(1,2:4,Mday)';
state0(7:12,Mday) = [r_eci_1; v_eci_1];
else
state0(7:12,Mday) = GNVi(1,2:7);
GNVL1B(:,5:7,Mday) = GNVi(1:mKBR,2:4);
end
end
% save initial state vector for comparisons
state00 = state0;
%% iteration
% number of coefficients
% Minimum degree and order of coefficients to be estimated
lmincs=2;
noc=lmaxcs^2-lmincs^2+2*lmaxcs+1; % total number of coefficients to be estimated
xhat_save = zeros (12, nods, ItrNo_max+1);
chat_save = zeros (noc, ItrNo_max+1);
chat_dv_save = zeros (ItrNo_max+1,lmaxcs-1);
dv_save = zeros (ItrNo_max+1,lmaxcs-1);
% save tic toc times:
t_itr_nod = zeros(ItrNo_max+1,nods+6); % +6 for clock
t_nod = zeros(1,nods);
for ItrNo = 0:ItrNo_max
c = clock;
[~,cs]=time2str(c);
fprintf(['start iteration ',num2str(ItrNo) ,', time: ', cs,'\n'])
% batch over all days
parfor Mday = 1:nods
% for Mday = 1:nods % for breakpoints and debugging
tic
batch_processor_partitioned_pos(Mday,nods,Temp_Directory,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),GNVL1B(:,1,Mday),GNVL1B(:,:,Mday),x0x(:,Mday))
t_nod(Mday) = toc;
end
t_itr_nod(ItrNo+1,1:nods) = t_nod;
t_itr_nod(ItrNo+1,nods+1:end) = c; % save time when each iteration was started
% solve normal equations
% read data from arc parallel
invMxx = zeros(12,12,nods);
iMxc = zeros(12,noc,nods);
iMcc = zeros(noc,noc,nods);
iNx = zeros(12,1,nods);
iNc = zeros(noc,1,nods);
iL = zeros(noc,noc,nods);
iN = zeros(noc,1,nods);
for Mday = 1:nods
FileName = ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File = fullfile(Temp_Directory, FileName);
arcstru=load(File);
invMxx(:,:,Mday) = arcstru.invMxx;
iMxc(:,:,Mday) = arcstru.Mxc;
iMcc(:,:,Mday) = arcstru.Mcc;
iNx(:,:,Mday) = arcstru.Nx;
iNc(:,:,Mday) = arcstru.Nc;
McxTinvMxx = iMxc(:,:,Mday)'*invMxx(:,:,Mday);
iL(:,:,Mday) = McxTinvMxx*iMxc(:,:,Mday);
iN(:,:,Mday) = McxTinvMxx*iNx(:,:,Mday);
end
% sum over the number of days
sumiMcc = sum(iMcc,3);
sumiNc = sum(iNc,3);
sumiL = sum(iL,3);
sumiN = sum(iN,3);
L = sumiMcc-sumiL;
N = sumiNc-sumiN;
% estimate global parameters
chat = L \ N;
% estimate local parameters
xhat = zeros(12,nods);
for Mday = 1:nods
xhat(:,Mday) = invMxx(:,:,Mday)*iNx(:,:,Mday)-invMxx(:,:,Mday)*iMxc(:,:,Mday)*chat;
end
% save xhat and chat of iterations
xhat_save(:,:,ItrNo+1) = xhat;
chat_save(:,ItrNo+1) = chat;
% put coefficients in right order for plotting and output
ko=1;
for i=1:lmaxcs+1
for j=1:lmaxcs+1
if i<=j
ordering1(ko,1)=j-1;
ordering1(ko,2)=i-1;
ko=ko+1;
end
end
end
nocC=(noc+lmaxcs-1)/2;
ordering1(3:end,3)=[chat(1:lmaxcs-1)', 0 ,chat(lmaxcs:nocC)']; % put C coeffs.
ordering1(3+lmaxcs:end,4)=chat(nocC+1:end); % put S coeffs.
ordering1_cs = vec2cs([ordering1(:,1) ordering1(:,2)]',ordering1(:,3),ordering1(:,4));
chat_cs = ordering1_cs;
% chat_vec = ordering1; % orderwise ordering
[outC1,outS1,nm1] = cs2vec(chat_cs,false); %degreewise
chat_vec = [nm1',outC1',outS1'];
chat_dv_save(ItrNo+1,:) = dv_geoidn_no_plot(chat_vec,lmaxcs);
% set up values for next iteration
state0 = state0 + xhat;
x0x = x0x - xhat;
% Add CS coeffs in cs format to reference field (just up to the order
% that was estimated)
field_cs(1:lmaxcs+1,1:lmaxcs+1) = field_cs(1:lmaxcs+1,1:lmaxcs+1) + chat_cs;
field_sc = cs2sc(field_cs(1:lmaxf+1,1:lmaxf+1),0);
field = field_sc(:)';
[outC1,outS1,nm1] = cs2vec(field_cs,false);
field_vec = [nm1',outC1',outS1'];
% save dv of true gravity field minus estimated from each iteration
d_vec = ggm05s(1:n_back,3:4)-field_vec(:,3:4);
d_vec = [field_vec(:,1:2) d_vec];
dv_save(ItrNo+1,:) = dv_geoidn_no_plot(d_vec,lmaxcs);
c = clock;
[~,cs]=time2str(c);
fprintf(['done with iteration ',num2str(ItrNo) ,', time: ', cs,'\n'])
end
% estimate residuals for the last day and last iteration
iHx = arcstru.Hx_save;
iHc = arcstru.Hc_save;
iygnv_save = arcstru.ygnv_save;
% estimate GNVA residuals
yhatXA=squeeze(iHx(:,1,:))*xhat(:,nods)+squeeze(iHc(:,1,:))*chat;
eps_save(:,1)= iygnv_save(:,1)-yhatXA;
yhatYA=squeeze(iHx(:,2,:))*xhat(:,nods)+squeeze(iHc(:,2,:))*chat;
eps_save(:,2) = iygnv_save(:,2)-yhatYA;
yhatZA=squeeze(iHx(:,3,:))*xhat(:,nods)+squeeze(iHc(:,3,:))*chat;
eps_save(:,3) = iygnv_save(:,3)-yhatZA;
% estimate GNVB residuals
yhatXB=squeeze(iHx(:,4,:))*xhat(:,nods)+squeeze(iHc(:,4,:))*chat;
eps_save(:,4)= iygnv_save(:,4)-yhatXB;
yhatYB=squeeze(iHx(:,5,:))*xhat(:,nods)+squeeze(iHc(:,5,:))*chat;
eps_save(:,5) = iygnv_save(:,5)-yhatYB;
yhatZB=squeeze(iHx(:,6,:))*xhat(:,nods)+squeeze(iHc(:,6,:))*chat;
eps_save(:,6) = iygnv_save(:,6)-yhatZB;
% save results in .mat file:
save_vars_for_plotting
% remove intermediate folder
FolderName_dd = Temp_Directory(1:end-16); % delete folder and subfolders
rmdir(FolderName_dd,'s');
else
% error message and end computation/ job
fprintf(['licence for MATLAB parallel computation toolbox not available\nComputation terminated\n'])
exit
return
end
%% GRACE gravity field recovery (GFR) using range-rates and positions
% This is the main m-file preforming the gravity field estimation. It is
% optimised for parallel computing using local and global parameters for
% different arcs. All necessary parameters and data are specified in the
% following. You have to set a number of iterations you want to perform.
% save_vars_for_plotting.m saves all the necessary variables for plotting.
%
% Written by Florian Wöske, ZARM Uni Bremen, 2018-12.
% Adapted by Neda Darbeheshti, AEI, 2019-06.
clear all
% close all;
% clc;
format longg;
nods = 1;
% check if Matlab toolbox licence is available, if not end job
[status,errmsg] = license('checkout', 'Distrib_Computing_Toolbox');
if status ~= 0 || nods == 1
%% variable inputs
% add folder name containing functions and input data (observations, ref.
% field, initial values...)
Release2_Path = pwd;
addpath(genpath(Release2_Path));
EBA_Path = fullfile(Release2_Path,'/../function_eba/');
addpath(genpath(EBA_Path));
GFR_Path = fullfile(Release2_Path,'/../function_gfr/');
addpath(genpath(GFR_Path));
Input_Data_Path = [Release2_Path,'/../input_data'];
addpath(genpath(Input_Data_Path));
% folder where observation data are stored
Input_Observation_Path = [Input_Data_Path, '/MockData_do20_nod12'];
% Define the number of iterations for batch processor,
ItrNo_max = 1;
% order of spherical harmonic coefficients to be estimated
lmaxcs = 20;
% parameters of background gravity field
lmaxf = 20;
% number of days
nods = 12;
% number of GNV observations per time step(eg. 3A positions + 3B positions)
no = 6;
% total number of observatrion per time step
tno=no+1;
% Name of Run/ and simulation extention of results file name
name_ext_str = 'test_new';
% GNV Observation in ECI or ECEF (0, 1)
obs_frame = 0;
% number of observations in each arc (one day, 17280 is the standard)
mKBR = 17280;
% mKBR = 20;
% a guide to relationship between order of spherical harmonic coefficients and number of days
% Degree 10 1 day Degree 70 30 days
% Degree 50 7 days Degree 120 16 days(from Gunter 2000)
%% fixed inputs
% n: size of gravity fields in vec format, estimated and background
n_est = ((lmaxcs+1)^2 + lmaxcs+1)/2;
n_back = ((lmaxf+1)^2 + lmaxf+1)/2;
GM = 0.3986004415E+15;
ae = 0.6378136300E+07;
% reference for comparison
ggm05s = importGravityField('GGM05S.gfc');
ggm05s = ggm05s(1:n_back,:); % cut to desired length
ggm05s_cs = vec2cs([ggm05s(:,1) ggm05s(:,2)]',ggm05s(:,3),ggm05s(:,4));
% Load a-priori/ reference gravity field
egm96 = importGravityField('EGM96.gfc');
egm96 = egm96(1:n_back,:); % cut to desired length
egm96_cs = vec2cs([egm96(:,1) egm96(:,2)]',egm96(:,3),egm96(:,4));
% reformatting spherical harmonics coefficients
field_cs = egm96_cs;
field_sc = cs2sc(field_cs(1:lmaxf+1,1:lmaxf+1),0);
field = field_sc(:)';
[outC1,outS1,nm1] = cs2vec(field_cs,false);
field_vec0 = [nm1',outC1',outS1'];
err_vec = egm96;
err_vec(:,3:4) = ggm05s(:,3:4) - egm96(:,3:4);
% initialzes Legendre polynomial calculation
data_plm = initplm(lmaxf,2);
% folder to save intermediate results
tc = clock;
tcs = num2str(round(tc(6)));
Temp_Directory = [Release2_Path,'/jn', tcs, '_' name_ext_str,'/OutputArcParall'];
mkdir(Temp_Directory); % add time tag to counter same name_ext_str
%% load observations data and initial states for all days from files
t0 = [2005 05 01 0 0 2];
date0 = time2str(t0);
if no == 3 % just position observations
GNVL1B = zeros(mKBR,3,nods);
else % position and velocity observations
GNVL1B = zeros(mKBR,6,nods);
end
KBRL1B = zeros(mKBR,4,nods);
state0 = zeros(12,nods);
% State deviation:
x0x = zeros(12,nods);
t0i = t0;
for Mday = 1:nods
if Mday >1
t0i(3)=t0i(3)+1;
end
date = time2str(t0i);
% load KBR data
data_KBR = [date, '/KBR1B_', date, '_X_02.asc'];
data_file = fullfile(Input_Observation_Path, data_KBR);
KBRL1Bi = readKBR(data_file);
KBRL1B(:,:,Mday) = KBRL1Bi(1:mKBR,1:4);
% load GNV data GRACE A
data_GNV = [date, '/GNV1B_', date, '_A_02.asc'];
data_file = fullfile(Input_Observation_Path, data_GNV);
GNVi = readGNV(data_file);
if obs_frame == 1 % trafo to eci frame
RotMat_1 = Ri2e(data_GNV(1,1,Mday));
RotMat_dot_1 = Ri2e_dot(data_GNV(1,1,Mday));
v_eci_1 = RotMat_1'*GNVi(1,5:7)' + RotMat_dot_1'*GNVi(1,2:4)';
r_eci_1 = RotMat_1'*data_GNV(1,2:4,Mday)';
state0(1:6,Mday) = [r_eci_1; v_eci_1];
else
state0(1:6,Mday) = GNVi(1,2:7);
GNVL1B(:,1:3,Mday) = GNVi(1:mKBR,2:4);
end
% load GNV data GRACE B
data_GNV = [date, '/GNV1B_', date, '_B_02.asc'];
data_file = fullfile(Input_Observation_Path, data_GNV);
GNVi = readGNV(data_file);
if obs_frame == 1 % trafo to eci frame
RotMat_1 = Ri2e(data_GNV(1,1,Mday));
RotMat_dot_1 = Ri2e_dot(data_GNV(1,1,Mday));
v_eci_1 = RotMat_1'*GNVi(1,5:7)' + RotMat_dot_1'*GNVi(1,2:4)';
r_eci_1 = RotMat_1'*data_GNV(1,2:4,Mday)';
state0(7:12,Mday) = [r_eci_1; v_eci_1];
else
state0(7:12,Mday) = GNVi(1,2:7);
GNVL1B(:,4:6,Mday) = GNVi(1:mKBR,2:4);
end
end
% save initial state vector for comparisons
state00 = state0;
%% iteration
% number of coefficients
% Minimum degree and order of coefficients to be estimated
lmincs=2;
noc=lmaxcs^2-lmincs^2+2*lmaxcs+1; %total number of coefficients to be estimated
xhat_save = zeros (12, nods, ItrNo_max+1);
chat_save = zeros (noc, ItrNo_max+1);
chat_dv_save = zeros (ItrNo_max+1,lmaxcs-1);
dv_save = zeros (ItrNo_max+1,lmaxcs-1);
% save tic toc times:
t_itr_nod = zeros(ItrNo_max+1,nods+6); % +6 for clock
t_nod = zeros(1,nods);
% define diagonal weighting matrix
WMAT0=10^(2*2)*eye(no+1);
WMAT0(1,1)=10^(7*2);
for ItrNo = 0:ItrNo_max
c = clock;
[~,cs]=time2str(c);
fprintf(['start iteration ',num2str(ItrNo) ,', time: ', cs,'\n'])
% batch over all days
parfor Mday = 1:nods
%for Mday = 1:nods % for breakpoints and debugging
tic
batch_processor_partitioned_pos_rrho(Mday,nods,Temp_Directory,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),KBRL1B(:,1,Mday),GNVL1B(:,:,Mday),KBRL1B(:,3,Mday),WMAT0)
t_nod(Mday) = toc;
end
t_itr_nod(ItrNo+1,1:nods) = t_nod;
t_itr_nod(ItrNo+1,nods+1:end) = c; % save time when each iteration was started
%% solve normal equations
% read data from arc parallel
invMxx = zeros(12,12,nods);
iMxc = zeros(12,noc,nods);
iMcc = zeros(noc,noc,nods);
iNx = zeros(12,1,nods);
iNc = zeros(noc,1,nods);
iL = zeros(noc,noc,nods);
iN = zeros(noc,1,nods);
for Mday = 1:nods
FileName = ['arcmatrix',num2str(Mday,'%.2d'),'.mat'];
File = fullfile(Temp_Directory, FileName);
arcstru=load(File);
invMxx(:,:,Mday) = arcstru.invMxx;
iMxc(:,:,Mday) = arcstru.Mxc;
iMcc(:,:,Mday) = arcstru.Mcc;
iNx(:,:,Mday) = arcstru.Nx;
iNc(:,:,Mday) = arcstru.Nc;
McxTinvMxx = iMxc(:,:,Mday)'*invMxx(:,:,Mday);
iL(:,:,Mday) = McxTinvMxx*iMxc(:,:,Mday);
iN(:,:,Mday) = McxTinvMxx*iNx(:,:,Mday);
end
% sum over the number of days
sumiMcc = sum(iMcc,3);
sumiNc = sum(iNc,3);
sumiL = sum(iL,3);
sumiN = sum(iN,3);
L = sumiMcc-sumiL;
N = sumiNc-sumiN;
% estimate global parameters
chat = L \ N;
% estimate local parameters
xhat = zeros(12,nods);
for Mday = 1:nods
xhat(:,Mday) = invMxx(:,:,Mday)*iNx(:,:,Mday)-invMxx(:,:,Mday)*iMxc(:,:,Mday)*chat;
end
% save xhat and chat of iterations
xhat_save(:,:,ItrNo+1) = xhat;
chat_save(:,ItrNo+1) = chat;
% put coefficients in right order for plotting and output
ko=1;
for i=1:lmaxcs+1
for j=1:lmaxcs+1
if i<=j
ordering1(ko,1)=j-1;
ordering1(ko,2)=i-1;
ko=ko+1;
end
end
end
nocC=(noc+lmaxcs-1)/2;
ordering1(3:end,3)=[chat(1:lmaxcs-1)', 0 ,chat(lmaxcs:nocC)']; % put C coeffs.
ordering1(3+lmaxcs:end,4)=chat(nocC+1:end); % put S coeffs.
ordering1_cs = vec2cs([ordering1(:,1) ordering1(:,2)]',ordering1(:,3),ordering1(:,4));
chat_cs = ordering1_cs;
% chat_vec = ordering1; % orderwise ordering
[outC1,outS1,nm1] = cs2vec(chat_cs,false); % degreewise
chat_vec = [nm1',outC1',outS1'];
chat_dv_save(ItrNo+1,:) = dv_geoidn_no_plot(chat_vec,lmaxcs);
% set up values for next iteration
state0 = state0 + xhat;
x0x = x0x - xhat;
% Add CS coeffs in cs format to reference field (just up to the order
% that was estimated)
field_cs(1:lmaxcs+1,1:lmaxcs+1) = field_cs(1:lmaxcs+1,1:lmaxcs+1) + chat_cs;
field_sc = cs2sc(field_cs(1:lmaxf+1,1:lmaxf+1),0);
field = field_sc(:)';
[outC1,outS1,nm1] = cs2vec(field_cs,false);
field_vec = [nm1',outC1',outS1'];
% save dv of true gravity field minus estimated from each iteration
d_vec = ggm05s(1:n_back,3:4)-field_vec(:,3:4);
d_vec = [field_vec(:,1:2) d_vec];
dv_save(ItrNo+1,:) = dv_geoidn_no_plot(d_vec,lmaxcs);
c = clock;
[~,cs]=time2str(c);
fprintf(['done with iteration ',num2str(ItrNo) ,', time: ', cs,'\n'])
end
% estimate residuals for the last day and last iteration
iHx = arcstru.Hx_save;
iHc = arcstru.Hc_save;
iykbr_save = arcstru.ykbr_save;
iygnv_save = arcstru.ygnv_save;
% estimate range rate residuals
yhatK=squeeze(iHx(:,1,:))*xhat(:,nods)+squeeze(iHc(:,1,:))*chat;
eps_save(:,1) = iykbr_save-yhatK;
% estimate GNVA residuals
yhatXA=squeeze(iHx(:,2,:))*xhat(:,nods)+squeeze(iHc(:,2,:))*chat;
eps_save(:,2)= iygnv_save(:,1)-yhatXA;
yhatYA=squeeze(iHx(:,3,:))*xhat(:,nods)+squeeze(iHc(:,3,:))*chat;
eps_save(:,3) = iygnv_save(:,2)-yhatYA;
yhatZA=squeeze(iHx(:,4,:))*xhat(:,nods)+squeeze(iHc(:,4,:))*chat;
eps_save(:,4) = iygnv_save(:,3)-yhatZA;
% estimate GNVB residuals
yhatXB=squeeze(iHx(:,5,:))*xhat(:,nods)+squeeze(iHc(:,5,:))*chat;
eps_save(:,5)= iygnv_save(:,4)-yhatXB;
yhatYB=squeeze(iHx(:,6,:))*xhat(:,nods)+squeeze(iHc(:,6,:))*chat;
eps_save(:,6) = iygnv_save(:,5)-yhatYB;
yhatZB=squeeze(iHx(:,7,:))*xhat(:,nods)+squeeze(iHc(:,7,:))*chat;
eps_save(:,7) = iygnv_save(:,6)-yhatZB;
% save results in .mat file:
save_vars_for_plotting
% remove intermediate folder
FolderName_dd = Temp_Directory(1:end-16); % delete folder and subfolders
rmdir(FolderName_dd,'s');
else
% error message and end computation/ job
fprintf(['licence for MATLAB parallel computation toolbox not available\nComputation terminated\n'])
exit
return
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment