00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "dyn.h"
00023
00024 #define G_TOL 1.e-6
00025
00026 local real solve3(real a, real b, real c)
00027 {
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 real z = 2*max(pow(abs(c/a), 1.0/3), sqrt(abs(b/a)));
00038 real g = c + z * (b + a*z*z);
00039 real gpr = b + 3*a*z*z;
00040
00041 while (abs(g) > G_TOL) {
00042 z = z - g/gpr;
00043 g = c + z * (b + a*z*z);
00044 gpr = b + 3*a*z*z;
00045 }
00046
00047 return z;
00048 }
00049
00050 #define M_TOL 1.e-4
00051 #define M_ITER_MAX 20
00052
00053 void refine_cluster_mass(dyn *b,
00054 int verbose)
00055 {
00056 if (b->get_external_field() == 0) return;
00057
00058 if (b->get_tidal_field() == 0) {
00059 refine_cluster_mass2(b, verbose);
00060 return;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 vector center, vcenter;
00082 int which = get_std_center(b, center, vcenter);
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 real M_inside = total_mass(b), M = -1, M0 = M_inside;
00093 real r_J, r_x2, r_y2, r_z2, r_max_inside;
00094 int N_inside, iter = 0;
00095
00096 real phi_J;
00097
00098 real M_J, M_x, M_y, M_z;
00099 int N_J, N_x, N_y, N_z;
00100
00101 if (verbose)
00102 cerr << endl << " refine_cluster_mass: getting M by iteration"
00103 << endl << " initial total system mass = " << M_inside
00104 << endl;
00105
00106 while (iter++ < M_ITER_MAX
00107 && M_inside > 0
00108 && abs(M_inside/M - 1) > M_TOL) {
00109
00110 M = M_inside;
00111 M_inside = 0;
00112 M_J = M_x = M_y = M_z = 0;
00113 N_J = N_x = N_y = N_z = 0;
00114
00115 r_J = pow(-M/b->get_alpha1(), 0.3333333);
00116
00117 phi_J = 1.5 * b->get_alpha1() * r_J * r_J;
00118 real r_max = 0;
00119
00120 r_x2 = square(r_J);
00121 r_y2 = square(-M/phi_J);
00122
00123
00124
00125
00126
00127
00128
00129 r_z2 = square(solve3(0.5*b->get_alpha3(), -phi_J, -M));
00130
00131 N_inside = 0;
00132 r_max_inside = 0;
00133
00134 for_all_daughters(dyn, b, bb) {
00135
00136 vector dx = bb->get_pos() - center;
00137
00138 real x = dx[0];
00139 real y = dx[1];
00140 real z = dx[2];
00141 real r = abs(dx);
00142
00143 if (r < r_J) {
00144
00145 N_J++;
00146 M_J += bb->get_mass();
00147
00148 if (r == 0
00149 || -M/r + 0.5 * (b->get_alpha1()*x*x + b->get_alpha3()*z*z)
00150 < phi_J) {
00151 N_inside++;
00152 M_inside += bb->get_mass();
00153 r_max_inside = max(r, r_max_inside);
00154 }
00155
00156 }
00157 r_max = max(r, r_max);
00158
00159
00160
00161 real xy = x*x + y*y;
00162 real xz = x*x + z*z;
00163 real yz = y*y + z*z;
00164
00165 if (xy < r_x2) {
00166 M_x += bb->get_mass();
00167 N_x++;
00168 }
00169 if (xz < r_x2) {
00170 M_x += bb->get_mass();
00171 N_x++;
00172 }
00173
00174 if (yz < r_y2) {
00175 M_y += bb->get_mass();
00176 N_y++;
00177 }
00178 if (xy < r_y2) {
00179 M_y += bb->get_mass();
00180 N_y++;
00181 }
00182
00183 if (yz < r_z2) {
00184 M_z += bb->get_mass();
00185 N_z++;
00186 }
00187 if (xz < r_z2) {
00188 M_z += bb->get_mass();
00189 N_z++;
00190 }
00191 }
00192
00193 M_x /= 2;
00194 N_x /= 2;
00195 M_y /= 2;
00196 N_y /= 2;
00197 M_z /= 2;
00198 N_z /= 2;
00199
00200 #if 0
00201 fprintf(stderr, " %2d ", iter);
00202 PRC(M); PRC(r_J); PRL(r_max);
00203 PRI(8); PRC(N_inside); PRC(M_inside); PRL(r_max_inside);
00204 #endif
00205
00206 }
00207
00208 if (iter >= M_ITER_MAX) {
00209 if (verbose) PRI(2);
00210 cerr << "warning: refine_cluster_mass: too many iterations at time "
00211 << b->get_system_time() << endl;
00212 }
00213
00214 if (verbose)
00215 cerr << " within last zero-velocity surface:"
00216 << " M = " << M_inside << " N = " << N_inside
00217 << endl
00218 << " "
00219 << " r_J = " << r_J << " r_max = " << r_max_inside
00220 << endl
00221 << " within r_J: "
00222 << " M = " << M_J << " N = " << N_J
00223 << endl
00224 << " within r_J (projected): "
00225 << " M = " << M_x << " N = " << N_x
00226 << endl
00227 << " within r_y (projected): "
00228 << " M = " << M_y << " N = " << N_y << " r_y = " << sqrt(r_y2)
00229 << endl
00230 << " within r_z (projected): "
00231 << " M = " << M_z << " N = " << N_z << " r_z = " << sqrt(r_z2)
00232 << endl;
00233
00234
00235
00236
00237
00238 bool disrupted = (M_inside < 0.01*M0);
00239
00240 for_all_daughters(dyn, b, bb) {
00241
00242 vector dx = bb->get_pos() - center;
00243
00244 real x = dx[0];
00245 real z = dx[2];
00246 real r = abs(dx);
00247
00248 bool escaper = true;
00249 if (!disrupted) {
00250 if (r < r_J
00251 && (r == 0 || -M/r + 0.5 * (b->get_alpha1()*x*x
00252 + b->get_alpha3()*z*z) < phi_J))
00253 escaper = false;
00254 }
00255 putiq(bb->get_dyn_story(), "esc", escaper);
00256
00257
00258
00259 if (escaper && !find_qmatch(bb->get_dyn_story(), "t_esc"))
00260 putrq(bb->get_dyn_story(), "t_esc", (real)b->get_system_time());
00261
00262
00263
00264 if (!escaper && find_qmatch(bb->get_dyn_story(), "t_esc"))
00265 rmq(bb->get_dyn_story(), "t_esc");
00266 }
00267 }