예제 #1
0
파일: _uberseg.c 프로젝트: esheldon/meds
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;
}
예제 #2
0
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;
      }
    }
  }
예제 #3
-10
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;
}