void find_parents(int64_t ngroups) { int64_t i, j, *halo_order = NULL; struct fast3tree_results *nearest; struct fast3tree *halo_tree; FAST3TREE_TYPE *h1, *h2; float max_dist = BOX_SIZE/2.01, range; halo_order = check_realloc(halo_order, sizeof(int64_t)*ngroups, "Allocating halo order."); halo_tree = fast3tree_init(ngroups, GROUP_LIST); for (i=0; i<ngroups; i++) { GROUP_LIST[i].parent = -1; halo_order[i] = i; } qsort(halo_order, ngroups, sizeof(int64_t), sort_halo_order); nearest = fast3tree_results_init(); for (i=0; i<ngroups; i++) { h1 = &(GROUP_LIST[halo_order[i]]); range = h1->RADIUS*RADIUS_CONVERSION; if (max_dist < range) range = max_dist; fast3tree_find_sphere_periodic(halo_tree, nearest, h1->pos, range); for (j=0; j<nearest->num_points; j++) { h2 = nearest->points[j]; if (h2->RADIUS < h1->RADIUS) h2->parent = h1->id; } } fast3tree_results_free(nearest); fast3tree_free(&halo_tree); free(halo_order); }
void load_previous_halos(int64_t snap, int64_t chunk, float *bounds) { int64_t rchunk; struct binary_output_header bh; float overlap_region[6]; num_prev_halos = 0; prev_snap = snap-1; if (!phtree) { phtree = fast3tree_init(num_prev_halos, ph); phtree_results = fast3tree_results_init(); } else fast3tree_rebuild(phtree, num_prev_halos, ph); if (snap == STARTING_SNAP || LIGHTCONE || !PARALLEL_IO) return; prev_halo_buffer = check_realloc(prev_halo_buffer, sizeof(struct halo)*PREV_HALO_BUFFER_SIZE, "Allocating previous halo buffer."); for (rchunk = 0; rchunk < NUM_WRITERS; rchunk++) { load_binary_header(snap-1, rchunk, &bh); if (!bounds || bounds_overlap(bh.bounds, bounds, overlap_region, OVERLAP_LENGTH)) load_prev_binary_halos(snap-1, rchunk, bounds, chunk); } prev_halo_buffer = check_realloc(prev_halo_buffer, 0, "Freeing previous halo buffer."); fast3tree_rebuild(phtree, num_prev_halos, ph); }
static PyObject * uberseg_tree(PyObject* self, PyObject* args) { int x=0,y=0,k=0,segmin=0; float dmin=0,r=0,dx=0,d=0; float pos[2],fac=0; PyObject* seg = NULL; PyObject* weight = NULL; int Nx; int Ny; int object_number; PyObject* obj_inds_x = NULL; PyObject* obj_inds_y = NULL; int Ninds; int *ptrx,*ptry,*ptrs; float *ptrw; struct mytype *obj = NULL; struct fast3tree *tree = NULL; struct fast3tree_results *res = NULL; if (!PyArg_ParseTuple(args, (char*)"OOiiiOOi", &seg, &weight, &Nx, &Ny, &object_number, &obj_inds_x, &obj_inds_y, &Ninds)) { return NULL; } obj = (struct mytype *)malloc(sizeof(struct mytype)*Ninds); if(obj == NULL) exit(1); for(k=0;k<Ninds;++k) { ptrx = (int*)PyArray_GETPTR1(obj_inds_x,k); ptry = (int*)PyArray_GETPTR1(obj_inds_y,k); ptrs = (int*)PyArray_GETPTR2(seg,*ptrx,*ptry); obj[k].idx = k; obj[k].seg = *ptrs; obj[k].pos[0] = (float)(*ptrx); obj[k].pos[1] = (float)(*ptry); } tree = fast3tree_init(Ninds,obj); if(tree == NULL) exit(1); res = fast3tree_results_init(); if(res == NULL) exit(1); float maxr = 1.1*sqrt(Nx*Nx+Ny*Ny); for(x=0;x<Nx;++x) { for(y=0;y<Ny;++y) { //shortcuts ptrs = (int*)PyArray_GETPTR2(seg,x,y); if(*ptrs == object_number) continue; if(*ptrs > 0 && *ptrs != object_number) { ptrw = (float*)PyArray_GETPTR2(weight,x,y); *ptrw = 0.0; continue; } //must do search pos[0] = (float)x; pos[1] = (float)y; r = fast3tree_find_next_closest_distance(tree,res,pos); fac = 1.0/1.1; do { fac *= 1.1; fast3tree_results_clear(res); fast3tree_find_sphere(tree,res,pos,r*fac); } while(res->num_points == 0 && r*fac <= maxr); segmin = -1; for(k=0;k<res->num_points;++k) { dx = res->points[k]->pos[0]-x; d = dx*dx; dx = res->points[k]->pos[1]-y; d += dx*dx; if(segmin == -1 || d < dmin) { segmin = res->points[k]->seg; dmin = d; } } if(segmin == -1) { continue; } if(segmin != object_number) { ptrw = (float*)PyArray_GETPTR2(weight,x,y); *ptrw = 0.0; } } } free(obj); fast3tree_free(&tree); fast3tree_results_free(res); Py_INCREF(Py_None); return Py_None; }
/* special_step = 1 (first step), 0 (normal step), -1 (last step) */ void do_timestep(double a1, double a2, double a3, int special_step) { int i,j; float dt = (scale_to_years(a3) - scale_to_years(a2))/1.0e6; //In Myr float old_dt = (scale_to_years(a2) - scale_to_years(a1))/1.0e6; //In Myr float range, av_a = (a2+a3)/2.0; float inv_rs, r,m, dx, dy, dz, r3, acc, rsoft2, inv_rs2, softening_factor; float dvx, dvy, dvz, vorb, coulomb, lnc, dens, rd; struct fast3tree_results *nearest; struct min_halo *h1, *h2; float vel_dt = dt * 1.02268944e-6 * h0 / av_a; //1 km/s to comoving Mpc/Myr/h float max_dist = box_size / 2.0; // 1 km/s / Myr to comoving Mpc/Myr^2/h float acc_dt2 = (dt*dt / 2.0) * 1.02268944e-6 * h0 / av_a; float conv_const = av_a*av_a / h0 / h0; //Update intermediate velocities if (special_step != 1) { //If we're not at the first step. for (i=0; i<num_halos; i++) { h1 = &(halos[i]); for (j=0; j<3; j++) { h1->vel[j] += h1->a[j]*old_dt*0.5; h1->a[j] = 0; } } } if (special_step<0) return; //Return if this is the final step. //Calculate accelerations fast3tree_rebuild(halo_tree, num_halos, halos); set_tree_maxmin(); nearest = fast3tree_results_init(); for (i=0; i<num_halos; i++) { h1 = &(halos[i]); range = halo_grav_range(h1->mvir/h0, dt)*h0/av_a; //In comoving Mpc/h if (max_dist < range) range = max_dist*0.99; assert(fast3tree_find_sphere_periodic(halo_tree, nearest, h1->pos, range)); if (!nearest->num_points) continue; //Skip if no close halos. inv_rs = 1.0/h1->rs; //In comoving h/Mpc for (j=0; j<nearest->num_points; j++) { //Calculate gravitational forces h2 = nearest->points[j]; #define DIST(a,b) a = h1->b - h2->b; \ if (a > max_dist) a-=box_size; \ else if (a < -max_dist) a+=box_size; DIST(dx,pos[0]); DIST(dy,pos[1]); DIST(dz,pos[2]); #undef DIST r = sqrtf(dx*dx + dy*dy + dz*dz); // in comoving Mpc/h //Including acorr slightly improves velocity results // as a function of redshift. m = h1->mass_factor*ff_cached(r*inv_rs); //In Msun //Apply force softening: rsoft2 = r*r + h2->rvir*h2->rvir*1.0e-6; r3 = rsoft2 * r * conv_const; //in (real Mpc)^2 * (comoving Mpc/h) acc = r ? Gc*m/r3 : 0; //In km/s / Myr / (comoving Mpc/h) h2->a[0] += acc*dx; //In km/s / Myr h2->a[1] += acc*dy; h2->a[2] += acc*dz; if (h2->id == 12) { print_halo(i); printf("R: %f Acc: %e Dx: %f Dy: %f Dz: %f\n", r, acc, dx, dy, dz); } } } fast3tree_results_free(nearest); //Update halo velocities if (special_step != 1) { //If not at the first step for (i=0; i<num_halos; i++) { h1 = &(halos[i]); for (j=0; j<3; j++) h1->vel[j] += h1->a[j]*dt*0.5; } } //Calculate new positions for (i=0; i<num_halos; i++) { h1 = &(halos[i]); for (j=0; j<3; j++) { h1->pos[j] += h1->vel[j]*vel_dt + h1->a[j]*acc_dt2; if (h1->pos[j] < 0) h1->pos[j] += box_size; if (h1->pos[j] > box_size) h1->pos[j] -= box_size; } if (h1->id == 12) print_halo(i); } printf("\n"); }
void calc_tidal_forces(struct halo_stash *h, double a1, double a2) { int64_t i,j, num_halo_pos=0; float dt = (scale_to_years(a2) - scale_to_years(a1))/1.0e6; //In Myr float range, av_a = (a1+a2)/2.0; float inv_rs, r,m, dx, dy, dz, r3, acc; float rvir,nearest_range; struct fast3tree_results *nearest; struct tree_halo *h1, *h2; float acorr = 1; //pow(av_a, 0.7); float conv_const = av_a*av_a / h0 / h0 / h0; float vel_dt = dt * 1.02268944e-6 * h0 / av_a; //1 km/s to comoving Mpc/Myr/h struct tree_halo *halos = h->halos; float max_dist = box_size / 2.0; float mass_factor; gen_ff_cache(); if (!tidal_tree) tidal_tree = fast3tree_init(0, NULL); hpos = check_realloc(hpos, sizeof(struct halo_pos)*h->num_halos, "Allocating tidal halo positions"); nearest = fast3tree_results_init(); vel_dt /= 2.0; for (i=0; i<h->num_halos; i++) { halos[i].tidal_force = 0; halos[i].tidal_id = -1; halos[i].pid = halos[i].upid = -1; halos[i].pid_vmax = halos[i].upid_vmax = 0; if (halos[i].flags & MERGER_FLUCTUATION_FLAG) continue; hpos[num_halo_pos].h = &(halos[i]); for (j=0; j<3; j++) { hpos[num_halo_pos].pos[j] = halos[i].pos[j] + vel_dt*halos[i].vel[j]; IF_PERIODIC { if (hpos[num_halo_pos].pos[j] > box_size) hpos[num_halo_pos].pos[j] -= box_size; else if (hpos[num_halo_pos].pos[j] < 0) hpos[num_halo_pos].pos[j] += box_size; } } num_halo_pos++; } fast3tree_rebuild(tidal_tree, num_halo_pos, hpos); IF_PERIODIC _fast3tree_set_minmax(tidal_tree, 0, box_size); //Calculate accelerations for (i=0; i<num_halo_pos; i++) { h1 = hpos[i].h; range = halo_tidal_range(h1->mvir/h0, av_a)*h0; //In comoving Mpc/h rvir = h1->rvir / 1.0e3; //In comoving Mpc/h if (range > rvir) nearest_range = range; else nearest_range = rvir; IF_PERIODIC { if (nearest_range > max_dist) nearest_range = max_dist; fast3tree_find_sphere_periodic(tidal_tree, nearest, hpos[i].pos, nearest_range); } else { fast3tree_find_sphere(tidal_tree, nearest, hpos[i].pos, nearest_range); } inv_rs = 1000.0/h1->rs; //In comoving h/Mpc mass_factor = calculate_mass_factor(h1->mvir/h0, h1->rvir, h1->rs); for (j=0; j<nearest->num_points; j++) { //Calculate tidal forces h2 = nearest->points[j]->h; #ifndef NO_PERIODIC #define DIST(a,b) a = hpos[i].pos[b] - nearest->points[j]->pos[b]; \ if (a > max_dist) a-=box_size; \ else if (a < -max_dist) a+=box_size; #else #define DIST(a,b) a = hpos[i].pos[b] - nearest->points[j]->pos[b]; #endif DIST(dx,0); DIST(dy,1); DIST(dz,2); #undef DIST r = sqrtf(dx*dx + dy*dy + dz*dz); // in comoving Mpc/h //Including acorr slightly improves velocity results // as a function of redshift. m = mass_factor*ff_cached(r*inv_rs*acorr); //In Msun r3 = r * r * r * conv_const; //in (real Mpc)^3 acc = r3 ? Gc*m/r3 : 0; //In km/s / Myr / (real Mpc) if (r < rvir && h1->vmax > h2->vmax) { if (h2->pid < 0) { h2->pid = h2->upid = h1->id; h2->pid_vmax = h2->upid_vmax = h1->vmax; } else { if (h2->pid_vmax > h1->vmax) { h2->pid = h1->id; h2->pid_vmax = h1->vmax; } if (h2->upid_vmax < h1->vmax) { h2->upid = h1->id; h2->upid_vmax = h1->vmax; } } } if ((acc > h2->tidal_force) && ((h2->mvir*MAJOR_MERGER) < h1->mvir) && (!(h2->phantom))) { h2->tidal_force = acc; h2->tidal_id = h1->id; } } }