Esempio n. 1
0
File: model.c Progetto: sakov/enkf-c
int model_z2fk(model* m, int vid, double fi, double fj, double z, double* fk)
{
    void* grid = m->grids[m->vars[vid].gridid];
    int isperiodic_x = grid_isperiodic_x(grid);
    int** numlevels = grid_getnumlevels(grid);
    int ni, nj;
    int i1, i2, j1, j2, k2;

    if (isnan(fi + fj)) {
        *fk = NaN;
        return STATUS_OUTSIDEGRID;
    }

    grid_z2fk(grid, fi, fj, z, fk);

    if (isnan(*fk))
        return STATUS_OUTSIDEGRID;

    if (grid_getvtype(grid) == GRIDVTYPE_SIGMA)
         return STATUS_OK;

    /*
     * a depth check for z-grid:
     */
    model_getvardims(m, vid, &ni, &nj, NULL);
    i1 = floor(fi);
    i2 = ceil(fi);
    if (i1 == -1)
        i1 = (isperiodic_x) ? ni - 1 : i2;
    if (i2 == ni)
        i2 = (isperiodic_x) ? 0 : i1;
    j1 = floor(fj);
    j2 = ceil(fj);
    if (j1 == -1)
        j1 = j2;
    if (j2 == nj)
        j2 = j1;
    k2 = floor(*fk);
    if (numlevels[j1][i1] <= k2 && numlevels[j1][i2] <= k2 && numlevels[j2][i1] <= k2 && numlevels[j2][i2] <= k2) {
        *fk = NaN;
        return STATUS_LAND;
    } else if (numlevels[j1][i1] <= k2 || numlevels[j1][i2] <= k2 || numlevels[j2][i1] <= k2 || numlevels[j2][i2] <= k2) {
        float** depth = grid_getdepth(grid);
        int ni, nj;
        double v;

        grid_getdims(grid, &ni, &nj, NULL);

        v = interpolate2d(fi, fj, ni, nj, depth, numlevels, grid_isperiodic_x(grid));

        if (z > v)
            return STATUS_LAND;
    }

    return STATUS_OK;
}
Esempio n. 2
0
File: grid.c Progetto: sakov/enkf-c
static void z2fk(void* p, double fi, double fj, double z, double* fk)
{
    grid* g = (grid*) p;
    gnz_simple* nodes = g->gridnodes_z;

    /*
     * for sigma coordinates convert `z' to sigma
     */
    if (g->vtype == GRIDVTYPE_SIGMA) {
        int ni = 0, nj = 0;
        double depth;

        if (g->htype == GRIDHTYPE_LATLON) {
            gnxy_simple* nodes = (gnxy_simple*) g->gridnodes_xy;

            ni = nodes->nx;
            nj = nodes->ny;
#if !defined(NO_GRIDUTILS)
        } else if (g->htype == GRIDHTYPE_CURVILINEAR) {
            gnxy_curv* nodes = (gnxy_curv*) g->gridnodes_xy;

            ni = gridnodes_getnx(nodes->gn);
            nj = gridnodes_getny(nodes->gn);
#endif
        } else
            enkf_quit("programming error");

        depth = (double) interpolate2d(fi, fj, ni, nj, g->depth, g->numlevels, grid_isperiodic_x(g));
        z /= depth;
    }

    *fk = z2fk_basic(nodes->nz, nodes->zt, nodes->zc, z);
}
Esempio n. 3
0
int model_xy2fij(model* m, int vid, double x, double y, double* fi, double* fj)
{
    void* grid = m->grids[m->vars[vid].gridid];
    int** numlevels = grid_getnumlevels(grid);
    int lontype = grid_getlontype(grid);
    int ni, nj;
    int i1, i2, j1, j2;

    if (lontype == LONTYPE_180) {
        if (x > 180.0)
            x -= 360.0;
    } else if (lontype == LONTYPE_360) {
        if (x < 0.0)
            x += 360.0;
    }

    grid_xy2fij(grid, x, y, fi, fj);

    if (isnan(*fi + *fj))
        return STATUS_OUTSIDEGRID;

    /*
     * Note that this section should be consistent with similar sections in
     * interpolate2d() and interpolate3d().
     */
    i1 = floor(*fi);
    i2 = ceil(*fi);
    j1 = floor(*fj);
    j2 = ceil(*fj);

    model_getvardims(m, vid, &ni, &nj, NULL);
    if (i1 == -1)
        i1 = (grid_isperiodic_x(model_getvargrid(m, vid))) ? ni - 1 : i2;
    if (i2 == ni)
        i2 = (grid_isperiodic_x(model_getvargrid(m, vid))) ? 0 : i1;
    if (j1 == -1)
        j1 = (grid_isperiodic_y(model_getvargrid(m, vid))) ? nj - 1 : j2;
    if (i2 == nj)
        j2 = (grid_isperiodic_y(model_getvargrid(m, vid))) ? 0 : j1;

    if (numlevels[j1][i1] == 0 && numlevels[j1][i2] == 0 && numlevels[j2][i1] == 0 && numlevels[j2][i2] == 0) {
        *fi = NaN;
        *fj = NaN;
        return STATUS_LAND;
    }
    return STATUS_OK;
}
Esempio n. 4
0
File: grid.c Progetto: 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);
}
Esempio n. 5
0
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);
    }
}
Esempio n. 6
0
/** 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() */
Esempio n. 7
0
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() */