int model_z2fk(model* m, int vid, double fi, double fj, double z, double* fk) { void* grid = m->grids[m->vars[vid].gridid]; int isperiodic_x = grid_isperiodic_x(grid); int** numlevels = grid_getnumlevels(grid); int ni, nj; int i1, i2, j1, j2, k2; if (isnan(fi + fj)) { *fk = NaN; return STATUS_OUTSIDEGRID; } grid_z2fk(grid, fi, fj, z, fk); if (isnan(*fk)) return STATUS_OUTSIDEGRID; if (grid_getvtype(grid) == GRIDVTYPE_SIGMA) return STATUS_OK; /* * a depth check for z-grid: */ model_getvardims(m, vid, &ni, &nj, NULL); i1 = floor(fi); i2 = ceil(fi); if (i1 == -1) i1 = (isperiodic_x) ? ni - 1 : i2; if (i2 == ni) i2 = (isperiodic_x) ? 0 : i1; j1 = floor(fj); j2 = ceil(fj); if (j1 == -1) j1 = j2; if (j2 == nj) j2 = j1; k2 = floor(*fk); if (numlevels[j1][i1] <= k2 && numlevels[j1][i2] <= k2 && numlevels[j2][i1] <= k2 && numlevels[j2][i2] <= k2) { *fk = NaN; return STATUS_LAND; } else if (numlevels[j1][i1] <= k2 || numlevels[j1][i2] <= k2 || numlevels[j2][i1] <= k2 || numlevels[j2][i2] <= k2) { float** depth = grid_getdepth(grid); int ni, nj; double v; grid_getdims(grid, &ni, &nj, NULL); v = interpolate2d(fi, fj, ni, nj, depth, numlevels, grid_isperiodic_x(grid)); if (z > v) return STATUS_LAND; } return STATUS_OK; }
void reader_cars_standard(char* fname, int fid, obsmeta* meta, grid* g, observations* obs) { int ncid; int dimid_nprof, dimid_nz = -1; size_t nprof, nz; int varid_lon, varid_lat, varid_z, varid_type; int varid_v = -1; double* lon; double* lat; double** z; double** v; double missval, validmin, validmax; int* type; char buf[MAXSTRLEN]; int len; int year, month, day; double tunits_multiple, tunits_offset; int p, i; for (i = 0; i < meta->npars; ++i) enkf_quit("unknown PARAMETER \"%s\"\n", meta->pars[i].name); if (meta->nstds == 0) enkf_quit("ERROR_STD is necessary but not specified for product \"%s\"", meta->product); ncw_open(fname, NC_NOWRITE, &ncid); ncw_inq_dimid(ncid, "nobs", &dimid_nprof); ncw_inq_dimlen(ncid, dimid_nprof, &nprof); enkf_printf(" # profiles = %u\n", (unsigned int) nprof); if (nprof == 0) { ncw_close(ncid); return; } if (ncw_dim_exists(ncid, "zt")) ncw_inq_dimid(ncid, "zt", &dimid_nz); else if (ncw_dim_exists(ncid, "ztd")) ncw_inq_dimid(ncid, "ztd", &dimid_nz); else enkf_quit("reader_cars_standard(): neither dimension \"zt\" ot \"ztd\" exist"); ncw_inq_dimlen(ncid, dimid_nz, &nz); enkf_printf(" # z levels = %u\n", (unsigned int) nz); ncw_inq_varid(ncid, "lon", &varid_lon); lon = malloc(nprof * sizeof(double)); ncw_get_var_double(ncid, varid_lon, lon); ncw_inq_varid(ncid, "lat", &varid_lat); lat = malloc(nprof * sizeof(double)); ncw_get_var_double(ncid, varid_lat, lat); ncw_inq_varid(ncid, "zt", &varid_z); z = alloc2d(nprof, nz, sizeof(double)); ncw_get_var_double(ncid, varid_z, z[0]); if (strncmp(meta->type, "TEM", 3) == 0) ncw_inq_varid(ncid, "temp", &varid_v); else if (strncmp(meta->type, "SAL", 3) == 0) ncw_inq_varid(ncid, "salt", &varid_v); else enkf_quit("observation type \"%s\" not handled for CARS product", meta->type); v = alloc2d(nprof, nz, sizeof(double)); ncw_get_var_double(ncid, varid_v, v[0]); ncw_get_att_double(ncid, varid_v, "missing_value", &missval); ncw_get_att_double(ncid, varid_v, "valid_min", &validmin); ncw_get_att_double(ncid, varid_v, "valid_max", &validmax); ncw_inq_varid(ncid, "type", &varid_type); type = malloc(nprof * sizeof(int)); ncw_get_var_int(ncid, varid_type, type); ncw_close(ncid); strcpy(buf, fname); len = strlen(buf); buf[len - 3] = 0; /* .nc */ if (!str2int(&buf[len - 5], &day)) enkf_quit("CARS reader: could not convert file name \"%s\" to date", fname); buf[len - 17] = 0; if (!str2int(&buf[len - 19], &month)) enkf_quit("CARS reader: could not convert file name \"%s\" to date", fname); buf[len - 21] = 0; if (!str2int(&buf[len - 25], &year)) enkf_quit("CARS reader: could not convert file name \"%s\" to date", fname); snprintf(buf, MAXSTRLEN, "days since %4d-%02d-%02d", year, month, day); tunits_convert(buf, &tunits_multiple, &tunits_offset); for (p = 0; p < (int) nprof; ++p) { char inststr[MAXSTRLEN]; if (type[p] == 11) strcpy(inststr, "ARGO"); else if (type[p] == 12) strcpy(inststr, "TAO"); else if (type[p] == 61) strcpy(inststr, "PIRATA"); else if (type[p] == 7 || type[p] == 9 || type[p] == 13 || type[p] == 35 || type[p] == 41) strcpy(inststr, "CTD"); else if (type[p] == 8 || type[p] == 17) strcpy(inststr, "XBT"); else snprintf(inststr, MAXSTRLEN, "CARS%02u", type[p]); for (i = 0; i < (int) nz; ++i) { observation* o; obstype* ot; if (fabs(v[p][i] - missval) < EPS || v[p][i] < validmin || v[p][i] > validmax) continue; if (z[p][i] < 0.0) continue; obs_checkalloc(obs); o = &obs->data[obs->nobs]; o->product = st_findindexbystring(obs->products, meta->product); assert(o->product >= 0); o->type = obstype_getid(obs->nobstypes, obs->obstypes, meta->type, 1); ot = &obs->obstypes[o->type]; o->instrument = st_add_ifabsent(obs->instruments, inststr, -1); o->id = obs->nobs; o->fid = fid; o->batch = p; o->value = v[p][i]; o->std = 0.0; o->lon = lon[p]; o->lat = lat[p]; o->depth = z[p][i]; o->status = grid_xy2fij(g, o->lon, o->lat, &o->fi, &o->fj); if (!obs->allobs && o->status == STATUS_OUTSIDEGRID) break; if (o->status == STATUS_OK) o->status = grid_z2fk(g, o->fi, o->fj, o->depth, &o->fk); else o->fk = NAN; if ((o->status == STATUS_OK) && (o->lon <= ot->xmin || o->lon >= ot->xmax || o->lat <= ot->ymin || o->lat >= ot->ymax || o->depth <= ot->zmin || o->depth >= ot->zmax)) o->status = STATUS_OUTSIDEOBSDOMAIN; o->model_depth = NAN; /* set in obs_add() */ o->date = tunits_offset + 0.5; o->aux = -1; obs->nobs++; } } free(lon); free(lat); free(v); free(z); free(type); }
int model_z2fk(model* m, int vid, double fi, double fj, double z, double* fk) { return grid_z2fk(m->grids[m->vars[vid].gridid], fi, fj, z, fk); }