PeTar
N-body code for collisional gravitational systems
orbit_sampling.hpp
Go to the documentation of this file.
1 #pragma once
2 #include "Common/binary_tree.h"
3 #include <iostream>
4 
7  PS::S32 n_split_; // oribital particle splitting number
8  PS::F64* decca_list_; // d ecca per orbital particle
9  PS::F64* dsin_ecca_list_; // d sin(ecca) per orbital particle
10  PS::F64 decca_; // ecca interval
11 
12  inline PS::F64 calcMeanAnomaly(const PS::F64 _ecca, const PS::F64 _sin_ecca, const PS::F64 _ecc) {
13  return _ecca - _ecc*_sin_ecca;
14  }
15 
16 public:
18 
20  OrbitalSamplingManager(): decca_list_(NULL), dsin_ecca_list_(NULL), decca_(0.0), gravitational_constant(-1.0) {}
21 
23  bool checkParams() {
24  ASSERT(n_split_>=0);
26  if (n_split_>0) {
27  ASSERT(decca_list_!=NULL);
28  ASSERT(dsin_ecca_list_!=NULL);
29  ASSERT(decca_>0.0);
30  }
31  return true;
32  }
33 
35 
40  template <class Tptcl>
41  void createSampleParticles(Tptcl* _ptcl_artificial,
42  COMM::BinaryTree<Tptcl> &_bin) {
43 #ifdef ARTIFICIAL_PARTICLE_DEBUG
44  PS::F64 m_check[2]={0.0,0.0};
45 #endif
46  PS::F64 inverse_twopi = 1.0/(decca_*n_split_);
47  for (int i=0; i<n_split_; i++) {
48  // center_of_mass_shift(*(Tptcl*)&_bin,p,2);
49  // generate particles at different orbitial phase
50  COMM::Binary::orbitToParticle(_ptcl_artificial[2*i], _ptcl_artificial[2*i+1], _bin, decca_*i, gravitational_constant);
51 
52 //#ifdef ARTIFICIAL_PARTICLE_DEBUG
53 // PS::F64 semi_i,ecc_i,r_i,rv_i;
54 // COMM::Binary::particleToSemiEcc(semi_i, ecc_i, r_i, rv_i, _ptcl_artificial[2*i], _ptcl_artificial[2*i+1], gravitational_constant);
55 // if (abs(semi_i-_bin.semi)>1e-10) {
56 // std::cerr<<"semi_i "<<semi_i<<" bin.semi "<<_bin.semi<<std::endl;
57 // abort();
58 // }
59 // assert(abs(ecc_i-_bin.ecc)<1e-10);
60 //#endif
61 
63  //PS::F64vec dvvec= _ptcl_artificial[2*i].vel - _ptcl_artificial[2*i+1].vel;
64  //PS::F64 odv = 1.0/std::sqrt(dvvec*dvvec);
65 
66  PS::F64 mass_member[2]= {_bin.m1, _bin.m2};
67  for (int j=0; j<2; j++) {
68  Tptcl* pj = &_ptcl_artificial[2*i+j];
69 
70  // set mass
71  PS::F64 dmean_anomaly = calcMeanAnomaly(decca_list_[i], dsin_ecca_list_[i], _bin.ecc);
72  pj->mass = mass_member[j] * dmean_anomaly * inverse_twopi;
73 
74  // center_of_mass_correction
75  pj->pos += _bin.pos;
76  pj->vel += _bin.vel;
77 
78 #ifdef ARTIFICIAL_PARTICLE_DEBUG
79  assert(mass_member[j]>0);
80  assert(pj->mass >0);
81  m_check[j] += pj->mass;
82 #endif
83  }
84 #ifdef ARTIFICIAL_PARTICLE_DEBUG
85  PS::F64vec pos_i_cm = (_ptcl_artificial[2*i].mass*_ptcl_artificial[2*i].pos+_ptcl_artificial[2*i+1].mass*_ptcl_artificial[2*i+1].pos)/(_ptcl_artificial[2*i].mass + _ptcl_artificial[2*i+1].mass);
86  assert(abs((pos_i_cm - _bin.pos)*(pos_i_cm - _bin.pos))<1e-10);
87 #endif
88  //mnormal += odv;
89  }
90 
91  // normalized the mass of each particles to keep the total mass the same as c.m. mass
92  //PS::F64 mfactor = 1.0/mnormal;
93  //for (int i=i_start_orb; i<n_pair; i++)
94  // for (int j=0; j<2; j++)
95  // _ptcl_artificial[2*i+j].mass *= mfactor;
96 
97 
98 #ifdef ARTIFICIAL_PARTICLE_DEBUG
99  if(n_split_>0) {
100  assert(abs(m_check[0]-_bin.m1)<1e-10);
101  assert(abs(m_check[1]-_bin.m2)<1e-10);
102  }
103 #endif
104  }
105 
107 
109  void setParticleSplitN(const PS::S32& _n_split) {
110  ASSERT(_n_split>=0);
111  n_split_ = _n_split;
112 
113  // get interval of ecc anomaly
114  if (n_split_>0) {
115  decca_ = 8.0*atan(1.0)/n_split_;
116 
117  // initial array
118  if (decca_list_ !=NULL) delete [] decca_list_;
119  if (dsin_ecca_list_!=NULL) delete [] dsin_ecca_list_;
120 
121  decca_list_ = new PS::F64[n_split_];
122  dsin_ecca_list_ = new PS::F64[n_split_];
123 
124  // calculate ecca boundary
125  PS::F64 ecca_list [n_split_+1];
126  PS::F64 sin_ecca_list[n_split_+1];
127  for (PS::S32 i=0; i<=n_split_; i++) {
128  ecca_list[i] = decca_*i-0.5*decca_;
129  sin_ecca_list[i] = std::sin(ecca_list[i]);
130  }
131  // get ecca interval per orbital particle
132  for (PS::S32 i=0; i<n_split_; i++) {
133  decca_list_[i] = ecca_list [i+1] - ecca_list [i];
134  dsin_ecca_list_[i] = sin_ecca_list[i+1] - sin_ecca_list[i];
135  }
136 #ifdef ARTIFICIAL_PARTICLE_DEBUG
137  PS::F64 decca_sum=0.0;
138  //std::cerr<<"dEcca:";
139  for (PS::S32 i=0; i<n_split_; i++) {
140  //std::cerr<<" "<<decca_list_[i]-dsin_ecca_list_[i];
141  decca_sum += decca_list_[i] - 0.5*dsin_ecca_list_[i];
142  assert(decca_list_[i]-dsin_ecca_list_[i]>=0.0);
143  }
144  ASSERT(abs(decca_sum-decca_*n_split_)<1e-10);
145 #endif
146  }
147  }
148 
151  return n_split_;
152  }
153 
156  return n_split_*2;
157  }
158 
160 
162  void writeBinary(FILE *_fp) {
163  fwrite(&n_split_, sizeof(PS::S32), 1, _fp);
164  fwrite(&gravitational_constant, sizeof(PS::F64), 1, _fp);
165  }
166 
168 
170  void readBinary(FILE *_fin) {
171  PS::S32 n_split;
172  size_t rcount = fread(&n_split, sizeof(PS::S32), 1, _fin);
173  rcount += fread(&gravitational_constant, sizeof(PS::F64), 1, _fin);
174  if (rcount<2) {
175  std::cerr<<"Error: Data reading fails! requiring data number is 2, only obtain "<<rcount<<".\n";
176  abort();
177  }
178  setParticleSplitN(n_split);
179  }
180 
183  if (decca_list_!=NULL) {
184  delete [] decca_list_;
185  decca_list_=NULL;
186  }
187  if (dsin_ecca_list_!=NULL) {
188  delete [] dsin_ecca_list_;
189  dsin_ecca_list_=NULL;
190  }
191  }
192 
194 
197  if (decca_list_!=NULL) {
198  delete [] decca_list_;
199  decca_list_=NULL;
200  }
201  if (dsin_ecca_list_!=NULL) {
202  delete [] dsin_ecca_list_;
203  dsin_ecca_list_=NULL;
204  }
205  setParticleSplitN(_manager.n_split_);
207  return *this;
208  }
209 
211  void print(std::ostream & _fout) const{
212  _fout<<"n_split : "<<n_split_<<std::endl
213  <<"G: : "<<gravitational_constant<<std::endl;
214  }
215 };
OrbitalSamplingManager::gravitational_constant
PS::F64 gravitational_constant
Definition: orbit_sampling.hpp:17
PIKG::S32
int32_t S32
Definition: pikg_vector.hpp:24
PIKG::F64vec
Vector3< F64 > F64vec
Definition: pikg_vector.hpp:167
OrbitalSamplingManager::writeBinary
void writeBinary(FILE *_fp)
write class data to file with binary format
Definition: orbit_sampling.hpp:162
OrbitalSamplingManager::OrbitalSamplingManager
OrbitalSamplingManager()
gravitational constant
Definition: orbit_sampling.hpp:20
PIKG::F64
double F64
Definition: pikg_vector.hpp:17
OrbitalSamplingManager::operator=
OrbitalSamplingManager & operator=(const OrbitalSamplingManager &_manager)
operator =
Definition: orbit_sampling.hpp:196
OrbitalSamplingManager
orbital sampling method for counter force from binary
Definition: orbit_sampling.hpp:6
OrbitalSamplingManager::readBinary
void readBinary(FILE *_fin)
read class data to file with binary format
Definition: orbit_sampling.hpp:170
OrbitalSamplingManager::getParticleSplitN
PS::S32 getParticleSplitN() const
get particle split number
Definition: orbit_sampling.hpp:150
OrbitalSamplingManager::setParticleSplitN
void setParticleSplitN(const PS::S32 &_n_split)
set particle split number
Definition: orbit_sampling.hpp:109
OrbitalSamplingManager::createSampleParticles
void createSampleParticles(Tptcl *_ptcl_artificial, COMM::BinaryTree< Tptcl > &_bin)
create orbit sampling particles
Definition: orbit_sampling.hpp:41
ASSERT
#define ASSERT(expr)
Definition: hard_assert.hpp:238
OrbitalSamplingManager::getParticleN
PS::S32 getParticleN() const
get particle number
Definition: orbit_sampling.hpp:155
OrbitalSamplingManager::~OrbitalSamplingManager
~OrbitalSamplingManager()
destructor
Definition: orbit_sampling.hpp:182
OrbitalSamplingManager::print
void print(std::ostream &_fout) const
print parameters
Definition: orbit_sampling.hpp:211
OrbitalSamplingManager::checkParams
bool checkParams()
check paramters
Definition: orbit_sampling.hpp:23