diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..754bd48 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "cmake", + "label": "CMake: build", + "command": "build", + "targets": [ + "all" + ], + "preset": "${command:cmake.activeBuildPresetName}", + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [], + "detail": "CMake template build task" + } + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 77d0f84..55a3093 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,21 +14,23 @@ include(GNUInstallDirs) set(CMAKE_EXPORT_COMPILE_COMMANDS 1) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_OSX_DEPLOYMENT_TARGET 11.3) +set(CMAKE_OSX_DEPLOYMENT_TARGET 14.0) option(INFRA_INSOURCE "Use submodule version of infra" ON) option(GDX_INSOURCE "Use submodule version of geodynamix" ON) set(PACKAGE_VERSION_COMMITHASH "dev" CACHE STRING "git commit hash") -if (PACKAGE_VERSION_COMMITHASH STREQUAL "dev") + +if(PACKAGE_VERSION_COMMITHASH STREQUAL "dev") set(EMAP_DEV_BUILD 1) -else () +else() set(EMAP_DEV_BUILD 0) - if (CMAKE_COMPILER_IS_GNUCXX) + + if(CMAKE_COMPILER_IS_GNUCXX) add_link_options($<$:-s>) # strip dist binaries - endif () -endif () + endif() +endif() -if (WIN32) +if(WIN32) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") set(CMAKE_VS_JUST_MY_CODE_DEBUGGING ON) @@ -54,24 +56,24 @@ if (WIN32) $<$:/await> ) - if (MSVC) + if(MSVC) # Fixes warning when linking against release c library in debug mode # Fixes warning when linking against release c library in debug mode add_link_options("$<$:/NODEFAULTLIB:MSVCRT;/NODEFAULTLIB:LIBCMT>") - endif () -else () + endif() +else() add_compile_options( -Wall -Wextra -Wpedantic -Wfatal-errors -Wno-unknown-pragmas $<$:-Wno-maybe-uninitialized> $<$:-fdiagnostics-color=always> $<$:-fcolor-diagnostics> ) -endif () +endif() -set (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) -set (EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) +set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) -if (INFRA_INSOURCE) +if(INFRA_INSOURCE) set(INFRA_LOGGING ON) set(INFRA_GDAL ON) set(INFRA_PROJDB_DIR "data") @@ -84,34 +86,37 @@ if (INFRA_INSOURCE) set(INFRA_TESTUTIL_MAIN_PROJDB_PATH ${INFRA_PROJDB_DIR}) add_subdirectory(deps/infra) -else () +else() find_package(Infra CONFIG COMPONENTS testutil REQUIRED) set_target_properties(fmt::fmt PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release) set_target_properties(spdlog::spdlog PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release) set_target_properties(Infra::infra PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release) -endif () +endif() -if (GDX_INSOURCE) +if(GDX_INSOURCE) set(GDX_PYTHON_BINDINGS OFF) set(GDX_ENABLE_TESTS OFF) set(GDX_ENABLE_TEST_UTILS ${BUILD_TESTING}) set(GDX_ENABLE_TOOLS OFF) set(GDX_ENABLE_SIMD ON) - IF(NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm" AND NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm64") + + IF(NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm" AND NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm64") set(GDX_AVX2 ON) - endif () + endif() + add_subdirectory(deps/geodynamix) -else () +else() find_package(Geodynamix CONFIG REQUIRED) -endif () +endif() add_subdirectory(logic) add_subdirectory(cli) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_BINARY_DIR}/emapconfig.h) -if (WIN32) + +if(WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) -endif () +endif() install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.md diff --git a/CMakePresets.json b/CMakePresets.json index b56624b..6308265 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -27,11 +27,21 @@ "inherits": "vcpkg-base", "hidden": true, "cacheVariables": { - "VCPKG_OSX_DEPLOYMENT_TARGET": "11.3", + "VCPKG_OSX_DEPLOYMENT_TARGET": "14.0", "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/deps/vcpkg/triplets/toolchain-osx-appleclang.cmake", "VCPKG_CXX_FLAGS": "-fvisibility=hidden -fvisibility-inlines-hidden" } }, + { + "name": "osx-homebrew-base", + "inherits": "vcpkg-base", + "hidden": true, + "cacheVariables": { + "VCPKG_OSX_DEPLOYMENT_TARGET": "14.0", + "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/deps/vcpkg/triplets/toolchain-osx-homebrew.cmake", + "VCPKG_CXX_FLAGS": "-fvisibility=hidden -fvisibility-inlines-hidden" + } + }, { "name": "windows-base", "inherits": "vcpkg-base", @@ -69,14 +79,14 @@ }, { "name": "arm64-osx", - "inherits": "osx-base", + "inherits": "osx-homebrew-base", "displayName": "OSX arm64", "description": "Vcpkg build for arm64 on mac", "cacheVariables": { - "VCPKG_TARGET_TRIPLET": "arm64-osx", + "VCPKG_TARGET_TRIPLET": "arm64-osx-homebrew", "CMAKE_OSX_ARCHITECTURES": "arm64", "CMAKE_BUILD_TYPE": "Release", - "VCPKG_INSTALLED_DIR": "${sourceDir}/vcpkgs-arm64-osx", + "VCPKG_INSTALLED_DIR": "${sourceDir}/vcpkgs-arm64-osx-homebrew", "VCPKG_ALLOW_SYSTEM_LIBS": "ON" } }, diff --git a/README.md b/README.md index f20a4fa..1bbf746 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ This section configures the model run - `included_pollutants` List of pollutants to include in the model run, this setting is optional, if it is not present all the configured pollutants will be included in the run. - `scenario` First search for emission input files with the `_scenario` suffix before using the default emission input files, allows easy creation of scenarios with modified input files. For point sources `emap_{scenario}_{pollutant}_{year}_*.csv` is checked before `emap_{pollutant}_{year}_*.csv` - `point_source_rescale_threshold` The threshold for allowing automatic rescaling of point sources when they exceed the reported total emissions [0 - 100] +- `combine_identical_point_sources` combine the emission of the point sources with the same location and properties. The emissions will be summed and only one entry will be present in the output file. (default=true) ### Output section This section configures the output of the model diff --git a/cli/main.cpp b/cli/main.cpp index 8165258..f6611cb 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -22,7 +22,7 @@ #include #endif -using inf::Log; +using namespace inf; static inf::Log::Level log_level_from_value(int32_t value) { @@ -75,7 +75,7 @@ int main(int argc, char** argv) lyra::opt(options.debugGrids)["-d"]["--debug"]("Dumps internal grid usages") | lyra::opt(options.config, "path")["-c"]["--config"]("The e-map run configuration").required(); - if (argc == 2 && fs::is_regular_file(fs::u8path(argv[1]))) { + if (argc == 2 && fs::is_regular_file(file::u8path(argv[1]))) { // simplified cli invocation, assume argument is config file options.config = argv[1]; } else { @@ -91,7 +91,7 @@ int main(int argc, char** argv) try { inf::gdal::RegistrationConfig gdalCfg; - gdalCfg.projdbPath = fs::u8path(argv[0]).parent_path() / "data"; + gdalCfg.projdbPath = file::u8path(argv[0]).parent_path() / "data"; inf::gdal::Registration reg(gdalCfg); inf::gdal::set_log_handler(inf::Log::Level::Debug); @@ -105,10 +105,10 @@ int main(int argc, char** argv) } if (options.debugGrids) { - return emap::debug_grids(fs::u8path(options.config), log_level_from_value(options.logLevel)); + return emap::debug_grids(file::u8path(options.config), log_level_from_value(options.logLevel)); } else { return emap::run_model( - fs::u8path(options.config), log_level_from_value(options.logLevel), options.concurrency, [&](const emap::ModelProgress::Status& info) { + file::u8path(options.config), log_level_from_value(options.logLevel), options.concurrency, [&](const emap::ModelProgress::Status& info) { if (progressBar) { progressBar->set_progress(info.progress()); progressBar->set_postfix_text(info.payload().to_string()); diff --git a/deps/geodynamix b/deps/geodynamix index 7917105..0ab6194 160000 --- a/deps/geodynamix +++ b/deps/geodynamix @@ -1 +1 @@ -Subproject commit 791710592aa33ccd441a0adf5522d8e1bf81bfcd +Subproject commit 0ab61942c9f0787541d24f7b165f6cf37eb74b85 diff --git a/deps/infra b/deps/infra index c64dff0..91b29a2 160000 --- a/deps/infra +++ b/deps/infra @@ -1 +1 @@ -Subproject commit c64dff02db93eee2f0fb0c4b95cc5719af9ce3a2 +Subproject commit 91b29a296cc23357824358f4cf9174bfc8b2cb0b diff --git a/logic/configurationparser.cpp b/logic/configurationparser.cpp index 2f88dfa..d0ad5e8 100644 --- a/logic/configurationparser.cpp +++ b/logic/configurationparser.cpp @@ -613,6 +613,7 @@ static RunConfiguration parse_run_configuration_impl(std::string_view configCont const auto grid = read_grid(model.section["grid"].value()); const auto scenario = read_string(model, "scenario", ""); + const auto combinePointSources = model.section["combine_identical_point_sources"].value().value_or(true); const double rescaleThreshold = model.section["point_source_rescale_threshold"].value().value_or(100.0); const auto year = read_year(model.section["year"]); const auto reportYear = read_year(model.section["report_year"]); @@ -644,6 +645,7 @@ static RunConfiguration parse_run_configuration_impl(std::string_view configCont year, reportYear, scenario, + combinePointSources, rescaleThreshold, std::move(includedPollutants), std::move(sectorInventory), diff --git a/logic/emissionscollector.cpp b/logic/emissionscollector.cpp index ddf66e5..7587547 100644 --- a/logic/emissionscollector.cpp +++ b/logic/emissionscollector.cpp @@ -77,7 +77,9 @@ void EmissionsCollector::add_emissions(const CountryCellCoverage& countryInfo, c } for (auto& entry : pointEmissions) { - _outputBuilder->add_point_output_entry(entry); + if (entry.value().amount() > 0.0) { + _outputBuilder->add_point_output_entry(entry); + } } if (diffuseEmissions.empty() && !pointEmissions.empty()) { diff --git a/logic/include/emap/emissioninventory.h b/logic/include/emap/emissioninventory.h index 859e8d6..690a13b 100644 --- a/logic/include/emap/emissioninventory.h +++ b/logic/include/emap/emissioninventory.h @@ -56,7 +56,7 @@ class EmissionInventoryEntry { std::vector result; result.reserve(_pointEmissionEntries.size()); - std::transform(_pointEmissionEntries.begin(), _pointEmissionEntries.end(), std::back_inserter(result), [=](const EmissionEntry& entry) { + std::transform(_pointEmissionEntries.begin(), _pointEmissionEntries.end(), std::back_inserter(result), [this](const EmissionEntry& entry) { auto scaledEntry = entry; scaledEntry.set_value(entry.value() * _pointAutoScaling * _pointUserScaling); return scaledEntry; diff --git a/logic/include/emap/runconfiguration.h b/logic/include/emap/runconfiguration.h index 6dad60c..766437a 100644 --- a/logic/include/emap/runconfiguration.h +++ b/logic/include/emap/runconfiguration.h @@ -54,6 +54,7 @@ class RunConfiguration date::year year, date::year reportYear, std::string_view scenario, + bool combineIdenticalPointSources, double rescaleThreshold, std::vector includedPollutants, SectorInventory sectors, @@ -95,6 +96,9 @@ class RunConfiguration std::string_view scenario() const noexcept; + bool combine_identical_point_sources() const noexcept; + void set_combine_identical_point_sources(bool enabled) noexcept; + double point_source_rescale_threshold() const noexcept; void set_max_concurrency(std::optional concurrency) noexcept; @@ -128,6 +132,7 @@ class RunConfiguration date::year _year; date::year _reportYear; std::string _scenario; + bool _combineIdenticalPointSources; double _pointRescaleThreshold; std::vector _includedPollutants; SectorInventory _sectorInventory; diff --git a/logic/include/emap/sector.h b/logic/include/emap/sector.h index 62e505e..fb165b1 100644 --- a/logic/include/emap/sector.h +++ b/logic/include/emap/sector.h @@ -249,4 +249,19 @@ struct hash : type_safe::hashable { }; +template <> +struct hash +{ + std::size_t operator()(const emap::EmissionSector& sector) const + { + std::size_t seed = 0; + if (sector.type() == emap::EmissionSector::Type::Nfr) { + seed = std::hash{}(sector.nfr_sector().id()); + } else { + seed = std::hash{}(sector.gnfr_sector().id()); + } + + return seed; + } +}; } diff --git a/logic/inputparsers.cpp b/logic/inputparsers.cpp index 9fad7d5..5aaccee 100644 --- a/logic/inputparsers.cpp +++ b/logic/inputparsers.cpp @@ -6,6 +6,7 @@ #include "emap/runconfiguration.h" #include "emap/scalingfactors.h" #include "emap/sector.h" +#include "infra/chrono.h" #include "infra/csvreader.h" #include "infra/enumutils.h" #include "infra/exception.h" @@ -114,16 +115,102 @@ Range parse_year_range(std::string_view yearRange) throw RuntimeError("Invalid year range specification: {}", yearRange); } +struct PointSourceIdentifier +{ + std::string type; + std::string scenario; + chrono::year year; + Country country; + EmissionSector sector; + Pollutant pollutant; + std::string eilNumber; + std::string eilPoint; + std::string subType; + std::optional coordinate; + std::optional dv; + double height = 0.0; + double diameter = 0.0; + double temperature = 0.0; + double warmthContents = 0.0; + double flowRate = 0.0; + +#ifdef HAVE_CPP20_CHRONO + auto operator<=>(const emap::PointSourceIdentifier& other) const = default; +#else + bool operator==(const emap::PointSourceIdentifier& other) const = default; +#endif + + std::string source_id() const + { + return fmt::format("{}_{}_{}_{}_{}_{}_{}_{}", height, diameter, temperature, warmthContents, flowRate, eilPoint, eilNumber, subType); + } + + EmissionEntry to_emission_entry(double emissionValue) const + { + EmissionEntry entry( + EmissionIdentifier(country, sector, pollutant), + EmissionValue(emissionValue)); + + entry.set_height(height); + entry.set_diameter(diameter); + entry.set_temperature(temperature); + entry.set_warmth_contents(warmthContents); + entry.set_flow_rate(flowRate); + + entry.set_source_id(source_id()); + entry.set_dv(dv); + if (coordinate.has_value()) { + entry.set_coordinate(*coordinate); + } + return entry; + } +}; +} + +namespace std { +template <> +struct hash +{ + std::size_t operator()(const emap::PointSourceIdentifier& ps) const + { + std::size_t seed = 0; + inf::hash_combine(seed, + ps.type, + ps.scenario, + ps.year, + ps.country, + ps.sector, + ps.pollutant, + ps.eilNumber, + ps.eilPoint, + ps.subType, + ps.coordinate, + ps.dv, + ps.height, + ps.diameter, + ps.temperature, + ps.warmthContents, + ps.flowRate); + return seed; + } +}; +} + +namespace emap { + SingleEmissions parse_point_sources(const fs::path& emissionsCsv, const RunConfiguration& cfg) { // pointsource csv columns: type;scenario;year;reporting_country;nfr-sector;pollutant;emission;unit;x;y;hoogte_m;diameter_m;temperatuur_C;warmteinhoud_MW;Debiet_Nm3/u;Type emissie omschrijving;EIL-nummer;Exploitatie naam;NACE-code;EIL Emissiepunt Jaar Naam;Activiteit type;subtype - const auto& countryInv = cfg.countries(); - const auto& sectorInv = cfg.sectors(); - const auto& pollutantInv = cfg.pollutants(); + const auto& countryInv = cfg.countries(); + const auto& sectorInv = cfg.sectors(); + const auto& pollutantInv = cfg.pollutants(); + const bool combineIdentical = cfg.combine_identical_point_sources(); size_t lineNr = 2; + std::unordered_map pointSourceEmissions; + try { Log::debug("Parse emissions: {}", emissionsCsv); @@ -210,11 +297,8 @@ SingleEmissions parse_point_sources(const fs::path& emissionsCsv, const RunConfi const auto pollutantName = line.get_string(colPollutant); const auto country = countryInv.try_country_from_string(line.get_string(colCountry)); - if (!country.has_value()) { - continue; - } - - if (sectorName.empty() || sectorInv.is_ignored_sector(sectorType, sectorName, *country) || + if (sectorName.empty() || + sectorInv.is_ignored_sector(sectorType, sectorName, *country) || pollutantInv.is_ignored_pollutant(pollutantName, *country)) { continue; } @@ -223,39 +307,40 @@ SingleEmissions parse_point_sources(const fs::path& emissionsCsv, const RunConfi auto sector = sectorInv.try_sector_from_string(sectorType, sectorName); auto pollutant = pollutantInv.try_pollutant_from_string(pollutantName); - if (sector.has_value() && pollutant.has_value()) { - EmissionEntry info( - EmissionIdentifier(*country, *sector, *pollutant), - EmissionValue(emissionValue)); - info.set_height(line.get_double(colHeight).value_or(0.0)); - info.set_diameter(line.get_double(colDiameter).value_or(0.0)); - info.set_temperature(line.get_double(colTemperature).value_or(-9999.0)); - info.set_warmth_contents(line.get_double(colWarmthContents).value_or(0.0)); - info.set_flow_rate(line.get_double(colFlowRate).value_or(0.0)); - - std::string subType = "none"; - if (colSubType.has_value()) { - subType = line.get_string(*colSubType); - } - - info.set_source_id(fmt::format("{}_{}_{}_{}_{}_{}_{}_{}", info.height(), info.diameter(), info.temperature(), info.warmth_contents(), info.flow_rate(), line.get_string(colEilPoint), line.get_string(colEil), subType)); + if (sector.has_value() && pollutant.has_value()) { + PointSourceIdentifier ps; + ps.sector = *sector; + ps.country = *country; + ps.pollutant = *pollutant; + ps.height = line.get_double(colHeight).value_or(0.0); + ps.diameter = line.get_double(colDiameter).value_or(0.0); + ps.temperature = line.get_double(colTemperature).value_or(0.0); + ps.warmthContents = line.get_double(colWarmthContents).value_or(0.0); + ps.flowRate = line.get_double(colFlowRate).value_or(0.0); + ps.subType = colSubType.has_value() ? line.get_string(*colSubType) : "none"; + ps.eilNumber = line.get_string(colEil); + ps.eilPoint = line.get_string(colEilPoint); if (colX.has_value() && colY.has_value()) { auto x = line.get_double(*colX); auto y = line.get_double(*colY); if (x.has_value() && y.has_value()) { - info.set_coordinate(Coordinate(*x, *y)); + ps.coordinate = Coordinate(*x, *y); } else { throw RuntimeError("Invalid coordinate in point sources: {}", line.get_string(*colX), line.get_string(*colY)); } } if (colDv.has_value()) { - info.set_dv(line.get_int32(*colDv)); + ps.dv = line.get_int32(*colDv); } - result.add_emission(std::move(info)); + if (combineIdentical) { + pointSourceEmissions[ps] += emissionValue; + } else { + result.add_emission(ps.to_emission_entry(emissionValue)); + } } else { if (!pollutant.has_value()) { Log::warn("Unknown pollutant name: {}", pollutantName); @@ -269,6 +354,12 @@ SingleEmissions parse_point_sources(const fs::path& emissionsCsv, const RunConfi ++lineNr; } + if (combineIdentical) { + for (const auto& [ps, emission] : pointSourceEmissions) { + result.add_emission(ps.to_emission_entry(emission)); + } + } + return result; } catch (const std::exception& e) { throw RuntimeError("Error parsing {} line {} ({})", emissionsCsv, lineNr, e.what()); diff --git a/logic/runconfiguration.cpp b/logic/runconfiguration.cpp index 4686c31..3af9d91 100644 --- a/logic/runconfiguration.cpp +++ b/logic/runconfiguration.cpp @@ -18,6 +18,7 @@ RunConfiguration::RunConfiguration( date::year year, date::year reportYear, std::string_view scenario, + bool combineIdenticalPointSources, double rescaleThreshold, std::vector includedPollutants, SectorInventory sectors, @@ -32,6 +33,7 @@ RunConfiguration::RunConfiguration( , _year(year) , _reportYear(reportYear) , _scenario(scenario) +, _combineIdenticalPointSources(combineIdenticalPointSources) , _pointRescaleThreshold(rescaleThreshold) , _includedPollutants(std::move(includedPollutants)) , _sectorInventory(std::move(sectors)) @@ -186,6 +188,16 @@ std::string_view RunConfiguration::scenario() const noexcept return _scenario; } +bool RunConfiguration::combine_identical_point_sources() const noexcept +{ + return _combineIdenticalPointSources; +} + +void RunConfiguration::set_combine_identical_point_sources(bool enabled) noexcept +{ + _combineIdenticalPointSources = enabled; +} + double RunConfiguration::point_source_rescale_threshold() const noexcept { return _pointRescaleThreshold; diff --git a/logic/test/emissioninventorytest.cpp b/logic/test/emissioninventorytest.cpp index 374b7e1..6cf89db 100644 --- a/logic/test/emissioninventorytest.cpp +++ b/logic/test/emissioninventorytest.cpp @@ -22,7 +22,7 @@ static RunConfiguration create_config(const SectorInventory& sectorInv, const Po outputConfig.path = "./out"; outputConfig.outputLevelName = "GNFR"; - return RunConfiguration("./data", {}, {}, ModelGrid::ChimereCams, ValidationType::NoValidation, 2016_y, 2021_y, "test", 90.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); + return RunConfiguration("./data", {}, {}, ModelGrid::ChimereCams, ValidationType::NoValidation, 2016_y, 2021_y, "test", true, 90.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); } static void create_empty_point_source_file(const fs::path& path) diff --git a/logic/test/gridprocessingtest.cpp b/logic/test/gridprocessingtest.cpp index 4fbae76..d27a112 100644 --- a/logic/test/gridprocessingtest.cpp +++ b/logic/test/gridprocessingtest.cpp @@ -46,7 +46,7 @@ TEST_CASE("create_geometry_extent") TEST_CASE("create_country_coverages") { auto outputGrid = grid_data(GridDefinition::Vlops60km).meta; - auto countriesPath = fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; + auto countriesPath = file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; CPLSetThreadLocalConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", "YES"); auto vectorDs = gdal::warp_vector(countriesPath, grid_data(GridDefinition::Vlops60km).meta); @@ -66,7 +66,7 @@ TEST_CASE("create_country_coverages") TEST_CASE("create_country_coverages flanders chimere") { auto outputGrid = grid_data(GridDefinition::Chimere01deg).meta; - auto countriesPath = fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; + auto countriesPath = file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; CPLSetThreadLocalConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", "YES"); auto vectorDs = gdal::warp_vector(countriesPath, grid_data(GridDefinition::Chimere01deg).meta); @@ -79,7 +79,7 @@ TEST_CASE("create_country_coverages flanders chimere") CHECK(bef.outputSubgridExtent.rows == 9); - auto spatialPatternRaster = gdx::resample_raster(gdx::read_dense_raster(fs::u8path(TEST_DATA_DIR) / "spatialpattern.tif"), bef.outputSubgridExtent, gdal::ResampleAlgorithm::Average); + auto spatialPatternRaster = gdx::resample_raster(gdx::read_dense_raster(file::u8path(TEST_DATA_DIR) / "spatialpattern.tif"), bef.outputSubgridExtent, gdal::ResampleAlgorithm::Average); CHECK(spatialPatternRaster.metadata().rows == 9); const auto intersection = metadata_intersection(bef.outputSubgridExtent, outputGrid); @@ -89,7 +89,7 @@ TEST_CASE("create_country_coverages flanders chimere") TEST_CASE("create_country_coverages edge country") { auto outputGrid = grid_data(GridDefinition::Chimere01deg).meta; - auto countriesPath = fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; + auto countriesPath = file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; CPLSetThreadLocalConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", "YES"); auto vectorDs = gdal::warp_vector(countriesPath, grid_data(GridDefinition::Chimere01deg).meta); @@ -108,7 +108,7 @@ TEST_CASE("create_country_coverages edge country") TEST_CASE("Normalize raster") { auto outputGrid = grid_data(GridDefinition::Vlops60km).meta; - auto countriesPath = fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; + auto countriesPath = file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; CPLSetThreadLocalConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", "YES"); auto vectorDs = gdal::warp_vector(countriesPath, grid_data(GridDefinition::Vlops60km).meta); @@ -119,7 +119,7 @@ TEST_CASE("Normalize raster") CHECK(coverageInfo.size() == 1); auto& nl = coverageInfo.front(); - auto grid = transform_grid(gdx::read_dense_raster(fs::u8path(TEST_DATA_DIR) / "spatialpattern.tif"), GridDefinition::Vlops60km); + auto grid = transform_grid(gdx::read_dense_raster(file::u8path(TEST_DATA_DIR) / "spatialpattern.tif"), GridDefinition::Vlops60km); auto nlRaster = extract_country_from_raster(sub_raster(grid, nl.outputSubgridExtent), nl); normalize_raster(nlRaster); @@ -131,7 +131,7 @@ TEST_CASE("Resample nodata check") auto gridDef = GridDefinition::Chimere005degLarge; auto outputGrid = grid_data(gridDef).meta; - auto countriesPath = fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; + auto countriesPath = file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; CPLSetThreadLocalConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", "YES"); auto vectorDs = gdal::warp_vector(countriesPath, grid_data(gridDef).meta); @@ -142,7 +142,7 @@ TEST_CASE("Resample nodata check") CHECK(coverageInfo.size() == 1); auto& bef = coverageInfo.front(); - auto inputPath = fs::u8path(TEST_DATA_DIR) / "1A3BI_NOX_2019.tif"; + auto inputPath = file::u8path(TEST_DATA_DIR) / "1A3BI_NOX_2019.tif"; auto result = gdx::resample_raster(gdx::read_dense_raster(inputPath), bef.outputSubgridExtent, gdal::ResampleAlgorithm::Average); size_t nodataCount = 0; @@ -172,7 +172,7 @@ TEST_CASE("Add to raster") Log::info("Check grid: {}", grid_data(gridDef).name); auto outputGrid = grid_data(gridDef).meta; - auto countriesPath = fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; + auto countriesPath = file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg"; CPLSetThreadLocalConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", "YES"); auto vectorDs = gdal::warp_vector(countriesPath, grid_data(gridDef).meta); @@ -199,7 +199,7 @@ TEST_CASE("Add to raster") // TEST_CASE("res") //{ -// auto spatialPattern = gdx::read_dense_raster(fs::u8path(TEST_DATA_DIR) / "spatialpattern.tif"); +// auto spatialPattern = gdx::read_dense_raster(file::u8path(TEST_DATA_DIR) / "spatialpattern.tif"); // auto resultCalc = transform_grid(spatialPattern, GridDefinition::VlopsCalc, gdal::ResampleAlgorithm::Average); // // auto result60Km = transform_grid(resultCalc, GridDefinition::Vlops60km, gdal::ResampleAlgorithm::Average); @@ -224,13 +224,13 @@ TEST_CASE("Add to raster") //{ // TempDir tmp("grid_country_extraction"); // -// const auto inputPath = fs::u8path(TEST_DATA_DIR) / "input" / "spatial_patterns" / "pm10_F_RoadTransport.tif"; -// const auto countriesPath = fs::u8path(EMAP_DATA_DIR) / "boundaries.gpkg"; +// const auto inputPath = file::u8path(TEST_DATA_DIR) / "input" / "spatial_patterns" / "pm10_F_RoadTransport.tif"; +// const auto countriesPath = file::u8path(EMAP_DATA_DIR) / "boundaries.gpkg"; // const auto outputPath = tmp.path(); // // /*SUBCASE("transform grid") // { -// const auto inputPath = fs::u8path("C:/Users/vdboerd/OneDrive - VITO/Documents/E-map/E-MAP/input/spatial patterns/co_A_PublicPower.tif"); +// const auto inputPath = file::u8path("C:/Users/vdboerd/OneDrive - VITO/Documents/E-map/E-MAP/input/spatial patterns/co_A_PublicPower.tif"); // const auto inputRaster = gdx::read_dense_raster(inputPath); // auto result = transform_grid(inputRaster, GridDefinition::Vlops1km); // gdx::write_raster(result, "c:/temp/trans.tif"); diff --git a/logic/test/inputparsertest.cpp b/logic/test/inputparsertest.cpp index fbf0d05..82ebf67 100644 --- a/logic/test/inputparsertest.cpp +++ b/logic/test/inputparsertest.cpp @@ -25,7 +25,7 @@ static RunConfiguration create_config(const SectorInventory& sectorInv, const Po outputConfig.path = "./out"; outputConfig.outputLevelName = "GNFR"; - return RunConfiguration("./data", {}, {}, ModelGrid::Invalid, ValidationType::NoValidation, 2016_y, 2021_y, "", 100.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); + return RunConfiguration("./data", {}, {}, ModelGrid::Invalid, ValidationType::NoValidation, 2016_y, 2021_y, "", true, 100.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); } TEST_CASE("Input parsers") @@ -176,6 +176,8 @@ TEST_CASE("Input parsers") SUBCASE("Load point source emissions") { + cfg.set_combine_identical_point_sources(false); + SUBCASE("nfr sectors") { const auto emissions = parse_point_sources(file::u8path(TEST_DATA_DIR) / "_input" / "01_data_emissions" / "inventory" / "reporting_2021" / "pointsources" / "pointsource_emissions_2021.csv", cfg); diff --git a/logic/test/outputbuilderstest.cpp b/logic/test/outputbuilderstest.cpp index 8077459..859b7bf 100644 --- a/logic/test/outputbuilderstest.cpp +++ b/logic/test/outputbuilderstest.cpp @@ -20,7 +20,7 @@ static RunConfiguration create_config(const SectorInventory& sectorInv, const Po outputConfig.outputLevelName = "NFR"; outputConfig.separatePointSources = poinSourcesSeparate; - return RunConfiguration(file::u8path(TEST_DATA_DIR) / "_input", {}, {}, grid, ValidationType::NoValidation, 2016_y, 2021_y, "", 100.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); + return RunConfiguration(file::u8path(TEST_DATA_DIR) / "_input", {}, {}, grid, ValidationType::NoValidation, 2016_y, 2021_y, "", true, 100.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); } TEST_CASE("Output builders") diff --git a/logic/test/runconfigurationparsertest.cpp b/logic/test/runconfigurationparsertest.cpp index cecd5f3..b6a8d37 100644 --- a/logic/test/runconfigurationparsertest.cpp +++ b/logic/test/runconfigurationparsertest.cpp @@ -31,6 +31,7 @@ TEST_CASE("Parse run configuration") report_year = 2018 scenario = "scenarionaam" scalefactors = "{}" + combine_identical_point_sources = true [output] path = "/temp" @@ -46,7 +47,8 @@ TEST_CASE("Parse run configuration") CHECK(config.data_root() == expectedDataRoot); CHECK(config.year() == 2020_y); CHECK(config.reporting_year() == 2018_y); - // CHECK(config.scenario() == "scenarionaam"); + CHECK(config.scenario() == "scenarionaam"); + CHECK(config.combine_identical_point_sources() == true); CHECK(config.spatial_pattern_path() == expectedDataRoot / "03_spatial_disaggregation"); CHECK(config.output_path() == expectedOutput); @@ -70,6 +72,7 @@ TEST_CASE("Parse run configuration") scenario = "scenarionaam" scalefactors = "{}" included_pollutants = ["CO", "NOx", "NMVOC"] + combine_identical_point_sources = false [output] path = "/temp" @@ -86,6 +89,7 @@ TEST_CASE("Parse run configuration") CHECK(config.year() == 2020_y); CHECK(config.reporting_year() == 2018_y); CHECK(config.scenario() == "scenarionaam"); + CHECK(config.combine_identical_point_sources() == false); CHECK(config.spatial_pattern_path() == expectedDataRoot / "03_spatial_disaggregation"); CHECK(config.output_path() == expectedOutput); @@ -117,6 +121,7 @@ TEST_CASE("Parse run configuration") const auto config = parse_run_configuration(fmt::format(tomlConfig, str::from_u8(scaleFactors.generic_u8string())), file::u8path(TEST_DATA_DIR)); CHECK(config.scenario() == "scen"); + CHECK(config.combine_identical_point_sources() == true); // Scenario specific input available CHECK(config.total_emissions_path_nfr_belgium(country::BEB) == expectedDataRoot / "01_data_emissions" / "inventory" / "reporting_2021" / "totals" / "BEB_2021_scen.xlsx"); CHECK(config.total_emissions_path_gnfr(config.reporting_year()) == expectedDataRoot / "01_data_emissions" / "inventory" / "reporting_2021" / "totals" / "gnfr_allyears_2021_scen.txt"); diff --git a/logic/test/spatialpatterninventorytest.cpp b/logic/test/spatialpatterninventorytest.cpp index b1f3528..c322989 100644 --- a/logic/test/spatialpatterninventorytest.cpp +++ b/logic/test/spatialpatterninventorytest.cpp @@ -20,12 +20,12 @@ static RunConfiguration create_config(const SectorInventory& sectorInv, const Po outputConfig.path = "./out"; outputConfig.outputLevelName = "NFR"; - return RunConfiguration(fs::u8path(TEST_DATA_DIR) / "_input", exceptionsPath, fs::path(), ModelGrid::Vlops1km, ValidationType::NoValidation, 2016_y, 2021_y, "", 100.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); + return RunConfiguration(file::u8path(TEST_DATA_DIR) / "_input", exceptionsPath, fs::path(), ModelGrid::Vlops1km, ValidationType::NoValidation, 2016_y, 2021_y, "", true, 100.0, {}, sectorInv, pollutantInv, countryInv, outputConfig); } TEST_CASE("Spatial pattern selection test") { - const auto parametersPath = fs::u8path(TEST_DATA_DIR) / "_input" / "05_model_parameters"; + const auto parametersPath = file::u8path(TEST_DATA_DIR) / "_input" / "05_model_parameters"; CountryInventory countryInventory(std::vector({countries::NL, countries::BEF})); const auto sectorInventory = parse_sectors(parametersPath / "id_nummers.xlsx", parametersPath / "code_conversions.xlsx", @@ -39,18 +39,18 @@ TEST_CASE("Spatial pattern selection test") pollutantInventory.add_fallback_for_pollutant(pollutantInventory.pollutant_from_string("PMcoarse"), pollutantInventory.pollutant_from_string("PM10")); - auto exceptionsPath = fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "exceptions_spatial_disaggregation.xlsx"; + auto exceptionsPath = file::u8path(TEST_DATA_DIR) / "spatialinventory" / "exceptions_spatial_disaggregation.xlsx"; auto cfg = create_config(sectorInventory, pollutantInventory, countryInventory, exceptionsPath); auto grid60km = grid_data(GridDefinition::Vlops60km); auto grid1km = grid_data(GridDefinition::Vlops1km); - CountryBorders borders60km(fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg", "Code3", grid60km.meta, countryInventory); - CountryBorders borders1km(fs::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg", "Code3", grid1km.meta, countryInventory); + CountryBorders borders60km(file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg", "Code3", grid60km.meta, countryInventory); + CountryBorders borders1km(file::u8path(TEST_DATA_DIR) / "_input" / "03_spatial_disaggregation" / "boundaries" / "boundaries.gpkg", "Code3", grid1km.meta, countryInventory); const auto coverage60km = borders60km.create_country_coverages(grid60km.meta, CoverageMode::AllCountryCells, nullptr); const auto coverage1km = borders1km.create_country_coverages(grid1km.meta, CoverageMode::AllCountryCells, nullptr); SpatialPatternInventory inv(cfg); - inv.scan_dir(2021_y, 2016_y, fs::u8path(TEST_DATA_DIR) / "spatialinventory"); + inv.scan_dir(2021_y, 2016_y, file::u8path(TEST_DATA_DIR) / "spatialinventory"); const auto& nlCoverage = inf::find_in_container_required(coverage60km, [](auto& cov) { return cov.country == countries::NL; }); const auto& befCoverage = inf::find_in_container_required(coverage1km, [](auto& cov) { return cov.country == countries::BEF; }); @@ -58,7 +58,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2016 at gnfr level: Industry const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr1A2b), pollutants::CO), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_co_B_Industry.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_co_B_Industry.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::CO); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A2b)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::Industry)); @@ -69,7 +69,7 @@ TEST_CASE("Spatial pattern selection test") { // Fallback pollutant Available in 2016 at gnfr level: Industry const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr1A2b), pollutants::PMcoarse), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_pm10_B_Industry.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_pm10_B_Industry.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::PMcoarse); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A2b)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::Industry)); @@ -80,7 +80,7 @@ TEST_CASE("Spatial pattern selection test") { // Fallback pollutant Available in 2015 at gnfr level: Waste const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr5C1bv), pollutants::PMcoarse), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2015" / "CAMS_emissions_REG-APv5.1_2015_pm10_J_Waste.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2015" / "CAMS_emissions_REG-APv5.1_2015_pm10_J_Waste.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::PMcoarse); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr5C1bv)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::Waste)); @@ -91,7 +91,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2016 at gnfr level: Public power const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr1A1a), pollutants::SOx), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_so2_A_PublicPower.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_so2_A_PublicPower.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::SOx); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A1a)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::PublicPower)); @@ -102,7 +102,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2016 at gnfr level: Industry, cams version in filename is different const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr1A1a), pollutants::CO), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.3_2016_co_A_PublicPower.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.3_2016_co_A_PublicPower.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::CO); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A1a)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::PublicPower)); @@ -113,7 +113,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2016 at nfr const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr5C2), pollutants::PM2_5), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_pm2_5_5C2.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2016" / "CAMS_emissions_REG-APv5.1_2016_pm2_5_5C2.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::PM2_5); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr5C2)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::nfr::Nfr5C2)); @@ -124,7 +124,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2015 at gnfr (not in 2016) const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr3Da1), pollutants::NOx), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2015" / "CAMS_emissions_REG-APv5.1_2015_nox_L_AgriOther.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2015" / "CAMS_emissions_REG-APv5.1_2015_nox_L_AgriOther.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::NOx); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr3Da1)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::AgriOther)); @@ -135,7 +135,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2017 at gnfr (not in 2016 or 2015) const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr2D3d), pollutants::NOx), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2017" / "CAMS_emissions_REG-APv5.1_2017_nox_E_Solvents.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2017" / "CAMS_emissions_REG-APv5.1_2017_nox_E_Solvents.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::NOx); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr2D3d)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::Solvents)); @@ -146,7 +146,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2018 at gnfr (not in 2016 or 2015 or 2017 or 2014) const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr1B2b), pollutants::NOx), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2018" / "CAMS_emissions_REG-ANTv6.1_2018_nox_D_Fugitives.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2018" / "CAMS_emissions_REG-ANTv6.1_2018_nox_D_Fugitives.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::NOx); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1B2b)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::Fugitive)); @@ -157,7 +157,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2010 at gnfr (not in 2016 or 2015 or 2017 or 2014 or 2018 or ...) const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr1A4bi), pollutants::NOx), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2010" / "CAMS_emissions_REG-APv5.1_2010_nox_I_OffRoad.tif"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CAMS" / "2010" / "CAMS_emissions_REG-APv5.1_2010_nox_I_OffRoad.tif"); CHECK(sp.source.emissionId.pollutant == pollutants::NOx); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A4bi)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::Offroad)); @@ -177,7 +177,7 @@ TEST_CASE("Spatial pattern selection test") { // Available in 2016 at gnfr level: Public power const auto sp = inv.get_spatial_pattern(EmissionIdentifier(countries::NL, EmissionSector(sectors::nfr::Nfr1A1a), pollutants::BaP), nlCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CEIP" / "2016" / "BaP_A_PublicPower_2018_GRID_2016.txt"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "rest" / "reporting_2021" / "CEIP" / "2016" / "BaP_A_PublicPower_2018_GRID_2016.txt"); CHECK(sp.source.emissionId.pollutant == pollutants::BaP); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A1a)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::PublicPower)); @@ -188,7 +188,7 @@ TEST_CASE("Spatial pattern selection test") { // Flanders excel data const auto sp = inv.get_spatial_pattern_checked(EmissionIdentifier(countries::BEF, EmissionSector(sectors::nfr::Nfr1A2a), pollutants::NOx), befCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2015" / "Emissies per km2 excl puntbrongegevens_2015_NOx.xlsx"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2015" / "Emissies per km2 excl puntbrongegevens_2015_NOx.xlsx"); CHECK(sp.source.emissionId.pollutant == pollutants::NOx); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A2a)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::nfr::Nfr1A2a)); @@ -200,7 +200,7 @@ TEST_CASE("Spatial pattern selection test") { // Flanders excel data, 2015 does not contain valid data for the sector, so 2019 needs to be used const auto sp = inv.get_spatial_pattern_checked(EmissionIdentifier(countries::BEF, EmissionSector(sectors::nfr::Nfr1A1a), pollutants::NOx), befCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2019" / "Emissies per km2 excl puntbrongegevens_2019_NOx.xlsx"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2019" / "Emissies per km2 excl puntbrongegevens_2019_NOx.xlsx"); CHECK(sp.source.emissionId.pollutant == pollutants::NOx); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A1a)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::nfr::Nfr1A1a)); @@ -225,7 +225,7 @@ TEST_CASE("Spatial pattern selection test") { // Flanders excel data (, in pollutant name) const auto sp = inv.get_spatial_pattern_checked(EmissionIdentifier(countries::BEF, EmissionSector(sectors::nfr::Nfr1A2a), pollutants::PM2_5), befCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2019" / "Emissies per km2 excl puntbrongegevens_2019_PM2,5.xlsx"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2019" / "Emissies per km2 excl puntbrongegevens_2019_PM2,5.xlsx"); CHECK(sp.source.emissionId.pollutant == pollutants::PM2_5); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A2a)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::nfr::Nfr1A2a)); @@ -237,7 +237,7 @@ TEST_CASE("Spatial pattern selection test") { // Flanders excel data const auto sp = inv.get_spatial_pattern_checked(EmissionIdentifier(countries::BEF, EmissionSector(sectors::nfr::Nfr1A2a), pollutants::As), befCoverage); - CHECK(sp.source.path == fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2019" / "Emissie per km2_met NFR_As 2019_juli 2021.xlsx"); + CHECK(sp.source.path == file::u8path(TEST_DATA_DIR) / "spatialinventory" / "bef" / "reporting_2021" / "2019" / "Emissie per km2_met NFR_As 2019_juli 2021.xlsx"); CHECK(sp.source.emissionId.pollutant == pollutants::As); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A2a)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::nfr::Nfr1A2a)); @@ -249,7 +249,7 @@ TEST_CASE("Spatial pattern selection test") { // Exception rule NFR level const auto sp = inv.get_spatial_pattern_checked(EmissionIdentifier(countries::BEF, EmissionSector(sectors::nfr::Nfr1A3bi), pollutants::CO), befCoverage); - CHECK(sp.source.path.generic_u8string() == (fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "." / "wegverkeer" / "2021" / "1A3BI_CO_2016.tif").generic_u8string()); + CHECK(sp.source.path.generic_u8string() == (file::u8path(TEST_DATA_DIR) / "spatialinventory" / "." / "wegverkeer" / "2021" / "1A3BI_CO_2016.tif").generic_u8string()); CHECK(sp.source.emissionId.pollutant == pollutants::CO); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A3bi)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::nfr::Nfr1A3bi)); @@ -260,7 +260,7 @@ TEST_CASE("Spatial pattern selection test") { // Exception rule GNFR level const auto sp = inv.get_spatial_pattern_checked(EmissionIdentifier(countries::BEF, EmissionSector(sectors::nfr::Nfr1A2c), pollutants::CO), befCoverage); - CHECK(sp.source.path.generic_u8string() == (fs::u8path(TEST_DATA_DIR) / "spatialinventory" / "." / "wegverkeer" / "2021" / "B_Industry_CO_2019.tif").generic_u8string()); + CHECK(sp.source.path.generic_u8string() == (file::u8path(TEST_DATA_DIR) / "spatialinventory" / "." / "wegverkeer" / "2021" / "B_Industry_CO_2019.tif").generic_u8string()); CHECK(sp.source.emissionId.pollutant == pollutants::CO); CHECK(sp.source.emissionId.sector == EmissionSector(sectors::nfr::Nfr1A2c)); CHECK(sp.source.usedEmissionId.sector == EmissionSector(sectors::gnfr::Industry));