/* interpolate Ne data near time t to latitude qdlat */ double interp_ne(const time_t t, const double qdlat, const satdata_mag *data) { double t_cdf = satdata_timet2epoch(t); double Ne; if (t_cdf >= data->t[0] && t_cdf <= data->t[data->n - 1]) { int idx = (int) bsearch_double(data->t, t_cdf, 0, data->n - 1); int half_window = 15; /* number of minutes in half time window */ int idx1 = GSL_MAX(0, idx - half_window*60*2); int idx2 = GSL_MIN(data->n - 1, idx + half_window*60*2); int qidx; if (data->qdlat[idx1] < data->qdlat[idx2]) qidx = (int) bsearch_double(data->qdlat, qdlat, idx1, idx2); else qidx = (int) bsearch_desc_double(data->qdlat, qdlat, idx1, idx2); Ne = interp1d(data->qdlat[qidx], data->qdlat[qidx + 1], data->ne[qidx], data->ne[qidx + 1], qdlat); } else Ne = 0.0; return Ne; }
/* * binary search a sorted double array 'arr' of size 'n'. if found, * the 'loc' pointer has the address of 'ele' and the return * value is TRUE. otherwise, the return value is FALSE and 'loc' * points to the 'should have been' location */ int bsearch_double(double *arr, int n, double ele, double **loc) { if(n < 0) fatal("wrong index in binary search\n"); if(n == 0) { *loc = arr; return FALSE; } if(eq(arr[n/2], ele)) { *loc = &arr[n/2]; return TRUE; } else if (arr[n/2] < ele) { return bsearch_double(&arr[n/2+1], (n-1)/2, ele, loc); } else return bsearch_double(arr, n/2, ele, loc); }
/* * binary search and insert an element into a partially sorted * double array if not already present. returns FALSE if present */ int bsearch_insert_double(double *arr, int n, double ele) { double *loc; int i; /* element found - nothing more left to do */ if (bsearch_double(arr, n, ele, &loc)) return FALSE; else { for(i=n-1; i >= (loc-arr); i--) arr[i+1] = arr[i]; arr[loc-arr] = ele; } return TRUE; }
int fill_dens(magdata *mdata, const satdata_lp *dens_data) { int s = 0; size_t i; /* initialize ne array */ for (i = 0; i < mdata->n; ++i) mdata->ne[i] = 0.0; for (i = 0; i < mdata->n; ++i) { double t = mdata->t[i]; size_t idx; double dt, ne; double t0, t1; if (t < dens_data->t[0] || t > dens_data->t[dens_data->n - 1]) continue; idx = bsearch_double(dens_data->t, t, 0, dens_data->n); t0 = dens_data->t[idx]; t1 = dens_data->t[idx + 1]; dt = t1 - t0; dt /= 1000.0; /* convert to s */ /* check for data gaps in PLP measurements */ if (fabs(dt) > 30.0) continue; ne = interp1d(t0, t1, dens_data->ne[idx], dens_data->ne[idx + 1], t); mdata->ne[i] = ne; } return s; }
/* * create a non-uniform grid-like floorplan equivalent to this. * this function is mainly useful when using the HotSpot block * model to model floorplans of drastically differing aspect * ratios and granularity. an example for such a floorplan * would be the standard ev6 floorplan that comes with HotSpot, * where the register file is subdivided into say 128 entries. * the HotSpot block model could result in inaccuracies while * trying to model such floorplans of differing granularity. * if such inaccuracies occur, use this function to create an * equivalent floorplan that can be modeled accurately in * HotSpot. 'map', if non-NULL, is an output parameter to store * the 2-d array allocated by the function. */ flp_t *flp_create_grid(flp_t *flp, int ***map) { double x[MAX_UNITS], y[MAX_UNITS]; int i, j, n, xsize=0, ysize=0, count=0, found, **ptr; flp_t *grid; /* sort the units' boundary co-ordinates */ for(i=0; i < flp->n_units; i++) { double r, t; r = flp->units[i].leftx + flp->units[i].width; t = flp->units[i].bottomy + flp->units[i].height; if(bsearch_insert_double(x, xsize, flp->units[i].leftx)) xsize++; if(bsearch_insert_double(y, ysize, flp->units[i].bottomy)) ysize++; if(bsearch_insert_double(x, xsize, r)) xsize++; if(bsearch_insert_double(y, ysize, t)) ysize++; } /* * the grid formed by the lines from x and y arrays * is our desired floorplan. allocate memory for it */ grid = (flp_t *) calloc (1, sizeof(flp_t)); if(!grid) fatal("memory allocation error\n"); grid->n_units = (xsize-1) * (ysize-1); grid->units = (unit_t *) calloc (grid->n_units, sizeof(unit_t)); grid->wire_density = (double **) calloc(grid->n_units, sizeof(double *)); if (!grid->units || !grid->wire_density) fatal("memory allocation error\n"); for (i=0; i < grid->n_units; i++) { grid->wire_density[i] = (double *) calloc(grid->n_units, sizeof(double)); if (!grid->wire_density[i]) fatal("memory allocation error\n"); } /* mapping between blocks of 'flp' to those of 'grid' */ ptr = (int **) calloc(flp->n_units, sizeof(int *)); if (!ptr) fatal("memory allocation error\n"); /* * ptr is a 2-d array with each row of possibly different * length. the size of each row is stored in its first element. * here, it is basically the mapping between 'flp' to 'grid' * i.e., for each flp->unit, it stores the set of grid->units * it maps to. */ for(i=0; i < flp->n_units; i++) { ptr[i] = (int *) calloc(grid->n_units+1, sizeof(int)); if(!ptr[i]) fatal("memory allocation error\n"); } /* * now populate the 'grid' blocks and map the blocks * from 'flp' to 'grid'. for each block, identify the * intervening lines that chop it into grid cells and * assign the names of those cells from that of the * block */ for(i=0; i < flp->n_units; i++) { double *xstart, *xend, *ystart, *yend; double *ptr1, *ptr2; int grid_num=0; if (!bsearch_double(x, xsize, flp->units[i].leftx, &xstart)) fatal("invalid sorted arrays\n"); if (!bsearch_double(x, xsize, flp->units[i].leftx+flp->units[i].width, &xend)) fatal("invalid sorted arrays\n"); if (!bsearch_double(y, ysize, flp->units[i].bottomy, &ystart)) fatal("invalid sorted arrays\n"); if (!bsearch_double(y, ysize, flp->units[i].bottomy+flp->units[i].height, ¥d)) fatal("invalid sorted arrays\n"); for(ptr1 = xstart; ptr1 < xend; ptr1++) for(ptr2 = ystart; ptr2 < yend; ptr2++) { /* add this grid block if it has not been added already */ for(n=0, found=FALSE; n < count; n++) { if (grid->units[n].leftx == ptr1[0] && grid->units[n].bottomy == ptr2[0]) { found = TRUE; break; } } if(!found) { sprintf(grid->units[count].name, "%s_%d", flp->units[i].name, grid_num); grid->units[count].leftx = ptr1[0]; grid->units[count].bottomy = ptr2[0]; grid->units[count].width = ptr1[1]-ptr1[0]; grid->units[count].height = ptr2[1]-ptr2[0]; } /* map between position in 'flp' to that in 'grid' */ ptr[i][++ptr[i][0]] = count; grid_num++; count++; } } /* sanity check */ if(count != (xsize-1) * (ysize-1)) fatal("mismatch in the no. of units\n"); /* fill-in the wire densities */ for(i=0; i < flp->n_units; i++) for(j=0; j < flp->n_units; j++) { int p, q; for(p=1; p <= ptr[i][0]; p++) for(q=1; q <= ptr[j][0]; q++) grid->wire_density[ptr[i][p]][ptr[j][q]] = flp->wire_density[i][j]; } /* output the map */ if (map) (*map) = ptr; else free_blkgrid_map(flp, ptr); return grid; }
int track_smooth(const double alpha, satdata_mag *data, track_workspace *w) { int s = 0; size_t i, j; for (i = 0; i < w->n; ++i) { track_data *tptr = &(w->tracks[i]); size_t sidx = tptr->start_idx; size_t eidx = tptr->end_idx; size_t idxs, idxn; size_t npts; if (tptr->satdir == 1) { idxn = bsearch_double(&data->qdlat[sidx], 55.0, 0, tptr->n - 1); idxs = bsearch_double(&data->qdlat[sidx], -55.0, 0, tptr->n - 1); npts = tptr->n - idxn; track_ema(alpha, &data->flags[sidx + idxn], &tptr->Bf[idxn], npts); track_ema(alpha, &data->flags[sidx + idxn], &tptr->Bx[idxn], npts); track_ema(alpha, &data->flags[sidx + idxn], &tptr->By[idxn], npts); track_ema(alpha, &data->flags[sidx + idxn], &tptr->Bz[idxn], npts); npts = idxs + 1; track_ema_reverse(alpha, &data->flags[sidx], tptr->Bf, npts); track_ema_reverse(alpha, &data->flags[sidx], tptr->Bx, npts); track_ema_reverse(alpha, &data->flags[sidx], tptr->By, npts); track_ema_reverse(alpha, &data->flags[sidx], tptr->Bz, npts); } else { idxn = bsearch_desc_double(&data->qdlat[sidx], 55.0, 0, tptr->n - 1); idxs = bsearch_desc_double(&data->qdlat[sidx], -55.0, 0, tptr->n - 1); npts = idxn + 1; track_ema_reverse(alpha, &data->flags[sidx], tptr->Bf, npts); track_ema_reverse(alpha, &data->flags[sidx], tptr->Bx, npts); track_ema_reverse(alpha, &data->flags[sidx], tptr->By, npts); track_ema_reverse(alpha, &data->flags[sidx], tptr->Bz, npts); npts = tptr->n - idxs; track_ema(alpha, &data->flags[sidx + idxs], &tptr->Bf[idxs], npts); track_ema(alpha, &data->flags[sidx + idxs], &tptr->Bx[idxs], npts); track_ema(alpha, &data->flags[sidx + idxs], &tptr->By[idxs], npts); track_ema(alpha, &data->flags[sidx + idxs], &tptr->Bz[idxs], npts); } /* recompute data arrays with smoothed residuals */ for (j = sidx; j <= eidx; ++j) { double B_model[4]; satdata_mag_model(j, B_model, data); SATDATA_VEC_X(data->B, j) = tptr->Bx[j - sidx] + B_model[0]; SATDATA_VEC_Y(data->B, j) = tptr->By[j - sidx] + B_model[1]; SATDATA_VEC_Z(data->B, j) = tptr->Bz[j - sidx] + B_model[2]; data->F[j] = tptr->Bf[j - sidx] + B_model[3]; } /* recompute residuals with smoothed data */ track_calc_residuals(tptr, data); } return s; } /* track_smooth() */
size_t track_init(satdata_mag *data, msynth_workspace *msynth_p, track_workspace *w) { size_t nflagged = 0; size_t i = 0, j; w->data = data; while (i < data->n - 1) { int s; double lon_eq, t_eq, lt_eq; size_t sidx, eidx; track_data *tptr; s = satdata_mag_find_track(i, &eidx, data); if (s) { #if TRACK_DEBUG fprintf(stderr, "track_init: no more tracks found in [%zu, %zu]\n", sidx, data->n - 1); #endif break; } /* update index i for next loop */ sidx = i; i = eidx + 1; /* check for equator crossing */ if (data->latitude[sidx] * data->latitude[eidx] < 0.0) { size_t idx; time_t unix_time; /* there is an equator crossing, find time and longitude */ if (data->latitude[eidx] > data->latitude[sidx]) idx = bsearch_double(data->latitude, 0.0, sidx, eidx); else if (data->latitude[eidx] < data->latitude[sidx]) idx = bsearch_desc_double(data->latitude, 0.0, sidx, eidx); /* sanity check we found equator crossing */ assert(data->latitude[idx] * data->latitude[idx + 1] < 0.0); /* interpolate t, but not longitude due to wrapping effects */ t_eq = interp1d(data->latitude[idx], data->latitude[idx + 1], data->t[idx], data->t[idx + 1], 0.0); lon_eq = data->longitude[idx]; /* compute local time */ unix_time = satdata_epoch2timet(t_eq); lt_eq = get_localtime(unix_time, lon_eq * M_PI / 180.0); } else { /* no equator crossing */ #if TRACK_DEBUG fprintf(stderr, "track_init: flagging partial track [%zu, %zu]\n", sidx, eidx); #endif nflagged += track_flag_data(sidx, eidx, data); continue; } /* compute main field along track in data->F_main */ if (msynth_p) track_calc_mf(sidx, eidx, data, msynth_p); /* store this track information */ tptr = &(w->tracks[w->n]); tptr->start_idx = sidx; tptr->end_idx = eidx; tptr->n = eidx - sidx + 1; tptr->t_eq = t_eq; tptr->lon_eq = lon_eq; tptr->lt_eq = lt_eq; tptr->nrms_scal = 0; tptr->nrms_vec = 0; tptr->flags = 0; tptr->k_ext = 0.0; tptr->meanalt = gsl_stats_mean(&(data->altitude[sidx]), 1, tptr->n); /* use index of track center to compute satellite direction */ tptr->satdir = satdata_mag_satdir(sidx + tptr->n / 2, data); for (j = 0; j < 3; ++j) tptr->rms[j] = 0.0; assert(tptr->n > 0); /* compute and store along-track residuals */ tptr->Bx = malloc(tptr->n * sizeof(double)); tptr->By = malloc(tptr->n * sizeof(double)); tptr->Bz = malloc(tptr->n * sizeof(double)); tptr->Bf = malloc(tptr->n * sizeof(double)); track_calc_residuals(tptr, data); if (++(w->n) >= w->ntot) { fprintf(stderr, "track_init: ntot not large enough: %zu\n", w->ntot); return nflagged; } } #if TRACK_DEBUG fprintf(stderr, "track_init: found %zu tracks\n", w->n); #endif return nflagged; } /* track_init() */