General Purpose Geodetic Library
SgPwlStorageBSplineQ.cpp
Go to the documentation of this file.
1 /*
2  *
3  * This file is a part of Space Geodetic Library. The library is used by
4  * nuSolve, a part of CALC/SOLVE system, and designed to make analysis of
5  * geodetic VLBI observations.
6  * Copyright (C) 2010-2020 Sergei Bolotin.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include <SgLogger.h>
24 
25 #include <SgPwlStorageBSplineQ.h>
26 
27 #include <SgTaskConfig.h>
28 
29 
30 
31 
32 /*=======================================================================================================
33 *
34 * METHODS:
35 *
36 *======================================================================================================*/
37 //
38 // static first:
40 {
41  return "SgPwlStorageBSplineQ";
42 };
43 
44 
45 
46 // An empty constructor:
48  : SgPwlStorage()
49 {
50 };
51 
52 
53 
54 // A destructor:
56 {
57 };
58 
59 
60 
61 //
63 {
65  int nAs, nBs(3);
66  switch (dDomain)
67  {
68  default:
70  nAs = getNumOfPolynomials();
71  break;
72  case SgPartial::DD_RATE:
74  break;
75  };
76  return nAs + nBs;
77 };
78 
79 
80 
81 //
83 {
84  return numOfNodes_ - 2;
85 };
86 
87 
88 
89 //
91  const SgMJD& t0, const SgMJD& tN, const SgMJD& tRefer,
92  const SgTaskConfig* /*cfg*/)
93 {
94  if (isPOrigOwner_)
95  delete pOrig_;
96  pOrig_ = p;
97  isPOrigOwner_ = false;
98  tStart_ = t0;
99  tFinis_ = tN;
100  //tRefer_ = tN;
101  //tRefer_.setTime(0.0); // 0hr
102  tRefer_ = tRefer;
103  step_ = pOrig_->getStep();
104  // emulate SOLVE:
105 // SgMJD t0h(tN);
106 // t0h.setTime(0); // 0hr
107 // if (cfg->getIsSolveCompatible())
108 
109 /*
110  if (?)
111  {
112  SgMJD t0h(tRefer_);
113  if (step_ > tFinis_-tStart_)
114  {
115  tStart_ = t0h - ceil((t0h - t0)*24.0)/24.0;
116  tFinis_ = t0h + ceil((tN - t0h)*24.0)/24.0;
117  step_ = tFinis_ - tStart_;
118  }
119  else
120  {
121  tStart_ = t0h - ceil((t0h - t0)*24.0)/24.0;
122  tFinis_ = tStart_ + ceil((tN - tStart_)/step_)*step_;
123  };
124 //
125 // if (step_ < tFinis_-tStart_)
126 // {
127 // tStart_ = t0h - ceil((t0h - t0)/step_)*step_;
128 // tFinis_ = t0h + ceil((tN - t0h)/step_)*step_;
129 // }
130 // else
131 // {
132 // tStart_ = t0h - ceil((t0h - t0)*24.0)/24.0;
133 // tFinis_ = t0h + ceil((tN - t0h)*24.0)/24.0;
134 // step_ = tFinis_ - tStart_;
135 // };
136 //
137  }
138  else
139 */
140 
141  // if the step equal to an interval of data set, no polynomial terms are expected:
142  if (step_ > tFinis_-tStart_)
143  {
144  step_ = tFinis_ - tStart_ + 1.0E-4/DAY2SEC;
145  numOfPolynomials_ = 0;
146  }
147  else
149 
150  if (numOfPolynomials_ == 1) // no polynomials
151  numOfPolynomials_ = 0;
152 
153  if (numOfPolynomials_ > 0)
154  {
156  for (int i=0; i<numOfPolynomials_; i++)
157  {
158  pAi_[i].setName(pOrig_->getName() + ": A_" + QString("").sprintf("%d", i));
159  pAi_[i].tune(*pOrig_);
162  pAi_[i].setTLeft(tZero);
163  pAi_[i].setTRight(tInf);
164  };
166  "::deployParameters(): " + QString("").setNum(numOfPolynomials_) +
167  " polynomial parameters were allocated for " + pOrig_->getName() + " parameter");
168  };
169 
170  // B-Spline nodes:
171  numOfNodes_ = floor((tFinis_ - tStart_)/step_) + 3;
173  for (int i=0; i<numOfNodes_; i++)
174  {
175  pBi_[i].setName(pOrig_->getName() + ": B_" + QString("").sprintf("%03d", i));
176  pBi_[i].tune(*pOrig_);
179  if (true)
180  {
181  pBi_[i].setTLeft (tStart_ + (i - 2)*step_);
182  pBi_[i].setTRight(tStart_ + (i + 1)*step_);
183  }
184  else
185  {
186  pBi_[i].setTLeft(tZero);
187  pBi_[i].setTRight(tInf);
188  };
189  };
190  pBi_[0 ].setTLeft (tStart_);
191  pBi_[1 ].setTLeft (tStart_);
194 
195 
196  sumP2_ = 0.0;
197  sumX1P2_ = 0.0;
198  sumX2P2_ = 0.0;
199  sumT1P2_ = 0.0;
200 };
201 
202 
203 
204 //
206 {
208  return;
209  //
210  // adjust time from constraints equations:
211  SgMJD t(tt==tZero?tStart_:tt);
213  //
214  if (t < tStart_)
216  ": propagatePartials(): t(" + t.toString(SgMJD::F_YYYYMMDDHHMMSSSS) + ") < tStart(" +
218  if (tFinis_ < t)
220  ": propagatePartials(): tFinis(" + tFinis_.toString(SgMJD::F_YYYYMMDDHHMMSSSS) + ") < t(" +
222  //
223  double d(pOrig_->getD());
224  //
225  // Polynomials:
226  if (numOfPolynomials_ > 0)
227  {
228  double dt = (t - tRefer_);
229  double dd = 1.0;
230  switch (dDomain)
231  {
232  default:
234  for (int i=0; i<numOfPolynomials_; i++)
235  {
236  pAi_[i].setD(d*dd);
237  dd *= dt;
238  };
239  break;
240  case SgPartial::DD_RATE:
241  for (int i=1; i<numOfPolynomials_; i++)
242  {
243  pAi_[i].setD(i*d*dd);
244  dd *= dt/*/DAY2SEC*/;
245  };
246  break;
247  };
248  };
249  //
250  //
251  // B-Splines:
252  int j=calcCurrentIdx(t);
253  double dt(t - tStart_), g(2.0*step_*step_), a;
254  switch (dDomain)
255  {
256  default:
258  a = -dt + (j+1)*step_;
259  pBi_[j ].setD(d* a*a/g);
260  //
261  a = (dt - (j-1)*step_)*((j+1)*step_ - dt) + (dt - j*step_)*((j+2)*step_ - dt);
262  pBi_[j+1].setD(d* a/g);
263  //
264  a = dt - j*step_;
265  pBi_[j+2].setD(d* a*a/g);
266  break;
267  case SgPartial::DD_RATE:
268  a = -dt + (j+1)*step_;
269  pBi_[j ].setD(-2.0*d*a/g);
270  //
271  a = (-2.0*dt + (2*j+1)*step_);
272  pBi_[j+1].setD( 2.0*d*a/g);
273  //
274  a = dt - j*step_;
275  pBi_[j+2].setD( 2.0*d*a/g);
276  break;
277  };
278  //
279  pOrig_->zerofy();
280 };
281 
282 
283 
284 //
285 double SgPwlStorageBSplineQ::calcAX(const SgMJD& t, bool isWorkingBand)
286 {
287  double f(0.0), s2(0.0), d;
289  //
290  // Polynomials:
291  if (numOfPolynomials_ > 0)
292  {
293  double dt = (t - tRefer_);
294  double dd = 1.0;
295  switch (dDomain)
296  {
297  default:
299  for (int i=0; i<numOfPolynomials_; i++)
300  {
301  f += pAi_[i].getSolution()*dd;
302  s2+= pAi_[i].getSigma()*pAi_[i].getSigma()*dd*dd;
303  dd *= dt;
304  };
305  break;
306  case SgPartial::DD_RATE:
307  for (int i=1; i<numOfPolynomials_; i++)
308  {
309  f += i*pAi_[i].getSolution()*dd;
310  s2+= i*i*pAi_[i].getSigma()*pAi_[i].getSigma()*dd*dd;
311  dd *= dt/*/DAY2SEC*/;
312  };
313  break;
314  };
315  };
316  //
317  // B-Splines:
318  double fs(0.0), s2s(s2), b;
319  if (numOfPolynomials_==1)
320  fs = f;
321  //
322  int j = calcCurrentIdx(t);
323  double dt(t - tStart_), g(2.0*step_*step_), a;
324  //
325  switch (dDomain)
326  {
327  default:
329  // j-th element:
330  a = -dt + (j+1)*step_;
331  d = a*a/g;
332  b = pBi_[j].getSolution()*d;
333  f += b;
334  fs += b;
335  b = pBi_[j].getSigma()*pBi_[j].getSigma()*d*d;
336  s2 += b;
337  s2s+= b;
338  // (j+1)-th element:
339  a = (dt - (j-1)*step_)*((j+1)*step_ - dt) + (dt - j*step_)*((j+2)*step_ - dt);
340  d = a/g;
341  b = pBi_[j+1].getSolution()*d;
342  f += b;
343  fs += b;
344  b = pBi_[j+1].getSigma()*pBi_[j+1].getSigma()*d*d;
345  s2 += b;
346  s2s+= b;
347  // (j+2)-th element:
348  a = dt - j*step_;
349  d = a*a/g;
350  b = pBi_[j+2].getSolution()*d;
351  f += b;
352  fs += b;
353  b = pBi_[j+2].getSigma()*pBi_[j+2].getSigma()*d*d;
354  s2 += b;
355  s2s+= b;
356  //
357  // sets up the original parameter solution:
358  pOrig_->setSolution(fs);
359  pOrig_->setSigma(sqrt(s2s));
360  pOrig_->setNumObs(pBi_[j].getNumObs() + pBi_[j+1].getNumObs() + pBi_[j+2].getNumObs());
361  // and statistics:
362  if (isWorkingBand)
363  {
364  sumP2_ += 1.0/s2;
365  sumX1P2_ += f /s2;
366  sumX2P2_ += f*f/s2;
367  sumT1P2_ += t.toDouble()/s2;
368  };
369  break;
370  case SgPartial::DD_RATE:
371  a = -dt + (j+1)*step_;
372  d = -2.0*a/g*pBi_[j ].getSolution();
373  f += d;
374  //
375  a = (-2.0*dt + (2*j+1)*step_);
376  d = 2.0*a/g*pBi_[j+1].getSolution();
377  f += d;
378  //
379  a = dt - j*step_;
380  d = 2.0*a/g*pBi_[j+2].getSolution();
381  f += d;
382  break;
383  };
384  // return Ax part:
385  return pOrig_->getD()*f;
386 };
387 
388 
389 
390 //
392 {
393  int j=calcCurrentIdx(t);
394  double f(0.0), dt(t - tStart_), g(2.0*step_*step_), d, a;
395  //
396  a = -dt + (j+1)*step_;
397  d = a*a/g;
398  f += pBi_[j ].getSolution()*d;
399  //
400  a = (dt - (j-1)*step_)*((j+1)*step_ - dt) + (dt - j*step_)*((j+2)*step_ - dt);
401  d = a/g;
402  f += pBi_[j+1].getSolution()*d;
403  //
404  a = dt - j*step_;
405  d = a*a/g;
406  f += pBi_[j+2].getSolution()*d;
407  //
408  return f;
409 };
410 
411 
412 
413 //
415 {
416  // B-splines only:
417  int j=calcCurrentIdx(t);
418  double s2(0.0), dt(t - tStart_), g(2.0*step_*step_), d, a;
419  //
420  a = -dt + (j+1)*step_;
421  d = a*a/g;
422  s2 += pBi_[j ].getSigma()*pBi_[j ].getSigma()*d*d;
423  //
424  a = (dt - (j-1)*step_)*((j+1)*step_ - dt) + (dt - j*step_)*((j+2)*step_ - dt);
425  d = a/g;
426  s2 += pBi_[j+1].getSigma()*pBi_[j+1].getSigma()*d*d;
427  //
428  a = dt - j*step_;
429  d = a*a/g;
430  s2 += pBi_[j+2].getSigma()*pBi_[j+2].getSigma()*d*d;
431  //
432  return sqrt(s2);
433 };
434 
435 
436 
437 //
438 double SgPwlStorageBSplineQ::calc_P_a(const SgSymMatrix& P, int idx, const SgMJD& t)
439 {
441  double v(0.0);
442  if (numOfPolynomials_ > 0)
443  {
444  double dt = (t - tRefer_);
445  double dd = 1.0;
446  switch (dDomain)
447  {
448  default:
450  for (int i=0; i<numOfPolynomials_; i++)
451  {
452  v += P.getElement(idx, pAi_[i].getIdx())*dd;
453  dd *= dt;
454  };
455  break;
456  case SgPartial::DD_RATE:
457  for (int i=1; i<numOfPolynomials_; i++)
458  {
459  v += i*P.getElement(idx, pAi_[i].getIdx())*dd;
460  dd *= dt/*/DAY2SEC*/;
461  };
462  break;
463  };
464  };
465  //
466  int j=calcCurrentIdx(t);
467  double dt(t - tStart_), g(2.0*step_*step_), d_0, d_1, d_2, a;
468  switch (dDomain)
469  {
470  default:
472  //
473  a = -dt + (j+1)*step_;
474  d_0 = a*a/g;
475  //
476  a = (dt - (j-1)*step_)*((j+1)*step_ - dt) + (dt - j*step_)*((j+2)*step_ - dt);
477  d_1 = a/g;
478  //
479  a = dt - j*step_;
480  d_2 = a*a/g;
481  //
482  v +=
483  P.getElement(idx, pBi_[j ].getIdx())*d_0 +
484  P.getElement(idx, pBi_[j+1].getIdx())*d_1 +
485  P.getElement(idx, pBi_[j+2].getIdx())*d_2 ;
486  break;
487  case SgPartial::DD_RATE:
488  //
489  a = -dt + (j+1)*step_;
490  d_0 = -2.0*a/g;
491  //
492  a = (-2.0*dt + (2*j+1)*step_);
493  d_1 = 2.0*a/g;
494  //
495  a = dt - j*step_;
496  d_2 = 2.0*a/g;
497  //
498  v +=
499  P.getElement(idx, pBi_[j ].getIdx())*d_0 +
500  P.getElement(idx, pBi_[j+1].getIdx())*d_1 +
501  P.getElement(idx, pBi_[j+2].getIdx())*d_2 ;
502  break;
503  };
504  //
505  return pOrig_->getD()*v;
506 };
507 
508 
509 
510 //
511 double SgPwlStorageBSplineQ::calc_aT_P_a(const SgVector& vP_a, const SgMJD& t)
512 {
514  double v(0.0);
515  if (numOfPolynomials_ > 0)
516  {
517  double dt = (t - tRefer_);
518  double dd = 1.0;
519  switch (dDomain)
520  {
521  default:
523  for (int i=0; i<numOfPolynomials_; i++)
524  {
525  v += vP_a.getElement(pAi_[i].getIdx())*dd;
526  dd *= dt;
527  };
528  break;
529  case SgPartial::DD_RATE:
530  for (int i=1; i<numOfPolynomials_; i++)
531  {
532  v += i*vP_a.getElement(pAi_[i].getIdx())*dd;
533  dd *= dt/*/DAY2SEC*/;
534  };
535  break;
536  };
537  };
538  //
539  int j=calcCurrentIdx(t);
540  double dt(t - tStart_), g(2.0*step_*step_), d_0, d_1, d_2, a;
541 
542  switch (dDomain)
543  {
544  default:
546  //
547  a = -dt + (j+1)*step_;
548  d_0 = a*a/g;
549  //
550  a = (dt - (j-1)*step_)*((j+1)*step_ - dt) + (dt - j*step_)*((j+2)*step_ - dt);
551  d_1 = a/g;
552  //
553  a = dt - j*step_;
554  d_2 = a*a/g;
555  //
556  v +=
557  vP_a.getElement(pBi_[j ].getIdx())*d_0 +
558  vP_a.getElement(pBi_[j+1].getIdx())*d_1 +
559  vP_a.getElement(pBi_[j+2].getIdx())*d_2 ;
560  break;
561  case SgPartial::DD_RATE:
562  //
563  a = -dt + (j+1)*step_;
564  d_0 = -2.0*a/g;
565  //
566  a = (-2.0*dt + (2*j+1)*step_);
567  d_1 = 2.0*a/g;
568  //
569  a = dt - j*step_;
570  d_2 = 2.0*a/g;
571  //
572  v +=
573  vP_a.getElement(pBi_[j ].getIdx())*d_0 +
574  vP_a.getElement(pBi_[j+1].getIdx())*d_1 +
575  vP_a.getElement(pBi_[j+2].getIdx())*d_2 ;
576  break;
577  };
578  //
579  return pOrig_->getD()*v;
580 };
581 
582 
583 
584 //
586 {
587  pars.clear();
589  int idx(calcCurrentIdx(t));
590  switch (dDomain)
591  {
592  default:
594  for (int i=0; i<getNumOfPolynomials(); i++)
595  pars.append(&pAi_[i]);
596  pars.append(&pBi_[idx ]);
597  pars.append(&pBi_[idx+1]);
598  pars.append(&pBi_[idx+2]);
599  break;
600  case SgPartial::DD_RATE:
601  for (int i=1; i<getNumOfPolynomials(); i++)
602  pars.append(&pAi_[i]);
603  pars.append(&pBi_[idx ]);
604  pars.append(&pBi_[idx+1]);
605  pars.append(&pBi_[idx+2]);
606  break;
607  };
608 };
609 
610 
611 
612 //
614 {
615  double vi, vim1, sD2;
616  sD2 = 0.0;
617  for (int i=1; i<numOfNodes_; i++)
618  {
619  vi = pBi_[i ].getSolution();
620  vim1 = pBi_[i-1].getSolution();
621  sD2 += (vi - vim1)*(vi - vim1);
622  };
623  return sD2/step_/step_;
624 };
625 /*=====================================================================================================*/
626 
627 
628 
629 
630 /*=======================================================================================================
631 *
632 * FRIENDS:
633 *
634 *======================================================================================================*/
635 //
636 
637 
638 
639 /*=====================================================================================================*/
640 //
641 // aux functions:
642 //
643 
644 
645 // i/o:
646 
647 
648 /*=====================================================================================================*/
649 //
650 // constants:
651 //
652 
653 
654 /*=====================================================================================================*/
SgLogger * logger
Definition: SgLogger.cpp:231
const SgMJD tZero(1957, 10, 4)
const SgMJD tInf(2100, 1, 1)
#define DAY2SEC
radians to mas:
Definition: SgMathSupport.h:69
bool isAttr(uint a) const
Definition: SgAttribute.h:226
virtual void write(LogLevel, quint32, const QString &, bool=false)
Definition: SgLogger.cpp:88
@ ESTIMATOR
Definition: SgLogger.h:90
Definition: SgMJD.h:59
@ F_YYYYMMDDHHMMSSSS
Long verbose: Fri, the 2nd of Apr, 2010; 17hr 02min 43.6400sec.
Definition: SgMJD.h:67
QString toString(Format format=F_Verbose) const
Definition: SgMJD.cpp:1008
double toDouble() const
Definition: SgMJD.h:531
double getStep() const
Definition: SgParameter.h:523
double getSolution() const
Definition: SgParameter.h:435
void setTLeft(const SgMJD &t)
Definition: SgParameter.h:691
void setTRight(const SgMJD &t)
Definition: SgParameter.h:699
int getNumOfPolynomials() const
Definition: SgParameter.h:539
void tune(const SgParameterCfg &)
Definition: SgParameter.cpp:72
void setSigma(double v)
Definition: SgParameter.h:587
double getSigma() const
Definition: SgParameter.h:443
int getIdx() const
Definition: SgParameter.h:563
double getSigmaAPriori() const
Definition: SgParameter.h:475
void setSolution(double v)
Definition: SgParameter.h:579
void setSigmaAPriori(double v)
Definition: SgParameter.h:619
double getSigmaAPrioriAux() const
Definition: SgParameter.h:483
void setPMode(SgParameterCfg::PMode mode)
Definition: SgParameter.h:603
void setD(double d)
Definition: SgPartial.h:347
void setName(const QString &name)
Definition: SgPartial.h:339
int getNumObs() const
Definition: SgPartial.h:299
@ DD_OFFSET
Definition: SgPartial.h:58
const QString & getName() const
Definition: SgPartial.h:283
double getD() const
Definition: SgPartial.h:291
void setNumObs(int n)
Definition: SgPartial.h:356
DataDomain getDataDomain() const
Definition: SgPartial.h:97
void zerofy()
Definition: SgPartial.h:408
@ Attr_IS_PARTIAL_SET
rise this bit on when the partial is assigned
Definition: SgPartial.h:53
virtual double calc_aT_P_a(const SgVector &, const SgMJD &)
virtual int getNumOfActiveParameters(const SgMJD &t)
virtual double calcRateSigma(const SgMJD &)
virtual void propagatePartials(const SgMJD &t)
virtual double calcRateSolution(const SgMJD &)
static const QString className()
virtual double calcAX(const SgMJD &, bool)
virtual double calc_P_a(const SgSymMatrix &, int, const SgMJD &)
virtual double calcRateRms4Sfo()
virtual void getListOfActiveParameters(const SgMJD &t, QList< SgParameter * > &pars)
virtual void deployParameters(SgParameter *, const SgMJD &tStart, const SgMJD &tFinis, const SgMJD &tRefer, const SgTaskConfig *)
int getNumOfPolynomials() const
Definition: SgPwlStorage.h:259
double sumT1P2_
Definition: SgPwlStorage.h:179
int numOfPolynomials_
Definition: SgPwlStorage.h:169
bool isPOrigOwner_
Definition: SgPwlStorage.h:180
const SgMJD & tRefer() const
Definition: SgPwlStorage.h:291
double sumX2P2_
Definition: SgPwlStorage.h:178
SgParameter * pOrig_
Definition: SgPwlStorage.h:165
int calcCurrentIdx(const SgMJD &t)
Definition: SgPwlStorage.h:345
SgParameter * pAi_
Definition: SgPwlStorage.h:167
double sumX1P2_
Definition: SgPwlStorage.h:177
SgParameter * pBi_
Definition: SgPwlStorage.h:168
double getElement(unsigned int i, unsigned int j) const
Definition: SgSymMatrix.h:274
double getElement(unsigned int i) const
Definition: SgVector.h:362