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; }
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; } } }
float find_previous_mass(struct halo *h, struct particle *hp, int64_t *best_num_p) { int64_t i, j, last_chunk = -1, max_particles, best_particles = 0; int64_t cur_part, remaining; char buffer[1024]; struct previous_halo *tph, *best_ph=NULL; struct litehash *lh = NULL; FILE *input = NULL; *best_num_p = 0; if (h->num_p < 100 || !num_prev_halos) return 0; fast3tree_find_sphere(phtree, phtree_results, h->pos, h->r); if (!phtree_results->num_points) return 0; for (i=0; i<phtree_results->num_points; i++) { if (!prev_halo_acceptable(h, phtree_results->points[i])) { phtree_results->num_points--; phtree_results->points[i] = phtree_results->points[phtree_results->num_points]; i--; } } if (!phtree_results->num_points) return 0; qsort(phtree_results->points, phtree_results->num_points, sizeof(struct previous_halo *), sort_previous_halos); max_particles = MAX_CORE_PARTICLES; if (max_particles >= h->num_p) max_particles = h->num_p; else convert_and_sort_core_particles(h, hp); lh = new_litehash(8); for (i=0; i<max_particles; i++) lh_setval(lh, &(p[hp[i].id].id), (void *)1); for (i=0; i<phtree_results->num_points; i++) { tph = phtree_results->points[i]; remaining = tph->num_p; cur_part = 0; if (remaining > MAX_CORE_PARTICLES) remaining = MAX_CORE_PARTICLES; if (tph->file_offset >= 0) { if (tph->chunk != last_chunk) { if (last_chunk > -1) fclose(input); get_output_filename(buffer, 1024, prev_snap, tph->chunk, "bin"); input = check_fopen(buffer, "rb"); last_chunk = tph->chunk; } check_fseeko(input, tph->file_offset, SEEK_SET); check_fread(prev_pids, sizeof(int64_t), remaining, input); } else { memcpy(prev_pids, hid_cache+tph->p_offset, sizeof(int64_t)*remaining); } for (j=0; j<remaining; j++) if (lh_getval(lh, prev_pids + j)) cur_part++; if (cur_part > best_particles) { best_particles = cur_part; best_ph = tph; } } if (last_chunk > -1) fclose(input); free_litehash(lh); if (best_ph && best_ph->m > 1e13 && best_particles > max_particles*0.1) { fprintf(stderr, "Hnow: %f %f %f (%"PRId64"; %e); Phalo: %f %f %f (%e); %"PRId64"\n", h->pos[0], h->pos[1], h->pos[2], h->num_p, h->num_p*PARTICLE_MASS, best_ph->pos[0], best_ph->pos[1], best_ph->pos[2], best_ph->m, best_particles); } *best_num_p = best_particles; if (best_ph && (best_particles > max_particles*0.1)) return best_ph->m; return 0; }