3 #include "Common/Float.h" 
    4 #include "Common/binary_tree.h" 
    8 #include "Hermite/hermite_particle.h" 
   18     typedef H4::ParticleH4<PtclHard> 
H4Ptcl;
 
   21 #ifdef STELLAR_EVOLUTION 
   22     int stellar_evolution_option;
 
   23     bool stellar_evolution_write_flag;
 
   24     Float time_interrupt_max;
 
   28     std::ofstream fout_sse; 
 
   29     std::ofstream fout_bse; 
 
   32                      stellar_evolution_option(1), stellar_evolution_write_flag(true), time_interrupt_max(NUMERIC_FLOAT_MAX), 
 
   33                      bse_manager(), fout_sse(), fout_bse() {}
 
   36                      stellar_evolution_option(0), stellar_evolution_write_flag(true), time_interrupt_max(NUMERIC_FLOAT_MAX){}
 
   48 #ifdef STELLAR_EVOLUTION 
   49         ASSERT(time_interrupt_max>=0.0);
 
   52         ASSERT(!stellar_evolution_write_flag||(stellar_evolution_write_flag&&fout_sse.is_open()));
 
   53         ASSERT(!stellar_evolution_write_flag||(stellar_evolution_write_flag&&fout_bse.is_open()));
 
   60     void print(std::ostream & _fout)
 const{
 
   61         _fout<<
"eps_sq : "<<
eps_sq<<std::endl
 
   63 #ifdef STELLAR_EVOLUTION 
   64         _fout<<
"SE_opt : "<<stellar_evolution_option<<std::endl;
 
   79         const Float mass1 = _p1.
mass;
 
   80         const Float* pos1 = &_p1.
pos.x;
 
   82         const Float mass2 = _p2.
mass;
 
   83         const Float* pos2 = &_p2.
pos.x;
 
   87         Float gm1m2 = gm1*mass2;
 
   89         Float dr[3] = {pos2[0] -pos1[0],
 
   92         Float r2 = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
   93         Float inv_r = 1.0/sqrt(r2);
 
   94         Float inv_r3 = inv_r*inv_r*inv_r;
 
   96         Float* acc1 = _f1.acc_in;
 
   97         Float* acc2 = _f2.acc_in;
 
  107         Float gmor3_1 = gm2*inv_r3*k;
 
  108         Float gmor3_2 = gm1*inv_r3*k;
 
  110         Float inv_rk = inv_r*kpot;
 
  111         Float gm1or =  gm1*inv_rk;
 
  112         Float gm2or =  gm2*inv_rk;
 
  113         Float gm1m2or = gm1m2*inv_rk;
 
  115         Float gmor3_1 = gm2*inv_r3;
 
  116         Float gmor3_2 = gm1*inv_r3;
 
  118         Float gm1or =  gm1*inv_r;
 
  119         Float gm2or =  gm2*inv_r;
 
  120         Float gm1m2or = gm1m2*inv_r;
 
  123         acc1[0] = gmor3_1 * dr[0];
 
  124         acc1[1] = gmor3_1 * dr[1];
 
  125         acc1[2] = gmor3_1 * dr[2];
 
  129         acc2[0] = - gmor3_2 * dr[0];
 
  130         acc2[1] = - gmor3_2 * dr[1];
 
  131         acc2[2] = - gmor3_2 * dr[2];
 
  139         Float gm1m2or3 = gm1m2*inv_r3*k;
 
  141         Float gm1m2or3 = gm1m2*inv_r3;
 
  143         Float* gtgrad1 = _f1.gtgrad;
 
  144         Float* gtgrad2 = _f2.gtgrad;
 
  145         gtgrad1[0] = gm1m2or3 * dr[0];
 
  146         gtgrad1[1] = gm1m2or3 * dr[1];
 
  147         gtgrad1[2] = gm1m2or3 * dr[2];
 
  149         gtgrad2[0] = - gtgrad1[0];
 
  150         gtgrad2[1] = - gtgrad1[1];
 
  151         gtgrad2[2] = - gtgrad1[2];
 
  158         Float gt_kick_inv = gm1m2or;
 
  173         Float gt_kick_inv = Float(0.0);
 
  175         for (
int i=0; i<_n_particle; i++) {
 
  176             const Float massi = _particles[i].
mass;
 
  177             const Float* posi = &_particles[i].
pos.x;
 
  178             Float* acci = _force[i].acc_in;
 
  179             acci[0] = acci[1] = acci[2] = Float(0.0);
 
  182             Float* gtgradi = _force[i].gtgrad;
 
  183             gtgradi[0] = gtgradi[1] = gtgradi[2] = Float(0.0);
 
  186             Float poti = Float(0.0);
 
  187             Float gtki = Float(0.0);
 
  189             for (
int j=0; j<_n_particle; j++) {
 
  191                 const Float massj = _particles[j].
mass;
 
  192                 const Float* posj = &_particles[j].
pos.x; 
 
  193                 Float dr[3] = {posj[0] -posi[0],
 
  196                 Float r2 = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
  197                 Float inv_r = 1.0/sqrt(r2);
 
  198                 Float inv_r3 = inv_r*inv_r*inv_r;
 
  210                 acci[0] += gmor3 * dr[0];
 
  211                 acci[1] += gmor3 * dr[1];
 
  212                 acci[2] += gmor3 * dr[2];
 
  215                 Float gmimjor3 = massi*gmor3;
 
  216                 gtgradi[0] += gmimjor3 * dr[0];
 
  217                 gtgradi[1] += gmimjor3 * dr[1];
 
  218                 gtgradi[2] += gmimjor3 * dr[2];
 
  225             _epot += poti * massi;
 
  226             gt_kick_inv += gtki * massi;
 
  243         static const Float inv3 = 1.0 / 3.0;
 
  246         const int n_pert = _perturber.neighbor_address.getSize();
 
  247         const int n_pert_single = _perturber.n_neighbor_single;
 
  248         const int n_pert_group = _perturber.n_neighbor_group;
 
  254             auto* pert_adr = _perturber.neighbor_address.getDataAddress();
 
  256             Float xp[n_pert][3], xcm[3], m[n_pert];
 
  258             H4::NBAdr<PtclHard>::Group* ptclgroup[n_pert_group];
 
  260             int n_single_count=0;
 
  262             for (
int j=0; j<n_pert; j++) {
 
  263                 H4::NBAdr<PtclHard>::Single* pertj;
 
  265                 if (pert_adr[j].type==H4::NBType::group) {
 
  266                     pertj = &(((H4::NBAdr<PtclHard>::Group*)pert_adr[j].adr)->cm);
 
  267                     k = n_group_count + n_pert_single;
 
  268                     ptclgroup[n_group_count] = (H4::NBAdr<PtclHard>::Group*)pert_adr[j].adr;
 
  272                     pertj = (H4::NBAdr<PtclHard>::Single*)pert_adr[j].adr;
 
  274                     changeover[n_single_count] = &pertj->changeover;
 
  278                 Float 
dt = time - pertj->time;
 
  280                 xp[k][0] = pertj->pos[0] + 
dt*(pertj->vel[0] + 0.5*
dt*(pertj->acc0[0] + inv3*
dt*pertj->acc1[0]));
 
  281                 xp[k][1] = pertj->pos[1] + 
dt*(pertj->vel[1] + 0.5*
dt*(pertj->acc0[1] + inv3*
dt*pertj->acc1[1]));
 
  282                 xp[k][2] = pertj->pos[2] + 
dt*(pertj->vel[2] + 0.5*
dt*(pertj->acc0[2] + inv3*
dt*pertj->acc1[2]));
 
  287             ASSERT(n_single_count == n_pert_single);
 
  288             ASSERT(n_group_count == n_pert_group);
 
  290             Float 
dt = time - _particle_cm.time;
 
  292             xcm[0] = _particle_cm.pos[0] + 
dt*(_particle_cm.vel[0] + 0.5*
dt*(_particle_cm.acc0[0] + inv3*
dt*_particle_cm.acc1[0]));
 
  293             xcm[1] = _particle_cm.pos[1] + 
dt*(_particle_cm.vel[1] + 0.5*
dt*(_particle_cm.acc0[1] + inv3*
dt*_particle_cm.acc1[1]));
 
  294             xcm[2] = _particle_cm.pos[2] + 
dt*(_particle_cm.vel[2] + 0.5*
dt*(_particle_cm.acc0[2] + inv3*
dt*_particle_cm.acc1[2]));
 
  297             Float acc_pert_cm[3]={0.0, 0.0, 0.0};
 
  301             for (
int i=0; i<_n_particle; i++) {
 
  302                 Float* acc_pert = _force[i].acc_pert;
 
  303                 Float& pot_pert = _force[i].pot_pert;
 
  304                 const auto& pi = _particles[i];
 
  306                 acc_pert[0] = acc_pert[1] = acc_pert[2] = Float(0.0);
 
  310                 xi[0] = pi.pos[0] + xcm[0];
 
  311                 xi[1] = pi.pos[1] + xcm[1];
 
  312                 xi[2] = pi.pos[2] + xcm[2];
 
  315                 for (
int j=0; j<n_pert_single; j++) {
 
  316                     Float dr[3] = {xp[j][0] - xi[0],
 
  319                     Float r2 = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2] + 
eps_sq;
 
  324                     Float gmor3 = gm/r3 * k;
 
  326                     acc_pert[0] += gmor3 * dr[0];
 
  327                     acc_pert[1] += gmor3 * dr[1];
 
  328                     acc_pert[2] += gmor3 * dr[2];
 
  332                 for (
int j=n_pert_single; j<n_pert; j++) {
 
  333                     Float dr[3] = {xp[j][0] - xi[0],
 
  336                     Float r2 = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2] + 
eps_sq;
 
  338                     const int jk = j-n_pert_single;
 
  339                     auto* ptcl_mem = ptclgroup[jk]->getDataAddress();
 
  341                     for (
int k=0; k<ptclgroup[jk]->getSize(); k++) {
 
  347                     acc_pert[0] += gmor3 * dr[0];
 
  348                     acc_pert[1] += gmor3 * dr[1];
 
  349                     acc_pert[2] += gmor3 * dr[2];
 
  353                 acc_pert_cm[0] += pi.mass *acc_pert[0];
 
  354                 acc_pert_cm[1] += pi.mass *acc_pert[1];
 
  355                 acc_pert_cm[2] += pi.mass *acc_pert[2];
 
  365             acc_pert_cm[0] /= mcm;
 
  366             acc_pert_cm[1] /= mcm;
 
  367             acc_pert_cm[2] /= mcm;
 
  370             for (
int i=0; i<_n_particle; i++) {
 
  371                 Float* acc_pert = _force[i].acc_pert;
 
  372                 Float& pot_pert = _force[i].pot_pert;
 
  373                 const auto& pi = _particles[i];
 
  374                 acc_pert[0] -= acc_pert_cm[0]; 
 
  375                 acc_pert[1] -= acc_pert_cm[1];        
 
  376                 acc_pert[2] -= acc_pert_cm[2]; 
 
  378                 pot_pert -= acc_pert[0]*pi.
pos[0] + acc_pert[1]*pi.pos[1] + acc_pert[2]*pi.pos[2];
 
  383                     if (pi.pos*pi.pos<pi.changeover.getRout()*pi.changeover.getRout()) {
 
  395                 for(
int i=0; i<_n_particle; i++) {
 
  396                     Float* acc_pert = _force[i].acc_pert;
 
  397                     Float& pot_pert = _force[i].pot_pert;
 
  398                     const auto& pi = _particles[i];
 
  399                     acc_pert[0] = acc_pert[1] = acc_pert[2] = pot_pert = Float(0.0);
 
  401                     if (pi.pos*pi.pos<pi.changeover.getRout()*pi.changeover.getRout()) {
 
  428         calcAccPert(_force, _particles, _n_particle, _particle_cm, _perturber, _time);
 
  436         Float force2 = _force[0]*_force[0]+_force[1]*_force[1]+_force[2]*_force[2];
 
  437 #ifdef AR_SLOWDOWN_PERT_R4 
  441         return sqrt(force/(_mp*_mpert))*force;
 
  447         Float apo = _bin.semi*(1.0+_bin.ecc);
 
  448         Float apo2 = apo*apo;
 
  449 #ifdef AR_SLOWDOWN_PERT_R4 
  450         return (_bin.m1*_bin.m2)/(apo2*apo2);
 
  452         return (_bin.m1*_bin.m2)/(apo2*apo);
 
  457     static Float 
calcPertFromMR(
const Float _r, 
const Float _mp, 
const Float _mpert) {
 
  459 #ifdef AR_SLOWDOWN_PERT_R4 
  460         return _mp*_mpert/(r2*r2);
 
  462         return (_mp*_mpert)/(r2*_r);
 
  466 #if (defined AR_SLOWDOWN_ARRAY) || (defined AR_SLOWDOWN_TREE) 
  469     void calcSlowDownTimeScale(Float& _t_min_sq, 
const Float dv[3], 
const Float dr[3], 
const Float& r, 
const Float& gm) {
 
  472         Float v2 = dv[0]*dv[0] + dv[1]*dv[1] + dv[2]*dv[2];
 
  473         Float drdv = dr[0]*dv[0] + dr[1]*dv[1] + dr[2]*dv[2];
 
  475         Float semi = 1.0/(2.0/r - v2/gm);
 
  478             _t_min_sq = 
std::min(_t_min_sq, r2/v2);
 
  480             Float ra_fact = (1 - r/semi); 
 
  481             Float e2 = drdv*drdv/(gm*semi) + ra_fact*ra_fact; 
 
  482             Float r_vrmax = semi*(1-e2);
 
  487                 Float vrmax_sq = e2*gm/r_vrmax;
 
  492                 _t_min_sq = 
std::min(_t_min_sq, semi*semi/vrmax_sq);
 
  496                 Float rovr = r2/abs(drdv);
 
  497                 _t_min_sq = 
std::min(_t_min_sq, rovr*rovr);
 
  509     void calcSlowDownPertOne(Float& _pert_out, Float& _t_min_sq, 
const PtclHard& pi, 
const PtclHard& pj) {
 
  510         Float dr[3] = {pj.
pos[0] - pi.
pos[0],
 
  513         Float r2 = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
  517 #ifdef AR_SLOWDOWN_TIMESCALE 
  518         Float dv[3] = {pj.
vel[0] - pi.
vel[0],
 
  525         calcSlowDownTimeScale(_t_min_sq, dv, dr, r, gm);
 
  541     void calcSlowDownPert(Float& _pert_out, Float& _t_min_sq, 
const Float& _time, 
const H4Ptcl& _particle_cm, 
const ARPerturber& _perturber) {
 
  542         static const Float inv3 = 1.0 / 3.0;
 
  544         const int n_pert = _perturber.neighbor_address.getSize();
 
  548             auto* pert_adr = _perturber.neighbor_address.getDataAddress();
 
  551             Float 
dt = _time - _particle_cm.time;
 
  553             xcm[0] = _particle_cm.pos[0] + 
dt*(_particle_cm.vel[0] + 0.5*
dt*(_particle_cm.acc0[0] + inv3*
dt*_particle_cm.acc1[0]));
 
  554             xcm[1] = _particle_cm.pos[1] + 
dt*(_particle_cm.vel[1] + 0.5*
dt*(_particle_cm.acc0[1] + inv3*
dt*_particle_cm.acc1[1]));
 
  555             xcm[2] = _particle_cm.pos[2] + 
dt*(_particle_cm.vel[2] + 0.5*
dt*(_particle_cm.acc0[2] + inv3*
dt*_particle_cm.acc1[2]));
 
  557             Float mcm = _particle_cm.mass;
 
  558             auto& chi = _particle_cm.changeover;
 
  560 #ifdef AR_SLOWDOWN_TIMESCALE 
  564             vcm[0] = _particle_cm.vel[0] + 
dt*(_particle_cm.acc0[0] + 0.5*
dt*_particle_cm.acc1[0]);
 
  565             vcm[1] = _particle_cm.vel[1] + 
dt*(_particle_cm.acc0[1] + 0.5*
dt*_particle_cm.acc1[1]);
 
  566             vcm[2] = _particle_cm.vel[2] + 
dt*(_particle_cm.acc0[2] + 0.5*
dt*_particle_cm.acc1[2]);
 
  569             for (
int j=0; j<n_pert; j++) {
 
  570                 H4::NBAdr<PtclHard>::Single* pertj;
 
  571                 if (pert_adr[j].type==H4::NBType::group) pertj = &(((H4::NBAdr<PtclHard>::Group*)pert_adr[j].adr)->cm);
 
  572                 else pertj = (H4::NBAdr<PtclHard>::Single*)pert_adr[j].adr;
 
  574                 Float 
dt = _time - pertj->time;
 
  576                 xp[0] = pertj->pos[0] + 
dt*(pertj->vel[0] + 0.5*
dt*(pertj->acc0[0] + inv3*
dt*pertj->acc1[0]));
 
  577                 xp[1] = pertj->pos[1] + 
dt*(pertj->vel[1] + 0.5*
dt*(pertj->acc0[1] + inv3*
dt*pertj->acc1[1]));
 
  578                 xp[2] = pertj->pos[2] + 
dt*(pertj->vel[2] + 0.5*
dt*(pertj->acc0[2] + inv3*
dt*pertj->acc1[2]));
 
  580                 Float mj = pertj->mass;
 
  582                 auto& chj = pertj->changeover;
 
  584                 Float dr[3] = {xp[0] - xcm[0],
 
  588                 Float r2 = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2] + 
eps_sq;
 
  593 #ifdef AR_SLOWDOWN_TIMESCALE 
  595                 vp[0] = pertj->vel[0] + 
dt*(pertj->acc0[0] + 0.5*
dt*pertj->acc1[0]);
 
  596                 vp[1] = pertj->vel[1] + 
dt*(pertj->acc0[1] + 0.5*
dt*pertj->acc1[1]);
 
  597                 vp[2] = pertj->vel[2] + 
dt*(pertj->acc0[2] + 0.5*
dt*pertj->acc1[2]);
 
  599                 Float dv[3] = {vp[0] - vcm[0],
 
  606                 calcSlowDownTimeScale(_t_min_sq, dv, dr, r, gm);
 
  612         _pert_out += _perturber.soft_pert_min;
 
  624     template <
class Tparticle>
 
  626 #ifdef STELLAR_EVOLUTION 
  636         if (_p.time_interrupt<=_time_end&&stellar_evolution_option>0) {
 
  642             Float 
dt = _time_end - _p.time_record;
 
  647             int event_flag = bse_manager.
evolveStar(_p.star, output, 
dt);
 
  651                 std::cerr<<
"SSE Error: ID= "<<_p.id;
 
  652                 _p.star.print(std::cerr);
 
  653                 output.
print(std::cerr);
 
  654                 std::cerr<<std::endl;
 
  656                 std::cout<<std::flush;
 
  657                 std::cerr<<std::flush;
 
  662             double dt_miss = bse_manager.
getDTMiss(output);
 
  663             _p.time_record += 
dt-dt_miss;
 
  671             if (dm==0.0) modify_flag = 0;
 
  674             _p.mass = bse_manager.
getMass(_p.star);
 
  680             if (stellar_evolution_write_flag&&event_flag>=1) {
 
  683                     fout_sse<<
"Type_change ";
 
  698                 for (
int k=0; k<3; k++) _p.vel[k] += dv[k];
 
  700                 if (stellar_evolution_write_flag) {
 
  713                 _p.group_data.artificial.setParticleTypeToUnused(); 
 
  721 #endif // STELLAR_EVOLUTION 
  732         int modify_return = 0;
 
  733 #ifdef STELLAR_EVOLUTION 
  734         int modify_branch[2];
 
  735         if (_bin.getMemberN()>2) {
 
  736             for (
int k=0; k<2; k++) {
 
  737                 if (_bin.isMemberTree(k)) {
 
  739                     modify_return = 
std::max(modify_return, modify_branch[k]);
 
  743                 else if (stellar_evolution_option>0) {
 
  745                     modify_branch[k] = 
modifyOneParticle(*_bin.getMember(k), _bin.getMember(k)->time_record, _bin_interrupt.time_now);
 
  746                     modify_return = 
std::max(modify_return, modify_branch[k]);
 
  748                     if (modify_branch[k]>0&&_bin_interrupt.status == AR::InterruptStatus::none) {
 
  749                         _bin_interrupt.status = AR::InterruptStatus::change;
 
  750                         _bin_interrupt.adr = &_bin;
 
  756             if (modify_branch[0]>0&&modify_branch[1]>0) {
 
  757                 _bin_interrupt.adr = &_bin;
 
  759             if (_bin_interrupt.status == AR::InterruptStatus::destroy) {
 
  761                 if (!(modify_branch[0]==3&&modify_branch[1]==3))
 
  762                     _bin_interrupt.status = AR::InterruptStatus::merge;
 
  766             auto* p1 = _bin.getLeftMember();
 
  767             auto* p2 = _bin.getRightMember();
 
  769             COMM::Vector3<Float> pos_red(p2->pos[0] - p1->pos[0], p2->pos[1] - p1->pos[1], p2->pos[2] - p1->pos[2]);
 
  770             COMM::Vector3<Float> vel_red(p2->vel[0] - p1->vel[0], p2->vel[1] - p1->vel[1], p2->vel[2] - p1->vel[2]);
 
  771             Float drdv = pos_red * vel_red;
 
  774             auto postProcess =[&](
StarParameterOut* out, Float* pos_cm, Float*vel_cm, Float& semi, Float& ecc, 
int binary_type_final) {
 
  776                 if (_bin_interrupt.status == AR::InterruptStatus::none) 
 
  777                     _bin_interrupt.status = AR::InterruptStatus::change;
 
  782                 p1->time_record = _bin_interrupt.time_now - bse_manager.
getDTMiss(out[0]);
 
  783                 p2->time_record = _bin_interrupt.time_now - bse_manager.
getDTMiss(out[1]);
 
  786                 p1->time_interrupt = 
std::min(p1->time_record + bse_manager.
getTimeStepBinary(p1->star, p2->star, semi, ecc, binary_type_final), time_interrupt_max);
 
  787                 p2->time_interrupt = p1->time_interrupt;
 
  807                 p1->mass = bse_manager.
getMass(p1->star);
 
  808                 p2->mass = bse_manager.
getMass(p2->star);
 
  815                 bool mass_zero_flag = 
false;
 
  818                 if (p1->mass==0.0&&p2->mass==0.0) {
 
  819                     p1->group_data.artificial.setParticleTypeToUnused(); 
 
  820                     p2->group_data.artificial.setParticleTypeToUnused(); 
 
  821                     _bin_interrupt.status = AR::InterruptStatus::destroy;
 
  823                     mass_zero_flag = 
true;
 
  828                         p1->group_data.artificial.setParticleTypeToUnused(); 
 
  829                         _bin_interrupt.status = AR::InterruptStatus::merge;
 
  833                         for (
int k=0; k<3; k++) {
 
  834                             p2->pos[k] = pos_cm[k];
 
  835                             p2->vel[k] = vel_cm[k];
 
  838                         mass_zero_flag = 
true;
 
  842                         p2->group_data.artificial.setParticleTypeToUnused(); 
 
  843                         _bin_interrupt.status = AR::InterruptStatus::merge;
 
  847                         for (
int k=0; k<3; k++) {
 
  848                             p1->pos[k] = pos_cm[k];
 
  849                             p1->vel[k] = vel_cm[k];
 
  852                         mass_zero_flag = 
true;
 
  856                     bool kick_flag=
false;
 
  857                     for (
int k=0; k<2; k++) {
 
  859                         auto* pk = _bin.getMember(k);
 
  873                             for (
int k=0; k<3; k++) pk->vel[k] += dv[k];
 
  877                     if (!kick_flag && !mass_zero_flag) {
 
  879                         if (ecc>=0.0&&ecc<=1.0) {
 
  904                             if(_bin.semi>0) _bin.semi = -_bin.semi;
 
  920                 if (mass_zero_flag) {
 
  926             bool check_flag = 
false;
 
  927             if (stellar_evolution_option>0) {
 
  928                 int binary_type_p1 = 
static_cast<int>(p1->getBinaryInterruptState());
 
  929                 int binary_type_p2 = 
static_cast<int>(p2->getBinaryInterruptState());
 
  930                 int binary_type_init = 0;
 
  931                 if (binary_type_p1==binary_type_p2) binary_type_init = binary_type_p1;
 
  934                 double time_check = 
std::min(p1->time_interrupt, p2->time_interrupt);
 
  935                 Float 
dt = _bin_interrupt.time_now - 
std::max(p1->time_record,p2->time_record);
 
  936                 if (time_check<=_bin_interrupt.time_now&&dt>0) check_flag = 
true;
 
  940                     Float t_record_min = 
std::min(p1->time_record,p2->time_record);
 
  943                     if (t_record_min<_bin_interrupt.time_now&&_bin.semi>0 && (!bse_manager.
isMassTransfer(binary_type_init)) && (!bse_manager.
isDisrupt(binary_type_init))) {
 
  944                         check_flag=bse_manager.
isCallBSENeeded(p1->star, p2->star, _bin.semi, _bin.ecc, 
dt);
 
  951                     _bin_interrupt.adr = &_bin;
 
  954                     if (p1->time_record!=p2->time_record) {
 
  955                         if (p1->time_record<p2->time_record) {
 
  956                             p1->time_interrupt = p1->time_record;
 
  960                             p2->time_interrupt = p2->time_record;
 
  964                     Float 
dt = _bin_interrupt.time_now - 
std::max(p1->time_record,p2->time_record);
 
  969                     Float ecc = _bin.ecc;
 
  971                     Float semi = _bin.semi;
 
  973                     Float mtot = p1->mass+p2->mass;
 
  974                     Float period = _bin.period;
 
  978                     Float pos_cm[3], vel_cm[3];
 
  979                     for (
int k=0; k<3; k++) {
 
  980                         pos_cm[k] = (p1->mass*p1->pos[k] + p2->mass*p2->pos[k])/mtot;
 
  981                         vel_cm[k] = (p1->mass*p1->vel[k] + p2->mass*p2->vel[k])/mtot;
 
  989                     int event_flag = bse_manager.
evolveBinary(p1->star, p2->star, out[0], out[1], semi, period, ecc, bin_event, binary_type_init, 
dt);
 
  993                         std::cerr<<
"BSE Error! ";
 
  994                         std::cerr<<
" ID="<<p1->id<<
" "<<p2->id<<
" ";
 
  995                         std::cerr<<
" semi[R*]: " 
  996                                  <<_bin.semi*bse_manager.
rscale 
  999                         std::cerr<<
" Init: Star1: ";
 
 1000                         p1_star_bk.
print(std::cerr);
 
 1001                         std::cerr<<
" Star2: ";
 
 1002                         p2_star_bk.
print(std::cerr);
 
 1003                         std::cerr<<
" final: Star1: ";
 
 1004                         p1->star.print(std::cerr);
 
 1005                         out[0].
print(std::cerr);
 
 1006                         std::cerr<<
" Star2: ";
 
 1007                         p2->star.print(std::cerr);
 
 1008                         out[1].
print(std::cerr);
 
 1009                         std::cerr<<std::endl;
 
 1012                         std::cout<<std::flush;
 
 1013                         std::cerr<<std::flush;
 
 1018                     int binary_type_final=0;
 
 1021                     for (
int i=0; i<nmax; i++) {
 
 1022                         int binary_type = bin_event.
getType(i);
 
 1023                         if (binary_type>0) {
 
 1024                             bool first_event = (i==0);
 
 1025                             if (stellar_evolution_write_flag) {
 
 1026                                 if ((first_event&&binary_type_init!=binary_type)||!first_event) {
 
 1028 #pragma omp critical 
 1035                                         fout_bse<<std::endl;
 
 1049                             if (binary_type>0) event_flag = 
std::max(event_flag, 1); 
 
 1051                             else if (bse_manager.
isDisrupt(binary_type)) event_flag = 
std::max(event_flag, 3); 
 
 1052                             else if (bse_manager.
isMerger(binary_type)) event_flag = 
std::max(event_flag, 4); 
 
 1053                             binary_type_final = binary_type;
 
 1055                         else if(binary_type<0) 
break;
 
 1059                     mtot = bse_manager.
getMass(p1->star) + bse_manager.
getMass(p2->star);
 
 1062                     postProcess(out, pos_cm, vel_cm, semi, ecc, binary_type_final);
 
 1068             if (_bin_interrupt.status!=AR::InterruptStatus::merge&&_bin_interrupt.status!=AR::InterruptStatus::destroy) {
 
 1070                 auto merge = [&](
const Float& dr, 
const Float& t_peri, 
const Float& sd_factor) {
 
 1071                     _bin_interrupt.adr = &_bin;
 
 1079                     if (stellar_evolution_option>0) {
 
 1080                         if (p1->time_record<_bin_interrupt.time_now) {
 
 1081                             p1->time_interrupt = p1->time_record; 
 
 1084                         if (p2->time_record<_bin_interrupt.time_now) {
 
 1085                             p2->time_interrupt = p2->time_record; 
 
 1089                         ASSERT(p1->star.tphys==p2->star.tphys);
 
 1094                         Float pos_cm[3], vel_cm[3];
 
 1095                         Float mtot = p1->mass+p2->mass;
 
 1097                         for (
int k=0; k<3; k++) {
 
 1098                             pos_cm[k] = (p1->mass*p1->pos[k] + p2->mass*p2->pos[k])/mtot;
 
 1099                             vel_cm[k] = (p1->mass*p1->vel[k] + p2->mass*p2->vel[k])/mtot;
 
 1102                         p1_star_bk = p1->star;
 
 1103                         p2_star_bk = p2->star;
 
 1105                         Float semi = _bin.semi;
 
 1106                         Float ecc = _bin.ecc;
 
 1107                         bse_manager.
merge(p1->star, p2->star, out[0], out[1], semi, ecc);
 
 1109                         postProcess(out, pos_cm, vel_cm, semi, ecc, 0);
 
 1110                         if (stellar_evolution_write_flag&&(p1->mass==0.0||p2->mass==0.0)) {
 
 1111 #pragma omp critical 
 1113                                 fout_bse<<
"Dynamic_merge: " 
 1119 #ifndef DYNAMIC_MERGER_LESS_OUTPUT 
 1130                                 fout_bse<<std::endl;
 
 1137 #else //not BSE_BASE 
 1139                     std::cerr<<
"Binary Merge: time: "<<_bin_interrupt.time_now<<std::endl;
 
 1140                     _bin.Binary::printColumnTitle(std::cerr);
 
 1143                     std::cerr<<std::endl;
 
 1144                     _bin.Binary::printColumn(std::cerr);
 
 1147                     std::cerr<<std::endl;
 
 1152                     p1->time_record = _bin_interrupt.time_now;
 
 1153                     p2->time_record = _bin_interrupt.time_now;
 
 1156                     Float mcm = p1->mass + p2->mass;
 
 1157                     for (
int k=0; k<3; k++) {
 
 1158                         p1->pos[k] = (p1->mass*p1->pos[k] + p2->mass*p2->pos[k])/mcm;
 
 1159                         p1->vel[k] = (p1->mass*p1->vel[k] + p2->mass*p2->vel[k])/mcm;
 
 1169                     if (_bin_interrupt.status == AR::InterruptStatus::none) 
 
 1170                         _bin_interrupt.status = AR::InterruptStatus::merge;
 
 1176                     p2->group_data.artificial.setParticleTypeToUnused(); 
 
 1185                     (p1->time_interrupt<_bin_interrupt.time_now && p2->time_interrupt<_bin_interrupt.time_now) &&
 
 1186                     (p1->getBinaryPairID()==p2->id||p2->getBinaryPairID()==p1->id)) {
 
 1187                     Float dr[3] = {p1->pos[0] - p2->pos[0], 
 
 1188                                    p1->pos[1] - p2->pos[1], 
 
 1189                                    p1->pos[2] - p2->pos[2]};
 
 1190                     Float dr2  = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
 1191                     merge(std::sqrt(dr2), 0.0, 1.0);
 
 1195                     Float radius = p1->radius + p2->radius;
 
 1198                     if (_bin.slowdown.getSlowDownFactor()>1.0) {
 
 1201                         _bin.particleToSemiEcc(_bin.semi, _bin.ecc, _bin.r, drdv, *_bin.getLeftMember(), *_bin.getRightMember(), 
gravitational_constant);
 
 1202                         Float peri = _bin.semi*(1 - _bin.ecc);
 
 1203                         if (peri<radius && p1->getBinaryPairID()!=p2->id&&p2->getBinaryPairID()!=p1->id) {
 
 1204                             Float ecc_anomaly  = _bin.calcEccAnomaly(_bin.r);
 
 1205                             Float mean_anomaly = _bin.calcMeanAnomaly(ecc_anomaly, _bin.ecc);
 
 1207                             Float t_peri = mean_anomaly/mean_motion;
 
 1208                             if (drdv<0 && t_peri<_bin_interrupt.time_end-_bin_interrupt.time_now) {
 
 1209                                 Float dr[3] = {p1->pos[0] - p2->pos[0], 
 
 1210                                                p1->pos[1] - p2->pos[1], 
 
 1211                                                p1->pos[2] - p2->pos[2]};
 
 1212                                 Float dr2  = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
 1213                                 merge(std::sqrt(dr2), t_peri, _bin.slowdown.getSlowDownFactor());
 
 1215                             else if (_bin.semi>0||(_bin.semi<0&&drdv<0)) {
 
 1216                                 p1->setBinaryPairID(p2->id);
 
 1217                                 p2->setBinaryPairID(p1->id);
 
 1220                                 p1->time_interrupt = 
std::min(_bin_interrupt.time_now + drdv<0 ? t_peri : (_bin.period - t_peri), time_interrupt_max);
 
 1221                                 p2->time_interrupt = p1->time_interrupt;
 
 1227                         Float dr[3] = {p1->pos[0] - p2->pos[0], 
 
 1228                                        p1->pos[1] - p2->pos[1], 
 
 1229                                        p1->pos[2] - p2->pos[2]};
 
 1230                         Float dr2  = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
 1231                         if (dr2<radius*radius) merge(std::sqrt(dr2), 0.0, 1.0);
 
 1235                     if (_bin.semi<0.0) {
 
 1236                         Float dr[3] = {p1->pos[0] - p2->pos[0], 
 
 1237                                        p1->pos[1] - p2->pos[1], 
 
 1238                                        p1->pos[2] - p2->pos[2]};
 
 1239                         Float dr2  = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
 1240                         if (dr2<radius*radius) merge(std::sqrt(dr2), 0.0, 1.0);
 
 1248                 if (stellar_evolution_option==2 && p1->mass>0 && p2->mass>0) {
 
 1250                         if (p1->getBinaryInterruptState() == BinaryInterruptState::tide) {
 
 1253                         if (p2->getBinaryInterruptState() == BinaryInterruptState::tide) {
 
 1258                         int binary_type_p1 = 
static_cast<int>(p1->getBinaryInterruptState());
 
 1259                         int binary_type_p2 = 
static_cast<int>(p2->getBinaryInterruptState());
 
 1260                         long long int pair_id1 = p1->getBinaryPairID();
 
 1261                         long long int pair_id2 = p2->getBinaryPairID();
 
 1262                         bool tide_flag = 
true;
 
 1263                         if ((binary_type_p1 != binary_type_p2) || (pair_id1 != p2->id) || (pair_id2 != p1->id)) tide_flag = 
false;
 
 1265                                  || bse_manager.
isMerger(binary_type_p1) 
 
 1266                                  || bse_manager.
isDisrupt(binary_type_p1)
 
 1267                                  || binary_type_p1 == 14)
 
 1270                         bool change_flag=
false;
 
 1272                             Float poly_type1=0, poly_type2=0;
 
 1273                             Float Etid=0, Ltid=0;
 
 1274                             Float semi = _bin.semi;
 
 1275                             Float ecc  = _bin.ecc;
 
 1278                             if (p1->star.kw>=10&&p1->star.kw<15&&p2->star.kw>=10&&p2->star.kw<15) {
 
 1282                                         Float dr[3] = {p1->pos[0] - p2->pos[0], 
 
 1283                                                        p1->pos[1] - p2->pos[1], 
 
 1284                                                        p1->pos[2] - p2->pos[2]};
 
 1285                                         Float dr2  = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2];
 
 1286                                         merge(std::sqrt(dr2), 0.0, 1.0);
 
 1288                                     else change_flag = 
true;
 
 1291                             else if (
std::min(p1->star.kw, p2->star.kw)<13) {
 
 1292                                 poly_type1 = (p1->star.kw<=2) ? 3.0 : 1.5;
 
 1293                                 poly_type2 = (p2->star.kw<=2) ? 3.0 : 1.5;
 
 1295                                 change_flag = (Etid>0);
 
 1297                                 Float sd_factor_ext = _bin.slowdown.getSlowDownFactor() - 1.5;
 
 1298                                 if (change_flag && sd_factor_ext>0) {
 
 1299                                     for (Float k=0; k<sd_factor_ext; k=k+1.0) {
 
 1301                                         if (etid_k==0) 
break;
 
 1309                                 _bin_interrupt.adr = &_bin;
 
 1312                                 if (_bin_interrupt.status == AR::InterruptStatus::none) 
 
 1313                                     _bin_interrupt.status = AR::InterruptStatus::change;
 
 1315                                 p1->pos += _bin.pos;
 
 1316                                 p2->pos += _bin.pos;
 
 1317                                 p1->vel += _bin.vel;
 
 1318                                 p2->vel += _bin.vel;
 
 1320                                 p1->setBinaryPairID(p2->id);
 
 1321                                 p2->setBinaryPairID(p1->id);
 
 1322                                 p1->setBinaryInterruptState(BinaryInterruptState::tide);
 
 1323                                 p2->setBinaryInterruptState(BinaryInterruptState::tide);
 
 1327 #pragma omp critical 
 1344                                     _bin.BinarySlowDown::printColumn(fout_bse, 
WRITE_WIDTH);
 
 1347                                     fout_bse<<std::endl;
 
 1358         return modify_return;
 
 1367         return _ekin_minus_etot;
 
 1374     Float 
calcH(Float _ekin_minus_etot, Float _epot) {
 
 1375         return log(_ekin_minus_etot) - log(-_epot);
 
 1383         fwrite(&
eps_sq, 
sizeof(Float),1,_fp);
 
 1385 #ifdef STELLAR_EVOLUTION 
 1386         fwrite(&stellar_evolution_option, 
sizeof(
int),1,_fp);
 
 1387         fwrite(&stellar_evolution_write_flag, 
sizeof(
bool),1,_fp);
 
 1395         size_t rcount = fread(&
eps_sq, 
sizeof(Float),1,_fin);
 
 1398             std::cerr<<
"Error: Data reading fails! requiring data number is 2, only obtain "<<rcount<<
".\n";
 
 1401 #ifdef STELLAR_EVOLUTION 
 1402         rcount += fread(&stellar_evolution_option, 
sizeof(
int),1,_fin);
 
 1403         rcount += fread(&stellar_evolution_write_flag, 
sizeof(
bool),1,_fin);
 
 1405             std::cerr<<
"Error: Data reading fails! requiring data number is 4, only obtain "<<rcount<<
".\n";