void ToyTestCase::calcInitCond(BarotropicModel &model) {
    // -------------------------------------------------------------------------
    // collect parameters
    TimeLevelIndex initTimeIdx;
    const Mesh &mesh = model.getMesh();
    const Domain &domain = static_cast<const Domain&>(mesh.getDomain());
    Field &u = model.getZonalWind();
    Field &v = model.getMeridionalWind();
    Field &gd = model.getGeopotentialDepth();
    SingleLevelField &ghs = model.getSurfaceGeopotentialHeight();
    // -------------------------------------------------------------------------
    // set geopotential height peaks if they are not set yet
    if (peaks.size() == 0) {
//#define TOYTESTCASE_RANDOM_PEAKS
#ifdef TOYTESTCASE_RANDOM_PEAKS
        std::mt19937 rng(clock());
        std::uniform_real_distribution<double> distLon(0, geomtk::PI2);
        std::uniform_real_distribution<double> distLat(-M_PI_2, M_PI_2);
        std::uniform_real_distribution<double> distAmptitude(100*G, 500*G);
        std::uniform_real_distribution<double> distRadius(domain.getRadius()/3,
                                                          domain.getRadius()/10);
#endif
        peaks.resize(2);
        for (int i = 0; i < peaks.size(); ++i) {
            peaks[i].x = new SpaceCoord(2);
#ifdef TOYTESTCASE_RANDOM_PEAKS
            double lon = distLon(rng);
            double lat = distLat(rng);
            peaks[i].x->setCoord(lon, lat);
            peaks[i].amptitude = distAmptitude(rng);
            peaks[i].radius = distRadius(rng);
#endif
        }
    }
    // -------------------------------------------------------------------------
    // surface geopotential height and geopotential depth
    assert(gd.getStaggerLocation() == CENTER);
    double gd0 = 8000*G;
    for (int j = 0; j < mesh.getNumGrid(1, FULL); ++j) {
        double cosLat = mesh.getCosLat(FULL, j);
        double sinLat = mesh.getSinLat(FULL, j);
        for (int i = 0; i < mesh.getNumGrid(0, FULL); ++i) {
            double lon = mesh.getGridCoordComp(0, FULL, i);
            gd(initTimeIdx, i, j) = gd0;
            for (int k = 0; k < peaks.size(); ++k) {
                double d = domain.calcDistance(*peaks[k].x, lon, sinLat, cosLat);
                if (d < peaks[k].radius) {
                    gd(initTimeIdx, i, j) += peaks[k].amptitude*(1+cos(M_PI*d/peaks[k].radius))/2;
                }
            }
            ghs(i, j) = 0;
        }
    }
    // -------------------------------------------------------------------------
    gd.applyBndCond(initTimeIdx);
    ghs.applyBndCond();
#define TOYTESTCASE_GEOSTROPHIC_WIND
#ifdef TOYTESTCASE_GEOSTROPHIC_WIND
    // -------------------------------------------------------------------------
    // construct initial wind flow from geostropic relation
    GeostrophicRelation::run(ghs, initTimeIdx, gd, u, v);
#else
    // -------------------------------------------------------------------------
    // set initial wind flow to zero
    // -------------------------------------------------------------------------
    // zonal wind speed
    for (int j = 0; j < mesh.getNumGrid(1, u.getGridType(1)); ++j) {
        for (int i = 0; i < mesh.getNumGrid(0, u.getGridType(0)); ++i) {
            u(initTimeIdx, i, j) = 0;
        }
    }
        // -------------------------------------------------------------------------
        // meridional wind speed
    for (int j = 0; j < mesh.getNumGrid(1, v.getGridType(1)); ++j) {
        for (int i = 0; i < mesh.getNumGrid(0, v.getGridType(0)); ++i) {
            v(initTimeIdx, i, j) = 0;
        }
    }
    u.applyBndCond(initTimeIdx);
    v.applyBndCond(initTimeIdx);
#endif
}
Esempio n. 2
0
void ToyTestCase::calcInitCond(BarotropicModel &model) {
    TimeLevelIndex<2> initTimeIdx;
    const Mesh &mesh = model.mesh();
    const Domain &domain = static_cast<const Domain&>(mesh.domain());
    Field<double, 2> &u = model.zonalWind();
    Field<double, 2> &v = model.meridionalWind();
    Field<double, 2> &gd = model.geopotentialDepth();
    Field<double> &ghs = model.surfaceGeopotential();
    // Set geopotential height peaks if they are not set yet.
    if (peaks.size() == 0) {
//#define TOYTESTCASE_RANDOM_PEAKS
#ifdef TOYTESTCASE_RANDOM_PEAKS
        std::mt19937 rng(clock());
        std::uniform_real_distribution<double> distLon(0, geomtk::PI2);
        std::uniform_real_distribution<double> distLat(-M_PI_2, M_PI_2);
        std::uniform_real_distribution<double> distAmptitude(100*G, 500*G);
        std::uniform_real_distribution<double> distRadius(domain.radius()/3,
                                                          domain.radius()/10);
#endif
        peaks.resize(2);
        for (int i = 0; i < peaks.size(); ++i) {
            peaks[i].x = new SpaceCoord(2);
#ifdef TOYTESTCASE_RANDOM_PEAKS
            double lon = distLon(rng);
            double lat = distLat(rng);
            peaks[i].x->setCoord(lon, lat);
            peaks[i].amptitude = distAmptitude(rng);
            peaks[i].radius = distRadius(rng);
#endif
        }
    }
    // Set surface geopotential height.
    SpaceCoord x(2);
    x.set(180*RAD, 45*RAD);
    double ghs0 = 1500*G;
    double topoRadius = domain.radius()/3;
    for (int j = mesh.js(FULL); j <= mesh.je(FULL); ++j) {
        double cosLat = mesh.cosLat(FULL, j);
        double sinLat = mesh.sinLat(FULL, j);
        for (int i = mesh.is(FULL); i <= mesh.ie(FULL); ++i) {
            double lon = mesh.gridCoordComp(0, FULL, i);
            double d = domain.calcDistance(x, lon, sinLat, cosLat);
            if (d < topoRadius) {
                ghs(i, j) = ghs0*(1+cos(M_PI*d/topoRadius))/2;
            } else {
                ghs(i, j) = 0;
            }
        }
    }
    // Set geopotential depth.
    assert(gd.staggerLocation() == CENTER);
    double gd0 = 8000*G;
    for (int j = mesh.js(FULL); j <= mesh.je(FULL); ++j) {
        double cosLat = mesh.cosLat(FULL, j);
        double sinLat = mesh.sinLat(FULL, j);
        for (int i = mesh.is(FULL); i <= mesh.ie(FULL); ++i) {
            double lon = mesh.gridCoordComp(0, FULL, i);
            gd(initTimeIdx, i, j) = gd0;
            for (int k = 0; k < peaks.size(); ++k) {
                double d = domain.calcDistance(*peaks[k].x, lon, sinLat, cosLat);
                if (d < peaks[k].radius) {
                    gd(initTimeIdx, i, j) += peaks[k].amptitude*(1+cos(M_PI*d/peaks[k].radius))/2;
                }
            }
        }
    }
    gd.applyBndCond(initTimeIdx);
    ghs.applyBndCond();
#define TOYTESTCASE_GEOSTROPHIC_WIND
#ifdef TOYTESTCASE_GEOSTROPHIC_WIND
    // Construct initial wind flow from geostropic relation.
    GeostrophicRelation::run(ghs, initTimeIdx, gd, u, v);
#else
    // Set initial wind flow to zero.
    // Set zonal wind speed.
    for (int j = mesh.js(u.gridType(1)); j <= mesh.je(u.gridType(1)); ++j) {
        for (int i = mesh.is(u.gridType(0)); i <= mesh.ie(u.gridType(0)); ++i) {
            u(initTimeIdx, i, j) = 0;
        }
    }
    // Set meridional wind speed.
    for (int j = mesh.js(v.gridType(1)); j <= mesh.je(v.gridType(1)); ++j) {
        for (int i = mesh.is(v.gridType(0)); i <= mesh.ie(v.gridType(0)); ++i) {
            v(initTimeIdx, i, j) = 0;
        }
    }
    u.applyBndCond(initTimeIdx);
    v.applyBndCond(initTimeIdx);
#endif
}