Esempio n. 1
0
// TODO: Support to only set parcels within limited region.
void ParcelManager::
init(const Mesh &mesh) {
    Field<int> numParcelPerCell;
    numParcelPerCell.create("rp", "1", "parcel refinement", mesh, CENTER, mesh.domain().numDim());
    if (ConfigManager::hasKey("lasm", "parcel_refine_file_path")) {
        auto filePath = ConfigManager::getValue<string>("lasm", "parcel_refine_file_path");
        int ncId, ret, varId;
        int *buffer = new int[mesh.totalNumGrid(CENTER)];
        ret = nc_open(filePath.c_str(), NC_NOWRITE, &ncId);
        CHECK_NC_OPEN(ret, filePath);
        ret = nc_inq_varid(ncId, "rp", &varId);
        CHECK_NC_INQ_VARID(ret, filePath, "rp");
        ret = nc_get_var(ncId, varId, buffer);
        CHECK_NC_GET_VAR(ret, filePath, "rp");
        ret = nc_close(ncId);
        CHECK_NC_CLOSE(ret, filePath);
        for (uword i = 0; i < mesh.totalNumGrid(CENTER); ++i) {
            numParcelPerCell(i) = buffer[i];
        }
        delete [] buffer;
    } else {
        for (uword i = 0; i < mesh.totalNumGrid(CENTER); ++i) {
            numParcelPerCell(i) = 1;
        }
    }
    uvec n(mesh.domain().numDim());
    SpaceCoord x(mesh.domain().numDim());
    vec dx(mesh.domain().numDim());
    this->mesh = &mesh;
    TimeLevelIndex<2> timeIdx;
    int id = 0;
#ifdef LASM_USE_RLL_MESH
    vec areas(mesh.numGrid(1, FULL));
    vec areaWeights(mesh.numGrid(1, FULL));
    for (uword j = mesh.js(FULL); j <= mesh.je(FULL); ++j) {
        int cellIdx = mesh.wrapIndex(CENTER, mesh.is(FULL), j, mesh.ks(FULL));
        areas[j] = mesh.cellVolume(cellIdx);
        areaWeights[j] = exp(-0.1*fabs(mesh.sinLat(FULL, j)));
    }
    double maxArea = areas.max();
    vec size(mesh.domain().numDim());
    for (uword k = mesh.ks(FULL); k <= mesh.ke(FULL); ++k) {
        if (mesh.domain().numDim() == 3) {
            size[2] = mesh.gridInterval(2, HALF, k);
        }
        for (uword j = mesh.js(FULL)+1; j < mesh.je(FULL); ++j) {
            size[1] = mesh.gridInterval(1, HALF, j)*mesh.domain().radius();
            int numReducedLon = mesh.numGrid(0, FULL)/
                std::max(1, static_cast<int>(maxArea*areaWeights[j]/areas[j]));
            double dlon = PI2/numReducedLon;
            for (uword i = 0; i < numReducedLon; ++i) {
                double lon = i*dlon;
                if (mesh.domain().numDim() == 2) {
                    x.set(lon, mesh.lat(FULL, j));
                } else if (mesh.domain().numDim() == 3) {
                    x.set(lon, mesh.lat(FULL, j), mesh.lev(FULL, k));
                }
                x.transformToCart(mesh.domain());
                size[0] = dlon*mesh.domain().radius()*mesh.cosLat(FULL, j);
                Parcel *parcel = new Parcel;
                parcel->init(id++, 0);
                parcel->x(timeIdx) = x;
                parcel->meshIndex(timeIdx).locate(mesh, x);
                parcel->skeletonPoints().init(mesh, size);
                parcel->updateDeformMatrix(timeIdx);
                parcel->tracers().init();
                _parcels.push_back(parcel);
            }
        }
    }
#else
    for (uword i = 0; i < mesh.totalNumGrid(CENTER); ++i) {
        n.fill(pow(numParcelPerCell(i), 1.0/mesh.domain().numDim()));
        const SpaceCoord &x0 = mesh.gridCoord(CENTER, i);
        dx = mesh.cellSize(CENTER, i)/n;
        for (uword j = 0; j < numParcelPerCell(i); ++j) {
            subdivide(n, dx, j, x0, x);
            Parcel *parcel = new Parcel;
            parcel->init(id++, 0);
            parcel->x(timeIdx) = x;
            parcel->meshIndex(timeIdx).locate(mesh, x);
            parcel->skeletonPoints().init(mesh, dx);
            parcel->volume(timeIdx) = mesh.cellVolume(i)/numParcelPerCell(i);
            parcel->updateDeformMatrix(timeIdx);
            parcel->resetSkeletonPoints(timeIdx, mesh);
            parcel->tracers().init();
            _parcels.push_back(parcel);
        }
    }
#endif
} // init