diff --git a/CMakeLists.txt b/CMakeLists.txt index 9735d7fb8..c05ec347e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -592,6 +592,12 @@ if (ASGARD_BUILD_TESTS) foreach (component IN LISTS components) + # TODO: while all components need testing, the transition period may leave some components hanging + # e.g., all tests depended on pdes that have been removed/transitioned to the new api + if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/${component}_tests.cpp) + continue() + endif() + add_executable (${component}-tests) target_sources (${component}-tests PRIVATE src/${component}_tests.cpp) target_include_directories (${component}-tests PRIVATE ${CMAKE_SOURCE_DIR}/testing) diff --git a/src/asgard_adapt_tests.cpp b/src/asgard_adapt_tests.cpp deleted file mode 100644 index f001d2ff0..000000000 --- a/src/asgard_adapt_tests.cpp +++ /dev/null @@ -1,39 +0,0 @@ - -#include "tests_general.hpp" - -static auto constexpr adapt_threshold = 1e-4; - -static auto const adapt_base_dir = gold_base_dir / "adapt"; - -using namespace asgard; - -struct distribution_test_init -{ - void set_my_rank(const int rank) { my_rank = rank; } - void set_num_ranks(const int size) { num_ranks = size; } - int get_my_rank() const { return my_rank; } - int get_num_ranks() const { return num_ranks; } - -private: - int my_rank; - int num_ranks; -}; -static distribution_test_init distrib_test_info; - -int main(int argc, char *argv[]) -{ - auto const [rank, total_ranks] = initialize_distribution(); - distrib_test_info.set_my_rank(rank); - distrib_test_info.set_num_ranks(total_ranks); - - int result = Catch::Session().run(argc, argv); - - finalize_distribution(); - - return result; -} - -TEMPLATE_TEST_CASE("no-test", "[none]", test_precs) -{ - REQUIRE(true); -} diff --git a/src/asgard_boundary_conditions_tests.cpp b/src/asgard_boundary_conditions_tests.cpp deleted file mode 100644 index b9d0fb2e3..000000000 --- a/src/asgard_boundary_conditions_tests.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "tests_general.hpp" - -static auto const boundary_conditions_base_dir = - gold_base_dir / "boundary_conditions"; - -using namespace asgard; -using namespace asgard::boundary_conditions; - -int main(int argc, char *argv[]) -{ - initialize_distribution(); - - int result = Catch::Session().run(argc, argv); - - finalize_distribution(); - - return result; -} - -TEMPLATE_TEST_CASE("no-test", "[none]", test_precs) -{ - REQUIRE(true); -} diff --git a/src/asgard_cblacs_grid.cpp b/src/asgard_cblacs_grid.cpp deleted file mode 100644 index 93ebd5fb3..000000000 --- a/src/asgard_cblacs_grid.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "asgard_tools.hpp" - -#include "asgard_cblacs_grid.hpp" -#include "asgard_distribution.hpp" - -extern "C" -{ - int numroc_(int *, int *, int *, int *, int *); - void Cblacs_get(int, int, int *); - int Csys2blacs_handle(MPI_Comm); - void Cblacs_gridinit(int *, const char *, int, int); - void Cblacs_gridinfo(int, int *, int *, int *, int *); - void Cfree_blacs_system_handle(int); - void Cblacs_gridexit(int); - void Cblacs_pinfo(int *, int *); - void Cblacs_exit(int); -} -namespace asgard -{ -cblacs_grid::cblacs_grid(MPI_Comm localCommunicator) -{ - int i_negone{-1}, i_zero{0}; - int numproc = get_num_ranks(); - npcol_ = get_num_subgrid_cols(numproc); - nprow_ = numproc / npcol_; - expect((nprow_ >= 1) && (npcol_ >= 1) && (nprow_ * npcol_ == numproc)); - Cblacs_get(i_negone, i_zero, &ictxt_); - bhandle_ = Csys2blacs_handle(localCommunicator); - ictxt_ = bhandle_; - Cblacs_gridinit(&ictxt_, "R", nprow_, npcol_); - Cblacs_gridinfo(ictxt_, &nprow_, &npcol_, &myrow_, &mycol_); -} - -int cblacs_grid::local_rows(int m, int mb) -{ - int i_zero{0}; - return numroc_(&m, &mb, &myrow_, &i_zero, &nprow_); -} - -int cblacs_grid::local_cols(int n, int nb) -{ - int i_zero{0}; - return numroc_(&n, &nb, &mycol_, &i_zero, &npcol_); -} - -cblacs_grid::~cblacs_grid() -{ - Cfree_blacs_system_handle(bhandle_); - Cblacs_gridexit(ictxt_); -} -} // namespace asgard diff --git a/src/asgard_cblacs_grid.hpp b/src/asgard_cblacs_grid.hpp deleted file mode 100644 index 1d6ea4336..000000000 --- a/src/asgard_cblacs_grid.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "asgard_mpi.hpp" -namespace asgard -{ -class cblacs_grid -{ -public: - cblacs_grid(MPI_Comm localCommunicator); - int get_context() const { return ictxt_; } - int get_myrow() const { return myrow_; } - int get_mycol() const { return mycol_; } - int local_rows(int m, int mb); - int local_cols(int n, int nb); - ~cblacs_grid(); - -private: - int bhandle_, ictxt_, nprow_{1}, npcol_, myrow_, mycol_; -}; -} // namespace asgard diff --git a/src/asgard_cblacs_grid_tests.cpp b/src/asgard_cblacs_grid_tests.cpp deleted file mode 100644 index 0af82a6bb..000000000 --- a/src/asgard_cblacs_grid_tests.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "asgard_cblacs_grid.hpp" -#include "tests_general.hpp" - -using namespace asgard; - -int main(int argc, char *argv[]) -{ - initialize_distribution(); - - int result = Catch::Session().run(argc, argv); - - finalize_distribution(); - - return result; -} - -TEST_CASE("Generating a cblacs grid.", "[cblacs_grid]") -{ - if (!is_active()) - { - return; - } - - int myrank = get_rank(); - int num_ranks = get_num_ranks(); - int nprow = std::sqrt(num_ranks); - auto grid = get_grid(); - int myrow = grid->get_myrow(); - int mycol = grid->get_mycol(); - if (get_num_ranks() != 2 && get_num_ranks() != 3) - { - REQUIRE(myrank / nprow == myrow); - REQUIRE(myrank % nprow == mycol); - } - - int local_rows = grid->local_rows(4, 1); - int local_cols = grid->local_cols(4, 1); - if (num_ranks == 4) - { - // 4 elements on each process - REQUIRE(local_rows * local_cols == 4); - } - else if (get_num_ranks() != 2 && get_num_ranks() != 3) - { - // 16 elements on one process - REQUIRE(local_rows * local_cols == 16); - } - - local_rows = grid->local_rows(4, 256); - local_cols = grid->local_cols(4, 256); - if (myrank == 0) - { - // 16 elements on zeroth proces - REQUIRE(local_rows * local_cols == 16); - } - else - { - // None on other processes - REQUIRE(local_rows * local_cols == 0); - } -} diff --git a/src/asgard_discretization_tests.cpp b/src/asgard_discretization_tests.cpp deleted file mode 100644 index f3340007b..000000000 --- a/src/asgard_discretization_tests.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "tests_general.hpp" - -using namespace asgard; - -TEMPLATE_TEST_CASE("discretization testing", "[core discretization]", test_precs) -{ - REQUIRE(true); -} diff --git a/src/asgard_indexset.hpp b/src/asgard_indexset.hpp index ca41aea79..5a78a4ec3 100644 --- a/src/asgard_indexset.hpp +++ b/src/asgard_indexset.hpp @@ -457,12 +457,41 @@ vector2d complete_poly_order(vector2d const &cells, /*! * \brief Manger for a sparse grid multi-index set + * + * \par Main components + * The main components of the grid are an indexset and a corresponding dimension_sort. + * Read access is provided for the multi-indexes and the grid can be refined using different + * strategies. + * After a refinement, the sparse grid can also remap a state vector from the old the grid + * to the new, by removing the data corresponding to the removed cells and adding zeros for + * the new cells. + * + * \par Generations + * Many components of ASGarD need to prepare intermediate data-structures based on the current + * set of indexes; therefore, there needs to be a mechanism that indicates when the grid + * has changed and the intermediates have to be updated. + * Simply counting the number of indexes is not sufficient, since refinement can both add and remove + * indexes, e.g., adding one index and removing another will change the grid but not change + * the number of indexes. + * Thus, we introduce the generation index, every time a refinement operation updates the grid, + * the generation index is incremented and that is the correct way to detect a change and update + * the appropriate data-structures. + * The generation index never decreases until we overflow the 32-bit signed int, thus the correct + * way to compare generations is the != operator (equal or not equal), + * as opposed to > (greater than or less than). */ class sparse_grid { public: //! indicates whether to refine, coarsen (compress) or do both - enum class strategy { refine, coarsen, adapt }; + enum class strategy { + //! add indexes based on the tolerance, does not remove indexes + refine, + //! remove indexes only (compress the solution) + coarsen, + //! simultaneously add and remove indexes + adapt }; + //! makes and empty grid, reinit before use sparse_grid() = default; //! number of dimensions and levels @@ -472,11 +501,14 @@ class sparse_grid //! Returns the number of indexes int64_t num_indexes() const { return iset_.num_indexes(); } - int const * operator[] (int64_t i) const { return iset_[i]; } + //! returns pointer to the i-th index in the grid + int const *operator[] (int64_t i) const { return iset_[i]; } + //! access the internal indexset indexset const &iset() const { return iset_; } + //! access the sort applied to the index set dimension_sort const &dsort() const { return dsort_; } - + //! calls the () operator on the sort int dsorted(int d, int j) const { return dsort_(iset_, d, j); } //! Testing purposes, returns the raw vector of indexes @@ -486,7 +518,7 @@ class sparse_grid int current_level(int d) const { return level_[d]; } //! Returns the first index disallowed due to the max level int max_index(int d) const { return max_index_[d]; } - //! check generation, i.e., if the grid changed + //! Returns the current generation of the grid int generation() const { return generation_; } /*! * \brief Update the grid based on the strategy and current state @@ -516,8 +548,17 @@ class sparse_grid friend class h5manager; protected: - enum class istatus { keep, refine, clear }; + //! marks the status of an entry + enum class istatus { + //! keep this index + keep, + //! refine this index, i.e., include the hierarchical descendants + refine, + //! mark index for removal + clear + }; + //! helper method, constructs a sparse grid given type and anisotropy template indexset make_level_set(std::vector const &levels); diff --git a/src/asgard_moment_tests.cpp b/src/asgard_moment_tests.cpp index 56f860e3b..a5aa181ab 100644 --- a/src/asgard_moment_tests.cpp +++ b/src/asgard_moment_tests.cpp @@ -2,8 +2,6 @@ using P = asgard::default_precision; -static auto const moment_base_dir = gold_base_dir / "moment"; - using namespace asgard; class somepde : public PDE

{ diff --git a/src/asgard_program_options.cpp b/src/asgard_program_options.cpp index c65fcaa0e..9117f0f5f 100644 --- a/src/asgard_program_options.cpp +++ b/src/asgard_program_options.cpp @@ -14,16 +14,14 @@ split_views split_argv(std::string_view const &opts) return split_views(std::move(splits)); } -prog_opts::prog_opts(int const argc, char const *const *argv, - bool ignore_unknown) +prog_opts::prog_opts(int const argc, char const *const *argv) { std::vector view_argv; view_argv.reserve(argc); for (auto i : indexof(argc)) view_argv.emplace_back(argv[i]); - process_inputs( - view_argv, (ignore_unknown) ? handle_mode::ignore_unknown : handle_mode::warn_on_unknown); + process_inputs(view_argv, handle_mode::from_cli); } void prog_opts::print_help(std::ostream &os) @@ -193,8 +191,7 @@ landau_1x3v Collisional Landau 1x3v. )help"; } -void prog_opts::process_inputs(std::vector const &argv, - handle_mode mode) +void prog_opts::process_inputs(std::vector const &argv, handle_mode mode) { std::map commands = { {"help", optentry::show_help}, {"-help", optentry::show_help}, {"--help", optentry::show_help}, @@ -266,13 +263,11 @@ void prog_opts::process_inputs(std::vector const &argv, { auto imap = commands.find(*iarg); if (imap == commands.end()) - { // entry not found - if (mode == handle_mode::warn_on_unknown) - std::cerr << " unrecognized option: " << *iarg << "\n"; - if (mode == handle_mode::save_unknown) - filedata.emplace_back(*iarg); - else + { + if (mode == handle_mode::from_cli) externals.emplace_back(*iarg); + else + filedata.emplace_back(*iarg); continue; } @@ -741,7 +736,7 @@ void prog_opts::process_file(std::string_view const &exec_name) for (auto &s : line_pairs) views.emplace_back(s); - process_inputs(views, handle_mode::save_unknown); + process_inputs(views, handle_mode::from_file); } void prog_opts::print_options(std::ostream &os) const diff --git a/src/asgard_program_options.hpp b/src/asgard_program_options.hpp index 180392b48..a4f248c3b 100644 --- a/src/asgard_program_options.hpp +++ b/src/asgard_program_options.hpp @@ -477,9 +477,8 @@ struct prog_opts //! create empty options, allows to manually fill the options later prog_opts() = default; - //! process the command line arguments, may yield warning if encountering unknown options - prog_opts(int const argc, char const *const *argv, - bool ignore_unknown = true); + //! process the command line arguments + prog_opts(int const argc, char const *const *argv); //! process from a file explicit prog_opts(std::filesystem::path const &filename) @@ -491,7 +490,7 @@ struct prog_opts //! for testing purposes, can read from manually specified argc/argv explicit prog_opts(vecstrview const &argv) { - process_inputs(argv, handle_mode::ignore_unknown); + process_inputs(argv, handle_mode::from_cli); } //! read an extra option from a file @@ -717,9 +716,8 @@ struct prog_opts }; enum class handle_mode { - warn_on_unknown, // print warning - ignore_unknown, // do nothing (user inputs) - save_unknown // reading from file + from_file, // reading from file + from_cli // reading from cli }; //! input filename @@ -731,8 +729,7 @@ struct prog_opts void process_file(std::string_view const &exec_name); //! not in the constructor so it can be reused when reading from file - void process_inputs(std::vector const &argv, - handle_mode mode); + void process_inputs(std::vector const &argv, handle_mode mode); //! map pde options string to enum value static std::optional get_pde_opt(std::string_view const &pde_str); diff --git a/src/asgard_term_manager_tests.cpp b/src/asgard_term_manager_tests.cpp deleted file mode 100644 index 8b4ccd595..000000000 --- a/src/asgard_term_manager_tests.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "tests_general.hpp" - -TEMPLATE_TEST_CASE("fast-transform", "[transformations]", test_precs) -{ - REQUIRE(true); -} diff --git a/src/asgard_transformations_tests.cpp b/src/asgard_transformations_tests.cpp index b8137e2df..b6115042d 100644 --- a/src/asgard_transformations_tests.cpp +++ b/src/asgard_transformations_tests.cpp @@ -2,66 +2,8 @@ #include "asgard_small_mats.hpp" -static auto const transformations_base_dir = gold_base_dir / "transformations"; - using namespace asgard; -template -void test_combine_dimensions(PDE

const &pde, P const time = 1.0, - int const num_ranks = 1, - bool const full_grid = false) -{ - int const dims = pde.num_dims(); - - dimension const dim = pde.get_dimensions()[0]; - int const lev = dim.get_level(); - int const degree = dim.get_degree(); - - std::string const filename = - "combine_dim_dim" + std::to_string(dims) + "_deg" + std::to_string(degree + 1) + - "_lev" + std::to_string(lev) + "_" + (full_grid ? "fg" : "sg") + ".dat"; - - elements::table const t(pde); - - std::vector> vectors; - P counter = 1.0; - for (int i = 0; i < pde.num_dims(); ++i) - { - int const vect_size = dims * fm::ipow2(lev); - std::vector

const vect_1d = [&counter, vect_size] { - std::vector

vect(vect_size); - std::iota(vect.begin(), vect.end(), static_cast

(counter)); - counter += vect.size(); - return vect; - }(); - vectors.push_back(vect_1d); - } - distribution_plan const plan = get_plan(num_ranks, t); - - fk::vector

const gold = - read_vector_from_txt_file

(transformations_base_dir / filename); - fk::vector

test(gold.size()); - for (auto const &[rank, grid] : plan) - { - int const rank_start = - grid.row_start * fm::ipow(degree + 1, dims); - int const rank_stop = - (grid.row_stop + 1) * fm::ipow(degree + 1, dims) - 1; - fk::vector const gold_partial(gold, rank_start, - rank_stop); - std::vector

test_partial(gold_partial.size()); - - combine_dimensions( - degree, t, plan.at(rank).row_start, plan.at(rank).row_stop, vectors, test_partial.data()); - for (auto &tp : test_partial) - tp *= time; - fk::vector

fk_test_partial(test_partial); - REQUIRE(fk_test_partial == gold_partial); - test.set_subvector(rank_start, fk_test_partial); - } - REQUIRE(test == gold); -} - TEMPLATE_TEST_CASE("fast-transform", "[transformations]", test_precs) { std::minstd_rand park_miller(42); diff --git a/src/elliptic.cpp b/src/elliptic.cpp index 4a7c48fb5..a41a823cf 100644 --- a/src/elliptic.cpp +++ b/src/elliptic.cpp @@ -338,12 +338,12 @@ void self_test(); * The main() processes the command line arguments and calls both * make_elliptic_pde() and get_error_l2(). * - * \snippet sinwav.cpp sinwav main + * \snippet elliptic.cpp elliptic main */ int main(int argc, char** argv) { #ifndef __ASGARD_DOXYGEN_SKIP -//! [sinwav main] +//! [elliptic main] #endif using P = asgard::default_precision; @@ -419,7 +419,7 @@ R"help(<< additional options for this file >> return 0; #ifndef __ASGARD_DOXYGEN_SKIP -//! [sinwav main] +//! [elliptic main] #endif } diff --git a/src/main.cpp b/src/main.cpp index 253d8f75f..f1fc98604 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,21 +14,14 @@ int main(int argc, char **argv) return 0; } - // custom projects may implement their own inputs - // in addition to ASGarD standard ones - // however, this the main executable and all - // unknown cli commands are to be treated as errors - // first we generate warnigns for the user - bool constexpr ignore_unknown = false; // -- parse cli - asgard::prog_opts const cli_input(argc, argv, ignore_unknown); + asgard::prog_opts const options(argc, argv); // if there were unknown options, throw an error - if (not cli_input.externals.empty()) - throw std::runtime_error("encountered unrecognized command line option(s)"); + options.throw_if_invalid(); // main call to asgard, does all the work - asgard::simulate_builtin(cli_input); + asgard::simulate_builtin(options); asgard::finalize_distribution(); diff --git a/testing/generated-inputs/transformations/combine_dim_dim2_deg2_lev3_sg.dat b/testing/generated-inputs/transformations/combine_dim_dim2_deg2_lev3_sg.dat deleted file mode 100644 index 52cf06419..000000000 --- a/testing/generated-inputs/transformations/combine_dim_dim2_deg2_lev3_sg.dat +++ /dev/null @@ -1,85 +0,0 @@ -# Created from matlab git hash a1a8dbd37a0f9ba671c9d2084bb54c87f518fd94 -# name: foo -# type: matrix -# rows: 80 -# columns: 1 -306 -324 -340 -360 -374 -396 -408 -432 -442 -468 -476 -504 -510 -540 -544 -576 -190 -200 -228 -240 -266 -280 -304 -320 -126 -132 -168 -176 -138 -144 -184 -192 -50 -52 -100 -104 -54 -56 -108 -112 -58 -60 -116 -120 -62 -64 -124 -128 -170 -180 -204 -216 -238 -252 -272 -288 -114 -120 -152 -160 -42 -44 -84 -88 -46 -48 -92 -96 -102 -108 -136 -144 -38 -40 -76 -80 -34 -36 -68 -72 diff --git a/testing/generated-inputs/transformations/combine_dim_dim3_deg3_lev2_fg.dat b/testing/generated-inputs/transformations/combine_dim_dim3_deg3_lev2_fg.dat deleted file mode 100644 index 4496a4087..000000000 --- a/testing/generated-inputs/transformations/combine_dim_dim3_deg3_lev2_fg.dat +++ /dev/null @@ -1,1733 +0,0 @@ -# Created from matlab git hash d4591680ada8fa22940eade8d507cd43dc65ed5c -# name: foo -# type: matrix -# rows: 1728 -# columns: 1 -812.5 -845 -877.5 -875 -910 -945 -937.5 -975 -1012.5 -1625 -1690 -1755 -1750 -1820 -1890 -1875 -1950 -2025 -2437.5 -2535 -2632.5 -2625 -2730 -2835 -2812.5 -2925 -3037.5 -3250 -3380 -3510 -3500 -3640 -3780 -3750 -3900 -4050 -4062.5 -4225 -4387.5 -4375 -4550 -4725 -4687.5 -4875 -5062.5 -4875 -5070 -5265 -5250 -5460 -5670 -5625 -5850 -6075 -5687.5 -5915 -6142.5 -6125 -6370 -6615 -6562.5 -6825 -7087.5 -6500 -6760 -7020 -7000 -7280 -7560 -7500 -7800 -8100 -7312.5 -7605 -7897.5 -7875 -8190 -8505 -8437.5 -8775 -9112.5 -8125 -8450 -8775 -8750 -9100 -9450 -9375 -9750 -10125 -8937.5 -9295 -9652.5 -9625 -10010 -10395 -10312.5 -10725 -11137.5 -9750 -10140 -10530 -10500 -10920 -11340 -11250 -11700 -12150 -1000 -1040 -1080 -1062.5 -1105 -1147.5 -1125 -1170 -1215 -2000 -2080 -2160 -2125 -2210 -2295 -2250 -2340 -2430 -3000 -3120 -3240 -3187.5 -3315 -3442.5 -3375 -3510 -3645 -4000 -4160 -4320 -4250 -4420 -4590 -4500 -4680 -4860 -5000 -5200 -5400 -5312.5 -5525 -5737.5 -5625 -5850 -6075 -6000 -6240 -6480 -6375 -6630 -6885 -6750 -7020 -7290 -7000 -7280 -7560 -7437.5 -7735 -8032.5 -7875 -8190 -8505 -8000 -8320 -8640 -8500 -8840 -9180 -9000 -9360 -9720 -9000 -9360 -9720 -9562.5 -9945 -10327.5 -10125 -10530 -10935 -10000 -10400 -10800 -10625 -11050 -11475 -11250 -11700 -12150 -11000 -11440 -11880 -11687.5 -12155 -12622.5 -12375 -12870 -13365 -12000 -12480 -12960 -12750 -13260 -13770 -13500 -14040 -14580 -1187.5 -1235 -1282.5 -1250 -1300 -1350 -1312.5 -1365 -1417.5 -2375 -2470 -2565 -2500 -2600 -2700 -2625 -2730 -2835 -3562.5 -3705 -3847.5 -3750 -3900 -4050 -3937.5 -4095 -4252.5 -1375 -1430 -1485 -1437.5 -1495 -1552.5 -1500 -1560 -1620 -2750 -2860 -2970 -2875 -2990 -3105 -3000 -3120 -3240 -4125 -4290 -4455 -4312.5 -4485 -4657.5 -4500 -4680 -4860 -4750 -4940 -5130 -5000 -5200 -5400 -5250 -5460 -5670 -5937.5 -6175 -6412.5 -6250 -6500 -6750 -6562.5 -6825 -7087.5 -7125 -7410 -7695 -7500 -7800 -8100 -7875 -8190 -8505 -5500 -5720 -5940 -5750 -5980 -6210 -6000 -6240 -6480 -6875 -7150 -7425 -7187.5 -7475 -7762.5 -7500 -7800 -8100 -8250 -8580 -8910 -8625 -8970 -9315 -9000 -9360 -9720 -8312.5 -8645 -8977.5 -8750 -9100 -9450 -9187.5 -9555 -9922.5 -9500 -9880 -10260 -10000 -10400 -10800 -10500 -10920 -11340 -10687.5 -11115 -11542.5 -11250 -11700 -12150 -11812.5 -12285 -12757.5 -11875 -12350 -12825 -12500 -13000 -13500 -13125 -13650 -14175 -13062.5 -13585 -14107.5 -13750 -14300 -14850 -14437.5 -15015 -15592.5 -14250 -14820 -15390 -15000 -15600 -16200 -15750 -16380 -17010 -9625 -10010 -10395 -10062.5 -10465 -10867.5 -10500 -10920 -11340 -11000 -11440 -11880 -11500 -11960 -12420 -12000 -12480 -12960 -12375 -12870 -13365 -12937.5 -13455 -13972.5 -13500 -14040 -14580 -13750 -14300 -14850 -14375 -14950 -15525 -15000 -15600 -16200 -15125 -15730 -16335 -15812.5 -16445 -17077.5 -16500 -17160 -17820 -16500 -17160 -17820 -17250 -17940 -18630 -18000 -18720 -19440 -910 -942.5 -975 -980 -1015 -1050 -1050 -1087.5 -1125 -1820 -1885 -1950 -1960 -2030 -2100 -2100 -2175 -2250 -2730 -2827.5 -2925 -2940 -3045 -3150 -3150 -3262.5 -3375 -3640 -3770 -3900 -3920 -4060 -4200 -4200 -4350 -4500 -4550 -4712.5 -4875 -4900 -5075 -5250 -5250 -5437.5 -5625 -5460 -5655 -5850 -5880 -6090 -6300 -6300 -6525 -6750 -6370 -6597.5 -6825 -6860 -7105 -7350 -7350 -7612.5 -7875 -7280 -7540 -7800 -7840 -8120 -8400 -8400 -8700 -9000 -8190 -8482.5 -8775 -8820 -9135 -9450 -9450 -9787.5 -10125 -9100 -9425 -9750 -9800 -10150 -10500 -10500 -10875 -11250 -10010 -10367.5 -10725 -10780 -11165 -11550 -11550 -11962.5 -12375 -10920 -11310 -11700 -11760 -12180 -12600 -12600 -13050 -13500 -1120 -1160 -1200 -1190 -1232.5 -1275 -1260 -1305 -1350 -2240 -2320 -2400 -2380 -2465 -2550 -2520 -2610 -2700 -3360 -3480 -3600 -3570 -3697.5 -3825 -3780 -3915 -4050 -4480 -4640 -4800 -4760 -4930 -5100 -5040 -5220 -5400 -5600 -5800 -6000 -5950 -6162.5 -6375 -6300 -6525 -6750 -6720 -6960 -7200 -7140 -7395 -7650 -7560 -7830 -8100 -7840 -8120 -8400 -8330 -8627.5 -8925 -8820 -9135 -9450 -8960 -9280 -9600 -9520 -9860 -10200 -10080 -10440 -10800 -10080 -10440 -10800 -10710 -11092.5 -11475 -11340 -11745 -12150 -11200 -11600 -12000 -11900 -12325 -12750 -12600 -13050 -13500 -12320 -12760 -13200 -13090 -13557.5 -14025 -13860 -14355 -14850 -13440 -13920 -14400 -14280 -14790 -15300 -15120 -15660 -16200 -1330 -1377.5 -1425 -1400 -1450 -1500 -1470 -1522.5 -1575 -2660 -2755 -2850 -2800 -2900 -3000 -2940 -3045 -3150 -3990 -4132.5 -4275 -4200 -4350 -4500 -4410 -4567.5 -4725 -1540 -1595 -1650 -1610 -1667.5 -1725 -1680 -1740 -1800 -3080 -3190 -3300 -3220 -3335 -3450 -3360 -3480 -3600 -4620 -4785 -4950 -4830 -5002.5 -5175 -5040 -5220 -5400 -5320 -5510 -5700 -5600 -5800 -6000 -5880 -6090 -6300 -6650 -6887.5 -7125 -7000 -7250 -7500 -7350 -7612.5 -7875 -7980 -8265 -8550 -8400 -8700 -9000 -8820 -9135 -9450 -6160 -6380 -6600 -6440 -6670 -6900 -6720 -6960 -7200 -7700 -7975 -8250 -8050 -8337.5 -8625 -8400 -8700 -9000 -9240 -9570 -9900 -9660 -10005 -10350 -10080 -10440 -10800 -9310 -9642.5 -9975 -9800 -10150 -10500 -10290 -10657.5 -11025 -10640 -11020 -11400 -11200 -11600 -12000 -11760 -12180 -12600 -11970 -12397.5 -12825 -12600 -13050 -13500 -13230 -13702.5 -14175 -13300 -13775 -14250 -14000 -14500 -15000 -14700 -15225 -15750 -14630 -15152.5 -15675 -15400 -15950 -16500 -16170 -16747.5 -17325 -15960 -16530 -17100 -16800 -17400 -18000 -17640 -18270 -18900 -10780 -11165 -11550 -11270 -11672.5 -12075 -11760 -12180 -12600 -12320 -12760 -13200 -12880 -13340 -13800 -13440 -13920 -14400 -13860 -14355 -14850 -14490 -15007.5 -15525 -15120 -15660 -16200 -15400 -15950 -16500 -16100 -16675 -17250 -16800 -17400 -18000 -16940 -17545 -18150 -17710 -18342.5 -18975 -18480 -19140 -19800 -18480 -19140 -19800 -19320 -20010 -20700 -20160 -20880 -21600 -1007.5 -1040 -1072.5 -1085 -1120 -1155 -1162.5 -1200 -1237.5 -2015 -2080 -2145 -2170 -2240 -2310 -2325 -2400 -2475 -3022.5 -3120 -3217.5 -3255 -3360 -3465 -3487.5 -3600 -3712.5 -1105 -1137.5 -1170 -1190 -1225 -1260 -1275 -1312.5 -1350 -2210 -2275 -2340 -2380 -2450 -2520 -2550 -2625 -2700 -3315 -3412.5 -3510 -3570 -3675 -3780 -3825 -3937.5 -4050 -4030 -4160 -4290 -4340 -4480 -4620 -4650 -4800 -4950 -5037.5 -5200 -5362.5 -5425 -5600 -5775 -5812.5 -6000 -6187.5 -6045 -6240 -6435 -6510 -6720 -6930 -6975 -7200 -7425 -4420 -4550 -4680 -4760 -4900 -5040 -5100 -5250 -5400 -5525 -5687.5 -5850 -5950 -6125 -6300 -6375 -6562.5 -6750 -6630 -6825 -7020 -7140 -7350 -7560 -7650 -7875 -8100 -7052.5 -7280 -7507.5 -7595 -7840 -8085 -8137.5 -8400 -8662.5 -8060 -8320 -8580 -8680 -8960 -9240 -9300 -9600 -9900 -9067.5 -9360 -9652.5 -9765 -10080 -10395 -10462.5 -10800 -11137.5 -10075 -10400 -10725 -10850 -11200 -11550 -11625 -12000 -12375 -11082.5 -11440 -11797.5 -11935 -12320 -12705 -12787.5 -13200 -13612.5 -12090 -12480 -12870 -13020 -13440 -13860 -13950 -14400 -14850 -7735 -7962.5 -8190 -8330 -8575 -8820 -8925 -9187.5 -9450 -8840 -9100 -9360 -9520 -9800 -10080 -10200 -10500 -10800 -9945 -10237.5 -10530 -10710 -11025 -11340 -11475 -11812.5 -12150 -11050 -11375 -11700 -11900 -12250 -12600 -12750 -13125 -13500 -12155 -12512.5 -12870 -13090 -13475 -13860 -14025 -14437.5 -14850 -13260 -13650 -14040 -14280 -14700 -15120 -15300 -15750 -16200 -1240 -1280 -1320 -1317.5 -1360 -1402.5 -1395 -1440 -1485 -2480 -2560 -2640 -2635 -2720 -2805 -2790 -2880 -2970 -3720 -3840 -3960 -3952.5 -4080 -4207.5 -4185 -4320 -4455 -1360 -1400 -1440 -1445 -1487.5 -1530 -1530 -1575 -1620 -2720 -2800 -2880 -2890 -2975 -3060 -3060 -3150 -3240 -4080 -4200 -4320 -4335 -4462.5 -4590 -4590 -4725 -4860 -4960 -5120 -5280 -5270 -5440 -5610 -5580 -5760 -5940 -6200 -6400 -6600 -6587.5 -6800 -7012.5 -6975 -7200 -7425 -7440 -7680 -7920 -7905 -8160 -8415 -8370 -8640 -8910 -5440 -5600 -5760 -5780 -5950 -6120 -6120 -6300 -6480 -6800 -7000 -7200 -7225 -7437.5 -7650 -7650 -7875 -8100 -8160 -8400 -8640 -8670 -8925 -9180 -9180 -9450 -9720 -8680 -8960 -9240 -9222.5 -9520 -9817.5 -9765 -10080 -10395 -9920 -10240 -10560 -10540 -10880 -11220 -11160 -11520 -11880 -11160 -11520 -11880 -11857.5 -12240 -12622.5 -12555 -12960 -13365 -12400 -12800 -13200 -13175 -13600 -14025 -13950 -14400 -14850 -13640 -14080 -14520 -14492.5 -14960 -15427.5 -15345 -15840 -16335 -14880 -15360 -15840 -15810 -16320 -16830 -16740 -17280 -17820 -9520 -9800 -10080 -10115 -10412.5 -10710 -10710 -11025 -11340 -10880 -11200 -11520 -11560 -11900 -12240 -12240 -12600 -12960 -12240 -12600 -12960 -13005 -13387.5 -13770 -13770 -14175 -14580 -13600 -14000 -14400 -14450 -14875 -15300 -15300 -15750 -16200 -14960 -15400 -15840 -15895 -16362.5 -16830 -16830 -17325 -17820 -16320 -16800 -17280 -17340 -17850 -18360 -18360 -18900 -19440 -1472.5 -1520 -1567.5 -1550 -1600 -1650 -1627.5 -1680 -1732.5 -2945 -3040 -3135 -3100 -3200 -3300 -3255 -3360 -3465 -4417.5 -4560 -4702.5 -4650 -4800 -4950 -4882.5 -5040 -5197.5 -1705 -1760 -1815 -1782.5 -1840 -1897.5 -1860 -1920 -1980 -3410 -3520 -3630 -3565 -3680 -3795 -3720 -3840 -3960 -5115 -5280 -5445 -5347.5 -5520 -5692.5 -5580 -5760 -5940 -1615 -1662.5 -1710 -1700 -1750 -1800 -1785 -1837.5 -1890 -3230 -3325 -3420 -3400 -3500 -3600 -3570 -3675 -3780 -4845 -4987.5 -5130 -5100 -5250 -5400 -5355 -5512.5 -5670 -1870 -1925 -1980 -1955 -2012.5 -2070 -2040 -2100 -2160 -3740 -3850 -3960 -3910 -4025 -4140 -4080 -4200 -4320 -5610 -5775 -5940 -5865 -6037.5 -6210 -6120 -6300 -6480 -5890 -6080 -6270 -6200 -6400 -6600 -6510 -6720 -6930 -7362.5 -7600 -7837.5 -7750 -8000 -8250 -8137.5 -8400 -8662.5 -8835 -9120 -9405 -9300 -9600 -9900 -9765 -10080 -10395 -6820 -7040 -7260 -7130 -7360 -7590 -7440 -7680 -7920 -8525 -8800 -9075 -8912.5 -9200 -9487.5 -9300 -9600 -9900 -10230 -10560 -10890 -10695 -11040 -11385 -11160 -11520 -11880 -6460 -6650 -6840 -6800 -7000 -7200 -7140 -7350 -7560 -8075 -8312.5 -8550 -8500 -8750 -9000 -8925 -9187.5 -9450 -9690 -9975 -10260 -10200 -10500 -10800 -10710 -11025 -11340 -7480 -7700 -7920 -7820 -8050 -8280 -8160 -8400 -8640 -9350 -9625 -9900 -9775 -10062.5 -10350 -10200 -10500 -10800 -11220 -11550 -11880 -11730 -12075 -12420 -12240 -12600 -12960 -10307.5 -10640 -10972.5 -10850 -11200 -11550 -11392.5 -11760 -12127.5 -11780 -12160 -12540 -12400 -12800 -13200 -13020 -13440 -13860 -13252.5 -13680 -14107.5 -13950 -14400 -14850 -14647.5 -15120 -15592.5 -14725 -15200 -15675 -15500 -16000 -16500 -16275 -16800 -17325 -16197.5 -16720 -17242.5 -17050 -17600 -18150 -17902.5 -18480 -19057.5 -17670 -18240 -18810 -18600 -19200 -19800 -19530 -20160 -20790 -11935 -12320 -12705 -12477.5 -12880 -13282.5 -13020 -13440 -13860 -13640 -14080 -14520 -14260 -14720 -15180 -14880 -15360 -15840 -15345 -15840 -16335 -16042.5 -16560 -17077.5 -16740 -17280 -17820 -17050 -17600 -18150 -17825 -18400 -18975 -18600 -19200 -19800 -18755 -19360 -19965 -19607.5 -20240 -20872.5 -20460 -21120 -21780 -20460 -21120 -21780 -21390 -22080 -22770 -22320 -23040 -23760 -11305 -11637.5 -11970 -11900 -12250 -12600 -12495 -12862.5 -13230 -12920 -13300 -13680 -13600 -14000 -14400 -14280 -14700 -15120 -14535 -14962.5 -15390 -15300 -15750 -16200 -16065 -16537.5 -17010 -16150 -16625 -17100 -17000 -17500 -18000 -17850 -18375 -18900 -17765 -18287.5 -18810 -18700 -19250 -19800 -19635 -20212.5 -20790 -19380 -19950 -20520 -20400 -21000 -21600 -21420 -22050 -22680 -13090 -13475 -13860 -13685 -14087.5 -14490 -14280 -14700 -15120 -14960 -15400 -15840 -15640 -16100 -16560 -16320 -16800 -17280 -16830 -17325 -17820 -17595 -18112.5 -18630 -18360 -18900 -19440 -18700 -19250 -19800 -19550 -20125 -20700 -20400 -21000 -21600 -20570 -21175 -21780 -21505 -22137.5 -22770 -22440 -23100 -23760 -22440 -23100 -23760 -23460 -24150 -24840 -24480 -25200 -25920