예제 #1
0
파일: ensobs.c 프로젝트: juicydut/enkf-c
/** Modifies observation error so that the increment for this observation would
 * not exceed KFACTOR * <ensemble spread> (all in observation space) after
 * assimilating this observation only. This can be viewed as an adaptive QC.
 */
void das_moderateobs(dasystem* das)
{
    observations* obs = das->obs;
    double kfactor = das->kfactor;
    double* std_new;
    int i;

    if (obs->nobs == 0)
        return;
    if (!isfinite(kfactor))
        return;

    assert(das->s_mode == S_MODE_HA_f);

    std_new = malloc(obs->nobs * sizeof(double));

    for (i = 0; i < obs->nobs; ++i) {
        observation* o = &obs->data[i];
        double svar = das->std_f[i] * das->std_f[i];
        double ovar = o->std * o->std;
        double inn = das->s_f[i];

        if (o->status != STATUS_OK) {
            std_new[i] = o->std;
            continue;
        }

        std_new[i] = sqrt(sqrt((svar + ovar) * (svar + ovar) + svar * inn * inn / kfactor / kfactor) - svar);
        if (svar > 0.0 && std_new[i] * std_new[i] / ovar > 2.0) {
            obs->nmodified++;
            obs->obstypes[o->type].nmodified++;
        }
    }

    for (i = 0; i < obs->nobs; ++i)
        obs->data[i].std = std_new[i];

    enkf_printf("    observations substantially modified:\n");
    for (i = 0; i < obs->nobstypes; ++i)
        enkf_printf("      %s    %7d (%.1f%%)\n", obs->obstypes[i].name, obs->obstypes[i].nmodified, 100.0 * (double) obs->obstypes[i].nmodified / (double) obs->obstypes[i].nobs);
    enkf_printf("      total  %7d (%.1f%%)\n", obs->nmodified, 100.0 * (double) obs->nmodified / (double) obs->nobs);

    free(std_new);
}
예제 #2
0
파일: ensobs.c 프로젝트: juicydut/enkf-c
/** Sorts all observations by j,i so that they can be processed in a single
 * cycle over horizontal grid cells.
 */
static void das_sortobs_byij(dasystem* das)
{
    observations* obs = das->obs;
    int o, e;

    if (das->sort_mode == OBS_SORTMODE_IJ)
        return;
    if (obs->nobs == 0)
        return;

    enkf_printf("    sorting obs by ij:\n");
    qsort_r(obs->data, obs->nobs, sizeof(observation), cmp_obs_byij, das);

    if (das->s_f != NULL) {
        double* s = calloc(obs->nobs, sizeof(double));

        for (o = 0; o < obs->nobs; ++o)
            s[o] = das->s_f[obs->data[o].id];
        memcpy(das->s_f, s, obs->nobs * sizeof(double));

        for (o = 0; o < obs->nobs; ++o)
            s[o] = das->std_f[obs->data[o].id];
        memcpy(das->std_f, s, obs->nobs * sizeof(double));

        free(s);
    }

    if (das->s_a != NULL) {
        double* s = calloc(obs->nobs, sizeof(double));

        for (o = 0; o < obs->nobs; ++o)
            s[o] = das->s_a[obs->data[o].id];
        memcpy(das->s_a, s, obs->nobs * sizeof(double));

        for (o = 0; o < obs->nobs; ++o)
            s[o] = das->std_a[obs->data[o].id];
        memcpy(das->std_a, s, obs->nobs * sizeof(double));

        free(s);
    }

    {
        ENSOBSTYPE* S = calloc(obs->nobs, sizeof(ENSOBSTYPE));

        for (e = 0; e < das->nmem; ++e) {
            ENSOBSTYPE* Se = das->S[e];

            for (o = 0; o < obs->nobs; ++o)
                S[o] = Se[obs->data[o].id];
            memcpy(Se, S, obs->nobs * sizeof(ENSOBSTYPE));
        }
        free(S);
    }

    das->sort_mode = OBS_SORTMODE_IJ;
}
예제 #3
0
파일: ensobs.c 프로젝트: sakov/enkf-c
/** Replaces observation errors in the observation file with the modified
 * values. The original values are stored as "std_orig".
 */
void das_addmodifiederrors(dasystem* das, char fname[])
{
    int ncid;
    int dimid_nobs[1];
    size_t nobs;
    int varid_std;
    double* std;
    int i;
    double da_julday = NaN;

    if (rank != 0)
        return;

    ncw_open(fname, NC_WRITE, &ncid);
    ncw_inq_dimid(ncid, "nobs", dimid_nobs);
    ncw_inq_dimlen(ncid, dimid_nobs[0], &nobs);

    ncw_get_att_double(ncid, NC_GLOBAL, "DA_JULDAY", &da_julday);
    if (!enkf_noobsdatecheck && (isnan(da_julday) || fabs(das->obs->da_date - da_julday) > 1e-6))
        enkf_quit("\"observations.nc\" from a different cycle");

    if (ncw_var_exists(ncid, "std_orig")) {
        enkf_printf("    nothing to do\n");
        ncw_close(ncid);
        return;
    }

    ncw_redef(ncid);
    ncw_rename_var(ncid, "std", "std_orig");
    ncw_def_var(ncid, "std", NC_FLOAT, 1, dimid_nobs, &varid_std);
    ncw_enddef(ncid);

    std = malloc(nobs * sizeof(double));

    for (i = 0; i < (int) nobs; ++i)
        std[i] = das->obs->data[i].std;
    ncw_put_var_double(ncid, varid_std, std);

    free(std);

    ncw_close(ncid);
}
예제 #4
0
파일: ensobs.c 프로젝트: juicydut/enkf-c
/** Adds forecast observations and forecast ensemble spread to the observation
 * file.
 */
void das_addforecast(dasystem* das, char fname[])
{
    int ncid;
    int dimid_nobs[1];
    size_t nobs;
    int varid_Hx, varid_spread;
    double* Hx;
    int o;

    if (das->obs->nobs == 0)
        return;
    if (rank != 0)
        return;

    assert(das->s_mode == S_MODE_HA_f);

    ncw_open(fname, NC_WRITE, &ncid);
    if (ncw_var_exists(ncid, "Hx_f")) {
        enkf_printf("  Hx already added to \"%s\" (skipping)\n", fname);
        goto finish;
    }

    ncw_inq_dimid(fname, ncid, "nobs", dimid_nobs);
    ncw_inq_dimlen(fname, ncid, dimid_nobs[0], &nobs);
    ncw_redef(fname, ncid);
    ncw_def_var(fname, ncid, "Hx_f", NC_FLOAT, 1, dimid_nobs, &varid_Hx);
    ncw_def_var(fname, ncid, "std_f", NC_FLOAT, 1, dimid_nobs, &varid_spread);
    ncw_enddef(fname, ncid);

    Hx = calloc(nobs, sizeof(double));
    for (o = 0; o < (int) nobs; ++o)
        Hx[o] = das->obs->data[o].value - das->s_f[o];

    ncw_put_var_double(fname, ncid, varid_Hx, Hx);
    ncw_put_var_double(fname, ncid, varid_spread, das->std_f);

    free(Hx);

  finish:
    ncw_close(fname, ncid);
}
예제 #5
0
void reader_mmt_standard(char* fname, int fid, obsmeta* meta, model* m, observations* obs)
{
    int ncid;
    int dimid_nprof, dimid_nz;
    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;
    double validmin = DBL_MAX;
    double validmax = -DBL_MAX;
    char* type;
    char buf[MAXSTRLEN];
    int len;
    int year, month, day;
    double tunits_multiple, tunits_offset;
    int mvid;
    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(fname, ncid, "N_PROF", &dimid_nprof);
    ncw_inq_dimlen(fname, ncid, dimid_nprof, &nprof);

    ncw_inq_dimid(fname, ncid, "N_LEVELS", &dimid_nz);
    ncw_inq_dimlen(fname, ncid, dimid_nz, &nz);
    enkf_printf("        # profiles = %u\n", (unsigned int) nprof);
    if (nprof == 0) {
        ncw_close(fname, ncid);
        return;
    }
    enkf_printf("        # z levels = %u\n", (unsigned int) nz);

    ncw_inq_varid(fname, ncid, "LONGITUDE", &varid_lon);
    lon = malloc(nprof * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lon, lon);

    ncw_inq_varid(fname, ncid, "LATITUDE", &varid_lat);
    lat = malloc(nprof * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lat, lat);

    ncw_inq_varid(fname, ncid, "PRES_BLUELINK", &varid_z);
    z = alloc2d(nprof, nz, sizeof(double));
    ncw_get_var_double(fname, ncid, varid_z, z[0]);

    if (strncmp(meta->type, "TEM", 3) == 0) {
        validmin = -2.0;
        validmax = 40.0;
        ncw_inq_varid(fname, ncid, "TEMP_BLUELINK", &varid_v);
    } else if (strncmp(meta->type, "SAL", 3) == 0) {
        validmin = 0;
        validmax = 50.0;
        ncw_inq_varid(fname, ncid, "PSAL_BLUELINK", &varid_v);
    } else
        enkf_quit("observation type \"%s\" not handled for MMT product", meta->type);
    v = alloc2d(nprof, nz, sizeof(double));
    ncw_get_var_double(fname, ncid, varid_v, v[0]);
    ncw_get_att_double(fname, ncid, varid_v, "_FillValue", &missval);

    ncw_inq_varid(fname, ncid, "WMO_INST_TYPE", &varid_type);
    type = malloc(nprof * WMO_INSTSIZE);
    ncw_get_var_text(fname, ncid, varid_type, type);

    ncw_close(fname, ncid);

    strcpy(buf, fname);
    len = strlen(buf);
    buf[len - 10] = 0;          /* _mmt_qc.nc */
    if (!str2int(&buf[len - 12], &day))
        enkf_quit("MMT reader: could not convert file name \"%s\" to date", fname);
    buf[len - 12] = 0;
    if (!str2int(&buf[len - 14], &month))
        enkf_quit("MMT reader: could not convert file name \"%s\" to date", fname);
    buf[len - 14] = 0;
    if (!str2int(&buf[len - 18], &year))
        enkf_quit("MMT 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);

    mvid = model_getvarid(m, obs->obstypes[obstype_getid(obs->nobstypes, obs->obstypes, meta->type)].varname, 1);

    for (p = 0; p < (int) nprof; ++p) {
        char inststr[MAXSTRLEN];

        snprintf(inststr, MAXSTRLEN, "WMO%04u", type[p * WMO_INSTSIZE]);

        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);
            assert(o->type >= 0);
            ot = &obs->obstypes[o->type];
            o->instrument = st_add_ifabscent(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 = model_xy2fij(m, mvid, o->lon, o->lat, &o->fi, &o->fj);
            if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
                break;
            if (o->status == STATUS_OK)
                o->status = model_z2fk(m, mvid, 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->date = tunits_offset + 0.5;
            o->aux = -1;

            obs->nobs++;
        }
    }

    free(lon);
    free(lat);
    free2d(v);
    free2d(z);
    free(type);
}
예제 #6
0
/** For files of the form ??_yyyymmdd.nc. They are assumed to have "time" 
 * variable.
 */
void reader_rads_standard(char* fname, int fid, obsmeta* meta, model* m, observations* obs)
{
    int ncid;
    int dimid_nobs;
    size_t nobs_local;
    int varid_lon, varid_lat, varid_pass, varid_sla, varid_time;
    double* lon;
    double* lat;
    int* pass;
    double* sla;
    double* time;
    double error_std;
    size_t tunits_len;
    char* tunits;
    double tunits_multiple, tunits_offset;
    char* basename;
    char instname[3];
    int mvid;
    float** depth;
    int i;

    ncw_open(fname, NC_NOWRITE, &ncid);

    ncw_inq_dimid(fname, ncid, "nobs", &dimid_nobs);
    ncw_inq_dimlen(fname, ncid, dimid_nobs, &nobs_local);
    enkf_printf("        nobs = %u\n", (unsigned int) nobs_local);

    if (nobs_local == 0) {
        ncw_close(fname, ncid);
        return;
    }

    ncw_inq_varid(fname, ncid, "lon", &varid_lon);
    lon = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lon, lon);

    ncw_inq_varid(fname, ncid, "lat", &varid_lat);
    lat = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lat, lat);

    ncw_inq_varid(fname, ncid, "pass", &varid_pass);
    pass = malloc(nobs_local * sizeof(int));
    ncw_get_var_int(fname, ncid, varid_pass, pass);

    ncw_inq_varid(fname, ncid, "sla", &varid_sla);
    sla = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_sla, sla);
    ncw_get_att_double(fname, ncid, varid_sla, "error_std", &error_std);
    enkf_printf("        error_std = %3g\n", error_std);

    ncw_inq_varid(fname, ncid, "time", &varid_time);
    time = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_time, time);
    ncw_inq_attlen(fname, ncid, varid_time, "units", &tunits_len);
    tunits = calloc(tunits_len + 1, 1);
    ncw_get_att_text(fname, ncid, varid_time, "units", tunits);

    ncw_close(fname, ncid);

    tunits_convert(tunits, &tunits_multiple, &tunits_offset);

    basename = strrchr(fname, '/');
    if (basename == NULL)
        basename = fname;
    else
        basename += 1;
    strncpy(instname, basename, 2);
    instname[2] = 0;

    mvid = model_getvarid(m, obs->obstypes[obstype_getid(obs->nobstypes, obs->obstypes, meta->type)].varname, 1);
    depth = model_getdepth(m, mvid);

    for (i = 0; i < (int) nobs_local; ++i) {
        observation* o;
        obstype* ot;

        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);
        assert(o->type >= 0);
        ot = &obs->obstypes[o->type];
        o->instrument = st_add_ifabscent(obs->instruments, instname, -1);
        o->id = obs->nobs;
        o->fid = fid;
        o->batch = pass[i];
        o->value = sla[i];
        o->std = error_std;
        o->lon = lon[i];
        o->lat = lat[i];
        o->depth = 0.0;
        o->status = model_xy2fij(m, mvid, o->lon, o->lat, &o->fi, &o->fj);
        if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
            continue;
        o->fk = 0.0;
        o->date = time[i] * tunits_multiple + tunits_offset;
        if (o->status == STATUS_OK && depth[(int) floor(o->fj + 0.5)][(int) floor(o->fi + 0.5)] < MINDEPTH)
            o->status = STATUS_SHALLOW;
        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->aux = -1;

        obs->nobs++;
    }

    free(lon);
    free(lat);
    free(pass);
    free(sla);
    free(tunits);
    free(time);
}
예제 #7
0
파일: model.c 프로젝트: TheProjecter/enkf-c
void model_print(model* m, char offset[])
{
    int i;

    enkf_printf("%smodel info:\n", offset);
    enkf_printf("%s  name = %s\n", offset, m->name);
    enkf_printf("%s  %d variables:\n", offset, m->nvar);
    for (i = 0; i < m->nvar; ++i) {
        variable* v = &m->vars[i];

        enkf_printf("%s    %s:\n", offset, v->name);
        if (isnan(v->inf_ratio))
            enkf_printf("%s      inflation = %.3f PLAIN\n", offset, v->inflation);
        else
            enkf_printf("%s      inflation = %.3f %.2f\n", offset, v->inflation, v->inf_ratio);
    }
    enkf_printf("%s  %d modeldata:\n", offset, m->ndata);
    for (i = 0; i < m->ndata; ++i) {
        enkf_printf("%s    %s:\n", offset, m->data[i].tag);
        if (m->data[i].alloctype == ALLOCTYPE_1D)
            enkf_printf("%s      type = 1D\n", offset);
        else if (m->data[i].alloctype == ALLOCTYPE_2D)
            enkf_printf("%s      type = 2D\n", offset);
        else if (m->data[i].alloctype == ALLOCTYPE_3D)
            enkf_printf("%s      type = 3D\n", offset);
    }
}
예제 #8
0
파일: ensobs.c 프로젝트: juicydut/enkf-c
static void update_Hx(dasystem* das)
{
    model* m = das->m;
    int ngrid = model_getngrid(m);
    int gid;
    observations* obs = das->obs;
    int e, o;

    enkf_printf("    updating Hx:\n");
    assert(das->s_mode == S_MODE_HE_f);

    /*
     * the following code for interpolation of X5 essentially coincides with
     * that in das_updatefields() 
     */

    for (gid = 0, o = 0; gid < ngrid && o < obs->nobs; ++gid) {
        void* grid = model_getgridbyid(m, gid);
        int periodic_i = grid_isperiodic_x(grid);
        int periodic_j = grid_isperiodic_y(grid);

        char fname_w[MAXSTRLEN];
        int ncid;
        int varid;
        int dimids[3];
        size_t dimlens[3];
        size_t start[3], count[3];
        float** wj = NULL;
        float** wjj = NULL;
        float** wjj1 = NULL;
        float** wjj2 = NULL;

        int mni, mnj;
        int* iiter;
        int* jiter;
        int i, j, ni, nj;
        int jj, stepj, ii, stepi;

        assert(obs->obstypes[obs->data[o].type].gridid == gid);

        das_getfname_w(das, grid, fname_w);

        ncw_open(fname_w, NC_NOWRITE, &ncid);
        ncw_inq_varid(fname_w, ncid, "w", &varid);
        ncw_inq_vardimid(fname_w, ncid, varid, dimids);
        for (i = 0; i < 3; ++i)
            ncw_inq_dimlen(fname_w, ncid, dimids[i], &dimlens[i]);
        ni = dimlens[1];
        nj = dimlens[0];

        assert((int) dimlens[2] == das->nmem);

        jiter = malloc((nj + 1) * sizeof(int)); /* "+ 1" to handle periodic
                                                 * grids */
        iiter = malloc((ni + 1) * sizeof(int));
        for (j = 0, i = 0; j < nj; ++j, i += das->stride)
            jiter[j] = i;
        if (periodic_j)
            jiter[nj] = jiter[nj - 1] + das->stride;
        for (i = 0, j = 0; i < ni; ++i, j += das->stride)
            iiter[i] = j;
        if (periodic_i)
            iiter[ni] = iiter[ni - 1] + das->stride;

        grid_getdims(grid, &mni, &mnj, NULL);

        start[0] = 0;
        start[1] = 0;
        start[2] = 0;
        count[0] = 1;
        count[1] = ni;
        count[2] = das->nmem;
        wj = alloc2d(mni, das->nmem, sizeof(float));
        if (das->stride > 1) {
            wjj = alloc2d(ni, das->nmem, sizeof(float));
            wjj1 = alloc2d(ni, das->nmem, sizeof(float));
            wjj2 = alloc2d(ni, das->nmem, sizeof(float));
            ncw_get_vara_float(fname_w, ncid, varid, start, count, wjj2[0]);
        }

        /*
         * jj, ii are the indices of the subsampled grid; i, j are the indices
         * of the model grid 
         */
        for (jj = 0, j = 0; jj < nj; ++jj) {
            for (stepj = 0; stepj < das->stride && j < mnj; ++stepj, ++j) {
                if (das->stride == 1) {
                    /*
                     * no interpolation necessary; simply read the ETMs for the
                     * j-th row from disk 
                     */
                    start[0] = j;
                    ncw_get_vara_float(fname_w, ncid, varid, start, count, wj[0]);
                } else {
                    /*
                     * the following code interpolates the ETM back to the
                     * original grid, first by j, and then by i 
                     */
                    if (stepj == 0) {
                        memcpy(wjj[0], wjj2[0], ni * das->nmem * sizeof(float));
                        memcpy(wjj1[0], wjj2[0], ni * das->nmem * sizeof(float));
                        if (jj < nj - 1 || periodic_j) {
                            start[0] = (jj + 1) % nj;
                            ncw_get_vara_float(fname_w, ncid, varid, start, count, wjj2[0]);
                        }
                    } else {
                        float weight2 = (float) stepj / das->stride;
                        float weight1 = (float) 1.0 - weight2;

                        for (ii = 0; ii < ni; ++ii) {
                            float* wjjii = wjj[ii];
                            float* wjj1ii = wjj1[ii];
                            float* wjj2ii = wjj2[ii];

                            for (e = 0; e < das->nmem; ++e)
                                wjjii[e] = wjj1ii[e] * weight1 + wjj2ii[e] * weight2;
                        }
                    }

                    for (ii = 0, i = 0; ii < ni; ++ii) {
                        for (stepi = 0; stepi < das->stride && i < mni; ++stepi, ++i) {
                            if (stepi == 0)
                                memcpy(wj[i], wjj[ii], das->nmem * sizeof(float));
                            else {
                                float weight2 = (float) stepi / das->stride;
                                float weight1 = (float) 1.0 - weight2;
                                float* wjjii1 = wjj[ii];
                                float* wji = wj[i];
                                float* wjjii2;

                                if (ii < ni - 1)
                                    wjjii2 = wjj[ii + 1];
                                else
                                    wjjii2 = wjj[(periodic_i) ? (ii + 1) % ni : ii];

                                for (e = 0; e < das->nmem; ++e)
                                    wji[e] = wjjii1[e] * weight1 + wjjii2[e] * weight2;
                            }
                        }
                    }
                }               /* stride != 1 */

                /*
                 * (at this stage wj should contain the array of b vectors for
                 * the j-th row of the grid) 
                 */

                if (o >= obs->nobs)
                    break;
                if ((int) (obs->data[o].fj) > j)
                    continue;

                for (; o < obs->nobs && (int) (obs->data[o].fj) == j; ++o) {
                    double dHx = 0.0;
                    double Hx = 0.0;

                    for (e = 0; e < das->nmem; ++e)
                        Hx += das->S[e][o];
                    Hx /= (double) das->nmem;

                    i = (int) (obs->data[o].fi);
                    /*
                     * HE(i, :) += HA(i, :) * b * 1' 
                     */
                    for (e = 0; e < das->nmem; ++e)
                        dHx += (das->S[e][o] - Hx) * wj[i][e];
                    for (e = 0; e < das->nmem; ++e)
                        das->S[e][o] += dHx;
                }
            }                   /* for stepj */
        }                       /* for jj */

        ncw_close(fname_w, ncid);

        free(iiter);
        free(jiter);
        free2d(wj);
        if (das->stride > 1) {
            free2d(wjj);
            free2d(wjj1);
            free2d(wjj2);
        }
    }                           /* for gid */

    das->s_mode = S_MODE_HE_a;
}                               /* update_Hx() */
예제 #9
0
파일: reader_rads.c 프로젝트: sakov/enkf-c
/** For files of the form ??_yyyymmdd.nc. They are assumed to have "time" 
 * variable.
 */
void reader_rads_standard(char* fname, int fid, obsmeta* meta, model* m, observations* obs)
{
    double mindepth = MINDEPTH_DEF;
    char* addname = NULL;
    int ncid;
    int dimid_nobs;
    size_t nobs_local;
    int varid_lon, varid_lat, varid_pass, varid_sla, varid_time, varid_add;
    double* lon;
    double* lat;
    int* pass;
    double* sla;
    double* time;
    double error_std;
    double* add = NULL;
    size_t tunits_len;
    char* tunits;
    double tunits_multiple, tunits_offset;
    char* basename;
    char instname[3];
    int mvid;
    float** depth;
    int i, ktop;

    for (i = 0; i < meta->npars; ++i) {
        if (strcasecmp(meta->pars[i].name, "MINDEPTH") == 0) {
            if (!str2double(meta->pars[i].value, &mindepth))
                enkf_quit("observation prm file: can not convert MINDEPTH = \"%s\" to double\n", meta->pars[i].value);
        } else if (strcasecmp(meta->pars[i].name, "ADD") == 0) {
            addname = meta->pars[i].value;
            enkf_printf("        ADDING \"%s\"\n", addname);
        } else
            enkf_quit("unknown PARAMETER \"%s\"\n", meta->pars[i].name);
    }
    enkf_printf("        MINDEPTH = %.0f\n", mindepth);

    ncw_open(fname, NC_NOWRITE, &ncid);

    ncw_inq_dimid(ncid, "nobs", &dimid_nobs);
    ncw_inq_dimlen(ncid, dimid_nobs, &nobs_local);
    enkf_printf("        nobs = %u\n", (unsigned int) nobs_local);

    if (nobs_local == 0) {
        ncw_close(ncid);
        return;
    }

    ncw_inq_varid(ncid, "lon", &varid_lon);
    lon = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_lon, lon);

    ncw_inq_varid(ncid, "lat", &varid_lat);
    lat = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_lat, lat);

    ncw_inq_varid(ncid, "pass", &varid_pass);
    pass = malloc(nobs_local * sizeof(int));
    ncw_get_var_int(ncid, varid_pass, pass);

    ncw_inq_varid(ncid, "sla", &varid_sla);
    sla = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_sla, sla);
    ncw_get_att_double(ncid, varid_sla, "error_std", &error_std);
    enkf_printf("        error_std = %3g\n", error_std);

    if (addname != NULL) {
        ncw_inq_varid(ncid, addname, &varid_add);
        add = malloc(nobs_local * sizeof(double));
        ncw_get_var_double(ncid, varid_add, add);
    }

    ncw_inq_varid(ncid, "time", &varid_time);
    time = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_time, time);
    ncw_inq_attlen(ncid, varid_time, "units", &tunits_len);
    tunits = calloc(tunits_len + 1, 1);
    ncw_get_att_text(ncid, varid_time, "units", tunits);

    ncw_close(ncid);

    tunits_convert(tunits, &tunits_multiple, &tunits_offset);

    basename = strrchr(fname, '/');
    if (basename == NULL)
        basename = fname;
    else
        basename += 1;
    strncpy(instname, basename, 2);
    instname[2] = 0;

    mvid = model_getvarid(m, obs->obstypes[obstype_getid(obs->nobstypes, obs->obstypes, meta->type, 1)].varnames[0], 1);
    ktop = grid_gettoplayerid(model_getvargrid(m, mvid));
    depth = model_getdepth(m, mvid, 1);

    for (i = 0; i < (int) nobs_local; ++i) {
        observation* o;
        obstype* ot;

        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_ifabscent(obs->instruments, instname, -1);
        o->id = obs->nobs;
        o->fid = fid;
        o->batch = pass[i];
        o->value = sla[i];
        if (add != NULL)
            o->value += add[i];
        o->std = error_std;
        o->lon = lon[i];
        o->lat = lat[i];
        o->depth = 0.0;
        o->status = model_xy2fij(m, mvid, o->lon, o->lat, &o->fi, &o->fj);
        if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
            continue;
        o->fk = (double) ktop;
        o->model_depth = (isnan(o->fi + o->fj)) ? NaN : depth[(int) (o->fj + 0.5)][(int) (o->fi + 0.5)];
        o->date = time[i] * tunits_multiple + tunits_offset;
        if (o->status == STATUS_OK && o->model_depth < mindepth)
            o->status = STATUS_SHALLOW;
        if ((o->status == STATUS_OK) && (o->lon <= ot->xmin || o->lon >= ot->xmax || o->lat <= ot->ymin || o->lat >= ot->ymax))
            o->status = STATUS_OUTSIDEOBSDOMAIN;

        o->aux = -1;

        obs->nobs++;
    }

    if (add != NULL)
        free(add);
    free(lon);
    free(lat);
    free(pass);
    free(sla);
    free(tunits);
    free(time);
}
예제 #10
0
파일: grid.c 프로젝트: sakov/enkf-c
void grid_print(grid* g, char offset[])
{
    int nx, ny, nz;

    enkf_printf("%sgrid info:\n", offset);
    switch (g->htype) {
    case GRIDHTYPE_LATLON:
        enkf_printf("%s  hor type = LATLON\n", offset);
        enkf_printf("%s  periodic by X = %s\n", offset, grid_isperiodic_x(g) ? "yes" : "no");
        break;
#if !defined(NO_GRIDUTILS)
    case GRIDHTYPE_CURVILINEAR:
        enkf_printf("%s  hor type = CURVILINEAR\n", offset);
        if (g->maptype == GRIDMAP_TYPE_BINARY)
            enkf_printf("%s  map type = BINARY TREE\n", offset);
        else if (g->maptype == GRIDMAP_TYPE_KDTREE)
            enkf_printf("%s  map type = KD-TREE\n", offset);
        else
            enkf_quit("unknown grid map type");
        break;
#endif
    default:
        enkf_printf("%s  h type = NONE\n", offset);
    }
    grid_getdims(g, &nx, &ny, &nz);
    enkf_printf("%s  dims = %d x %d x %d\n", offset, nx, ny, nz);
    if (!isnan(g->lonbase))
        enkf_printf("%s  longitude range = [%.3f, %.3f]\n", offset, g->lonbase, g->lonbase + 360.0);
    else
        enkf_printf("%s  longitude range = any\n", offset);
    switch (g->vtype) {
    case GRIDVTYPE_Z:
        enkf_printf("%s  vert type = Z\n", offset);
        break;
    case GRIDVTYPE_SIGMA:
        enkf_printf("%s  vert type = SIGMA\n", offset);
        break;
    default:
        enkf_printf("%s  vert type = NONE\n", offset);
    }
    if (g->sfactor != 1.0)
        enkf_printf("%s  SFACTOR = \"%.f\"\n", offset, g->sfactor);
}
예제 #11
0
파일: ensobs.c 프로젝트: sakov/enkf-c
void das_getHE(dasystem* das)
{
    observations* obs = das->obs;
    model* m = das->m;
    ENSOBSTYPE* Hx = NULL;
    int i, e;

    das->s_mode = S_MODE_HE_f;
    if (obs->nobs == 0)
        return;

    if (das->nmem <= 0)
        das_setnmem(das);
    enkf_printf("    ensemble size = %d\n", das->nmem);
    assert(das->nmem > 0);

    distribute_iterations(0, das->nmem - 1, nprocesses, rank, "    ");

    /*
     * ensemble observation array to be filled 
     */
    assert(das->S == NULL);
    das->S = alloc2d(das->nmem, obs->nobs, sizeof(ENSOBSTYPE));
    if (das->mode == MODE_ENOI)
        Hx = calloc(obs->nobs, sizeof(ENSOBSTYPE));

    for (i = 0; i < obs->nobstypes; ++i) {
        obstype* ot = &obs->obstypes[i];
        float*** vvv = NULL;
        float** vv = NULL;
        H_fn H = NULL;
        int mvid;
        int ni, nj, nk;
        int nobs;
        int* obsids;
        char fname[MAXSTRLEN];

        enkf_printf("    %s ", ot->name);
        fflush(stdout);

        mvid = model_getvarid(m, obs->obstypes[i].varnames[0], 1);
        if (ot->issurface) {
            model_getvardims(m, mvid, &ni, &nj, NULL);
            vv = alloc2d(nj, ni, sizeof(float));
        } else {
            model_getvardims(m, mvid, &ni, &nj, &nk);
            vvv = alloc3d(nk, nj, ni, sizeof(float));
        }

        /*
         * set H
         */
        H = getH(ot->name, ot->hfunction);

        if (ot->isasync) {
            int t1 = get_tshift(ot->date_min, ot->async_tstep);
            int t2 = get_tshift(ot->date_max, ot->async_tstep);
            int t;

            for (t = t1; t <= t2; ++t) {
                enkf_printf("|");
                obs_find_bytypeandtime(obs, i, t, &nobs, &obsids);
                if (nobs == 0)
                    continue;

                /*
                 * for EnOI it is essential sometimes (e.g. in some bias
                 * correction cases) that the background is interpolated first
                 */
                if (das->mode == MODE_ENOI) {
                    if (enkf_obstype == OBSTYPE_VALUE) {
                        int success = model_getbgfname_async(m, das->bgdir, ot->varnames[0], ot->name, t, fname);

                        H(das, nobs, obsids, fname, -1, t, (ot->issurface) ? (void*) vv : (void*) vvv, Hx);
                        enkf_printf((success) ? "A" : "S");
                        fflush(stdout);
                    } else if (enkf_obstype == OBSTYPE_INNOVATION) {
                        Hx[0] = 0;
                        enkf_printf("-");
                        fflush(stdout);
                    }
                }

                if (das->mode == MODE_ENKF || !enkf_fstatsonly) {
                    for (e = my_first_iteration; e <= my_last_iteration; ++e) {
                        int success = model_getmemberfname_async(m, das->ensdir, ot->varnames[0], ot->name, e + 1, t, fname);

                        H(das, nobs, obsids, fname, e + 1, t, (ot->issurface) ? (void*) vv : (void*) vvv, das->S[e]);
                        enkf_printf((success) ? "a" : "s");
                        fflush(stdout);
                    }
                }

                free(obsids);
            }
        } else {
            obs_find_bytype(obs, i, &nobs, &obsids);
            if (nobs == 0)
                goto next;

            /*
             * for EnOI it is essential sometimes (e.g. in some bias correction
             * cases) that the background is interpolated first
             */
            if (das->mode == MODE_ENOI) {
                if (enkf_obstype == OBSTYPE_VALUE) {
                    model_getbgfname(m, das->bgdir, ot->varnames[0], fname);
                    H(das, nobs, obsids, fname, -1, INT_MAX, (ot->issurface) ? (void*) vv : (void*) vvv, Hx);
                    enkf_printf("+");
                    fflush(stdout);
                } else if (enkf_obstype == OBSTYPE_INNOVATION) {
                    Hx[0] = 0;
                    enkf_printf("-");
                    fflush(stdout);
                }
            }

            if (das->mode == MODE_ENKF || !enkf_fstatsonly) {
                for (e = my_first_iteration; e <= my_last_iteration; ++e) {
                    model_getmemberfname(m, das->ensdir, ot->varnames[0], e + 1, fname);
                    H(das, nobs, obsids, fname, e + 1, INT_MAX, (ot->issurface) ? (void*) vv : (void*) vvv, das->S[e]);
                    enkf_printf(".");
                    fflush(stdout);
                }
            }

            free(obsids);
        }

      next:

        if (ot->issurface)
            free(vv);
        else
            free(vvv);
        enkf_printf("\n");
    }                           /* for i (over obstypes) */

#if defined(MPI)
    if (das->mode == MODE_ENKF || !enkf_fstatsonly) {
#if !defined(HE_VIAFILE)
        /*
         * communicate HE via MPI
         */
        int ierror, sendcount, *recvcounts, *displs;

        recvcounts = malloc(nprocesses * sizeof(int));
        displs = malloc(nprocesses * sizeof(int));

        sendcount = my_number_of_iterations * obs->nobs;
        for (i = 0; i < nprocesses; ++i) {
            recvcounts[i] = number_of_iterations[i] * obs->nobs;
            displs[i] = first_iteration[i] * obs->nobs;
        }

        ierror = MPI_Allgatherv(das->S[my_first_iteration], sendcount, MPIENSOBSTYPE, das->S[0], recvcounts, displs, MPIENSOBSTYPE, MPI_COMM_WORLD);
        assert(ierror == MPI_SUCCESS);

        free(recvcounts);
        free(displs);
#else
        /*
         * communicate HE via file
         */
        {
            int ncid;
            int varid;
            size_t start[2], count[2];

            if (rank == 0) {
                int dimids[2];

                ncw_create(FNAME_HE, NC_CLOBBER | NETCDF_FORMAT, &ncid);
                ncw_def_dim(FNAME_HE, ncid, "m", das->nmem, &dimids[0]);
                ncw_def_dim(FNAME_HE, ncid, "p", obs->nobs, &dimids[1]);
                ncw_def_var(FNAME_HE, ncid, "HE", NC_FLOAT, 2, dimids, &varid);
                ncw_close(FNAME_HE, ncid);
            }
            MPI_Barrier(MPI_COMM_WORLD);

            ncw_open(FNAME_HE, NC_WRITE, &ncid);
            ncw_inq_varid(FNAME_HE, ncid, "HE", &varid);
            start[0] = my_first_iteration;
            start[1] = 0;
            count[0] = my_last_iteration - my_first_iteration + 1;
            count[1] = obs->nobs;
            ncw_put_vara_float(FNAME_HE, ncid, varid, start, count, das->S[my_first_iteration]);
            ncw_close(FNAME_HE, ncid);
            MPI_Barrier(MPI_COMM_WORLD);

            ncw_open(FNAME_HE, NC_NOWRITE, &ncid);
            ncw_inq_varid(FNAME_HE, ncid, "HE", &varid);
            ncw_get_var_float(FNAME_HE, ncid, varid, das->S[0]);
            ncw_close(FNAME_HE, ncid);
        }
#endif
    }
#endif

    if (das->mode == MODE_ENOI) {
        /*
         * subtract ensemble mean; add background
         */
        if (!enkf_fstatsonly) {
            double* ensmean = calloc(obs->nobs, sizeof(double));

            for (e = 0; e < das->nmem; ++e) {
                ENSOBSTYPE* Se = das->S[e];

                for (i = 0; i < obs->nobs; ++i)
                    ensmean[i] += Se[i];
            }
            for (i = 0; i < obs->nobs; ++i)
                ensmean[i] /= (double) das->nmem;

            for (e = 0; e < das->nmem; ++e) {
                ENSOBSTYPE* Se = das->S[e];

                for (i = 0; i < obs->nobs; ++i)
                    Se[i] += Hx[i] - ensmean[i];
            }

            free(ensmean);
        } else {
            for (e = 0; e < das->nmem; ++e) {
                ENSOBSTYPE* Se = das->S[e];

                for (i = 0; i < obs->nobs; ++i)
                    Se[i] = Hx[i];
            }
        }
    }

    if (das->mode == MODE_ENOI)
        free(Hx);
}
예제 #12
0
파일: grid.c 프로젝트: marshallward/enkf-c
void grid_describeprm(void)
{
    enkf_printf("\n");
    enkf_printf("  Grid parameter file format:\n");
    enkf_printf("\n");
    enkf_printf("    NAME             = <name> [ PREP | CALC ]\n");
    enkf_printf("    VTYPE            = { z | sigma }\n");
    enkf_printf("    DATA             = <data file name>\n");
    enkf_printf("    XDIMNAME         = <x dimension name>\n");
    enkf_printf("    YDIMNAME         = <y dimension name>\n");
    enkf_printf("    ZDIMNAME         = <z dimension name>\n");
    enkf_printf("    XVARNAME         = <x variable name>\n");
    enkf_printf("    YVARNAME         = <y variable name>\n");
    enkf_printf("    ZVARNAME         = <z variable name>\n");
    enkf_printf("    DEPTHVARNAME     = <depth variable name>\n");
    enkf_printf("    [ NUMLEVELSVARNAME = <# of levels variable name> (z) ]\n");
    enkf_printf("    [ MASKVARNAME      = <land mask variable name> (sigma) ]\n");
    enkf_printf("\n");
    enkf_printf("  [ <more of the above blocks> ]\n");
    enkf_printf("\n");
    enkf_printf("  Notes:\n");
    enkf_printf("    1. < ... > denotes a description of an entry\n");
    enkf_printf("    2. [ ... ] denotes an optional input\n");
    enkf_printf("\n");
}
예제 #13
0
파일: grid.c 프로젝트: marshallward/enkf-c
void grid_print(grid* g, char offset[])
{
    int nx, ny, nz;

    enkf_printf("%sgrid info:\n", offset);
    switch (g->htype) {
    case GRIDHTYPE_LATLON_REGULAR:
        enkf_printf("%s  hor type = LATLON_REGULAR\n", offset);
        break;
    case GRIDHTYPE_LATLON_IRREGULAR:
        enkf_printf("%s  hor type = LATLON_IRREGULAR\n", offset);
        break;
#if !defined(NO_GRIDUTILS)
    case GRIDHTYPE_CURVILINEAR:
        enkf_printf("%s  hor type = CURVILINEAR\n", offset);
        break;
#endif
    default:
        enkf_printf("%s  h type = NONE\n", offset);
    }
    enkf_printf("%s  periodic by X = %s\n", offset, grid_isperiodic_x(g) ? "yes" : "no");
    enkf_printf("%s  periodic by Y = %s\n", offset, grid_isperiodic_y(g) ? "yes" : "no");
    grid_getdims(g, &nx, &ny, &nz);
    enkf_printf("%s  dims = %d x %d x %d\n", offset, nx, ny, nz);
    if (!isnan(g->lonbase))
        enkf_printf("%s  longitude range = [%.3f, %.3f]\n", offset, g->lonbase, g->lonbase + 360.0);
    else
        enkf_printf("%s  longitude range = any\n", offset);
    switch (g->vtype) {
    case GRIDVTYPE_Z:
        enkf_printf("%s  vert type = Z\n", offset);
        break;
    case GRIDVTYPE_SIGMA:
        enkf_printf("%s  vert type = SIGMA\n", offset);
        break;
    default:
        enkf_printf("%s  vert type = NONE\n", offset);
    }
}
예제 #14
0
void reader_navo_standard(char* fname, int fid, obsmeta* meta, model* m, observations* obs)
{
    int addbias = ADDBIAS_DEF;
    int ncid;
    int dimid_nobs;
    size_t nobs_local;
    int varid_lon, varid_lat, varid_sst, varid_sstb, varid_error, varid_time;
    double* lon = NULL;
    double* lat = NULL;
    double* sst = NULL;
    double* sstb = NULL;
    double* error_std = NULL;
    double* time = NULL;
    int year, month, day;
    char tunits[MAXSTRLEN];
    size_t tunits_len;
    double tunits_multiple, tunits_offset;
    char* basename;
    int model_vid;
    int k, i;

    for (i = 0; i < meta->npars; ++i) {
        if (strcasecmp(meta->pars[i].name, "ADDBIAS") == 0)
            addbias = (istrue(meta->pars[i].value)) ? 1 : 0;
        else
            enkf_quit("unknown PARAMETER \"%s\"\n", meta->pars[i].name);
    }
    enkf_printf("        ADDBIAS = %s\n", (addbias) ? "YES" : "NO");

    basename = strrchr(fname, '/');
    if (basename == NULL)
        basename = fname;
    else
        basename += 1;

    ncw_open(fname, NC_NOWRITE, &ncid);
    ncw_inq_dimid(fname, ncid, (ncw_dim_exists(ncid, "nobs")) ? "nobs" : "length", &dimid_nobs);
    ncw_inq_dimlen(fname, ncid, dimid_nobs, &nobs_local);
    enkf_printf("        nobs = %u\n", (unsigned int) nobs_local);

    if (nobs_local == 0) {
        ncw_close(fname, ncid);
        return;
    }

    ncw_inq_varid(fname, ncid, "lon", &varid_lon);
    lon = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lon, lon);

    ncw_inq_varid(fname, ncid, "lat", &varid_lat);
    lat = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lat, lat);

    ncw_inq_varid(fname, ncid, "sst", &varid_sst);
    sst = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_sst, sst);

    if (addbias) {
        ncw_inq_varid(fname, ncid, "SST_bias", &varid_sstb);
        sstb = malloc(nobs_local * sizeof(double));
        ncw_get_var_double(fname, ncid, varid_sstb, sstb);
    }

    ncw_inq_varid(fname, ncid, "error", &varid_error);
    error_std = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_error, error_std);

    ncw_inq_varid(fname, ncid, "GMT_time", &varid_time);
    time = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_time, time);
    ncw_inq_attlen(fname, ncid, varid_time, "units", &tunits_len);
    ncw_get_att_text(fname, ncid, varid_time, "units", tunits);
    basename[13] = 0;
    if (!str2int(&basename[11], &day))
        enkf_quit("NAVO reader: could not convert file name \"%s\" to date", fname);
    basename[11] = 0;
    if (!str2int(&basename[9], &month))
        enkf_quit("NAVO reader: could not convert file name \"%s\" to date", fname);
    basename[9] = 0;
    if (!str2int(&basename[5], &year))
        enkf_quit("NAVO reader: could not convert file name \"%s\" to date", fname);
    snprintf(&tunits[tunits_len], MAXSTRLEN - tunits_len, " since %4d-%02d-%02d", year, month, day);

    ncw_close(fname, ncid);

    tunits_convert(tunits, &tunits_multiple, &tunits_offset);

    model_vid = model_getvarid(m, obs->obstypes[obstype_getid(obs->nobstypes, obs->obstypes, meta->type)].varname, 1);
    k = grid_gettoplayerid(model_getvargrid(m, model_vid));

    for (i = 0; i < (int) nobs_local; ++i) {
        observation* o;
        obstype* ot;

        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);
        assert(o->type >= 0);
        ot = &obs->obstypes[o->type];
        o->instrument = st_add_ifabscent(obs->instruments, "AVHRR", -1);
        o->id = obs->nobs;
        o->fid = fid;
        o->batch = 0;
        o->value = (addbias) ? sst[i] + sstb[i] : sst[i];
        o->std = error_std[i];
        o->lon = lon[i];
        o->lat = lat[i];
        o->depth = 0.0;
        o->status = model_xy2fij(m, model_vid, o->lon, o->lat, &o->fi, &o->fj);
        if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
            continue;
        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->fk = (double) k;
        o->date = time[i] * tunits_multiple + tunits_offset;
        o->aux = -1;

        obs->nobs++;
    }

    free(lon);
    free(lat);
    free(sst);
    if (addbias)
        free(sstb);
    free(error_std);
    free(time);
}
예제 #15
0
파일: model.c 프로젝트: sakov/enkf-c
void model_print(model* m, char offset[])
{
    int i;

    enkf_printf("%smodel info:\n", offset);
    enkf_printf("%s  name = %s\n", offset, m->name);
    enkf_printf("%s  %d variables:\n", offset, m->nvar);
    for (i = 0; i < m->nvar; ++i) {
        variable* v = &m->vars[i];

        enkf_printf("%s    %s:\n", offset, v->name);
        enkf_printf("%s      grid = \"%s\"\n", offset, grid_getname(model_getgridbyid(m, v->gridid)));
        if (isnan(v->inf_ratio))
            enkf_printf("%s      inflation = %.3f PLAIN\n", offset, v->inflation);
        else
            enkf_printf("%s      inflation = %.3f %.2f\n", offset, v->inflation, v->inf_ratio);
        if (!isnan(v->deflation))
            enkf_printf("%s      randomise: deflation = %.3f, sigma = %.3f\n", offset, v->deflation, v->sigma);
    }
    enkf_printf("%s  %d modeldata:\n", offset, m->ndata);
    for (i = 0; i < m->ndata; ++i) {
        enkf_printf("%s    %s:\n", offset, m->data[i].tag);
        if (m->data[i].alloctype == ALLOCTYPE_1D)
            enkf_printf("%s      type = 1D\n", offset);
        else if (m->data[i].alloctype == ALLOCTYPE_2D)
            enkf_printf("%s      type = 2D\n", offset);
        else if (m->data[i].alloctype == ALLOCTYPE_3D)
            enkf_printf("%s      type = 3D\n", offset);
    }
}
예제 #16
0
파일: obstypes.c 프로젝트: juicydut/enkf-c
void obstypes_describeprm(void)
{
    enkf_printf("\n");
    enkf_printf("  Observation types parameter file format:\n");
    enkf_printf("\n");
    enkf_printf("    NAME      = <name>\n");
    enkf_printf("    VAR       = <model variable name>\n");
    enkf_printf("  [ VAR2       = <model variable name> ]\n");
    enkf_printf("    ISSURFACE = { yes | no }\n");
    enkf_printf("  [ OFFSET    = <file name> <variable name> ]    (none*)\n");
    enkf_printf("    HFUNCTION = <H function name>\n");
    enkf_printf("  [ ASYNC     = <time interval> ]                (synchronous*)\n");
    enkf_printf("  [ RFACTOR   = <rfactor> ]                      (1*)\n");
    enkf_printf("  [ MINVALUE  = <minimal allowed value> ]        (-inf*)\n");
    enkf_printf("  [ MAXVALUE  = <maximal allowed value> ]        (+inf*)\n");
    enkf_printf("  [ XMIN      = <minimal allowed X coordinate> ] (-inf*)\n");
    enkf_printf("  [ XMAX      = <maximal allowed X coordinate> ] (+inf*)\n");
    enkf_printf("  [ YMIN      = <minimal allowed Y coordinate> ] (-inf*)\n");
    enkf_printf("  [ YMAX      = <maximal allowed Y coordinate> ] (+inf*)\n");
    enkf_printf("  [ ZMIN      = <minimal allowed Z coordinate> ] (-inf*)\n");
    enkf_printf("  [ ZMAX      = <maximal allowed Z coordinate> ] (+inf*)\n");
    enkf_printf("\n");
    enkf_printf("  [ <more of the above blocks> ]\n");
    enkf_printf("\n");
    enkf_printf("  Notes:\n");
    enkf_printf("    1. { ... | ... | ... } denotes the list of possible choices\n");
    enkf_printf("    2. [ ... ] denotes an optional input\n");
    enkf_printf("    3. ( ... ) is a note\n");
    enkf_printf("    4. * denotes the default value\n");
    enkf_printf("    5. < ... > denotes a description of an entry\n");
    enkf_printf("\n");

}
예제 #17
0
파일: obstypes.c 프로젝트: juicydut/enkf-c
static void obstype_print(obstype* type)
{
    enkf_printf("    NAME = %s\n", type->name);
    enkf_printf("      VAR = %s\n", type->varname);
    if (type->varname2 != NULL)
        enkf_printf("      SECONDARY VAR = %s\n", type->varname2);
    enkf_printf("      ID = %d\n", type->id);
    enkf_printf("      ISSURFACE = %s\n", (type->issurface) ? "yes" : "no");
    if (type->offset_fname != NULL)
        enkf_printf("      OFFSET = %s %s\n", type->offset_fname, type->offset_varname);
    enkf_printf("      HFUNCTION = %s\n", type->hfunction);
    enkf_printf("      ALLOWED MIN = %.3g\n", type->allowed_min);
    enkf_printf("      ALLOWED MAX = %.3g\n", type->allowed_max);
    enkf_printf("      ASYNCHRONOUS = %s", (type->isasync) ? "yes" : "no");
    if (type->isasync)
        enkf_printf(", DT = %.3f\n", type->async_tstep);
    else
        enkf_printf("\n");
    enkf_printf("      RFACTOR = %.3g\n", type->rfactor);
    if (type->xmin > -DBL_MAX || type->xmax < DBL_MAX || type->ymin > -DBL_MAX || type->ymax < DBL_MAX || type->zmin > -DBL_MAX || type->zmax < DBL_MAX)
        enkf_printf("      DOMAIN = %.3g %.3g %.3g %.3g %.3g %.3g\n", type->xmin, type->xmax, type->ymin, type->ymax, type->zmin, type->zmax);
}
예제 #18
0
파일: grid.c 프로젝트: sakov/enkf-c
void grid_describeprm(void)
{
    enkf_printf("\n");
    enkf_printf("  Grid parameter file format:\n");
    enkf_printf("\n");
    enkf_printf("    NAME             = <name> [ PREP | CALC ]\n");
    enkf_printf("    VTYPE            = { z | sigma }\n");
#if !defined(NO_GRIDUTILS)
    enkf_printf("  [ MAPTYPE          = { binary* | kdtree } (curvilinear grids) ]\n");
#endif
    enkf_printf("    DATA             = <data file name>\n");
    enkf_printf("    XDIMNAME         = <x dimension name>\n");
    enkf_printf("    YDIMNAME         = <y dimension name>\n");
    enkf_printf("    ZDIMNAME         = <z dimension name>\n");
    enkf_printf("    XVARNAME         = <x variable name>\n");
    enkf_printf("    YVARNAME         = <y variable name>\n");
    enkf_printf("    ZVARNAME         = <z variable name>\n");
    enkf_printf("    DEPTHVARNAME     = <depth variable name>\n");
    enkf_printf("    [ NUMLEVELSVARNAME = <# of levels variable name> (z) ]\n");
    enkf_printf("    [ MASKVARNAME    = <land mask variable name> (sigma) ]\n");
    enkf_printf("    [ SFACTOR        = <spread factor> (1.0*) ]\n");
    enkf_printf("\n");
    enkf_printf("  [ <more of the above blocks> ]\n");
    enkf_printf("\n");
    enkf_printf("  Notes:\n");
    enkf_printf("    1. < ... > denotes a description of an entry\n");
    enkf_printf("    2. [ ... ] denotes an optional input\n");
    enkf_printf("    3. (...) is a note\n");
    enkf_printf("    4. * denotes the default value\n");
    enkf_printf("\n");
}
예제 #19
0
void reader_windsat_standard(char* fname, int fid, obsmeta* meta, model* m, observations* obs)
{
    int ncid;
    int dimid_nobs;
    size_t nobs_local;
    int varid_lon, varid_lat, varid_sst, varid_error, varid_time;
    double* lon;
    double* lat;
    double* sst;
    double* error_std;
    double* time;
    int year, month, day;
    char tunits[MAXSTRLEN];
    size_t tunits_len;
    double tunits_multiple, tunits_offset;
    char* basename;
    int mvid;
    float** depth;
    int ktop;
    int i;

    for (i = 0; i < meta->npars; ++i)
        enkf_quit("unknown PARAMETER \"%s\"\n", meta->pars[i].name);

    basename = strrchr(fname, '/');
    if (basename == NULL)
        basename = fname;
    else
        basename += 1;

    ncw_open(fname, NC_NOWRITE, &ncid);

    ncw_inq_dimid(ncid, "nobs", &dimid_nobs);
    ncw_inq_dimlen(ncid, dimid_nobs, &nobs_local);
    enkf_printf("        nobs = %u\n", (unsigned int) nobs_local);

    if (nobs_local == 0) {
        ncw_close(ncid);
        return;
    }

    ncw_inq_varid(ncid, "lon", &varid_lon);
    lon = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_lon, lon);

    ncw_inq_varid(ncid, "lat", &varid_lat);
    lat = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_lat, lat);

    ncw_inq_varid(ncid, "sst", &varid_sst);
    sst = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_sst, sst);

    ncw_inq_varid(ncid, "error", &varid_error);
    error_std = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_error, error_std);

    ncw_inq_varid(ncid, "age", &varid_time);
    time = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(ncid, varid_time, time);
    ncw_inq_attlen(ncid, varid_time, "units", &tunits_len);
    ncw_get_att_text(ncid, varid_time, "units", tunits);
    basename[16] = 0;
    if (!str2int(&basename[14], &day))
        enkf_quit("WindSat reader: could not convert file name \"%s\" to date", fname);
    basename[14] = 0;
    if (!str2int(&basename[12], &month))
        enkf_quit("WindSat reader: could not convert file name \"%s\" to date", fname);
    basename[12] = 0;
    if (!str2int(&basename[8], &year))
        enkf_quit("WindSat reader: could not convert file name \"%s\" to date", fname);
    snprintf(&tunits[tunits_len], MAXSTRLEN - tunits_len, " since %4d-%02d-%02d", year, month, day);

    ncw_close(ncid);

    tunits_convert(tunits, &tunits_multiple, &tunits_offset);

    mvid = model_getvarid(m, obs->obstypes[obstype_getid(obs->nobstypes, obs->obstypes, meta->type, 1)].varnames[0], 1);
    ktop = grid_gettoplayerid(model_getvargrid(m, mvid));
    depth = model_getdepth(m, mvid, 0);

    for (i = 0; i < (int) nobs_local; ++i)
        if (time[i] != 0.0)
            break;
    if (i == (int) nobs_local)
        for (i = 0; i < (int) nobs_local; ++i)
            time[i] = 0.5;

    for (i = 0; i < (int) nobs_local; ++i) {
        observation* o;
        obstype* ot;

        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_ifabscent(obs->instruments, "WindSat", -1);
        o->id = obs->nobs;
        o->fid = fid;
        o->batch = 0;
        o->value = sst[i];
        o->std = error_std[i];
        o->lon = lon[i];
        o->lat = lat[i];
        o->depth = 0.0;
        o->fk = (double) ktop;
        o->status = model_xy2fij(m, mvid, o->lon, o->lat, &o->fi, &o->fj);
        if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
            continue;
        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 = (depth == NULL || isnan(o->fi + o->fj)) ? NaN : depth[(int) (o->fj + 0.5)][(int) (o->fi + 0.5)];
        o->date = time[i] * tunits_multiple + tunits_offset;
        o->aux = -1;

        obs->nobs++;
    }

    free(lon);
    free(lat);
    free(sst);
    free(error_std);
    free(time);
}
예제 #20
0
void obsmeta_describeprm(void)
{
    enkf_printf("\n");
    enkf_printf("  Observation data parameter file format:\n");
    enkf_printf("\n");
    enkf_printf("    PRODUCT   = <product>\n");
    enkf_printf("    READER    = <reader>\n");
    enkf_printf("    TYPE      = <observation type>\n");
    enkf_printf("    FILE      = <data file wildcard> \n");
    enkf_printf("    ...\n");
    enkf_printf("  [ ERROR_STD = { <value> | <data file> } [ EQ* | PL | MU | MI | MA ] ]\n");
    enkf_printf("    ...\n");
    enkf_printf("\n");
    enkf_printf("  [ <more of the above blocks> ]\n");
    enkf_printf("\n");
    enkf_printf("  Notes:\n");
    enkf_printf("    1. { ... | ... | ... } denotes the list of possible choices\n");
    enkf_printf("    2. [ ... ] denotes an optional input\n");
    enkf_printf("    3. * denotes the default value\n");
    enkf_printf("    4. < ... > denotes a description of an entry\n");
    enkf_printf("    5. ... denotes repeating the previous item an arbitrary number of times\n");
    enkf_printf("\n");
}
예제 #21
0
파일: ensobs.c 프로젝트: juicydut/enkf-c
void das_getHE(dasystem* das)
{
    observations* obs = das->obs;
    model* m = das->m;
    ENSOBSTYPE* Hx = NULL;
    int i, e;

    das->s_mode = S_MODE_HE_f;
    if (obs->nobs == 0)
        return;

    if (das->nmem <= 0)
        das_getnmem(das);
    enkf_printf("    ensemble size = %d\n", das->nmem);
    assert(das->nmem > 0);

    distribute_iterations(0, das->nmem - 1, nprocesses, rank, "    ");

    /*
     * ensemble observation array to be filled 
     */
    assert(das->S == NULL);
    das->S = alloc2d(das->nmem, obs->nobs, sizeof(ENSOBSTYPE));
    if (das->mode == MODE_ENOI)
        Hx = calloc(obs->nobs, sizeof(ENSOBSTYPE));

    for (i = 0; i < obs->nobstypes; ++i) {
        obstype* ot = &obs->obstypes[i];
        float*** vvv = NULL;
        float** vv = NULL;
        H_fn H = NULL;
        int mvid;
        int ni, nj, nk;
        int nobs;
        int* obsids;
        char fname[MAXSTRLEN];

        enkf_printf("    %s ", ot->name);
        fflush(stdout);

        mvid = model_getvarid(m, obs->obstypes[i].varname);
        if (mvid < 0)
            enkf_quit("variable \"%s\" required for observation type \"%s\" is not defined", obs->obstypes[i].varname, ot->name);
        if (ot->issurface) {
            model_getvardims(m, mvid, &ni, &nj, NULL);
            vv = alloc2d(nj, ni, sizeof(float));
        } else {
            model_getvardims(m, mvid, &ni, &nj, &nk);
            vvv = alloc3d(nk, nj, ni, sizeof(float));
        }

        /*
         * set H
         */
        H = getH(ot->name, ot->hfunction);

        if (ot->isasync) {
            int t1 = get_tshift(ot->date_min, ot->async_tstep);
            int t2 = get_tshift(ot->date_max, ot->async_tstep);
            int t;

            for (t = t1; t <= t2; ++t) {
                enkf_printf("|");
                obs_find_bytypeandtime(obs, i, t, &nobs, &obsids);
                if (nobs == 0)
                    continue;

                if (das->mode == MODE_ENKF || !enkf_fstatsonly) {
                    for (e = my_first_iteration; e <= my_last_iteration; ++e) {
                        int success = model_getmemberfname_async(m, das->ensdir, ot->varname, ot->name, e + 1, t, fname);

                        H(das, nobs, obsids, fname, e + 1, t, ot->varname, ot->varname2, (ot->issurface) ? (void*) vv : (void*) vvv, das->S[e]);
                        enkf_printf((success) ? "a" : "s");
                        fflush(stdout);
                    }
                }

                if (das->mode == MODE_ENOI) {
                    if (enkf_obstype == OBSTYPE_VALUE) {
                        int success = model_getbgfname_async(m, das->bgdir, ot->varname, ot->name, t, fname);

                        H(das, nobs, obsids, fname, -1, t, ot->varname, ot->varname2, (ot->issurface) ? (void*) vv : (void*) vvv, Hx);
                        enkf_printf((success) ? "A" : "S");
                        fflush(stdout);
                    } else if (enkf_obstype == OBSTYPE_INNOVATION) {
                        Hx[0] = 0;
                        enkf_printf("-");
                        fflush(stdout);
                    }
                }

                free(obsids);
            }
        } else {
            obs_find_bytype(obs, i, &nobs, &obsids);
            if (nobs == 0)
                goto next;

            if (das->mode == MODE_ENKF || !enkf_fstatsonly) {
                for (e = my_first_iteration; e <= my_last_iteration; ++e) {
                    model_getmemberfname(m, das->ensdir, ot->varname, e + 1, fname);
                    H(das, nobs, obsids, fname, e + 1, MAXINT, ot->varname, ot->varname2, (ot->issurface) ? (void*) vv : (void*) vvv, das->S[e]);
                    enkf_printf(".");
                    fflush(stdout);
                }
            }

            if (das->mode == MODE_ENOI) {
                if (enkf_obstype == OBSTYPE_VALUE) {
                    model_getbgfname(m, das->bgdir, ot->varname, fname);
                    H(das, nobs, obsids, fname, -1, MAXINT, ot->varname, ot->varname2, (ot->issurface) ? (void*) vv : (void*) vvv, Hx);
                    enkf_printf("+");
                    fflush(stdout);
                } else if (enkf_obstype == OBSTYPE_INNOVATION) {
                    Hx[0] = 0;
                    enkf_printf("-");
                    fflush(stdout);
                }
            }

            free(obsids);
        }

      next:

        if (ot->issurface)
            free2d(vv);
        else
            free3d(vvv);
        enkf_printf("\n");
    }                           /* for i (over obstypes) */

#if defined(MPI)
    if (das->mode == MODE_ENKF || !enkf_fstatsonly) {
#if !defined(HE_VIAFILE)
        /*
         * communicate HE via MPI
         */
        int ierror, count;

        /*
         * Blocking communications can create a bottleneck in instances with
         * large number of observations (e.g., 2e6 obs., 144 members, 48
         * processes), but asynchronous send/receive seem to work well
         */
        if (rank > 0) {
            MPI_Request request;

            /*
             * send ensemble observations to master
             */
            count = (my_last_iteration - my_first_iteration + 1) * obs->nobs;
            ierror = MPI_Isend(das->S[my_first_iteration], count, MPIENSOBSTYPE, 0, rank, MPI_COMM_WORLD, &request);
            assert(ierror == MPI_SUCCESS);
        } else {
            int r;
            MPI_Request* requests = malloc((nprocesses - 1) * sizeof(MPI_Request));

            /*
             * collect ensemble observations from slaves
             */
            for (r = 1; r < nprocesses; ++r) {
                count = (last_iteration[r] - first_iteration[r] + 1) * obs->nobs;
                ierror = MPI_Irecv(das->S[first_iteration[r]], count, MPIENSOBSTYPE, r, r, MPI_COMM_WORLD, &requests[r - 1]);
                assert(ierror == MPI_SUCCESS);
            }
            ierror = MPI_Waitall(nprocesses - 1, requests, MPI_STATUS_IGNORE);
            assert(ierror == MPI_SUCCESS);
            free(requests);
        }
        /*
         * now send the full set of ensemble observations to slaves
         */
        count = das->nmem * obs->nobs;
        ierror = MPI_Bcast(das->S[0], count, MPIENSOBSTYPE, 0, MPI_COMM_WORLD);
        assert(ierror == MPI_SUCCESS);
#else
        /*
         * communicate HE via file
         */
        {
            int ncid;
            int varid;
            size_t start[2], count[2];

            if (rank == 0) {
                int dimids[2];

                ncw_create(FNAME_HE, NC_CLOBBER | NC_64BIT_OFFSET, &ncid);
                ncw_def_dim(FNAME_HE, ncid, "m", das->nmem, &dimids[0]);
                ncw_def_dim(FNAME_HE, ncid, "p", obs->nobs, &dimids[1]);
                ncw_def_var(FNAME_HE, ncid, "HE", NC_FLOAT, 2, dimids, &varid);
                ncw_close(FNAME_HE, ncid);
            }
            MPI_Barrier(MPI_COMM_WORLD);

            ncw_open(FNAME_HE, NC_WRITE, &ncid);
            ncw_inq_varid(FNAME_HE, ncid, "HE", &varid);
            start[0] = my_first_iteration;
            start[1] = 0;
            count[0] = my_last_iteration - my_first_iteration + 1;
            count[1] = obs->nobs;
            ncw_put_vara_float(FNAME_HE, ncid, varid, start, count, das->S[my_first_iteration]);
            ncw_close(FNAME_HE, ncid);
            MPI_Barrier(MPI_COMM_WORLD);

            ncw_open(FNAME_HE, NC_NOWRITE, &ncid);
            ncw_inq_varid(FNAME_HE, ncid, "HE", &varid);
            ncw_get_var_float(FNAME_HE, ncid, varid, das->S[0]);
            ncw_close(FNAME_HE, ncid);
        }
#endif
    }
#endif

    if (das->mode == MODE_ENOI) {
        /*
         * subtract ensemble mean; add background
         */
        if (!enkf_fstatsonly) {
            double* ensmean = calloc(obs->nobs, sizeof(double));

            for (e = 0; e < das->nmem; ++e) {
                ENSOBSTYPE* Se = das->S[e];

                for (i = 0; i < obs->nobs; ++i)
                    ensmean[i] += Se[i];
            }
            for (i = 0; i < obs->nobs; ++i)
                ensmean[i] /= (double) das->nmem;

            for (e = 0; e < das->nmem; ++e) {
                ENSOBSTYPE* Se = das->S[e];

                for (i = 0; i < obs->nobs; ++i)
                    Se[i] += Hx[i] - ensmean[i];
            }

            free(ensmean);
        } else {
            for (e = 0; e < das->nmem; ++e) {
                ENSOBSTYPE* Se = das->S[e];

                for (i = 0; i < obs->nobs; ++i)
                    Se[i] = Hx[i];
            }
        }
    }

    if (das->mode == MODE_ENOI)
        free(Hx);
}
예제 #22
0
void obsmeta_read(enkfprm* prm, int* nmeta, obsmeta** meta)
{
    char* fname = prm->obsprm;
    FILE* f = NULL;
    char buf[MAXSTRLEN];
    int line;
    obsmeta* m = NULL;
    int i, j;

    *nmeta = 0;
    *meta = NULL;

    f = enkf_fopen(fname, "r");

    line = 0;
    while (fgets(buf, MAXSTRLEN, f) != NULL) {
        char seps[] = " =\t\n";
        char* token;

        line++;
        if (buf[0] == '#')
            continue;
        if ((token = strtok(buf, seps)) == NULL)
            continue;
        if (strcasecmp(token, "PRODUCT") == 0) {
            if ((token = strtok(NULL, seps)) == NULL)
                enkf_quit("%s, l.%d: PRODUCT not specified", fname, line);

            *meta = realloc(*meta, (*nmeta + 1) * sizeof(obsmeta));
            m = &(*meta)[*nmeta];
            obsmeta_init(m);
            m->product = strdup(token);
            (*nmeta)++;
        } else if (strcasecmp(token, "READER") == 0) {
            if ((token = strtok(NULL, seps)) == NULL)
                enkf_quit("%s, l.%d: READER not specified", fname, line);
            m->reader = strdup(token);
        } else if (strcasecmp(token, "TYPE") == 0) {
            if ((token = strtok(NULL, seps)) == NULL)
                enkf_quit("%s, l.%d: TYPE not specified", fname, line);
            m->type = strdup(token);
        } else if (strcasecmp(token, "FILE") == 0) {
            if ((token = strtok(NULL, seps)) == NULL)
                enkf_quit("%s, l.%d: FILE not specified", fname, line);
            obsmeta_addfname(m, token);
        } else if (strcasecmp(token, "ERROR_STD") == 0) {
            if ((token = strtok(NULL, seps)) == NULL)
                enkf_quit("%s, l.%d: STD not specified", fname, line);
            else {
                double std;
                m->stdtypes = realloc(m->stdtypes, (m->nstds + 1) * sizeof(int));
                m->stdops = realloc(m->stdops, (m->nstds + 1) * sizeof(int));
                m->stds = realloc(m->stds, (m->nstds + 1) * sizeof(void*));
                m->varnames = realloc(m->varnames, (m->nstds + 1) * sizeof(char*));
                if (str2double(token, &std)) {
                    if (!isfinite(std) || std < 0.0)
                        enkf_quit("%s, l.%d: invalid STD value", fname, line);
                    m->stdtypes[m->nstds] = STDTYPE_VALUE;
                    m->stds[m->nstds] = malloc(sizeof(double));
                    *((double*) m->stds[m->nstds]) = std;
                    m->varnames[m->nstds] = NULL;
                } else {
                    m->stdtypes[m->nstds] = STDTYPE_FILE;

                    m->stds[m->nstds] = strdup(token);
                    if ((token = strtok(NULL, seps)) == NULL)
                        enkf_quit("%s, l.%d: variable name not specified", fname, line);
                    m->varnames[m->nstds] = strdup(token);
                }
                if ((token = strtok(NULL, seps)) == NULL)
                    m->stdops[m->nstds] = ARITHMETIC_EQ;
                else if (strncasecmp(token, "EQ", 2) == 0)
                    m->stdops[m->nstds] = ARITHMETIC_EQ;
                else if (strncasecmp(token, "PL", 2) == 0)
                    m->stdops[m->nstds] = ARITHMETIC_PLUS;
                else if (strncasecmp(token, "MU", 2) == 0)
                    m->stdops[m->nstds] = ARITHMETIC_MULT;
                else if (strncasecmp(token, "MI", 2) == 0)
                    m->stdops[m->nstds] = ARITHMETIC_MIN;
                else if (strncasecmp(token, "MA", 2) == 0)
                    m->stdops[m->nstds] = ARITHMETIC_MAX;
                else
                    enkf_quit("%s, l.%d:, unknown operation", fname, line);
                m->nstds++;
            }
        } else
            enkf_quit("%s, l.%d: unknown token \"%s\"", fname, line, token);
    }

    fclose(f);

    /*
     * print summary 
     */
    for (i = 0; i < (*nmeta); ++i) {
        obsmeta* m = &(*meta)[i];

        enkf_printf("    PRODUCT = %s\n", m->product);
        if (m->reader == NULL) {
            m->reader = strdup("standard");
            enkf_printf("      (assumed) READER = %s\n", m->reader);
        } else
            enkf_printf("      READER = %s\n", m->reader);
        if (m->type == NULL)
            enkf_quit("%s: obsservation type not specified for product \"%s\"", fname, m->product);
        enkf_printf("      TYPE = %s\n", m->type);
        for (j = 0; j < m->nfiles; ++j)
            enkf_printf("      File:        obsmeta.c = %s\n", m->fnames[j]);
        for (j = 0; j < m->nstds; ++j) {
            char operstr[MAXSTRLEN] = "";

            if (m->stdops[j] == ARITHMETIC_EQ)
                strcpy(operstr, "EQUAL");
            else if (m->stdops[j] == ARITHMETIC_PLUS)
                strcpy(operstr, "PLUS");
            else if (m->stdops[j] == ARITHMETIC_MULT)
                strcpy(operstr, "MULT");
            else if (m->stdops[j] == ARITHMETIC_MIN)
                strcpy(operstr, "MIN");
            else if (m->stdops[j] == ARITHMETIC_MAX)
                strcpy(operstr, "MAX");

            if (m->stdtypes[j] == STDTYPE_VALUE)
                enkf_printf("      ERROR_STD = %.3g, operation = %s\n", *((double*) m->stds[j]), operstr);
            else if (m->stdtypes[j] == STDTYPE_FILE)
                enkf_printf("      ERROR_STD = %s %s, operation = %s\n", (char*) m->stds[j], m->varnames[j], operstr);
        }
    }

    /*
     * check asynchronous obs types 
     */
    do {
        for (j = 0; j < prm->nasync; ++j) {
            for (i = 0; i < (*nmeta); ++i) {
                obsmeta* m = &(*meta)[i];

                if (strcmp(m->type, prm->async_types[j]) == 0)
                    break;
            }
            if (i == (*nmeta)) {
                int k;

                enkf_printf("    WARNING: %s: asynchronous type \"%s\" not in obs\n", prm->fname, prm->async_types[j]);
                /*
                 * eliminate redundant entry 
                 */
                for (k = j; k < prm->nasync - 1; ++k)
                    prm->async_types[k] = prm->async_types[k + 1];
                prm->nasync--;
            }
        }
    } while (j != prm->nasync);
}
예제 #23
0
void reader_jplmur_gridded(char* fname, int fid, obsmeta* meta, grid* g, observations* obs)
{
    int ksurf = grid_getsurflayerid(g);
    char* varname = "analysed_sst";
    char* lonname = "lon";
    char* latname = "lat";
    char* npointsname = NULL;
    char* stdname = "analysis_error";
    char* estdname = NULL;
    char* timename = "time";
    int ncid;
    int ndim_var, ndim_xy;
    size_t dimlen_var[3], dimlen_xy[2];

    float varshift = -273.15;
    double mindepth = 0.0;
    char instrument[MAXSTRLEN];

    int iscurv = -1;
    size_t ni = 0, nj = 0, n = 0, n_var = 0;
    int varid_lon = -1, varid_lat = -1;
    double* lon = NULL;
    double* lat = NULL;
    int varid_var = -1, varid_npoints = -1, varid_std = -1, varid_estd = -1, varid_time = -1;
    float* var = NULL;
    float var_fill_value = NAN;
    float var_add_offset = NAN, var_scale_factor = NAN;
    double var_estd = NAN;
    short* npoints = NULL;
    float* std = NULL;
    float std_add_offset = NAN, std_scale_factor = NAN;
    float std_fill_value = NAN;
    float* estd = NULL;
    float estd_add_offset = NAN, estd_scale_factor = NAN;
    float estd_fill_value = NAN;
    int have_time = 1;
    int singletime = -1;
    float* time = NULL;
    float time_add_offset = NAN, time_scale_factor = NAN;
    float time_fill_value = NAN;
    char tunits[MAXSTRLEN];
    double tunits_multiple = NAN, tunits_offset = NAN;
    int i, nobs_read;
    strcpy(instrument, meta->product);
    for (i = 0; i < meta->npars; ++i) {
        if (strcasecmp(meta->pars[i].name, "VARNAME") == 0)
            varname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "TIMENAME") == 0)
            timename = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "NPOINTSNAME") == 0)
            npointsname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "LONNAME") == 0)
            lonname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "LATNAME") == 0)
            latname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "STDNAME") == 0)
            stdname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "ESTDNAME") == 0)
            estdname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "VARSHIFT") == 0) {
            if (!str2float(meta->pars[i].value, &varshift))
                enkf_quit("observation prm file: can not convert VARSHIFT = \"%s\" to float\n", meta->pars[i].value);
            enkf_printf("        VARSHIFT = %s\n", meta->pars[i].value);
        } else if (strcasecmp(meta->pars[i].name, "MINDEPTH") == 0) {
            if (!str2double(meta->pars[i].value, &mindepth))
                enkf_quit("observation prm file: can not convert MINDEPTH = \"%s\" to double\n", meta->pars[i].value);
            enkf_printf("        MINDEPTH = %f\n", mindepth);
        } else if (strcasecmp(meta->pars[i].name, "INSTRUMENT") == 0) {
            strncpy(instrument, meta->pars[i].value, MAXSTRLEN);
        } else
            enkf_quit("unknown PARAMETER \"%s\"\n", meta->pars[i].name);
    }
//    if (varname == NULL)
//        enkf_quit("reader_xy_gridded(): %s variable name not specified", fname);

    ncw_open(fname, NC_NOWRITE, &ncid);
    ncw_inq_varid(ncid, varname, &varid_var);
    ncw_inq_vardims(ncid, varid_var, 3, &ndim_var, dimlen_var);
    if (ndim_var == 3) {
        int dimid[3];
        size_t nr;

        ncw_inq_vardimid(ncid, varid_var, dimid);
        ncw_inq_dimlen(ncid, dimid[0], &nr);
        if (nr != 1)
            enkf_quit("reader_xy_gridded(): %d records (currently only one is allowed)", nr);
        n_var = dimlen_var[1] * dimlen_var[2];
    } else if (ndim_var == 2) {
        if (nc_hasunlimdim(ncid))
            enkf_quit("reader_xy_gridded(): %s: %s: not enough spatial dimensions (must be 2)", fname, varname);
        n_var = dimlen_var[0] * dimlen_var[1];
    } else if (ndim_var != 2)
        enkf_quit("reader_xy_gridded(): %s: # dimensions = %d (must be 2 or 3 with only one record)", fname, ndim_var);

    if (lonname != NULL)
        ncw_inq_varid(ncid, lonname, &varid_lon);
    else if (ncw_var_exists(ncid, "lon"))
        ncw_inq_varid(ncid, "lon", &varid_lon);
    else if (ncw_var_exists(ncid, "longitude"))
        ncw_inq_varid(ncid, "longitude", &varid_lon);
    else
        enkf_quit("reader_xy_gridded(): %s: could not find longitude variable", fname);
    ncw_inq_vardims(ncid, varid_lon, 2, &ndim_xy, dimlen_xy);
    if (ndim_xy == 1) {
        iscurv = 0;
        ni = dimlen_xy[0];
    } else if (ndim_xy == 2) {
        iscurv = 1;
        ni = dimlen_xy[1];
        nj = dimlen_xy[0];
    } else
        enkf_quit("reader_xy_gridded(): %s: coordinate variable \"%s\" has neither 1 or 2 dimensions", fname, lonname);

    if (latname != NULL)
        ncw_inq_varid(ncid, latname, &varid_lat);
    else if (ncw_var_exists(ncid, "lat"))
        ncw_inq_varid(ncid, "lat", &varid_lat);
    else if (ncw_var_exists(ncid, "latitude"))
        ncw_inq_varid(ncid, "latitude", &varid_lat);
    else
        enkf_quit("reader_xy_gridded(): %s: could not find latitude variable", fname);
    if (iscurv == 0) {
        ncw_check_varndims(ncid, varid_lat, 1);
        ncw_inq_vardims(ncid, varid_lat, 1, NULL, &nj);
    } else
        ncw_check_vardims(ncid, varid_lat, 2, dimlen_xy);

    enkf_printf("        (ni, nj) = (%u, %u)\n", ni, nj);
    n = ni * nj;
    if (n != n_var)
        enkf_quit("reader_xy_gridded(): %s: dimensions of variable \"%s\" do not match coordinate dimensions", fname, varname);
    if (dimlen_var[ndim_var - 1] != ni)
        enkf_quit("reader_xy_gridded(): %s: %s: longitude must be the inner coordinate", fname, varname);

    if (iscurv == 0) {
        lon = malloc(ni * sizeof(double));
        lat = malloc(nj * sizeof(double));
    } else {
        lon = malloc(n * sizeof(double));
        lat = malloc(n * sizeof(double));
    }
    ncw_get_var_double(ncid, varid_lon, lon);
    ncw_get_var_double(ncid, varid_lat, lat);

    var = malloc(n * sizeof(float));
    ncw_get_var_float(ncid, varid_var, var);
    if (ncw_att_exists(ncid, varid_var, "add_offset")) {
        ncw_get_att_float(ncid, varid_var, "add_offset", &var_add_offset);
        ncw_get_att_float(ncid, varid_var, "scale_factor", &var_scale_factor);
    }
    if (ncw_att_exists(ncid, varid_var, "_FillValue"))
        ncw_get_att_float(ncid, varid_var, "_FillValue", &var_fill_value);

    if (npointsname != NULL)
        ncw_inq_varid(ncid, npointsname, &varid_npoints);
    else if (ncw_var_exists(ncid, "npoints"))
        ncw_inq_varid(ncid, "npoints", &varid_npoints);
    if (varid_npoints >= 0) {
        npoints = malloc(n * sizeof(short));
        ncw_get_var_short(ncid, varid_npoints, npoints);
    }

    if (stdname != NULL)
        ncw_inq_varid(ncid, stdname, &varid_std);
    else if (ncw_var_exists(ncid, "std"))
        ncw_inq_varid(ncid, "std", &varid_std);
    if (varid_std >= 0) {
        std = malloc(n * sizeof(float));
        ncw_get_var_float(ncid, varid_std, std);
        if (ncw_att_exists(ncid, varid_std, "_FillValue"))
            ncw_get_att_float(ncid, varid_std, "_FillValue", &std_fill_value);
        if (ncw_att_exists(ncid, varid_std, "add_offset")) {
            ncw_get_att_float(ncid, varid_std, "add_offset", &std_add_offset);
            ncw_get_att_float(ncid, varid_std, "scale_factor", &std_scale_factor);
        }
    }

    if (estdname != NULL)
        ncw_inq_varid(ncid, estdname, &varid_estd);
    else if (ncw_var_exists(ncid, "error_std"))
        ncw_inq_varid(ncid, "error_std", &varid_estd);
    if (varid_estd >= 0) {
        estd = malloc(n * sizeof(float));
        ncw_get_var_float(ncid, varid_estd, estd);
        if (ncw_att_exists(ncid, varid_estd, "_FillValue"))
            ncw_get_att_float(ncid, varid_estd, "_FillValue", &estd_fill_value);
        if (ncw_att_exists(ncid, varid_estd, "add_offset")) {
            ncw_get_att_float(ncid, varid_estd, "add_offset", &estd_add_offset);
            ncw_get_att_float(ncid, varid_estd, "scale_factor", &estd_scale_factor);
        }
    }

    if (std == NULL && estd == NULL) {
        if (ncw_att_exists(ncid, varid_var, "error_std")) {
            ncw_check_attlen(ncid, varid_var, "error_std", 1);
            ncw_get_att_double(ncid, varid_var, "error_std", &var_estd);
        }
    }

    if (timename != NULL)
        ncw_inq_varid(ncid, timename, &varid_time);
    else if (ncw_var_exists(ncid, "time"))
        ncw_inq_varid(ncid, "time", &varid_time);
    else {
        enkf_printf("        reader_xy_gridded(): %s: no TIME variable\n", fname);
        have_time = 0;
    }

    if (have_time) {
        int timendims;
        int timedimids[NC_MAX_DIMS];
        size_t timelen = 1;

        ncw_inq_varndims(ncid, varid_time, &timendims);
        ncw_inq_vardimid(ncid, varid_time, timedimids);
        for (i = 0; i < timendims; ++i) {
            size_t dimlen;

            ncw_inq_dimlen(ncid, timedimids[i], &dimlen);
            timelen *= dimlen;
        }

        if (timelen == 1) {
            singletime = 1;
            time = malloc(sizeof(float));
        } else {
            singletime = 0;
            assert(timelen == n);
            time = malloc(n * sizeof(float));
        }

        ncw_get_var_float(ncid, varid_time, time);
        if (ncw_att_exists(ncid, varid_time, "_FillValue"))
            ncw_get_att_float(ncid, varid_time, "_FillValue", &time_fill_value);
        if (ncw_att_exists(ncid, varid_time, "add_offset")) {
            ncw_get_att_float(ncid, varid_time, "add_offset", &time_add_offset);
            ncw_get_att_float(ncid, varid_time, "scale_factor", &time_scale_factor);
        }
        ncw_get_att_text(ncid, varid_time, "units", tunits);
        tunits_convert(tunits, &tunits_multiple, &tunits_offset);
    }

    ncw_close(ncid);

    nobs_read = 0;
    for (i = 0; i < (int) n; ++i) {
        observation* o;
        obstype* ot;

        if ((npoints != NULL && npoints[i] == 0) || var[i] == var_fill_value || isnan(var[i]) || (std != NULL && (std[i] == std_fill_value || isnan(std[i]))) || (estd != NULL && (estd[i] == estd_fill_value || isnan(estd[i]))) || (have_time && !singletime && (time[i] == time_fill_value || isnan(time[i]))))
            continue;

        nobs_read++;
        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, instrument, -1);
        o->id = obs->nobs;
        o->fid = fid;
        o->batch = 0;
        if (!isnan(var_add_offset))
            o->value = (double) (var[i] * var_scale_factor + var_add_offset + varshift);
        else
            o->value = (double) (var[i] + varshift);
        if (!isnan(var_estd)) {
            o->std = var_estd;
        }
        else {
            if (!isnan(std_add_offset))
                o->std = (double) (std[i] * std_scale_factor + std_add_offset);
            else
                o->std = (double) std[i];
             
            if (!isnan(estd_add_offset)) {
                double std2 = (double) (estd[i] * estd_scale_factor + estd_add_offset);
                o->std = (o->std > std2) ? o->std : std2;
            } 
        }
        if (iscurv == 0) {
            o->lon = lon[i % ni];
            o->lat = lat[i / ni];
        } else {
            o->lon = lon[i];
            o->lat = lat[i];
        }
        o->depth = 0.0;
        o->fk = (double) ksurf;
        o->status = grid_xy2fij(g, o->lon, o->lat, &o->fi, &o->fj);
        if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
            continue;
        if ((o->status == STATUS_OK) && (o->lon <= ot->xmin || o->lon >= ot->xmax || o->lat <= ot->ymin || o->lat >= ot->ymax))
            o->status = STATUS_OUTSIDEOBSDOMAIN;
        o->model_depth = NAN;   /* set in obs_add() */
        if (have_time) {
            float t = (singletime) ? time[0] : time[i];

            if (!isnan(time_add_offset))
                o->date = (double) (t * time_scale_factor + time_add_offset) * tunits_multiple + tunits_offset;
            else
                o->date = (double) t* tunits_multiple + tunits_offset;
        } else
            o->date = NAN;

        o->aux = -1;

        obs->nobs++;
    }
    enkf_printf("        nobs = %d\n", nobs_read);
}
예제 #24
0
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);
}
예제 #25
0
파일: ensobs.c 프로젝트: juicydut/enkf-c
/** Updates ensemble observations by applying X5
 */
static void update_HE(dasystem* das)
{
    model* m = das->m;
    int ngrid = model_getngrid(m);
    int gid;
    observations* obs = das->obs;
    int e, o;
    float* HEi_f;
    float* HEi_a;
    char do_T = 'T';
    float alpha = 1.0f;
    float beta = 0.0f;
    int inc = 1;

    enkf_printf("    updating HE:\n");
    assert(das->s_mode == S_MODE_HE_f);

    HEi_f = malloc(das->nmem * sizeof(ENSOBSTYPE));
    HEi_a = malloc(das->nmem * sizeof(ENSOBSTYPE));

    /*
     * the following code for interpolation of X5 essentially coincides with
     * that in das_updatefields() 
     */

    for (gid = 0, o = 0; gid < ngrid && o < obs->nobs; ++gid) {
        void* grid = model_getgridbyid(m, gid);
        int periodic_i = grid_isperiodic_x(grid);
        int periodic_j = grid_isperiodic_y(grid);

        char fname_X5[MAXSTRLEN];
        int ncid;
        int varid;
        int dimids[3];
        size_t dimlens[3];
        size_t start[3], count[3];
        float** X5j = NULL;
        float** X5jj = NULL;
        float** X5jj1 = NULL;
        float** X5jj2 = NULL;

        int mni, mnj;
        int* iiter;
        int* jiter;
        int i, j, ni, nj;
        int jj, stepj, ii, stepi;

        assert(obs->obstypes[obs->data[o].type].gridid == gid);

        das_getfname_X5(das, grid, fname_X5);

        ncw_open(fname_X5, NC_NOWRITE, &ncid);
        ncw_inq_varid(fname_X5, ncid, "X5", &varid);
        ncw_inq_vardimid(fname_X5, ncid, varid, dimids);
        for (i = 0; i < 3; ++i)
            ncw_inq_dimlen(fname_X5, ncid, dimids[i], &dimlens[i]);
        ni = dimlens[1];
        nj = dimlens[0];

        assert((int) dimlens[2] == das->nmem * das->nmem);

        jiter = malloc((nj + 1) * sizeof(int)); /* "+ 1" to handle periodic
                                                 * grids */
        iiter = malloc((ni + 1) * sizeof(int));
        for (j = 0, i = 0; j < nj; ++j, i += das->stride)
            jiter[j] = i;
        if (periodic_j)
            jiter[nj] = jiter[nj - 1] + das->stride;
        for (i = 0, j = 0; i < ni; ++i, j += das->stride)
            iiter[i] = j;
        if (periodic_i)
            iiter[ni] = iiter[ni - 1] + das->stride;

        grid_getdims(grid, &mni, &mnj, NULL);

        start[0] = 0;
        start[1] = 0;
        start[2] = 0;
        count[0] = 1;
        count[1] = ni;
        count[2] = das->nmem * das->nmem;
        X5j = alloc2d(mni, das->nmem * das->nmem, sizeof(float));
        if (das->stride > 1) {
            X5jj = alloc2d(ni, das->nmem * das->nmem, sizeof(float));
            X5jj1 = alloc2d(ni, das->nmem * das->nmem, sizeof(float));
            X5jj2 = alloc2d(ni, das->nmem * das->nmem, sizeof(float));
            ncw_get_vara_float(fname_X5, ncid, varid, start, count, X5jj2[0]);
        }

        /*
         * jj, ii are the indices of the subsampled grid; i, j are the indices
         * of the model grid 
         */
        for (jj = 0, j = 0; jj < nj; ++jj) {
            for (stepj = 0; stepj < das->stride && j < mnj; ++stepj, ++j) {
                if (das->stride == 1) {
                    /*
                     * no interpolation necessary; simply read the ETMs for the
                     * j-th row from disk 
                     */
                    start[0] = j;
                    ncw_get_vara_float(fname_X5, ncid, varid, start, count, X5j[0]);
                } else {
                    /*
                     * the following code interpolates the ETM back to the
                     * original grid, first by j, and then by i 
                     */
                    if (stepj == 0) {
                        memcpy(X5jj[0], X5jj2[0], ni * das->nmem * das->nmem * sizeof(float));
                        memcpy(X5jj1[0], X5jj2[0], ni * das->nmem * das->nmem * sizeof(float));
                        if (jj < nj - 1 || periodic_j) {
                            start[0] = (jj + 1) % nj;
                            ncw_get_vara_float(fname_X5, ncid, varid, start, count, X5jj2[0]);
                        }
                    } else {
                        float weight2 = (float) stepj / das->stride;
                        float weight1 = (float) 1.0 - weight2;

                        for (ii = 0; ii < ni; ++ii) {
                            float* X5jjii = X5jj[ii];
                            float* X5jj1ii = X5jj1[ii];
                            float* X5jj2ii = X5jj2[ii];

                            for (e = 0; e < das->nmem * das->nmem; ++e)
                                X5jjii[e] = X5jj1ii[e] * weight1 + X5jj2ii[e] * weight2;
                        }
                    }

                    for (ii = 0, i = 0; ii < ni; ++ii) {
                        for (stepi = 0; stepi < das->stride && i < mni; ++stepi, ++i) {
                            if (stepi == 0)
                                memcpy(X5j[i], X5jj[ii], das->nmem * das->nmem * sizeof(float));
                            else {
                                float weight2 = (float) stepi / das->stride;
                                float weight1 = (float) 1.0 - weight2;
                                float* X5jjii1 = X5jj[ii];
                                float* X5ji = X5j[i];
                                float* X5jjii2;

                                if (ii < ni - 1)
                                    X5jjii2 = X5jj[ii + 1];
                                else
                                    X5jjii2 = X5jj[(periodic_i) ? (ii + 1) % ni : ii];

                                for (e = 0; e < das->nmem * das->nmem; ++e)
                                    X5ji[e] = X5jjii1[e] * weight1 + X5jjii2[e] * weight2;
                            }
                        }
                    }
                }               /* stride != 1 */

                /*
                 * (at this stage X5j should contain the array of X5 matrices
                 * for the j-th row of the grid) 
                 */

                if (o >= obs->nobs)
                    break;
                if ((int) (obs->data[o].fj) > j)
                    continue;

                for (; o < obs->nobs && (int) (obs->data[o].fj) == j; ++o) {
                    float inflation = model_getvarinflation(m, obs->obstypes[obs->data[o].type].vid);

                    /*
                     * HE(i, :) = HE(i, :) * X5 
                     */
                    i = (int) (obs->data[o].fi);
                    for (e = 0; e < das->nmem; ++e)
                        HEi_f[e] = das->S[e][o];
                    sgemv_(&do_T, &das->nmem, &das->nmem, &alpha, X5j[i], &das->nmem, HEi_f, &inc, &beta, HEi_a, &inc);
                    /*
                     * applying inflation:
                     */
                    if (fabsf(inflation - 1.0f) > EPSF) {
                        float v_av = 0.0f;

                        for (e = 0; e < das->nmem; ++e)
                            v_av += HEi_a[e];
                        v_av /= (float) das->nmem;
                        for (e = 0; e < das->nmem; ++e)
                            HEi_a[e] = (HEi_a[e] - v_av) * inflation + v_av;
                    }

                    for (e = 0; e < das->nmem; ++e)
                        das->S[e][o] = HEi_a[e];
                }

            }                   /* for stepj */
        }                       /* for jj */

        ncw_close(fname_X5, ncid);

        free(iiter);
        free(jiter);
        free2d(X5j);
        if (das->stride > 1) {
            free2d(X5jj);
            free2d(X5jj1);
            free2d(X5jj2);
        }
    }                           /* for gid */

    free(HEi_a);
    free(HEi_f);
    das->s_mode = S_MODE_HE_a;
}                               /* update_HE() */
예제 #26
0
void reader_xy_gridded_hfradar(char* fname, int fid, obsmeta* meta, grid* g, observations* obs)
{

    int ksurf = grid_getsurflayerid(g);
    int isperiodic_i = grid_isperiodic_i(g);
    int** numlevels = grid_getnumlevels(g);
    float** grid_angle = grid_getangle(g);
    int grid_ni = 0, grid_nj = 0;

    char* varname = NULL;
    char* u_varname = NULL;
    char* v_varname = NULL;
    char* u_stdvarname = NULL;
    char* v_stdvarname = NULL;
    char* lonname = NULL;
    char* latname = NULL;
    char* gdopname = NULL; 
    char* npointsname_1 = NULL;
    char* npointsname_2 = NULL;
    char* stdname = NULL;
    char* estdname = NULL;
    char* timename = NULL;
    char* qcflagname = NULL;
    char* u_qcflagname = NULL;
    char* v_qcflagname = NULL;
    char* rotation_flag = NULL;

    int ncid;
    int ndim_var, ndim_xy;
    size_t dimlen_var[3], dimlen_xy[2];

    uint32_t qcflagvals = 0;
    float varshift = 0.0;
    float u_varshift = 0.0;
    float v_varshift = 0.0;
    double mindepth = 0.0;
    char instrument[MAXSTRLEN];

    int iscurv = -1;
    int need_rotation = -1;
    size_t ni = 0, nj = 0, n = 0, n_var = 0;
    int varid_lon = -1, varid_lat = -1;
    double* lon = NULL;
    double* lat = NULL;
    int varid_gdop = -1, varid_npoints_1 = -1, varid_npoints_2 = -1;
    int varid_var = -1, varid_std = -1, varid_estd = -1, varid_qcflag = -1, varid_time = -1;
    int varid_u = -1, varid_v =-1, varid_u_std = -1, varid_v_std = -1, varid_u_qcflag = -1, varid_v_qcflag = -1;
    float* var = NULL;
    float* u_var = NULL;
    float* v_var = NULL;
    float* u_std = NULL;
    float* v_std = NULL;
    float var_fill_value = NAN;
    float var_add_offset = NAN, var_scale_factor = NAN;
    
    float u_var_fill_value = NAN;
    float u_var_add_offset = NAN, u_var_scale_factor = NAN;
    float v_var_fill_value = NAN;
    float v_var_add_offset = NAN, v_var_scale_factor = NAN;
    
    float u_std_fill_value = NAN;
    float u_std_add_offset = NAN, u_std_scale_factor = NAN;
    float v_std_fill_value = NAN;
    float v_std_add_offset = NAN, v_std_scale_factor = NAN;

    double var_estd = NAN;
    float* gdop = NULL;
    short* npoints_1 = NULL;
    short* npoints_2 = NULL;
    float* std = NULL;
    float std_add_offset = NAN, std_scale_factor = NAN;
    float std_fill_value = NAN;
    float* estd = NULL;
    float estd_add_offset = NAN, estd_scale_factor = NAN;
    float estd_fill_value = NAN;
    int32_t* qcflag = NULL;
    int32_t* u_qcflag = NULL;
    int32_t* v_qcflag = NULL;

    int have_time = 1;
    int singletime = -1;
    float* time = NULL;
    float time_add_offset = NAN, time_scale_factor = NAN;
    float time_fill_value = NAN;
    char tunits[MAXSTRLEN];
    double tunits_multiple = NAN, tunits_offset = NAN;
    int i, nobs_read;

    strcpy(instrument, meta->product);
    for (i = 0; i < meta->npars; ++i) {
        if (strcasecmp(meta->pars[i].name, "VARNAME") == 0)
            varname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "ROTATION") == 0)
            rotation_flag = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "U_VARNAME") == 0)
            u_varname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "V_VARNAME") == 0)
            v_varname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "U_STD") == 0)
            u_stdvarname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "V_STD") == 0)
            v_stdvarname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "TIMENAME") == 0)
            timename = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "GDOPNAME") == 0)
            gdopname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "NPOINTSNAME_1") == 0)
            npointsname_1 = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "NPOINTSNAME_2") == 0)
            npointsname_2 = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "LONNAME") == 0)
            lonname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "LATNAME") == 0)
            latname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "STDNAME") == 0)
            stdname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "ESTDNAME") == 0)
            estdname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "QCFLAGNAME") == 0)
            qcflagname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "U_QCFLAGNAME") == 0)
            u_qcflagname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "V_QCFLAGNAME") == 0)
            v_qcflagname = meta->pars[i].value;
        else if (strcasecmp(meta->pars[i].name, "QCFLAGVALS") == 0) {
            char* pline = meta->pars[i].value;
            int linelen = sizeof(pline);
            char lineval[linelen];
            char* line = strcpy(lineval,pline);
            char seps[] = " ,";
            char* token;
            int val;

            qcflagvals = 0;
            while ((token = strtok(line, seps)) != NULL) {
                if (!str2int(token, &val))
                    enkf_quit("%s: could not convert QCFLAGVALS entry \"%s\" to integer", meta->prmfname, token);
                if (val < 0 || val > 31)
                    enkf_quit("%s: QCFLAGVALS entry = %d (supposed to be in [0,31] interval", meta->prmfname, val);
                qcflagvals |= 1 << val;
                line = NULL;
            }
            if (qcflagvals == 0)
                enkf_quit("%s: no valid flag entries found after QCFLAGVALS\n", meta->prmfname);
        } else if (strcasecmp(meta->pars[i].name, "VARSHIFT") == 0) {
            if (!str2float(meta->pars[i].value, &varshift))
                enkf_quit("%s: can not convert VARSHIFT = \"%s\" to float\n", meta->prmfname, meta->pars[i].value);
            enkf_printf("        VARSHIFT = %s\n", meta->pars[i].value);
        } else if (strcasecmp(meta->pars[i].name, "U_VARSHIFT") == 0) {
            if (!str2float(meta->pars[i].value, &u_varshift))
                enkf_quit("%s: can not convert U_VARSHIFT = \"%s\" to float\n", meta->prmfname, meta->pars[i].value);
            enkf_printf("        U_VARSHIFT = %s\n", meta->pars[i].value);
        } else if (strcasecmp(meta->pars[i].name, "V_VARSHIFT") == 0) {
            if (!str2float(meta->pars[i].value, &v_varshift))
                enkf_quit("%s: can not convert V_VARSHIFT = \"%s\" to float\n", meta->prmfname, meta->pars[i].value);
            enkf_printf("        V_VARSHIFT = %s\n", meta->pars[i].value);

        } else if (strcasecmp(meta->pars[i].name, "MINDEPTH") == 0) {
            if (!str2double(meta->pars[i].value, &mindepth))
                enkf_quit("%s: can not convert MINDEPTH = \"%s\" to double\n", meta->prmfname, meta->pars[i].value);
            enkf_printf("        MINDEPTH = %f\n", mindepth);
        } else if (strcasecmp(meta->pars[i].name, "INSTRUMENT") == 0) {
            strncpy(instrument, meta->pars[i].value, MAXSTRLEN);
        } else
            enkf_quit("unknown PARAMETER \"%s\"\n", meta->pars[i].name);
    }

    if (varname == NULL)
        enkf_quit("reader_xy_gridded(): %s variable name not specified", fname);

    if (rotation_flag != NULL) {
        int bool_rotation_flag, valid_rotation_flag;
        bool_rotation_flag = atoi(rotation_flag);
        valid_rotation_flag = (bool_rotation_flag == 0 || bool_rotation_flag == 1);
        
        if (valid_rotation_flag) {
            need_rotation = bool_rotation_flag == 1;
            grid_getdims(g, &grid_ni, &grid_nj, NULL);
            if (need_rotation == 1 && grid_angle == NULL)
                enkf_quit("reader_xy_gridded_hfradar(): %s cannot rotate vectors without ANGLE parameter defined within grid prm file",fname);    
            enkf_printf("\t#Rotation of vectors enabled\n");
        }
        else
            enkf_quit("reader_xy_gridded_hfradar(): %s invalid ROTATION parameter. Need to be a boolean digit");
    }

    ncw_open(fname, NC_NOWRITE, &ncid);
    ncw_inq_varid(ncid, varname, &varid_var);
    ncw_inq_vardims(ncid, varid_var, 3, &ndim_var, dimlen_var);
    if (ndim_var == 3) {
        int dimid[3];
        size_t nr;

        ncw_inq_vardimid(ncid, varid_var, dimid);
        ncw_inq_dimlen(ncid, dimid[0], &nr);
        if (nr != 1)
            enkf_quit("reader_xy_gridded(): %d records (currently only one is allowed)", nr);
        n_var = dimlen_var[1] * dimlen_var[2];
    } else if (ndim_var == 2) {
        if (nc_hasunlimdim(ncid))
            enkf_quit("reader_xy_gridded(): %s: %s: not enough spatial dimensions (must be 2)", fname, varname);
        n_var = dimlen_var[0] * dimlen_var[1];
    } else if (ndim_var != 2)
        enkf_quit("reader_xy_gridded(): %s: # dimensions = %d (must be 2 or 3 with only one record)", fname, ndim_var);

    if (lonname != NULL)
        ncw_inq_varid(ncid, lonname, &varid_lon);
    else if (ncw_var_exists(ncid, "lon"))
        ncw_inq_varid(ncid, "lon", &varid_lon);
    else if (ncw_var_exists(ncid, "longitude"))
        ncw_inq_varid(ncid, "longitude", &varid_lon);
    else if (ncw_var_exists(ncid, "LONGITUDE"))
        ncw_inq_varid(ncid, "LONGITUDE", &varid_lon);
    else
        enkf_quit("reader_xy_gridded(): %s: could not find longitude variable", fname);
    ncw_inq_vardims(ncid, varid_lon, 2, &ndim_xy, dimlen_xy);
    if (ndim_xy == 1) {
        iscurv = 0;
        ni = dimlen_xy[0];
    } else if (ndim_xy == 2) {
        iscurv = 1;
        ni = dimlen_xy[1];
        nj = dimlen_xy[0];
    } else
        enkf_quit("reader_xy_gridded(): %s: coordinate variable \"%s\" has neither 1 or 2 dimensions", fname, lonname);

    if (latname != NULL)
        ncw_inq_varid(ncid, latname, &varid_lat);
    else if (ncw_var_exists(ncid, "lat"))
        ncw_inq_varid(ncid, "lat", &varid_lat);
    else if (ncw_var_exists(ncid, "latitude"))
        ncw_inq_varid(ncid, "latitude", &varid_lat);
    else if (ncw_var_exists(ncid, "LATITUDE"))
        ncw_inq_varid(ncid, "LATITUDE", &varid_lat);
    else
        enkf_quit("reader_xy_gridded(): %s: could not find latitude variable", fname);
    if (iscurv == 0) {
        ncw_check_varndims(ncid, varid_lat, 1);
        ncw_inq_vardims(ncid, varid_lat, 1, NULL, &nj);
    } else
        ncw_check_vardims(ncid, varid_lat, 2, dimlen_xy);

    enkf_printf("        (ni, nj) = (%u, %u)\n", ni, nj);
    n = ni * nj;
    if (n != n_var)
        enkf_quit("reader_xy_gridded(): %s: dimensions of variable \"%s\" do not match coordinate dimensions", fname, varname);
    if (dimlen_var[ndim_var - 1] != ni)
        enkf_quit("reader_xy_gridded(): %s: %s: longitude must be the inner coordinate", fname, varname);

    if (iscurv == 0) {
        lon = malloc(ni * sizeof(double));
        lat = malloc(nj * sizeof(double));
    } else {
        lon = malloc(n * sizeof(double));
        lat = malloc(n * sizeof(double));
    }
    ncw_get_var_double(ncid, varid_lon, lon);
    ncw_get_var_double(ncid, varid_lat, lat);

    var = malloc(n * sizeof(float));
    ncw_get_var_float(ncid, varid_var, var);
    if (ncw_att_exists(ncid, varid_var, "add_offset")) {
        ncw_get_att_float(ncid, varid_var, "add_offset", &var_add_offset);
        ncw_get_att_float(ncid, varid_var, "scale_factor", &var_scale_factor);
    }
    if (ncw_att_exists(ncid, varid_var, "_FillValue"))
        ncw_get_att_float(ncid, varid_var, "_FillValue", &var_fill_value);

    if (gdopname != NULL)
        ncw_inq_varid(ncid, gdopname, &varid_gdop);
    else if (ncw_var_exists(ncid, "GDOP"))
        ncw_inq_varid(ncid, "GDOP", &varid_gdop);

    if (varid_gdop >= 0) {
        gdop = malloc(n * sizeof(float));
        ncw_get_var_float(ncid, varid_gdop, gdop);
        float gdop_fill_value, gdop_add_offset, gdop_scale_factor;
        if (ncw_att_exists(ncid, varid_gdop, "_FillValue"))
            ncw_get_att_float(ncid, varid_gdop, "_FillValue", &gdop_fill_value);
        if (ncw_att_exists(ncid, varid_gdop, "add_offset")) {
            ncw_get_att_float(ncid, varid_gdop, "add_offset", &gdop_add_offset);
            ncw_get_att_float(ncid, varid_gdop, "scale_factor", &gdop_scale_factor);
            }
    }

    if (npointsname_1 != NULL)
        ncw_inq_varid(ncid, npointsname_1, &varid_npoints_1);
    else if (ncw_var_exists(ncid, "NOBS1"))
        ncw_inq_varid(ncid, "NOBS1", &varid_npoints_1);
    if (varid_npoints_1 >= 0) {
        npoints_1 = malloc(n * sizeof(short));
        ncw_get_var_short(ncid, varid_npoints_1, npoints_1);
    }

    if (npointsname_2 != NULL)
        ncw_inq_varid(ncid, npointsname_2, &varid_npoints_2);
    else if (ncw_var_exists(ncid, "NOBS2"))
        ncw_inq_varid(ncid, "NOBS2", &varid_npoints_2);
    if (varid_npoints_2 >= 0) {
        npoints_2 = malloc(n * sizeof(short));
        ncw_get_var_short(ncid, varid_npoints_2, npoints_2);
    }

    if (need_rotation == 1) {

        if (u_varname != NULL ) 
            ncw_inq_varid(ncid, u_varname, &varid_u);
        else if (ncw_var_exists(ncid, "UCUR")) {
            ncw_inq_varid(ncid, "UCUR", &varid_u);
            u_varname = "UCUR";
        }
        if (varid_u >= 0) {
            u_var = malloc(n * sizeof(float));
            ncw_get_var_float(ncid,varid_u,u_var);
            if (ncw_att_exists(ncid,varid_u, "_FillValue"))
                ncw_get_att_float(ncid, varid_u, "_FillValue", &u_var_fill_value);
            if (ncw_att_exists(ncid,varid_u,"add_offset")) {
                ncw_get_att_float(ncid, varid_u, "add_offset", &u_var_add_offset);
                ncw_get_att_float(ncid, varid_u, "scale_factor", &u_var_scale_factor);
                }
        }
        else
            enkf_quit("reader_xy_gridded(): %s: Variable %s not found.",fname, u_varname);
        
        if (v_varname != NULL) 
            ncw_inq_varid(ncid, v_varname, &varid_v);
        else if (ncw_var_exists(ncid, "VCUR")) {
            ncw_inq_varid(ncid, "VCUR", &varid_v);
            v_varname = "VCUR";
        }
        if (varid_v >= 0) {
            v_var = malloc(n * sizeof(float));
            ncw_get_var_float(ncid,varid_v,v_var);
            if (ncw_att_exists(ncid,varid_v, "_FillValue"))
                ncw_get_att_float(ncid,varid_v, "_FillValue", &v_var_fill_value);
            if (ncw_att_exists(ncid,varid_v,"add_offset")) {
                ncw_get_att_float(ncid, varid_v, "add_offset", &v_var_add_offset);
                ncw_get_att_float(ncid, varid_v, "scale_factor", &v_var_scale_factor);
                }
        }
        else
            enkf_quit("reader_xy_gridded(): %s: Variable %s not found.",fname, v_varname);
    }

    if (stdname != NULL)
        ncw_inq_varid(ncid, stdname, &varid_std);
    else if (ncw_var_exists(ncid, "std"))
        ncw_inq_varid(ncid, "std", &varid_std);
    if (varid_std >= 0) {
        std = malloc(n * sizeof(float));
        ncw_get_var_float(ncid, varid_std, std);
        if (ncw_att_exists(ncid, varid_std, "_FillValue"))
            ncw_get_att_float(ncid, varid_std, "_FillValue", &std_fill_value);
        if (ncw_att_exists(ncid, varid_std, "add_offset")) {
            ncw_get_att_float(ncid, varid_std, "add_offset", &std_add_offset);
            ncw_get_att_float(ncid, varid_std, "scale_factor", &std_scale_factor);
        }
    }

    if (estdname != NULL)
        ncw_inq_varid(ncid, estdname, &varid_estd);
    else if (ncw_var_exists(ncid, "error_std"))
        ncw_inq_varid(ncid, "error_std", &varid_estd);
    if (varid_estd >= 0) {
        estd = malloc(n * sizeof(float));
        ncw_get_var_float(ncid, varid_estd, estd);
        if (ncw_att_exists(ncid, varid_estd, "_FillValue"))
            ncw_get_att_float(ncid, varid_estd, "_FillValue", &estd_fill_value);
        if (ncw_att_exists(ncid, varid_estd, "add_offset")) {
            ncw_get_att_float(ncid, varid_estd, "add_offset", &estd_add_offset);
            ncw_get_att_float(ncid, varid_estd, "scale_factor", &estd_scale_factor);
        }
    }

    if (std == NULL && estd == NULL)
        if (ncw_att_exists(ncid, varid_var, "error_std")) {
            ncw_check_attlen(ncid, varid_var, "error_std", 1);
            ncw_get_att_double(ncid, varid_var, "error_std", &var_estd);
        }

    if (u_stdvarname != NULL) 
        ncw_inq_varid(ncid, u_stdvarname, &varid_u_std);
    else if (ncw_var_exists(ncid, "UCUR_sd"))
        ncw_inq_varid(ncid, "UCUR_sd", &varid_u_std);
    if (varid_u_std >= 0) {
        u_std = malloc(n * sizeof(float));
        ncw_get_var_float(ncid, varid_u_std, u_std);
        if (ncw_att_exists(ncid, varid_u_std, "_FillValue"))
            ncw_get_att_float(ncid, varid_u_std, "_FillValue", &u_std_fill_value);
        if (ncw_att_exists(ncid, varid_u_std, "add_offset")) {
            ncw_get_att_float(ncid, varid_u_std, "add_offset", &u_std_add_offset);
            ncw_get_att_float(ncid, varid_u_std, "scale_factor", &u_std_scale_factor);
        }
    }

    if (v_stdvarname != NULL) 
        ncw_inq_varid(ncid, v_stdvarname, &varid_v_std);
    else if (ncw_var_exists(ncid, "vcur_sd"))
        ncw_inq_varid(ncid, "vcur_sd", &varid_v_std);
    if (varid_v_std >= 0) {
        v_std = malloc(n * sizeof(float));
        ncw_get_var_float(ncid, varid_v_std, v_std);
        if (ncw_att_exists(ncid, varid_v_std, "_FillValue"))
            ncw_get_att_float(ncid, varid_v_std, "_FillValue", &v_std_fill_value);
        if (ncw_att_exists(ncid, varid_v_std, "add_offset")) {
            ncw_get_att_float(ncid, varid_v_std, "add_offset", &v_std_add_offset);
            ncw_get_att_float(ncid, varid_v_std, "scale_factor", &v_std_scale_factor);
        }
    }

    if (qcflagname != NULL) {
        ncw_inq_varid(ncid, qcflagname, &varid_qcflag);
        qcflag = malloc(n * sizeof(int32_t));
        ncw_get_var_int(ncid, varid_qcflag, qcflag);
    }

    if (u_qcflagname != NULL) 
        ncw_inq_varid(ncid, u_qcflagname, &varid_u_qcflag);
    else if (ncw_var_exists(ncid, "UCUR_quality_control"))
        ncw_inq_varid(ncid, "UCUR_quality_control", &varid_u_qcflag);
    if (varid_u_qcflag >= 0) {
        u_qcflag = malloc(n * sizeof(int32_t));
        ncw_get_var_int(ncid, varid_u_qcflag, u_qcflag);
    }

    if (v_qcflagname != NULL) 
        ncw_inq_varid(ncid, v_qcflagname, &varid_v_qcflag);
    else if (ncw_var_exists(ncid, "VCUR_quality_control"))
        ncw_inq_varid(ncid, "VCUR_quality_control", &varid_v_qcflag);
    if (varid_v_qcflag >= 0) {
        v_qcflag = malloc(n * sizeof(int32_t));
        ncw_get_var_int(ncid, varid_v_qcflag, v_qcflag);
    }

    if (timename != NULL)
        ncw_inq_varid(ncid, timename, &varid_time);
    else if (ncw_var_exists(ncid, "time"))
        ncw_inq_varid(ncid, "time", &varid_time);
    else if (ncw_var_exists(ncid, "TIME"))
        ncw_inq_varid(ncid, "TIME", &varid_time);
    else {
        enkf_printf("        reader_xy_gridded(): %s: no TIME variable\n", fname);
        have_time = 0;
    }

    if (have_time) {
        int timendims;
        int timedimids[NC_MAX_DIMS];
        size_t timelen = 1;

        ncw_inq_varndims(ncid, varid_time, &timendims);
        ncw_inq_vardimid(ncid, varid_time, timedimids);
        for (i = 0; i < timendims; ++i) {
            size_t dimlen;

            ncw_inq_dimlen(ncid, timedimids[i], &dimlen);
            timelen *= dimlen;
        }

        if (timelen == 1) {
            singletime = 1;
            time = malloc(sizeof(float));
        } else {
            singletime = 0;
            assert(timelen == n);
            time = malloc(n * sizeof(float));
        }

        ncw_get_var_float(ncid, varid_time, time);
        if (ncw_att_exists(ncid, varid_time, "_FillValue"))
            ncw_get_att_float(ncid, varid_time, "_FillValue", &time_fill_value);
        if (ncw_att_exists(ncid, varid_time, "add_offset")) {
            ncw_get_att_float(ncid, varid_time, "add_offset", &time_add_offset);
            ncw_get_att_float(ncid, varid_time, "scale_factor", &time_scale_factor);
        }
        ncw_get_att_text(ncid, varid_time, "units", tunits);
        tunits_convert(tunits, &tunits_multiple, &tunits_offset);
    }

    ncw_close(ncid);

    nobs_read = 0;
    for (i = 0; i < (int) n; ++i) {
        observation* o;
        obstype* ot;
          int invalid_gdop, invalid_npoints1, invalid_npoints2, invalid_var, invalid_std, invalid_estd, invalid_u_var, invalid_v_var, invalid_time;

          invalid_gdop = (gdop != NULL && (gdop[i] > 180.0 || gdop[i] < 0.0));
          invalid_npoints1 = (npoints_1 != NULL &&  (npoints_1[i] == 0 || npoints_1[i]< 0));
          invalid_npoints2 = (npoints_2 != NULL && (npoints_2[i] == 0 || npoints_2[i] < 0));
          invalid_var = var[i] == var_fill_value || isnan(var[i]);
          invalid_std = (std != NULL && (std[i] == std_fill_value || isnan(std[i])));
          invalid_estd = (estd != NULL && (estd[i] == estd_fill_value || isnan(estd[i])));
          invalid_u_var = (u_var != NULL && (u_var[i] == u_var_fill_value || isnan(u_var[i])));
          invalid_v_var = (v_var != NULL && (v_var[i] == v_var_fill_value || isnan(v_var[i])));
          invalid_time = (have_time && !singletime && (time[i] == time_fill_value || isnan(time[i])));

        if (invalid_gdop || invalid_npoints1 || invalid_npoints2 || invalid_var || invalid_std || invalid_estd || invalid_u_var || invalid_v_var || invalid_time)
             continue;

        if (qcflag != NULL) {
            /* general qcflags has precedence in discarding obs*/
            if ( (qcflagvals != (qcflagvals | 1<<qcflag[i])) || (u_qcflag != NULL && (qcflagvals != (qcflagvals | 1<<u_qcflag[i]))) || (v_qcflag != NULL && (qcflagvals != (qcflagvals | 1<<v_qcflag[i]))) )
                continue;
        }

        /* [u,v]_qcflags has precedence in values. */
        if (u_qcflagname != NULL && v_qcflagname != NULL) {
            if ( (u_qcflag != NULL && (qcflagvals != (qcflagvals | 1<<u_qcflag[i]))) || (v_qcflag != NULL && (qcflagvals != (qcflagvals | 1<<v_qcflag[i]))) )
                 continue;
        } else if (u_qcflagname != NULL) {
            if (u_qcflag != NULL && (qcflagvals != (qcflagvals | 1<<u_qcflag[i])))
                continue;
        } else if (v_qcflagname != NULL) {
            if (v_qcflag != NULL && (qcflagvals != (qcflagvals | 1<<v_qcflag[i])))
                continue;
        }

        nobs_read++;
        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, instrument, -1);
        o->id = obs->nobs;
        o->fid = fid;
        o->batch = 0;
        
        /* Shifted the reading order for HF-Radar to obtain indexes */
        if (iscurv == 0) {
            o->lon = lon[i % ni];
            o->lat = lat[i / ni];
        } else {
            o->lon = lon[i];
            o->lat = lat[i];
        }
        o->depth = 0.0;
        o->fk = (double) ksurf;
        o->model_depth = NAN;   /* set in obs_add() */
        o->status = grid_xy2fij(g, o->lon, o->lat, &o->fi, &o->fj);
        if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
            continue;
        if ((o->status == STATUS_OK) && (o->lon <= ot->xmin || o->lon >= ot->xmax || o->lat <= ot->ymin || o->lat >= ot->ymax))
            o->status = STATUS_OUTSIDEOBSDOMAIN;

        if (need_rotation == 1) {
            double zonal, meridional, oangle;
            if (!isnan(u_var_add_offset))
                zonal = u_var[i] * u_var_scale_factor + u_var_add_offset + varshift + u_varshift;
            else
                zonal = u_var[i];
            if (!isnan(v_var_add_offset))
                meridional = v_var[i] * v_var_scale_factor + v_var_add_offset + varshift + u_varshift;
            else
                meridional = v_var[i];
                        
            oangle = interpolate2d(o->fi, o-> fj, grid_ni, grid_nj, grid_angle, numlevels, isperiodic_i);

            if (strcmp(varname,u_varname) == 0)
                o->value = zonal*cos(oangle) - meridional*sin(oangle);
            if (strcmp(varname,v_varname) == 0)
                o->value = zonal*sin(oangle) + meridional*cos(oangle);

        }
        else {
            if (!isnan(var_add_offset))
                o->value = (double) (var[i] * var_scale_factor + var_add_offset + varshift);
            else
                o->value = (double) (var[i] + varshift);
        }

        if (estd == NULL && std == NULL){
            if (!isnan(var_estd))
                o->std = var_estd;
        }
        else {
            if (std == NULL)
                o->std = 0.0;
            else {
                if (!isnan(std_add_offset))
                    o->std = (double) (std[i] * std_scale_factor + std_add_offset);
                else
                    o->std = (double) std[i];
            }
            if (estd != NULL) {
                if (!isnan(estd_add_offset)) {
                    double std2 = (double) (estd[i] * estd_scale_factor + estd_add_offset);
                    o->std = (o->std > std2) ? o->std : std2;
                } else
                    o->std = (o->std > estd[i]) ? o->std : estd[i];
            }
        }

        if (have_time) {
            float t = (singletime) ? time[0] : time[i];

            if (!isnan(time_add_offset))
                o->date = (double) (t * time_scale_factor + time_add_offset) * tunits_multiple + tunits_offset;
            else
                o->date = (double) t* tunits_multiple + tunits_offset;
        } else
            o->date = NAN;

        o->aux = -1;

        obs->nobs++;
    }
    enkf_printf("        nobs = %d\n", nobs_read);

    free(lon);
    free(lat);
    free(var);
    if (gdop != NULL)
        free(gdop);
    if (npoints_1 != NULL) 
        free(npoints_1);
    if (npoints_2 != NULL)
        free(npoints_2);
    if (u_var != NULL)
        free(u_var);
    if (v_var != NULL)
        free(v_var);
    if (std != NULL)
        free(std);
    if (estd != NULL)
        free(estd);
    if (u_std != NULL)
        free(u_std);
    if (v_std != NULL)
        free(v_std);
    if (qcflag != NULL)
        free(qcflag);
    if (u_qcflag != NULL)
        free(u_qcflag);
    if (v_qcflag != NULL)
        free(v_qcflag);
    if (time != NULL)
        free(time);
}
예제 #27
0
파일: model.c 프로젝트: TheProjecter/enkf-c
void model_describeprm(void)
{
    enkf_printf("\n");
    enkf_printf("  Model parameter file format:\n");
    enkf_printf("\n");
    enkf_printf("    NAME        = <name>\n");
    enkf_printf("\n");
    enkf_printf("    VAR         = <name>\n");
    enkf_printf("    GRID        = <name>\n");
    enkf_printf("  [ INFLATION   = <value> [<value> | PLAIN]]\n");
    enkf_printf("\n");
    enkf_printf("  [ <more of the above blocks> ]\n");
    enkf_printf("\n");
    enkf_printf("  Notes:\n");
    enkf_printf("    1. [ ... ] denotes an optional input\n");
    enkf_printf("    2. < ... > denotes a description of an entry\n");
    enkf_printf("    3. ... denotes repeating the previous item an arbitrary number of times\n");
    enkf_printf("\n");
}
예제 #28
0
/** For files of the form y<yyyy>/m<mm>/??_d<dd>.nc with no "time" variable.
 */
void reader_rads_standard2(char* fname, int fid, obsmeta* meta, model* m, observations* obs)
{
    int ncid;
    int dimid_nobs;
    size_t nobs_local;
    int varid_lon, varid_lat, varid_pass, varid_sla, varid_flag;
    double* lon;
    double* lat;
    int* pass;
    double* sla;
    int* flag;
    double error_std;
    char buf[MAXSTRLEN];
    int len;
    int year, month, day;
    double tunits_multiple, tunits_offset;
    char* basename;
    char instname[3];
    int mvid;
    float** depth;
    int i;

    ncw_open(fname, NC_NOWRITE, &ncid);

    ncw_inq_dimid(fname, ncid, "nobs", &dimid_nobs);
    ncw_inq_dimlen(fname, ncid, dimid_nobs, &nobs_local);
    enkf_printf("        nobs = %u\n", (unsigned int) nobs_local);

    if (nobs_local == 0)
        return;

    ncw_inq_varid(fname, ncid, "lon", &varid_lon);
    lon = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lon, lon);

    ncw_inq_varid(fname, ncid, "lat", &varid_lat);
    lat = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_lat, lat);

    ncw_inq_varid(fname, ncid, "pass", &varid_pass);
    pass = malloc(nobs_local * sizeof(int));
    ncw_get_var_int(fname, ncid, varid_pass, pass);

    ncw_inq_varid(fname, ncid, "sla", &varid_sla);
    sla = malloc(nobs_local * sizeof(double));
    ncw_get_var_double(fname, ncid, varid_sla, sla);
    ncw_get_att_double(fname, ncid, varid_sla, "error_std", &error_std);
    enkf_printf("        error_std = %3g\n", error_std);

    ncw_inq_varid(fname, ncid, "local_flag", &varid_flag);
    flag = malloc(nobs_local * sizeof(int));
    ncw_get_var_int(fname, ncid, varid_flag, flag);

    ncw_close(fname, ncid);

    strcpy(buf, fname);
    len = strlen(buf);
    buf[len - 3] = 0;           /* .nc */
    if (!str2int(&buf[len - 5], &day))
        enkf_quit("RADS reader: could not convert file name \"%s\" to date", fname);
    buf[len - 10] = 0;
    if (!str2int(&buf[len - 12], &month))
        enkf_quit("RADS reader: could not convert file name \"%s\" to date", fname);
    buf[len - 14] = 0;
    if (!str2int(&buf[len - 18], &year))
        enkf_quit("RADS 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);

    basename = strrchr(fname, '/');
    if (basename == NULL)
        basename = fname;
    else
        basename += 1;
    strncpy(instname, basename, 2);
    instname[2] = 0;

    mvid = model_getvarid(m, obs->obstypes[obstype_getid(obs->nobstypes, obs->obstypes, meta->type)].varname, 1);
    depth = model_getdepth(m, mvid);

    for (i = 0; i < (int) nobs_local; ++i) {
        observation* o;
        obstype* ot;

        if (flag[i] != 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);
        assert(o->type >= 0);
        ot = &obs->obstypes[o->type];
        o->instrument = st_add_ifabscent(obs->instruments, instname, -1);
        o->id = obs->nobs;
        o->fid = fid;
        o->batch = pass[i];
        o->value = sla[i];
        o->std = error_std;
        o->lon = lon[i];
        o->lat = lat[i];
        o->depth = 0.0;
        o->status = model_xy2fij(m, mvid, o->lon, o->lat, &o->fi, &o->fj);
        if (!obs->allobs && o->status == STATUS_OUTSIDEGRID)
            continue;
        o->fk = 0.0;
        o->date = tunits_offset + 0.5;
        if (o->status == STATUS_OK && depth[(int) floor(o->fj + 0.5)][(int) floor(o->fi + 0.5)] < MINDEPTH)
            o->status = STATUS_SHALLOW;
        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->aux = -1;

        obs->nobs++;
    }

    free(lon);
    free(lat);
    free(pass);
    free(sla);
    free(flag);
}