예제 #1
0
/**
 * Adds a double to a GPS time.  Computes epoch + dt and places the result
 * in epoch.  Returns epoch on success, NULL on error.
 */
LIGOTimeGPS * XLALGPSAdd( LIGOTimeGPS *epoch, REAL8 dt )
{
  LIGOTimeGPS dt_gps;
  if(!XLALGPSSetREAL8(&dt_gps, dt))
    XLAL_ERROR_NULL(XLAL_EFUNC);
  return XLALGPSAddGPS(epoch, &dt_gps);
}
예제 #2
0
/**
 * Multiply a GPS time by a number.  Computes gps * x and places the result
 * in gps.  Returns gps on success, NULL on failure.
 */
LIGOTimeGPS *XLALGPSMultiply( LIGOTimeGPS *gps, REAL8 x )
{
  LIGOTimeGPS workspace = *gps;
  double slo, shi;
  double xlo, xhi;
  double addendlo[4], addendhi[4];

  if(isnan(x) || isinf(x)) {
    XLALPrintError("%s(): invalid multiplicand %g", __func__, x);
    XLAL_ERROR_NULL(XLAL_EFPINVAL);
  }

  /* ensure the seconds and nanoseconds components have the same sign so
   * that the addend fragments we compute below all have the same sign */

  if(workspace.gpsSeconds < 0 && workspace.gpsNanoSeconds > 0) {
    workspace.gpsSeconds += 1;
    workspace.gpsNanoSeconds -= 1000000000;
  } else if(workspace.gpsSeconds > 0 && workspace.gpsNanoSeconds < 0) {
    workspace.gpsSeconds -= 1;
    workspace.gpsNanoSeconds += 1000000000;
  }

  /* split seconds and multiplicand x into leading-order and low-order
   * components */

  slo = workspace.gpsSeconds % (1<<16);
  shi = workspace.gpsSeconds - slo;
  split_double(x, &xhi, &xlo);

  /* the count of seconds and the multiplicand x have each been split into
   * two parts, a high part and a low part.  from these, there are 4 terms
   * in their product, and each term has sufficiently low dynamic range
   * that it can be computed using double precision floating point
   * arithmetic.  we compute the 4 terms, split each into an integer and
   * fractional part on its own, then sum the fractional parts and integer
   * parts separately, adding the product of the nanoseconds and x into the
   * fractional parts when summing them.  because the storage locations for
   * those sums have relatively low dynamic range no care need be taken in
   * computing the sums. */

  addendlo[0] = modf(slo * xlo, &addendhi[0]);
  addendlo[1] = modf(shi * xlo, &addendhi[1]);
  addendlo[2] = modf(slo * xhi, &addendhi[2]);
  addendlo[3] = modf(shi * xhi, &addendhi[3]);

  /* initialize result with the sum of components that contribute to the
   * fractional part */
  if(!XLALGPSSetREAL8(gps, addendlo[0] + addendlo[1] + addendlo[2] + addendlo[3] + workspace.gpsNanoSeconds * x / XLAL_BILLION_REAL8))
    XLAL_ERROR_NULL(XLAL_EFUNC);
  /* now add the components that contribute only to the integer seconds
   * part */
  if(!XLALGPSSetREAL8(&workspace, addendhi[0] + addendhi[1] + addendhi[2] + addendhi[3]))
    XLAL_ERROR_NULL(XLAL_EFUNC);
  return XLALGPSAddGPS(gps, &workspace);
}
예제 #3
0
static PyObject *__add__(PyObject *self, PyObject *other)
{
	LIGOTimeGPS self_gps;
	LIGOTimeGPS other_gps;

	if(!pyobject_to_ligotimegps(self, &self_gps))
		return NULL;
	if(!pyobject_to_ligotimegps(other, &other_gps))
		return NULL;

	XLALGPSAddGPS(&self_gps, &other_gps);

	return pylal_LIGOTimeGPS_new(self_gps);
}
예제 #4
0
/**
 * Generate the + and x time series for a single sim_burst table row.
 * Note:  only the row pointed to by sim_burst is processed, the linked
 * list is not iterated over.  The hplus and hcross time series objects
 * will be allocated by this function.  The time-at-geocentre is applied,
 * but the time shift offset must be applied separately.  delta_t is the
 * sample interval for the time series.  The return value is 0 in success,
 * non-0 on failure.
 */
int XLALGenerateSimBurst(
	REAL8TimeSeries **hplus,
	REAL8TimeSeries **hcross,
	const SimBurst *sim_burst,
	double delta_t
)
{
	if(!strcmp(sim_burst->waveform, "BTLWNB")) {
		/* E_{GW}/r^{2} is in M_{sun} / pc^{2}, so we multiply by
		 * (M_{sun} c^2) to convert to energy/pc^{2}, and divide by
		 * (distance/pc)^{2} to convert to energy/distance^{2},
		 * which is then multiplied by (4 G / c^3) to convert to a
		 * value of \int \dot{h}^{2} \diff t.  From the values of
		 * the LAL constants, the total factor multiplying
		 * egw_over_rsquared is 1.8597e-21. */

		double int_hdot_squared_dt = sim_burst->egw_over_rsquared * LAL_GMSUN_SI * 4 / LAL_C_SI / LAL_PC_SI / LAL_PC_SI;

		/* the waveform number is interpreted as the seed for GSL's
		 * Mersenne twister random number generator */
		gsl_rng *rng = gsl_rng_alloc(gsl_rng_mt19937);
		if(!rng) {
			XLALPrintError("%s(): failure creating random number generator\n", __func__);
			XLAL_ERROR(XLAL_ENOMEM);
		}
		gsl_rng_set(rng, sim_burst->waveform_number);

		XLALPrintInfo("%s(): BTLWNB @ %9d.%09u s (GPS): f = %.16g Hz, df = %.16g Hz, dt = %.16g s, hdot^2 = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->frequency, sim_burst->bandwidth, sim_burst->duration, int_hdot_squared_dt);
		if(XLALGenerateBandAndTimeLimitedWhiteNoiseBurst(hplus, hcross, sim_burst->duration, sim_burst->frequency, sim_burst->bandwidth, sim_burst->pol_ellipse_e, int_hdot_squared_dt, delta_t, rng)) {
			gsl_rng_free(rng);
			XLAL_ERROR(XLAL_EFUNC);
		}
		gsl_rng_free(rng);
	} else if(!strcmp(sim_burst->waveform, "StringCusp")) {
		XLALPrintInfo("%s(): string cusp @ %9d.%09u s (GPS): A = %.16g, fhigh = %.16g Hz\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->amplitude, sim_burst->frequency);
		if(XLALGenerateStringCusp(hplus, hcross, sim_burst->amplitude, sim_burst->frequency, delta_t))
			XLAL_ERROR(XLAL_EFUNC);
	} else if(!strcmp(sim_burst->waveform, "SineGaussian")) {
		XLALPrintInfo("%s(): sine-Gaussian @ %9d.%09u s (GPS): f = %.16g Hz, Q = %.16g, hrss = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->frequency, sim_burst->q, sim_burst->hrss);
		if(XLALSimBurstSineGaussian(hplus, hcross, sim_burst->q, sim_burst->frequency, sim_burst->hrss, sim_burst->pol_ellipse_e, sim_burst->pol_ellipse_angle, delta_t))
			XLAL_ERROR(XLAL_EFUNC);
	} else if(!strcmp(sim_burst->waveform, "Gaussian")) {
		XLALPrintInfo("%s(): Gaussian @ %9d.%09u s (GPS): duration = %.16g, hrss = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->duration, sim_burst->hrss);
		if(XLALSimBurstGaussian(hplus, hcross, sim_burst->duration, sim_burst->hrss, delta_t))
			XLAL_ERROR(XLAL_EFUNC);
	} else if(!strcmp(sim_burst->waveform, "Impulse")) {
		XLALPrintInfo("%s(): impulse @ %9d.%09u s (GPS): hpeak = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->amplitude);
		if(XLALGenerateImpulseBurst(hplus, hcross, sim_burst->amplitude, delta_t))
			XLAL_ERROR(XLAL_EFUNC);
	} else {
		/* unrecognized waveform */
		XLALPrintError("%s(): error: unrecognized waveform\n", __func__);
		XLAL_ERROR(XLAL_EINVAL);
	}

	/* add the time of the injection at the geocentre to the start
	 * times of the h+ and hx time series.  after this, their epochs
	 * mark the start of those time series at the geocentre. */

	if(!XLALGPSAddGPS(&(*hcross)->epoch, &sim_burst->time_geocent_gps) ||
	   !XLALGPSAddGPS(&(*hplus)->epoch, &sim_burst->time_geocent_gps)) {
		XLALPrintError("%s(): bad geocentre time or waveform too long\n", __func__);
		XLALDestroyREAL8TimeSeries(*hcross);
		XLALDestroyREAL8TimeSeries(*hplus);
		*hplus = *hcross = NULL;
		XLAL_ERROR(XLAL_EFUNC);
	}

	/* done */

	return 0;
}