SlowDown Algorithmic Regularization (SDAR)
Algorithmic Regularization with slowdown method for integrating few-body motions
symplectic_step.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <array>
5 #include "Common/Float.h"
6 
7 namespace AR {
9 
12  private:
13  // cd pair type
14  typedef std::array<Float,2> CDPair;
16  struct CumSumCkIndex{
17  Float cck;
18  int index;
19  };
20 
21  // members
22  int sym_order_; // symplectic order
23  int sym_type_; // symplectic method (Yoshida) solution 1 or 2
24  int cd_pair_array_size_; // cd_pair array size
25  CDPair* cd_pair_; // Ck Dk pair for KDKD... or DKDK...
26  CumSumCkIndex* sorted_cumsum_ck_index_; // increasing order of cumsum ck with index of cd_pair
27 
29 
38  void recursiveSymplecticCofficientsSplit(Float* _ck, const int _n) {
39  if (_n==1) {
40  _ck[0] = 0.5;
41  _ck[1] = 1.0;
42  _ck[2] = 0.5;
43  }
44  else if (_n>1) {
45  // order 2(n-1)
46  recursiveSymplecticCofficientsSplit(_ck, _n-1);
47 
48  // last order array size
49  const int n_size=std::pow(3, _n-1);
50 
51  // backup last order cofficients
52  Float ck_last[n_size];
53  for (int i=0; i<n_size; i++) ck_last[i] = _ck[i];
54 
55  // 2^(1/(2n-1))
56  Float ap = pow(2.0, 1.0/(2*_n-1));
57 
58  Float w[3];
59  w[0] = 1.0/(2.0-ap);
60  w[1] = - ap*w[0];
61  w[2] = w[0];
62 
63  for (int i=0; i<3; i++) {
64  for (int j=0; j<n_size; j++) {
65  _ck[i*n_size+j] = w[i]*ck_last[j];
66  }
67  }
68  }
69  else {
70  std::cerr<<"Error: integrator order should be positive, given value "<<_n<<std::endl;
71  abort();
72  }
73  }
74 
76 
88  void symplecticCofficientsGenerator(CDPair _cd_pair[], CumSumCkIndex _sorted_cumsum_ck_index[], const int _n, const int _cd_pair_size) {
89  if (_n>0) {
90  const int n_size = std::pow(3,_n);
91  Float coff_array[n_size];
92 
93  recursiveSymplecticCofficientsSplit(coff_array, _n);
94 
95  // DKD group number
96  const int n_group= n_size/3;
97 
98  // _cd_pair array size
99  const int k = n_group+1;
100 
101  if(k>_cd_pair_size) {
102  std::cerr<<"Error: _cd_pair array size "<<_cd_pair_size<<" not big enough for order "<<_n<<", required size "<<k<<std::endl;
103  abort();
104  }
105 
106  _cd_pair[0][0] = coff_array[0];
107  _sorted_cumsum_ck_index[0].cck = coff_array[0];
108  _sorted_cumsum_ck_index[0].index = 0;
109  for (int i=0; i<n_group-1; i++) {
110  _cd_pair[i ][1] = coff_array[3*i+1];
111  _cd_pair[i+1][0] = coff_array[3*i+2]+coff_array[3*i+3];
112  _sorted_cumsum_ck_index[i+1].cck = _sorted_cumsum_ck_index[i].cck + _cd_pair[i+1][0];
113  _sorted_cumsum_ck_index[i+1].index = i+1;
114  }
115  _cd_pair[k-2][1] = coff_array[n_size-2];
116  _cd_pair[k-1][0] = coff_array[n_size-1];
117  _cd_pair[k-1][1] = Float(0.0);
118  _sorted_cumsum_ck_index[k-1].cck = _sorted_cumsum_ck_index[k-2].cck + _cd_pair[k-1][0];
119  _sorted_cumsum_ck_index[k-1].index = k-1;
120 
121  std::sort(_sorted_cumsum_ck_index, _sorted_cumsum_ck_index+k, [](const CumSumCkIndex &a, const CumSumCkIndex &b){ return a.cck<b.cck;} );
122 
123  }
124  else if (_n==-3) {
125  if(_cd_pair_size<8) {
126  std::cerr<<"Error: _cd_pair array size "<<_cd_pair_size<<" not big enough for order "<<_n<<", required size "<<8<<std::endl;
127  abort();
128  }
129  // Solution A
130  _cd_pair[0][0] = 0.3922568052387800;
131  _cd_pair[0][1] = 0.7845136104775600;
132  _cd_pair[1][0] = 0.5100434119184585;
133  _cd_pair[1][1] = 0.2355732133593570;
134  _cd_pair[2][0] = -0.4710533854097566;
135  _cd_pair[2][1] = -1.1776799841788701;
136  _cd_pair[3][0] = 0.0687531682525181;
137  _cd_pair[3][1] = 1.3151863206839063;
138  _cd_pair[4][0] = 0.0687531682525181;
139  _cd_pair[4][1] = -1.1776799841788701;
140  _cd_pair[5][0] = -0.4710533854097566;
141  _cd_pair[5][1] = 0.2355732133593570;
142  _cd_pair[6][0] = 0.5100434119184585;
143  _cd_pair[6][1] = 0.7845136104775600;
144  _cd_pair[7][0] = 0.3922568052387800;
145  _cd_pair[7][1] = 0.0000000000000000;
146  _sorted_cumsum_ck_index[0].cck = 0.0976997828427615;
147  _sorted_cumsum_ck_index[0].index = 5;
148  _sorted_cumsum_ck_index[1].cck = 0.3922568052387800;
149  _sorted_cumsum_ck_index[1].index = 0;
150  _sorted_cumsum_ck_index[2].cck = 0.4312468317474820;
151  _sorted_cumsum_ck_index[2].index = 2;
152  _sorted_cumsum_ck_index[3].cck = 0.5000000000000000;
153  _sorted_cumsum_ck_index[3].index = 3;
154  _sorted_cumsum_ck_index[4].cck = 0.5687531682525181;
155  _sorted_cumsum_ck_index[4].index = 4;
156  _sorted_cumsum_ck_index[5].cck = 0.6077431947612200;
157  _sorted_cumsum_ck_index[5].index = 6;
158  _sorted_cumsum_ck_index[6].cck = 0.9023002171572385;
159  _sorted_cumsum_ck_index[6].index = 1;
160  _sorted_cumsum_ck_index[7].cck = 1.0000000000000000;
161  _sorted_cumsum_ck_index[7].index = 7;
162  }
163  else if (_n==-4) {
164  if(_cd_pair_size<16) {
165  std::cerr<<"Error: _cd_pair array size "<<_cd_pair_size<<" not big enough for order "<<_n<<", required size "<<16<<std::endl;
166  abort();
167  }
168  //Solution B
169  _cd_pair[0][0] = 0.4574221231148700;
170  _cd_pair[0][1] = 0.9148442462297400;
171  _cd_pair[1][0] = 0.5842687913979845;
172  _cd_pair[1][1] = 0.2536933365662290;
173  _cd_pair[2][0] = -0.5955794501471254;
174  _cd_pair[2][1] = -1.4448522368604799;
175  _cd_pair[3][0] = -0.8015464361143615;
176  _cd_pair[3][1] = -0.1582406353682430;
177  _cd_pair[4][0] = 0.8899492511272584;
178  _cd_pair[4][1] = 1.9381391376227599;
179  _cd_pair[5][0] = -0.0112355476763650;
180  _cd_pair[5][1] = -1.9606102329754900;
181  _cd_pair[6][0] = -0.9289051917917525;
182  _cd_pair[6][1] = 0.1027998493919850;
183  _cd_pair[7][0] = 0.9056264600894914;
184  _cd_pair[7][1] = 1.7084530707869978;
185  _cd_pair[8][0] = 0.9056264600894914;
186  _cd_pair[8][1] = 0.1027998493919850;
187  _cd_pair[9][0] = -0.9289051917917525;
188  _cd_pair[9][1] = -1.9606102329754900;
189  _cd_pair[10][0] = -0.0112355476763650;
190  _cd_pair[10][1] = 1.9381391376227599;
191  _cd_pair[11][0] = 0.8899492511272584;
192  _cd_pair[11][1] = -0.1582406353682430;
193  _cd_pair[12][0] = -0.8015464361143615;
194  _cd_pair[12][1] = -1.4448522368604799;
195  _cd_pair[13][0] = -0.5955794501471254;
196  _cd_pair[13][1] = 0.2536933365662290;
197  _cd_pair[14][0] = 0.5842687913979845;
198  _cd_pair[14][1] = 0.9148442462297400;
199  _cd_pair[15][0] = 0.4574221231148700;
200  _cd_pair[15][1] = 0.0000000000000000;
201  _sorted_cumsum_ck_index[0].cck = -0.4056264600894914;
202  _sorted_cumsum_ck_index[0].index = 6;
203  _sorted_cumsum_ck_index[1].cck = -0.3554349717486324;
204  _sorted_cumsum_ck_index[1].index = 3;
205  _sorted_cumsum_ck_index[2].cck = -0.0416909145128544;
206  _sorted_cumsum_ck_index[2].index = 13;
207  _sorted_cumsum_ck_index[3].cck = 0.4461114643657291;
208  _sorted_cumsum_ck_index[3].index = 2;
209  _sorted_cumsum_ck_index[4].cck = 0.4574221231148700;
210  _sorted_cumsum_ck_index[4].index = 0;
211  _sorted_cumsum_ck_index[5].cck = 0.4654857206213739;
212  _sorted_cumsum_ck_index[5].index = 10;
213  _sorted_cumsum_ck_index[6].cck = 0.4767212682977390;
214  _sorted_cumsum_ck_index[6].index = 9;
215  _sorted_cumsum_ck_index[7].cck = 0.5000000000000000;
216  _sorted_cumsum_ck_index[7].index = 7;
217  _sorted_cumsum_ck_index[8].cck = 0.5232787317022610;
218  _sorted_cumsum_ck_index[8].index = 5;
219  _sorted_cumsum_ck_index[9].cck = 0.5345142793786261;
220  _sorted_cumsum_ck_index[9].index = 4;
221  _sorted_cumsum_ck_index[10].cck = 0.5425778768851300;
222  _sorted_cumsum_ck_index[10].index = 14;
223  _sorted_cumsum_ck_index[11].cck = 0.5538885356342710;
224  _sorted_cumsum_ck_index[11].index = 12;
225  _sorted_cumsum_ck_index[12].cck = 1.0000000000000000;
226  _sorted_cumsum_ck_index[12].index = 15;
227  _sorted_cumsum_ck_index[13].cck = 1.0416909145128546;
228  _sorted_cumsum_ck_index[13].index = 1;
229  _sorted_cumsum_ck_index[14].cck = 1.3554349717486325;
230  _sorted_cumsum_ck_index[14].index = 11;
231  _sorted_cumsum_ck_index[15].cck = 1.4056264600894914;
232  _sorted_cumsum_ck_index[15].index = 8;
233  }
234  }
235  public:
236 
238  SymplecticStep(): sym_order_(0), sym_type_(0), cd_pair_array_size_(0), cd_pair_(NULL), sorted_cumsum_ck_index_(NULL) {}
239 
241  void clear() {
242  if (cd_pair_array_size_>0) {
243  ASSERT(cd_pair_!=NULL);
244  delete [] cd_pair_;
245  cd_pair_ = NULL;
246  ASSERT(sorted_cumsum_ck_index_!=NULL);
247  delete [] sorted_cumsum_ck_index_;
248  sorted_cumsum_ck_index_ = NULL;
249  cd_pair_array_size_ = 0;
250  }
251  sym_order_ = 0;
252  sym_type_ = 0;
253  }
254 
256 
259  void initialSymplecticCofficients(const int _n) {
260  // if already initialized, clear
261  if(cd_pair_array_size_>0) clear();
262 
263  // calculate cd_pair array size
264  int k = _n/2;
265  if (_n>0) cd_pair_array_size_ = std::pow(3,k-1)+1;
266  else if(_n==-6) cd_pair_array_size_ = 8;
267  else if(_n==-8) cd_pair_array_size_ = 16;
268  else {
269  std::cerr<<"Error: input order "<<_n<<" cannot be generated !\n";
270  abort();
271  }
272 
273  // create new array
274  cd_pair_ = new CDPair[cd_pair_array_size_];
275  sorted_cumsum_ck_index_ = new CumSumCkIndex[cd_pair_array_size_];
276  // generate coefficients
277  symplecticCofficientsGenerator(cd_pair_, sorted_cumsum_ck_index_, k, cd_pair_array_size_);
278 
279  // store the order
280  sym_order_ = _n<0?-_n:_n;
281 
282  // store the symplectic method type
283  sym_type_ = _n<0?2:1;
284  }
285 
287  Float getCK(const int _k) const {
288  ASSERT(_k<cd_pair_array_size_);
289  return cd_pair_[_k][0];
290  }
291 
293  Float getDK(const int _k) const {
294  ASSERT(_k<cd_pair_array_size_);
295  return cd_pair_[_k][1];
296  }
297 
299  int getCDPairSize() const {
300  return cd_pair_array_size_;
301  }
302 
304  int getSortCumSumCKIndex(const int _k) const {
305  return sorted_cumsum_ck_index_[_k].index;
306  }
307 
309  Float getSortCumSumCK(const int _k) const {
310  return sorted_cumsum_ck_index_[_k].cck;
311  }
312 
314 
317  Float calcStepModifyFactorFromErrorRatio(const Float _error_new_over_old) {
318  return pow(_error_new_over_old, Float(1.0/sym_order_));
319  }
320 
322 
325  Float calcErrorRatioFromStepModifyFactor(const Float _step_new_over_old) {
326  return pow(_step_new_over_old, Float(sym_order_));
327  }
328 
330  int getOrder() const {
331  return sym_order_;
332  }
333 
335 
337  void writeBinary(FILE *_fout) {
338  fwrite(this, sizeof(*this),1,_fout);
339  }
340 
342 
344  void readBinary(FILE *_fin) {
345  size_t rcount = fread(this, sizeof(*this), 1, _fin);
346  if (rcount<1) {
347  std::cerr<<"Error: Data reading fails! requiring data number is 1, only obtain "<<rcount<<".\n";
348  abort();
349  }
350 
351  ASSERT(sym_type_==1||sym_type_==2);
352  ASSERT(sym_order_>=0);
353  cd_pair_array_size_ = 0;
354 
355  int sym_n = (sym_type_==2)?-sym_order_:sym_order_;
356  if (sym_order_>0) initialSymplecticCofficients(sym_n);
357  }
358 
360  void print(std::ostream & _fout) const{
361  _fout<<"sym_order : "<<sym_order_<<std::endl
362  <<"sym_type : "<<(sym_type_==1?"Yoshida method 1":"Yoshida method 2")<<std::endl
363  <<"CD_pair_size : "<<cd_pair_array_size_<<std::endl;
364  }
365  };
366 }
AR::SymplecticStep::calcErrorRatioFromStepModifyFactor
Float calcErrorRatioFromStepModifyFactor(const Float _step_new_over_old)
calculate the enstep modify factor based on the order scaling and input energy error ratio
Definition: symplectic_step.h:325
AR::SymplecticStep::getSortCumSumCK
Float getSortCumSumCK(const int _k) const
get sorted cumsum CK
Definition: symplectic_step.h:309
Float.h
AR
Algorithmic regularization (time transformed explicit symplectic integrator) namespace.
Definition: force.h:5
AR::SymplecticStep::getDK
Float getDK(const int _k) const
get coefficient d_k
Definition: symplectic_step.h:293
AR::SymplecticStep::readBinary
void readBinary(FILE *_fin)
read class data with BINARY format and initial the array
Definition: symplectic_step.h:344
AR::SymplecticStep
class to manager symplectic KD steps
Definition: symplectic_step.h:11
AR::SymplecticStep::SymplecticStep
SymplecticStep()
constructor
Definition: symplectic_step.h:238
Float
double Float
Definition: Float.h:25
AR::SymplecticStep::initialSymplecticCofficients
void initialSymplecticCofficients(const int _n)
Symplectic coefficients generation for input order.
Definition: symplectic_step.h:259
AR::SymplecticStep::getSortCumSumCKIndex
int getSortCumSumCKIndex(const int _k) const
get sorted cumsum CK index
Definition: symplectic_step.h:304
AR::SymplecticStep::print
void print(std::ostream &_fout) const
print parameters
Definition: symplectic_step.h:360
AR::SymplecticStep::writeBinary
void writeBinary(FILE *_fout)
write class data with BINARY format
Definition: symplectic_step.h:337
AR::SymplecticStep::calcStepModifyFactorFromErrorRatio
Float calcStepModifyFactorFromErrorRatio(const Float _error_new_over_old)
calculate the step modify factor based on the order scaling and input energy error ratio
Definition: symplectic_step.h:317
AR::SymplecticStep::getCK
Float getCK(const int _k) const
get coefficient c_k
Definition: symplectic_step.h:287
AR::SymplecticStep::getCDPairSize
int getCDPairSize() const
get cd_pair array size
Definition: symplectic_step.h:299
AR::SymplecticStep::clear
void clear()
clear function
Definition: symplectic_step.h:241
AR::SymplecticStep::getOrder
int getOrder() const
get Symplectic order
Definition: symplectic_step.h:330