00001
00002
00003
00004
00005 #include "dyn.h"
00006
00007 void dbg_message(char* s, dyn* b) {
00008 #ifdef DEBUG
00009 cerr << s << " ";
00010 b->pretty_print_node(cerr); cerr << "\n";
00011 #else
00012 char* dummy_char = s;
00013 dyn* dummy = b;
00014 #endif
00015 }
00016
00017 void dbg_message(char* s, dyn* bj, dyn *bi) {
00018 #ifdef DEBUG
00019 cerr << s << " ";
00020 bj->pretty_print_node(cerr); cerr << "->";
00021 bi->pretty_print_node(cerr); cerr << "\n";
00022 #else
00023 char* dummy_char = s;
00024 dyn* dummy_i = bi;
00025 dyn* dummy_j = bj;
00026 #endif
00027 }
00028
00029 local inline void accumulate_pot_on_work(real mass,
00030 vector d_pos,
00031
00032 real eps2,
00033 real & p) {
00034 real r2inv = 1.0 / (d_pos*d_pos + eps2);
00035 real mrinv = mass * sqrt(r2inv);
00036 p -= mrinv;
00037
00038
00039
00040
00041
00042 }
00043
00044 local void tree_calculate_pot(dyn * bj,
00045 dyn *mask,
00046 dyn *bi,
00047 vector offset_pos,
00048
00049 real eps2,
00050 real & p)
00051 {
00052 if (bj == mask) return;
00053
00054 if (bj->get_oldest_daughter()) {
00055 for_all_daughters(dyn, bj, bb)
00056 tree_calculate_pot(bb, mask, bi,
00057 offset_pos + bb->get_pos(),
00058
00059 eps2, p);
00060 } else {
00061 if (bj != bi)
00062 accumulate_pot_on_work(bj->get_mass(), offset_pos,
00063
00064 eps2, p);
00065 }
00066 }
00067
00068
00069 local void calculate_pot_on_leaf(dyn * bj,
00070 dyn *mask,
00071 dyn *bi,
00072 real eps2,
00073 real & p)
00074 {
00075
00076
00077 vector d_pos;
00078
00079 for(dyn * b = bi; b != bj; b = b->get_parent()){
00080 d_pos -= b->get_pos();
00081
00082 }
00083 tree_calculate_pot(bj, mask, bi,
00084 d_pos,
00085
00086 eps2, p);
00087 }
00088
00089 local real pot_on_node(dyn * bj,
00090 dyn * mask,
00091 dyn * bi,
00092 real eps2)
00093 {
00094
00095
00096
00097 real p = 0;
00098 real mtot = 0;
00099
00100 if (bi->get_oldest_daughter() == NULL) {
00101
00102 calculate_pot_on_leaf(bj, mask, bi, eps2, p);
00103
00104 } else {
00105
00106
00107
00108 real p_daughter;
00109 for_all_daughters(dyn, bi, bd) {
00110 real m_daughter = bd->get_mass();
00111 p_daughter = pot_on_node(bj, mask, bd, eps2);
00112 p += m_daughter * p_daughter;
00113 mtot += m_daughter;
00114 }
00115
00116 real minv = 1/mtot;
00117 p *= minv;
00118 }
00119 return p;
00120 }
00121
00122 local real pot_on_low_level_node(dyn * bi, real eps2)
00123 {
00124
00125
00126 dyn * parent = bi->get_parent();
00127
00128 if (parent->get_oldest_daughter()
00129 ->get_younger_sister()->get_younger_sister())
00130 err_exit("pot_on_low_level_node: not a binary node!");
00131
00132 dyn * sister = bi->get_elder_sister();
00133 if (sister == NULL) sister = bi->get_younger_sister();
00134
00135 return pot_on_node(parent, bi, bi, eps2);
00136 }
00137
00138 local inline real cm_pot_on_node(dyn * bj, dyn * bi, real eps2)
00139 {
00140
00141
00142
00143 real p = 0;
00144 for_all_daughters(dyn, bj, bb)
00145 if (bb != bi)
00146 accumulate_pot_on_work(bb->get_mass(),
00147 bb->get_pos() - bi->get_pos(),
00148
00149 eps2, p);
00150 return p;
00151 }
00152
00153 real pot_on_general_node(dyn * bj, dyn * bi, real eps2, bool cm = false)
00154 {
00155
00156
00157
00158
00159
00160
00161 if (bi->is_top_level_node()) {
00162
00163
00164
00165
00166
00167
00168
00169 if (cm)
00170 return cm_pot_on_node(bj, bi, eps2);
00171 else
00172 return pot_on_node(bj, bi, bi, eps2);
00173
00174 } else
00175
00176 return pot_on_low_level_node(bi, eps2);
00177 }
00178
00179 local void accumulate_energies(dyn * root, dyn * b, real eps2,
00180 real & epot, real & ekin, real & etot,
00181 bool cm = false)
00182 {
00183 if (b->get_oldest_daughter()) {
00184
00185
00186
00187
00188 if (!cm || b->is_root())
00189 for_all_daughters(dyn, b, bb)
00190 accumulate_energies(root, bb, eps2, epot, ekin, etot, cm);
00191
00192 etot = epot + ekin;
00193 }
00194
00195
00196
00197 if (!b->is_root()) {
00198 real m2 = 0.5 * b->get_mass();
00199 epot += m2 * pot_on_general_node(root, b, eps2, cm);
00200 ekin += m2 * square(b->get_vel());
00201 }
00202 }
00203
00204 void calculate_energies(dyn * root, real eps2,
00205 real & epot, real & ekin, real & etot,
00206 bool cm)
00207 {
00208 epot = ekin = etot = 0;
00209 accumulate_energies(root, root, eps2, epot, ekin, etot, cm);
00210 }
00211
00212 void print_recalculated_energies(dyn * b, int mode, real eps2, real e_corr)
00213 {
00214 real epot = 0;
00215 real ekin = 0;
00216 real etot = 0;
00217 static real initial_etot;
00218
00219 if (!b->get_ignore_internal())
00220 accumulate_energies(b, b, eps2, epot, ekin, etot);
00221
00222 cerr << "Energies: " << epot << " " << ekin << " " << etot
00223 << " " << initial_etot;
00224
00225 if (mode) {
00226
00227
00228
00229
00230
00231
00232 real de = (etot - e_corr - initial_etot) / initial_etot;
00233 cerr << " de = " << de << endl;
00234
00235 } else {
00236 initial_etot = etot;
00237 cerr << "\n";
00238 }
00239 }