// 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