From 51ae64264854c2769602c95a2949f27e0fd7050c Mon Sep 17 00:00:00 2001 From: Axel Schnitger <axel.schnitger@aei.mpg.de> Date: Fri, 13 Sep 2019 12:58:32 +0200 Subject: [PATCH] Add proper path handling. m-files in the release directory are now executable from the release diretory. No need to change the path to the repo's root level. --- .gitignore | 2 + README.md | 141 ++++++- function_eba/calculatePnm.m | 41 +++ function_eba/designmatrixn.m | 41 +++ function_eba/potential_EBAs.m | 41 +++ function_eba/sortCoefficients.m | 38 ++ function_eba/threeDmulti_rot.m | 45 +++ .../batch_processor_partitioned_pos.m | 184 ++++++++++ .../batch_processor_partitioned_pos_rrho.m | 201 ++++++++++ .../batch_processor_partitioned_rrho.m | 179 +++++++++ ...atch_processor_partitioned_rrho_tickonov.m | 182 +++++++++ function_gfr/hmat_pos.m | 42 +++ function_gfr/save_vars_for_plotting.m | 17 + get_input_data.sh | 31 +- .../continue_gfr_par_from_iteration.m | 32 +- gfr_parallel.m => release1/gfr_parallel.m | 61 +-- .../save_vars2continue_itr.m | 4 +- release2/gfr_eba.m | 151 ++++++++ release2/gfr_pos.m | 333 +++++++++++++++++ release2/gfr_pos_rrho.m | 347 ++++++++++++++++++ release2/gfr_rrho.m | 317 ++++++++++++++++ release2/gfr_rrho_tickonov.m | 322 ++++++++++++++++ release2/results/.gitkeep | 0 23 files changed, 2674 insertions(+), 78 deletions(-) create mode 100644 function_eba/calculatePnm.m create mode 100644 function_eba/designmatrixn.m create mode 100644 function_eba/potential_EBAs.m create mode 100644 function_eba/sortCoefficients.m create mode 100644 function_eba/threeDmulti_rot.m create mode 100644 function_gfr/batch_processor_partitioned_pos.m create mode 100644 function_gfr/batch_processor_partitioned_pos_rrho.m create mode 100644 function_gfr/batch_processor_partitioned_rrho.m create mode 100644 function_gfr/batch_processor_partitioned_rrho_tickonov.m create mode 100644 function_gfr/hmat_pos.m create mode 100644 function_gfr/save_vars_for_plotting.m rename continue_gfr_par_from_iteration.m => release1/continue_gfr_par_from_iteration.m (92%) rename gfr_parallel.m => release1/gfr_parallel.m (85%) rename save_vars2continue_itr.m => release1/save_vars2continue_itr.m (70%) create mode 100644 release2/gfr_eba.m create mode 100644 release2/gfr_pos.m create mode 100644 release2/gfr_pos_rrho.m create mode 100644 release2/gfr_rrho.m create mode 100644 release2/gfr_rrho_tickonov.m create mode 100644 release2/results/.gitkeep diff --git a/.gitignore b/.gitignore index 050fd26..b5a48cf 100644 --- a/.gitignore +++ b/.gitignore @@ -228,3 +228,5 @@ TSWLatexianTemp* # End of https://www.gitignore.io/api/latex variational.pdf +input_data/ +results/ diff --git a/README.md b/README.md index 927fcc1..63f9514 100644 --- a/README.md +++ b/README.md @@ -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) -- [Performance](#performance) + - [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 10min. +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) diff --git a/function_eba/calculatePnm.m b/function_eba/calculatePnm.m new file mode 100644 index 0000000..8c85758 --- /dev/null +++ b/function_eba/calculatePnm.m @@ -0,0 +1,41 @@ +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 diff --git a/function_eba/designmatrixn.m b/function_eba/designmatrixn.m new file mode 100644 index 0000000..b669957 --- /dev/null +++ b/function_eba/designmatrixn.m @@ -0,0 +1,41 @@ +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 + + + + diff --git a/function_eba/potential_EBAs.m b/function_eba/potential_EBAs.m new file mode 100644 index 0000000..65ae2ff --- /dev/null +++ b/function_eba/potential_EBAs.m @@ -0,0 +1,41 @@ +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 diff --git a/function_eba/sortCoefficients.m b/function_eba/sortCoefficients.m new file mode 100644 index 0000000..ffa9714 --- /dev/null +++ b/function_eba/sortCoefficients.m @@ -0,0 +1,38 @@ +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 diff --git a/function_eba/threeDmulti_rot.m b/function_eba/threeDmulti_rot.m new file mode 100644 index 0000000..b6d4ee3 --- /dev/null +++ b/function_eba/threeDmulti_rot.m @@ -0,0 +1,45 @@ +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 diff --git a/function_gfr/batch_processor_partitioned_pos.m b/function_gfr/batch_processor_partitioned_pos.m new file mode 100644 index 0000000..7bfeb0e --- /dev/null +++ b/function_gfr/batch_processor_partitioned_pos.m @@ -0,0 +1,184 @@ +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 + + diff --git a/function_gfr/batch_processor_partitioned_pos_rrho.m b/function_gfr/batch_processor_partitioned_pos_rrho.m new file mode 100644 index 0000000..28a9941 --- /dev/null +++ b/function_gfr/batch_processor_partitioned_pos_rrho.m @@ -0,0 +1,201 @@ +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 + + diff --git a/function_gfr/batch_processor_partitioned_rrho.m b/function_gfr/batch_processor_partitioned_rrho.m new file mode 100644 index 0000000..c464d0f --- /dev/null +++ b/function_gfr/batch_processor_partitioned_rrho.m @@ -0,0 +1,179 @@ +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 diff --git a/function_gfr/batch_processor_partitioned_rrho_tickonov.m b/function_gfr/batch_processor_partitioned_rrho_tickonov.m new file mode 100644 index 0000000..c7127da --- /dev/null +++ b/function_gfr/batch_processor_partitioned_rrho_tickonov.m @@ -0,0 +1,182 @@ +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 diff --git a/function_gfr/hmat_pos.m b/function_gfr/hmat_pos.m new file mode 100644 index 0000000..021ca35 --- /dev/null +++ b/function_gfr/hmat_pos.m @@ -0,0 +1,42 @@ +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 diff --git a/function_gfr/save_vars_for_plotting.m b/function_gfr/save_vars_for_plotting.m new file mode 100644 index 0000000..0c367c9 --- /dev/null +++ b/function_gfr/save_vars_for_plotting.m @@ -0,0 +1,17 @@ +%% 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); diff --git a/get_input_data.sh b/get_input_data.sh index 1d637cc..edbc057 100755 --- a/get_input_data.sh +++ b/get_input_data.sh @@ -1,16 +1,20 @@ #!/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 diff --git a/continue_gfr_par_from_iteration.m b/release1/continue_gfr_par_from_iteration.m similarity index 92% rename from continue_gfr_par_from_iteration.m rename to release1/continue_gfr_par_from_iteration.m index 0d559f5..7dc1e3d 100644 --- a/continue_gfr_par_from_iteration.m +++ b/release1/continue_gfr_par_from_iteration.m @@ -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,:)); diff --git a/gfr_parallel.m b/release1/gfr_parallel.m similarity index 85% rename from gfr_parallel.m rename to release1/gfr_parallel.m index fe055ce..b270dbd 100644 --- a/gfr_parallel.m +++ b/release1/gfr_parallel.m @@ -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'); +% Load a-priori/ reference gravity field +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,26 +106,25 @@ 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 - state00 = state0; +% save initial state vector for comparisons +state00 = state0; %% iteration @@ -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; @@ -228,16 +230,16 @@ for ItrNo = 0:ItrNo_max chat_vec = [nm1',outC1',outS1']; chat_dv_save(ItrNo+1,:) = dv_geoidn_no_plot(chat_vec,lmaxcs); -% dv_geoidn(chat_vec,lmaxcs); + % dv_geoidn(chat_vec,lmaxcs); -% % 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); -% fileID = fopen(File,'w'); -% for i=1:length(ordering2) -% fprintf(fileID,'%4i %4i %17.16e %17.16e\n',ordering2(i,:)); -% end -% fclose(fileID); + % % 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(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,:)); + % end + % fclose(fileID); % set up values for next iteration state0 = state0 + xhat; @@ -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 diff --git a/save_vars2continue_itr.m b/release1/save_vars2continue_itr.m similarity index 70% rename from save_vars2continue_itr.m rename to release1/save_vars2continue_itr.m index 37aee8b..4899ba8 100644 --- a/save_vars2continue_itr.m +++ b/release1/save_vars2continue_itr.m @@ -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'); diff --git a/release2/gfr_eba.m b/release2/gfr_eba.m new file mode 100644 index 0000000..184f4f3 --- /dev/null +++ b/release2/gfr_eba.m @@ -0,0 +1,151 @@ +%% 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'); diff --git a/release2/gfr_pos.m b/release2/gfr_pos.m new file mode 100644 index 0000000..57fa4b9 --- /dev/null +++ b/release2/gfr_pos.m @@ -0,0 +1,333 @@ +%% 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 diff --git a/release2/gfr_pos_rrho.m b/release2/gfr_pos_rrho.m new file mode 100644 index 0000000..1c6c8da --- /dev/null +++ b/release2/gfr_pos_rrho.m @@ -0,0 +1,347 @@ +%% 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 diff --git a/release2/gfr_rrho.m b/release2/gfr_rrho.m new file mode 100644 index 0000000..0137971 --- /dev/null +++ b/release2/gfr_rrho.m @@ -0,0 +1,317 @@ +%% GRACE gravity field recovery (GFR) using range-rates +% 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 = 0; +% total number of observatrion per time step +tno=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); + 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); + 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 + +% SH deviation: +% x0c = zeros(noc,1); +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_rrho(Mday,nods,Temp_Directory,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),KBRL1B(:,1,Mday),KBRL1B(:,3,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(:)'; + % x0c=x0c-chat; + + [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; + +% estimate range rate residuals +yhatK=iHx*xhat(:,nods)+iHc*chat; +eps_save(:,1) = iykbr_save-yhatK; + +% 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 diff --git a/release2/gfr_rrho_tickonov.m b/release2/gfr_rrho_tickonov.m new file mode 100644 index 0000000..353263f --- /dev/null +++ b/release2/gfr_rrho_tickonov.m @@ -0,0 +1,322 @@ +%% GRACE gravity field recovery (GFR) using range-rates with Tickonov regularization +% 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 = 0; + +% total number of observatrion per time step +tno=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); + 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); + 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 + +% SH deviation: +% x0c = zeros(noc,1); +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_rrho_tickonov(Mday,nods,Temp_Directory,lmaxcs,mKBR,field,data_plm,GM,ae,lmaxf,state0(:,Mday),KBRL1B(:,1,Mday),KBRL1B(:,3,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(:)'; + % x0c=x0c-chat; + + [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; + +% estimate range rate residuals +yhatK=iHx*xhat(:,nods)+iHc*chat; +eps_save(:,1) = iykbr_save-yhatK; + +% 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 diff --git a/release2/results/.gitkeep b/release2/results/.gitkeep new file mode 100644 index 0000000..e69de29 -- GitLab