Beispiel #1
0
void prolongate( int level ) {
	int i,j;
	const int prolongation_vars[1] = { VAR_POTENTIAL };
	int icell;
	int num_level_cells;
	int *level_cells;

	cart_assert( level >= min_level+1 );

	start_time( WORK_TIMER );

	select_level( level-1, CELL_TYPE_LOCAL | CELL_TYPE_REFINED, &num_level_cells, &level_cells );
#pragma omp parallel for default(none), private(i,icell,j), shared(num_level_cells,level_cells,cell_vars,cell_child_oct)
	for ( i = 0; i < num_level_cells; i++ ) {
		icell = level_cells[i];

		for ( j = 0; j < num_children; j++ ) {
			cell_potential( cell_child(icell,j) ) = cell_interpolate( icell, j, VAR_POTENTIAL );
		}
	}
	cart_free( level_cells );

	end_time( WORK_TIMER );

	/* update buffers */
	start_time( PROLONGATE_UPDATE_TIMER );
	update_buffer_level( level, prolongation_vars, 1 );
	end_time( PROLONGATE_UPDATE_TIMER );
}
/**
 * rtp_jitter_buffer_pop:
 * @jbuf: an #RTPJitterBuffer
 * @percent: the buffering percent
 *
 * Pops the oldest buffer from the packet queue of @jbuf. The popped buffer will
 * have its timestamp adjusted with the incomming running_time and the detected
 * clock skew.
 *
 * Returns: a #GstBuffer or %NULL when there was no packet in the queue.
 */
RTPJitterBufferItem *
rtp_jitter_buffer_pop (RTPJitterBuffer * jbuf, gint * percent)
{
  GList *item = NULL;
  GQueue *queue;

  g_return_val_if_fail (jbuf != NULL, NULL);

  queue = jbuf->packets;

  item = queue->head;
  if (item) {
    queue->head = item->next;
    if (queue->head)
      queue->head->prev = NULL;
    else
      queue->tail = NULL;
    queue->length--;
  }

  /* buffering mode, update buffer stats */
  if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
    update_buffer_level (jbuf, percent);
  else if (percent)
    *percent = -1;

  return (RTPJitterBufferItem *) item;
}
Beispiel #3
0
void compute_accelerations_particles( int level ) {
	int i, j;
	double a2half;
	const int accel_vars[nDim] = { VAR_ACCEL, VAR_ACCEL+1, VAR_ACCEL+2 };
	int neighbors[num_neighbors];
	int L1, R1;
	double phi_l, phi_r;
	int icell;
	int num_level_cells;
	int *level_cells;

	start_time( GRAVITY_TIMER );
	start_time( PARTICLE_ACCEL_TIMER );
	start_time( WORK_TIMER );

#ifdef COSMOLOGY
	a2half = -0.5*abox[level]*abox[level]*cell_size_inverse[level];
#else
	a2half = -0.5 * cell_size_inverse[level];
#endif

	select_level( level, CELL_TYPE_LOCAL, &num_level_cells, &level_cells );
#pragma omp parallel for default(none), private(icell,j,neighbors,L1,R1,phi_l,phi_r), shared(num_level_cells,level_cells,level,cell_vars,a2half)
	for ( i = 0; i < num_level_cells; i++ ) {
		icell = level_cells[i];

		cell_all_neighbors( icell, neighbors );
		for ( j = 0; j < nDim; j++ ) {
			L1 = neighbors[2*j];
			R1 = neighbors[2*j+1];

			if ( cell_level(L1) < level ) {
				phi_l = 0.8*cell_potential(L1) + 0.2*cell_potential(icell);
			} else {
				phi_l = cell_potential(L1);
			}

			if ( cell_level(R1) < level ) {
				phi_r = 0.8*cell_potential(R1)+0.2*cell_potential(icell);
			} else {
				phi_r = cell_potential(R1);
			}

			cell_accel( icell, j ) = (float)(a2half * ( phi_r - phi_l ) );
		}
	}
	cart_free( level_cells );

	end_time( WORK_TIMER );

	/* update accelerations */
	start_time( PARTICLE_ACCEL_UPDATE_TIMER );
	update_buffer_level( level, accel_vars, nDim );
	end_time( PARTICLE_ACCEL_UPDATE_TIMER );

	end_time( PARTICLE_ACCEL_TIMER );
	end_time( GRAVITY_TIMER );
}
Beispiel #4
0
void rtOtvetSingleSourceEddingtonTensor(int level)
{
  int i, j, l, index, cell;
  int num_level_cells, *level_cells;
  double eps1, eps2, dr2, pos[nDim];

  start_time(WORK_TIMER);

  eps1 = 0.01*cell_size[rtSingleSourceLevel]*cell_size[rtSingleSourceLevel];
  eps2 = 9*cell_size[rtSingleSourceLevel]*cell_size[rtSingleSourceLevel];

  select_level(level,CELL_TYPE_LOCAL,&num_level_cells,&level_cells);

#pragma omp parallel for default(none), private(index,cell,pos,dr2,i,j,l), shared(level,num_level_cells,level_cells,rtSingleSourceValue,rtSingleSourcePos,eps1,eps2,cell_vars)
  for(index=0; index<num_level_cells; index++)
    {
      cell = level_cells[index];
      cell_center_position(cell,pos);

      dr2 = eps1;
      for(i=0; i<nDim; i++)
	{
	  pos[i] -= rtSingleSourcePos[i];
	  if(pos[i] >  0.5*num_grid) pos[i] -= num_grid;
	  if(pos[i] < -0.5*num_grid) pos[i] += num_grid;
	  dr2 += pos[i]*pos[i];
	}

      cell_var(cell,RT_VAR_OT_FIELD) = rtSingleSourceValue/(4*M_PI*dr2);
      
      dr2 += nDim*eps2;
      for(l=j=0; j<nDim; j++)
	{
	  for(i=0; i<j; i++)
	    {
	      cell_var(cell,rt_et_offset+l++) = pos[i]*pos[j]/dr2;
	    }
	  cell_var(cell,rt_et_offset+l++) = (eps2+pos[j]*pos[j])/dr2;
	}
    }

  cart_free(level_cells);

  end_time(WORK_TIMER);

  start_time(RT_SINGLE_SOURCE_UPDATE_TIMER);
  update_buffer_level(level,rtOtvetETVars,rtNumOtvetETVars);
  end_time(RT_SINGLE_SOURCE_UPDATE_TIMER);
}
Beispiel #5
0
/**
 * rtp_jitter_buffer_pop:
 * @jbuf: an #RTPJitterBuffer
 * @percent: the buffering percent
 *
 * Pops the oldest buffer from the packet queue of @jbuf. The popped buffer will
 * have its timestamp adjusted with the incomming running_time and the detected
 * clock skew.
 *
 * Returns: a #GstBuffer or %NULL when there was no packet in the queue.
 */
GstBuffer *
rtp_jitter_buffer_pop (RTPJitterBuffer * jbuf, gint * percent)
{
  GstBuffer *buf;

  g_return_val_if_fail (jbuf != NULL, NULL);

  buf = g_queue_pop_tail (jbuf->packets);

  /* buffering mode, update buffer stats */
  if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
    update_buffer_level (jbuf, percent);
  else
    *percent = -1;

  return buf;
}
Beispiel #6
0
void compute_accelerations_hydro( int level ) {
	int i, j;
	double a2half;
	int neighbors[num_neighbors];
	int L1, R1;
	double phi_l, phi_r;
#ifdef GRAVITY_IN_RIEMANN
	const int accel_vars[nDim] = { VAR_ACCEL, VAR_ACCEL+1, VAR_ACCEL+2 };
#endif

	int icell;
	int num_level_cells;
	int *level_cells;

	start_time( GRAVITY_TIMER );
	start_time( HYDRO_ACCEL_TIMER );
	start_time( WORK_TIMER );

#ifdef COSMOLOGY
	a2half = abox_from_tcode( tl[level] + dtl[level] );
	a2half = -0.5*dtl[level]*cell_size_inverse[level]*a2half*a2half;
#else
	a2half = -0.5*dtl[level]*cell_size_inverse[level];
#endif 

	select_level( level, CELL_TYPE_LOCAL, &num_level_cells, &level_cells );
#ifdef OPENMP_DECLARE_CONST
#pragma omp parallel for default(none), private(icell,j,neighbors,L1,R1,phi_l,phi_r), shared(num_level_cells,level_cells,level,cell_vars,a2half), shared(local)
#else  /* OPENMP_DECLARE_CONST */
#pragma omp parallel for default(none), private(icell,j,neighbors,L1,R1,phi_l,phi_r), shared(num_level_cells,level_cells,level,cell_vars,a2half)
#endif /* OPENMP_DECLARE_CONST */
	for ( i = 0; i < num_level_cells; i++ ) {
		icell = level_cells[i];

		cell_all_neighbors( icell, neighbors );
		for ( j = 0; j < nDim; j++ ) {
			L1 = neighbors[2*j];
			R1 = neighbors[2*j+1];

			if ( cell_level(L1) == level && cell_level(R1) == level ) {
				phi_l = cell_potential_hydro(L1);
				phi_r = cell_potential_hydro(R1);
			} else {
				if ( cell_level(L1) < level ) {
					phi_l = cell_interpolate( L1, local[cell_child_number(icell)][2*j], VAR_POTENTIAL_HYDRO );
					phi_r = cell_potential_hydro(R1);
				} else {
					phi_l = cell_potential_hydro(L1);
					phi_r = cell_interpolate( R1, local[cell_child_number(icell)][2*j], VAR_POTENTIAL_HYDRO );
				}
			}

			cell_accel( icell, j ) = (float)(a2half * ( phi_r - phi_l ) );
		}
	}
	cart_free( level_cells );

	end_time( WORK_TIMER );

#ifdef GRAVITY_IN_RIEMANN
	/* this only gets called if we pass gravity on to Riemann solver (and thus need accel in buffer cells) */
	start_time( HYDRO_ACCEL_UPDATE_TIMER );
	update_buffer_level( level, accel_vars, nDim );
	end_time( HYDRO_ACCEL_UPDATE_TIMER );
#endif

	end_time( HYDRO_ACCEL_TIMER );
	end_time( GRAVITY_TIMER );
}
Beispiel #7
0
void init_run() {
	int i, j, k;
	int index;
	double a_th;

	int ipart;
	int icell;
	double qi, qj, qk;
	double xcons, vcons;
	double dx, dvx;
	double pw;
	double a_vel;
	double qfact;

	int num_level_cells;
	int *level_cells;

	cosmology_set(OmegaM,OmM0);
	cosmology_set(OmegaB,OmB0);
	cosmology_set(OmegaL,OmL0);
	cosmology_set(h,h0);
	cosmology_set(DeltaDC,dDC);
	box_size = Lbox0;

	units_set_art(cosmology->OmegaM,cosmology->h,box_size);
	units_init();
	build_cell_buffer();
	repair_neighbors();
        
	auni[min_level] = auni_init;
	tl[min_level] = tcode_from_auni( auni_init );
	for ( i = min_level; i <= max_level; i++ ) { tl[i] = tl[min_level]; }
	abox[min_level] = auni_init;

	for(i=min_level+1; i<=max_level; i++)
	{
            tl[i] = tl[min_level];
            auni[i] = auni[min_level];
            abox[i] = abox[min_level];
	}
        
	units_update(min_level);
	cart_debug("tl[min_level] = %f", tl[min_level] );
	cart_debug("au[min_level] = %f", auni[min_level] );
	cart_debug("ab[min_level] = %f", abox[min_level] );
	cart_debug("DC mode = %f", cosmology->DeltaDC );
	cosmology_set_fixed();


	rhogas0 = cosmology->OmegaB/cosmology->OmegaM;
	cart_debug("rhogas0 = %e", rhogas0 );

	Tinit = TinitK/units->temperature;


	ak = 2.0*M_PI / lambda;
	dgrowth = growth(abox[min_level]);
	ddgrowthdt = dgrowthdt(abox[min_level]);
	ampl = 1.0 / ( growth(a_cross) * ak );
	cart_debug("Tinit,TinitK = %e %e", Tinit,TinitK );

#ifdef HYDRO
	for ( i = min_level; i <= max_level; i++ ) {
		cart_debug("generating initial conditions on level %u", i );
	
		select_level( i, CELL_TYPE_LOCAL, &num_level_cells, &level_cells );
		for ( j = 0; j < num_level_cells; j++ ) {
//                    cart_debug("%d %d",level_cells[j],num_cells);
			initial_conditions( level_cells[j], i );
		}
		cart_free( level_cells );
	}

	for ( i = min_level; i <= max_level; i++ ) {
		update_buffer_level( i, all_hydro_vars, num_hydro_vars );
	}
#endif /* HYDRO */

	cart_debug("choose timestep and set velocity on the half step");
	dtl[min_level] = 0.0;
	set_timestepping_scheme();
	dtl[min_level]=.125;
	cart_debug("=======================%e",dtl[min_level]);

	dtl_old[min_level] = dtl[min_level];
	tl_old[min_level] = tl[min_level]-dtl[min_level];
	abox_old[min_level] = abox_from_tcode(tl_old[min_level]);
	dtl_old[min_level] = dtl[min_level];

	for ( i = min_level+1; i <= max_level; i++ ) {
		tl_old[i] = tl[i]-dtl[i];
		abox_old[i] = abox_from_tcode(tl_old[i]);
		dtl_old[i] = dtl[i];
	}

#ifdef GRAVITY
#ifdef HYDRO
	for ( i = min_level; i <= max_level; i++ ) {
		cart_debug("generating gravity on level %u", i );
	
//                cart_assert(dtl[i]==0);
		select_level( i, CELL_TYPE_LOCAL, &num_level_cells, &level_cells );
		for ( j = 0; j < num_level_cells; j++ ) {
			initial_gravity( level_cells[j], i );
		}
		cart_free( level_cells );
	}

	for ( i = min_level; i <= max_level; i++ ) {
		update_buffer_level( i, all_hydro_vars, num_hydro_vars );
	}
#endif /* GRAVITY */
#endif /* HYDRO */
        
        
#ifdef PARTICLES
	qfact = (double)num_grid / (double)num_grid;
	pw = (1.0-rhogas0)*qfact*qfact*qfact;

	cart_debug("particle weight = %e", pw );

	xcons = dgrowth*ampl;
	a_vel = abox_from_tcode( tl[min_level] - 0.5*dtl[min_level] );
	vcons = ampl * dgrowthdt( a_vel);

	ipart = 0;
	for ( i = 0; i < num_grid; i++ ) {
		qi = qfact*((double)i + 0.5);
		dx = xcons * sin( ak * qi );
		dvx = vcons * sin( ak * qi );
		for ( j = 0; j < num_grid; j++ ) {
			qj = qfact*((double)j + 0.5);
			for ( k = 0; k < num_grid; k++ ) {
				qk = qfact*((double)k + 0.5);

				particle_x[ipart][0] = qi + dx;
				particle_x[ipart][1] = qj;
				particle_x[ipart][2] = qk;

				if ( particle_x[ipart][0] >= (double)num_grid ) {
					particle_x[ipart][0] -= num_grid;
				}

				if ( particle_x[ipart][1] >= (double)num_grid ) {
					particle_x[ipart][1] -= num_grid;
				}

				if ( particle_x[ipart][2] >= (double)num_grid ) {
					particle_x[ipart][2] -= num_grid;
				}

				icell = cell_find_position( particle_x[ipart] );

				if ( icell != -1 && cell_is_local(icell) ) {
					particle_v[ipart][0] = dvx;
					particle_v[ipart][1] = 0.0;
					particle_v[ipart][2] = 0.0;

					particle_id[ipart] = (particleid_t)num_grid*(num_grid*i + j) + k;
					particle_mass[ipart] = pw;

					cart_assert( qi == particle_q_init( particle_id[ipart] ) );

					particle_t[ipart] = tl[min_level];
					particle_dt[ipart] = dtl[min_level];

					ipart++;
				}
			}
		}
	}

	cart_debug("created %u particles", ipart );

	num_local_particles = ipart;
	num_particles_total = (particleid_t)num_grid*(particleid_t)num_grid*(particleid_t)num_grid;
	num_particle_species = 1;
	particle_species_mass[0] = pw;
	particle_species_num[0] = num_particles_total;
	particle_species_indices[0] = 0;
	particle_species_indices[1] = num_particles_total;

	build_particle_list();

/* 	assign_density( min_level, min_level ); */ //for refinement
/* 	modify( min_level, 0 ); */
 	assign_density( min_level, min_level );  //for refinement
 	modify( min_level, 0 ); 

	if ( local_proc_id == MASTER_NODE ) {
		particles = fopen("dumps/particle_rms.dat", "w");
		fclose(particles);
	}
#endif

	check_map();
	cart_debug("done with initialization");
}
/**
 * rtp_jitter_buffer_insert:
 * @jbuf: an #RTPJitterBuffer
 * @item: an #RTPJitterBufferItem to insert
 * @tail: TRUE when the tail element changed.
 * @percent: the buffering percent after insertion
 *
 * Inserts @item into the packet queue of @jbuf. The sequence number of the
 * packet will be used to sort the packets. This function takes ownerhip of
 * @buf when the function returns %TRUE.
 *
 * Returns: %FALSE if a packet with the same number already existed.
 */
gboolean
rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item,
    gboolean * tail, gint * percent)
{
  GList *list = NULL;
  guint32 rtptime;
  guint16 seqnum;
  GstClockTime dts;

  g_return_val_if_fail (jbuf != NULL, FALSE);
  g_return_val_if_fail (item != NULL, FALSE);

  /* no seqnum, simply append then */
  if (item->seqnum == -1) {
    goto append;
  }

  seqnum = item->seqnum;

  /* loop the list to skip strictly smaller seqnum buffers */
  for (list = jbuf->packets->head; list; list = g_list_next (list)) {
    guint16 qseq;
    gint gap;
    RTPJitterBufferItem *qitem = (RTPJitterBufferItem *) list;

    if (qitem->seqnum == -1)
      continue;

    qseq = qitem->seqnum;

    /* compare the new seqnum to the one in the buffer */
    gap = gst_rtp_buffer_compare_seqnum (seqnum, qseq);

    /* we hit a packet with the same seqnum, notify a duplicate */
    if (G_UNLIKELY (gap == 0))
      goto duplicate;

    /* seqnum < qseq, we can stop looking */
    if (G_LIKELY (gap > 0))
      break;
  }

  dts = item->dts;
  if (item->rtptime == -1)
    goto append;

  rtptime = item->rtptime;

  /* rtp time jumps are checked for during skew calculation, but bypassed
   * in other mode, so mind those here and reset jb if needed.
   * Only reset if valid input time, which is likely for UDP input
   * where we expect this might happen due to async thread effects
   * (in seek and state change cycles), but not so much for TCP input */
  if (GST_CLOCK_TIME_IS_VALID (dts) &&
      jbuf->mode != RTP_JITTER_BUFFER_MODE_SLAVE &&
      jbuf->base_time != -1 && jbuf->last_rtptime != -1) {
    GstClockTime ext_rtptime = jbuf->ext_rtptime;

    ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
    if (ext_rtptime > jbuf->last_rtptime + 3 * jbuf->clock_rate ||
        ext_rtptime + 3 * jbuf->clock_rate < jbuf->last_rtptime) {
      /* reset even if we don't have valid incoming time;
       * still better than producing possibly very bogus output timestamp */
      GST_WARNING ("rtp delta too big, reset skew");
      rtp_jitter_buffer_reset_skew (jbuf);
    }
  }

  switch (jbuf->mode) {
    case RTP_JITTER_BUFFER_MODE_NONE:
    case RTP_JITTER_BUFFER_MODE_BUFFER:
      /* send 0 as the first timestamp and -1 for the other ones. This will
       * interpollate them from the RTP timestamps with a 0 origin. In buffering
       * mode we will adjust the outgoing timestamps according to the amount of
       * time we spent buffering. */
      if (jbuf->base_time == -1)
        dts = 0;
      else
        dts = -1;
      break;
    case RTP_JITTER_BUFFER_MODE_SYNCED:
      /* synchronized clocks, take first timestamp as base, use RTP timestamps
       * to interpolate */
      if (jbuf->base_time != -1)
        dts = -1;
      break;
    case RTP_JITTER_BUFFER_MODE_SLAVE:
    default:
      break;
  }
  /* do skew calculation by measuring the difference between rtptime and the
   * receive dts, this function will return the skew corrected rtptime. */
  item->pts = calculate_skew (jbuf, rtptime, dts);

append:
  queue_do_insert (jbuf, list, (GList *) item);

  /* buffering mode, update buffer stats */
  if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
    update_buffer_level (jbuf, percent);
  else if (percent)
    *percent = -1;

  /* tail was changed when we did not find a previous packet, we set the return
   * flag when requested. */
  if (G_LIKELY (tail))
    *tail = (list == NULL);

  return TRUE;

  /* ERRORS */
duplicate:
  {
    GST_WARNING ("duplicate packet %d found", (gint) seqnum);
    return FALSE;
  }
}
Beispiel #9
0
void cosmics_init()
{
  static const int page_size = 262144;
  FILE *f[6];
  int i, j, n, index, ipart, coords[3];
  int level, levelMax;
  int l, wrong_order[6], page, num_pages;
  int cell, num_level_cells, *level_cells;
  int slice, num_slices, num_data_per_slice, num_data_done;
  long id;
  int ng1, ng2;
  double x0[3], x[3], fRef;
  float q, xFac, vFac;
  float *buffer[6], *vxc, *vyc, *vzc, *vxb, *vyb, *vzb;
  float fracB, temIn, fracHII;
  int children[num_children];

  GIC_RECORD s1, s2;
  const char *tmp, *dir;
  char filename[999];
  struct cosmics_header
  {
    int n[3];
    float dx, abeg, OmegaM, OmegaL, H0;
  } header[6];

  
  /*
  //  Where do we get the root name? Use options for now
  */
  tmp = extract_option1("dir","dir",NULL);
  if(tmp != NULL)
    {
      dir = tmp;
    }
  else
    {
      cart_error("An option --dir=<name> is required, where <name> is the directory name for a set of COSMICS input files.");
    }
  
  /*
  //  No more options are allowed.
  */
  if(num_options > 0)
    {
      cart_error("Unrecognized option: %s",options[0]);
    }

  MPI_Barrier(mpi.comm.run);

  if(local_proc_id == MASTER_NODE)
    {
      for(l=0; l<6; l++)
	{
	  strcpy(filename,dir);
	  switch(l)
	    {
	    case 0:
	      {
		strcat(filename,"/ic_vxc.dat");
		break;
	      }
	    case 1:
	      {
		strcat(filename,"/ic_vyc.dat");
		break;
	      }
	    case 2:
	      {
		strcat(filename,"/ic_vzc.dat");
		break;
	      }
	    case 3:
	      {
		strcat(filename,"/ic_vxb.dat");
		break;
	      }
	    case 4:
	      {
		strcat(filename,"/ic_vyb.dat");
		break;
	      }
	    case 5:
	      {
		strcat(filename,"/ic_vzb.dat");
		break;
	      }
	    }

	  f[l] = fopen(filename,"r");
	  cart_assert(f[l] != NULL);

	  if(gicReadRecordHelper(f[l],sizeof(struct cosmics_header),header+l,wrong_order+l) != 0)
	    {
	      cart_error("Error in reading the header for stream %d, file %s",l,filename);
	    }
	  if(l!=0 && memcmp(header,header+l,sizeof(struct cosmics_header))!=0)
	    {
	      cart_error("Incompatible input streams 0 and %d",l);
	    }
	}

      if(wrong_order[0])
	{
	  reorder((char*)&header->n[0],sizeof(int));
	  reorder((char*)&header->n[1],sizeof(int));
	  reorder((char*)&header->n[2],sizeof(int));
	  reorder((char*)&header->dx,sizeof(float));
	  reorder((char*)&header->abeg,sizeof(float));
	  reorder((char*)&header->OmegaM,sizeof(float));
	  reorder((char*)&header->OmegaL,sizeof(float));
	  reorder((char*)&header->H0,sizeof(float));
	}


      if(header->n[0]!=header->n[1] || header->n[1]!=header->n[2])
	{
	  cart_error("Only a cubic input mesh is supported.");
	}
    }

  MPI_Bcast(header,sizeof(struct cosmics_header),MPI_BYTE,MASTER_NODE,mpi.comm.run);

  levelMax = 0;
  while(header->n[0] > num_grid)
    {
      header->n[0] = header->n[0] >> 1;
      levelMax++;
    }

  if(num_grid != header->n[0])
    {
      cart_error("The input grid size (=%d) is not a power-of-two multiple of num_grid (=%d).",header->n[1],num_grid);
    }

  cart_assert(header->n[1] == num_grid << levelMax);
  levelMax += min_level;

  /*
  //  Set units
  */
  cosmology_set(OmegaM,header->OmegaM);
  cosmology_set(OmegaB,0.04);
  cosmology_set(OmegaL,header->OmegaL);
  cosmology_set(h,header->H0/100.0);
  cosmology_set(DeltaDC,0.0);
  box_size = header->dx*cosmology->h*num_grid;

  auni[min_level] = header->abeg;
  tl[min_level] = tcode_from_auni(auni[min_level]);
  abox[min_level] = abox_from_auni(auni[min_level]);

  units_init();
  units_update(min_level);

  /*
  //  Particle parameters
  */
  num_particles_total = (particleid_t)header->n[1]*(particleid_t)header->n[1]*(particleid_t)header->n[1];
  num_particle_species = 1;
  particle_species_num[0] = num_particles_total;
  particle_species_mass[0] = 1.0 - cosmology->OmegaB/cosmology->OmegaM;
  particle_species_indices[0] = 0;
  particle_species_indices[1] = num_particles_total;

#ifdef STARFORM
  if(MAX_PARTICLE_SPECIES < 2)
    {
      cart_error("MAX_PARTICLE_SPECIES should be at least 2. Increase and rerun.");
    }

  num_particle_species = 2;

  particle_species_num[1] = 0;
  particle_species_mass[1] = 0.0;
  particle_species_indices[2] = particle_species_indices[1];

  total_stellar_mass = 0.0;
  total_stellar_initial_mass = 0.0;
#endif

  cart_debug("num_particle_species = %d",num_particle_species);
  cart_debug("num_particles_total = %d",num_particles_total);


  /*
  //  Balance load - split uniformly
  */
  for(i=0; i<=num_procs; i++)
    {
      proc_sfc_index[i] = ((unsigned long)num_root_cells*(unsigned long)i)/num_procs;
    }
  init_tree();

  for(i=0; i<nDim; i++)
    {
      refinement_volume_min[i] = 0.0;
      refinement_volume_max[i] = num_grid;
    }

  /*
  // Refine grid uniformly to levelMax
  */
  for(level=min_level; level<levelMax; level++)
    {
      cart_debug("refining level %d",level);

      select_level(level,CELL_TYPE_LOCAL,&num_level_cells,&level_cells);
      cart_debug("num_level_cells = %d",num_level_cells);
      
      for(i=0; i<num_level_cells; i++)
	{
	  refinement_indicator(level_cells[i],0) = 1.0;       
	}
       cart_free( level_cells );

       refine(level);
    }

  /*
  //  Read in the data
  */
  for(l=0; l<6; l++)
    {
      buffer[l] = cart_alloc(float,page_size);
    }

  vxc = buffer[0];
  vyc = buffer[1];
  vzc = buffer[2];
  vxb = buffer[3];
  vyb = buffer[4];
  vzb = buffer[5];

  /*
  //  Unit conversion factors
  */
  vFac = constants->kms/units->velocity;
  xFac = abox[min_level]*abox[min_level]*constants->Mpc/(100*cosmology->h*units->length)*dPlus(abox[min_level])/qPlus(abox[min_level]);

  if(header->n[1] > 256)
    {
      num_slices = header->n[1];
      num_data_per_slice = header->n[1]*header->n[1];
    }
  else
    {
      num_slices = 1;
      num_data_per_slice = header->n[1]*header->n[1]*header->n[1];
    }

  num_pages = (num_data_per_slice+page_size-1)/page_size;

  id = 0L;

  fRef = pow(0.5,levelMax);
  ng1 = num_grid << levelMax;
  ng2 = ng1*ng1;

  for(slice=0; slice<num_slices; slice++)
    {

      num_data_done = 0;

      if(local_proc_id == MASTER_NODE)
	{
	  for(l=0; l<6; l++)
	    {
	      if(fread(&s1,sizeof(GIC_RECORD),1,f[l]) != 1)
		{
		  cart_error("Error in reading header for file %d, record %d",l,slice);
		}
	      if(wrong_order[l]) reorder((char *)&s1,sizeof(s1));
	      if(s1 != sizeof(float)*num_data_per_slice)
		{
		  cart_error("Header for file %d, record %d is corrupted: %d, should be %d",l,slice,s1,num_data_per_slice);
		}
	    }
	}

      for(page=0; page<num_pages; page++)
	{

	  n = page_size;
	  if(num_data_done+n > num_data_per_slice)
	    {
	      n = num_data_per_slice - num_data_done;
	      cart_assert(page == (num_pages-1));
	    }
	  num_data_done += n;

	  if(local_proc_id == MASTER_NODE)
	    {
	      for(l=0; l<6; l++)
		{
		  if(fread(buffer[l],sizeof(float),n,f[l]) != n)
		    {
		      cart_error("Error in reading data for file %d, record %d, page %d",l,slice,page);
		    }
		  if(wrong_order[l])
		    {
		      for(j=0; j<n; j++) reorder((char *)(buffer[l]+j),sizeof(float));
		    }
		}
	    }

	  for(l=0; l<6; l++)
	    {
	      MPI_Bcast(buffer[l],n,MPI_FLOAT,MASTER_NODE,mpi.comm.run);
	    }

	  /*
	  //  We need a barrier here to avoid overfilling MPI buffers 
	  //  with too many asynchronized broadcasts
	  */
	  if(page%100 == 99) MPI_Barrier(mpi.comm.run);

	  for(j=0; j<n; j++)
	    {

	      /*
	      //  Particle position
	      */
	      x0[0] = fRef*(0.5+(id % ng1));
	      x0[1] = fRef*(0.5+(id/ng1 % ng1));
	      x0[2] = fRef*(0.5+(id/ng2 % ng1));
	      
	      x[0] = xFac*vxc[j] + x0[0];
	      x[1] = xFac*vyc[j] + x0[1];
	      x[2] = xFac*vzc[j] + x0[2];

	      /* enforce periodic boundary conditions */
	      for(i=0; i<3; i++)
		{
		  if(x[i] < 0.0)
		    {
		      x[i] += (double)num_grid;
		    } 
		  else if(x[i] >= (double)num_grid)
		    {
		      x[i] -= (double)num_grid;
		    }
		  coords[i] = (int)(x[i]);
		}

	      index = sfc_index( coords );
	      cart_assert( index >= 0 && index < num_root_cells );
          
	      /* check if we're supposed to read in this particle */
	      if(local_proc_id == processor_owner(index))
		{
		  ipart = particle_alloc(id);
		  cart_assert(ipart>=0 && ipart<num_particles );

		  particle_x[ipart][0] = x[0];
		  particle_x[ipart][1] = x[1];
		  particle_x[ipart][2] = x[2];
		  particle_v[ipart][0] = vFac*vxc[j];
		  particle_v[ipart][1] = vFac*vyc[j];
		  particle_v[ipart][2] = vFac*vzc[j];

		  particle_id[ipart] = id;
		  particle_mass[ipart] = particle_species_mass[0];
		  particle_level[ipart] = min_level + levelMax;
		}

	      for(i=0; i<3; i++)
		{
		  coords[i] = (int)(x0[i]);
		}

	      index = sfc_index( coords );
	      cart_assert( index >= 0 && index < num_root_cells );
	      if(local_proc_id == processor_owner(index))
		{
		  cell = cell_find_position(x0);
#ifdef DEBUG
		  if(cell == -1)
		    {
		      cart_debug("%lf %lf %lf",x0[0],x0[1],x0[2]);
		      cart_debug("%ld %d %g",id,ng1,fRef);
		    }
#endif
		  cart_assert(cell != -1);

		  cell_var(cell,HVAR_MOMENTUM+0) = vFac*vxb[j];
		  cell_var(cell,HVAR_MOMENTUM+1) = vFac*vyb[j];
		  cell_var(cell,HVAR_MOMENTUM+2) = vFac*vzb[j];
		}

	      id++;
	    }
	}

      if(local_proc_id == MASTER_NODE)
	{
	  for(l=0; l<6; l++)
	    {
	      if(fread(&s2,sizeof(GIC_RECORD),1,f[l]) != 1)
		{
		  cart_error("Error in reading footer for file %d, record %d",l,slice);
		}
	      if(wrong_order[l]) reorder((char *)&s2,sizeof(s2));
	      if(s2 != sizeof(float)*num_data_per_slice)
		{
		  cart_error("Footer for file %d, record %d is corrupted: %d, should be %d",l,slice,s2,num_data_per_slice);
		}
	    }
	}
    }

  if(local_proc_id == MASTER_NODE)
    {
      for(l=0; l<6; l++) fclose(f[l]);
    }

  
  for(l=0; l<6; l++) cart_free(buffer[l]);
  
  build_particle_list();

  /*
  //  Thermal state of the primordial gas
  */
  fracB = cosmology->OmegaB/cosmology->OmegaM;
  fracHII = 1.2e-5*sqrt(cosmology->Omh2)/cosmology->Obh2;
  q = auni[min_level]*137.0*pow(cosmology->Obh2/0.022,0.4);
  temIn = 2.728/auni[min_level]*q/pow(pow(q,1.73)+1,1.0/1.73);

  if(local_proc_id == MASTER_NODE)
    {
      cart_debug("Initial temperature: %f",temIn);
    }

  temIn /= units->temperature;

  if(local_proc_id == MASTER_NODE)
    {
      cart_debug("f_HII: %e, T_in: %e",fracHII,temIn);
    }

  /*
  //  Finish filling in the lowest level
  */
  select_level(min_level+levelMax,CELL_TYPE_LOCAL,&num_level_cells,&level_cells);
  for(i=0; i<num_level_cells; i++)
    {
      cell = level_cells[i];

      cell_gas_density(cell) = fracB;
      cell_momentum(cell,0) *= fracB;
      cell_momentum(cell,1) *= fracB;
      cell_momentum(cell,2) *= fracB;

      cell_gas_gamma(cell) = constants->gamma;
      cell_gas_internal_energy(cell) =  cell_gas_density(cell)*temIn/(constants->gamma-1)*(1.0-constants->Yp+0.25*constants->Yp);
      cell_gas_pressure(cell) = cell_gas_internal_energy(cell)*(constants->gamma-1);
      cell_gas_energy(cell) = cell_gas_internal_energy(cell) + cell_gas_kinetic_energy(cell);

#ifdef RADIATIVE_TRANSFER
      cell_HI_density(cell) = cell_gas_density(cell)*constants->XH*(1.0-fracHII);
      cell_HII_density(cell) = cell_gas_density(cell)*constants->XH*fracHII;
      cell_HeI_density(cell) = cell_gas_density(cell)*constants->XHe;
      cell_HeII_density(cell) = cell_gas_density(cell)*0.0;
      cell_HeIII_density(cell) = cell_gas_density(cell)*0.0;
      cell_H2_density(cell) = cell_gas_density(cell)*constants->XH*2.0e-6;
#endif
#ifdef EXTRA_PRESSURE_SOURCE
      cell_extra_pressure_source(cell) = 0;
#endif /* EXTRA_PRESSURE_SOURCE */
#ifdef ISOTROPIC_TURBULENCE_ENERGY
      cell_isotropic_turbulence_energy(cell) = 0;
#endif /* ISOTROPIC_TURBULENCE_ENERGY */
    }
  cart_free(level_cells);


  /*
  //  Finish filling in the grid
  */
  for(level=min_level+levelMax-1; level>=min_level; level--)
    {
      select_level(level,CELL_TYPE_LOCAL,&num_level_cells,&level_cells);
      for(i=0; i<num_level_cells; i++)
        {
	  cell = level_cells[i];

          cell_all_children(cell,children);
          for(j=0; j<num_hydro_vars; j++)
            {
              q = 0.0;
              for(l=0; l<num_children; l++)
                {
                  q += cell_var(children[l],all_hydro_vars[j]);
                }
              cell_var(cell,all_hydro_vars[j]) = q/num_children;
            }
        }
      cart_free(level_cells);
    }

  build_cell_buffer();
  repair_neighbors();

  /*
  //  Update the buffer everywhere
  */
  for(level=min_level; level<=max_level; level++)
    {
      update_buffer_level(level,all_hydro_vars,num_hydro_vars);
    }

  hydro_magic(min_level);
  hydro_eos(min_level);

  cart_debug("tl[min_level] = %f", tl[min_level] );
  cart_debug("au[min_level] = %f", auni[min_level] );
  cart_debug("ab[min_level] = %f", abox[min_level] );

  for(level=min_level+1; level<=max_level; level++)
    {
      tl[level] = tl[min_level];
      auni[level] = auni[min_level];
      abox[level] = abox[min_level];
    }

  for(i=0; i<num_particles; i++) if(particle_level[i] != FREE_PARTICLE_LEVEL)
    {
      particle_t[i] = tl[min_level];
      particle_dt[i] = 0.0;
    }

#ifdef STARFORM
  for(i=0; i<nDim; i++)
    {
      star_formation_volume_min[i] = refinement_volume_min[i];
      star_formation_volume_max[i] = refinement_volume_max[i];
    }
#endif
}
Beispiel #10
0
/**
 * rtp_jitter_buffer_insert:
 * @jbuf: an #RTPJitterBuffer
 * @buf: a buffer
 * @time: a running_time when this buffer was received in nanoseconds
 * @clock_rate: the clock-rate of the payload of @buf
 * @max_delay: the maximum lateness of @buf
 * @tail: TRUE when the tail element changed.
 *
 * Inserts @buf into the packet queue of @jbuf. The sequence number of the
 * packet will be used to sort the packets. This function takes ownerhip of
 * @buf when the function returns %TRUE.
 * @buf should have writable metadata when calling this function.
 *
 * Returns: %FALSE if a packet with the same number already existed.
 */
gboolean
rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, GstBuffer * buf,
    GstClockTime time, guint32 clock_rate, gboolean * tail, gint * percent)
{
  GList *list;
  guint32 rtptime;
  guint16 seqnum;
  GstRTPBuffer rtp = {NULL};

  g_return_val_if_fail (jbuf != NULL, FALSE);
  g_return_val_if_fail (buf != NULL, FALSE);

  gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);

  seqnum = gst_rtp_buffer_get_seq (&rtp);

  /* loop the list to skip strictly smaller seqnum buffers */
  for (list = jbuf->packets->head; list; list = g_list_next (list)) {
    guint16 qseq;
    gint gap;
    GstRTPBuffer rtpb = {NULL};

    gst_rtp_buffer_map (GST_BUFFER_CAST (list->data), GST_MAP_READ, &rtpb);
    qseq = gst_rtp_buffer_get_seq (&rtpb);
    gst_rtp_buffer_unmap (&rtpb);

    /* compare the new seqnum to the one in the buffer */
    gap = gst_rtp_buffer_compare_seqnum (seqnum, qseq);

    /* we hit a packet with the same seqnum, notify a duplicate */
    if (G_UNLIKELY (gap == 0))
      goto duplicate;

    /* seqnum > qseq, we can stop looking */
    if (G_LIKELY (gap < 0))
      break;
  }

  rtptime = gst_rtp_buffer_get_timestamp (&rtp);
  /* rtp time jumps are checked for during skew calculation, but bypassed
   * in other mode, so mind those here and reset jb if needed.
   * Only reset if valid input time, which is likely for UDP input
   * where we expect this might happen due to async thread effects
   * (in seek and state change cycles), but not so much for TCP input */
  if (GST_CLOCK_TIME_IS_VALID (time) &&
      jbuf->mode != RTP_JITTER_BUFFER_MODE_SLAVE &&
      jbuf->base_time != -1 && jbuf->last_rtptime != -1) {
    GstClockTime ext_rtptime = jbuf->ext_rtptime;

    ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
    if (ext_rtptime > jbuf->last_rtptime + 3 * clock_rate ||
        ext_rtptime + 3 * clock_rate < jbuf->last_rtptime) {
      /* reset even if we don't have valid incoming time;
       * still better than producing possibly very bogus output timestamp */
      GST_WARNING ("rtp delta too big, reset skew");
      rtp_jitter_buffer_reset_skew (jbuf);
    }
  }

  switch (jbuf->mode) {
    case RTP_JITTER_BUFFER_MODE_NONE:
    case RTP_JITTER_BUFFER_MODE_BUFFER:
      /* send 0 as the first timestamp and -1 for the other ones. This will
       * interpollate them from the RTP timestamps with a 0 origin. In buffering
       * mode we will adjust the outgoing timestamps according to the amount of
       * time we spent buffering. */
      if (jbuf->base_time == -1)
        time = 0;
      else
        time = -1;
      break;
    case RTP_JITTER_BUFFER_MODE_SLAVE:
    default:
      break;
  }
  /* do skew calculation by measuring the difference between rtptime and the
   * receive time, this function will retimestamp @buf with the skew corrected
   * running time. */
  time = calculate_skew (jbuf, rtptime, time, clock_rate);
  GST_BUFFER_TIMESTAMP (buf) = time;

  /* It's more likely that the packet was inserted in the front of the buffer */
  if (G_LIKELY (list))
    g_queue_insert_before (jbuf->packets, list, buf);
  else
    g_queue_push_tail (jbuf->packets, buf);

  /* buffering mode, update buffer stats */
  if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
    update_buffer_level (jbuf, percent);
  else
    *percent = -1;

  /* tail was changed when we did not find a previous packet, we set the return
   * flag when requested. */
  if (G_LIKELY (tail))
    *tail = (list == NULL);

  gst_rtp_buffer_unmap (&rtp);

  return TRUE;

  /* ERRORS */
duplicate:
  {
    gst_rtp_buffer_unmap (&rtp);
    GST_WARNING ("duplicate packet %d found", (gint) seqnum);
    return FALSE;
  }
}
Beispiel #11
0
/**
 * rtp_jitter_buffer_insert:
 * @jbuf: an #RTPJitterBuffer
 * @buf: a buffer
 * @time: a running_time when this buffer was received in nanoseconds
 * @clock_rate: the clock-rate of the payload of @buf
 * @max_delay: the maximum lateness of @buf
 * @tail: TRUE when the tail element changed.
 *
 * Inserts @buf into the packet queue of @jbuf. The sequence number of the
 * packet will be used to sort the packets. This function takes ownerhip of
 * @buf when the function returns %TRUE.
 * @buf should have writable metadata when calling this function.
 *
 * Returns: %FALSE if a packet with the same number already existed.
 */
gboolean
rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, GstBuffer * buf,
    GstClockTime time, guint32 clock_rate, gboolean * tail, gint * percent)
{
  GList *list;
  guint32 rtptime;
  guint16 seqnum;

  g_return_val_if_fail (jbuf != NULL, FALSE);
  g_return_val_if_fail (buf != NULL, FALSE);

  seqnum = gst_rtp_buffer_get_seq (buf);

  /* loop the list to skip strictly smaller seqnum buffers */
  for (list = jbuf->packets->head; list; list = g_list_next (list)) {
    guint16 qseq;
    gint gap;

    qseq = gst_rtp_buffer_get_seq (GST_BUFFER_CAST (list->data));

    /* compare the new seqnum to the one in the buffer */
    gap = gst_rtp_buffer_compare_seqnum (seqnum, qseq);

    /* we hit a packet with the same seqnum, notify a duplicate */
    if (G_UNLIKELY (gap == 0))
      goto duplicate;

    /* seqnum > qseq, we can stop looking */
    if (G_LIKELY (gap < 0))
      break;
  }

  rtptime = gst_rtp_buffer_get_timestamp (buf);
  switch (jbuf->mode) {
    case RTP_JITTER_BUFFER_MODE_NONE:
    case RTP_JITTER_BUFFER_MODE_BUFFER:
      /* send 0 as the first timestamp and -1 for the other ones. This will
       * interpollate them from the RTP timestamps with a 0 origin. In buffering
       * mode we will adjust the outgoing timestamps according to the amount of
       * time we spent buffering. */
      if (jbuf->base_time == -1)
        time = 0;
      else
        time = -1;
      break;
    case RTP_JITTER_BUFFER_MODE_SLAVE:
    default:
      break;
  }
  /* do skew calculation by measuring the difference between rtptime and the
   * receive time, this function will retimestamp @buf with the skew corrected
   * running time. */
  time = calculate_skew (jbuf, rtptime, time, clock_rate);
  GST_BUFFER_TIMESTAMP (buf) = time;

  /* It's more likely that the packet was inserted in the front of the buffer */
  if (G_LIKELY (list))
    g_queue_insert_before (jbuf->packets, list, buf);
  else
    g_queue_push_tail (jbuf->packets, buf);

  /* buffering mode, update buffer stats */
  if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
    update_buffer_level (jbuf, percent);
  else
    *percent = -1;

  /* tail was changed when we did not find a previous packet, we set the return
   * flag when requested. */
  if (G_LIKELY (tail))
    *tail = (list == NULL);

  return TRUE;

  /* ERRORS */
duplicate:
  {
    GST_WARNING ("duplicate packet %d found", (gint) seqnum);
    return FALSE;
  }
}
Beispiel #12
0
void rtOtvetTreeEmulatorEddingtonTensor(int level, int num_level_cells, int *level_cells)
{
  const int NumSmooth = 2;
  const double S1 = 1.0;
  const double S2 = (S1-1)/nDim;

  int i, j, k, l, cell, parent;
  int nb3[nDim], nb18[rtStencilSize];
  int num_parent_cells, *parent_cells;
  float norm, h2, eps2, *tmp;
  float ot, et[rt_num_et_vars], sor;
  double r2, q;

  if(level == min_level)
    {
      root_grid_fft_exec(RT_VAR_SOURCE,rtNumOtvetETVars-1,rtOtvetETVars+1,rtOtvetTopLevelFFTWorker);

      start_time(WORK_TIMER);

      /*
      //  Normalize
      */
#pragma omp parallel for default(none), private(i,j,cell), shared(num_level_cells,level_cells,cell_vars)
      for(i=0; i<num_level_cells; i++)
	{
	  cell = level_cells[i];

	  cell_var(cell,RT_VAR_OT_FIELD) = cell_var(cell,rt_et_offset+0)
#if (nDim > 1)
	    + cell_var(cell,rt_et_offset+2)
#if (nDim > 2)
	    + cell_var(cell,rt_et_offset+5)
#endif /* nDim > 2 */
#endif /* nDim > 1 */
	    ;

	  if(cell_var(cell,RT_VAR_OT_FIELD) > 0.0)
	    {
	      for(j=0; j<rt_num_et_vars; j++)
		{
		  cell_var(cell,rt_et_offset+j) /= cell_var(cell,RT_VAR_OT_FIELD);
		}
	    }
	  else
	    {
	      cell_var(cell,RT_VAR_OT_FIELD) = 0.0;
	      cell_var(cell,rt_et_offset+0) = 1.0/nDim;
#if (nDim > 1)
	      cell_var(cell,rt_et_offset+1) = 0.0;
	      cell_var(cell,rt_et_offset+2) = 1.0/nDim;
#if (nDim > 2)
	      cell_var(cell,rt_et_offset+3) = 0.0;
	      cell_var(cell,rt_et_offset+4) = 0.0;
	      cell_var(cell,rt_et_offset+5) = 1.0/nDim;
#endif /* nDim > 2 */
#endif /* nDim > 1 */
	    }
	}

      end_time(WORK_TIMER);

    }
  else
    {

      start_time(WORK_TIMER);

      /*
      // We start with interpolating from parents
      */
      select_level(level-1,CELL_TYPE_LOCAL | CELL_TYPE_REFINED,&num_parent_cells,&parent_cells);

      h2 = cell_size[level]*cell_size[level];
      norm = cell_volume[level]/(4*M_PI*h2);

      if(level == 1)
	{
	  eps2 = 0.1;
	}
      else
	{
	  eps2 = 0.05;
	}

#pragma omp parallel for default(none), private(i,j,k,parent,cell,ot,et,nb3,nb18,sor,l,r2,q), shared(level,num_parent_cells,parent_cells,cell_vars,cell_child_oct,norm,h2,rtStencilDist2,rtStencilTensor,eps2)
      for(i=0; i<num_parent_cells; i++)
	{
	  parent = parent_cells[i];

	  /*
	  //  Loop over all children
	  */
	  for(j=0; j<num_children; j++)
	    {
	      /*
	      //  Interpolate from parents and turn ET into OT radiation pressure tensor
	      */
	      cell_interpolation_neighbors(parent,j,nb3);

	      /*
	      //  NG: this is the best interpolation, I did check two other forms
	      */
	      ot = cell_interpolate_with_neighbors(parent,RT_VAR_OT_FIELD,nb3);
	      for(k=0; k<rt_num_et_vars; k++)
		{
		  et[k] = ot*cell_interpolate_with_neighbors(parent,rt_et_offset+k,nb3);
		}

	      cell = cell_child(parent,j);
	      
	      /*
	      //  Add local contributions from 18 neighbors
	      */
	      rtGetStencil(level,cell,nb18);
	      for(l=0; l<rtStencilSize; l++) if((sor = cell_rt_source(nb18[l])) > 0.0)
		{
		  r2 = rtStencilDist2[l];

		  sor *= norm/(r2+eps2);

		  ot += sor;

		  et[0] += sor*(S1*rtStencilTensor[l][0]-S2);
#if (nDim > 1)
		  et[1] += sor*rtStencilTensor[l][1];
		  et[2] += sor*(S1*rtStencilTensor[l][2]-S2);
#if (nDim > 2)
		  et[3] += sor*rtStencilTensor[l][3];
		  et[4] += sor*rtStencilTensor[l][4];
		  et[5] += sor*(S1*rtStencilTensor[l][5]-S2);
#endif /* nDim > 2 */
#endif /* nDim > 1 */
		}

	      cell_var(cell,RT_VAR_OT_FIELD) = ot;
	      if(ot > 0.0)
		{
		  q = et[0]
#if (nDim > 1)
		    + et[2]
#if (nDim > 2)
		    + et[5]
#endif /* nDim > 2 */
#endif /* nDim > 1 */
		    ;
		  for(k=0; k<rt_num_et_vars; k++)
		    {
		      cell_var(cell,rt_et_offset+k) = et[k]/q;
		    }
		}
	      else
		{
		  cell_var(cell,rt_et_offset+0) = 1.0/nDim;
#if (nDim > 1)
		  cell_var(cell,rt_et_offset+1) = 0.0;
		  cell_var(cell,rt_et_offset+2) = 1.0/nDim;
#if (nDim > 2)
		  cell_var(cell,rt_et_offset+3) = 0.0;
		  cell_var(cell,rt_et_offset+4) = 0.0;
		  cell_var(cell,rt_et_offset+5) = 1.0/nDim;
#endif /* nDim > 2 */
#endif /* nDim > 1 */
		}
	    }
	}
      
      cart_free(parent_cells);

      end_time(WORK_TIMER);

    }
 
  start_time(RT_TREE_EMULATOR_UPDATE_TIMER);
  update_buffer_level(level,rtOtvetETVars,rtNumOtvetETVars);
  end_time(RT_TREE_EMULATOR_UPDATE_TIMER);

  /*
  // Smooth a few times
  */
  start_time(WORK_TIMER);
  tmp = cart_alloc(float, num_level_cells*rt_num_et_vars);
  end_time(WORK_TIMER);

  for(l=0; l<NumSmooth; l++)
    {

      start_time(WORK_TIMER);

#pragma omp parallel for default(none), private(i,j,k,cell,et,nb18), shared(level,num_level_cells,level_cells,cell_vars,tmp)
      for(i=0; i<num_level_cells; i++)
	{
	  cell = level_cells[i];

	  rtGetStencil(level,cell,nb18);
	  //cell_all_neighbors(cell,nb18);

	  for(k=0; k<rt_num_et_vars; k++) et[k] = 2*cell_var(cell,rt_et_offset+k);

	  for(j=0; j<rtStencilSize; j++)
	    //for(j=0; j<num_neighbors; j++)
	    {
	      for(k=0; k<rt_num_et_vars; k++)
		{
		  et[k] += cell_var(nb18[j],rt_et_offset+k);
		}
	    }

	  for(k=0; k<rt_num_et_vars; k++) tmp[i*rt_num_et_vars+k] = et[k]/(2+rtStencilSize);
	}

#pragma omp parallel for default(none), private(i,k,cell), shared(level,num_level_cells,level_cells,cell_vars,tmp)
      for(i=0; i<num_level_cells; i++)
	{
	  cell = level_cells[i];
	  
	  for(k=0; k<rt_num_et_vars; k++)
	    {
	      cell_var(cell,rt_et_offset+k) = tmp[i*rt_num_et_vars+k];
	    }
	}

      end_time(WORK_TIMER);

      start_time(RT_TREE_EMULATOR_UPDATE_TIMER);
      update_buffer_level(level,rtOtvetETVars+1,rtNumOtvetETVars-1);
      end_time(RT_TREE_EMULATOR_UPDATE_TIMER);
    }

  start_time(WORK_TIMER);
  cart_free(tmp);
  end_time(WORK_TIMER);

}