diff --git a/.circleci/config.yml b/.circleci/config.yml index aff29a4..67ee221 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,6 +10,7 @@ jobs: - run: name: GCC-8 build command: | + source /opt/intel/compilers_and_libraries/linux/bin/compilervars.sh -arch intel64 -platform linux mkdir -p build [ "$(ls -A build)" ] && rm -rf build/* cd build @@ -20,6 +21,7 @@ jobs: - run: name: Clang-6.0 build command: | + source /opt/intel/compilers_and_libraries/linux/bin/compilervars.sh -arch intel64 -platform linux mkdir -p build [ "$(ls -A build)" ] && rm -rf build/* cd build @@ -32,10 +34,16 @@ jobs: command: | cppcheck --version cppcheck --enable=warning --inconclusive --force --language=c++ --std=c++11 src/*.cc include/*.h include/*.tcc --error-exitcode=1 + # clang-format + - run: + name: clang-format + command: | + python3 ./clang-tools/run-clang-format.py -r include/* src/* tests/* # codecoverage - run: name: codecov.io command: | + source /opt/intel/compilers_and_libraries/linux/bin/compilervars.sh -arch intel64 -platform linux mkdir -p build [ "$(ls -A build)" ] && rm -rf build/* cd build diff --git a/.gitignore b/.gitignore index 34f6c0c..7710628 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,3 @@ configure.scan *install-sh *missing *stamp-h1 -benchmarks/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 893c7da..0621ea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ project(pipe_network LANGUAGES CXX) -# Require C++14-compliant compiler; only available for CMake v. 3.1 and up -set(CMAKE_CXX_STANDARD 14) +# Require C++17-compliant compiler; only available for CMake v. 3.1 and up +set(CMAKE_CXX_STANDARD 17) cmake_minimum_required(VERSION 3.1) @@ -11,7 +11,7 @@ SET(CMAKE_VERBOSE_MAKEFILE OFF) # General compile settings IF (NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE "Debug") - #SET(CMAKE_BUILD_TYPE "Release") +# SET(CMAKE_BUILD_TYPE "Release") ENDIF (NOT CMAKE_BUILD_TYPE) # GNU Specific settings @@ -24,72 +24,110 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -pthread") endif() +# CMake seems to have no way to enable/disable testing per subproject, +# so we provide an option similar to BUILD_TESTING, but just for CITYSCAPE. +option(PIPE_NETWORK_TEST_BUILD_TESTING "enable testing for cityscape" ON) + # CMake Modules set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) -# Boost Archive -#find_package(Boost REQUIRED COMPONENTS system serialization) -#include_directories(${BOOST_INCLUDE_DIRS}) -#link_libraries(${Boost_SERIALIZATION_LIBRARY} ${Boost_SYSTEM_LIBRARY}) - +# pipe_network executable +SET(pipe_network_src + src/index_manager.cc + src/mesh_components.cc + src/mesh.cc + src/matrix_assembler_components.cc + src/matrix_assembler.cc + src/curves.cc + src/mkl_unsym.cc + src/LU_solver.cc + src/hydralic_sim.cc + src/io.cc + src/io_utils.cc + src/valve_graph.cc + src/valve_graph_components.cc + ) + +# Find dependencies for the library # Eigen find_package(Eigen3 REQUIRED) -include_directories(${EIGEN3_INCLUDE_DIR}) + # Pthreads set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) - -# Include directories -include_directories( - ${pipe_network_SOURCE_DIR}/include/ - ${pipe_network_SOURCE_DIR}/external/ -) +find_package (Threads) + +# OpenMP +find_package(OpenMP) +if (OPENMP_FOUND) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + endif() +endif() -# pipe_network executable -SET(pipe_network_src - src/main.cc - src/eigen_gmres.cc - src/matrix_assembler.cc - src/mesh.cc - src/pipe.cc - src/node.cc - src/io.cc -) -add_executable(pipe_network - ${pipe_network_src} -) - -target_link_libraries(pipe_network Threads::Threads) - -# Unit test -SET(test_src - src/eigen_gmres.cc - src/matrix_assembler.cc - src/mesh.cc - src/pipe.cc - src/io.cc - src/node.cc - tests/eigen_gmres_test.cc -# tests/matrix_assembler_test.cc - tests/matrix_assembler_test_full.cc - tests/mesh_test.cc - tests/node_test.cc - tests/pipe_test.cc - tests/io_test.cc - tests/todini_example_test.cc - tests/test.cc -) -add_executable(pipe_network_test - ${test_src} -) - -target_link_libraries(pipe_network_test Threads::Threads) - -add_test(NAME pipe_network_test COMMAND $) -enable_testing() +# MKL +find_package(MKL REQUIRED) + +# BLAS Math Libraries +find_package(BLAS REQUIRED) + +# LAPACK +find_package(LAPACK REQUIRED) + + +add_library(lpipe_network SHARED ${pipe_network_src}) +# include directories +target_include_directories(lpipe_network + PUBLIC + ${pipe_network_SOURCE_DIR}/include/ + ${pipe_network_SOURCE_DIR}/external/ + ${EIGEN3_INCLUDE_DIR} + ${MKL_INCLUDE_DIR} + ${BOOST_INCLUDE_DIRS} + + ) + +# link libs +target_link_libraries(lpipe_network + PUBLIC + ${CMAKE_THREAD_LIBS_INIT} + ${BLAS_LIBRARIES} + ${LAPACK_LIBRARIES} + ${Boost_LIBRARIES} + ${MKL_LIBRARIES} + ) + +add_executable(pipe_network ${pipe_network_SOURCE_DIR}/src/main.cc) +target_link_libraries(pipe_network + PUBLIC + lpipe_network) + +# Testing +if(PIPE_NETWORK_TEST_BUILD_TESTING) + # Unit test + SET(pipe_network_test_src + tests/node_test.cc + tests/link_test.cc + tests/mesh_test.cc + tests/matrix_assembler_test.cc + tests/solver_test.cc + tests/hydraulic_sim_test.cc + tests/input_test.cc + tests/curve_test.cc + tests/valve_graph_test.cc + ) + + add_executable(pipe_network_test tests/main_test.cc ${pipe_network_test_src}) + target_link_libraries(pipe_network_test lpipe_network) + add_test(NAME pipe_network_test COMMAND $) + enable_testing() +endif() # Coverage find_package(codecov) -add_coverage(pipe_network) -add_coverage(pipe_network_test) +if(ENABLE_COVERAGE) + add_executable(pipe_network_test_coverage tests/main_test.cc ${pipe_network_src} ${pipe_network_test_src}) + target_link_libraries(pipe_network_test_coverage lpipe_network) + add_coverage(pipe_network_test_coverage) +endif() diff --git a/README.md b/README.md index 3985614..eb662a8 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ ### Prerequisite packages > The following prerequisite packages can be found in the docker image: -* [Boost](http://www.boost.org/) * [Eigen](http://eigen.tuxfamily.org/) +* [Intel MKL](https://software.intel.com/content/www/us/en/develop/tools/math-kernel-library.html) ## Compile and Run > See https://pipe-network-doc.cb-cities.com/ for more detailed instructions. @@ -31,3 +31,21 @@ ### Run tests 0. Run `./pipe-network-test -s` (for a verbose output) or `ctest -VV`. + +### Run hydraulic simulation +Run ./pipe-network with the following flags + +-f , --file + .inp file path for the WDN system + +-t , --to + folder to save the simulation results + +-d, --debug + debug mode: output intermediate results (residuals) + +-n , --name + Name for the WDN + +-h, --help + Displays usage information and exits. diff --git a/benchmarks/Honai_network_nodes.csv b/benchmarks/Honai_network_nodes.csv deleted file mode 100644 index 052406d..0000000 --- a/benchmarks/Honai_network_nodes.csv +++ /dev/null @@ -1,33 +0,0 @@ -Node_id,Node_coord1,Node_coord2,Node_coord3,Node_head ,Node_discharge -0,0,0,0,100,-5.5389 -1,0,100,0,98.6,0.24722 -2,0,1450,0,81.4,0.23611 -3,900,1450,0,75.9,0.03611 -4,900,2600,0,69,0.20139 -5,900,4050,0,60.9,0.27917 -6,900,4500,0,58.5,0.375 -7,900,5350,0,54.7,0.15278 -8,900,6200,0,51,0.14583 -9,900,7000,0,47.8,0.14583 -10,1850,7000,0,44,0.13889 -11,3050,7000,0,39.8,0.15556 -12,6550,7000,0,30,0.26111 -13,812.416385,7795.19124,0,43.2,0.17083 -14,425.55144,7478.433507,0,40.3,0.07778 -15,0,7130,0,38,0.08611 -16,0,4400,0,56.7,0.24028 -17,0,2650,0,70.5,0.37361 -18,0,1850,0,77.8,0.01667 -19,-2185.977127,1202,0,67,0.35417 -20,-2185.977127,-298,0,42.3,0.25833 -21,-2185.977127,-798,0,37.2,0.13472 -22,0,2700,0,51.9,0.29028 -23,0,3930,0,40.1,0.22778 -24,0,5230,0,32.6,0.04722 -25,0,6080,0,34.1,0.25 -26,0,6380,0,35.2,0.10278 -27,0,4200,0,44.3,0.08056 -28,-1737.237816,3209.038462,0,35.3,0.1 -29,-148.9091842,3401.917543,0,30,0.1 -30,0,3420,0,30,0.02917 -31,0,4280,0,30.1,0.22361 diff --git a/benchmarks/Honai_network_pipes.csv b/benchmarks/Honai_network_pipes.csv deleted file mode 100644 index 94b8af4..0000000 --- a/benchmarks/Honai_network_pipes.csv +++ /dev/null @@ -1,35 +0,0 @@ -Pipe_id,Pipe_node1,Pipe_node2,Pipe_diameter,Pipe_roughness,Pipe_status,Pipe_discharge -0,0,1,1.016,130,1,NA -1,1,2,1.016,130,1,NA -2,2,3,0.98552,130,1,NA -3,3,4,0.98298,130,1,NA -4,4,5,0.96012,130,1,NA -5,5,6,0.92202,130,1,NA -6,6,7,0.85852,130,1,NA -7,7,8,0.83312,130,1,NA -8,8,9,0.8001,130,1,NA -9,9,10,0.635,130,1,NA -10,10,11,0.5842,130,1,NA -11,11,12,0.51308,130,1,NA -12,9,13,0.4826,130,1,NA -13,13,14,0.3683,130,1,NA -14,14,15,0.3048,130,1,NA -15,16,15,0.50546,130,1,NA -16,16,17,0.58674,130,1,NA -17,17,18,0.67564,130,1,NA -18,18,2,0.68072,130,1,NA -19,2,19,0.89408,130,1,NA -20,19,20,0.41656,130,1,NA -21,20,21,0.3048,130,1,NA -22,19,22,0.7493,130,1,NA -23,22,23,0.49022,130,1,NA -24,23,24,0.41656,130,1,NA -25,25,24,0.3048,130,1,NA -26,26,25,0.508,130,1,NA -27,15,26,0.5588,130,1,NA -28,22,27,0.48006,130,1,NA -29,27,28,0.43434,130,1,NA -30,28,29,0.37084,130,1,NA -31,29,30,0.3048,130,1,NA -32,31,30,0.3048,130,1,NA -33,24,31,0.4953,130,1,NA diff --git a/benchmarks/small/branch.inp b/benchmarks/small/branch.inp new file mode 100644 index 0000000..5f2707b --- /dev/null +++ b/benchmarks/small/branch.inp @@ -0,0 +1,479 @@ +[JUNCTIONS] +;ID Elev Demand Pattern +29005 10.54 0.0 ; +29006 10.54 0.0 ; +29026 10.28 0.0 ; +64810 9.57 13.963670378800002 ; +64811 11.18 0.0 ; +70334 9.56 0.0 ; +70335 8.63 0.0 ; +71423 9.56 0.0 ; +71626 9.42 4.26737847019 ; +72291 11.25 8.585258460730001 ; +73712 9.92 1.2845448837755002 ; +73713 9.71 1.0169313663223 ; +73908 10.52 0.160568110472 ; +73909 10.93 0.24085216570729998 ; +73913 10.87 0.347897572689 ; +74383 9.77 0.1873294622169 ; +74384 9.77 1.150738125048 ; +74420 13.72 0.0 ; +74421 14.04 0.0 ; +74875 10.54 0.0 ; +74876 10.54 0.0 ; +76649 10.34 0.5887497383970001 ; +76650 9.46 0.7493178488694999 ; +76787 10.99 0.37465892443449994 ; +76788 10.85 0.4014202761799 ; +77189 10.28 0.0 ; +77563 9.99 1.3648289390103003 ; +77564 10.38 0.5084656831612999 ; +77753 10.59 0.0 ; +77754 12.0 20.766808954400002 ; +79187 13.82 0.3746589244344001 ; +79188 14.56 3.8536346513289006 ; +80240 9.54 1.5253970494822002 ; +80241 10.29 1.0972154215576002 ; +80704 9.65 0.8902482689724999 ; +80740 9.48 0.267613517453 ; +80741 9.44 0.9098859593399 ; +81150 11.13 0.321136220944 ; +81151 11.02 0.5084656831616 ; +81697 10.2 0.3211362209436 ; +81698 10.15 0.053522703490599996 ; +81723 11.99 0.0 ; +81724 13.98 0.0 ; +81806 10.24 0.4817043314152 ; +81807 10.24 0.0 ; +81984 12.51 0.0 ; +81985 12.94 0.0 ; +82274 9.51 0.6422724418879999 ; +82275 9.77 0.0 ; +85188 12.16 2.4888057123099996 ; +85578 10.32 0.0 ; +85579 10.32 0.481704331416 ; +85718 10.03 0.0 ; +85719 10.03 0.0 ; +85902 10.28 0.160568110472 ; +85903 10.28 0.4817043314156 ; +88285 10.01 0.21409081396200003 ; +88286 10.01 0.0 ; +88373 10.29 0.5352270349054 ; +89218 9.35 0.0 ; +89600 12.29 0.0 ; +89601 10.05 0.0 ; +90111 9.17 0.4549429796702 ; +90112 9.63 1.81977191868 ; +90189 9.77 0.0 ; +90256 10.8 0.187329462217 ; +90257 11.62 1.1239767733036 ; +90419 9.62 0.133806758727 ; +90420 8.94 0.3746589244336 ; +90732 11.13 1.097215421558 ; +90799 11.27 0.0 ; +91010 9.06 0.5887497383969 ; +91426 13.98 0.0 ; +91562 9.83 0.0802840552359 ; +91563 10.58 0.6155110901419001 ; +91629 12.38 1.097215421558 ; +93896 9.91 0.1338067587265 ; +93897 10.49 0.7493178488689001 ; +94070 10.01 1.4718743459911003 ; +94071 9.48 0.1873294622169 ; +94936 11.28 1.3113062355187002 ; +94937 10.29 0.9098859593408001 ; +95385 9.69 0.10704540698100001 ; +95435 13.59 0.0 ; +96755 9.13 0.321136220944 ; +96756 8.59 0.160568110472 ; +96972 11.13 0.0802840552359 ; +97227 10.78 0.053522703490599996 ; +99034 11.56 0.0 ; +99391 11.61 0.9634086628313 ; +99392 10.01 0.8831246075954999 ; +100097 9.48 0.0 ; +100134 12.52 1.2577835320292 ; +100135 11.35 1.1239767733022 ; +100219 10.98 0.0 ; +100411 9.12 0.10704540698100001 ; +101496 9.88 0.0 ; +101501 9.6 0.0 ; +101502 9.6 0.0 ; +101814 10.86 0.133806758727 ; +101940 12.32 0.6422724418875 ; +102478 8.67 0.5619883866515999 ; +102797 10.47 0.5084656831609999 ; +103020 13.25 26.895158503986302 ; +103415 10.14 0.7493178488689999 ; +103949 9.61 2.0606240843898003 ; +103974 10.4 0.0 ; +103975 10.4 0.0 ; +104441 9.67 1.4451129942459002 ; +104527 10.97 0.5619883866512 ; +104528 10.73 0.1873294622169 ; +105465 13.59 0.0 ; +105663 10.32 30.855838562315 ; +105754 10.18 1.6056811047196 ; +105810 9.79 1.3915902907549005 ; +106112 11.47 0.508465683161 ; +106113 11.08 1.1774994767928002 ; +106188 10.15 0.8831246075949001 ; +106260 9.35 1.0704540698115 ; +106261 9.56 1.3113062355194005 ; +106341 10.02 0.5084656831614001 ; +106695 10.8 0.8831246075949001 ; +106775 12.63 0.2408521657075 ; +106776 12.76 0.0 ; +106861 9.42 0.0 ; +107102 10.0 0.7493178488684 ; +107231 10.91 0.8563632558485998 ; +107232 12.28 1.4183516425022 ; +107378 10.93 0.160568110472 ; +107379 11.57 0.6422724418874999 ; +107721 10.33 1.8465332704263009 ; +107791 9.88 0.0 ; +107856 10.85 0.1873294622169 ; +107959 9.88 0.0 ; +108008 10.62 2.56908976755 ; +108017 9.97 1.2310221802836 ; +108072 11.09 1.1774994767945002 ; +108393 10.73 0.3211362209436 ; +108573 10.66 0.6957951453779 ; +108579 11.65 0.0 ; +108623 9.92 0.7493178488685999 ; +108756 9.95 0.8028405523587999 ; +108807 10.08 0.7760792006135999 ; +108885 10.66 0.401420276179 ; +108898 10.95 12.1228923406 ; +109253 10.64 1.2845448837741005 ; +109254 10.93 0.9634086628305 ; +109576 13.22 0.0 ; +109976 9.25 0.6422724418869 ; +110263 11.99 0.0 ; +110382 10.51 13.3003918174 ; +110433 9.69 0.10704540698100001 ; +110434 9.21 1.445112994247 ; +110464 9.48 0.37465892443490006 ; +110557 9.24 1.043692718067 ; +110558 9.76 0.1873294622169 ; +111049 13.21 0.0 ; +111198 10.14 0.6155110901426 ; +111361 11.42 0.0 ; +111366 10.47 0.0 ; +111437 10.73 0.8028405523587999 ; +111849 9.6 0.0 ; +111895 9.45 0.0 ; +111955 11.56 0.0 ; +112525 9.88 0.053522703490599996 ; +112526 9.43 0.4281816279258 ; +113059 12.06 0.8296019041042 ; +113307 9.99 0.37465892443390003 ; +113309 10.22 0.321136220944 ; +113528 10.14 0.5352270349059001 ; +113687 10.28 0.0 ; +113782 10.12 0.8296019041042999 ; +113855 10.41 11.105960974261999 ; +113962 11.61 22.907717093979997 ; +114255 9.03 0.588749738396 ; +114287 9.74 1.1239767733016002 ; +114734 9.4 0.9098859593399 ; +[RESERVOIRS] +;ID Head Pattern +92966 150 ; +111724 150 ; + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness Minorloss Status +PIPE-29647 29005 29006 1.2203496462889367 6.0 130 0 Open ; +PIPE-29665 29026 29006 5.5901556306456754 6.0 130 0 Open ; +PIPE-63966 64810 64811 386.45228061120673 12.0 130 0 Open ; +PIPE-69346 70334 70335 20.837756553396755 8.0 130 0 Open ; +PIPE-71309 71423 64810 14.671493496222686 12.0 130 0 Open ; +PIPE-71761 70335 71626 35.672488372209365 8.0 130 0 Open ; +PIPE-75634 71626 72291 284.28848871911185 8.0 130 0 Open ; +PIPE-76288 73712 73713 401.2151542572505 6.0 130 0 Open ; +PIPE-76388 73908 73909 181.48078896889763 8.0 130 0 Open ; +PIPE-76391 73909 73913 38.381433843927866 8.0 130 0 Open ; +PIPE-76634 74383 74384 10.13657705135866 6.0 130 0 Open ; +PIPE-76653 74420 74421 31.85365922398078 8.0 130 0 Open ; +PIPE-76889 74875 74876 5.26341299294121 6.0 130 0 Open ; +PIPE-77836 76649 76650 331.58421182439406 6.0 130 0 Open ; +PIPE-77915 76787 76788 89.64825824108631 6.0 130 0 Open ; +PIPE-78137 77189 29026 4.5675305792431775 8.0 130 0 Open ; +PIPE-78348 77563 77564 333.6682980110292 12.0 130 0 Open ; +PIPE-78453 77753 77754 273.2235453029176 8.0 130 0 Open ; +PIPE-79268 79187 79188 273.85028943451766 8.0 130 0 Open ; +PIPE-79889 80240 80241 147.50208755686694 6.0 130 0 Open ; +PIPE-80165 80704 71423 107.28114050222185 12.0 130 0 Open ; +PIPE-80188 80740 80741 239.70107092963454 8.0 130 0 Open ; +PIPE-80433 81150 81151 46.301048862186576 8.0 130 0 Open ; +PIPE-80768 81697 81698 7.2198859656303735 6.0 130 0 Open ; +PIPE-80784 81723 81724 268.4477825206959 8.0 130 0 Open ; +PIPE-80838 81806 81807 9.075637172877498 12.0 130 0 Open ; +PIPE-80949 81984 81985 136.96383382593473 8.0 130 0 Open ; +PIPE-81128 82274 82275 24.75363801275703 12.0 130 0 Open ; +PIPE-82899 74421 85188 263.0799170138221 8.0 130 0 Open ; +PIPE-83159 85578 85579 22.04690314058097 12.0 130 0 Open ; +PIPE-83255 85718 85719 1.8396396757578344 8.0 130 0 Open ; +PIPE-83380 85902 85903 6.216331637653773 8.0 130 0 Open ; +PIPE-85195 88285 88286 7.408194651432542 6.0 130 0 Open ; +PIPE-85271 88373 73712 176.0750003093423 6.0 130 0 Open ; +PIPE-86051 71423 89218 28.998966040746694 8.0 130 0 Open ; +PIPE-86424 89600 89601 83.63005095328879 8.0 130 0 Open ; +PIPE-86952 90111 90112 223.8018280465678 6.0 130 0 Open ; +PIPE-87034 82275 90189 6.311232054431414 8.0 130 0 Open ; +PIPE-87099 90256 90257 125.33074634695429 6.0 130 0 Open ; +PIPE-87285 90419 90420 48.23104910485076 12.0 130 0 Open ; +PIPE-87659 88373 90732 216.78159148481674 6.0 130 0 Open ; +PIPE-87735 90799 89600 8.020003880797749 6.0 130 0 Open ; +PIPE-88001 91010 81150 231.14669529421815 8.0 130 0 Open ; +PIPE-88502 91426 81724 6.872085983429692 6.0 130 0 Open ; +PIPE-88623 91562 91563 151.1066526669198 8.0 130 0 Open ; +PIPE-88672 91629 91426 35.23834924397188 6.0 130 0 Open ; +PIPE-90404 93896 93897 197.07749407480617 8.0 130 0 Open ; +PIPE-90570 94070 94071 169.3864652310429 8.0 130 0 Open ; +PIPE-91553 94936 94937 401.7387889018222 6.0 130 0 Open ; +PIPE-91959 95385 88285 114.37570037725156 12.0 130 0 Open ; +PIPE-91995 81724 95435 218.57537360872573 8.0 130 0 Open ; +PIPE-92866 96755 96756 66.98356901500833 12.0 130 0 Open ; +PIPE-93015 81150 96972 6.594199008512208 6.0 130 0 Open ; +PIPE-93197 73913 97227 30.802119724660486 8.0 130 0 Open ; +PIPE-94521 99034 81984 106.54934150523547 8.0 130 0 Open ; +PIPE-94805 99391 99392 363.8270399764201 6.0 130 0 Open ; +PIPE-95390 100097 80740 1.0114898134903576 8.0 130 0 Open ; +PIPE-95426 100134 100135 387.4574707607188 6.0 130 0 Open ; +PIPE-95494 100219 85578 59.12778358144916 12.0 130 0 Open ; +PIPE-95665 100411 70334 64.27891608742496 8.0 130 0 Open ; +PIPE-96707 101496 77563 41.535974780020396 12.0 130 0 Open ; +PIPE-96710 101501 101502 5.100976944521513 8.0 130 0 Open ; +PIPE-97023 101814 73908 25.98400296113164 8.0 130 0 Open ; +PIPE-97151 96972 101940 116.38561928790432 6.0 130 0 Open ; +PIPE-97714 79188 102478 373.9558376028368 8.0 130 0 Open ; +PIPE-98054 97227 102797 133.77001247649588 8.0 130 0 Open ; +PIPE-98312 103020 79187 67.21046392381288 8.0 130 0 Open ; +PIPE-98779 77564 103415 20.0269033275674 12.0 130 0 Open ; +PIPE-99466 103949 94070 397.47693120355365 8.0 130 0 Open ; +PIPE-99505 103974 103975 13.416902331158422 8.0 130 0 Open ; +PIPE-99886 90189 91010 40.33150673303457 8.0 130 0 Open ; +PIPE-100139 104441 76787 179.91119857268814 6.0 130 0 Open ; +PIPE-100285 104527 104528 110.26568638585199 6.0 130 0 Open ; +PIPE-100654 102478 70334 22.499840015172964 8.0 130 0 Open ; +PIPE-101825 95435 105465 25.386043208880825 8.0 130 0 Open ; +PIPE-102203 85578 105663 23.413842174899827 8.0 130 0 Open ; +PIPE-102326 90420 105754 440.2387135126513 12.0 130 0 Open ; +PIPE-102388 104528 105810 50.39939808175959 6.0 130 0 Open ; +PIPE-102460 81698 82274 299.54271912832974 12.0 130 0 Open ; +PIPE-102683 85718 96755 132.65322055481036 12.0 130 0 Open ; +PIPE-102719 106112 106113 46.776247917057454 6.0 130 0 Open ; +PIPE-102800 74383 106188 362.298818089598 12.0 130 0 Open ; +PIPE-102897 106260 106261 284.87075202326594 6.0 130 0 Open ; +PIPE-102995 76788 106341 50.16509431131614 6.0 130 0 Open ; +PIPE-103061 99392 104441 50.30380653339778 6.0 130 0 Open ; +PIPE-103449 106695 90256 5.040246128183253 6.0 130 0 Open ; +PIPE-103549 106775 106776 31.4623348722082 6.0 130 0 Open ; +PIPE-103672 96756 106861 14.194164302258079 12.0 130 0 Open ; +PIPE-103951 107102 81806 353.34742565422385 12.0 130 0 Open ; +PIPE-104030 82275 74383 13.416465122591275 12.0 130 0 Open ; +PIPE-104126 107231 107232 390.0817802649898 6.0 130 0 Open ; +PIPE-104331 107378 107379 123.49851606085235 6.0 130 0 Open ; +PIPE-104745 105810 107721 399.3774106567459 6.0 130 0 Open ; +PIPE-104840 101496 107791 7.585427015582808 6.0 130 0 Open ; +PIPE-104920 94937 107856 46.984882216544676 6.0 130 0 Open ; +PIPE-105068 107959 101496 3.3541162863853287 12.0 130 0 Open ; +PIPE-105134 85188 108008 272.7207609238771 8.0 130 0 Open ; +PIPE-105147 108017 76649 66.03093320306793 6.0 130 0 Open ; +PIPE-105225 108072 100134 104.24173338312876 6.0 130 0 Open ; +PIPE-105394 85903 103949 157.7015948851412 8.0 130 0 Open ; +PIPE-105687 108393 106112 81.77763132408742 6.0 130 0 Open ; +PIPE-105953 108573 80240 373.30780463195816 6.0 130 0 Open ; +PIPE-105960 108579 81723 28.552983730056834 8.0 130 0 Open ; +PIPE-106027 108623 107102 270.1141214525296 12.0 130 0 Open ; +PIPE-106077 73909 107378 4.8556442724553115 6.0 130 0 Open ; +PIPE-106229 108756 93897 61.260837715559724 8.0 130 0 Open ; +PIPE-106248 107856 104527 132.5777981728064 6.0 130 0 Open ; +PIPE-106300 108807 107959 117.642714978085 12.0 130 0 Open ; +PIPE-106416 106188 108885 13.029419478138086 12.0 130 0 Open ; +PIPE-106434 108898 103974 282.77377245845616 8.0 130 0 Open ; +PIPE-106997 109253 109254 63.59052799299721 6.0 130 0 Open ; +PIPE-107495 109576 74420 78.86473461331316 8.0 130 0 Open ; +PIPE-107829 81151 106695 217.99067305024 8.0 130 0 Open ; +PIPE-107983 100135 90799 33.157609155884835 6.0 130 0 Open ; +PIPE-108147 109976 90419 24.778642496502858 12.0 130 0 Open ; +PIPE-108638 110263 99034 40.742889221979524 8.0 130 0 Open ; +PIPE-108860 110382 103975 272.2291446247247 8.0 130 0 Open ; +PIPE-108971 110433 110434 290.9337422250752 6.0 130 0 Open ; +PIPE-108981 106695 101814 39.850765891185375 8.0 130 0 Open ; +PIPE-109023 88286 110464 871.8546390191965 6.0 130 0 Open ; +PIPE-109193 109254 91629 323.0528707010052 6.0 130 0 Open ; +PIPE-109206 110557 110558 61.54576545097779 6.0 130 0 Open ; +PIPE-109335 105465 89600 267.8886478841571 8.0 130 0 Open ; +PIPE-109915 81985 108579 228.2654185497421 8.0 130 0 Open ; +PIPE-110177 111049 105465 7.767817124141186 6.0 130 0 Open ; +PIPE-110529 103415 111198 9.653335305212751 6.0 130 0 Open ; +PIPE-110857 107232 111049 33.67072788738711 6.0 130 0 Open ; +PIPE-110891 80741 108756 336.57088045387667 8.0 130 0 Open ; +PIPE-110925 90732 111361 30.055140316391093 6.0 130 0 Open ; +PIPE-110934 111366 77189 35.40031983395876 8.0 130 0 Open ; +PIPE-111101 111437 94936 388.9791656298002 6.0 130 0 Open ; +PIPE-111241 106261 81697 146.25411085777404 6.0 130 0 Open ; +PIPE-111288 110464 29026 738.3528389298639 6.0 130 0 Open ; +PIPE-111427 106776 81985 7.7411891834566875 6.0 130 0 Open ; +PIPE-111883 107791 74875 230.0973133559863 6.0 130 0 Open ; +PIPE-111931 111849 101501 3.1346161322552253 8.0 130 0 Open ; +PIPE-112055 85719 111895 3.0054710801567706 8.0 130 0 Open ; +PIPE-112084 89218 91562 79.00307714612131 8.0 130 0 Open ; +PIPE-112172 111955 111437 34.16091421295658 6.0 130 0 Open ; +PIPE-112889 111361 81723 7.647029999065992 6.0 130 0 Open ; +PIPE-112917 108885 108573 6.464374536677274 6.0 130 0 Open ; +PIPE-113118 105754 95385 37.76336069127747 12.0 130 0 Open ; +PIPE-113209 112525 112526 332.72085179602277 6.0 130 0 Open ; +PIPE-113581 106113 109253 402.1461939224279 6.0 130 0 Open ; +PIPE-113753 91563 103020 389.2302096756307 8.0 130 0 Open ; +PIPE-113913 113059 106775 116.65617459375298 6.0 130 0 Open ; +PIPE-114204 108885 108807 260.03251054274523 12.0 130 0 Open ; +PIPE-114553 113307 108393 187.89291539800217 6.0 130 0 Open ; +PIPE-114555 113309 81698 60.7229069813902 12.0 130 0 Open ; +PIPE-114741 85579 113309 154.3004834558164 12.0 130 0 Open ; +PIPE-114790 99034 111955 6.932452147507843 6.0 130 0 Open ; +PIPE-114967 111724 108623 108.39027605609829 12.0 130 0 Open ; +PIPE-115302 113528 106260 133.86505880116488 6.0 130 0 Open ; +PIPE-115320 89601 100411 135.63160516281454 8.0 130 0 Open ; +PIPE-115404 107959 112525 6.828259382260761 6.0 130 0 Open ; +PIPE-115435 103975 77753 63.634635016325 8.0 130 0 Open ; +PIPE-115774 107721 113059 273.3882996026948 6.0 130 0 Open ; +PIPE-115857 74876 113687 13.726691079853554 6.0 130 0 Open ; +PIPE-116191 112526 113782 92.90929740705842 6.0 130 0 Open ; +PIPE-116479 113855 110382 305.1373722207637 8.0 130 0 Open ; +PIPE-116805 81807 100219 97.1969617953315 12.0 130 0 Open ; +PIPE-116888 113962 113855 179.9510541374449 8.0 130 0 Open ; +PIPE-117739 106341 108072 298.6651970649376 6.0 130 0 Open ; +PIPE-117786 101502 93896 35.769528172305606 8.0 130 0 Open ; +PIPE-117791 105663 114255 134.63017075481227 8.0 130 0 Open ; +PIPE-117892 92966 80704 417.31434076837957 12.0 130 0 Open ; +PIPE-117933 103415 109976 318.30862265755246 12.0 130 0 Open ; +PIPE-117956 74384 114287 296.2132123354749 6.0 130 0 Open ; +PIPE-118224 111895 111849 11.600426391263829 8.0 130 0 Open ; +PIPE-118420 111198 110557 334.8884791789637 6.0 130 0 Open ; +PIPE-118707 73713 113307 47.25474378752285 6.0 130 0 Open ; +PIPE-118725 76650 90420 6.917744085086813 6.0 130 0 Open ; +PIPE-119193 94071 100097 1.2545450527826594 8.0 130 0 Open ; +PIPE-119283 114255 108898 310.6435263648527 8.0 130 0 Open ; +PIPE-119477 106861 71423 67.21404125741702 12.0 130 0 Open ; +PIPE-119528 102797 113687 20.60967548535361 8.0 130 0 Open ; +PIPE-119583 99391 107231 37.187855859306886 6.0 130 0 Open ; +PIPE-119650 108008 110263 187.75636345917889 8.0 130 0 Open ; +PIPE-119656 77754 109576 221.27855428123547 8.0 130 0 Open ; +PIPE-119668 95385 110433 6.979676185103246 6.0 130 0 Open ; +PIPE-119832 114287 90111 56.826602024401396 6.0 130 0 Open ; +PIPE-119871 110434 114734 53.389684011190866 6.0 130 0 Open ; +PIPE-191185 88285 85718 7.885360634699314 12.0 130 0 Open ; +PIPE-191522 113687 85902 12.57142661859409 8.0 130 0 Open ; + +[PUMPS] +;ID Node1 Node2 Parameters + +[CURVES] +;ID X-Value Y-Value +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers + +[CONTROLS] + + + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0:30 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] \ No newline at end of file diff --git a/benchmarks/small/ky7.inp b/benchmarks/small/ky7.inp new file mode 100755 index 0000000..8f732cd --- /dev/null +++ b/benchmarks/small/ky7.inp @@ -0,0 +1,2992 @@ +[TITLE] + + +[JUNCTIONS] +;ID Elev Demand Pattern + J-1 455.9993 2.8 1 ; + J-10 595.1784 0 ; + J-100 524.5092 5.39 1 ; + J-101 596.9546 2.12 1 ; + J-102 590.1794 1.22 1 ; + J-103 587.8557 0.61 1 ; + J-104 509.5502 1.57 1 ; + J-105 501.7983 0.85 1 ; + J-106 518.8116 1.38 1 ; + J-107 492.4018 1.42 1 ; + J-109 486.3669 1.61 1 ; + J-11 508.9102 8.11 1 ; + J-110 482.9622 3.26 1 ; + J-111 464.0534 2.91 1 ; + J-112 480.0848 3.19 1 ; + J-113 484.5578 3.49 1 ; + J-114 522.0294 1.81 1 ; + J-115 500.6847 0.76 1 ; + J-116 526.5716 2.09 1 ; + J-117 582.5688 2.01 1 ; + J-118 532.9451 2.42 1 ; + J-119 448.1282 1.36 1 ; + J-12 485.0004 10.13 1 ; + J-120 507.4623 1.62 1 ; + J-121 540.0488 8.19 1 ; + J-122 516.4416 3.12 1 ; + J-123 508.3246 0.5 1 ; + J-124 518.9949 2.27 1 ; + J-125 598.2817 0 ; + J-126 457.644 1.33 1 ; + J-127 498.5753 0.86 1 ; + J-128 491.4736 2.63 1 ; + J-129 444.638 1.57 1 ; + J-13 495.8325 1.7 1 ; + J-130 442 0.73 1 ; + J-131 526.585 2.29 1 ; + J-132 479.0093 2.82 1 ; + J-133 469.3847 0.5 1 ; + J-134 451.9946 0.39 1 ; + J-135 491.2834 1.83 1 ; + J-136 513.3248 6.08 1 ; + J-137 560.774 4.91 1 ; + J-138 496.6935 0 ; + J-139 518.2602 0.86 1 ; + J-14 500.893 1.86 1 ; + J-140 481.1981 2.48 1 ; + J-141 484.4633 1.8 1 ; + J-142 502.3007 1.85 1 ; + J-143 509.9977 0.61 1 ; + J-145 471.8571 0.44 1 ; + J-146 481.9362 1.85 1 ; + J-149 459.9394 10.7 1 ; + J-15 525.4294 8.23 1 ; + J-150 470.337 4.54 1 ; + J-151 511.761 9.42 1 ; + J-152 576.5399 4.45 1 ; + J-153 514.6708 0.72 1 ; + J-154 577.6719 6.69 1 ; + J-155 581.6533 0.51 1 ; + J-159 522.4083 1.91 1 ; + J-16 525.9792 2.99 1 ; + J-160 528.1484 0.94 1 ; + J-163 532.8851 0.93 1 ; + J-164 539.1323 3.25 1 ; + J-165 466.0002 2.65 1 ; + J-166 461.4258 4.02 1 ; + J-167 501.1688 2.33 1 ; + J-168 513.3461 3.05 1 ; + J-169 502.0866 1.49 1 ; + J-17 508.5245 3.48 1 ; + J-170 468.8607 0.97 1 ; + J-171 472.7928 1.07 1 ; + J-172 504.8509 0.8 1 ; + J-173 502.808 0.41 1 ; + J-174 500.4205 2.07 1 ; + J-175 502.6548 1.15 1 ; + J-176 514.5234 14.5 1 ; + J-177 501.0704 14.8 1 ; + J-178 508.4932 0.87 1 ; + J-179 480 1.34 1 ; + J-18 495.4805 2.22 1 ; + J-180 479.987 1.77 1 ; + J-181 516.3846 1.45 1 ; + J-182 510.2406 1.27 1 ; + J-183 510.0078 0.8 1 ; + J-184 505.1692 3.34 1 ; + J-185 507.4666 1.49 1 ; + J-186 498.4245 1.99 1 ; + J-187 497.0519 1.23 1 ; + J-188 537.1629 0.24 1 ; + J-189 539.3553 1.19 1 ; + J-19 451.4271 2.48 1 ; + J-190 528.1495 2.14 1 ; + J-191 469.3718 2.18 1 ; + J-192 484.5555 1.2 1 ; + J-193 559.3116 1.35 1 ; + J-194 570.1228 0.28 1 ; + J-195 490.7295 0.85 1 ; + J-196 494.2793 3.03 1 ; + J-197 501.5159 0.51 1 ; + J-198 512.6523 1.83 1 ; + J-199 466.0287 0.86 1 ; + J-2 478.9985 5.8 1 ; + J-20 469.1313 2.22 1 ; + J-200 462.1439 1.59 1 ; + J-201 509.6591 0.9 1 ; + J-202 496.2192 0.84 1 ; + J-203 502.6068 2.41 1 ; + J-204 510.6372 2.12 1 ; + J-205 488.3963 2.44 1 ; + J-206 481.4232 1.24 1 ; + J-207 518.3533 12.12 1 ; + J-208 528.9981 0.99 1 ; + J-209 484 0.97 1 ; + J-21 527.0889 2.47 1 ; + J-210 491.4746 0.55 1 ; + J-213 575.1281 1.82 1 ; + J-214 581.0258 0.28 1 ; + J-215 516.9788 1 1 ; + J-216 484.554 1.81 1 ; + J-217 481.1604 1.98 1 ; + J-218 479.0001 1.26 1 ; + J-219 482.7389 1.56 1 ; + J-22 492.0377 2.28 1 ; + J-220 538.1606 2.79 1 ; + J-221 569.4635 6.81 1 ; + J-222 502.0962 1.1 1 ; + J-223 480.5506 0.92 1 ; + J-224 472.7624 1.88 1 ; + J-225 471.6321 2.37 1 ; + J-226 475.1904 1.33 1 ; + J-227 490 0.77 1 ; + J-228 489.4911 1.29 1 ; + J-229 498.0078 1.85 1 ; + J-23 490.1721 0.76 1 ; + J-230 521.9763 0.78 1 ; + J-231 521.9881 0.33 1 ; + J-232 502.0344 13.12 1 ; + J-233 504.5677 1.57 1 ; + J-234 510.4407 1.2 1 ; + J-235 506.1234 0.4 1 ; + J-236 500.3952 2.62 1 ; + J-237 510.8809 1.47 1 ; + J-238 477.675 1.82 1 ; + J-239 501.4544 0.54 1 ; + J-24 481.6824 3.07 1 ; + J-240 491.8328 4.56 1 ; + J-241 481 0.73 1 ; + J-242 481.225 0.42 1 ; + J-243 481 0.93 1 ; + J-244 482.9984 2.2 1 ; + J-245 482.9207 4.15 1 ; + J-246 495.1471 2.3 1 ; + J-247 524.8229 2.57 1 ; + J-248 520.8935 3.29 1 ; + J-249 509.3695 1.01 1 ; + J-25 568.0386 3.46 1 ; + J-250 481.6129 1.08 1 ; + J-251 483.9978 1.12 1 ; + J-252 493 3.46 1 ; + J-253 491.4134 4.89 1 ; + J-254 449.0851 2.48 1 ; + J-255 492.5444 0 ; + J-256 489.3675 0 ; + J-257 492.1461 1.69 1 ; + J-258 574.8646 0.61 1 ; + J-259 579.3059 1.02 1 ; + J-26 560.9025 1.88 1 ; + J-260 513.7104 3.34 1 ; + J-261 496.2522 3.29 1 ; + J-262 485.4243 1.67 1 ; + J-263 477.4413 2.28 1 ; + J-264 474.2711 1.8 1 ; + J-265 496.0786 3.7 1 ; + J-266 485.8466 1.98 1 ; + J-267 485.8361 1.42 1 ; + J-268 498.4509 2.99 1 ; + J-269 497.4185 1.53 1 ; + J-27 494.9632 3.13 1 ; + J-270 497.7462 6.26 1 ; + J-271 507.7723 4.49 1 ; + J-272 499.3048 3.64 1 ; + J-273 495.6205 1.16 1 ; + J-274 488.7503 1.26 1 ; + J-275 504.1435 2.22 1 ; + J-276 507.6058 0.86 1 ; + J-277 518.8781 2.75 1 ; + J-278 524.0801 4.03 1 ; + J-279 512.6635 0.43 1 ; + J-28 458.5122 3.05 1 ; + J-281 521.4147 1.87 1 ; + J-282 519.5876 3.22 1 ; + J-283 499.8236 0.68 1 ; + J-284 496.0324 1.33 1 ; + J-285 494.5862 1.64 1 ; + J-286 493.2452 1.15 1 ; + J-287 485.4213 2.96 1 ; + J-288 488.0925 1.41 1 ; + J-289 478 1.13 1 ; + J-29 506.9205 2.97 1 ; + J-290 508.765 0.78 1 ; + J-291 513.9404 1.31 1 ; + J-292 519.4761 2.39 1 ; + J-293 521.6347 0.39 1 ; + J-294 480.276 1.55 1 ; + J-295 461.5843 7.9 1 ; + J-296 491.015 2.81 1 ; + J-297 501.4336 1.62 1 ; + J-298 558.7437 0.41 1 ; + J-299 498.1978 1.75 1 ; + J-3 464.8073 6.68 1 ; + J-30 609.4363 0.19 1 ; + J-300 511.3123 1.59 1 ; + J-301 474.8772 0 ; + J-304 471.7538 2.9 1 ; + J-305 466.7338 3.07 1 ; + J-306 548.8678 2.06 1 ; + J-307 554.0214 0.54 1 ; + J-308 502.2219 0 ; + J-309 488.7215 1.49 1 ; + J-31 444.0782 3.9 1 ; + J-310 490.7023 3.89 1 ; + J-311 529.0698 3.59 1 ; + J-312 487.6328 0.88 1 ; + J-313 503.101 2.76 1 ; + J-314 503.8253 2.32 1 ; + J-315 508.989 1.93 1 ; + J-316 472.0821 1.62 1 ; + J-317 467.0691 2.73 1 ; + J-318 472.9484 1.97 1 ; + J-319 515.3685 2.51 1 ; + J-32 498.9131 8.78 1 ; + J-320 522.8976 3.26 1 ; + J-321 462.4562 0.62 1 ; + J-322 480.5464 2.13 1 ; + J-323 518.7606 11.35 1 ; + J-324 490.0733 0.75 1 ; + J-325 492.6802 0.83 1 ; + J-326 490 0.83 1 ; + J-327 486.5356 1.8 1 ; + J-328 495.8007 1.38 1 ; + J-329 438.3787 1.14 1 ; + J-33 475.1818 2.69 1 ; + J-330 507.1313 2.73 1 ; + J-331 501.497 3.72 1 ; + J-332 508.4567 1.51 1 ; + J-333 483.9486 1.95 1 ; + J-334 526.2042 1.48 1 ; + J-335 532.6345 1.41 1 ; + J-336 466.3337 1.84 1 ; + J-337 498.3394 0.62 1 ; + J-338 551.8472 1.39 1 ; + J-339 574.1849 1.08 1 ; + J-34 518.5588 1.16 1 ; + J-340 528.9781 4.87 1 ; + J-341 481.6297 0.72 1 ; + J-342 534.0692 2.47 1 ; + J-343 489.8181 2.15 1 ; + J-344 488.2337 1 1 ; + J-345 470.0639 2.25 1 ; + J-346 469.9374 3.54 1 ; + J-347 475.3846 2.84 1 ; + J-348 547.2335 1.17 1 ; + J-349 508.129 3.38 1 ; + J-35 509.302 2.38 1 ; + J-350 509.3872 0.89 1 ; + J-351 471.0427 2.34 1 ; + J-352 495.0651 1.85 1 ; + J-353 478.2367 0.88 1 ; + J-355 530.8107 1.96 1 ; + J-356 482.4141 1.52 1 ; + J-357 480.9397 0 ; + J-358 480.9402 3.25 1 ; + J-359 502.0011 2.07 1 ; + J-36 448.4345 4.55 1 ; + J-360 500.7264 1.8 1 ; + J-361 506.4985 1.59 1 ; + J-362 502.0006 1.31 1 ; + J-363 499.1425 2.33 1 ; + J-364 503.2437 0.67 1 ; + J-365 513.3711 0.43 1 ; + J-366 463 0.84 1 ; + J-367 490.8905 2.41 1 ; + J-368 490.93 0.77 1 ; + J-369 493.9485 2.3 1 ; + J-37 547.561 4.36 1 ; + J-370 481.8642 0.73 1 ; + J-371 483.0338 1.29 1 ; + J-372 478.0858 3.53 1 ; + J-373 506.9422 8.21 1 ; + J-374 490.83 1.78 1 ; + J-375 507.9999 2.12 1 ; + J-376 515.4537 0.94 1 ; + J-377 487.1313 0.69 1 ; + J-378 480.3527 3.62 1 ; + J-379 490.1904 1.45 1 ; + J-38 607.4169 6.48 1 ; + J-380 538.087 5.82 1 ; + J-381 542.3325 5.59 1 ; + J-382 481.2118 0.39 1 ; + J-383 502.3597 1.72 1 ; + J-384 541.9366 1.59 1 ; + J-385 548.9761 5.35 1 ; + J-386 524.0029 0.56 1 ; + J-389 476.6302 2.31 1 ; + J-39 525.2971 2.6 1 ; + J-390 487.0836 2.23 1 ; + J-391 467.1523 0.86 1 ; + J-392 476.5407 1.72 1 ; + J-393 497.392 5.17 1 ; + J-394 488.0978 2.18 1 ; + J-395 497.7795 2.01 1 ; + J-396 490.5647 2.01 1 ; + J-399 483.3183 0 ; + J-4 458.7631 0.91 1 ; + J-40 589.3142 2.45 1 ; + J-400 481.3831 0 ; + J-401 518.4275 0 ; + J-402 518.58 0 ; + J-403 509.3106 1.18 1 ; + J-404 477.9795 1.16 1 ; + J-405 500.3975 2.76 1 ; + J-407 486.074 0.96 1 ; + J-408 479.3506 1.43 1 ; + J-409 472.4832 1.52 1 ; + J-41 473.098 1.98 1 ; + J-410 594.5468 0.56 1 ; + J-411 490.1539 1.84 1 ; + J-412 504.9463 0.68 1 ; + J-413 588.7702 1.52 1 ; + J-414 552.341 0.89 1 ; + J-415 473.5639 0.67 1 ; + J-416 486.827 0.9 1 ; + J-417 525.3533 0.65 1 ; + J-418 460.2465 0.46 1 ; + J-42 475.9804 3.08 1 ; + J-421 477.2951 1.16 1 ; + J-422 486.0984 1.62 1 ; + J-423 450.5235 0.76 1 ; + J-424 474.9283 0.98 1 ; + J-425 512.1717 2.07 1 ; + J-426 482.1189 0.71 1 ; + J-427 483.981 0.82 1 ; + J-428 479.8727 0.49 1 ; + J-429 515.4822 1.21 1 ; + J-43 596.8589 3.49 1 ; + J-430 529.1633 0 ; + J-431 484.9331 2.79 1 ; + J-432 544.171 0.96 1 ; + J-433 470.4881 1.07 1 ; + J-434 481.0371 4.94 1 ; + J-435 483.9914 1.09 1 ; + J-436 508.8152 0.46 1 ; + J-437 499.4956 2.92 1 ; + J-438 486.9981 1.35 1 ; + J-439 486.8324 1.49 1 ; + J-44 512.27 2.44 1 ; + J-440 540.5227 0.45 1 ; + J-441 524.4695 1.47 1 ; + J-442 567.1469 1.04 1 ; + J-443 558.5177 3.71 1 ; + J-444 596.4774 3.59 1 ; + J-445 479.2007 2.16 1 ; + J-446 480.1219 2.81 1 ; + J-447 496.9023 0.61 1 ; + J-448 491.8542 3.1 1 ; + J-449 547.8398 0.49 1 ; + J-45 534.9763 1.73 1 ; + J-450 474.2244 1.88 1 ; + J-451 481.451 0.88 1 ; + J-452 548.8386 2.3 1 ; + J-453 462.8346 1.43 1 ; + J-454 524.0289 2.93 1 ; + J-455 579.3934 3.8 1 ; + J-456 570.6416 2.44 1 ; + J-457 490.7882 0 ; + J-458 494.9143 4.31 1 ; + J-459 549.727 0.39 1 ; + J-46 520.6902 2.55 1 ; + J-460 496.4661 1.02 1 ; + J-461 478.0045 0.61 1 ; + J-462 518.8717 0.93 1 ; + J-463 511.8604 1.63 1 ; + J-464 500.9794 3.39 1 ; + J-465 489.8635 2.52 1 ; + J-466 481.8074 2.81 1 ; + J-467 497.4941 1.59 1 ; + J-468 479.8872 1.34 1 ; + J-469 475.0601 3.41 1 ; + J-47 487.5859 0 ; + J-470 502.7264 1.8 1 ; + J-471 497.0363 1.82 1 ; + J-472 564.6595 2.12 1 ; + J-473 480.9905 0.6 1 ; + J-474 463.0974 0.96 1 ; + J-475 478.1137 1.49 1 ; + J-476 546.3054 0.68 1 ; + J-477 471.8116 2.78 1 ; + J-48 484.6961 1.02 1 ; + J-480 546.97 1.77 1 ; + J-481 546.7557 0.44 1 ; + J-482 546.3155 1.34 1 ; + J-483 476.8362 0.73 1 ; + J-484 481.6585 0.86 1 ; + J-485 422.2466 2.03 1 ; + J-486 505.9986 1.83 1 ; + J-487 468.2568 2.78 1 ; + J-489 488.0002 1.8 1 ; + J-49 555.9262 2.74 1 ; + J-490 544.4709 1.09 1 ; + J-491 527.7111 0.62 1 ; + J-492 440.9033 1.54 1 ; + J-493 499.1115 2.04 1 ; + J-494 511.8824 1.34 1 ; + J-495 488.6389 2.11 1 ; + J-496 486.0899 1.04 1 ; + J-497 500.6081 2.29 1 ; + J-498 536.9547 1.18 1 ; + J-499 532.8607 1.7 1 ; + J-5 462.6719 1.78 1 ; + J-50 497.7022 2.18 1 ; + J-500 569.5358 1.3 1 ; + J-501 518.7972 0.78 1 ; + J-502 502.8119 1.17 1 ; + J-503 526.1456 0.33 1 ; + J-504 526.7564 2.15 1 ; + J-507 574.7755 2.92 1 ; + J-51 511.7838 2.87 1 ; + J-52 518.7493 3.08 1 ; + J-53 514.88 0.52 1 ; + J-54 499.978 2.92 1 ; + J-55 517.971 4.14 1 ; + J-56 501.0215 0.88 1 ; + J-57 609.3941 1.53 1 ; + J-58 563.9152 1.59 1 ; + J-59 482.9267 0 ; + J-6 505.4406 0.6 1 ; + J-60 488.8423 3.34 1 ; + J-61 494.0808 0.67 1 ; + J-62 548.4188 3.92 1 ; + J-63 532.6959 3.05 1 ; + J-64 582.2819 1.32 1 ; + J-65 593.1793 1.21 1 ; + J-66 541.706 2.01 1 ; + J-67 592.4525 1.65 1 ; + J-68 560.7532 4.74 1 ; + J-69 532.494 3.13 1 ; + J-70 578.8301 3.62 1 ; + J-71 560.0139 2.61 1 ; + J-72 594.7625 2.1 1 ; + J-73 538.481 2.21 1 ; + J-74 490.0489 2.81 1 ; + J-75 489.0844 3.42 1 ; + J-76 474.6046 2.36 1 ; + J-77 471.3981 3.77 1 ; + J-78 582.8333 1.03 1 ; + J-79 495.1102 1.25 1 ; + J-8 593.702 0.21 1 ; + J-80 491.5203 2.81 1 ; + J-81 518.2358 1.43 1 ; + J-82 520.1119 1.54 1 ; + J-83 545.0627 1.39 1 ; + J-84 489.7787 2.54 1 ; + J-85 513.5375 0.76 1 ; + J-86 565.179 1.89 1 ; + J-87 519.58 2.94 1 ; + J-88 499.2278 0.38 1 ; + J-89 499.6834 1.03 1 ; + J-9 517.8172 1.97 1 ; + J-90 501.7362 0.34 1 ; + J-91 499.168 4.47 1 ; + J-92 510.9476 6.6 1 ; + J-93 421.1141 4.14 1 ; + J-94 505.6865 20.33 1 ; + J-95 427.0432 16.62 1 ; + J-96 491.0535 2.47 1 ; + J-97 569.1588 1.18 1 ; + J-98 568.0916 0.91 1 ; + J-99 507.0185 2.46 1 ; + O-Pump-1 379.7485 0 ; + I-Pump-1 379.7485 0 ; + +[RESERVOIRS] +;ID Head Pattern + R-1 352 ; + T-1 532 133 118 158 65 0 ; + T-2 566.1183 123.8817 109.8817 126.8817 78 0 ; + T-3 622.8533 97.14667 92.14667 117.1467 58 0 ; + +[TANKS] +;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve + + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status + P-1 J-1 J-2 1765.51 8 150 0 Open ; + P-10 J-15 J-16 559.77 4 150 0 Open ; + P-100 J-69 J-17 455.019 8 150 0 Open ; + P-101 J-45 J-107 643.549 12 150 0 Open ; + P-102 J-140 J-59 738.4 6 150 0 Open ; + P-103 J-141 J-77 485.73 2 150 0 Open ; + P-104 J-142 J-120 351.07 6 150 0 Open ; + P-105 J-104 J-44 325.309 6 150 0 Open ; + P-106 J-107 J-143 406.459 6 150 0 Open ; + P-107 J-40 T-2 635.979 16 150 0 Open ; + P-108 J-145 J-146 335.07 8 150 0 Open ; + P-109 O-Pump-1 J-401 55784.769 16 150 0 Open ; + P-11 J-17 J-6 814.09 8 150 0 Open ; + P-110 J-149 J-150 755.75 4 150 0 Open ; + P-111 J-151 J-149 5471.009 4 150 0 Open ; + P-113 J-150 J-152 1861.8 4 150 0 Open ; + P-114 J-14 J-9 377.38 10 150 0 Open ; + P-115 J-14 J-153 665.88 8 140 0 Open ; + P-116 J-154 J-155 350.22 8 150 0 Open ; + P-119 J-159 J-160 763.58 6 150 0 Open ; + P-12 J-19 J-20 464.549 6 150 0 Open ; + P-120 R-1 I-Pump-1 618.39 16 150 0 Open ; + P-121 J-163 J-164 418.17 6 150 0 Open ; + P-122 J-165 J-166 447.309 6 150 0 Open ; + P-123 J-167 J-168 573.64 4 150 0 Open ; + P-124 J-50 J-142 898.07 8 150 0 Open ; + P-125 J-169 J-79 416.42 6 150 0 Open ; + P-126 J-170 J-171 172.25 4 150 0 Open ; + P-127 J-172 J-173 82.4 6 150 0 Open ; + P-128 J-174 J-175 80.75 4 150 0 Open ; + P-129 J-176 J-177 899.95 4 150 0 Open ; + P-13 J-21 J-22 2455 10 150 0 Open ; + P-130 J-167 J-178 262.26 8 150 0 Open ; + P-131 J-179 J-180 416.76 6 150 0 Open ; + P-132 J-175 J-181 504.019 4 150 0 Open ; + P-133 J-182 J-183 91.209 8 150 0 Open ; + P-134 J-184 J-185 732.299 6 150 0 Open ; + P-135 J-186 J-187 78.389 4 150 0 Open ; + P-136 J-188 J-189 73.75 6 150 0 Open ; + P-137 J-190 J-189 553.109 6 150 0 Open ; + P-138 J-191 J-171 187.22 10 150 0 Open ; + P-139 J-192 J-179 319.91 16 150 0 Open ; + P-14 J-23 J-24 179.99 2 150 0 Open ; + P-140 J-193 J-194 114.62 6 150 0 Open ; + P-141 J-195 J-196 181.38 6 150 0 Open ; + P-142 J-197 J-198 209.979 4 150 0 Open ; + P-143 J-199 J-200 251.44 8 150 0 Open ; + P-144 J-201 J-499 340.95 6 150 0 Open ; + P-145 J-190 J-193 662.32 6 150 0 Open ; + P-146 J-202 J-203 326.089 4 150 0 Open ; + P-147 J-178 J-204 162.729 8 150 0 Open ; + P-148 J-205 J-206 264.73 4 150 0 Open ; + P-149 J-73 J-71 453.64 6 150 0 Open ; + P-15 J-25 J-26 1516.569 8 150 0 Open ; + P-150 J-207 J-208 740.539 6 150 0 Open ; + P-151 J-192 J-209 328.5 8 150 0 Open ; + P-152 J-55 J-87 377.269 4 150 0 Open ; + P-153 J-99 J-136 1142.39 6 150 0 Open ; + P-154 J-210 J-202 72.76 4 150 0 Open ; + P-157 J-67 T-2 859.65 12 150 0 Open ; + P-158 J-213 J-214 117.919 6 150 0 Open ; + P-159 J-207 J-215 249.8 2 150 0 Open ; + P-16 J-6 J-18 530.08 8 150 0 Open ; + P-160 J-216 J-217 249.259 4 150 0 Open ; + P-161 J-57 J-66 1180.569 12 150 0 Open ; + P-162 J-218 J-219 394.35 4 150 0 Open ; + P-163 J-220 J-221 1035.819 10 150 0 Open ; + P-164 J-173 J-222 58.15 4 150 0 Open ; + P-165 J-223 J-224 368.7 4 150 0 Open ; + P-166 J-225 J-226 1260.28 10 150 0 Open ; + P-167 J-227 J-228 279.649 8 150 0 Open ; + P-168 J-87 J-229 501.57 2 150 0 Open ; + P-169 J-142 J-172 637.89 8 150 0 Open ; + P-17 J-8 J-125 61.59 12 150 0 Open ; + P-170 J-230 J-231 36.09 8 150 0 Open ; + P-171 J-232 J-29 81.25 10 150 0 Open ; + P-172 J-233 J-234 563.789 8 150 0 Open ; + P-173 J-178 J-235 390.679 16 150 0 Open ; + P-174 J-60 J-236 737.739 4 150 0 Open ; + P-175 J-237 J-74 408.47 6 150 0 Open ; + P-176 J-238 J-171 203.47 4 150 0 Open ; + P-177 J-196 J-239 282.47 6 150 0 Open ; + P-178 J-56 J-240 764.38 10 150 0 Open ; + P-179 J-241 J-223 161.979 8 150 0 Open ; + P-18 J-31 J-32 879.679 10 150 0 Open ; + P-180 J-165 J-224 410.709 6 150 0 Open ; + P-181 J-176 J-177 7074.25 4 150 0 Open ; + P-182 J-191 J-170 81.849 4 150 0 Open ; + P-183 J-189 J-193 281.769 6 150 0 Open ; + P-184 J-191 J-165 1518.25 10 150 0 Open ; + P-185 J-242 J-192 351.42 16 150 0 Open ; + P-186 J-243 J-244 345.19 4 150 0 Open ; + P-187 J-245 J-246 402.109 2 150 0 Open ; + P-188 J-247 J-248 327.709 4 150 0 Open ; + P-189 J-81 J-249 331.73 6 150 0 Open ; + P-19 J-24 J-33 355.88 2 150 0 Open ; + P-190 J-250 J-251 307.45 8 150 0 Open ; + P-191 J-252 J-253 270.97 2 150 0 Open ; + P-192 J-254 J-36 1425.239 6 150 0 Open ; + P-193 J-255 J-256 138.85 16 150 0 Open ; + P-194 J-75 J-257 330.64 6 150 0 Open ; + P-195 J-137 J-258 259.07 6 150 0 Open ; + P-196 J-26 J-259 258.35 6 150 0 Open ; + P-197 J-248 J-260 397.89 4 150 0 Open ; + P-198 J-12 J-261 784.94 8 150 0 Open ; + P-199 J-262 J-245 281.079 4 150 0 Open ; + P-2 J-3 J-4 896.049 8 150 0 Open ; + P-20 J-34 J-35 507.799 4 150 0 Open ; + P-200 J-263 J-264 81.819 6 150 0 Open ; + P-201 J-265 J-50 391.869 8 150 0 Open ; + P-202 J-266 J-267 98.29 10 150 0 Open ; + P-203 J-268 J-269 404.98 2 150 0 Open ; + P-204 J-221 J-270 2317.909 10 150 0 Open ; + P-205 J-271 J-182 82.059 8 150 0 Open ; + P-206 J-272 J-75 461.07 2 150 0 Open ; + P-207 J-273 J-274 264.39 6 150 0 Open ; + P-208 J-169 J-275 343.649 6 150 0 Open ; + P-209 J-185 J-276 125.66 8 150 0 Open ; + P-21 J-36 J-19 1593.8 6 150 0 Open ; + P-210 J-146 J-109 501.619 8 150 0 Open ; + P-211 J-277 J-278 879.669 6 150 0 Open ; + P-212 J-279 J-233 240.149 8 150 0 Open ; + P-213 T-3 J-8 512.09 12 150 0 Open ; + P-214 J-281 J-282 876.369 6 150 0 Open ; + P-215 J-257 J-283 310.369 4 150 0 Open ; + P-216 J-284 J-246 169.449 4 150 0 Open ; + P-217 J-285 J-74 342.239 4 150 0 Open ; + P-218 J-286 J-135 147.52 4 150 0 Open ; + P-219 J-287 J-288 267.79 2 150 0 Open ; + P-22 J-37 J-10 1109.469 6 150 0 Open ; + P-220 J-179 J-289 243.08 16 150 0 Open ; + P-221 J-290 J-291 553.5 6 150 0 Open ; + P-222 J-292 J-293 111.989 8 150 0 Open ; + P-223 J-231 J-34 80.16 4 150 0 Open ; + P-224 J-294 J-76 373.26 6 150 0 Open ; + P-225 J-232 J-295 3427.659 3 150 0 Open ; + P-226 J-277 J-278 1047.229 6 150 0 Open ; + P-227 J-32 J-232 1290.01 10 150 0 Open ; + P-228 J-180 J-296 598.83 4 150 0 Open ; + P-229 J-1 J-200 635.969 8 150 0 Open ; + P-23 J-39 J-40 1538.78 16 150 0 Open ; + P-230 J-285 J-75 406.459 6 150 0 Open ; + P-231 J-203 J-297 567.359 6 150 0 Open ; + P-232 J-137 J-68 2291.649 8 150 0 Open ; + P-233 J-213 J-298 228.5 6 150 0 Open ; + P-234 J-299 J-300 806.34 6 150 0 Open ; + P-235 J-266 J-301 1662.199 10 150 0 Open ; + P-237 J-304 J-305 1091.77 4 150 0 Open ; + P-238 J-306 J-307 340.739 6 150 0 Open ; + P-239 J-308 J-237 233.619 6 150 0 Open ; + P-24 J-41 J-42 538.159 2 150 0 Open ; + P-240 J-309 J-310 438.5 4 150 0 Open ; + P-241 J-311 J-86 1145.069 6 150 0 Open ; + P-242 J-312 J-228 241.44 4 150 0 Open ; + P-243 J-265 J-313 601.2 6 150 0 Open ; + P-244 J-314 J-315 305.04 6 150 0 Open ; + P-245 J-111 J-316 534.109 4 150 0 Open ; + P-246 J-264 J-317 790.96 8 150 0 Open ; + P-247 J-318 J-166 339.109 4 150 0 Open ; + P-248 J-277 J-319 368.95 6 150 0 Open ; + P-249 J-246 J-113 287.38 4 150 0 Open ; + P-25 J-25 J-43 2391.26 8 150 0 Open ; + P-250 J-221 J-94 1644.729 3 150 0 Open ; + P-251 J-238 J-294 507.6 6 150 0 Open ; + P-252 J-278 J-320 1501.81 6 150 0 Open ; + P-253 J-275 J-268 293.399 2 150 0 Open ; + P-254 J-199 J-321 417.45 6 150 0 Open ; + P-255 J-110 J-322 456 6 150 0 Open ; + P-256 J-207 J-323 9114.169 6 150 0 Open ; + P-257 J-324 J-325 189.179 6 150 0 Open ; + P-258 J-326 J-227 164.889 8 150 0 Open ; + P-259 J-327 J-328 328.22 4 150 0 Open ; + P-26 J-44 J-45 1076.719 6 150 0 Open ; + P-260 J-236 J-222 79.72 4 150 0 Open ; + P-261 J-250 J-244 281.859 4 150 0 Open ; + P-262 J-261 J-260 1067.06 6 150 0 Open ; + P-263 J-313 J-136 1508.729 6 150 0 Open ; + P-264 J-36 J-329 288.07 2 150 0 Open ; + P-265 J-313 J-330 247.619 8 150 0 Open ; + P-266 J-310 J-252 281.309 2 150 0 Open ; + P-267 J-15 J-331 1147.109 4 150 0 Open ; + P-268 J-249 J-332 77.809 6 150 0 Open ; + P-269 J-284 J-331 447.44 4 150 0 Open ; + P-27 J-39 J-46 838.94 4 150 0 Open ; + P-270 J-310 J-333 417.14 4 150 0 Open ; + P-271 J-68 J-213 1133.969 6 150 0 Open ; + P-272 J-276 J-230 704.979 8 150 0 Open ; + P-273 J-301 J-165 749.14 10 150 0 Open ; + P-274 J-334 J-335 196.11 8 150 0 Open ; + P-275 J-336 J-199 29.319 8 150 0 Open ; + P-276 J-132 J-146 353.109 6 150 0 Open ; + P-277 J-337 J-268 138.02 2 150 0 Open ; + P-278 J-338 J-339 319.019 6 150 0 Open ; + P-279 J-312 J-274 251.19 6 150 0 Open ; + P-28 J-47 J-48 510.82 4 150 0 Open ; + P-280 J-340 J-63 477.929 8 150 0 Open ; + P-281 J-132 J-341 332.04 4 150 0 Open ; + P-282 J-259 J-258 153.559 6 150 0 Open ; + P-283 J-340 J-342 683.21 2 150 0 Open ; + P-284 J-184 J-343 433.54 4 150 0 Open ; + P-285 J-26 J-137 187.61 8 150 0 Open ; + P-287 J-266 J-344 166.97 8 150 0 Open ; + P-288 J-177 J-324 368.79 6 150 0 Open ; + P-289 J-257 J-186 751.809 8 150 0 Open ; + P-29 J-49 J-16 1907.589 8 150 0 Open ; + P-290 J-345 J-346 320.39 2 150 0 Open ; + P-291 J-245 J-347 293.25 4 150 0 Open ; + P-292 J-348 J-220 895.059 6 150 0 Open ; + P-293 J-182 J-159 829.03 6 150 0 Open ; + P-294 J-113 J-184 450 4 150 0 Open ; + P-295 J-349 J-291 524.659 8 150 0 Open ; + P-296 J-347 J-113 403.119 4 150 0 Open ; + P-297 J-173 J-239 56.9 6 150 0 Open ; + P-298 J-350 J-233 647.75 6 150 0 Open ; + P-299 J-317 J-351 245.949 8 150 0 Open ; + P-3 J-3 J-5 1432.439 6 150 0 Open ; + P-30 J-50 J-51 554.489 4 150 0 Open ; + P-300 J-146 J-238 343.54 4 150 0 Open ; + P-301 J-352 J-353 319.709 3 150 0 Open ; + P-303 J-18 J-265 1092.479 8 150 0 Open ; + P-304 J-17 J-355 1594.349 6 150 0 Open ; + P-305 J-203 J-198 311.829 2 150 0 Open ; + P-306 J-209 J-326 626.64 8 150 0 Open ; + P-307 J-356 J-110 330.88 8 150 0 Open ; + P-308 J-357 J-308 1147.54 16 150 0 Open ; + P-309 J-358 J-205 1084.969 4 150 0 Open ; + P-31 J-52 J-53 186.61 4 150 0 Open ; + P-310 J-234 J-183 664.15 8 150 0 Open ; + P-311 J-359 J-360 82.319 6 150 0 Open ; + P-312 J-270 J-152 1696.41 3 150 0 Open ; + P-313 J-361 J-362 85.199 4 150 0 Open ; + P-314 J-318 J-255 349.45 4 150 0 Open ; + P-315 J-325 J-284 112.87 6 150 0 Open ; + P-316 J-363 J-364 236.729 8 150 0 Open ; + P-317 J-271 J-330 2169.959 8 150 0 Open ; + P-318 J-168 J-365 82.629 2 150 0 Open ; + P-319 J-33 J-262 496.66 8 150 0 Open ; + P-32 J-54 J-55 357.059 2 150 0 Open ; + P-320 J-200 J-366 200.49 2 150 0 Open ; + P-321 J-206 J-318 377.64 4 150 0 Open ; + P-322 J-191 J-76 431.88 4 150 0 Open ; + P-323 J-33 J-346 284.019 3 150 0 Open ; + P-324 J-167 J-287 410.799 6 150 0 Open ; + P-325 J-84 J-367 387.579 2 150 0 Open ; + P-326 J-368 J-262 170.149 4 150 0 Open ; + P-327 J-55 J-369 633.32 2 150 0 Open ; + P-328 J-249 J-185 464.22 8 150 0 Open ; + P-329 J-370 J-371 102.47 6 150 0 Open ; + P-33 J-56 J-13 294.13 10 150 0 Open ; + P-330 J-112 J-372 407.66 6 150 0 Open ; + P-331 J-84 J-195 438.41 6 150 0 Open ; + P-332 J-308 J-255 369.82 16 150 0 Open ; + P-333 J-267 J-344 97.16 4 150 0 Open ; + P-334 J-347 J-372 404.41 4 150 0 Open ; + P-335 J-12 J-373 1196.589 6 150 0 Open ; + P-336 J-317 J-316 279.519 4 150 0 Open ; + P-337 J-374 J-272 954.15 4 150 0 Open ; + P-338 J-375 J-376 360.589 6 150 0 Open ; + P-339 J-377 J-312 31.45 6 150 0 Open ; + P-34 J-57 J-10 200.679 10 150 0 Open ; + P-340 J-248 J-378 1693.93 6 150 0 Open ; + P-341 J-379 J-272 183.789 4 150 0 Open ; + P-342 J-380 J-381 782.419 8 150 0 Open ; + P-343 J-382 J-242 281.39 16 150 0 Open ; + P-344 J-356 J-383 470.959 4 150 0 Open ; + P-345 J-164 J-384 423.6 2 150 0 Open ; + P-346 J-15 J-385 2638.04 4 150 0 Open ; + P-347 J-322 J-383 428.059 6 150 0 Open ; + P-348 J-386 J-323 358.029 6 150 0 Open ; + P-349 J-225 J-132 1206.89 6 150 0 Open ; + P-35 J-59 J-47 1566.64 16 150 0 Open ; + P-351 J-336 J-170 447.989 8 150 0 Open ; + P-352 J-361 J-360 301.489 8 150 0 Open ; + P-353 J-360 J-266 581.7 8 150 0 Open ; + P-354 J-389 J-390 232.82 6 150 0 Open ; + P-355 J-391 J-392 231.979 4 150 0 Open ; + P-356 J-187 J-393 262.869 4 150 0 Open ; + P-357 J-394 J-395 1508.689 10 150 0 Open ; + P-358 J-260 J-314 776.489 4 150 0 Open ; + P-359 J-396 J-174 233.169 4 150 0 Open ; + P-36 J-60 J-61 304.829 4 150 0 Open ; + P-361 J-399 J-400 854.95 16 150 0 Open ; + P-362 J-305 J-166 632.63 4 150 0 Open ; + P-363 J-314 J-373 303.489 4 150 0 Open ; + P-364 J-328 J-273 172.75 6 150 0 Open ; + P-365 J-401 J-402 325.579 16 150 0 Open ; + P-366 J-322 J-389 244.009 6 150 0 Open ; + P-367 J-390 J-27 871.89 6 150 0 Open ; + P-368 J-331 J-184 509.97 4 150 0 Open ; + P-369 J-293 J-39 164.72 8 150 0 Open ; + P-37 J-62 J-63 1826.67 8 150 0 Open ; + P-370 J-403 J-237 345.92 4 150 0 Open ; + P-371 J-287 J-404 418.739 6 150 0 Open ; + P-372 J-37 J-49 763.179 8 150 0 Open ; + P-373 J-405 J-389 504.859 6 150 0 Open ; + P-375 J-42 J-304 184.22 4 150 0 Open ; + P-376 J-407 J-394 776.45 10 150 0 Open ; + P-377 J-408 J-409 318.309 4 150 0 Open ; + P-378 J-259 J-410 699.989 6 150 0 Open ; + P-379 J-409 J-347 485.579 4 150 0 Open ; + P-38 J-22 J-13 675.95 10 140 0 Open ; + P-380 J-238 J-226 143.1 6 150 0 Open ; + P-381 J-358 J-47 395.559 4 150 0 Open ; + P-382 J-411 J-360 474.73 4 150 0 Open ; + P-383 J-244 J-216 307.07 4 150 0 Open ; + P-384 J-315 J-375 328.35 6 150 0 Open ; + P-385 J-379 J-285 263.049 4 150 0 Open ; + P-386 J-262 J-325 396.38 8 150 0 Open ; + P-387 J-330 J-412 622.7 8 150 0 Open ; + P-388 J-240 J-271 2859.55 8 150 0 Open ; + P-389 J-323 J-401 441.809 6 150 0 Open ; + P-39 J-64 J-65 708.599 10 150 0 Open ; + P-390 J-38 J-413 619.26 2 150 0 Open ; + P-391 J-335 J-414 652.28 6 150 0 Open ; + P-392 J-316 J-415 94.589 8 150 0 Open ; + P-393 J-416 J-210 154.85 4 150 0 Open ; + P-394 J-376 J-417 344.1 6 150 0 Open ; + P-395 J-418 J-391 182.389 4 150 0 Open ; + P-397 J-421 J-254 634.02 6 150 0 Open ; + P-398 J-422 J-217 289.119 6 150 0 Open ; + P-399 J-423 J-424 360.769 4 150 0 Open ; + P-4 J-10 J-58 844.989 10 150 0 Open ; + P-40 J-66 J-67 1805.29 12 150 0 Open ; + P-400 J-425 J-168 201.35 2 150 0 Open ; + P-401 J-216 J-179 551.08 8 150 0 Open ; + P-402 J-426 J-427 247.949 8 150 0 Open ; + P-403 J-352 J-403 258.89 4 150 0 Open ; + P-404 J-251 J-216 277.67 8 150 0 Open ; + P-405 J-428 J-241 215.38 8 150 0 Open ; + P-406 J-315 J-429 312.82 2 150 0 Open ; + P-407 J-430 J-399 2730.709 16 150 0 Open ; + P-408 J-431 J-389 618.919 4 150 0 Open ; + P-409 J-381 J-432 256.6 8 150 0 Open ; + P-41 J-68 J-69 1611.969 8 150 0 Open ; + P-410 J-334 J-380 520.07 8 150 0 Open ; + P-411 J-422 J-309 345.359 4 150 0 Open ; + P-412 J-433 J-434 812.84 6 150 0 Open ; + P-413 J-435 J-192 284.839 4 150 0 Open ; + P-414 J-110 J-263 654.539 4 150 0 Open ; + P-415 J-436 J-39 564.299 16 150 0 Open ; + P-416 J-428 J-243 165.11 16 150 0 Open ; + P-417 J-359 J-437 309.44 6 150 0 Open ; + P-418 J-252 J-438 418.179 4 150 0 Open ; + P-419 J-256 J-363 289.239 8 150 0 Open ; + P-42 J-70 J-71 1303.01 6 150 0 Open ; + P-420 J-371 J-427 105.55 6 150 0 Open ; + P-421 J-217 J-439 350.41 4 150 0 Open ; + P-422 J-83 J-440 173.699 4 150 0 Open ; + P-423 J-81 J-441 177.119 8 150 0 Open ; + P-424 J-343 J-112 456.119 6 150 0 Open ; + P-425 J-291 J-279 85.91 8 150 0 Open ; + P-426 J-344 J-377 353.89 8 150 0 Open ; + P-427 J-441 J-37 629.65 8 150 0 Open ; + P-428 J-372 J-371 792.479 6 150 0 Open ; + P-429 J-417 J-247 92.97 6 150 0 Open ; + P-43 J-38 J-72 859.07 3 150 0 Open ; + P-430 J-442 J-443 260.019 2 150 0 Open ; + P-431 J-390 J-176 716.27 6 150 0 Open ; + P-432 J-140 J-42 466.519 4 150 0 Open ; + P-433 J-393 J-437 592.96 2 150 0 Open ; + P-435 J-152 J-444 1465.77 3 150 0 Open ; + P-436 J-286 J-177 444.309 4 150 0 Open ; + P-437 J-405 J-247 1034.92 4 150 0 Open ; + P-438 J-379 J-352 476.22 6 150 0 Open ; + P-439 J-445 J-446 359.94 2 150 0 Open ; + P-44 J-70 J-73 1368.51 6 150 0 Open ; + P-440 J-373 J-154 7304.799 8 150 0 Open ; + P-441 J-396 J-447 286.97 8 150 0 Open ; + P-442 J-448 J-174 408.17 2 150 0 Open ; + P-443 J-378 J-356 342.7 8 150 0 Open ; + P-444 J-432 J-449 224.279 8 150 0 Open ; + P-445 J-363 J-450 510.25 2 150 0 Open ; + P-446 J-451 J-370 251.05 8 150 0 Open ; + P-447 J-335 J-116 416.869 8 150 0 Open ; + P-448 J-311 J-452 634.229 2 150 0 Open ; + P-449 J-383 J-405 172.21 4 150 0 Open ; + P-45 J-74 J-75 778.02 6 150 0 Open ; + P-450 J-336 J-453 379.269 2 150 0 Open ; + P-451 J-402 J-430 297.82 16 150 0 Open ; + P-452 J-454 J-240 2149.75 10 150 0 Open ; + P-453 J-439 J-252 433.57 4 150 0 Open ; + P-454 J-328 J-169 280.769 4 150 0 Open ; + P-455 J-455 J-456 674.849 2 150 0 Open ; + P-456 J-457 J-458 3687.389 6 150 0 Open ; + P-457 J-65 J-455 846.15 10 150 0 Open ; + P-458 J-47 J-357 272.57 16 150 0 Open ; + P-459 J-235 J-436 184.059 16 150 0 Open ; + P-46 J-76 J-77 617.299 4 150 0 Open ; + P-460 J-187 J-362 297.059 4 150 0 Open ; + P-461 J-448 J-204 458.04 2 150 0 Open ; + P-462 J-459 J-338 281.14 8 150 0 Open ; + P-463 J-427 J-422 291.989 6 150 0 Open ; + P-464 J-447 J-460 257.38 8 150 0 Open ; + P-465 J-461 J-289 84.19 4 150 0 Open ; + P-466 J-344 J-227 146.729 4 150 0 Open ; + P-467 J-181 J-462 154.919 6 150 0 Open ; + P-468 J-15 J-334 842.979 8 150 0 Open ; + P-469 J-297 J-463 349.959 8 150 0 Open ; + P-47 J-43 J-78 1030.06 8 150 0 Open ; + P-470 J-304 J-358 344.72 4 150 0 Open ; + P-471 J-91 J-464 2862.669 6 150 0 Open ; + P-473 J-465 J-167 301.029 4 150 0 Open ; + P-474 J-370 J-408 290.75 8 150 0 Open ; + P-475 J-466 J-399 61.279 6 150 0 Open ; + P-476 J-467 J-468 263.75 6 150 0 Open ; + P-477 J-469 J-140 623.469 6 150 0 Open ; + P-478 J-470 J-471 494.339 4 150 0 Open ; + P-479 J-472 J-220 355.019 10 150 0 Open ; + P-48 J-79 J-80 105.129 6 150 0 Open ; + P-480 J-253 J-465 417.359 2 150 0 Open ; + P-481 J-241 J-473 299 8 150 0 Open ; + P-482 J-217 J-445 274.609 4 150 0 Open ; + P-483 J-364 J-467 226.009 6 150 0 Open ; + P-484 J-204 J-181 314.63 8 150 0 Open ; + P-485 J-253 J-287 284.48 2 150 0 Open ; + P-487 J-415 J-451 509.45 8 150 0 Open ; + P-488 J-112 J-333 391.25 4 150 0 Open ; + P-489 J-168 J-292 568.39 4 150 0 Open ; + P-49 J-35 J-81 445.07 4 150 0 Open ; + P-490 J-288 J-178 422 16 150 0 Open ; + P-491 J-351 J-345 304.769 4 150 0 Open ; + P-492 J-351 J-33 326.529 8 150 0 Open ; + P-493 J-20 J-466 1371.27 6 150 0 Open ; + P-494 J-455 J-472 331.92 10 150 0 Open ; + P-495 J-457 J-138 941.71 16 150 0 Open ; + P-496 J-474 J-469 469.899 4 150 0 Open ; + P-497 J-198 J-425 77.33 2 150 0 Open ; + P-498 J-219 J-288 400.679 16 150 0 Open ; + P-499 J-466 J-475 926.349 6 150 0 Open ; + P-5 J-2 J-3 4901.1 8 150 0 Open ; + P-50 J-82 J-62 1231.069 6 150 0 Open ; + P-500 J-443 J-306 333.839 2 150 0 Open ; + P-501 J-270 J-119 1142.03 10 150 0 Open ; + P-502 J-320 J-282 958.09 6 150 0 Open ; + P-503 J-476 J-83 37.49 8 150 0 Open ; + P-504 J-264 J-477 265.91 6 150 0 Open ; + P-505 J-251 J-422 250.27 8 150 0 Open ; + P-506 J-332 J-343 663.2 6 150 0 Open ; + P-507 J-226 J-171 237.229 10 150 0 Open ; + P-508 J-32 J-92 1085.819 3 150 0 Open ; + P-509 J-319 J-402 1824.189 8 150 0 Open ; + P-51 J-83 J-62 982.929 8 150 0 Open ; + P-510 J-380 J-381 1347.209 2 150 0 Open ; + P-511 J-372 J-310 394.04 2 150 0 Open ; + P-513 J-346 J-245 486.35 2 150 0 Open ; + P-514 J-109 J-294 352.329 6 150 0 Open ; + P-515 J-425 J-463 573.95 4 150 0 Open ; + P-516 J-480 J-163 277.26 6 150 0 Open ; + P-517 J-481 J-83 40.939 4 150 0 Open ; + P-518 J-281 J-320 294.72 6 150 0 Open ; + P-519 J-395 J-454 1223.589 10 150 0 Open ; + P-52 J-80 J-84 56.919 6 150 0 Open ; + P-520 J-164 J-482 349.899 2 150 0 Open ; + P-521 J-319 J-281 347.63 6 150 0 Open ; + P-522 J-462 J-190 537.78 6 150 0 Open ; + P-523 J-469 J-483 213.449 4 150 0 Open ; + P-524 J-451 J-484 98.83 8 150 0 Open ; + P-525 J-426 J-251 296.059 8 150 0 Open ; + P-526 J-274 J-84 466.95 6 150 0 Open ; + P-527 J-385 J-481 124.339 4 150 0 Open ; + P-528 J-267 J-407 105.12 10 150 0 Open ; + P-53 J-35 J-85 180.94 2 150 0 Open ; + P-530 J-470 J-364 47.9 6 150 0 Open ; + P-531 J-333 J-416 250.27 4 150 0 Open ; + P-532 J-407 J-377 178.41 6 150 0 Open ; + P-533 J-244 J-435 269.839 4 150 0 Open ; + P-534 J-385 J-449 33.509 6 150 0 Open ; + P-535 J-416 J-438 32.139 4 150 0 Open ; + P-536 J-445 J-461 188.82 4 150 0 Open ; + P-537 J-477 J-317 718.46 4 150 0 Open ; + P-539 J-74 J-470 438.01 4 150 0 Open ; + P-54 J-86 J-70 398.79 6 150 0 Open ; + P-540 J-434 J-485 2219.34 8 150 0 Open ; + P-541 J-484 J-426 101.44 8 150 0 Open ; + P-542 J-467 J-486 519.69 4 150 0 Open ; + P-543 J-393 J-52 1510.959 4 150 0 Open ; + P-544 J-438 J-465 255.779 4 150 0 Open ; + P-545 J-263 J-111 542.83 4 150 0 Open ; + P-546 J-446 J-253 424.94 2 150 0 Open ; + P-547 J-468 J-411 520.15 4 150 0 Open ; + P-548 J-332 J-297 615.919 8 150 0 Open ; + P-549 J-135 J-368 194.029 4 150 0 Open ; + P-55 J-51 J-87 267.529 4 150 0 Open ; + P-550 J-124 J-349 1047.689 4 150 0 Open ; + P-551 J-256 J-301 657.169 16 150 0 Open ; + P-552 J-455 J-339 504.049 6 150 0 Open ; + P-553 J-487 J-400 2320.58 6 150 0 Open ; + P-554 J-301 J-428 176.35 16 150 0 Open ; + P-556 J-71 J-385 420.23 6 150 0 Open ; + P-557 J-475 J-421 257.589 6 150 0 Open ; + P-558 J-431 J-351 697.059 4 150 0 Open ; + P-559 J-489 J-60 329.269 4 150 0 Open ; + P-56 J-88 J-54 66.879 2 150 0 Open ; + P-560 J-484 J-392 314.779 4 150 0 Open ; + P-561 J-218 J-289 271.179 6 150 0 Open ; + P-562 J-490 J-63 827.679 6 150 0 Open ; + P-563 J-394 J-327 71.54 6 150 0 Open ; + P-564 J-486 J-361 466.14 4 150 0 Open ; + P-565 J-296 J-396 451.739 4 150 0 Open ; + P-566 J-243 J-382 272.75 16 150 0 Open ; + P-567 J-483 J-424 125.93 4 150 0 Open ; + P-568 J-491 J-454 416.44 6 150 0 Open ; + P-569 J-463 J-292 241.039 8 150 0 Open ; + P-57 J-89 J-90 218.479 8 150 0 Open ; + P-570 J-186 J-361 292.26 8 150 0 Open ; + P-571 J-282 J-430 875.309 6 150 0 Open ; + P-572 J-359 J-267 575.039 4 150 0 Open ; + P-573 J-273 J-79 455.23 6 150 0 Open ; + P-574 J-322 J-477 624.21 6 150 0 Open ; + P-575 J-492 J-469 410.549 2 150 0 Open ; + P-576 J-110 J-264 676.979 8 150 0 Open ; + P-577 J-400 J-457 305.779 16 150 0 Open ; + P-578 J-292 J-46 579.469 4 150 0 Open ; + P-579 J-275 J-299 616.2 6 150 0 Open ; + P-58 J-91 J-89 99.069 8 150 0 Open ; + P-580 J-473 J-250 230.63 8 150 0 Open ; + P-581 J-477 J-431 241.49 4 150 0 Open ; + P-582 J-449 J-476 108.44 8 150 0 Open ; + P-583 J-327 J-349 590.619 4 150 0 Open ; + P-584 J-471 J-186 486.859 4 150 0 Open ; + P-585 J-196 J-493 1113.239 4 150 0 Open ; + P-586 J-340 J-434 2359.29 8 150 0 Open ; + P-587 J-494 J-375 348.17 2 150 0 Open ; + P-588 J-180 J-218 111.16 6 150 0 Open ; + P-589 J-296 J-60 515.53 4 150 0 Open ; + P-59 J-92 J-93 1767.39 3 150 0 Open ; + P-590 J-404 J-289 364.94 6 150 0 Open ; + P-591 J-495 J-367 278.369 4 150 0 Open ; + P-592 J-496 J-495 260.45 2 150 0 Open ; + P-593 J-300 J-497 472.91 6 150 0 Open ; + P-594 J-498 J-472 757.38 6 150 0 Open ; + P-595 J-408 J-345 288.079 4 150 0 Open ; + P-596 J-437 J-394 355.42 6 150 0 Open ; + P-597 J-497 J-265 1416.219 6 150 0 Open ; + P-598 J-228 J-489 289.359 4 150 0 Open ; + P-599 J-236 J-499 637.369 4 150 0 Open ; + P-6 T-1 J-9 1148.78 10 140 0 Open ; + P-60 J-51 J-54 394.679 2 150 0 Open ; + P-600 J-362 J-359 298.709 4 150 0 Open ; + P-601 J-443 J-500 337.91 2 150 0 Open ; + P-602 J-441 J-501 561.21 6 150 0 Open ; + P-603 J-404 J-219 274.47 16 150 0 Open ; + P-604 J-472 J-338 567.169 6 150 0 Open ; + P-605 J-219 J-396 533.419 8 150 0 Open ; + P-606 J-489 J-495 352.39 4 150 0 Open ; + P-607 J-367 J-196 278.98 4 150 0 Open ; + P-61 J-94 J-95 7288.6 3 150 0 Open ; + P-610 J-222 J-118 637.349 6 150 0 Open ; + P-611 J-460 J-502 383.14 4 150 0 Open ; + P-612 J-261 J-378 1493.819 8 150 0 Open ; + P-613 J-432 J-443 351.649 6 150 0 Open ; + P-614 J-476 J-306 351 6 150 0 Open ; + P-615 J-116 J-480 1154.13 6 150 0 Open ; + P-616 J-224 J-392 566.289 6 150 0 Open ; + P-617 J-502 J-201 213.559 4 150 0 Open ; + P-618 J-503 J-498 207.039 8 150 0 Open ; + P-619 J-499 J-118 79.739 6 150 0 Open ; + P-62 J-31 J-96 1366.349 4 150 0 Open ; + P-620 J-504 J-27 1768.209 6 150 0 Open ; + P-621 J-29 J-507 3558.419 8 150 0 Open ; + P-623 J-28 J-126 690.14 4 150 0 Open ; + P-624 J-30 J-57 27.059 12 150 0 Open ; + P-625 J-125 J-30 87.959 12 150 0 Open ; + P-63 J-58 J-64 616.739 10 150 0 Open ; + P-64 J-97 J-98 224.199 2 150 0 Open ; + P-65 J-99 J-100 897.51 6 150 0 Open ; + P-66 J-101 J-102 919.809 6 150 0 Open ; + P-67 J-101 J-103 402.69 6 150 0 Open ; + P-68 J-104 J-105 308.079 3 150 0 Open ; + P-69 J-49 J-58 379.57 8 150 0 Open ; + P-7 J-38 J-10 1566.9 6 150 0 Open ; + P-70 J-106 J-69 1089.699 6 150 0 Open ; + P-71 J-107 J-6 785.21 12 150 0 Open ; + P-72 J-109 J-110 742.7 8 150 0 Open ; + P-73 J-77 J-111 550.549 4 150 0 Open ; + P-74 J-112 J-113 415.119 2 150 0 Open ; + P-75 J-114 J-21 958.869 10 150 0 Open ; + P-76 J-89 J-115 713.7 8 150 0 Open ; + P-77 J-16 J-116 161.47 4 150 0 Open ; + P-78 J-117 J-100 1641.829 6 150 0 Open ; + P-79 J-40 J-118 1724.319 8 150 0 Open ; + P-8 J-11 J-12 9310.61 8 150 0 Open ; + P-80 J-119 J-31 633.159 10 150 0 Open ; + P-81 J-120 J-104 322.76 6 150 0 Open ; + P-82 J-64 J-97 231.399 6 150 0 Open ; + P-83 J-121 J-122 2627.56 6 150 0 Open ; + P-84 J-123 J-124 202.71 4 150 0 Open ; + P-85 J-91 J-114 1182.55 8 150 0 Open ; + P-86 J-28 J-166 1012.789 4 150 0 Open ; + P-87 J-43 J-101 390.44 6 150 0 Open ; + P-88 J-120 J-127 309.97 3 150 0 Open ; + P-89 J-128 J-80 1463.089 4 150 0 Open ; + P-9 J-13 J-14 1306.41 10 150 0 Open ; + P-90 J-129 J-130 511.89 6 150 0 Open ; + P-91 J-121 J-131 628.409 2 150 0 Open ; + P-92 J-132 J-133 301.709 6 150 0 Open ; + P-93 J-129 J-134 205.72 6 150 0 Open ; + P-94 J-24 J-135 488.7 3 150 0 Open ; + P-95 J-136 J-121 2595.939 6 150 0 Open ; + P-96 J-100 J-137 2093.34 6 150 0 Open ; + P-97 J-1 J-129 541.179 6 150 0 Open ; + P-98 J-59 J-138 1307.78 16 150 0 Open ; + P-99 J-44 J-139 311.179 3 150 0 Open ; + +[PUMPS] +;ID Node1 Node2 Parameters + ~@Pump-1 I-Pump-1 O-Pump-1 POWER 100 ; + +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers +; + 1 1 +; + 11 1 +; (ID specified in pipe2000 water quality data window + MAXPatternID) + 2 1 +; + ENRG1 1 + +[CURVES] +;ID X-Value Y-Value + +[CONTROLS] + + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0 + Global Pattern ENRG1 + Demand Charge 0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk 0 + Global Wall 0 + Limiting Potential 0 + Roughness Correlation 0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0 + Hydraulic Timestep 1:00 + Quality Timestep 0:30 + Pattern Timestep 1:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Full + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1 + Viscosity 1 + Trials 100 + Accuracy 0.0001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Trace R-1 + Diffusivity 0.05 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + J-1 4299642.16 3566592.00 + J-10 4301005.25 3574618.00 + J-100 4294926.11 3577174.00 + J-101 4296473.21 3580861.00 + J-102 4296340.54 3579952.00 + J-103 4296071.89 3580828.00 + J-104 4296628.04 3573338.00 + J-105 4296361.26 3573492.00 + J-106 4295806.97 3575791.00 + J-107 4296849.11 3574818.00 + J-109 4300787.20 3568227.00 + J-11 4310571.91 3561389.00 + J-110 4301349.49 3568712.00 + J-111 4300459.49 3569508.00 + J-112 4300239.24 3571498.00 + J-113 4300606.30 3571304.00 + J-114 4287585.02 3570572.00 + J-115 4286240.89 3569852.00 + J-116 4302404.41 3572937.00 + J-117 4293555.97 3577946.00 + J-118 4297151.82 3572787.00 + J-119 4303938.85 3582664.00 + J-12 4303984.30 3567610.00 + J-120 4296458.08 3573064.00 + J-121 4292192.90 3574494.00 + J-122 4289621.82 3574351.00 + J-123 4294849.82 3570389.00 + J-124 4294828.29 3570545.00 + J-125 4300793.08 3574742.00 + J-126 4299187.49 3567245.00 + J-127 4296204.85 3573243.00 + J-128 4295566.92 3572698.00 + J-129 4299525.35 3566064.00 + J-13 4291174.54 3570070.00 + J-130 4299019.68 3566144.00 + J-131 4292437.94 3574056.00 + J-132 4301004.26 3567665.00 + J-133 4300926.16 3567374.00 + J-134 4299480.94 3565863.00 + J-135 4301231.99 3570506.00 + J-136 4294701.42 3575156.00 + J-137 4295118.38 3579226.00 + J-138 4296496.42 3564877.00 + J-139 4296513.94 3573768.00 + J-14 4290812.63 3571249.00 + J-140 4297589.34 3566605.00 + J-141 4300650.90 3568788.00 + J-142 4296258.08 3572775.00 + J-143 4297027.86 3575183.00 + J-145 4300574.98 3567418.00 + J-146 4300659.61 3567742.00 + J-149 4302542.31 3583173.00 + J-15 4301982.76 3572352.00 + J-150 4302688.16 3582457.00 + J-151 4302837.76 3588307.00 + J-152 4302430.09 3580672.00 + J-153 4290330.88 3570812.00 + J-154 4311198.87 3565616.00 + J-155 4311545.02 3565669.00 + J-159 4293868.37 3571158.00 + J-16 4302308.98 3572806.00 + J-160 4293904.26 3571049.00 + J-163 4303219.44 3574110.00 + J-164 4302878.52 3574342.00 + J-165 4298931.27 3569088.00 + J-166 4298718.53 3568694.00 + J-167 4299162.24 3572091.00 + J-168 4299455.64 3572584.00 + J-169 4296266.48 3571089.00 + J-17 4296579.39 3575512.00 + J-170 4299962.51 3567919.00 + J-171 4300128.97 3567875.00 + J-172 4296761.97 3572384.00 + J-173 4296716.24 3572316.00 + J-174 4298226.88 3571994.00 + J-175 4298269.69 3572062.00 + J-176 4301930.47 3570224.00 + J-177 4301602.29 3570805.00 + J-178 4298939.17 3572229.00 + J-179 4298477.30 3570828.00 + J-18 4295820.55 3574403.00 + J-180 4298277.60 3571082.00 + J-181 4298538.51 3572489.00 + J-182 4294042.50 3571850.00 + J-183 4294117.38 3571798.00 + J-184 4300836.17 3571691.00 + J-185 4301214.69 3572318.00 + J-186 4296748.56 3569822.00 + J-187 4296677.47 3569855.00 + J-188 4299022.45 3573477.00 + J-189 4298958.22 3573513.00 + J-19 4296657.58 3562608.00 + J-190 4298683.53 3573033.00 + J-191 4299987.21 3567997.00 + J-192 4298317.17 3570551.00 + J-193 4298710.58 3573648.00 + J-194 4298611.29 3573705.00 + J-195 4296413.97 3571892.00 + J-196 4296518.11 3572040.00 + J-197 4299589.90 3572263.00 + J-198 4299696.26 3572444.00 + J-199 4299851.80 3567455.00 + J-2 4300939.98 3565428.00 + J-20 4296274.94 3562872.00 + J-200 4299793.20 3567210.00 + J-201 4297471.66 3572513.00 + J-202 4299804.79 3572007.00 + J-203 4299967.25 3572290.00 + J-204 4298801.32 3572316.00 + J-205 4298116.67 3568290.00 + J-206 4298243.69 3568522.00 + J-207 4300238.70 3556341.00 + J-208 4300203.59 3555602.00 + J-209 4298031.00 3570712.00 + J-21 4288525.64 3570396.00 + J-210 4299768.55 3571944.00 + J-213 4297082.31 3578120.00 + J-214 4296968.84 3578146.00 + J-215 4300484.15 3556295.00 + J-216 4298955.05 3570553.00 + J-217 4299070.78 3570774.00 + J-218 4298351.22 3571164.00 + J-219 4298538.25 3571511.00 + J-22 4290816.60 3569745.00 + J-220 4302615.35 3577330.00 + J-221 4303103.90 3579306.00 + J-222 4296763.21 3572281.00 + J-223 4298787.72 3569609.00 + J-224 4299120.64 3569452.00 + J-225 4301122.60 3566755.00 + J-226 4300279.56 3567691.00 + J-227 4297341.82 3571101.00 + J-228 4297095.34 3571233.00 + J-229 4296266.13 3574341.00 + J-23 4301140.72 3569982.00 + J-230 4301851.99 3572315.00 + J-231 4301874.86 3572343.00 + J-232 4305465.94 3586761.00 + J-233 4295073.25 3571463.00 + J-234 4294607.42 3571780.00 + J-235 4299129.69 3572570.00 + J-236 4296826.66 3572233.00 + J-237 4297738.51 3568822.00 + J-238 4300326.66 3567827.00 + J-239 4296680.68 3572271.00 + J-24 4300990.19 3570081.00 + J-240 4291927.79 3569963.00 + J-241 4298748.03 3569725.00 + J-242 4298146.52 3570244.00 + J-243 4298635.96 3569984.00 + J-244 4298804.27 3570285.00 + J-245 4300665.48 3570814.00 + J-246 4300858.86 3571167.00 + J-247 4303069.39 3569048.00 + J-248 4303081.96 3568722.00 + J-249 4300812.32 3572549.00 + J-25 4294271.61 3580649.00 + J-250 4299050.73 3570149.00 + J-251 4299198.01 3570418.00 + J-252 4299452.98 3571458.00 + J-253 4299217.04 3571591.00 + J-254 4296437.85 3562214.00 + J-255 4298114.34 3569025.00 + J-256 4298102.94 3569163.00 + J-257 4296604.92 3569188.00 + J-258 4295347.23 3579348.00 + J-259 4295259.53 3579474.00 + J-26 4295017.18 3579384.00 + J-260 4303479.33 3568702.00 + J-261 4303218.79 3567703.00 + J-262 4300915.43 3570686.00 + J-263 4300836.74 3569118.00 + J-264 4300892.84 3569177.00 + J-265 4295218.53 3573492.00 + J-266 4297306.16 3570857.00 + J-267 4297215.27 3570894.00 + J-268 4296148.55 3571519.00 + J-269 4295808.36 3571738.00 + J-27 4302650.02 3569513.00 + J-270 4303663.06 3581555.00 + J-271 4293975.24 3571897.00 + J-272 4296909.46 3568653.00 + J-273 4296561.03 3571117.00 + J-274 4296807.70 3571212.00 + J-275 4295979.63 3571279.00 + J-276 4301323.86 3572255.00 + J-277 4295670.15 3559676.00 + J-278 4296405.18 3559685.00 + J-279 4295271.25 3571327.00 + J-28 4299278.56 3567926.00 + J-281 4295386.85 3560186.00 + J-282 4294642.51 3560552.00 + J-283 4296452.49 3568917.00 + J-284 4301009.30 3571089.00 + J-285 4297210.37 3568767.00 + J-286 4301360.48 3570433.00 + J-287 4298968.23 3571729.00 + J-288 4298734.62 3571860.00 + J-289 4298593.03 3571041.00 + J-29 4305394.87 3586800.00 + J-290 4294988.02 3570870.00 + J-291 4295342.33 3571279.00 + J-292 4299730.31 3573082.00 + J-293 4299633.39 3573138.00 + J-294 4300447.76 3568319.00 + J-295 4308551.11 3587728.00 + J-296 4297807.80 3571453.00 + J-297 4300241.94 3572786.00 + J-298 4297302.17 3578062.00 + J-299 4295469.37 3571624.00 + J-3 4300231.33 3560589.00 + J-30 4300802.24 3574655.00 + J-300 4294801.73 3572076.00 + J-301 4298475.81 3569683.00 + J-304 4297905.62 3567174.00 + J-305 4298423.85 3568135.00 + J-306 4304315.23 3573673.00 + J-307 4304137.59 3573963.00 + J-308 4297937.78 3568700.00 + J-309 4299482.04 3570942.00 + J-31 4304095.56 3583277.00 + J-310 4299699.46 3571323.00 + J-311 4304180.90 3570065.00 + J-312 4296974.32 3571024.00 + J-313 4294737.49 3573851.00 + J-314 4304255.00 3568666.00 + J-315 4304191.58 3568964.00 + J-316 4300168.07 3569915.00 + J-317 4300396.48 3569753.00 + J-318 4298420.24 3568856.00 + J-319 4295340.89 3559841.00 + J-32 4304449.78 3584714.00 + J-320 4295429.28 3560478.00 + J-321 4299444.73 3567547.00 + J-322 4301573.91 3569108.00 + J-323 4293896.34 3560113.00 + J-324 4301274.19 3570944.00 + J-325 4301107.16 3571032.00 + J-326 4297484.32 3571018.00 + J-327 4296298.12 3570707.00 + J-328 4296511.46 3570952.00 + J-329 4297107.95 3561092.00 + J-33 4300677.00 3570250.00 + J-330 4294621.38 3573632.00 + J-331 4301282.14 3571443.00 + J-332 4300775.50 3572480.00 + J-333 4299898.16 3571689.00 + J-334 4302806.73 3572509.00 + J-335 4302743.30 3572694.00 + J-336 4299858.31 3567483.00 + J-337 4296262.77 3571441.00 + J-338 4301961.45 3577019.00 + J-339 4301946.15 3576700.00 + J-34 4301805.04 3572382.00 + J-340 4307556.26 3574640.00 + J-341 4301091.51 3567985.00 + J-342 4307656.37 3573965.00 + J-343 4300455.99 3571899.00 + J-344 4297275.89 3570970.00 + J-345 4300268.06 3570112.00 + J-346 4300429.36 3570389.00 + J-347 4300407.32 3570953.00 + J-348 4301721.61 3577378.00 + J-349 4295776.43 3570984.00 + J-35 4301358.24 3572623.00 + J-350 4294699.85 3570934.00 + J-351 4300530.89 3569958.00 + J-352 4297457.78 3568286.00 + J-353 4297309.17 3568003.00 + J-355 4295028.13 3575144.00 + J-356 4301621.65 3568524.00 + J-357 4297389.06 3567692.00 + J-358 4297600.98 3567335.00 + J-359 4296958.18 3570381.00 + J-36 4296842.12 3561198.00 + J-360 4297031.80 3570344.00 + J-361 4296893.35 3570076.00 + J-362 4296818.47 3570117.00 + J-363 4297868.14 3569332.00 + J-364 4297667.56 3569458.00 + J-365 4299386.73 3572630.00 + J-366 4299596.81 3567250.00 + J-367 4296735.16 3571865.00 + J-368 4301062.63 3570600.00 + J-369 4296638.10 3574323.00 + J-37 4301335.89 3573560.00 + J-370 4299761.11 3570391.00 + J-371 4299671.17 3570441.00 + J-372 4300047.54 3571138.00 + J-373 4304558.41 3568659.00 + J-374 4296582.93 3567757.00 + J-375 4303864.07 3568979.00 + J-376 4303504.79 3569010.00 + J-377 4296995.26 3571001.00 + J-378 4301905.01 3568331.00 + J-379 4297061.76 3568550.00 + J-38 4301373.42 3576133.00 + J-380 4303270.18 3572745.00 + J-381 4303965.99 3573103.00 + J-382 4298392.98 3570108.00 + J-383 4301933.69 3568877.00 + J-384 4302681.29 3574655.00 + J-385 4304409.09 3573289.00 + J-386 4294202.26 3559951.00 + J-389 4301684.96 3569325.00 + J-39 4299493.20 3573225.00 + J-390 4301778.48 3569538.00 + J-391 4299599.74 3569844.00 + J-392 4299392.98 3569949.00 + J-393 4296442.63 3569973.00 + J-394 4296361.59 3570674.00 + J-395 4294901.75 3570294.00 + J-396 4298092.26 3571804.00 + J-399 4295175.69 3563248.00 + J-4 4300112.51 3559701.00 + J-40 4298187.57 3574035.00 + J-400 4295656.22 3563955.00 + J-401 4293538.39 3560323.00 + J-402 4293687.56 3560612.00 + J-403 4297574.65 3568517.00 + J-404 4298768.36 3571361.00 + J-405 4302047.03 3569006.00 + J-407 4297113.62 3570867.00 + J-408 4300015.78 3570251.00 + J-409 4300166.55 3570532.00 + J-41 4298267.31 3566757.00 + J-410 4295842.80 3579817.00 + J-411 4297451.95 3570123.00 + J-412 4294310.71 3573093.00 + J-413 4300895.09 3575740.00 + J-414 4303147.16 3573204.00 + J-415 4300074.09 3569925.00 + J-416 4299682.08 3571816.00 + J-417 4303162.05 3569041.00 + J-418 4299760.93 3569758.00 + J-42 4297814.18 3567014.00 + J-421 4295888.27 3562530.00 + J-422 4299324.24 3570635.00 + J-423 4298542.71 3566463.00 + J-424 4298231.73 3566646.00 + J-425 4299627.35 3572479.00 + J-426 4299456.17 3570274.00 + J-427 4299577.73 3570490.00 + J-428 4298563.48 3569836.00 + J-429 4304139.64 3569273.00 + J-43 4296485.53 3581251.00 + J-430 4293828.76 3560874.00 + J-431 4301140.63 3569620.00 + J-432 4304195.78 3573217.00 + J-433 4309764.47 3576478.00 + J-434 4309674.11 3575671.00 + J-435 4298568.31 3570416.00 + J-436 4299218.51 3572732.00 + J-437 4296680.19 3570517.00 + J-438 4299651.70 3571826.00 + J-439 4299241.43 3571080.00 + J-44 4296788.40 3573621.00 + J-440 4304626.24 3573528.00 + J-441 4301050.08 3572999.00 + J-442 4303785.78 3573404.00 + J-443 4304018.13 3573520.00 + J-444 4301810.27 3579344.00 + J-445 4298831.32 3570908.00 + J-446 4299008.97 3571221.00 + J-447 4297852.36 3571961.00 + J-448 4298571.07 3571920.00 + J-449 4304395.13 3573320.00 + J-45 4297404.30 3574493.00 + J-450 4298114.55 3569779.00 + J-451 4299631.37 3570177.00 + J-452 4304583.70 3569575.00 + J-453 4300199.06 3567317.00 + J-454 4294003.06 3570404.00 + J-455 4302448.85 3576663.00 + J-456 4303121.67 3576611.00 + J-457 4295857.91 3564184.00 + J-458 4292846.50 3565111.00 + J-459 4301680.89 3577037.00 + J-46 4300011.55 3573589.00 + J-460 4297637.85 3572103.00 + J-461 4298666.62 3571000.00 + J-462 4298407.69 3572572.00 + J-463 4299937.07 3572958.00 + J-464 4284998.56 3570524.00 + J-465 4299428.59 3571951.00 + J-466 4295227.06 3563215.00 + J-467 4297783.17 3569652.00 + J-468 4297912.71 3569882.00 + J-469 4298142.79 3566318.00 + J-47 4297232.85 3567468.00 + J-470 4297642.18 3569417.00 + J-471 4297191.55 3569620.00 + J-472 4302527.65 3576986.00 + J-473 4298939.71 3569947.00 + J-474 4298023.31 3565864.00 + J-475 4295663.55 3562656.00 + J-476 4304491.62 3573369.00 + J-477 4301026.10 3569407.00 + J-48 4296726.32 3567533.00 + J-480 4303087.83 3573866.00 + J-481 4304519.55 3573346.00 + J-482 4302599.89 3574517.00 + J-483 4298199.97 3566524.00 + J-484 4299544.93 3570224.00 + J-485 4311781.99 3576246.00 + J-486 4297312.23 3569872.00 + J-487 4297525.76 3562580.00 + J-489 4297237.79 3571485.00 + J-49 4301683.91 3574239.00 + J-490 4307302.08 3573612.00 + J-491 4293794.85 3570698.00 + J-492 4298545.20 3566237.00 + J-493 4296107.00 3572789.00 + J-494 4303879.41 3569327.00 + J-495 4296953.47 3571692.00 + J-496 4296802.34 3571480.00 + J-497 4294404.45 3572333.00 + J-498 4303279.18 3576908.00 + J-499 4297215.29 3572738.00 + J-5 4298825.80 3560865.00 + J-50 4295523.15 3573245.00 + J-500 4303841.75 3573808.00 + J-501 4300580.44 3573298.00 + J-502 4297340.86 3572345.00 + J-503 4303461.96 3576813.00 + J-504 4303547.86 3570260.00 + J-507 4304987.95 3589986.00 + J-51 4295832.60 3573705.00 + J-52 4294977.95 3570052.00 + J-53 4294888.94 3570154.00 + J-54 4296144.86 3573464.00 + J-55 4296325.64 3573772.00 + J-56 4291188.94 3569776.00 + J-57 4300804.80 3574628.00 + J-58 4301849.36 3574580.00 + J-59 4297218.46 3565967.00 + J-6 4296116.25 3574843.00 + J-60 4297401.63 3571771.00 + J-61 4297579.20 3572019.00 + J-62 4305433.16 3573758.00 + J-63 4307138.53 3574408.00 + J-64 4302066.29 3575156.00 + J-65 4302250.57 3575841.00 + J-66 4299977.40 3574099.00 + J-67 4298194.42 3574382.00 + J-68 4296324.73 3577278.00 + J-69 4296834.50 3575889.00 + J-70 4304446.69 3571580.00 + J-71 4304481.34 3572883.00 + J-72 4302189.40 3575864.00 + J-73 4304075.03 3572681.00 + J-74 4297400.88 3569052.00 + J-75 4296877.82 3569001.00 + J-76 4300087.50 3568417.00 + J-77 4300239.76 3569015.00 + J-78 4297455.36 3581524.00 + J-79 4296360.54 3571475.00 + J-8 4300753.11 3574789.00 + J-80 4296449.52 3571531.00 + J-81 4300969.82 3572841.00 + J-82 4305462.61 3574874.00 + J-83 4304524.64 3573387.00 + J-84 4296497.70 3571562.00 + J-85 4301440.86 3572784.00 + J-86 4304435.16 3571182.00 + J-87 4295981.91 3573927.00 + J-88 4296110.99 3573406.00 + J-89 4286307.04 3570556.00 + J-9 4290501.31 3571462.00 + J-90 4286089.59 3570535.00 + J-91 4286405.64 3570566.00 + J-92 4305426.45 3584239.00 + J-93 4306984.10 3584909.00 + J-94 4304585.06 3579977.00 + J-95 4311403.19 3582363.00 + J-96 4303393.68 3584271.00 + J-97 4302289.95 3575097.00 + J-98 4302509.66 3575064.00 + J-99 4294772.45 3576290.00 + O-Pump-1 4248205.67 3541635.00 + I-Pump-1 4248205.67 3541635.00 + R-1 4248378.00 3541041.00 + T-1 4289578.00 3572147.00 + T-2 4297624.00 3573739.00 + T-3 4300380.00 3575141.00 + +[VERTICES] +;Link X-Coord Y-Coord + P-1 4299800.28 3566462.04 + P-1 4300318.22 3566068.71 + P-1 4300602.21 3565850.67 + P-1 4300693.20 3565779.65 + P-1 4300736.06 3565744.03 + P-1 4300775.88 3565705.92 + P-1 4300812.52 3565665.32 + P-1 4300845.42 3565621.64 + P-1 4300875.33 3565575.63 + P-1 4300900.74 3565528.11 + P-1 4300922.14 3565478.59 + P-10 4302286.30 3572776.04 + P-100 4296686.75 3575670.36 + P-101 4297359.61 3574518.42 + P-101 4297281.74 3574565.37 + P-101 4296980.46 3574746.65 + P-102 4297448.36 3566356.79 + P-103 4300609.38 3568823.69 + P-103 4300480.37 3568919.82 + P-103 4300353.13 3569008.91 + P-103 4300275.90 3569004.80 + P-104 4296397.41 3572970.26 + P-105 4296707.67 3573473.95 + P-106 4296968.28 3575052.89 + P-108 4300601.01 3567496.56 + P-108 4300606.21 3567519.97 + P-108 4300614.02 3567543.37 + P-109 4248336.55 3541725.12 + P-109 4248360.85 3543413.56 + P-109 4249045.72 3544444.46 + P-109 4249058.32 3544489.56 + P-109 4249072.19 3544545.83 + P-109 4249126.38 3544620.36 + P-109 4249182.81 3544669.49 + P-109 4249242.58 3544711.37 + P-109 4249336.41 3544771.09 + P-109 4249397.86 3544796.50 + P-109 4249447.00 3544817.14 + P-109 4249482.76 3544848.69 + P-109 4249492.53 3544858.77 + P-109 4249526.04 3544893.35 + P-109 4249545.89 3544917.07 + P-109 4249558.46 3544970.96 + P-109 4249563.54 3545069.54 + P-109 4249560.46 3545139.62 + P-109 4249581.43 3545200.78 + P-109 4249626.13 3545251.59 + P-109 4249636.11 3545255.74 + P-109 4249688.41 3545277.53 + P-109 4249723.25 3545297.04 + P-109 4249751.72 3545312.97 + P-109 4249776.67 3545326.92 + P-109 4249847.05 3545383.60 + P-109 4249867.83 3545405.69 + P-109 4250017.44 3545564.77 + P-109 4250037.29 3545583.10 + P-109 4250139.21 3545665.22 + P-109 4250177.31 3545705.82 + P-109 4250219.20 3545783.26 + P-109 4250257.36 3545953.35 + P-109 4250257.39 3546052.38 + P-109 4250243.45 3546170.45 + P-109 4250215.55 3546252.97 + P-109 4250193.99 3546279.65 + P-109 4250160.90 3546302.20 + P-109 4250107.66 3546338.08 + P-109 4250007.36 3546371.13 + P-109 4249956.62 3546410.47 + P-109 4249869.04 3546498.10 + P-109 4249828.44 3546565.40 + P-109 4249825.92 3546635.24 + P-109 4249848.78 3546721.54 + P-109 4249878.02 3546824.37 + P-109 4249881.86 3546880.24 + P-109 4249877.39 3546926.13 + P-109 4249875.54 3546977.99 + P-109 4249855.24 3547041.47 + P-109 4249826.06 3547094.80 + P-109 4249770.21 3547155.76 + P-109 4249744.84 3547202.32 + P-109 4249737.24 3547252.25 + P-109 4249741.06 3547323.35 + P-109 4249746.17 3547388.10 + P-109 4249796.98 3547490.91 + P-109 4249830.00 3547531.53 + P-109 4249892.22 3547594.98 + P-109 4249965.88 3547685.11 + P-109 4249996.38 3547747.30 + P-109 4250009.09 3547810.76 + P-109 4250005.34 3547955.50 + P-109 4250014.24 3548031.67 + P-109 4250171.69 3548140.81 + P-109 4250517.11 3548519.02 + P-109 4250627.60 3548638.33 + P-109 4250660.62 3548687.84 + P-109 4250692.36 3548755.11 + P-109 4250730.51 3548884.60 + P-109 4250763.57 3549044.53 + P-109 4250781.13 3549191.59 + P-109 4250811.91 3549363.18 + P-109 4250828.46 3549500.29 + P-109 4250838.68 3549731.35 + P-109 4250851.37 3549771.97 + P-109 4250883.13 3549806.23 + P-109 4250925.03 3549827.80 + P-109 4251036.77 3549858.23 + P-109 4251148.49 3549892.47 + P-109 4251281.81 3549954.65 + P-109 4251374.50 3549999.05 + P-109 4251512.91 3550084.07 + P-109 4251562.44 3550125.95 + P-109 4251638.63 3550218.60 + P-109 4251699.61 3550362.05 + P-109 4251732.63 3550428.05 + P-109 4251760.59 3550476.29 + P-109 4251806.31 3550519.44 + P-109 4251874.87 3550557.51 + P-109 4251957.40 3550599.37 + P-109 4252005.66 3550633.63 + P-109 4252037.40 3550675.51 + P-109 4252051.37 3550699.64 + P-109 4252078.07 3550793.57 + P-109 4252086.98 3550900.21 + P-109 4252087.24 3551024.29 + P-109 4252093.62 3551085.24 + P-109 4252105.05 3551129.68 + P-109 4252219.41 3551427.98 + P-109 4252375.62 3551605.44 + P-109 4252621.95 3551728.74 + P-109 4252797.15 3551778.20 + P-109 4252867.78 3551799.49 + P-109 4252931.74 3551818.78 + P-109 4253034.58 3551847.95 + P-109 4253169.73 3551892.79 + P-109 4253251.22 3551912.67 + P-109 4254244.19 3552186.02 + P-109 4254501.93 3552260.85 + P-109 4254834.57 3552358.49 + P-109 4255112.63 3552440.94 + P-109 4255691.96 3552607.04 + P-109 4256044.93 3552712.30 + P-109 4256349.66 3552812.50 + P-109 4256562.94 3552873.37 + P-109 4256766.09 3552939.33 + P-109 4256899.42 3552990.06 + P-109 4257050.51 3553061.11 + P-109 4257202.90 3553141.06 + P-109 4257680.32 3553440.52 + P-109 4258137.44 3553732.38 + P-109 4258513.29 3553972.21 + P-109 4258748.20 3554116.88 + P-109 4258862.47 3554180.31 + P-109 4259044.03 3554257.70 + P-109 4259184.97 3554305.90 + P-109 4259511.27 3554384.51 + P-109 4259730.92 3554431.43 + P-109 4260007.69 3554493.55 + P-109 4260128.30 3554511.28 + P-109 4260217.17 3554515.07 + P-109 4260332.69 3554513.77 + P-109 4260488.85 3554485.79 + P-109 4260667.83 3554429.87 + P-109 4261376.15 3554147.83 + P-109 4261892.80 3553944.54 + P-109 4262382.16 3553747.63 + P-109 4262707.79 3553640.88 + P-109 4263367.86 3553469.30 + P-109 4263859.13 3553334.59 + P-109 4264007.65 3553301.54 + P-109 4264245.04 3553269.72 + P-109 4264469.95 3553248.80 + P-109 4265004.22 3553198.41 + P-109 4265331.74 3553171.66 + P-109 4265498.05 3553170.33 + P-109 4265557.44 3553176.90 + P-109 4265614.85 3553177.93 + P-109 4265783.70 3553200.72 + P-109 4265939.87 3553237.49 + P-109 4266299.18 3553352.92 + P-109 4266639.45 3553467.08 + P-109 4267209.34 3553660.98 + P-109 4268140.01 3553972.99 + P-109 4269046.55 3554276.17 + P-109 4269610.26 3554465.15 + P-109 4269791.84 3554529.84 + P-109 4269951.83 3554598.37 + P-109 4270111.80 3554677.02 + P-109 4270259.10 3554763.32 + P-109 4270660.34 3555023.45 + P-109 4271059.09 3555288.67 + P-109 4271503.48 3555575.45 + P-109 4271679.98 3555666.81 + P-109 4271841.23 3555735.32 + P-109 4271925.78 3555765.43 + P-109 4271979.49 3555784.55 + P-109 4272206.77 3555858.12 + P-109 4272387.05 3555905.03 + P-109 4272564.79 3555932.92 + P-109 4272686.67 3555937.96 + P-109 4273035.80 3555936.58 + P-109 4273475.05 3555930.22 + P-109 4273868.67 3555935.93 + P-109 4274207.40 3555942.81 + P-109 4275298.13 3555982.92 + P-109 4275450.47 3555991.74 + P-109 4275728.50 3556003.09 + P-109 4275926.55 3556004.30 + P-109 4276080.17 3556000.45 + P-109 4276191.89 3555990.26 + P-109 4276401.35 3555969.88 + P-109 4276518.13 3555957.17 + P-109 4276782.21 3555952.00 + P-109 4276912.96 3555953.23 + P-109 4277237.97 3555963.29 + P-109 4277377.63 3555955.64 + P-109 4277522.34 3555937.82 + P-109 4278231.98 3555829.71 + P-109 4278667.62 3555761.14 + P-109 4278774.02 3555751.62 + P-109 4279041.91 3555748.22 + P-109 4279563.69 3555744.27 + P-109 4279850.61 3555745.46 + P-109 4279925.52 3555753.06 + P-109 4280102.00 3555808.85 + P-109 4280251.82 3555872.29 + P-109 4280326.73 3555904.01 + P-109 4280396.57 3555943.33 + P-109 4280532.44 3556032.17 + P-109 4280740.68 3556184.46 + P-109 4280825.75 3556241.55 + P-109 4280895.59 3556279.63 + P-109 4281006.05 3556331.67 + P-109 4281261.25 3556419.17 + P-109 4281628.19 3556543.48 + P-109 4281838.95 3556619.59 + P-109 4282016.70 3556672.87 + P-109 4282134.37 3556696.43 + P-109 4282463.33 3556775.08 + P-109 4282628.64 3556812.71 + P-109 4282859.32 3556864.32 + P-109 4283385.16 3556978.39 + P-109 4283714.17 3557051.97 + P-109 4283907.17 3557101.42 + P-109 4284200.45 3557181.32 + P-109 4284461.97 3557247.26 + P-109 4284620.70 3557270.06 + P-109 4284743.83 3557277.65 + P-109 4284882.22 3557291.57 + P-109 4284981.24 3557309.34 + P-109 4285059.96 3557332.14 + P-109 4285164.08 3557370.20 + P-109 4285355.80 3557446.33 + P-109 4285901.76 3557654.36 + P-109 4286287.74 3557791.36 + P-109 4286799.42 3557975.30 + P-109 4287441.85 3558176.98 + P-109 4287620.89 3558234.06 + P-109 4287914.17 3558321.56 + P-109 4288408.06 3558459.81 + P-109 4288461.32 3558476.88 + P-109 4288517.24 3558491.52 + P-109 4288834.65 3558575.22 + P-109 4289220.61 3558665.25 + P-109 4290203.30 3558878.26 + P-109 4290379.78 3558909.93 + P-109 4290471.17 3558917.53 + P-109 4290580.36 3558920.03 + P-109 4290685.72 3558909.86 + P-109 4290937.09 3558893.28 + P-109 4291042.45 3558886.90 + P-109 4291166.86 3558879.24 + P-109 4291281.12 3558879.20 + P-109 4291376.35 3558889.34 + P-109 4291494.42 3558919.79 + P-109 4291663.29 3558981.94 + P-109 4292009.90 3559104.99 + P-109 4292118.66 3559127.15 + P-109 4292138.13 3559149.39 + P-109 4292531.73 3559292.73 + P-109 4292645.61 3559339.74 + P-109 4292742.13 3559389.23 + P-109 4292851.33 3559472.99 + P-109 4292938.96 3559560.57 + P-109 4293154.83 3559801.71 + P-109 4293291.99 3559956.55 + P-109 4293407.64 3560097.98 + P-109 4293473.61 3560197.71 + P-11 4296430.75 3575315.01 + P-11 4296234.92 3575012.09 + P-110 4302599.23 3583008.07 + P-110 4302700.15 3582740.07 + P-110 4302723.64 3582656.19 + P-110 4302730.33 3582608.23 + P-110 4302727.97 3582558.45 + P-110 4302715.77 3582509.56 + P-110 4302693.77 3582464.96 + P-111 4302783.03 3588182.80 + P-111 4302627.04 3587839.67 + P-111 4302581.83 3587728.65 + P-111 4302542.06 3587614.82 + P-111 4302504.94 3587542.30 + P-111 4302477.72 3587476.64 + P-111 4302471.66 3587393.99 + P-111 4302473.93 3587333.51 + P-111 4302477.19 3587296.60 + P-111 4302491.57 3587216.42 + P-111 4302524.33 3587107.37 + P-111 4302529.66 3587052.63 + P-111 4302538.21 3586929.97 + P-111 4302537.39 3586797.72 + P-111 4302527.97 3586718.04 + P-111 4302507.99 3586631.31 + P-111 4302457.03 3586445.68 + P-111 4302415.17 3586217.81 + P-111 4302380.60 3586085.83 + P-111 4302323.15 3585896.16 + P-111 4302243.66 3585653.89 + P-111 4302214.42 3585551.12 + P-111 4302077.71 3585116.89 + P-111 4302044.00 3584999.16 + P-111 4301995.25 3584755.49 + P-111 4301937.07 3584519.07 + P-111 4301925.91 3584434.88 + P-111 4301924.64 3584397.51 + P-111 4301926.83 3584357.16 + P-111 4301933.30 3584315.38 + P-111 4301942.77 3584274.50 + P-111 4302022.83 3584047.52 + P-111 4302038.32 3584010.66 + P-111 4302118.52 3583829.85 + P-111 4302190.49 3583693.14 + P-111 4302260.39 3583608.06 + P-111 4302331.14 3583531.18 + P-111 4302415.03 3583453.64 + P-111 4302469.23 3583374.79 + P-111 4302486.44 3583338.85 + P-111 4302529.37 3583210.67 + P-113 4302665.59 3582427.87 + P-113 4302586.78 3582338.14 + P-113 4302520.03 3582251.79 + P-113 4302492.76 3582207.67 + P-113 4302474.80 3582133.99 + P-113 4302443.94 3581989.17 + P-113 4302418.42 3581829.75 + P-113 4302410.82 3581744.82 + P-113 4302399.70 3581497.77 + P-113 4302400.00 3581411.25 + P-113 4302420.15 3581119.80 + P-114 4290743.74 3571299.92 + P-115 4290480.54 3570866.17 + P-119 4293886.00 3571117.73 + P-119 4293906.64 3571103.43 + P-119 4293934.53 3571079.49 + P-119 4294004.32 3571035.60 + P-119 4293970.40 3570989.76 + P-119 4293950.44 3570953.87 + P-119 4293922.52 3570912.01 + P-119 4293898.58 3570874.14 + P-119 4293868.68 3570846.23 + P-119 4293840.77 3570836.27 + P-119 4293850.75 3570939.93 + P-119 4293866.72 3570983.81 + P-119 4293868.72 3571023.68 + P-119 4293868.73 3571057.57 + P-119 4293874.72 3571091.47 + P-12 4296586.95 3562659.05 + P-12 4296508.66 3562711.73 + P-12 4296466.25 3562741.29 + P-121 4303139.83 3574145.25 + P-121 4303018.69 3574214.52 + P-121 4302913.11 3574294.16 + P-124 4295643.75 3573252.07 + P-125 4296388.03 3571342.59 + P-129 4301924.70 3570281.54 + P-129 4301952.75 3570310.74 + P-129 4301991.34 3570344.60 + P-129 4301986.68 3570418.21 + P-129 4301993.70 3570482.46 + P-129 4301858.17 3570507.03 + P-129 4301827.83 3570539.75 + P-129 4301824.33 3570573.63 + P-129 4301841.86 3570656.58 + P-129 4301746.09 3570668.28 + P-129 4301695.85 3570689.32 + P-129 4301650.30 3570725.55 + P-129 4301602.41 3570768.79 + P-13 4288727.46 3570309.01 + P-13 4289039.00 3570128.32 + P-13 4289282.14 3569985.12 + P-13 4289506.82 3569858.10 + P-13 4289669.98 3569791.38 + P-13 4289768.31 3569757.73 + P-13 4289888.90 3569728.51 + P-13 4290029.81 3569710.68 + P-13 4290163.12 3569705.57 + P-13 4290311.66 3569709.32 + P-131 4298223.85 3570967.16 + P-131 4298237.88 3571002.21 + P-131 4298260.06 3571044.27 + P-139 4298393.16 3570690.25 + P-145 4298717.44 3573135.34 + P-145 4298717.46 3573222.97 + P-145 4298694.12 3573307.10 + P-145 4298645.08 3573392.38 + P-145 4298628.75 3573443.80 + P-145 4298624.07 3573495.21 + P-145 4298641.61 3573538.42 + P-146 4299866.74 3572110.45 + P-15 4294227.82 3580583.14 + P-15 4294429.64 3580326.67 + P-15 4294676.02 3579948.74 + P-151 4298140.79 3570650.59 + P-153 4294761.53 3576187.62 + P-153 4294771.12 3576087.16 + P-153 4294786.32 3575972.90 + P-153 4294787.56 3575858.64 + P-153 4294777.37 3575764.69 + P-153 4294736.70 3575555.24 + P-153 4294713.80 3575366.08 + P-154 4299788.42 3571978.47 + P-157 4298030.03 3574174.68 + P-158 4296989.71 3578134.12 + P-16 4295967.85 3574625.14 + P-161 4300201.00 3574623.77 + P-161 4300200.99 3574575.53 + P-161 4300181.92 3574491.74 + P-161 4300157.76 3574434.63 + P-161 4300096.81 3574317.85 + P-162 4298397.99 3571263.87 + P-163 4302779.28 3577987.78 + P-163 4302950.98 3578680.01 + P-165 4298854.30 3569588.44 + P-172 4294686.10 3571723.85 + P-175 4297549.38 3568949.13 + P-178 4291261.27 3569786.25 + P-178 4291450.39 3569817.29 + P-178 4291730.98 3569890.82 + P-179 4298816.96 3569687.75 + P-179 4298805.26 3569656.21 + P-18 4304341.77 3584286.31 + P-181 4301964.41 3570195.06 + P-181 4302615.49 3570100.77 + P-181 4302685.40 3570443.09 + P-181 4302552.20 3570437.27 + P-181 4302683.07 3571122.20 + P-181 4302762.37 3571102.62 + P-181 4302826.45 3571594.90 + P-181 4303166.04 3571728.29 + P-181 4303294.27 3571919.54 + P-181 4303244.72 3572467.12 + P-181 4302539.58 3572209.86 + P-181 4302282.28 3571801.13 + P-181 4302441.74 3571806.40 + P-181 4302455.22 3571233.11 + P-181 4302304.46 3571218.93 + P-181 4301859.70 3571520.05 + P-181 4301537.04 3570956.90 + P-186 4298732.97 3570156.25 + P-188 4303071.90 3568981.46 + P-188 4303066.78 3568892.59 + P-188 4303065.51 3568839.28 + P-188 4303068.64 3568804.37 + P-190 4299158.27 3570351.24 + P-192 4296227.06 3561589.33 + P-192 4296224.48 3561539.24 + P-192 4296233.46 3561510.99 + P-192 4296269.41 3561480.15 + P-198 4303785.01 3567688.88 + P-198 4303689.80 3567711.77 + P-198 4303532.38 3567725.77 + P-198 4303456.20 3567725.79 + P-2 4300215.41 3560495.99 + P-2 4300195.22 3560364.56 + P-2 4300175.65 3560222.22 + P-2 4300159.61 3560099.67 + P-2 4300120.67 3559773.72 + P-201 4295257.89 3573456.58 + P-203 4295922.61 3571663.83 + P-204 4303188.80 3579622.47 + P-204 4303250.36 3579899.21 + P-204 4303270.88 3579972.41 + P-204 4303352.97 3580293.06 + P-204 4303470.24 3580758.63 + P-206 4296819.34 3568717.02 + P-206 4296753.34 3568761.49 + P-206 4296757.15 3568781.78 + P-206 4296783.82 3568830.02 + P-206 4296825.73 3568908.72 + P-21 4296867.86 3561279.63 + P-21 4296885.89 3561573.73 + P-21 4296906.55 3561933.34 + P-21 4296982.69 3562387.96 + P-210 4300740.34 3568049.31 + P-210 4300767.67 3568149.46 + P-211 4295721.93 3559737.21 + P-211 4295782.35 3559828.67 + P-211 4295818.38 3559863.02 + P-211 4295859.56 3559883.00 + P-211 4295908.95 3559894.75 + P-211 4295955.99 3559894.73 + P-211 4295999.50 3559882.97 + P-211 4296066.54 3559855.90 + P-214 4294676.58 3560445.50 + P-214 4294650.72 3560472.54 + P-214 4294638.97 3560498.43 + P-214 4294637.80 3560524.29 + P-22 4301195.99 3574032.11 + P-22 4301041.61 3574494.54 + P-22 4301021.32 3574563.10 + P-221 4295070.55 3570902.36 + P-221 4295114.99 3570953.12 + P-221 4295169.61 3571031.82 + P-225 4305625.91 3586783.09 + P-225 4305917.91 3586855.38 + P-225 4306036.34 3586886.51 + P-225 4306131.21 3586897.21 + P-225 4306274.68 3586885.74 + P-225 4306835.74 3586771.33 + P-225 4306910.64 3586763.69 + P-225 4306998.24 3586767.47 + P-225 4307121.39 3586800.46 + P-225 4307207.71 3586829.63 + P-225 4307300.41 3586875.31 + P-225 4307379.15 3586917.17 + P-225 4307457.86 3586964.13 + P-225 4307532.78 3587023.78 + P-225 4307761.16 3587240.07 + P-225 4308208.32 3587634.22 + P-225 4308344.18 3587695.13 + P-225 4308438.13 3587716.68 + P-226 4295777.15 3559585.48 + P-226 4295837.11 3559533.71 + P-226 4295894.08 3559498.59 + P-226 4295973.50 3559454.89 + P-226 4296055.83 3559423.11 + P-226 4296182.85 3559399.55 + P-226 4296326.31 3559387.75 + P-226 4296343.98 3559470.07 + P-226 4296376.94 3559620.59 + P-227 4304496.79 3584860.09 + P-227 4304542.52 3584984.49 + P-227 4304583.19 3585080.96 + P-227 4304678.43 3585280.26 + P-227 4305101.40 3586039.31 + P-227 4305334.48 3586468.54 + P-228 4298206.36 3571145.92 + P-228 4298126.93 3571206.69 + P-23 4299016.64 3573567.53 + P-23 4298687.24 3573752.21 + P-232 4295347.09 3578850.01 + P-232 4295608.23 3578428.73 + P-232 4295840.98 3578056.06 + P-232 4296081.84 3577667.19 + P-233 4297171.41 3578108.33 + P-235 4297744.04 3570503.10 + P-237 4298088.51 3567503.00 + P-237 4298309.54 3567923.14 + P-24 4298205.12 3566793.30 + P-24 4298172.11 3566837.76 + P-24 4298142.93 3566870.76 + P-24 4298055.35 3566920.29 + P-24 4298019.81 3566925.39 + P-24 4297965.22 3566924.13 + P-24 4297930.94 3566943.17 + P-24 4297895.40 3566963.50 + P-243 4295063.69 3573592.47 + P-243 4294860.61 3573760.11 + P-245 4300141.82 3569863.79 + P-246 4300611.36 3569466.44 + P-246 4300374.26 3569729.38 + P-246 4300382.91 3569743.88 + P-248 4295603.13 3559716.08 + P-25 4294449.46 3580512.66 + P-25 4295042.47 3580733.42 + P-25 4295580.83 3580925.10 + P-25 4295807.56 3581000.63 + P-25 4296228.46 3581145.83 + P-25 4296384.28 3581208.56 + P-250 4303220.10 3579355.33 + P-250 4303469.75 3579459.42 + P-250 4304100.99 3579731.22 + P-250 4304547.47 3579904.25 + P-252 4296504.04 3559901.65 + P-252 4296511.11 3559949.86 + P-252 4296405.29 3560049.85 + P-252 4296378.26 3560074.56 + P-252 4295944.33 3560286.37 + P-252 4295764.42 3560365.21 + P-254 4299592.99 3567512.45 + P-255 4301398.58 3568779.28 + P-255 4301480.40 3568922.95 + P-256 4299638.97 3556655.46 + P-256 4299399.65 3555570.69 + P-256 4293873.35 3559674.55 + P-256 4293874.65 3559809.13 + P-256 4293868.33 3559849.73 + P-256 4293870.89 3559887.83 + P-256 4293897.57 3560009.71 + P-256 4293901.40 3560073.17 + P-259 4296365.42 3570761.07 + P-259 4296450.50 3570851.17 + P-26 4297084.92 3574163.18 + P-262 4303218.84 3567882.02 + P-262 4303226.49 3567975.95 + P-262 4303241.74 3568049.59 + P-262 4303260.81 3568123.21 + P-262 4303283.68 3568184.14 + P-262 4303317.97 3568238.73 + P-262 4303410.68 3568337.72 + P-262 4303448.78 3568401.19 + P-262 4303467.83 3568482.43 + P-263 4294647.36 3573907.44 + P-263 4294507.75 3573977.30 + P-263 4294531.87 3574056.00 + P-263 4294531.91 3574122.02 + P-263 4294516.69 3574209.61 + P-263 4294507.33 3574316.29 + P-263 4294509.11 3574367.03 + P-263 4294524.38 3574429.24 + P-263 4294550.14 3574485.89 + P-263 4294697.47 3574699.14 + P-263 4294726.67 3574770.23 + P-263 4294736.86 3574841.31 + P-263 4294734.34 3574935.26 + P-264 4297025.76 3561110.06 + P-267 4301757.90 3572060.37 + P-267 4301521.37 3571756.80 + P-269 4301132.95 3571246.36 + P-27 4299776.21 3573719.68 + P-271 4296533.36 3577476.72 + P-272 4301660.23 3572062.74 + P-274 4302754.73 3572670.54 + P-28 4297133.82 3567486.75 + P-281 4301034.20 3567747.47 + P-283 4307574.01 3574571.09 + P-284 4300716.60 3571757.03 + P-284 4300638.69 3571801.37 + P-287 4297345.53 3570938.53 + P-288 4301546.77 3570832.66 + P-288 4301517.17 3570873.96 + P-288 4301454.08 3570877.48 + P-288 4301385.15 3570891.52 + P-289 4296491.96 3569261.74 + P-29 4302215.87 3573914.14 + P-29 4302022.35 3572991.32 + P-29 4302192.39 3572892.98 + P-293 4293892.81 3571593.92 + P-293 4293805.04 3571452.38 + P-293 4293789.05 3571294.86 + P-293 4293761.11 3571215.11 + P-293 4293800.98 3571185.21 + P-299 4300451.41 3569815.80 + P-303 4295666.42 3574184.87 + P-303 4295622.43 3574112.79 + P-303 4295480.17 3573902.12 + P-306 4297962.07 3570753.45 + P-309 4297781.33 3567664.30 + P-31 4294943.70 3570175.65 + P-310 4294471.52 3571593.15 + P-310 4294455.01 3571577.92 + P-310 4294428.35 3571575.38 + P-310 4294394.08 3571596.97 + P-312 4303557.70 3581576.13 + P-312 4303492.95 3581577.42 + P-312 4303447.26 3581573.62 + P-312 4303404.08 3581555.85 + P-312 4303294.88 3581493.68 + P-312 4303203.49 3581455.62 + P-312 4303052.39 3581429.01 + P-312 4302893.70 3581401.13 + P-312 4302826.41 3581374.49 + P-312 4302788.32 3581350.38 + P-312 4302738.78 3581302.14 + P-312 4302685.45 3581245.03 + P-312 4302654.97 3581194.26 + P-312 4302624.49 3581134.61 + P-312 4302580.02 3581045.75 + P-317 4294327.03 3572387.90 + P-317 4294491.26 3572634.87 + P-317 4294671.20 3572888.00 + P-317 4294945.19 3573304.09 + P-325 4296565.00 3571619.22 + P-328 4300925.30 3572478.08 + P-328 4301094.11 3572386.62 + P-331 4296356.81 3571723.38 + P-331 4296326.34 3571758.93 + P-331 4296312.39 3571776.71 + P-331 4296373.34 3571832.56 + P-335 4304162.12 3567941.42 + P-335 4304290.40 3568162.29 + P-337 4296676.95 3568011.19 + P-337 4296886.57 3568569.72 + P-340 4302972.80 3568719.96 + P-340 4302970.17 3568460.98 + P-340 4302496.65 3568475.09 + P-340 4302466.18 3568486.52 + P-340 4302159.02 3568698.62 + P-343 4298241.13 3570187.94 + P-344 4301792.27 3568717.25 + P-344 4301883.44 3568822.37 + P-345 4302862.97 3574427.45 + P-345 4302873.37 3574512.28 + P-345 4302863.01 3574553.81 + P-345 4302759.16 3574621.35 + P-346 4302069.10 3572334.31 + P-346 4302526.13 3572393.85 + P-346 4302673.41 3572431.90 + P-346 4302847.35 3572500.39 + P-346 4303141.93 3572641.23 + P-346 4303986.28 3573077.71 + P-347 4301863.60 3568929.85 + P-348 4294039.79 3560079.50 + P-348 4293990.27 3560103.62 + P-348 4293938.22 3560117.61 + P-349 4301157.51 3566823.96 + P-349 4301204.38 3566996.92 + P-349 4301227.82 3567103.58 + P-349 4301253.88 3567214.13 + P-349 4301328.09 3567501.56 + P-349 4301343.71 3567580.89 + P-349 4301268.29 3567600.43 + P-349 4301218.86 3567616.05 + P-35 4297075.19 3566617.15 + P-35 4297175.53 3566811.36 + P-35 4297202.21 3566862.13 + P-35 4297214.92 3566902.77 + P-35 4297213.66 3566956.08 + P-35 4297204.78 3567001.77 + P-35 4297174.34 3567088.11 + P-35 4297162.94 3567159.21 + P-35 4297162.96 3567210.00 + P-353 4297165.16 3570583.12 + P-354 4301736.39 3569422.90 + P-357 4296285.90 3570649.56 + P-358 4303787.83 3568686.73 + P-36 4297543.87 3571968.03 + P-361 4295405.67 3563616.19 + P-361 4295572.70 3563849.87 + P-362 4298548.33 3568369.95 + P-364 4296545.78 3571045.40 + P-37 4305504.82 3573784.41 + P-37 4306551.94 3574161.31 + P-37 4306725.88 3574222.20 + P-37 4306870.62 3574275.48 + P-371 4298939.01 3571674.95 + P-372 4301581.04 3574025.93 + P-373 4301998.01 3569136.60 + P-373 4301937.28 3569181.02 + P-378 4295319.99 3579505.59 + P-378 4295381.64 3579552.07 + P-378 4295426.98 3579612.53 + P-378 4295445.61 3579661.36 + P-38 4290805.53 3570051.82 + P-381 4297419.45 3567429.55 + P-381 4297335.68 3567453.70 + P-383 4298879.08 3570421.41 + P-384 4304105.28 3568960.86 + P-388 4292165.22 3570068.46 + P-388 4292398.86 3570199.14 + P-388 4292644.31 3570356.11 + P-388 4292883.63 3570567.36 + P-388 4293206.75 3570940.13 + P-388 4293547.35 3571352.06 + P-388 4293813.07 3571681.67 + P-389 4293817.63 3560110.05 + P-389 4293802.39 3560154.47 + P-389 4293756.72 3560200.18 + P-389 4293683.09 3560252.25 + P-391 4302805.51 3572749.23 + P-397 4296024.38 3562449.86 + P-397 4296211.86 3562343.22 + P-401 4298720.26 3570688.99 + P-403 4297484.46 3568338.51 + P-403 4297544.16 3568457.83 + P-407 4293952.14 3561114.81 + P-407 4294197.06 3561565.24 + P-407 4294377.10 3561898.02 + P-407 4294498.29 3562109.68 + P-407 4294786.37 3562629.45 + P-407 4294970.11 3562929.27 + P-407 4295117.86 3563152.63 + P-41 4296519.11 3577122.33 + P-41 4296844.97 3576583.61 + P-41 4296903.66 3576453.97 + P-41 4296936.02 3576326.41 + P-41 4296942.06 3576223.13 + P-41 4296931.92 3576140.10 + P-41 4296919.75 3576063.16 + P-41 4296858.96 3575925.47 + P-410 4303105.11 3572660.29 + P-412 4309738.99 3576171.36 + P-412 4309681.76 3575775.29 + P-414 4301057.49 3568923.07 + P-42 4304454.42 3571999.76 + P-426 4297157.51 3571050.31 + P-426 4297095.22 3570965.71 + P-428 4299826.64 3570737.75 + P-431 4301866.19 3569850.45 + P-431 4301950.39 3570153.01 + P-431 4301955.05 3570183.39 + P-432 4297629.99 3566679.20 + P-432 4297716.36 3566831.52 + P-436 4301452.82 3570592.43 + P-437 4302076.26 3569027.93 + P-437 4302231.64 3569065.28 + P-437 4302336.80 3569078.09 + P-438 4297170.92 3568480.78 + P-438 4297271.19 3568412.20 + P-438 4297361.33 3568356.32 + P-44 4304200.41 3571566.92 + P-44 4304185.21 3571692.61 + P-44 4304151.00 3571943.98 + P-442 4298546.53 3571887.69 + P-442 4298517.31 3571865.49 + P-442 4298477.60 3571854.98 + P-442 4298426.19 3571866.68 + P-447 4302577.03 3572807.69 + P-45 4297027.71 3569297.12 + P-452 4293972.59 3570393.01 + P-452 4292717.97 3569983.22 + P-452 4292245.98 3569922.16 + P-452 4292031.87 3569940.27 + P-456 4295723.08 3564256.96 + P-456 4295509.92 3564348.19 + P-456 4295463.68 3564376.47 + P-456 4295439.29 3564400.88 + P-456 4295429.01 3564425.28 + P-456 4295422.61 3564459.97 + P-456 4295426.47 3564493.35 + P-456 4295486.91 3564770.75 + P-456 4295517.78 3564920.99 + P-456 4295005.37 3564990.48 + P-456 4294593.12 3565047.12 + P-456 4294349.11 3565062.60 + P-456 4293551.57 3565089.79 + P-456 4292967.22 3565114.35 + P-46 4300155.50 3568661.62 + P-46 4300171.89 3568738.73 + P-468 4302051.32 3572367.31 + P-468 4302523.61 3572420.50 + P-468 4302603.59 3572435.71 + P-47 4296590.09 3581296.84 + P-47 4296890.07 3581383.98 + P-47 4297077.27 3581423.46 + P-47 4297166.81 3581437.38 + P-47 4297341.21 3581443.14 + P-47 4297379.57 3581451.28 + P-47 4297415.62 3581472.18 + P-47 4297438.87 3581494.28 + P-471 4286361.38 3571445.90 + P-471 4286357.60 3571525.88 + P-471 4286337.31 3571577.93 + P-471 4286309.38 3571612.22 + P-471 4286240.84 3571671.90 + P-471 4286167.20 3571607.19 + P-471 4285090.37 3570690.90 + P-471 4285028.15 3570631.25 + P-471 4285006.56 3570588.07 + P-481 4298870.73 3569823.26 + P-481 4298905.78 3569893.35 + P-487 4300015.68 3569966.63 + P-487 4299861.48 3570049.62 + P-49 4301094.22 3572775.09 + P-490 4298800.06 3571978.73 + P-493 4295839.63 3563167.84 + P-493 4295752.32 3563225.65 + P-493 4295652.17 3563297.61 + P-493 4295566.14 3563355.42 + P-493 4295469.84 3563423.51 + P-493 4295391.51 3563471.07 + P-495 4296017.20 3564357.05 + P-495 4296278.00 3564631.79 + P-495 4296389.76 3564757.64 + P-499 4295184.65 3563147.48 + P-499 4295151.25 3563097.41 + P-499 4295138.39 3563066.57 + P-499 4295090.84 3562990.82 + P-499 4295241.08 3562898.30 + P-499 4295506.89 3562749.25 + P-5 4300953.90 3565376.48 + P-5 4300963.88 3565324.88 + P-5 4300969.13 3565272.90 + P-5 4300969.88 3565219.90 + P-5 4300966.91 3565164.85 + P-5 4300961.25 3565107.74 + P-5 4300945.65 3564987.52 + P-5 4300805.81 3563978.31 + P-5 4300753.76 3563630.74 + P-5 4300726.21 3563453.70 + P-5 4300673.88 3563142.87 + P-5 4300566.89 3562532.67 + P-5 4300285.48 3560907.67 + P-50 4305379.19 3574787.10 + P-50 4305297.73 3574691.96 + P-50 4305272.83 3574657.96 + P-50 4305251.66 3574621.17 + P-50 4305234.82 3574583.97 + P-50 4305223.18 3574544.49 + P-50 4305218.33 3574503.97 + P-50 4305219.62 3574462.61 + P-50 4305235.54 3574378.82 + P-50 4305329.22 3574081.34 + P-501 4303779.98 3582015.32 + P-502 4295042.38 3560607.70 + P-502 4294942.42 3560639.48 + P-502 4294840.12 3560679.48 + P-502 4294764.86 3560704.21 + P-502 4294720.12 3560533.69 + P-506 4300620.53 3572200.14 + P-506 4300501.71 3571981.45 + P-509 4295177.44 3559918.47 + P-509 4294119.12 3560411.56 + P-51 4304791.27 3573519.28 + P-51 4304987.82 3573602.10 + P-51 4305337.23 3573724.81 + P-510 4303220.68 3572816.40 + P-510 4303166.13 3572912.90 + P-510 4303154.71 3572957.34 + P-510 4303162.33 3572999.23 + P-510 4303189.01 3573039.85 + P-510 4303223.29 3573070.30 + P-510 4303253.77 3573091.89 + P-510 4303750.22 3573360.88 + P-510 4303783.24 3573368.48 + P-510 4303820.04 3573353.25 + P-510 4303846.69 3573325.33 + P-510 4303877.15 3573268.18 + P-510 4303907.62 3573221.19 + P-510 4303932.99 3573172.95 + P-514 4300766.40 3568230.10 + P-514 4300735.21 3568240.52 + P-514 4300706.57 3568252.23 + P-514 4300661.05 3568262.65 + P-515 4299691.62 3572536.93 + P-516 4303150.18 3573979.08 + P-519 4294828.46 3570270.77 + P-519 4294507.03 3570166.70 + P-519 4294408.07 3570536.35 + P-520 4302835.27 3574420.53 + P-520 4302774.69 3574424.02 + P-520 4302738.35 3574434.42 + P-520 4302658.74 3574491.57 + P-522 4298456.78 3572643.57 + P-528 4297214.15 3570894.47 + P-531 4299824.56 3571731.95 + P-537 4300728.21 3569576.24 + P-540 4309850.59 3575723.18 + P-540 4310333.03 3575851.27 + P-540 4311023.69 3576023.75 + P-540 4311790.54 3576212.71 + P-543 4296217.02 3570082.63 + P-543 4296118.00 3570120.74 + P-543 4296071.07 3570130.09 + P-543 4296038.02 3570132.18 + P-543 4295402.00 3570151.40 + P-543 4295339.79 3570143.80 + P-543 4295177.28 3570110.83 + P-543 4295060.15 3570086.04 + P-543 4295014.77 3570070.27 + P-546 4299123.53 3571438.90 + P-548 4300644.75 3572547.98 + P-548 4300487.35 3572636.88 + P-548 4300407.39 3572695.31 + P-550 4295102.54 3570641.52 + P-550 4295324.72 3570750.64 + P-550 4295719.63 3570965.08 + P-551 4298346.81 3569610.32 + P-553 4296540.91 3563301.22 + P-556 4304482.66 3573077.58 + P-556 4304472.52 3573141.05 + P-556 4304452.23 3573198.20 + P-560 4299471.29 3570094.13 + P-562 4307316.05 3573655.83 + P-562 4307322.42 3573720.57 + P-562 4307316.08 3573780.24 + P-562 4307248.90 3574129.39 + P-562 4307228.61 3574210.63 + P-562 4307174.06 3574345.21 + P-565 4297862.39 3571508.41 + P-568 4293923.85 3570678.15 + P-568 4293944.49 3570637.09 + P-572 4297124.58 3570679.62 + P-573 4296575.01 3571192.65 + P-573 4296572.49 3571247.24 + P-573 4296562.34 3571300.57 + P-573 4296539.51 3571337.39 + P-573 4296451.93 3571414.83 + P-576 4301330.84 3568824.87 + P-576 4301097.23 3568994.33 + P-580 4298975.93 3570018.32 + P-585 4295907.62 3572511.88 + P-586 4308471.73 3575133.24 + P-586 4308904.69 3575365.44 + P-586 4309293.22 3575536.72 + P-588 4298307.98 3571128.38 + P-589 4297600.91 3571613.84 + P-59 4305516.73 3584265.50 + P-59 4305607.90 3584317.81 + P-59 4305640.55 3584340.21 + P-59 4305748.40 3584439.06 + P-59 4305793.54 3584489.60 + P-59 4305880.26 3584559.41 + P-59 4305925.71 3584583.32 + P-59 4305982.39 3584601.76 + P-59 4306047.73 3584611.81 + P-59 4306222.61 3584612.41 + P-59 4306260.54 3584616.29 + P-59 4306419.83 3584655.41 + P-59 4306628.84 3584699.87 + P-59 4306724.48 3584724.97 + P-59 4306838.58 3584756.35 + P-59 4306872.44 3584771.56 + P-59 4306903.27 3584793.14 + P-59 4306964.78 3584861.42 + P-59 4306982.50 3584899.07 + P-591 4296848.12 3571775.29 + P-592 4296879.81 3571596.28 + P-594 4303199.20 3576932.68 + P-594 4303078.60 3576947.95 + P-597 4294786.72 3572876.54 + P-598 4297133.93 3571303.93 + P-599 4296999.38 3572454.43 + P-602 4300783.52 3573147.65 + P-602 4300607.09 3573260.68 + P-606 4297164.17 3571527.63 + P-607 4296628.54 3571953.08 + P-61 4304681.92 3579998.50 + P-61 4304726.34 3579997.08 + P-61 4304865.54 3579998.64 + P-61 4305000.01 3580005.92 + P-61 4305038.26 3580012.82 + P-61 4305077.03 3580024.08 + P-61 4305157.28 3580052.07 + P-61 4305324.45 3580116.07 + P-61 4306434.42 3580563.24 + P-61 4306732.18 3580679.53 + P-61 4306788.44 3580710.82 + P-61 4306907.35 3580797.68 + P-61 4306977.19 3580830.65 + P-61 4307185.96 3580929.62 + P-61 4307221.98 3580943.05 + P-61 4307330.32 3580972.25 + P-61 4307511.37 3581015.13 + P-61 4308105.67 3581141.43 + P-61 4309012.05 3581342.78 + P-61 4309591.12 3581467.75 + P-61 4309698.97 3581502.07 + P-61 4309798.17 3581548.96 + P-61 4309985.25 3581658.86 + P-61 4310179.55 3581767.76 + P-61 4310333.77 3581871.37 + P-61 4310409.94 3581915.23 + P-61 4310515.78 3581967.26 + P-61 4310691.56 3582047.20 + P-61 4310839.89 3582111.02 + P-61 4311026.27 3582186.26 + P-61 4311112.15 3582224.97 + P-61 4311237.96 3582288.85 + P-611 4297480.47 3572219.44 + P-612 4303067.73 3567699.25 + P-612 4302973.76 3567706.88 + P-612 4302837.95 3567736.12 + P-612 4302701.42 3567793.97 + P-612 4302317.54 3568040.64 + P-612 4302061.13 3568220.03 + P-615 4302857.81 3573543.93 + P-615 4303030.68 3573771.40 + P-616 4299162.71 3569528.77 + P-616 4299211.81 3569622.21 + P-616 4299257.40 3569700.47 + P-616 4299284.27 3569750.71 + P-618 4303380.71 3576866.59 + P-619 4297215.29 3572738.75 + P-62 4303965.16 3583299.89 + P-62 4303777.57 3583316.24 + P-62 4303746.24 3583326.68 + P-62 4303724.39 3583345.34 + P-62 4303706.56 3583378.60 + P-62 4303446.24 3584130.63 + P-620 4303562.78 3570340.67 + P-620 4303562.95 3570368.66 + P-620 4303549.59 3570398.39 + P-620 4303525.23 3570417.71 + P-620 4303498.37 3570427.39 + P-620 4303156.87 3570482.81 + P-620 4303123.59 3570470.07 + P-620 4303103.55 3570444.34 + P-620 4303095.41 3570418.76 + P-620 4303086.70 3570360.00 + P-620 4303000.22 3570372.96 + P-620 4302950.88 3570370.34 + P-620 4302920.93 3570359.69 + P-620 4302898.92 3570344.85 + P-620 4302874.04 3570314.28 + P-620 4302851.26 3570259.94 + P-620 4302832.81 3570197.46 + P-620 4302746.91 3569863.66 + P-621 4305446.71 3586896.77 + P-621 4305464.02 3587026.61 + P-621 4305498.64 3587234.35 + P-621 4305498.64 3587390.15 + P-621 4305507.30 3587554.61 + P-621 4305489.99 3587658.48 + P-621 4305464.02 3587796.98 + P-621 4305429.40 3587978.75 + P-621 4305351.49 3588350.95 + P-623 4299277.97 3567910.07 + P-623 4299273.43 3567864.16 + P-623 4299266.78 3567824.30 + P-623 4299257.49 3567772.19 + P-623 4299224.02 3567626.24 + P-623 4299204.25 3567531.02 + P-623 4299188.38 3567431.65 + P-623 4299183.75 3567380.21 + P-623 4299182.18 3567328.62 + P-623 4299183.98 3567276.21 + P-63 4301927.82 3574748.94 + P-64 4302446.36 3575060.34 + P-65 4294785.29 3576378.62 + P-65 4294841.97 3576674.92 + P-66 4296456.62 3580745.66 + P-66 4296440.04 3580705.86 + P-69 4301767.74 3574394.04 + P-7 4301037.93 3574946.50 + P-7 4300990.89 3574712.90 + P-7 4300998.17 3574646.88 + P-70 4295834.05 3575805.04 + P-70 4295897.56 3575849.13 + P-70 4296029.70 3575951.32 + P-70 4296049.04 3575962.10 + P-70 4296067.33 3575968.13 + P-70 4296086.83 3575970.06 + P-70 4296111.87 3575968.24 + P-70 4296238.94 3575955.56 + P-70 4296698.04 3575919.28 + P-70 4296771.52 3575910.82 + P-71 4296781.68 3574837.34 + P-71 4296742.70 3574841.23 + P-71 4296702.83 3574840.66 + P-71 4296661.45 3574834.44 + P-71 4296587.49 3574809.86 + P-71 4296421.05 3574739.58 + P-71 4296393.20 3574732.70 + P-71 4296364.92 3574729.76 + P-71 4296337.35 3574730.58 + P-71 4296309.85 3574736.08 + P-71 4296257.61 3574752.80 + P-71 4296235.37 3574764.62 + P-71 4296162.00 3574811.79 + P-71 4296146.34 3574822.35 + P-71 4296127.50 3574835.88 + P-73 4300309.90 3569301.79 + P-73 4300320.41 3569326.34 + P-75 4287643.35 3570565.75 + P-75 4288080.06 3570503.42 + P-75 4288241.27 3570476.72 + P-75 4288325.05 3570456.37 + P-75 4288407.57 3570434.77 + P-76 4286322.07 3570435.59 + P-76 4286303.62 3570313.82 + P-76 4286263.03 3570177.28 + P-76 4286251.96 3570055.51 + P-76 4286237.20 3569948.50 + P-78 4293598.36 3577935.85 + P-78 4293666.84 3577933.74 + P-78 4293686.53 3577929.29 + P-78 4293736.43 3577909.15 + P-78 4293815.32 3577871.76 + P-78 4293871.46 3577856.29 + P-78 4294055.84 3577825.46 + P-78 4294164.23 3577803.59 + P-78 4294223.02 3577780.46 + P-78 4294272.49 3577753.77 + P-78 4294309.16 3577728.81 + P-78 4294336.02 3577700.23 + P-78 4294437.26 3577528.92 + P-78 4294478.36 3577478.11 + P-78 4294522.05 3577433.25 + P-78 4294586.11 3577379.51 + P-78 4294761.13 3577253.27 + P-78 4294809.88 3577223.44 + P-79 4298193.39 3574015.32 + P-79 4298201.31 3573977.02 + P-79 4298203.85 3573943.49 + P-79 4298200.26 3573907.81 + P-79 4298191.63 3573871.16 + P-79 4298162.11 3573791.39 + P-79 4298125.52 3573711.49 + P-79 4298103.00 3573679.08 + P-79 4298074.44 3573650.60 + P-79 4298041.24 3573626.03 + P-79 4298004.12 3573606.72 + P-79 4297964.81 3573592.07 + P-79 4297832.86 3573555.17 + P-79 4297785.03 3573538.33 + P-79 4297738.32 3573516.13 + P-79 4297694.96 3573487.56 + P-79 4297655.01 3573453.63 + P-79 4297618.48 3573415.36 + P-79 4297553.00 3573331.27 + P-79 4297526.71 3573296.12 + P-79 4297475.56 3573228.25 + P-79 4297281.07 3572965.90 + P-8 4310524.38 3561443.07 + P-8 4310182.93 3561713.59 + P-8 4309875.79 3561957.43 + P-8 4309569.88 3562189.83 + P-8 4309437.06 3562289.17 + P-8 4309295.72 3562380.34 + P-8 4309092.62 3562507.34 + P-8 4308455.43 3562873.14 + P-8 4308041.62 3563110.66 + P-8 4307840.09 3563236.23 + P-8 4307725.56 3563315.14 + P-8 4307597.39 3563445.94 + P-8 4307518.71 3563562.76 + P-8 4307465.41 3563670.68 + P-8 4307431.16 3563768.44 + P-8 4307352.53 3564050.31 + P-8 4307276.43 3564334.69 + P-8 4307214.27 3564520.07 + P-8 4307112.78 3564723.22 + P-8 4306857.72 3565149.84 + P-8 4304540.28 3567354.79 + P-80 4304082.47 3583223.81 + P-81 4296519.71 3573154.08 + P-83 4291642.89 3574363.58 + P-83 4291042.38 3574225.37 + P-83 4290849.40 3574180.99 + P-83 4290698.33 3574160.71 + P-83 4290601.84 3574160.75 + P-83 4290535.83 3574170.92 + P-83 4290409.56 3574195.85 + P-83 4290066.14 3574276.42 + P-83 4289906.24 3574307.99 + P-83 4289885.87 3574312.02 + P-83 4289871.08 3574314.22 + P-83 4289736.91 3574334.25 + P-83 4289640.74 3574348.61 + P-84 4294893.00 3570401.64 + P-84 4294862.55 3570485.44 + P-85 4286611.24 3570585.10 + P-85 4286833.40 3570600.26 + P-85 4287106.36 3570609.06 + P-85 4287407.25 3570593.74 + P-86 4299275.68 3568032.05 + P-86 4299249.05 3568155.20 + P-86 4299191.95 3568299.94 + P-86 4299142.70 3568369.62 + P-86 4299047.26 3568486.61 + P-86 4298966.04 3568547.58 + P-86 4298863.23 3568608.54 + P-89 4295654.80 3572575.37 + P-89 4295785.84 3572383.62 + P-89 4296029.61 3572071.52 + P-89 4296215.23 3571833.47 + P-89 4296403.91 3571587.00 + P-9 4291166.30 3570647.27 + P-9 4291152.37 3570747.57 + P-9 4291134.61 3570846.60 + P-9 4291094.03 3570948.16 + P-9 4291059.77 3571009.11 + P-9 4291019.16 3571073.87 + P-9 4290979.82 3571117.05 + P-9 4290901.12 3571184.35 + P-91 4292251.79 3574056.43 + P-92 4300937.85 3567408.02 + P-95 4294107.69 3575004.03 + P-95 4293519.39 3574868.31 + P-95 4293358.18 3574825.53 + P-95 4292969.63 3574692.00 + P-95 4292775.40 3574633.66 + P-96 4294934.24 3577222.75 + P-96 4294948.68 3577294.86 + P-96 4295014.13 3577570.98 + P-96 4295030.04 3577666.02 + P-96 4295037.64 3577762.66 + P-96 4295050.39 3578093.35 + P-96 4295057.40 3578465.68 + P-96 4295052.03 3579145.79 + P-96 4295055.41 3579165.17 + P-96 4295061.26 3579180.11 + P-96 4295068.09 3579190.60 + P-96 4295075.25 3579197.70 + P-98 4297092.56 3565769.48 + P-98 4296904.97 3565475.42 + P-98 4296728.95 3565205.76 + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + +[BACKDROP] + DIMENSIONS 4245026.86 3539217.45 4314960.81 3592403.55 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/benchmarks/small/synthetic10.inp b/benchmarks/small/synthetic10.inp new file mode 100644 index 0000000..9e4ab73 --- /dev/null +++ b/benchmarks/small/synthetic10.inp @@ -0,0 +1,354 @@ +[JUNCTIONS] +;ID Elev Demand Pattern +0 861.641021729 3.01063513756 ; +1 874.166534424 3.17381310463 ; +2 627.876037598 4.12776899338 ; +3 441.447444916 1.07248437405 ; +4 424.54621315 0.482213526964 ; +5 856.279815674 1.95303320885 ; +6 862.802124023 3.15825676918 ; +7 482.003379822 2.30877709389 ; +8 761.772277832 3.06876349449 ; +9 571.066635132 1.17128455639 ; +10 478.062835693 0.0220792945474 ; +11 508.671134949 4.35947418213 ; +12 868.147827148 1.60639047623 ; +13 760.43548584 3.3978073597 ; +14 594.946350098 4.63545751572 ; +15 713.551239014 3.5590672493 ; +16 624.152587891 3.32537412643 ; +17 856.35168457 4.02775144577 ; +18 841.601348877 4.93947219849 ; +19 670.981872559 3.92183756828 ; +20 832.436920166 4.67877483368 ; +21 516.746871948 1.64861941338 ; +22 734.780822754 1.61478245258 ; +23 865.094696045 3.46958994865 ; +24 739.790283203 3.55347800255 ; +25 730.51373291 4.44629621506 ; +26 790.360443115 2.88683342934 ; +27 801.061187744 1.35761010647 ; +28 635.147323608 1.21438968182 ; +29 424.849529266 1.46060013771 ; +30 730.729278564 0.672055244446 ; +31 423.282735825 3.129570961 ; +32 770.32434082 0.414074957371 ; +33 835.804656982 0.688569366932 ; +34 678.616912842 2.14836812019 ; +35 662.087615967 4.06809091568 ; +36 640.589065552 0.807814598083 ; +37 593.97996521 2.21497273445 ; +38 604.893310547 1.41965997219 ; +39 422.672115326 0.502704143524 ; +40 794.883331299 3.04834413528 ; +41 752.41394043 0.215073138475 ; +42 873.421630859 2.97773218155 ; +43 574.317062378 2.47021174431 ; +44 584.913452148 3.40577292442 ; +45 482.952758789 1.87001526356 ; +46 834.647064209 1.13778650761 ; +47 677.952484131 0.475274652243 ; +48 694.097442627 3.95662164688 ; +49 793.724822998 3.33144688606 ; +50 562.794174194 0.819016158581 ; +51 420.526456833 4.8816485405 ; +52 486.579826355 1.47186481953 ; +53 663.366119385 3.94360280037 ; +54 412.914263725 0.500408947468 ; +55 437.305091858 4.86747598648 ; +56 667.130615234 1.64732897282 ; +57 565.93737793 4.09628009796 ; +58 518.208030701 2.22400355339 ; +59 782.958587646 3.85632562637 ; +60 726.468383789 4.5429110527 ; +61 670.375030518 1.93360221386 ; +62 705.347229004 4.70733499527 ; +63 518.432678223 4.98169612885 ; +64 636.54598999 1.28482985497 ; +65 813.413787842 2.45842695236 ; +66 778.14553833 4.92095947266 ; +67 557.082595825 0.873581528664 ; +68 628.53616333 0.0743796750903 ; +69 409.919199944 2.11992120743 ; +70 851.560852051 3.83976840973 ; +71 898.818511963 1.43248975277 ; +72 485.434677124 4.00739622116 ; +73 631.289093018 2.75927329063 ; +74 410.815821648 2.8152525425 ; +75 494.950370789 3.30967569351 ; +76 472.134765625 3.6907582283 ; +77 457.444065094 4.62457513809 ; +78 424.054143906 2.7803041935 ; +79 757.477722168 1.28694581985 ; +80 869.872497559 1.47530698776 ; +81 448.657402039 2.85044646263 ; +82 645.107437134 0.208093672991 ; +83 643.036346436 2.12077260017 ; +84 782.659454346 3.57765555382 ; +85 865.613830566 0.717719614506 ; +86 671.398925781 4.01714849472 ; +87 521.631607056 2.62595033646 ; +88 834.40145874 4.85705375671 ; +89 650.831863403 2.31098437309 ; +90 471.463493347 0.869184374809 ; +91 738.181762695 3.21010041237 ; +92 615.828964233 4.37568235397 ; +93 609.712188721 1.32878267765 ; +94 685.217956543 1.58622097969 ; +95 861.663604736 1.80724573135 ; +96 838.038269043 1.09363663197 ; +97 475.100715637 2.17847394943 ; +98 761.05581665 2.65103316307 ; +99 491.393852234 0.565166890621 ; + +[RESERVOIRS] +;ID Head Pattern +100 905.322357178 ; +101 752.874267578 ; +102 558.07837677 ; +103 623.291221619 ; +104 655.622436523 ; + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status +P-V-1 0 1 651.21005249 4.74800133705 155 0 Open ; +P-V-2 1 2 332.863235474 11.6459569931 155 0 Open ; +P-V-3 2 3 430.845352173 7.35658884048 155 0 Open ; +P-V-4 3 4 659.601287842 5.37774324417 155 0 Open ; +P-V-5 4 5 336.714599609 10.2493057251 155 0 Open ; +P-V-6 5 6 354.111175537 13.9337244034 155 0 Open ; +P-V-7 6 7 555.600921631 14.697136879 155 0 Open ; +P-V-8 7 8 689.270385742 6.34994530678 155 0 Open ; +P-V-9 8 9 726.680725098 5.46273207664 155 0 Open ; +P-V-11 10 11 356.920349121 10.2083106041 155 0 Open ; +P-V-12 11 12 703.859680176 14.3893003464 155 0 Open ; +P-V-13 12 13 598.58807373 4.40367746353 155 0 Open ; +P-V-14 13 14 780.372680664 5.47289514542 155 0 Open ; +P-V-15 14 15 497.633636475 5.57267332077 155 0 Open ; +P-V-16 15 16 346.232727051 5.6705930233 155 0 Open ; +P-V-17 16 17 432.827819824 13.7456970215 155 0 Open ; +P-V-18 17 18 346.887527466 9.77361059189 155 0 Open ; +P-V-19 18 19 203.616585732 6.67917203903 155 0 Open ; +P-V-21 20 21 792.343383789 9.31083440781 155 0 Open ; +P-V-22 21 22 709.941253662 6.65257239342 155 0 Open ; +P-V-23 22 23 639.209106445 14.7492427826 155 0 Open ; +P-V-24 23 24 676.576080322 11.288359642 155 0 Open ; +P-V-25 24 25 523.205291748 9.22895097733 155 0 Open ; +P-V-26 25 26 299.231719971 10.7507419586 155 0 Open ; +P-V-27 26 27 536.166046143 9.85619544983 155 0 Open ; +P-V-28 27 28 603.848937988 8.78499126434 155 0 Open ; +P-V-29 28 29 417.401855469 12.4622249603 155 0 Open ; +P-V-31 30 31 581.379882812 4.04598104954 155 0 Open ; +P-V-32 31 32 790.137817383 11.9273900986 155 0 Open ; +P-V-33 32 33 532.05682373 8.57962703705 155 0 Open ; +P-V-34 33 34 639.92086792 13.9999427795 155 0 Open ; +P-V-35 34 35 401.912826538 13.9789037704 155 0 Open ; +P-V-36 35 36 721.999084473 3.77853858471 155 0 Open ; +P-V-37 36 37 444.901519775 4.20038795471 155 0 Open ; +P-V-38 37 38 346.116821289 14.7092676163 155 0 Open ; +P-V-39 38 39 683.058441162 6.26348233223 155 0 Open ; +P-V-41 40 41 667.360351562 9.51911830902 155 0 Open ; +P-V-42 41 42 541.172149658 12.6061973572 155 0 Open ; +P-V-43 42 43 368.348876953 11.7917413712 155 0 Open ; +P-V-44 43 44 540.396881104 4.0083874464 155 0 Open ; +P-V-45 44 45 398.3878479 5.09164237976 155 0 Open ; +P-V-46 45 46 511.801422119 3.93524158001 155 0 Open ; +P-V-47 46 47 730.262145996 9.3113451004 155 0 Open ; +P-V-48 47 48 539.083007812 6.35716605186 155 0 Open ; +P-V-49 48 49 794.719909668 4.16831791401 155 0 Open ; +P-V-51 50 51 395.951675415 14.1938009262 155 0 Open ; +P-V-52 51 52 711.237243652 10.2938933372 155 0 Open ; +P-V-53 52 53 623.193664551 7.32323312759 155 0 Open ; +P-V-54 53 54 228.880636215 14.9371213913 155 0 Open ; +P-V-55 54 55 760.479248047 14.4974336624 155 0 Open ; +P-V-56 55 56 268.543930054 3.35744789243 155 0 Open ; +P-V-57 56 57 581.327148438 10.308078289 155 0 Open ; +P-V-58 57 58 543.832519531 6.86821770668 155 0 Open ; +P-V-59 58 59 656.997039795 5.99527359009 155 0 Open ; +P-V-61 60 61 278.383300781 10.7645049095 155 0 Open ; +P-V-62 61 62 701.786682129 13.5844163895 155 0 Open ; +P-V-63 62 63 414.461029053 7.93205738068 155 0 Open ; +P-V-64 63 64 654.435852051 9.07292938232 155 0 Open ; +P-V-65 64 65 586.150909424 11.762676239 155 0 Open ; +P-V-66 65 66 715.569396973 14.5072259903 155 0 Open ; +P-V-67 66 67 698.121459961 5.55260920525 155 0 Open ; +P-V-68 67 68 285.237411499 10.704079628 155 0 Open ; +P-V-69 68 69 323.102386475 6.63702535629 155 0 Open ; +P-V-71 70 71 774.203186035 7.67506599426 155 0 Open ; +P-V-72 71 72 691.611480713 13.2882127762 155 0 Open ; +P-V-73 72 73 499.507171631 11.3448915482 155 0 Open ; +P-V-74 73 74 630.432800293 4.69214034081 155 0 Open ; +P-V-75 74 75 790.14855957 3.54364198446 155 0 Open ; +P-V-76 75 76 449.576293945 3.57480084896 155 0 Open ; +P-V-77 76 77 233.918693542 4.42966139317 155 0 Open ; +P-V-78 77 78 415.994567871 7.41427183151 155 0 Open ; +P-V-79 78 79 533.552886963 7.47581911087 155 0 Open ; +P-V-81 80 81 654.876434326 13.1703128815 155 0 Open ; +P-V-82 81 82 422.560699463 6.55709218979 155 0 Open ; +P-V-83 82 83 202.52795434 12.7465705872 155 0 Open ; +P-V-84 83 84 730.927001953 4.80352520943 155 0 Open ; +P-V-85 84 85 792.368164062 5.64178562164 155 0 Open ; +P-V-86 85 86 224.562267303 3.36109998822 155 0 Open ; +P-V-87 86 87 650.370513916 10.5559859276 155 0 Open ; +P-V-88 87 88 672.725524902 12.9650707245 155 0 Open ; +P-V-89 88 89 747.350036621 5.23266506195 155 0 Open ; +P-V-91 90 91 220.048116684 9.97417163849 155 0 Open ; +P-V-92 91 92 745.386413574 5.20010232925 155 0 Open ; +P-V-93 92 93 456.030822754 13.1985702515 155 0 Open ; +P-V-94 93 94 768.611816406 12.1893930435 155 0 Open ; +P-V-95 94 95 506.563537598 7.27057123184 155 0 Open ; +P-V-96 95 96 374.650604248 6.05759263039 155 0 Open ; +P-V-97 96 97 448.190414429 5.72460246086 155 0 Open ; +P-V-98 97 98 219.741661072 14.9622154236 155 0 Open ; +P-V-99 98 99 248.39956665 12.0300979614 155 0 Open ; +P-H-11 1 11 332.624008179 3.23546107113 155 0 Open ; +P-H-12 2 12 278.616966248 5.30700397491 155 0 Open ; +P-H-16 6 16 657.702575684 3.15248219669 155 0 Open ; +P-H-17 7 17 603.810211182 7.77052164078 155 0 Open ; +P-H-18 8 18 668.597351074 5.3232228756 155 0 Open ; +P-H-19 9 19 628.590576172 9.43508625031 155 0 Open ; +P-H-20 10 20 779.318054199 10.9817576408 155 0 Open ; +P-H-23 13 23 223.869297028 10.4256224632 155 0 Open ; +P-H-25 15 25 480.424285889 4.82362723351 155 0 Open ; +P-H-33 23 33 648.276550293 14.6778802872 155 0 Open ; +P-H-34 24 34 479.13104248 14.1158351898 155 0 Open ; +P-H-35 25 35 493.269897461 14.7454681396 155 0 Open ; +P-H-36 26 36 434.13130188 7.89731025696 155 0 Open ; +P-H-38 28 38 511.546844482 14.3537998199 155 0 Open ; +P-H-39 29 39 452.293945312 5.08527517319 155 0 Open ; +P-H-40 30 40 328.219558716 10.7254772186 155 0 Open ; +P-H-44 34 44 210.115700722 7.29191017151 155 0 Open ; +P-H-51 41 51 258.377536774 6.02571582794 155 0 Open ; +P-H-52 42 52 545.242736816 12.8935594559 155 0 Open ; +P-H-53 43 53 529.024597168 9.33596849442 155 0 Open ; +P-H-55 45 55 586.340148926 3.37838029861 155 0 Open ; +P-H-56 46 56 534.802520752 7.52175331116 155 0 Open ; +P-H-61 51 61 326.2786026 6.29169273376 155 0 Open ; +P-H-63 53 63 462.09564209 11.829955101 155 0 Open ; +P-H-70 60 70 369.696304321 8.7149066925 155 0 Open ; +P-H-72 62 72 302.727760315 9.91230010986 155 0 Open ; +P-H-75 65 75 367.618865967 6.41121077538 155 0 Open ; +P-H-76 66 76 353.627563477 7.36635446548 155 0 Open ; +P-H-82 72 82 615.676330566 12.4489660263 155 0 Open ; +P-H-84 74 84 699.204620361 9.63749885559 155 0 Open ; +P-H-87 77 87 634.813293457 13.140619278 155 0 Open ; +P-H-88 78 88 727.153259277 8.29072523117 155 0 Open ; +P-H-91 81 91 313.179222107 7.06489992142 155 0 Open ; +P-H-93 83 93 292.195083618 9.45640802383 155 0 Open ; +P-H-94 84 94 796.25402832 3.84212207794 155 0 Open ; +P-H-97 87 97 542.175048828 13.7245798111 155 0 Open ; +P-H-98 88 98 263.700561523 7.30709838867 155 0 Open ; +P-S-0 100 0 30 30 155 0 Open ; +P-S-1 101 10 30 30 155 0 Open ; +P-S-2 102 20 30 30 155 0 Open ; +P-S-3 103 30 30 30 155 0 Open ; +P-S-4 104 40 30 30 155 0 Open ; + +[PUMPS] +;ID Node1 Node2 Parameters + +[CURVES] +;ID X-Value Y-Value +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers + +[CONTROLS] + + + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0:30 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/benchmarks/small/synthetic20.inp b/benchmarks/small/synthetic20.inp new file mode 100644 index 0000000..554ca79 --- /dev/null +++ b/benchmarks/small/synthetic20.inp @@ -0,0 +1,1087 @@ +[JUNCTIONS] +;ID Elev Demand Pattern +0 446.356853485 1.19704723358 ; +1 777.329437256 2.76274299622 ; +2 741.832641602 1.81736850739 ; +3 851.238464355 4.65131807327 ; +4 870.450592041 3.63451600075 ; +5 431.143129349 4.2259850502 ; +6 512.981697083 3.83418917656 ; +7 521.556381226 4.98162889481 ; +8 523.580177307 0.120489194989 ; +9 406.19324255 0.898385107517 ; +10 815.84072876 0.352005183697 ; +11 515.092163086 3.54034876823 ; +12 664.214324951 1.50177955627 ; +13 440.93270874 4.56077671051 ; +14 697.755096436 3.70133495331 ; +15 733.578308105 4.50658369064 ; +16 615.224899292 2.85119891167 ; +17 409.786104202 4.75070953369 ; +18 418.26049614 4.04195022583 ; +19 706.087371826 4.10602664948 ; +20 899.2371521 1.7910015583 ; +21 536.210861206 2.96155714989 ; +22 889.337341309 2.92990207672 ; +23 686.610473633 0.621897637844 ; +24 623.361953735 0.447398543358 ; +25 842.735290527 0.522246658802 ; +26 640.018554688 4.91855144501 ; +27 509.413551331 4.13704013824 ; +28 523.38470459 2.26934337616 ; +29 485.389038086 1.33649814129 ; +30 652.290924072 2.53680372238 ; +31 506.110534668 3.99901151657 ; +32 538.741210938 3.23476243019 ; +33 565.207992554 1.50802361965 ; +34 435.287769318 0.81585496664 ; +35 607.470458984 4.56079244614 ; +36 723.922546387 1.66728150845 ; +37 599.973068237 4.4737443924 ; +38 422.483200073 3.75159358978 ; +39 703.460418701 2.59251832962 ; +40 645.793411255 0.498926192522 ; +41 445.283462524 0.792426884174 ; +42 731.871887207 2.70951676369 ; +43 785.187652588 3.48752140999 ; +44 877.303009033 0.318758159876 ; +45 636.838760376 0.492109060287 ; +46 487.717575073 2.69303607941 ; +47 586.140686035 4.66644763947 ; +48 799.016967773 2.78223013878 ; +49 494.025802612 2.91754460335 ; +50 417.23434639 1.57686853409 ; +51 643.085769653 0.427954941988 ; +52 663.875244141 4.512819767 ; +53 595.89163208 3.51036214828 ; +54 765.792907715 3.81936001778 ; +55 598.706512451 1.60647928715 ; +56 409.801776886 2.3846745491 ; +57 822.520446777 3.01313519478 ; +58 576.277252197 1.91977787018 ; +59 470.653038025 4.65658855438 ; +60 728.257080078 0.166941598058 ; +61 478.750244141 0.554081380367 ; +62 644.612411499 2.00913167 ; +63 647.741760254 2.96067261696 ; +64 402.741997004 0.847457885742 ; +65 722.475463867 3.45581293106 ; +66 584.917236328 4.04174375534 ; +67 859.019195557 2.35849666595 ; +68 825.61907959 3.80349874496 ; +69 440.300590515 3.32078814507 ; +70 648.786712646 3.58255982399 ; +71 608.197219849 1.7102637291 ; +72 840.233612061 0.0630412921309 ; +73 853.496582031 4.17411184311 ; +74 830.350860596 4.07081508636 ; +75 718.827270508 0.299382954836 ; +76 572.936325073 0.410693347454 ; +77 652.365722656 0.109474673867 ; +78 894.086791992 1.16885173321 ; +79 889.184020996 2.16330313683 ; +80 763.695678711 1.33174133301 ; +81 657.729064941 1.52701127529 ; +82 847.738861084 1.4731760025 ; +83 867.013397217 0.947543680668 ; +84 436.668754578 2.9173617363 ; +85 610.041519165 1.67964458466 ; +86 878.584289551 0.664673686028 ; +87 517.039581299 0.842593967915 ; +88 547.660598755 2.32034420967 ; +89 702.567443848 2.51077437401 ; +90 758.66293335 0.486278951168 ; +91 689.001525879 2.48557138443 ; +92 899.883300781 0.390249192715 ; +93 791.802825928 0.304708123207 ; +94 522.945259094 3.40994000435 ; +95 486.273628235 0.00961298309267 ; +96 556.54145813 4.92553567886 ; +97 747.99307251 2.1946413517 ; +98 433.814651489 3.22878098488 ; +99 511.986236572 1.52723240852 ; +100 719.557922363 3.10325598717 ; +101 542.462936401 3.74546861649 ; +102 408.967349052 2.14239835739 ; +103 629.190948486 0.123657926917 ; +104 731.880981445 4.23914146423 ; +105 625.487991333 2.76971793175 ; +106 464.806396484 2.01147413254 ; +107 584.655960083 0.127125114202 ; +108 559.17640686 2.7790749073 ; +109 691.445404053 3.22998285294 ; +110 532.300842285 0.804300963879 ; +111 688.640014648 1.72680580616 ; +112 642.662963867 4.36823940277 ; +113 600.286178589 2.09981679916 ; +114 561.986419678 0.0590975023806 ; +115 725.168365479 1.05032539368 ; +116 681.864135742 2.90727543831 ; +117 658.200042725 0.684553444386 ; +118 428.960426331 2.3789741993 ; +119 742.093566895 0.667850196362 ; +120 855.863861084 2.04512453079 ; +121 640.841186523 3.18052101135 ; +122 402.089675903 1.21184229851 ; +123 643.492919922 3.85589718819 ; +124 506.262413025 4.52412796021 ; +125 601.810684204 3.32270240784 ; +126 865.858825684 1.89530062675 ; +127 831.714752197 3.30329227448 ; +128 743.391662598 3.84119796753 ; +129 801.736938477 4.93035888672 ; +130 854.100219727 0.627689063549 ; +131 857.040893555 4.86466884613 ; +132 448.765228271 0.972482562065 ; +133 851.489746094 1.88768947124 ; +134 539.733352661 4.98667287827 ; +135 501.212921143 0.856946349144 ; +136 669.669403076 3.33839821815 ; +137 746.146881104 1.9125970602 ; +138 402.000324249 1.19452679157 ; +139 541.166213989 0.807616055012 ; +140 760.298797607 0.4213090837 ; +141 494.178863525 3.64266395569 ; +142 625.121414185 1.15881729126 ; +143 524.148750305 0.681983947754 ; +144 610.502914429 4.2254242897 ; +145 570.596832275 2.21041893959 ; +146 451.302894592 2.47802782059 ; +147 721.372497559 3.07984375954 ; +148 693.387908936 4.70983314514 ; +149 716.669342041 2.61560940742 ; +150 454.688491821 1.49549615383 ; +151 880.440887451 2.70491170883 ; +152 545.264541626 4.6124792099 ; +153 593.694290161 4.19984531403 ; +154 579.947433472 3.76575398445 ; +155 502.811477661 4.52665472031 ; +156 848.754730225 2.21086072922 ; +157 693.724029541 1.19692730904 ; +158 575.64390564 0.474738329649 ; +159 792.6796875 2.67837190628 ; +160 439.53036499 3.86900162697 ; +161 530.690765381 0.196979105473 ; +162 462.764717102 3.8667011261 ; +163 664.444793701 0.235107153654 ; +164 544.58706665 0.748745858669 ; +165 817.245056152 1.38066673279 ; +166 886.565551758 2.07579851151 ; +167 694.520751953 0.107396632433 ; +168 401.530388355 2.2123734951 ; +169 736.12789917 3.01708817482 ; +170 720.164276123 0.0147929554805 ; +171 762.520263672 3.78475046158 ; +172 430.152259827 2.69039535522 ; +173 647.423187256 4.41637182236 ; +174 496.139373779 3.14552760124 ; +175 588.094726562 3.08187651634 ; +176 610.192901611 2.12379693985 ; +177 865.811950684 4.01555538177 ; +178 844.128936768 4.75279998779 ; +179 430.809371948 3.13122677803 ; +180 552.939056396 4.46986150742 ; +181 896.676483154 1.4203646183 ; +182 606.891784668 2.3030102253 ; +183 569.592666626 3.44270968437 ; +184 562.257644653 0.644293963909 ; +185 764.867980957 3.36379623413 ; +186 432.428817749 0.311453253031 ; +187 859.511566162 0.109594762325 ; +188 595.921020508 3.44903588295 ; +189 694.838104248 3.44582486153 ; +190 797.981262207 3.71630334854 ; +191 891.336608887 3.94884443283 ; +192 722.748962402 4.4241104126 ; +193 502.089813232 3.23573613167 ; +194 701.979614258 3.71894574165 ; +195 832.147674561 1.06250369549 ; +196 650.050262451 0.949915647507 ; +197 423.25689888 3.78722763062 ; +198 593.4559021 4.13513469696 ; +199 821.21005249 2.77839994431 ; +200 556.602294922 0.148730635643 ; +201 871.569244385 1.64675855637 ; +202 607.297134399 0.432650506496 ; +203 555.700332642 3.55716252327 ; +204 423.198863983 4.03338003159 ; +205 801.995178223 3.3341896534 ; +206 672.568725586 0.625757813454 ; +207 611.128601074 4.38443470001 ; +208 819.635406494 3.12209248543 ; +209 701.061828613 4.46351623535 ; +210 732.082244873 3.06560969353 ; +211 770.20803833 0.866856873035 ; +212 826.300201416 3.27980184555 ; +213 763.017578125 2.36853480339 ; +214 696.75112915 4.96418714523 ; +215 710.039337158 3.31163287163 ; +216 761.596893311 3.59121346474 ; +217 652.38923645 4.06155633926 ; +218 657.774658203 4.18840026855 ; +219 844.895751953 3.63517904282 ; +220 545.727676392 2.45159125328 ; +221 789.336761475 0.833066523075 ; +222 534.905197144 3.51724624634 ; +223 835.553741455 3.51837015152 ; +224 724.534057617 4.43921041489 ; +225 880.704345703 1.98412203789 ; +226 613.8934021 4.06583547592 ; +227 849.507537842 3.73511576653 ; +228 509.316680908 2.85568761826 ; +229 454.241714478 1.40547454357 ; +230 581.144729614 4.99716472626 ; +231 634.840713501 4.68080043793 ; +232 421.330991745 0.100021548569 ; +233 506.212844849 1.19291865826 ; +234 838.49395752 2.67919921875 ; +235 829.990509033 3.50723910332 ; +236 516.85055542 4.07410860062 ; +237 754.848693848 4.42070293427 ; +238 775.617584229 0.0513604916632 ; +239 721.585388184 3.86192560196 ; +240 638.589187622 4.686855793 ; +241 598.334594727 4.09738540649 ; +242 875.718475342 4.01038265228 ; +243 650.128372192 4.07943248749 ; +244 702.595794678 2.27574205399 ; +245 739.587371826 4.45261716843 ; +246 414.30848217 4.82656097412 ; +247 401.504130125 2.79916214943 ; +248 451.792297363 4.73195552826 ; +249 897.875244141 2.89728856087 ; +250 872.962402344 0.796113312244 ; +251 427.632772446 4.24010801315 ; +252 749.71395874 1.42989599705 ; +253 626.334823608 0.096508204937 ; +254 601.354202271 1.60049140453 ; +255 845.990936279 2.69760966301 ; +256 772.789703369 4.76425123215 ; +257 677.197509766 3.58666300774 ; +258 504.332069397 0.0920863002539 ; +259 669.437866211 4.42197275162 ; +260 409.837198257 3.33811545372 ; +261 770.526702881 4.42567539215 ; +262 633.162536621 2.62960481644 ; +263 476.997825623 1.02569663525 ; +264 788.404510498 4.14989709854 ; +265 632.651565552 1.7494071722 ; +266 628.619247437 4.03826570511 ; +267 513.617492676 0.691834807396 ; +268 666.748809814 2.4724316597 ; +269 815.802368164 3.90718579292 ; +270 707.08303833 1.44765424728 ; +271 472.475761414 1.00095152855 ; +272 699.336547852 4.49543952942 ; +273 885.482757568 0.0935386046767 ; +274 610.329803467 0.13332273066 ; +275 475.526039124 3.66280889511 ; +276 482.91443634 0.430791676044 ; +277 431.589830399 4.30289745331 ; +278 779.69833374 0.903021395206 ; +279 608.083099365 2.52818489075 ; +280 520.279762268 0.420580774546 ; +281 770.087768555 0.649740636349 ; +282 419.098194122 4.83348083496 ; +283 531.614074707 0.377015680075 ; +284 550.259262085 4.076359272 ; +285 536.945556641 1.43959391117 ; +286 425.371017456 4.10713148117 ; +287 755.448455811 0.224652156234 ; +288 472.897155762 1.82544541359 ; +289 426.103351593 2.19048380852 ; +290 446.41652298 1.22548282146 ; +291 569.119857788 3.97641706467 ; +292 564.461868286 1.10853517056 ; +293 515.017402649 0.975973844528 ; +294 719.243591309 0.273580878973 ; +295 707.403839111 0.365507781506 ; +296 708.941162109 3.74491024017 ; +297 470.796981812 3.84961748123 ; +298 452.403465271 2.45101737976 ; +299 824.830657959 1.29371464252 ; +300 746.208526611 2.26766633987 ; +301 666.749542236 2.59632277489 ; +302 540.121002197 0.139436081052 ; +303 750.241851807 0.15302246809 ; +304 584.867706299 0.717226266861 ; +305 842.183349609 2.7575442791 ; +306 504.33706665 0.931425213814 ; +307 846.446777344 4.31475162506 ; +308 703.176971436 4.96049165726 ; +309 498.320487976 4.72554159164 ; +310 617.818588257 3.77264881134 ; +311 590.960342407 4.7059969902 ; +312 769.286743164 1.02844119072 ; +313 401.250921965 0.242457523942 ; +314 898.342681885 1.45396125317 ; +315 572.815505981 0.103300005198 ; +316 516.325073242 0.755762279034 ; +317 609.756088257 3.70724892616 ; +318 673.270751953 3.61582684517 ; +319 520.150978088 3.77566099167 ; +320 653.24772644 3.34646511078 ; +321 804.012908936 2.45100450516 ; +322 803.206420898 1.90462827682 ; +323 508.703300476 4.76452112198 ; +324 630.872558594 2.75400495529 ; +325 555.846405029 3.10730910301 ; +326 854.27255249 4.58830785751 ; +327 468.627609253 4.24286603928 ; +328 884.932037354 2.53013014793 ; +329 789.839416504 0.315083414316 ; +330 460.698600769 1.61386668682 ; +331 825.733978271 3.10946917534 ; +332 484.573066711 4.19549894333 ; +333 775.354370117 0.81229954958 ; +334 631.841873169 0.663872361183 ; +335 670.293609619 3.24751281738 ; +336 495.027938843 1.34633302689 ; +337 681.888031006 1.92212474346 ; +338 415.194018364 3.65878605843 ; +339 722.077941895 1.64409422874 ; +340 629.393005371 4.085521698 ; +341 436.974521637 4.30835437775 ; +342 451.710067749 0.91125279665 ; +343 442.560390472 3.1247446537 ; +344 658.190856934 4.14005851746 ; +345 596.480316162 2.44666576385 ; +346 511.065132141 1.71738314629 ; +347 805.801269531 3.02533769608 ; +348 585.086151123 2.43131136894 ; +349 705.134735107 3.99436020851 ; +350 721.098327637 1.99966859818 ; +351 742.94720459 4.13776016235 ; +352 733.345306396 0.347501635551 ; +353 446.003051758 1.73370242119 ; +354 733.578460693 4.53366279602 ; +355 627.299606323 2.24561357498 ; +356 602.731735229 3.12535142899 ; +357 678.138946533 1.81632244587 ; +358 593.279403687 4.47159099579 ; +359 802.979156494 3.70818972588 ; +360 754.275604248 3.10165500641 ; +361 851.287567139 2.90715932846 ; +362 462.877361298 2.79876637459 ; +363 786.934387207 2.06555008888 ; +364 470.149475098 0.0237183179706 ; +365 763.37701416 2.77773547173 ; +366 440.440731049 1.87448132038 ; +367 840.741729736 0.467865377665 ; +368 741.349975586 0.694272756577 ; +369 764.236602783 2.24687719345 ; +370 726.632232666 2.08636975288 ; +371 461.462947845 0.0780830904841 ; +372 634.250228882 0.437468498945 ; +373 653.315917969 4.80520915985 ; +374 514.650527954 4.31533670425 ; +375 686.321594238 2.07226800919 ; +376 761.091949463 3.72801327705 ; +377 571.798690796 4.20771837234 ; +378 812.12689209 1.16900348663 ; +379 644.139755249 2.57085776329 ; +380 740.474151611 3.49196720123 ; +381 849.63861084 0.766345381737 ; +382 896.678955078 1.83766663074 ; +383 466.378166199 1.17878985405 ; +384 592.096084595 0.59180855751 ; +385 552.639144897 4.06323051453 ; +386 471.538330078 3.44815540314 ; +387 714.949981689 3.64222502708 ; +388 887.607421875 2.18184947968 ; +389 434.41437149 4.02341651917 ; +390 556.268997192 4.1309838295 ; +391 844.710144043 2.43880176544 ; +392 794.147064209 4.3010020256 ; +393 594.851303101 3.65870738029 ; +394 589.479705811 0.854338169098 ; +395 786.221710205 2.28692102432 ; +396 528.054656982 2.14821100235 ; +397 898.299835205 4.25659751892 ; +398 463.204502106 2.78084993362 ; +399 674.242980957 2.02122092247 ; + +[RESERVOIRS] +;ID Head Pattern +400 812.475524902 ; +401 776.031066895 ; +402 754.393920898 ; +403 598.812255859 ; +404 737.642272949 ; + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status +P-V-1 0 1 279.324569702 3.16041502357 155 0 Open ; +P-V-2 1 2 604.776062012 8.42910528183 155 0 Open ; +P-V-3 2 3 748.833862305 12.0243330002 155 0 Open ; +P-V-4 3 4 398.507888794 9.44452762604 155 0 Open ; +P-V-5 4 5 258.814975739 9.06616401672 155 0 Open ; +P-V-6 5 6 301.192100525 9.71171808243 155 0 Open ; +P-V-7 6 7 392.485717773 13.1510810852 155 0 Open ; +P-V-8 7 8 461.820373535 3.30555394292 155 0 Open ; +P-V-9 8 9 772.27947998 9.04137229919 155 0 Open ; +P-V-10 9 10 467.489471436 12.9138936996 155 0 Open ; +P-V-11 10 11 340.945343018 4.36890864372 155 0 Open ; +P-V-12 11 12 362.482589722 7.89981412888 155 0 Open ; +P-V-13 12 13 559.043029785 7.72737646103 155 0 Open ; +P-V-14 13 14 250.850006104 7.72152757645 155 0 Open ; +P-V-15 14 15 735.991882324 3.30227467418 155 0 Open ; +P-V-16 15 16 416.52255249 4.89435052872 155 0 Open ; +P-V-17 16 17 317.401802063 10.4434580803 155 0 Open ; +P-V-18 17 18 309.99911499 6.10441827774 155 0 Open ; +P-V-19 18 19 797.986999512 10.3515543938 155 0 Open ; +P-V-21 20 21 478.850372314 3.76663774252 155 0 Open ; +P-V-22 21 22 644.041290283 7.04716157913 155 0 Open ; +P-V-23 22 23 432.234603882 6.34092235565 155 0 Open ; +P-V-24 23 24 343.976089478 3.12363861501 155 0 Open ; +P-V-25 24 25 299.705474854 13.9993867874 155 0 Open ; +P-V-26 25 26 535.063659668 11.2930440903 155 0 Open ; +P-V-27 26 27 260.045909882 14.8327512741 155 0 Open ; +P-V-28 27 28 652.976104736 10.3877511024 155 0 Open ; +P-V-29 28 29 297.123931885 10.240208149 155 0 Open ; +P-V-30 29 30 509.013153076 14.6835384369 155 0 Open ; +P-V-31 30 31 661.636444092 5.47657942772 155 0 Open ; +P-V-32 31 32 593.504272461 11.5251846313 155 0 Open ; +P-V-33 32 33 339.049163818 14.9858894348 155 0 Open ; +P-V-34 33 34 342.717163086 11.9490661621 155 0 Open ; +P-V-35 34 35 748.087768555 13.2328062057 155 0 Open ; +P-V-36 35 36 739.436218262 9.10103178024 155 0 Open ; +P-V-37 36 37 202.3344028 7.68615102768 155 0 Open ; +P-V-38 37 38 407.130630493 3.8946455121 155 0 Open ; +P-V-39 38 39 215.414361954 12.3835916519 155 0 Open ; +P-V-41 40 41 501.516021729 14.595580101 155 0 Open ; +P-V-42 41 42 545.441864014 7.83737945557 155 0 Open ; +P-V-43 42 43 292.159217834 9.39894723892 155 0 Open ; +P-V-44 43 44 355.599609375 10.2536015511 155 0 Open ; +P-V-45 44 45 363.793899536 4.68512606621 155 0 Open ; +P-V-46 45 46 295.666915894 12.477853775 155 0 Open ; +P-V-47 46 47 514.169952393 8.09582042694 155 0 Open ; +P-V-48 47 48 272.797950745 5.303388834 155 0 Open ; +P-V-49 48 49 252.798160553 14.5739421844 155 0 Open ; +P-V-50 49 50 362.140777588 13.0047998428 155 0 Open ; +P-V-51 50 51 534.101226807 11.7948923111 155 0 Open ; +P-V-52 51 52 787.764892578 6.29269862175 155 0 Open ; +P-V-53 52 53 619.247344971 12.8139381409 155 0 Open ; +P-V-54 53 54 342.72328186 14.0084657669 155 0 Open ; +P-V-55 54 55 364.458831787 12.1948671341 155 0 Open ; +P-V-56 55 56 307.49193573 3.34081578255 155 0 Open ; +P-V-57 56 57 404.557067871 14.8182830811 155 0 Open ; +P-V-58 57 58 494.437530518 11.2336912155 155 0 Open ; +P-V-59 58 59 782.907653809 5.58625435829 155 0 Open ; +P-V-61 60 61 358.840042114 7.49289417267 155 0 Open ; +P-V-62 61 62 603.785675049 11.5181779861 155 0 Open ; +P-V-63 62 63 451.662887573 8.96327590942 155 0 Open ; +P-V-64 63 64 239.095954895 4.71427822113 155 0 Open ; +P-V-65 64 65 793.744445801 12.2745008469 155 0 Open ; +P-V-66 65 66 626.888885498 13.4357481003 155 0 Open ; +P-V-67 66 67 281.043807983 5.06672143936 155 0 Open ; +P-V-68 67 68 569.338897705 12.5768823624 155 0 Open ; +P-V-69 68 69 333.801330566 14.9807052612 155 0 Open ; +P-V-70 69 70 786.553771973 7.1868519783 155 0 Open ; +P-V-71 70 71 221.269784927 12.6258325577 155 0 Open ; +P-V-72 71 72 668.878845215 3.93548083305 155 0 Open ; +P-V-73 72 73 331.313720703 6.79613757133 155 0 Open ; +P-V-74 73 74 684.204833984 7.621945858 155 0 Open ; +P-V-75 74 75 452.281829834 13.019068718 155 0 Open ; +P-V-76 75 76 525.097595215 9.30803394318 155 0 Open ; +P-V-77 76 77 756.606750488 8.8099694252 155 0 Open ; +P-V-78 77 78 408.062316895 5.06687402725 155 0 Open ; +P-V-79 78 79 697.656890869 5.39606881142 155 0 Open ; +P-V-81 80 81 736.421936035 3.86276561022 155 0 Open ; +P-V-82 81 82 425.071487427 10.5315589905 155 0 Open ; +P-V-83 82 83 545.979370117 8.51287078857 155 0 Open ; +P-V-84 83 84 341.030380249 8.95237445831 155 0 Open ; +P-V-85 84 85 677.975402832 13.6575345993 155 0 Open ; +P-V-86 85 86 659.633544922 4.23185312748 155 0 Open ; +P-V-87 86 87 387.865386963 8.0688662529 155 0 Open ; +P-V-88 87 88 421.939163208 13.6356706619 155 0 Open ; +P-V-89 88 89 286.250320435 3.18175891042 155 0 Open ; +P-V-90 89 90 541.105133057 14.080529213 155 0 Open ; +P-V-91 90 91 323.102539062 6.68792796135 155 0 Open ; +P-V-92 91 92 350.291931152 14.1320810318 155 0 Open ; +P-V-93 92 93 444.634384155 10.4063248634 155 0 Open ; +P-V-94 93 94 305.034576416 5.32307624817 155 0 Open ; +P-V-95 94 95 597.238769531 6.83596396446 155 0 Open ; +P-V-96 95 96 552.278320312 13.8411540985 155 0 Open ; +P-V-97 96 97 763.780456543 8.17341184616 155 0 Open ; +P-V-98 97 98 676.769042969 4.14413571358 155 0 Open ; +P-V-99 98 99 474.497436523 4.56986618042 155 0 Open ; +P-V-101 100 101 637.003051758 5.21121191978 155 0 Open ; +P-V-102 101 102 791.972045898 4.49909090996 155 0 Open ; +P-V-103 102 103 561.04675293 9.26117753983 155 0 Open ; +P-V-104 103 104 380.476043701 8.21602678299 155 0 Open ; +P-V-105 104 105 488.165466309 14.9431743622 155 0 Open ; +P-V-106 105 106 446.814727783 11.3016023636 155 0 Open ; +P-V-107 106 107 251.743579865 8.08778142929 155 0 Open ; +P-V-108 107 108 717.173034668 13.5502567291 155 0 Open ; +P-V-109 108 109 508.185394287 12.4416475296 155 0 Open ; +P-V-110 109 110 689.120330811 3.91391056776 155 0 Open ; +P-V-111 110 111 204.738149166 11.6813268661 155 0 Open ; +P-V-112 111 112 753.522155762 3.94101428986 155 0 Open ; +P-V-113 112 113 781.383911133 9.38181686401 155 0 Open ; +P-V-114 113 114 359.929397583 13.6662025452 155 0 Open ; +P-V-115 114 115 744.012634277 11.4227771759 155 0 Open ; +P-V-116 115 116 681.408813477 3.76321673393 155 0 Open ; +P-V-117 116 117 769.179504395 11.0066375732 155 0 Open ; +P-V-118 117 118 778.111633301 13.4471321106 155 0 Open ; +P-V-119 118 119 248.104030609 8.6895236969 155 0 Open ; +P-V-121 120 121 591.422485352 7.75498342514 155 0 Open ; +P-V-122 121 122 650.448394775 12.7249536514 155 0 Open ; +P-V-123 122 123 565.221130371 8.43605184555 155 0 Open ; +P-V-124 123 124 586.195556641 14.7822618484 155 0 Open ; +P-V-125 124 125 224.030702591 4.68105137348 155 0 Open ; +P-V-126 125 126 471.530181885 3.15792700648 155 0 Open ; +P-V-127 126 127 313.961524963 6.02705669403 155 0 Open ; +P-V-128 127 128 587.009490967 12.3694658279 155 0 Open ; +P-V-129 128 129 631.033233643 14.5119762421 155 0 Open ; +P-V-130 129 130 489.593261719 14.883936882 155 0 Open ; +P-V-131 130 131 466.372833252 9.56870603561 155 0 Open ; +P-V-132 131 132 212.484307289 11.4751224518 155 0 Open ; +P-V-133 132 133 269.606468201 12.5190057755 155 0 Open ; +P-V-134 133 134 296.477386475 8.90838289261 155 0 Open ; +P-V-135 134 135 309.533241272 5.50496792793 155 0 Open ; +P-V-136 135 136 449.846176147 10.2938466072 155 0 Open ; +P-V-137 136 137 584.406188965 13.2976713181 155 0 Open ; +P-V-138 137 138 648.903839111 9.5360455513 155 0 Open ; +P-V-139 138 139 366.050643921 7.26288461685 155 0 Open ; +P-V-141 140 141 515.425933838 10.2867121696 155 0 Open ; +P-V-142 141 142 588.339782715 3.54823291302 155 0 Open ; +P-V-143 142 143 707.536468506 14.3174180984 155 0 Open ; +P-V-144 143 144 792.741699219 11.2076778412 155 0 Open ; +P-V-145 144 145 522.520019531 6.88134169579 155 0 Open ; +P-V-146 145 146 285.439216614 6.54019927979 155 0 Open ; +P-V-147 146 147 406.495880127 6.52947449684 155 0 Open ; +P-V-148 147 148 393.946456909 12.1616792679 155 0 Open ; +P-V-149 148 149 617.908905029 6.89731931686 155 0 Open ; +P-V-150 149 150 512.460083008 9.32679224014 155 0 Open ; +P-V-151 150 151 320.122879028 13.1050662994 155 0 Open ; +P-V-152 151 152 792.424865723 12.692358017 155 0 Open ; +P-V-153 152 153 773.066467285 9.56733131409 155 0 Open ; +P-V-154 153 154 257.166633606 6.99246692657 155 0 Open ; +P-V-155 154 155 669.791473389 10.7117185593 155 0 Open ; +P-V-156 155 156 742.764709473 11.9375247955 155 0 Open ; +P-V-157 156 157 649.150115967 8.32309770584 155 0 Open ; +P-V-158 157 158 465.431549072 5.15927243233 155 0 Open ; +P-V-159 158 159 344.630050659 6.9444372654 155 0 Open ; +P-V-161 160 161 507.862182617 11.8049430847 155 0 Open ; +P-V-162 161 162 234.33165741 11.2436876297 155 0 Open ; +P-V-163 162 163 782.957641602 10.3772912025 155 0 Open ; +P-V-164 163 164 506.757293701 12.3977651596 155 0 Open ; +P-V-165 164 165 412.467391968 9.79108142853 155 0 Open ; +P-V-166 165 166 485.290496826 8.55286550522 155 0 Open ; +P-V-167 166 167 350.776794434 9.11240148544 155 0 Open ; +P-V-168 167 168 757.016418457 14.5056381226 155 0 Open ; +P-V-169 168 169 563.836639404 11.0517721176 155 0 Open ; +P-V-170 169 170 307.398727417 8.01085758209 155 0 Open ; +P-V-171 170 171 274.418380737 9.99605512619 155 0 Open ; +P-V-172 171 172 535.172180176 11.7881240845 155 0 Open ; +P-V-173 172 173 500.425323486 7.96583652496 155 0 Open ; +P-V-174 173 174 241.024662018 5.0303902626 155 0 Open ; +P-V-175 174 175 638.628570557 11.6137208939 155 0 Open ; +P-V-176 175 176 340.528701782 8.31922388077 155 0 Open ; +P-V-177 176 177 209.91237545 10.9461054802 155 0 Open ; +P-V-178 177 178 309.967224121 7.38291835785 155 0 Open ; +P-V-179 178 179 585.65032959 11.5085725784 155 0 Open ; +P-V-181 180 181 779.414123535 7.27276182175 155 0 Open ; +P-V-182 181 182 415.614593506 11.6865167618 155 0 Open ; +P-V-183 182 183 314.587989807 12.6086378098 155 0 Open ; +P-V-184 183 184 619.375701904 7.95764350891 155 0 Open ; +P-V-185 184 185 555.884307861 13.9524402618 155 0 Open ; +P-V-186 185 186 683.780944824 9.12996387482 155 0 Open ; +P-V-187 186 187 515.603210449 9.86851644516 155 0 Open ; +P-V-188 187 188 758.013366699 13.6194696426 155 0 Open ; +P-V-189 188 189 471.222869873 7.85407876968 155 0 Open ; +P-V-190 189 190 525.307312012 7.8009557724 155 0 Open ; +P-V-191 190 191 283.49356842 12.5299329758 155 0 Open ; +P-V-192 191 192 479.954711914 14.9820384979 155 0 Open ; +P-V-193 192 193 705.807525635 9.14695262909 155 0 Open ; +P-V-194 193 194 391.760101318 9.23696184158 155 0 Open ; +P-V-195 194 195 431.161499023 5.62772655487 155 0 Open ; +P-V-196 195 196 410.105331421 7.80570077896 155 0 Open ; +P-V-197 196 197 670.78137207 7.45923042297 155 0 Open ; +P-V-198 197 198 514.484924316 5.95945477486 155 0 Open ; +P-V-199 198 199 777.82434082 12.8734302521 155 0 Open ; +P-V-201 200 201 537.11151123 3.65934926271 155 0 Open ; +P-V-202 201 202 484.168823242 3.51145344973 155 0 Open ; +P-V-203 202 203 399.920761108 4.36592614651 155 0 Open ; +P-V-204 203 204 256.12071228 3.41593161225 155 0 Open ; +P-V-205 204 205 528.152435303 4.15901792049 155 0 Open ; +P-V-206 205 206 380.691146851 8.52566814423 155 0 Open ; +P-V-207 206 207 295.236549377 11.815369606 155 0 Open ; +P-V-208 207 208 595.598297119 7.4100522995 155 0 Open ; +P-V-209 208 209 587.794372559 12.2113380432 155 0 Open ; +P-V-210 209 210 347.961090088 10.6405467987 155 0 Open ; +P-V-211 210 211 333.902862549 13.1080589294 155 0 Open ; +P-V-212 211 212 307.427055359 5.53060293198 155 0 Open ; +P-V-213 212 213 392.232788086 12.1306028366 155 0 Open ; +P-V-214 213 214 302.35559082 4.80716097355 155 0 Open ; +P-V-215 214 215 247.803092957 3.53157246113 155 0 Open ; +P-V-216 215 216 506.921051025 7.44096517563 155 0 Open ; +P-V-217 216 217 765.051025391 3.26871326566 155 0 Open ; +P-V-218 217 218 413.211685181 7.97534370422 155 0 Open ; +P-V-219 218 219 430.359283447 11.9682016373 155 0 Open ; +P-V-221 220 221 628.205535889 12.0169296265 155 0 Open ; +P-V-222 221 222 777.018615723 6.03685069084 155 0 Open ; +P-V-223 222 223 417.35244751 7.85254096985 155 0 Open ; +P-V-224 223 224 433.143997192 12.0276346207 155 0 Open ; +P-V-225 224 225 773.498962402 10.9369125366 155 0 Open ; +P-V-226 225 226 384.54246521 7.10788440704 155 0 Open ; +P-V-227 226 227 460.901000977 6.25813508034 155 0 Open ; +P-V-228 227 228 373.830123901 6.25790548325 155 0 Open ; +P-V-229 228 229 780.860046387 13.291513443 155 0 Open ; +P-V-230 229 230 273.793861389 4.06925880909 155 0 Open ; +P-V-231 230 231 551.681335449 5.16362309456 155 0 Open ; +P-V-232 231 232 400.806091309 13.9635229111 155 0 Open ; +P-V-233 232 233 396.905227661 10.7251338959 155 0 Open ; +P-V-234 233 234 616.281799316 11.9684085846 155 0 Open ; +P-V-235 234 235 202.321927309 3.49268856645 155 0 Open ; +P-V-236 235 236 230.863615036 9.49574947357 155 0 Open ; +P-V-237 236 237 703.190063477 5.3045797348 155 0 Open ; +P-V-238 237 238 653.538757324 7.52567625046 155 0 Open ; +P-V-239 238 239 552.358154297 4.67157566547 155 0 Open ; +P-V-241 240 241 308.661216736 12.3838033676 155 0 Open ; +P-V-242 241 242 679.342071533 5.04957008362 155 0 Open ; +P-V-243 242 243 556.209625244 3.29952955246 155 0 Open ; +P-V-244 243 244 509.667358398 6.58407211304 155 0 Open ; +P-V-245 244 245 675.142456055 9.3891582489 155 0 Open ; +P-V-246 245 246 529.149475098 3.30844262242 155 0 Open ; +P-V-247 246 247 799.770385742 9.82097959518 155 0 Open ; +P-V-248 247 248 410.185134888 10.6308631897 155 0 Open ; +P-V-249 248 249 595.992462158 7.90284538269 155 0 Open ; +P-V-250 249 250 706.413543701 8.84530544281 155 0 Open ; +P-V-251 250 251 702.507843018 3.98911160231 155 0 Open ; +P-V-252 251 252 399.921279907 4.54502475262 155 0 Open ; +P-V-253 252 253 761.657897949 14.6881246567 155 0 Open ; +P-V-254 253 254 315.633377075 4.00447881222 155 0 Open ; +P-V-255 254 255 713.792114258 5.09466552734 155 0 Open ; +P-V-256 255 256 652.245574951 4.8343205452 155 0 Open ; +P-V-257 256 257 271.209823608 11.4715938568 155 0 Open ; +P-V-258 257 258 304.007316589 8.02231836319 155 0 Open ; +P-V-259 258 259 305.369949341 10.0566034317 155 0 Open ; +P-V-261 260 261 416.864074707 11.6905641556 155 0 Open ; +P-V-262 261 262 715.691711426 7.61435461044 155 0 Open ; +P-V-263 262 263 673.120941162 13.8796424866 155 0 Open ; +P-V-264 263 264 707.693054199 6.94865608215 155 0 Open ; +P-V-265 264 265 453.240341187 11.2146949768 155 0 Open ; +P-V-266 265 266 418.828353882 11.9655246735 155 0 Open ; +P-V-267 266 267 779.127685547 6.99799561501 155 0 Open ; +P-V-268 267 268 515.489868164 7.75722885132 155 0 Open ; +P-V-269 268 269 737.356262207 5.94250845909 155 0 Open ; +P-V-270 269 270 337.102142334 8.51477622986 155 0 Open ; +P-V-271 270 271 742.620117188 11.3378381729 155 0 Open ; +P-V-272 271 272 702.23046875 6.75207209587 155 0 Open ; +P-V-273 272 273 253.651054382 13.2654933929 155 0 Open ; +P-V-274 273 274 607.536437988 12.2975234985 155 0 Open ; +P-V-275 274 275 774.288879395 12.4589490891 155 0 Open ; +P-V-276 275 276 228.088256836 12.587023735 155 0 Open ; +P-V-277 276 277 455.726623535 6.95278501511 155 0 Open ; +P-V-278 277 278 322.790374756 9.75801086426 155 0 Open ; +P-V-279 278 279 294.479377747 9.29939889908 155 0 Open ; +P-V-281 280 281 700.087982178 6.58340978622 155 0 Open ; +P-V-282 281 282 718.344848633 11.427315712 155 0 Open ; +P-V-283 282 283 295.228309631 9.04333162308 155 0 Open ; +P-V-284 283 284 313.985389709 14.0497732162 155 0 Open ; +P-V-285 284 285 277.41809082 10.317984581 155 0 Open ; +P-V-286 285 286 468.354888916 3.8138410449 155 0 Open ; +P-V-287 286 287 711.312988281 11.7554826736 155 0 Open ; +P-V-288 287 288 670.117095947 12.1627721786 155 0 Open ; +P-V-289 288 289 336.050018311 14.8527326584 155 0 Open ; +P-V-290 289 290 644.106994629 5.12372136116 155 0 Open ; +P-V-291 290 291 469.259185791 7.78892755508 155 0 Open ; +P-V-292 291 292 375.122512817 8.68479251862 155 0 Open ; +P-V-293 292 293 215.761516571 9.07644796371 155 0 Open ; +P-V-294 293 294 543.184844971 5.16025710106 155 0 Open ; +P-V-295 294 295 572.212249756 6.42491841316 155 0 Open ; +P-V-296 295 296 730.32598877 6.78834271431 155 0 Open ; +P-V-297 296 297 733.76385498 10.3926486969 155 0 Open ; +P-V-298 297 298 212.401073456 7.49694871902 155 0 Open ; +P-V-299 298 299 410.740386963 5.2769036293 155 0 Open ; +P-V-301 300 301 795.946960449 8.62204742432 155 0 Open ; +P-V-302 301 302 287.691398621 7.58824729919 155 0 Open ; +P-V-303 302 303 333.758972168 12.7444782257 155 0 Open ; +P-V-304 303 304 772.106994629 11.0609369278 155 0 Open ; +P-V-305 304 305 208.311294556 12.7588424683 155 0 Open ; +P-V-306 305 306 243.298629761 13.4022293091 155 0 Open ; +P-V-307 306 307 313.768661499 13.199549675 155 0 Open ; +P-V-308 307 308 391.441879272 10.2749752998 155 0 Open ; +P-V-309 308 309 325.475708008 12.4067678452 155 0 Open ; +P-V-310 309 310 777.81628418 10.1661949158 155 0 Open ; +P-V-311 310 311 712.142883301 14.7111377716 155 0 Open ; +P-V-312 311 312 454.947128296 8.9308257103 155 0 Open ; +P-V-313 312 313 569.417694092 3.06864225864 155 0 Open ; +P-V-314 313 314 283.523635864 10.6375956535 155 0 Open ; +P-V-315 314 315 253.701400757 6.18838906288 155 0 Open ; +P-V-316 315 316 562.886413574 3.6408637166 155 0 Open ; +P-V-317 316 317 549.841705322 10.7942676544 155 0 Open ; +P-V-318 317 318 512.934417725 12.7843074799 155 0 Open ; +P-V-319 318 319 643.044952393 8.13675403595 155 0 Open ; +P-V-321 320 321 471.357849121 5.23215055466 155 0 Open ; +P-V-322 321 322 387.778961182 3.01957516372 155 0 Open ; +P-V-323 322 323 449.988830566 10.2491731644 155 0 Open ; +P-V-324 323 324 242.867172241 12.3713111877 155 0 Open ; +P-V-325 324 325 381.551254272 9.63763380051 155 0 Open ; +P-V-326 325 326 535.7578125 4.63245606422 155 0 Open ; +P-V-327 326 327 434.505844116 13.8010206223 155 0 Open ; +P-V-328 327 328 637.807769775 11.7118520737 155 0 Open ; +P-V-329 328 329 605.330230713 14.7030487061 155 0 Open ; +P-V-330 329 330 257.15845871 4.24409663677 155 0 Open ; +P-V-331 330 331 476.692138672 10.3019342422 155 0 Open ; +P-V-332 331 332 780.288330078 13.1322975159 155 0 Open ; +P-V-333 332 333 276.172904968 11.7593107224 155 0 Open ; +P-V-334 333 334 287.186882019 5.99902749062 155 0 Open ; +P-V-335 334 335 432.885955811 9.28688907623 155 0 Open ; +P-V-336 335 336 387.434890747 7.36628007889 155 0 Open ; +P-V-337 336 337 403.386169434 5.22823238373 155 0 Open ; +P-V-338 337 338 695.082946777 4.19038367271 155 0 Open ; +P-V-339 338 339 338.924514771 9.0905213356 155 0 Open ; +P-V-341 340 341 369.724151611 6.0764029026 155 0 Open ; +P-V-342 341 342 655.297790527 10.8031468391 155 0 Open ; +P-V-343 342 343 774.627746582 6.37779593468 155 0 Open ; +P-V-344 343 344 730.768066406 11.3788805008 155 0 Open ; +P-V-345 344 345 393.12902832 13.3896255493 155 0 Open ; +P-V-346 345 346 522.465240479 12.4654560089 155 0 Open ; +P-V-347 346 347 296.35836792 4.90317642689 155 0 Open ; +P-V-348 347 348 534.254730225 3.38487842679 155 0 Open ; +P-V-349 348 349 232.589233398 13.5452289581 155 0 Open ; +P-V-350 349 350 483.148132324 8.41378688812 155 0 Open ; +P-V-351 350 351 476.112518311 7.46234226227 155 0 Open ; +P-V-352 351 352 729.583251953 9.11160421371 155 0 Open ; +P-V-353 352 353 686.819396973 10.4712467194 155 0 Open ; +P-V-354 353 354 262.160057068 5.48223233223 155 0 Open ; +P-V-355 354 355 544.003967285 4.49496436119 155 0 Open ; +P-V-356 355 356 693.389160156 10.8346042633 155 0 Open ; +P-V-357 356 357 210.191926956 8.9141907692 155 0 Open ; +P-V-358 357 358 390.323196411 6.24438524246 155 0 Open ; +P-V-359 358 359 219.347953796 14.6212863922 155 0 Open ; +P-V-361 360 361 547.742492676 13.1618022919 155 0 Open ; +P-V-362 361 362 471.092132568 11.9128341675 155 0 Open ; +P-V-363 362 363 300.808151245 12.6522274017 155 0 Open ; +P-V-364 363 364 650.019256592 12.4822759628 155 0 Open ; +P-V-365 364 365 630.997253418 14.4197664261 155 0 Open ; +P-V-366 365 366 400.845840454 3.32482624054 155 0 Open ; +P-V-367 366 367 767.731384277 4.22087037563 155 0 Open ; +P-V-368 367 368 758.462890625 8.72039461136 155 0 Open ; +P-V-369 368 369 733.634216309 14.8142032623 155 0 Open ; +P-V-370 369 370 666.187255859 11.188536644 155 0 Open ; +P-V-371 370 371 636.541870117 6.18730354309 155 0 Open ; +P-V-372 371 372 250.591598511 4.8600051403 155 0 Open ; +P-V-373 372 373 255.370471954 3.23030988872 155 0 Open ; +P-V-374 373 374 540.924468994 13.350689888 155 0 Open ; +P-V-375 374 375 202.675620794 14.3831892014 155 0 Open ; +P-V-376 375 376 263.077987671 14.0348997116 155 0 Open ; +P-V-377 376 377 377.812606812 12.9323835373 155 0 Open ; +P-V-378 377 378 278.681625366 3.04330474883 155 0 Open ; +P-V-379 378 379 591.147247314 11.2413816452 155 0 Open ; +P-V-381 380 381 645.527374268 14.5789852142 155 0 Open ; +P-V-382 381 382 400.279403687 4.91780853271 155 0 Open ; +P-V-383 382 383 230.41843605 3.85287708044 155 0 Open ; +P-V-384 383 384 515.27520752 7.61597967148 155 0 Open ; +P-V-385 384 385 238.637695312 6.67442631721 155 0 Open ; +P-V-386 385 386 404.130493164 3.42620676756 155 0 Open ; +P-V-387 386 387 762.861999512 11.426243782 155 0 Open ; +P-V-388 387 388 594.104827881 9.40324878693 155 0 Open ; +P-V-389 388 389 370.551040649 8.02978181839 155 0 Open ; +P-V-390 389 390 577.362792969 9.73121881485 155 0 Open ; +P-V-391 390 391 579.470733643 10.2902131081 155 0 Open ; +P-V-392 391 392 530.722808838 4.17102515697 155 0 Open ; +P-V-393 392 393 271.016166687 6.3741710186 155 0 Open ; +P-V-394 393 394 684.677825928 10.6114754677 155 0 Open ; +P-V-395 394 395 503.524963379 5.87491130829 155 0 Open ; +P-V-396 395 396 531.86618042 4.49809849262 155 0 Open ; +P-V-397 396 397 327.143989563 9.18234205246 155 0 Open ; +P-V-398 397 398 731.153991699 9.11569690704 155 0 Open ; +P-V-399 398 399 525.912322998 7.16543579102 155 0 Open ; +P-H-22 2 22 752.449401855 3.34831354022 155 0 Open ; +P-H-23 3 23 418.17098999 6.9975373745 155 0 Open ; +P-H-24 4 24 678.215576172 10.3880987167 155 0 Open ; +P-H-25 5 25 462.567962646 14.5981235504 155 0 Open ; +P-H-27 7 27 463.042327881 6.05244636536 155 0 Open ; +P-H-29 9 29 385.512664795 9.22320604324 155 0 Open ; +P-H-32 12 32 616.348937988 10.5329580307 155 0 Open ; +P-H-33 13 33 372.187164307 5.99322652817 155 0 Open ; +P-H-39 19 39 269.263908386 5.36985397339 155 0 Open ; +P-H-42 22 42 452.920272827 11.6193351746 155 0 Open ; +P-H-44 24 44 464.944885254 9.5715007782 155 0 Open ; +P-H-45 25 45 639.121765137 9.39256381989 155 0 Open ; +P-H-49 29 49 347.627731323 6.58349990845 155 0 Open ; +P-H-50 30 50 237.754398346 9.76307630539 155 0 Open ; +P-H-52 32 52 288.640975952 14.7792978287 155 0 Open ; +P-H-53 33 53 624.817840576 13.272313118 155 0 Open ; +P-H-56 36 56 738.984802246 13.3412828445 155 0 Open ; +P-H-57 37 57 343.500198364 11.1569080353 155 0 Open ; +P-H-61 41 61 527.308441162 8.46959877014 155 0 Open ; +P-H-62 42 62 319.484802246 14.6223831177 155 0 Open ; +P-H-64 44 64 602.707489014 9.10077571869 155 0 Open ; +P-H-65 45 65 603.760986328 3.21991091967 155 0 Open ; +P-H-67 47 67 594.082061768 13.7435188293 155 0 Open ; +P-H-70 50 70 558.691253662 9.48208141327 155 0 Open ; +P-H-71 51 71 214.256988525 7.34426164627 155 0 Open ; +P-H-72 52 72 341.145751953 11.7348833084 155 0 Open ; +P-H-73 53 73 703.467437744 14.5450000763 155 0 Open ; +P-H-74 54 74 711.335357666 7.26644945145 155 0 Open ; +P-H-75 55 75 379.524154663 12.2526073456 155 0 Open ; +P-H-78 58 78 592.698150635 4.54960870743 155 0 Open ; +P-H-82 62 82 485.908538818 12.2914094925 155 0 Open ; +P-H-85 65 85 789.418579102 10.1706237793 155 0 Open ; +P-H-87 67 87 669.054901123 3.11879821867 155 0 Open ; +P-H-92 72 92 764.433410645 11.6454992294 155 0 Open ; +P-H-93 73 93 409.947814941 14.8600301743 155 0 Open ; +P-H-94 74 94 562.639465332 4.63583135605 155 0 Open ; +P-H-98 78 98 600.959686279 9.59339237213 155 0 Open ; +P-H-99 79 99 677.119293213 13.8847236633 155 0 Open ; +P-H-100 80 100 726.51184082 8.6859292984 155 0 Open ; +P-H-101 81 101 455.348495483 11.8453474045 155 0 Open ; +P-H-102 82 102 658.433349609 8.78902959824 155 0 Open ; +P-H-105 85 105 540.47076416 4.84383630753 155 0 Open ; +P-H-107 87 107 726.71307373 4.34079051018 155 0 Open ; +P-H-108 88 108 259.007862091 13.9031562805 155 0 Open ; +P-H-109 89 109 229.992992401 4.84482479095 155 0 Open ; +P-H-110 90 110 242.52407074 5.04137039185 155 0 Open ; +P-H-112 92 112 467.416137695 12.2627086639 155 0 Open ; +P-H-114 94 114 670.506225586 10.9661026001 155 0 Open ; +P-H-117 97 117 603.713989258 11.4239187241 155 0 Open ; +P-H-119 99 119 424.288970947 11.4971809387 155 0 Open ; +P-H-122 102 122 426.036972046 11.0714321136 155 0 Open ; +P-H-123 103 123 407.186477661 10.6623415947 155 0 Open ; +P-H-124 104 124 449.552902222 7.71587371826 155 0 Open ; +P-H-125 105 125 239.466304779 9.20341920853 155 0 Open ; +P-H-128 108 128 415.171920776 6.89142823219 155 0 Open ; +P-H-130 110 130 345.319168091 10.5846190453 155 0 Open ; +P-H-131 111 131 488.403930664 11.1012239456 155 0 Open ; +P-H-133 113 133 685.061889648 7.70618391037 155 0 Open ; +P-H-135 115 135 358.968978882 14.8364543915 155 0 Open ; +P-H-136 116 136 579.983062744 14.5094690323 155 0 Open ; +P-H-137 117 137 414.296340942 12.5732984543 155 0 Open ; +P-H-140 120 140 608.259307861 3.2853461206 155 0 Open ; +P-H-141 121 141 235.663146973 14.8102350235 155 0 Open ; +P-H-144 124 144 363.629318237 9.3620557785 155 0 Open ; +P-H-145 125 145 577.695007324 13.3962583542 155 0 Open ; +P-H-146 126 146 494.190307617 12.1321134567 155 0 Open ; +P-H-148 128 148 518.060882568 7.98543167114 155 0 Open ; +P-H-149 129 149 481.621582031 11.2821121216 155 0 Open ; +P-H-150 130 150 676.974975586 13.3631744385 155 0 Open ; +P-H-153 133 153 533.433837891 3.45361405611 155 0 Open ; +P-H-155 135 155 795.899414062 4.63803446293 155 0 Open ; +P-H-157 137 157 633.427398682 3.29802849889 155 0 Open ; +P-H-159 139 159 387.337692261 10.6889033318 155 0 Open ; +P-H-160 140 160 268.565704346 10.6750402451 155 0 Open ; +P-H-161 141 161 411.97442627 12.0807981491 155 0 Open ; +P-H-164 144 164 532.351013184 11.4695901871 155 0 Open ; +P-H-166 146 166 322.088661194 13.8829488754 155 0 Open ; +P-H-169 149 169 203.379704475 11.0539102554 155 0 Open ; +P-H-171 151 171 229.941976547 11.6966228485 155 0 Open ; +P-H-176 156 176 541.531402588 13.3588733673 155 0 Open ; +P-H-182 162 182 268.354179382 11.5746669769 155 0 Open ; +P-H-183 163 183 672.841827393 4.05431044102 155 0 Open ; +P-H-184 164 184 766.413269043 5.16926121712 155 0 Open ; +P-H-186 166 186 658.514190674 11.9654388428 155 0 Open ; +P-H-187 167 187 369.190795898 6.7915327549 155 0 Open ; +P-H-189 169 189 591.753997803 11.1876735687 155 0 Open ; +P-H-190 170 190 395.387084961 4.41696321964 155 0 Open ; +P-H-191 171 191 613.322143555 13.1087417603 155 0 Open ; +P-H-194 174 194 607.772583008 7.68170213699 155 0 Open ; +P-H-196 176 196 495.154327393 12.1809911728 155 0 Open ; +P-H-197 177 197 469.927185059 4.32827532291 155 0 Open ; +P-H-201 181 201 434.560287476 8.09209060669 155 0 Open ; +P-H-202 182 202 597.759857178 13.9991235733 155 0 Open ; +P-H-207 187 207 692.520690918 6.90561556816 155 0 Open ; +P-H-209 189 209 424.991409302 7.6139831543 155 0 Open ; +P-H-211 191 211 562.063873291 3.15098445117 155 0 Open ; +P-H-214 194 214 560.710876465 4.3538107872 155 0 Open ; +P-H-222 202 222 668.499908447 8.55728244781 155 0 Open ; +P-H-225 205 225 746.258361816 10.3052072525 155 0 Open ; +P-H-226 206 226 247.036312103 9.78609800339 155 0 Open ; +P-H-229 209 229 614.038818359 14.0150947571 155 0 Open ; +P-H-230 210 230 337.830444336 13.3238258362 155 0 Open ; +P-H-232 212 232 750.668884277 4.85580718517 155 0 Open ; +P-H-234 214 234 375.129089355 10.8923926353 155 0 Open ; +P-H-235 215 235 659.044494629 10.2237086296 155 0 Open ; +P-H-240 220 240 668.49105835 5.59065055847 155 0 Open ; +P-H-244 224 244 275.593711853 9.07111263275 155 0 Open ; +P-H-246 226 246 449.940048218 5.84826517105 155 0 Open ; +P-H-249 229 249 687.299072266 3.72012394667 155 0 Open ; +P-H-250 230 250 325.245346069 6.97013521194 155 0 Open ; +P-H-251 231 251 564.613647461 8.23496437073 155 0 Open ; +P-H-253 233 253 762.777160645 6.92749071121 155 0 Open ; +P-H-254 234 254 565.876800537 12.8282375336 155 0 Open ; +P-H-256 236 256 779.74029541 8.90216302872 155 0 Open ; +P-H-258 238 258 295.505172729 6.10906791687 155 0 Open ; +P-H-259 239 259 782.000671387 12.6967029572 155 0 Open ; +P-H-262 242 262 447.470748901 3.82339346409 155 0 Open ; +P-H-265 245 265 469.841003418 11.3583431244 155 0 Open ; +P-H-266 246 266 570.64956665 9.1444029808 155 0 Open ; +P-H-267 247 267 287.313858032 12.6816034317 155 0 Open ; +P-H-268 248 268 498.264007568 13.4693670273 155 0 Open ; +P-H-270 250 270 644.357299805 5.26166749001 155 0 Open ; +P-H-271 251 271 710.438415527 5.76850295067 155 0 Open ; +P-H-272 252 272 440.645584106 13.6102743149 155 0 Open ; +P-H-273 253 273 754.02722168 5.71994519234 155 0 Open ; +P-H-274 254 274 285.620788574 7.57122850418 155 0 Open ; +P-H-276 256 276 415.744247437 7.27322673798 155 0 Open ; +P-H-278 258 278 610.301177979 5.64944624901 155 0 Open ; +P-H-279 259 279 419.679901123 10.2031788826 155 0 Open ; +P-H-280 260 280 460.222625732 6.24049830437 155 0 Open ; +P-H-281 261 281 639.831115723 7.83727169037 155 0 Open ; +P-H-283 263 283 500.227600098 13.5008964539 155 0 Open ; +P-H-286 266 286 647.355041504 4.93407082558 155 0 Open ; +P-H-287 267 287 451.879257202 9.69450807571 155 0 Open ; +P-H-289 269 289 270.793380737 3.48849597573 155 0 Open ; +P-H-292 272 292 374.790084839 4.93804562092 155 0 Open ; +P-H-299 279 299 469.592773438 11.9195108414 155 0 Open ; +P-H-300 280 300 735.268554688 12.1773347855 155 0 Open ; +P-H-301 281 301 621.739593506 10.5492544174 155 0 Open ; +P-H-305 285 305 723.723999023 7.57669734955 155 0 Open ; +P-H-308 288 308 371.220291138 4.98827910423 155 0 Open ; +P-H-309 289 309 660.32913208 10.04037714 155 0 Open ; +P-H-310 290 310 551.007385254 6.62432479858 155 0 Open ; +P-H-316 296 316 381.390365601 3.55886244774 155 0 Open ; +P-H-317 297 317 794.373352051 7.67015028 155 0 Open ; +P-H-318 298 318 253.355953217 10.070019722 155 0 Open ; +P-H-320 300 320 260.785541534 11.4530239105 155 0 Open ; +P-H-322 302 322 634.164550781 11.0710802078 155 0 Open ; +P-H-324 304 324 434.674240112 10.4007911682 155 0 Open ; +P-H-326 306 326 333.623291016 3.13584157825 155 0 Open ; +P-H-329 309 329 235.839439392 14.0700941086 155 0 Open ; +P-H-330 310 330 270.297012329 4.63675224781 155 0 Open ; +P-H-335 315 335 214.013755798 9.58418560028 155 0 Open ; +P-H-336 316 336 772.845275879 7.22111225128 155 0 Open ; +P-H-339 319 339 745.637451172 5.57481193542 155 0 Open ; +P-H-343 323 343 729.112854004 6.99812722206 155 0 Open ; +P-H-344 324 344 502.637512207 7.56899642944 155 0 Open ; +P-H-346 326 346 755.43762207 11.8068962097 155 0 Open ; +P-H-347 327 347 271.136528015 10.8333692551 155 0 Open ; +P-H-350 330 350 419.271865845 5.04696536064 155 0 Open ; +P-H-351 331 351 279.160110474 7.88195514679 155 0 Open ; +P-H-352 332 352 322.774421692 4.39528870583 155 0 Open ; +P-H-354 334 354 471.378234863 12.0791273117 155 0 Open ; +P-H-358 338 358 374.554718018 9.82425260544 155 0 Open ; +P-H-359 339 359 594.562194824 7.14209890366 155 0 Open ; +P-H-369 349 369 454.077407837 4.58090305328 155 0 Open ; +P-H-371 351 371 516.257080078 13.6540966034 155 0 Open ; +P-H-372 352 372 410.05380249 14.4842233658 155 0 Open ; +P-H-373 353 373 382.402099609 7.6447224617 155 0 Open ; +P-H-380 360 380 664.771331787 3.24260343611 155 0 Open ; +P-H-381 361 381 702.80090332 6.50115537643 155 0 Open ; +P-H-382 362 382 491.706848145 5.33910441399 155 0 Open ; +P-H-384 364 384 640.475738525 8.52454900742 155 0 Open ; +P-H-385 365 385 786.296325684 4.65009248257 155 0 Open ; +P-H-387 367 387 200.574466288 4.1011043787 155 0 Open ; +P-H-392 372 392 320.105308533 7.20035219193 155 0 Open ; +P-H-393 373 393 433.92767334 11.4481973648 155 0 Open ; +P-H-395 375 395 526.156951904 5.40608239174 155 0 Open ; +P-H-396 376 396 735.712524414 5.42613363266 155 0 Open ; +P-H-398 378 398 694.791687012 14.2802495956 155 0 Open ; +P-H-399 379 399 694.776428223 9.15288209915 155 0 Open ; +P-S-0 400 0 30 30 155 0 Open ; +P-S-1 401 20 30 30 155 0 Open ; +P-S-2 402 40 30 30 155 0 Open ; +P-S-3 403 60 30 30 155 0 Open ; +P-S-4 404 80 30 30 155 0 Open ; +[PUMPS] +;ID Node1 Node2 Parameters + +[CURVES] +;ID X-Value Y-Value +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers + +[CONTROLS] + + + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0:30 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] \ No newline at end of file diff --git a/benchmarks/small/synthetic50.inp b/benchmarks/small/synthetic50.inp new file mode 100644 index 0000000..d983cb0 --- /dev/null +++ b/benchmarks/small/synthetic50.inp @@ -0,0 +1,6298 @@ +[JUNCTIONS] +;ID Elev Demand Pattern +0 453.982814789 2.89203548431 ; +1 544.003967285 2.74655866623 ; +2 541.243255615 3.75587439537 ; +3 898.120330811 4.09056138992 ; +4 406.604812622 0.070928029716 ; +5 608.744277954 3.65366721153 ; +6 618.366317749 0.827656328678 ; +7 441.9789505 0.40250658989 ; +8 892.85723877 4.5176410675 ; +9 699.556976318 1.5455108881 ; +10 440.158664703 4.46683645248 ; +11 812.107421875 2.89906787872 ; +12 863.813354492 3.11119127274 ; +13 879.312255859 3.01250433922 ; +14 515.874656677 0.0552448071539 ; +15 749.943511963 0.00634407857433 ; +16 562.492858887 0.175793796778 ; +17 856.654693604 4.96054935455 ; +18 595.289199829 2.25749254227 ; +19 567.7605896 0.523994207382 ; +20 577.03187561 3.74918317795 ; +21 652.08164978 2.36686110497 ; +22 883.719207764 3.69226455688 ; +23 489.082771301 2.14246034622 ; +24 733.453826904 3.58779430389 ; +25 405.983278751 0.609716534615 ; +26 650.624786377 2.51252055168 ; +27 693.18359375 0.369055390358 ; +28 671.374511719 4.91472244263 ; +29 573.852722168 4.42816209793 ; +30 811.7862854 3.92654752731 ; +31 748.202911377 2.46405696869 ; +32 740.734680176 2.27917289734 ; +33 505.962341309 4.09112167358 ; +34 848.437896729 3.96055722237 ; +35 408.822566986 2.80892515182 ; +36 860.483703613 3.50207543373 ; +37 838.138793945 2.99143314362 ; +38 601.632034302 3.29554533958 ; +39 723.064178467 2.40182113647 ; +40 640.875152588 3.89036631584 ; +41 438.73033905 4.40872955322 ; +42 651.842575073 2.1854596138 ; +43 502.139755249 1.62955641747 ; +44 695.526885986 4.20502662659 ; +45 788.121520996 1.58846449852 ; +46 632.263534546 1.536028862 ; +47 503.573387146 2.57896924019 ; +48 873.891967773 2.03075313568 ; +49 486.822547913 2.26693201065 ; +50 432.742424011 3.01962399483 ; +51 482.154556274 2.71692848206 ; +52 741.617401123 0.635163426399 ; +53 419.095331192 4.35219860077 ; +54 639.985870361 4.42772722244 ; +55 581.273010254 1.55509459972 ; +56 547.429214478 3.43091964722 ; +57 746.794616699 0.774654269218 ; +58 861.484863281 1.7643969059 ; +59 821.917114258 1.61148619652 ; +60 824.909637451 4.56723690033 ; +61 555.077606201 3.8941090107 ; +62 729.123748779 0.830974042416 ; +63 518.122261047 2.8085360527 ; +64 706.222717285 1.85732138157 ; +65 500.01927948 0.240649059415 ; +66 858.886077881 4.98455047607 ; +67 434.282527924 1.86446070671 ; +68 499.236442566 3.67014670372 ; +69 815.558410645 2.90417194366 ; +70 441.803642273 0.938222050667 ; +71 769.834899902 3.15893411636 ; +72 620.466171265 3.7522995472 ; +73 889.965362549 3.48316597939 ; +74 557.25680542 0.151676774025 ; +75 823.160461426 0.58247178793 ; +76 860.346130371 0.380554407835 ; +77 497.849891663 0.632019102573 ; +78 634.507736206 3.71838617325 ; +79 891.688079834 3.02169251442 ; +80 458.706047058 1.72563922405 ; +81 681.789642334 0.38618054986 ; +82 453.626190186 2.95378661156 ; +83 828.954498291 4.38652801514 ; +84 837.709655762 0.868153274059 ; +85 505.270996094 2.89728283882 ; +86 863.191192627 3.54682826996 ; +87 554.388000488 2.99321103096 ; +88 589.818069458 2.72445464134 ; +89 891.131469727 4.47051811218 ; +90 499.791503906 1.95968568325 ; +91 543.647186279 2.78420448303 ; +92 812.555053711 3.13145136833 ; +93 430.346162796 0.27974909544 ; +94 574.326049805 3.98023152351 ; +95 474.997894287 4.89663743973 ; +96 678.598083496 3.98080158234 ; +97 433.188110352 2.92603898048 ; +98 693.799743652 3.92381668091 ; +99 658.831695557 1.84745240211 ; +100 413.207504272 4.78532552719 ; +101 597.094696045 0.706881642342 ; +102 456.056663513 1.4438123703 ; +103 515.38458252 2.68752145767 ; +104 817.496795654 3.68751430511 ; +105 505.626541138 2.65388154984 ; +106 779.034362793 4.30733060837 ; +107 730.965393066 0.353351831436 ; +108 778.395965576 2.01219105721 ; +109 789.537231445 4.52503824234 ; +110 631.936309814 1.53692317009 ; +111 506.79586792 4.18172264099 ; +112 621.533981323 3.21889042854 ; +113 889.263153076 0.460500240326 ; +114 862.745635986 3.66428375244 ; +115 461.768203735 1.38255536556 ; +116 560.893981934 1.45223987103 ; +117 679.571136475 2.52347016335 ; +118 596.421325684 2.53456878662 ; +119 750.196777344 2.57682323456 ; +120 766.593200684 3.31915521622 ; +121 404.137709618 0.424875795841 ; +122 488.743354797 0.0963680818677 ; +123 865.827423096 1.61852765083 ; +124 659.424804688 1.5269087553 ; +125 675.547027588 1.18671774864 ; +126 416.517158508 1.03876852989 ; +127 758.294799805 3.61198186874 ; +128 557.917877197 1.25896275043 ; +129 838.711273193 4.20717334747 ; +130 896.081665039 1.4494934082 ; +131 563.598129272 0.937446475029 ; +132 466.404014587 0.522737801075 ; +133 465.489196777 1.76983964443 ; +134 469.561431885 1.1906837225 ; +135 582.216278076 0.09193918854 ; +136 422.19503212 0.319320589304 ; +137 582.103729248 1.174939394 ; +138 620.729629517 3.02912282944 ; +139 446.69171524 2.47689890862 ; +140 824.241027832 2.19293999672 ; +141 574.274536133 0.323797464371 ; +142 606.402526855 0.0739704370499 ; +143 722.106567383 1.45018947124 ; +144 733.425079346 3.75782871246 ; +145 682.925811768 1.3411771059 ; +146 516.383285522 0.539623916149 ; +147 845.958526611 2.25460457802 ; +148 714.237701416 3.93082427979 ; +149 436.472637177 4.95605945587 ; +150 549.800506592 1.97284758091 ; +151 664.973815918 4.15060567856 ; +152 823.003173828 4.1482834816 ; +153 420.098508835 2.95641469955 ; +154 746.591674805 1.66628050804 ; +155 417.651952744 1.76355242729 ; +156 402.648106337 0.0672669485211 ; +157 455.558864594 2.77875089645 ; +158 646.792709351 3.45245838165 ; +159 446.718654633 2.0044927597 ; +160 851.054016113 3.64985632896 ; +161 713.731384277 3.83447647095 ; +162 504.811203003 0.619673550129 ; +163 885.409729004 2.81744813919 ; +164 684.801696777 1.62716710567 ; +165 679.758117676 3.94872999191 ; +166 530.26335144 3.3628051281 ; +167 766.99307251 0.529040336609 ; +168 558.159103394 1.8018643856 ; +169 793.334197998 2.67971372604 ; +170 694.596923828 2.90562367439 ; +171 881.41204834 0.92759937048 ; +172 416.25094986 1.29741120338 ; +173 459.026977539 0.664350032806 ; +174 473.075614929 1.81832301617 ; +175 455.346775055 2.1326520443 ; +176 748.498321533 2.11790895462 ; +177 469.657600403 2.35346674919 ; +178 871.610229492 3.535176754 ; +179 471.489463806 0.235007062554 ; +180 876.386657715 1.30500721931 ; +181 725.463104248 0.587564408779 ; +182 419.482727051 4.46226835251 ; +183 635.151397705 1.89677083492 ; +184 802.824310303 2.68864250183 ; +185 701.229522705 2.64748501778 ; +186 528.428314209 4.9496588707 ; +187 791.790710449 3.26769971848 ; +188 423.164361954 3.23470568657 ; +189 469.964996338 4.01689529419 ; +190 596.319320679 0.388050556183 ; +191 596.574768066 3.32261228561 ; +192 714.465545654 2.22556209564 ; +193 402.362240553 2.02177286148 ; +194 893.951171875 3.3761947155 ; +195 770.680877686 0.339527845383 ; +196 544.425735474 3.63389825821 ; +197 892.853912354 3.96165585518 ; +198 755.110015869 3.34342217445 ; +199 689.621459961 1.68229067326 ; +200 826.04776001 0.84953224659 ; +201 708.864685059 0.894520699978 ; +202 820.979492188 4.02491903305 ; +203 581.967483521 3.27705717087 ; +204 649.670318604 2.0917904377 ; +205 572.319396973 1.72354888916 ; +206 668.739868164 2.11271977425 ; +207 748.033843994 4.05386686325 ; +208 734.411956787 4.62328529358 ; +209 756.173309326 2.05328130722 ; +210 850.045684814 4.18102169037 ; +211 443.411064148 1.0979539156 ; +212 731.099822998 2.95066261292 ; +213 578.579925537 3.92712450027 ; +214 718.077880859 4.35263586044 ; +215 874.682373047 4.86865758896 ; +216 653.091384888 2.07318711281 ; +217 805.457641602 0.272289276123 ; +218 536.61946106 1.63329076767 ; +219 471.934593201 0.0469969026744 ; +220 887.690429688 1.13368320465 ; +221 781.293273926 3.96313405037 ; +222 739.336578369 2.30210161209 ; +223 541.979309082 2.46478891373 ; +224 470.629051208 0.624795198441 ; +225 493.331977844 1.30718612671 ; +226 887.879119873 2.84789228439 ; +227 852.649139404 1.73986577988 ; +228 592.419937134 0.0207240208983 ; +229 730.86114502 2.8347287178 ; +230 728.360198975 2.50293636322 ; +231 585.35736084 3.01314258575 ; +232 588.709442139 1.39754247665 ; +233 749.707305908 0.313934087753 ; +234 529.013702393 3.33361649513 ; +235 709.123077393 4.32010889053 ; +236 706.953094482 4.60578393936 ; +237 840.7918396 3.88974308968 ; +238 891.194274902 0.0254336185753 ; +239 646.282745361 2.74338412285 ; +240 705.71383667 1.32743191719 ; +241 414.780432701 4.14743995667 ; +242 502.089523315 3.18803453445 ; +243 529.697769165 3.30450677872 ; +244 784.892272949 3.84619164467 ; +245 694.426177979 4.21297979355 ; +246 655.211959839 3.47563409805 ; +247 898.135803223 1.68997251987 ; +248 736.931304932 3.04461526871 ; +249 484.900932312 4.30006504059 ; +250 519.301422119 0.991262733936 ; +251 415.25265789 3.51425909996 ; +252 815.356567383 3.98014831543 ; +253 835.230651855 4.22074174881 ; +254 700.951660156 0.94699203968 ; +255 509.478782654 0.0997486338019 ; +256 547.521072388 3.86835479736 ; +257 443.968086243 4.71663093567 ; +258 641.356643677 4.81252002716 ; +259 802.461120605 1.64652311802 ; +260 711.44720459 4.93478536606 ; +261 794.109008789 2.90693688393 ; +262 589.09777832 1.66652727127 ; +263 832.351654053 0.349044829607 ; +264 539.657913208 2.30591988564 ; +265 459.551239014 3.77760648727 ; +266 423.394384384 1.89430892467 ; +267 665.022918701 2.40272927284 ; +268 667.384979248 4.40000581741 ; +269 490.008514404 2.73154234886 ; +270 803.1980896 0.509617030621 ; +271 413.398547173 1.89386665821 ; +272 421.596107483 4.65777206421 ; +273 717.829681396 2.63969182968 ; +274 430.12673378 3.40044903755 ; +275 535.103912354 1.91506385803 ; +276 547.808120728 2.11201238632 ; +277 559.255340576 1.04594492912 ; +278 819.602478027 2.59190177917 ; +279 609.413848877 1.18680024147 ; +280 555.110412598 4.40798187256 ; +281 895.142883301 3.67059350014 ; +282 566.5415802 0.646473705769 ; +283 428.297527313 0.965559840202 ; +284 716.484436035 1.54097104073 ; +285 810.137329102 1.78569424152 ; +286 616.235641479 2.72493052483 ; +287 690.853363037 3.72857618332 ; +288 518.429367065 4.42398881912 ; +289 798.267669678 1.84957015514 ; +290 472.57371521 2.4650888443 ; +291 474.983764648 2.52160835266 ; +292 467.110198975 4.21170186996 ; +293 506.959693909 1.71633780003 ; +294 548.851837158 2.52935743332 ; +295 490.701271057 4.16365480423 ; +296 755.240814209 0.32738032937 ; +297 628.159729004 1.80812370777 ; +298 813.504516602 2.70873355865 ; +299 468.467536926 2.33968257904 ; +300 704.488952637 0.457058161497 ; +301 577.665679932 0.272642880678 ; +302 630.918716431 0.510406315327 ; +303 739.878112793 3.31792354584 ; +304 834.246948242 3.8866174221 ; +305 637.747833252 3.28021168709 ; +306 451.562000275 1.02609860897 ; +307 463.984546661 3.88400053978 ; +308 739.668762207 3.12978482246 ; +309 629.319900513 1.79749619961 ; +310 451.933738708 3.50408244133 ; +311 711.79699707 3.72713661194 ; +312 598.633377075 4.31371831894 ; +313 466.724807739 4.43918228149 ; +314 834.274414062 3.50484037399 ; +315 485.319488525 4.6467590332 ; +316 707.871582031 3.98138689995 ; +317 417.130994797 4.20635938644 ; +318 528.314086914 0.749422907829 ; +319 455.070034027 0.620891869068 ; +320 432.924911499 3.69034337997 ; +321 760.181091309 0.636051952839 ; +322 412.491806984 4.49802160263 ; +323 725.145812988 2.26345825195 ; +324 594.447052002 0.716078341007 ; +325 412.91681385 0.929059147835 ; +326 869.770751953 4.37097263336 ; +327 693.903198242 1.30892217159 ; +328 805.400878906 0.729910254478 ; +329 660.262298584 2.28815126419 ; +330 595.949676514 3.26510953903 ; +331 569.938201904 1.51491749287 ; +332 521.824401855 0.0273536648601 ; +333 873.306091309 3.55910110474 ; +334 681.39855957 4.65688800812 ; +335 731.480865479 1.99165070057 ; +336 767.559387207 0.709156155586 ; +337 778.827148438 4.48155260086 ; +338 545.997436523 2.79064822197 ; +339 642.692672729 4.3591542244 ; +340 830.804962158 0.391807109118 ; +341 410.224252701 3.39023137093 ; +342 861.960083008 1.63730847836 ; +343 724.29119873 3.62175965309 ; +344 491.520652771 1.87687897682 ; +345 870.715362549 3.13501691818 ; +346 422.867969513 3.41982626915 ; +347 602.04296875 2.36309742928 ; +348 558.024978638 4.25808572769 ; +349 464.9973526 4.10518407822 ; +350 482.746505737 2.20592999458 ; +351 406.749455452 4.38103961945 ; +352 613.421737671 4.79336261749 ; +353 605.044113159 1.76516127586 ; +354 606.517807007 4.44849967957 ; +355 493.481445312 1.42752277851 ; +356 637.508346558 3.02856826782 ; +357 514.8176651 2.40562367439 ; +358 531.935256958 4.36061096191 ; +359 778.466705322 3.9050245285 ; +360 574.516784668 1.03856611252 ; +361 418.008207321 1.63938605785 ; +362 716.31149292 2.47485303879 ; +363 885.612213135 1.84775364399 ; +364 419.690990448 4.46492242813 ; +365 595.52053833 1.13975584507 ; +366 487.825790405 0.881244540215 ; +367 507.722900391 4.98904275894 ; +368 484.400512695 0.195122599602 ; +369 842.571289062 2.95906543732 ; +370 701.40802002 2.64865875244 ; +371 500.67729187 0.833468675613 ; +372 710.786529541 3.89339780807 ; +373 533.375854492 1.47904837132 ; +374 736.773345947 1.49772727489 ; +375 630.238342285 1.15928590298 ; +376 811.853240967 0.177305400372 ; +377 897.168518066 4.11695194244 ; +378 761.124267578 4.15747833252 ; +379 874.313323975 2.84393787384 ; +380 706.378936768 3.11228561401 ; +381 718.732055664 4.30291032791 ; +382 801.342163086 3.58055257797 ; +383 734.601623535 1.49758327007 ; +384 888.074829102 0.736878633499 ; +385 871.973876953 4.65348577499 ; +386 513.308525085 3.7655184269 ; +387 606.609359741 4.83678531647 ; +388 584.923934937 0.168075859547 ; +389 885.097229004 0.298440515995 ; +390 488.992683411 2.00047087669 ; +391 591.430618286 3.74673056602 ; +392 530.359512329 4.52480554581 ; +393 741.009155273 3.41174578667 ; +394 520.952217102 3.44082713127 ; +395 898.025238037 3.10531973839 ; +396 510.683250427 2.53442430496 ; +397 507.274124146 4.56276130676 ; +398 532.997573853 2.90470743179 ; +399 841.855651855 2.68303155899 ; +400 770.900665283 2.27689933777 ; +401 684.686676025 2.29055643082 ; +402 638.441589355 4.87918233871 ; +403 842.169006348 0.349331110716 ; +404 520.827003479 2.39575910568 ; +405 452.562454224 4.17196369171 ; +406 719.534088135 4.09685945511 ; +407 491.550094604 1.8249835968 ; +408 650.064025879 3.26589488983 ; +409 889.483612061 2.51417160034 ; +410 468.15978241 0.616029918194 ; +411 761.451873779 4.22123003006 ; +412 521.303863525 2.54114556313 ; +413 803.745941162 2.58152961731 ; +414 676.579376221 4.69787216187 ; +415 613.595062256 3.92420506477 ; +416 811.320007324 0.559116244316 ; +417 606.721542358 3.6935608387 ; +418 668.06137085 3.07531929016 ; +419 589.232772827 4.35258865356 ; +420 796.387390137 0.828331947327 ; +421 577.448165894 3.71398949623 ; +422 502.014602661 0.595288991928 ; +423 402.278854132 3.00701522827 ; +424 790.690582275 3.36968684196 ; +425 832.907226562 3.71982145309 ; +426 803.97076416 0.36919683218 ; +427 409.139613152 1.09476017952 ; +428 863.540985107 2.33824014664 ; +429 780.458862305 3.72735381126 ; +430 463.643512726 1.56504166126 ; +431 765.54397583 1.98095977306 ; +432 799.076477051 2.78495597839 ; +433 575.652801514 1.96773552895 ; +434 573.295211792 0.727660357952 ; +435 878.772003174 2.21104621887 ; +436 505.60874939 4.66319084167 ; +437 825.53604126 4.84556055069 ; +438 833.474182129 4.00891971588 ; +439 691.00881958 4.85299682617 ; +440 832.111541748 4.98947572708 ; +441 712.303710938 3.88805198669 ; +442 548.970031738 2.39401292801 ; +443 517.474411011 3.92429089546 ; +444 455.775249481 4.14636278152 ; +445 691.955963135 4.04166078568 ; +446 719.345916748 2.4671356678 ; +447 415.236554146 0.807704985142 ; +448 409.798116684 1.76960015297 ; +449 567.043426514 4.99086380005 ; +450 544.890472412 1.74258959293 ; +451 670.407653809 2.42020010948 ; +452 530.44720459 4.26240682602 ; +453 727.281036377 1.12581145763 ; +454 551.344314575 1.44258081913 ; +455 445.525138855 1.41077458858 ; +456 488.922569275 0.217363253236 ; +457 722.430023193 0.819820165634 ; +458 771.772583008 3.8190112114 ; +459 512.272766113 4.68413448334 ; +460 525.20703125 3.54757356644 ; +461 807.037536621 0.80002361536 ; +462 499.662002563 0.193104848266 ; +463 451.315498352 4.59619522095 ; +464 725.83972168 3.88226914406 ; +465 829.883331299 0.498802632093 ; +466 737.567687988 0.0057647516951 ; +467 588.818161011 4.67125368118 ; +468 876.3230896 0.624674022198 ; +469 789.666351318 1.22857773304 ; +470 770.579650879 3.32406187057 ; +471 650.829956055 1.99080765247 ; +472 850.372161865 4.05545330048 ; +473 400.492071241 2.70241785049 ; +474 853.797668457 4.78043317795 ; +475 874.155456543 1.31281995773 ; +476 856.580688477 2.51623082161 ; +477 429.285503387 2.01493620872 ; +478 403.5341115 3.97814679146 ; +479 471.609786987 0.457171261311 ; +480 767.776031494 2.11676073074 ; +481 539.80015564 1.2139518261 ; +482 688.842102051 0.693874597549 ; +483 595.01940918 1.91499185562 ; +484 426.742021561 4.53156423569 ; +485 600.526306152 2.4570376873 ; +486 443.206970215 1.79536879063 ; +487 876.245605469 2.6037478447 ; +488 519.008529663 1.76390886307 ; +489 501.506225586 0.151998326182 ; +490 863.602539062 2.68669605255 ; +491 430.265022278 1.64265286922 ; +492 706.662139893 0.708546102047 ; +493 753.435821533 1.95997238159 ; +494 525.696754456 0.854055583477 ; +495 811.165008545 4.50720691681 ; +496 662.800079346 3.81138420105 ; +497 693.372528076 2.12529206276 ; +498 878.522583008 0.292034298182 ; +499 722.056915283 3.10684943199 ; +500 581.751205444 1.92607629299 ; +501 556.287033081 2.16389775276 ; +502 762.845153809 3.39128541946 ; +503 633.384429932 4.92468070984 ; +504 810.719451904 4.62360572815 ; +505 794.420135498 0.194010049105 ; +506 472.671676636 3.92950034142 ; +507 711.013214111 1.99396324158 ; +508 654.013046265 1.97671794891 ; +509 669.946716309 4.94591426849 ; +510 498.204147339 0.171279773116 ; +511 769.913238525 1.31909132004 ; +512 896.849121094 0.435650378466 ; +513 597.623504639 4.58438301086 ; +514 872.876647949 1.3795106411 ; +515 443.598960876 2.67833209038 ; +516 872.837921143 4.87638473511 ; +517 639.937667847 1.32598721981 ; +518 486.751106262 0.259638100863 ; +519 773.747680664 0.778259158134 ; +520 420.264732361 0.893618285656 ; +521 804.291717529 4.31452083588 ; +522 815.368652344 1.0133998394 ; +523 621.197738647 1.70542144775 ; +524 702.053985596 1.2114354372 ; +525 459.659996033 2.0558180809 ; +526 613.432952881 1.67810916901 ; +527 798.058166504 1.63885223866 ; +528 818.994750977 0.454613298178 ; +529 468.60660553 0.711999535561 ; +530 557.6199646 1.189021945 ; +531 789.137695312 2.37592482567 ; +532 617.007400513 2.43526148796 ; +533 844.032440186 3.53597569466 ; +534 814.572662354 2.23323941231 ; +535 805.728515625 0.79640096426 ; +536 411.075427055 1.44722211361 ; +537 746.071289062 4.20288658142 ; +538 691.357025146 3.37549495697 ; +539 594.342376709 3.12474822998 ; +540 664.275878906 1.8463613987 ; +541 579.61831665 3.45144152641 ; +542 737.592193604 4.12505674362 ; +543 882.990386963 1.19851136208 ; +544 738.041687012 4.66857719421 ; +545 877.999969482 2.45665287971 ; +546 796.654937744 0.797827899456 ; +547 809.368438721 2.55676317215 ; +548 551.991439819 0.200899422169 ; +549 551.671508789 1.43209898472 ; +550 828.923583984 4.19150114059 ; +551 556.639419556 1.38936007023 ; +552 497.489112854 4.99659729004 ; +553 680.841522217 1.03625440598 ; +554 532.779373169 1.22846281528 ; +555 577.424850464 4.79794836044 ; +556 811.478179932 2.13824892044 ; +557 654.952865601 4.92826747894 ; +558 839.363861084 3.89029479027 ; +559 818.501617432 2.57371520996 ; +560 542.883026123 4.3521938324 ; +561 631.838623047 0.119352728128 ; +562 496.132598877 2.00722122192 ; +563 436.735080719 4.06579017639 ; +564 773.349151611 3.79295158386 ; +565 713.926391602 1.61135017872 ; +566 596.254455566 4.48705291748 ; +567 789.984344482 4.67156600952 ; +568 401.515529752 4.71509647369 ; +569 562.614929199 0.692855656147 ; +570 882.42980957 1.98084318638 ; +571 603.323318481 2.55338573456 ; +572 875.33404541 4.39673900604 ; +573 499.153060913 4.65597581863 ; +574 698.831237793 4.56806325912 ; +575 443.905967712 4.27605867386 ; +576 671.573852539 3.42257881165 ; +577 728.237213135 1.8326343298 ; +578 508.593086243 1.24064004421 ; +579 543.717010498 4.51914072037 ; +580 720.047027588 0.30760383606 ; +581 889.776885986 1.80319726467 ; +582 533.683273315 3.148229599 ; +583 629.509841919 3.72051286697 ; +584 466.108352661 0.830810666084 ; +585 743.432342529 0.675653338432 ; +586 470.624343872 4.83401870728 ; +587 435.520587921 4.94543170929 ; +588 686.946166992 2.04622411728 ; +589 489.030471802 3.35184335709 ; +590 843.320709229 3.91187810898 ; +591 593.840576172 3.78481888771 ; +592 545.336837769 1.76436531544 ; +593 768.752593994 1.24953770638 ; +594 497.955986023 3.46377515793 ; +595 467.233863831 4.99658155441 ; +596 655.045822144 0.550757169724 ; +597 557.637405396 4.12011480331 ; +598 576.610351562 2.90316677094 ; +599 752.423126221 1.75718092918 ; +600 693.999206543 2.4504172802 ; +601 816.516448975 3.92667150497 ; +602 456.720867157 3.07695198059 ; +603 833.33392334 0.433821290731 ; +604 523.468711853 1.38713526726 ; +605 758.147705078 3.88707256317 ; +606 402.963272333 3.03719067574 ; +607 506.33429718 1.60608541965 ; +608 747.855285645 4.03884077072 ; +609 479.974517822 1.31805562973 ; +610 656.104156494 3.42957353592 ; +611 484.058227539 2.66770839691 ; +612 517.547821045 1.26248371601 ; +613 756.538208008 3.38075017929 ; +614 426.603578568 1.26376867294 ; +615 416.111347198 2.83415174484 ; +616 758.986114502 4.79854202271 ; +617 810.150268555 3.95974206924 ; +618 538.683578491 3.54935646057 ; +619 803.542999268 3.47562098503 ; +620 876.186767578 2.71270418167 ; +621 641.805206299 0.201665475965 ; +622 839.18359375 3.58968424797 ; +623 582.675247192 2.23027801514 ; +624 828.48248291 0.0519924871624 ; +625 783.78024292 1.94799363613 ; +626 892.917480469 4.64590215683 ; +627 767.796173096 0.50506991148 ; +628 771.03112793 4.20411634445 ; +629 758.328521729 4.27780342102 ; +630 604.552719116 4.17591285706 ; +631 856.361755371 0.721025407314 ; +632 727.416717529 3.92895579338 ; +633 795.911071777 0.777487874031 ; +634 623.912750244 3.01671600342 ; +635 594.328674316 0.822504222393 ; +636 782.930938721 4.20675754547 ; +637 698.012573242 1.97704803944 ; +638 724.687591553 0.245528072119 ; +639 559.046646118 0.971288442612 ; +640 844.468231201 1.7799526453 ; +641 466.291038513 1.53561377525 ; +642 806.165618896 4.25595474243 ; +643 883.631195068 3.8981962204 ; +644 598.29675293 2.73599505424 ; +645 786.991546631 1.67042267323 ; +646 879.430450439 2.87735557556 ; +647 871.492248535 3.70601344109 ; +648 597.103256226 2.14450740814 ; +649 673.687042236 3.58544635773 ; +650 459.657886505 1.7013617754 ; +651 878.790435791 0.313066959381 ; +652 571.610687256 2.61066961288 ; +653 652.839904785 4.80394458771 ; +654 890.303894043 0.377779185772 ; +655 833.494262695 2.37993240356 ; +656 852.388580322 2.95539951324 ; +657 539.918823242 1.15781033039 ; +658 831.856811523 2.18037104607 ; +659 449.487346649 2.3384168148 ; +660 577.234817505 2.85661792755 ; +661 517.461135864 1.69506692886 ; +662 799.186645508 1.30441534519 ; +663 730.923339844 3.285592556 ; +664 495.362129211 2.51387619972 ; +665 472.073631287 3.41594839096 ; +666 584.696578979 1.95535838604 ; +667 770.809631348 1.97650384903 ; +668 810.180236816 3.99777173996 ; +669 454.950824738 0.585386514664 ; +670 759.160247803 4.06552410126 ; +671 826.408660889 1.50827670097 ; +672 860.791809082 0.280512660742 ; +673 857.627532959 3.46451663971 ; +674 713.086181641 0.397704303265 ; +675 821.667419434 4.64301109314 ; +676 409.475725174 2.58525872231 ; +677 444.409385681 3.88568425179 ; +678 569.73085022 1.6639777422 ; +679 547.457565308 3.19353938103 ; +680 781.585388184 3.05939602852 ; +681 827.287841797 4.27521562576 ; +682 754.762329102 4.90701436996 ; +683 618.957595825 0.205562695861 ; +684 889.220703125 3.33083438873 ; +685 533.321395874 2.32787060738 ; +686 852.050231934 1.08461761475 ; +687 816.937835693 4.74776077271 ; +688 461.5938797 2.08368110657 ; +689 442.986919403 4.8120174408 ; +690 457.534156799 4.76582145691 ; +691 816.468353271 0.838862359524 ; +692 775.925262451 1.75896906853 ; +693 699.37588501 1.10684335232 ; +694 671.673950195 0.245516076684 ; +695 538.874176025 0.584799051285 ; +696 771.750274658 0.0728022456169 ; +697 758.736572266 2.86258602142 ; +698 548.667327881 1.51787769794 ; +699 497.14516449 2.18880319595 ; +700 621.692016602 4.77900505066 ; +701 473.811943054 0.574273824692 ; +702 582.066116333 4.85487222672 ; +703 483.954803467 0.285264015198 ; +704 843.263427734 4.28583526611 ; +705 603.587890625 2.01878523827 ; +706 872.360931396 4.70071029663 ; +707 883.630157471 3.72382450104 ; +708 532.104766846 2.84941673279 ; +709 414.497628212 1.61637318134 ; +710 538.363311768 4.72330617905 ; +711 860.903045654 3.98209142685 ; +712 601.331100464 2.71822094917 ; +713 414.010099411 4.67753505707 ; +714 432.995632172 0.576133012772 ; +715 706.75970459 2.10478973389 ; +716 420.051822662 0.109971046448 ; +717 728.334716797 3.21643400192 ; +718 760.700744629 2.97817635536 ; +719 820.983978271 4.7816119194 ; +720 855.072143555 3.97763347626 ; +721 608.470809937 2.69213962555 ; +722 579.212417603 0.232267662883 ; +723 772.25491333 4.8857178688 ; +724 826.298278809 2.95222902298 ; +725 711.605316162 1.50777447224 ; +726 516.623970032 0.991465687752 ; +727 756.364959717 4.25922107697 ; +728 873.324432373 1.64014708996 ; +729 495.273292542 2.58210301399 ; +730 640.549362183 4.1338391304 ; +731 643.327163696 0.998444378376 ; +732 485.568473816 1.49412059784 ; +733 568.578399658 2.97100424767 ; +734 766.720062256 4.64178514481 ; +735 848.366149902 1.90098333359 ; +736 882.585357666 3.12400817871 ; +737 420.305786133 2.7936193943 ; +738 636.076705933 2.41275429726 ; +739 516.274497986 2.25675582886 ; +740 829.421539307 2.88563776016 ; +741 791.519592285 2.69819521904 ; +742 756.791259766 0.909905850887 ; +743 678.75177002 4.81102895737 ; +744 796.324645996 0.287464737892 ; +745 541.989898682 4.24184417725 ; +746 667.646636963 3.36925268173 ; +747 603.227432251 1.43611299992 ; +748 575.163894653 4.79844999313 ; +749 654.910339355 2.78177499771 ; +750 729.315155029 3.00243878365 ; +751 599.005325317 1.8262168169 ; +752 722.701843262 1.50178968906 ; +753 457.947235107 4.19229125977 ; +754 883.725524902 4.75520277023 ; +755 469.552436829 4.67929458618 ; +756 890.220550537 1.37014341354 ; +757 700.172363281 4.97426748276 ; +758 651.776947021 1.15387916565 ; +759 724.749816895 0.703709661961 ; +760 624.831756592 2.47320461273 ; +761 614.971847534 0.320125520229 ; +762 434.962097168 1.08014583588 ; +763 801.118927002 1.06066429615 ; +764 558.58354187 3.13679385185 ; +765 409.555267334 0.953871369362 ; +766 571.691055298 1.11679184437 ; +767 892.015350342 3.02056336403 ; +768 560.870193481 2.45472598076 ; +769 558.197265625 3.21502590179 ; +770 894.308013916 3.34887981415 ; +771 862.357116699 3.36297607422 ; +772 554.017349243 0.697463989258 ; +773 627.745285034 2.15124583244 ; +774 498.999053955 3.77170729637 ; +775 508.851974487 4.75188779831 ; +776 897.799713135 0.200256705284 ; +777 471.440811157 2.05770349503 ; +778 782.130279541 4.64016485214 ; +779 625.079223633 4.06722640991 ; +780 687.858398438 0.365463227034 ; +781 634.074111938 0.840096533298 ; +782 850.284851074 4.37799787521 ; +783 501.010375977 1.81525313854 ; +784 796.031951904 1.09489905834 ; +785 596.790283203 4.54524040222 ; +786 585.876266479 0.226171016693 ; +787 525.620109558 2.97134304047 ; +788 836.240997314 4.03252792358 ; +789 869.859619141 4.30873346329 ; +790 588.068237305 3.62910294533 ; +791 833.505401611 4.25376081467 ; +792 695.881225586 3.75966596603 ; +793 770.702392578 3.95362758636 ; +794 762.175476074 0.837608098984 ; +795 667.970977783 2.88038420677 ; +796 461.895881653 2.84152078629 ; +797 643.949371338 0.573059976101 ; +798 541.942977905 1.35638594627 ; +799 577.802261353 3.22687530518 ; +800 809.18548584 1.80605840683 ; +801 842.345397949 4.9953827858 ; +802 640.362258911 2.68807435036 ; +803 746.584625244 0.484263956547 ; +804 802.43762207 2.6917412281 ; +805 409.705665588 1.23140060902 ; +806 514.967750549 2.63036394119 ; +807 752.973846436 4.31628465652 ; +808 779.911254883 1.68572950363 ; +809 605.586669922 2.95363306999 ; +810 571.146087646 4.52373600006 ; +811 442.79126358 1.92819643021 ; +812 619.703399658 0.551714420319 ; +813 666.488494873 3.72044467926 ; +814 851.483306885 0.806359171867 ; +815 647.883468628 1.77733182907 ; +816 561.66519165 1.07158923149 ; +817 420.071510315 3.41899895668 ; +818 711.7862854 1.92468464375 ; +819 717.603546143 4.6299905777 ; +820 524.861541748 0.480570405722 ; +821 594.733703613 3.89450311661 ; +822 891.457611084 4.28801250458 ; +823 763.131622314 1.53543066978 ; +824 498.374076843 3.73232293129 ; +825 815.322570801 3.26756381989 ; +826 694.767425537 1.5619918108 ; +827 639.847366333 1.14889621735 ; +828 850.029876709 1.52870440483 ; +829 693.539764404 0.232288599014 ; +830 807.453979492 0.797739744186 ; +831 661.234832764 0.741912424564 ; +832 832.255584717 4.19717979431 ; +833 599.785385132 2.93210673332 ; +834 891.950195312 2.07221627235 ; +835 673.91796875 2.3914809227 ; +836 761.917419434 2.4627737999 ; +837 584.252990723 2.40003442764 ; +838 637.682052612 2.22436928749 ; +839 897.457733154 2.72375321388 ; +840 711.748504639 0.573742568493 ; +841 689.171295166 1.02313554287 ; +842 483.956222534 0.522755205631 ; +843 494.681556702 3.12933731079 ; +844 877.413208008 3.84060430527 ; +845 804.01184082 2.26958918571 ; +846 898.613494873 1.97325968742 ; +847 857.697479248 0.219958037138 ; +848 583.478652954 2.25980091095 ; +849 447.43271637 2.01662158966 ; +850 736.13973999 0.0101514114067 ; +851 461.477153778 2.46614313126 ; +852 746.779846191 3.28942990303 ; +853 444.791290283 3.07236051559 ; +854 616.302947998 4.03908205032 ; +855 885.427398682 0.784581065178 ; +856 545.425811768 1.71691775322 ; +857 523.55960083 1.66377747059 ; +858 710.935424805 3.91770458221 ; +859 886.138977051 0.382421165705 ; +860 635.229995728 0.109482258558 ; +861 406.832044125 3.2617316246 ; +862 892.45123291 1.28070163727 ; +863 875.141784668 2.08209061623 ; +864 769.886566162 1.83892548084 ; +865 581.935775757 2.94698643684 ; +866 400.146624386 4.64316272736 ; +867 663.734893799 0.924181759357 ; +868 672.314178467 2.84729290009 ; +869 845.356262207 1.02963614464 ; +870 409.426836014 4.36843156815 ; +871 423.570022583 1.41396510601 ; +872 851.030334473 4.66909122467 ; +873 741.444152832 1.52142190933 ; +874 453.826118469 1.55587244034 ; +875 854.8359375 4.27907943726 ; +876 749.275268555 2.69978427887 ; +877 427.645441055 1.36954569817 ; +878 695.622650146 0.303985506296 ; +879 808.449279785 3.0702996254 ; +880 652.37538147 1.73489415646 ; +881 736.639831543 4.06019163132 ; +882 864.448883057 4.92700529099 ; +883 717.556915283 1.79285991192 ; +884 659.601348877 1.20105731487 ; +885 517.148223877 4.10213947296 ; +886 865.936706543 4.98545122147 ; +887 447.546237946 1.09703600407 ; +888 688.50680542 4.33947658539 ; +889 758.364624023 0.34410071373 ; +890 730.049468994 1.41719925404 ; +891 786.73727417 3.93441581726 ; +892 472.908195496 3.68142962456 ; +893 778.980255127 0.214615911245 ; +894 604.970001221 4.31199884415 ; +895 576.744033813 0.371929436922 ; +896 501.790054321 2.8546974659 ; +897 789.698181152 1.57614016533 ; +898 418.799015045 4.55058479309 ; +899 567.718948364 3.5249505043 ; +900 784.176025391 3.46559739113 ; +901 529.433883667 3.95411586761 ; +902 582.645095825 2.16243004799 ; +903 796.317932129 4.15968513489 ; +904 582.462738037 1.51491594315 ; +905 519.245605469 1.61034166813 ; +906 401.352453828 2.3069164753 ; +907 634.593826294 3.18636894226 ; +908 730.279815674 0.132408753037 ; +909 439.393680573 0.896064043045 ; +910 414.892631531 3.0046069622 ; +911 742.915863037 3.8755440712 ; +912 527.083938599 3.99701738358 ; +913 687.082885742 0.0262835528702 ; +914 574.767318726 3.1450586319 ; +915 800.331512451 3.72122097015 ; +916 656.487365723 2.83350944519 ; +917 679.530212402 0.646556973457 ; +918 568.283874512 3.47203612328 ; +919 851.079864502 2.99681758881 ; +920 651.329315186 0.920556783676 ; +921 579.763565063 2.86251330376 ; +922 426.016382217 2.57340884209 ; +923 528.338394165 4.83337879181 ; +924 859.930908203 0.590119659901 ; +925 714.108917236 2.2901699543 ; +926 488.442062378 4.45768499374 ; +927 431.147428513 4.94851541519 ; +928 869.841827393 1.31753408909 ; +929 779.574279785 0.0529867224395 ; +930 454.788356781 3.27945804596 ; +931 685.259338379 3.54257202148 ; +932 400.656058729 0.26379904151 ; +933 767.0390625 3.26110172272 ; +934 833.938690186 2.0799267292 ; +935 633.11756897 0.0719149187207 ; +936 767.410186768 0.634212553501 ; +937 821.11505127 1.81174564362 ; +938 400.905425489 2.17486739159 ; +939 699.505432129 2.87804174423 ; +940 524.735168457 4.24066495895 ; +941 685.947296143 4.16665124893 ; +942 790.805084229 2.61007213593 ; +943 648.513244629 2.62193226814 ; +944 581.727890015 3.0094871521 ; +945 444.986099243 0.814485013485 ; +946 804.968261719 3.01883101463 ; +947 649.343429565 2.15216517448 ; +948 544.260879517 0.92675101757 ; +949 490.482124329 2.33186125755 ; +950 559.456100464 4.78651857376 ; +951 601.600036621 2.92062973976 ; +952 602.387893677 0.334697276354 ; +953 425.765066147 0.334728807211 ; +954 478.690879822 0.577651977539 ; +955 759.682220459 1.79282331467 ; +956 598.125213623 3.90779876709 ; +957 737.342376709 2.13427686691 ; +958 479.286849976 0.741364955902 ; +959 412.085877419 1.2735260725 ; +960 815.238952637 4.2125005722 ; +961 849.545928955 0.18807476759 ; +962 497.255767822 0.777917265892 ; +963 845.593994141 0.984229505062 ; +964 594.496261597 3.98890280724 ; +965 549.043579102 4.75685882568 ; +966 752.640655518 3.31544303894 ; +967 665.214385986 4.58526849747 ; +968 860.865081787 2.59921789169 ; +969 405.481297016 1.24165165424 ; +970 743.850921631 1.02939105034 ; +971 497.595458984 2.86893296242 ; +972 715.910766602 0.128045588732 ; +973 606.23046875 1.15565347672 ; +974 706.694335938 1.11875855923 ; +975 697.654571533 1.80709946156 ; +976 592.016357422 2.18993377686 ; +977 521.797515869 0.509503722191 ; +978 722.947753906 2.83081078529 ; +979 643.883132935 4.4414191246 ; +980 593.490905762 0.0164948608726 ; +981 622.913452148 0.065922960639 ; +982 696.716094971 4.07230091095 ; +983 716.503448486 4.73495149612 ; +984 433.040374756 3.09570837021 ; +985 857.444488525 2.69835472107 ; +986 524.727020264 2.87167668343 ; +987 826.957122803 3.68369269371 ; +988 582.697463989 0.964904129505 ; +989 614.425979614 3.57766413689 ; +990 880.10043335 0.48217818141 ; +991 796.850311279 3.6310904026 ; +992 673.78805542 0.560489058495 ; +993 413.986094475 0.642963349819 ; +994 528.479064941 3.47648835182 ; +995 833.808898926 0.266231358051 ; +996 855.037384033 3.13986635208 ; +997 573.315429688 4.12626123428 ; +998 407.222122669 3.82220959663 ; +999 887.587524414 3.83603739738 ; +1000 628.202346802 3.97015142441 ; +1001 533.804199219 3.47315406799 ; +1002 730.015045166 0.630146980286 ; +1003 488.068611145 1.69102537632 ; +1004 506.20337677 4.60306978226 ; +1005 779.865600586 4.01404857635 ; +1006 811.210601807 2.17063117027 ; +1007 579.939483643 2.43077111244 ; +1008 796.990234375 2.14882135391 ; +1009 424.129463196 0.439339190722 ; +1010 797.40322876 1.56151652336 ; +1011 840.735900879 4.49031257629 ; +1012 768.607177734 1.81150400639 ; +1013 494.763809204 1.955088377 ; +1014 816.915435791 0.978581368923 ; +1015 601.716888428 2.56051206589 ; +1016 852.633483887 4.11047935486 ; +1017 883.120574951 3.07865262032 ; +1018 691.703979492 1.68981134892 ; +1019 466.056747437 2.15844988823 ; +1020 606.897094727 3.19615578651 ; +1021 678.830963135 3.12207865715 ; +1022 677.563140869 0.0414274446666 ; +1023 527.102371216 2.09539866447 ; +1024 636.577713013 1.61728739738 ; +1025 574.840042114 0.366677910089 ; +1026 675.559051514 3.2143342495 ; +1027 731.763458252 4.48761606216 ; +1028 736.587615967 0.28401440382 ; +1029 743.037689209 4.34290838242 ; +1030 526.363555908 2.92351531982 ; +1031 452.28327179 2.25021910667 ; +1032 843.257446289 3.28449058533 ; +1033 643.357498169 1.09583699703 ; +1034 673.248016357 4.79651927948 ; +1035 410.320702553 4.60040283203 ; +1036 797.484802246 0.270771831274 ; +1037 486.240509033 4.44306850433 ; +1038 865.590881348 1.86209797859 ; +1039 528.034942627 3.83319592476 ; +1040 852.207458496 2.5102751255 ; +1041 419.566619873 3.56209897995 ; +1042 719.987701416 0.333131015301 ; +1043 793.291381836 0.488219380379 ; +1044 450.320026398 2.28716492653 ; +1045 438.089893341 1.76848602295 ; +1046 694.537628174 2.94046401978 ; +1047 437.923381805 3.78295469284 ; +1048 412.253401756 4.4293589592 ; +1049 823.750183105 4.6954164505 ; +1050 486.406196594 2.29069924355 ; +1051 878.292419434 1.60742580891 ; +1052 500.675674438 0.562011003494 ; +1053 471.968360901 0.72279727459 ; +1054 705.393249512 2.44741892815 ; +1055 776.835571289 4.75521373749 ; +1056 487.967880249 4.76344919205 ; +1057 829.543640137 3.40774774551 ; +1058 801.481994629 2.08392190933 ; +1059 847.758880615 4.84066677094 ; +1060 609.192764282 4.02755117416 ; +1061 505.220085144 4.34043931961 ; +1062 876.431213379 3.8018860817 ; +1063 730.189331055 4.92569494247 ; +1064 515.619667053 2.19898581505 ; +1065 735.609741211 0.934642672539 ; +1066 754.053161621 0.715793192387 ; +1067 433.731700897 4.28751277924 ; +1068 422.708721161 1.65470004082 ; +1069 454.258152008 4.16790914536 ; +1070 404.683939457 2.22971320152 ; +1071 879.222137451 2.86875367165 ; +1072 414.25122261 0.202983692288 ; +1073 554.691772461 4.04880475998 ; +1074 726.295501709 0.489980340004 ; +1075 409.967219353 0.190629690886 ; +1076 791.349761963 4.16012239456 ; +1077 817.722747803 1.6630538702 ; +1078 494.647201538 2.35652923584 ; +1079 518.621994019 1.79890024662 ; +1080 811.631011963 2.82760167122 ; +1081 750.070770264 1.39389383793 ; +1082 617.316574097 4.39804887772 ; +1083 700.781188965 2.29242372513 ; +1084 776.412597656 3.66767573357 ; +1085 662.695129395 1.17352616787 ; +1086 745.516540527 0.96895390749 ; +1087 420.866727829 2.07127666473 ; +1088 594.509674072 1.2427406311 ; +1089 574.266540527 3.97754454613 ; +1090 459.139785767 4.62447309494 ; +1091 751.86227417 2.49384593964 ; +1092 806.98147583 1.37817072868 ; +1093 691.498596191 2.16992712021 ; +1094 896.533721924 2.4297645092 ; +1095 605.234420776 3.75059342384 ; +1096 522.078460693 2.72767210007 ; +1097 798.596954346 2.19475769997 ; +1098 629.450393677 3.72968292236 ; +1099 878.225128174 0.300709336996 ; +1100 802.191497803 1.3310624361 ; +1101 516.734436035 4.5587439537 ; +1102 781.224029541 2.32559680939 ; +1103 530.621963501 3.63418364525 ; +1104 872.637756348 1.22961032391 ; +1105 505.979217529 1.92704582214 ; +1106 685.960144043 1.32708132267 ; +1107 825.677856445 3.6812376976 ; +1108 456.079929352 0.353983789682 ; +1109 840.586883545 4.44056987762 ; +1110 666.062866211 2.19083404541 ; +1111 535.014266968 1.84981167316 ; +1112 878.586181641 0.981132924557 ; +1113 890.085906982 3.74379682541 ; +1114 599.469039917 4.76358890533 ; +1115 564.037353516 4.75983095169 ; +1116 748.145629883 2.83644890785 ; +1117 619.726257324 4.39207458496 ; +1118 659.983764648 0.474019229412 ; +1119 584.131759644 2.02592110634 ; +1120 865.677001953 1.33528530598 ; +1121 613.889572144 3.42145109177 ; +1122 833.128875732 0.970912992954 ; +1123 713.455474854 2.4651954174 ; +1124 653.781066895 2.98699855804 ; +1125 648.498397827 0.127590224147 ; +1126 840.881988525 4.03725004196 ; +1127 806.631530762 2.56824946404 ; +1128 856.740814209 4.4291973114 ; +1129 551.95211792 3.59466099739 ; +1130 446.974349976 4.97963428497 ; +1131 671.28793335 0.366401940584 ; +1132 711.721466064 1.02881336212 ; +1133 526.738258362 0.900430440903 ; +1134 753.495178223 1.93264508247 ; +1135 596.813095093 3.37980914116 ; +1136 845.57522583 2.83180713654 ; +1137 818.158752441 4.94314908981 ; +1138 851.054748535 3.77746558189 ; +1139 686.094940186 3.97925496101 ; +1140 833.851287842 2.38947963715 ; +1141 898.363037109 4.87991523743 ; +1142 573.722564697 2.55506420135 ; +1143 696.524963379 1.95010328293 ; +1144 438.65801239 2.25277376175 ; +1145 636.81930542 2.22099971771 ; +1146 734.324310303 4.89257144928 ; +1147 845.226806641 4.27189922333 ; +1148 680.86517334 0.0144370319322 ; +1149 664.319549561 4.19176101685 ; +1150 492.955596924 3.04856085777 ; +1151 616.39881897 0.151893824339 ; +1152 687.943603516 4.6878361702 ; +1153 746.610992432 4.91379308701 ; +1154 512.402053833 1.41397070885 ; +1155 860.547180176 4.16859483719 ; +1156 557.515945435 3.70702624321 ; +1157 798.786804199 4.09957838058 ; +1158 561.089263916 4.27403688431 ; +1159 773.704772949 3.5653989315 ; +1160 766.171630859 2.47263002396 ; +1161 649.483551025 0.700849533081 ; +1162 817.797485352 4.224650383 ; +1163 770.026428223 0.344838500023 ; +1164 470.071166992 1.86180007458 ; +1165 527.393836975 1.0831874609 ; +1166 413.154641151 0.900635778904 ; +1167 598.540222168 3.65499281883 ; +1168 846.455383301 0.756721138954 ; +1169 721.154632568 1.46307945251 ; +1170 897.676086426 4.42519855499 ; +1171 831.347076416 1.50796318054 ; +1172 833.936279297 1.67229044437 ; +1173 518.548027039 4.3687081337 ; +1174 888.1980896 1.45265185833 ; +1175 872.193084717 1.4929100275 ; +1176 534.027603149 1.02156925201 ; +1177 851.556884766 3.17233562469 ; +1178 644.561248779 3.41061282158 ; +1179 617.109619141 4.61739015579 ; +1180 847.348052979 0.794402658939 ; +1181 552.510360718 2.41776275635 ; +1182 433.933792114 3.2525074482 ; +1183 889.313751221 3.96604180336 ; +1184 626.485473633 0.416338890791 ; +1185 640.805374146 2.16083025932 ; +1186 607.345748901 3.60024952888 ; +1187 839.270965576 3.27140545845 ; +1188 650.966384888 4.92234325409 ; +1189 882.680389404 4.09567117691 ; +1190 494.421096802 4.35488891602 ; +1191 661.74899292 2.15250325203 ; +1192 612.224395752 3.55729556084 ; +1193 646.516464233 2.02584886551 ; +1194 744.25869751 4.56283283234 ; +1195 652.921035767 3.43998456001 ; +1196 482.20766449 1.64274597168 ; +1197 863.279510498 3.39302039146 ; +1198 549.340942383 4.73112201691 ; +1199 497.268226624 2.8716275692 ; +1200 744.502410889 0.520023107529 ; +1201 402.825490713 4.88025522232 ; +1202 645.196228027 0.132588520646 ; +1203 741.546325684 3.68993258476 ; +1204 569.566604614 4.06103849411 ; +1205 787.650665283 2.44860982895 ; +1206 778.582092285 3.29825878143 ; +1207 783.423034668 1.91261947155 ; +1208 439.472980499 4.22382307053 ; +1209 879.448852539 0.975932538509 ; +1210 649.83152771 4.18715047836 ; +1211 743.801300049 2.68530750275 ; +1212 596.312561035 4.2546749115 ; +1213 732.09576416 0.337878614664 ; +1214 772.580078125 4.53807592392 ; +1215 544.905426025 4.25567579269 ; +1216 414.553858757 1.06718361378 ; +1217 515.508331299 3.48617601395 ; +1218 616.233627319 2.38730096817 ; +1219 736.835296631 1.91497695446 ; +1220 401.760250807 0.845367014408 ; +1221 708.337860107 2.34482645988 ; +1222 850.185119629 2.61814117432 ; +1223 709.830657959 3.24198532104 ; +1224 704.881072998 1.3666703701 ; +1225 862.87487793 0.381401926279 ; +1226 422.217794418 4.14492797852 ; +1227 780.725921631 3.61248159409 ; +1228 897.828155518 4.982442379 ; +1229 890.678588867 3.35575079918 ; +1230 410.466288567 4.06907701492 ; +1231 797.721008301 4.97429513931 ; +1232 698.085571289 4.24480342865 ; +1233 641.441238403 4.03201532364 ; +1234 508.575515747 3.28825950623 ; +1235 477.965995789 3.7454226017 ; +1236 831.795440674 1.85879874229 ; +1237 482.911445618 4.92739963531 ; +1238 880.536468506 3.76857376099 ; +1239 742.049835205 3.31431078911 ; +1240 762.59664917 1.61846995354 ; +1241 562.42086792 3.07575726509 ; +1242 825.38104248 3.79611635208 ; +1243 532.993057251 2.14241909981 ; +1244 663.799133301 1.72464966774 ; +1245 518.615737915 0.747975409031 ; +1246 522.211837769 0.144937291741 ; +1247 496.09929657 1.4092540741 ; +1248 433.362564087 2.24698352814 ; +1249 405.363069057 1.37104797363 ; +1250 720.2059021 2.00871038437 ; +1251 439.65102005 4.1468501091 ; +1252 511.216400146 2.14059996605 ; +1253 606.670623779 0.131982669234 ; +1254 723.265228271 1.18915724754 ; +1255 516.701133728 3.96089434624 ; +1256 475.158210754 1.84087026119 ; +1257 850.611053467 4.20378875732 ; +1258 707.356048584 2.33263969421 ; +1259 867.672821045 1.77628922462 ; +1260 809.231567383 4.54864645004 ; +1261 809.957519531 1.5626039505 ; +1262 668.588378906 1.65220999718 ; +1263 769.408508301 1.48786187172 ; +1264 549.445053101 2.22955346107 ; +1265 610.554641724 2.91915082932 ; +1266 616.948242188 2.49244618416 ; +1267 454.582279205 3.64452624321 ; +1268 755.187774658 1.41565024853 ; +1269 683.299438477 4.13984632492 ; +1270 740.282653809 1.31083714962 ; +1271 523.838729858 3.57609152794 ; +1272 736.908569336 4.2256603241 ; +1273 466.990699768 4.12704658508 ; +1274 727.464080811 1.8900949955 ; +1275 582.796585083 2.62333130836 ; +1276 432.632270813 4.50595617294 ; +1277 560.680343628 0.547009944916 ; +1278 759.660217285 3.09670305252 ; +1279 528.773483276 2.96031236649 ; +1280 796.887084961 4.81490039825 ; +1281 803.273712158 3.21568846703 ; +1282 507.534690857 3.35642361641 ; +1283 541.188812256 4.60387468338 ; +1284 632.250473022 4.33889293671 ; +1285 777.477935791 2.71884298325 ; +1286 459.413455963 0.620358228683 ; +1287 536.105178833 0.19659909606 ; +1288 824.11340332 0.743131458759 ; +1289 881.140350342 0.261204302311 ; +1290 406.096142292 4.57872247696 ; +1291 858.950408936 0.800084233284 ; +1292 601.608276367 4.30538845062 ; +1293 466.242408752 3.36238002777 ; +1294 551.874252319 0.50588029623 ; +1295 633.05418396 4.41682195663 ; +1296 752.550140381 3.10238981247 ; +1297 586.879547119 3.84787940979 ; +1298 530.921569824 3.98779129982 ; +1299 680.924468994 4.97576141357 ; +1300 662.456634521 1.08979773521 ; +1301 523.096687317 3.86066675186 ; +1302 522.675483704 3.06896543503 ; +1303 410.241923332 1.36022114754 ; +1304 523.71346283 2.52300167084 ; +1305 808.822479248 0.79684907198 ; +1306 664.203033447 4.60306310654 ; +1307 768.423431396 0.931585788727 ; +1308 616.22958374 1.70570254326 ; +1309 674.23840332 1.24746692181 ; +1310 517.761322021 2.14666080475 ; +1311 792.784088135 0.229200556874 ; +1312 617.365936279 2.69415664673 ; +1313 469.399925232 4.04605674744 ; +1314 607.696762085 2.59467744827 ; +1315 774.364257812 4.40760564804 ; +1316 763.234039307 3.74506878853 ; +1317 737.222229004 1.94345736504 ; +1318 768.781616211 1.128926754 ; +1319 787.126678467 4.37992429733 ; +1320 739.033691406 1.39458250999 ; +1321 774.997039795 0.751959204674 ; +1322 717.842926025 4.86081552505 ; +1323 472.554237366 4.19088792801 ; +1324 525.847900391 1.25704133511 ; +1325 609.516113281 3.3740940094 ; +1326 739.920043945 0.365921318531 ; +1327 403.989298582 0.481493473053 ; +1328 646.053131104 4.15202665329 ; +1329 711.607177734 1.82000756264 ; +1330 786.629730225 0.865794658661 ; +1331 541.066268921 4.0081577301 ; +1332 410.998304367 3.48511099815 ; +1333 826.061218262 3.11221385002 ; +1334 597.857727051 3.94922041893 ; +1335 854.943511963 2.36092758179 ; +1336 411.003426552 4.34605073929 ; +1337 807.499694824 3.47568178177 ; +1338 478.63394928 1.00917208195 ; +1339 515.472732544 2.50393414497 ; +1340 762.32131958 0.347174823284 ; +1341 896.701477051 0.621716201305 ; +1342 818.434875488 1.35207116604 ; +1343 825.974578857 3.55109715462 ; +1344 729.298095703 0.135170221329 ; +1345 580.598907471 3.26037764549 ; +1346 616.468688965 1.89669132233 ; +1347 669.196929932 3.92669463158 ; +1348 495.958366394 2.72396063805 ; +1349 560.616744995 4.85818529129 ; +1350 552.013473511 3.90594172478 ; +1351 616.331100464 3.76965284348 ; +1352 555.493927002 3.86552858353 ; +1353 693.999786377 2.54589915276 ; +1354 792.618011475 2.31160211563 ; +1355 509.881813049 2.83724832535 ; +1356 463.541244507 4.37813901901 ; +1357 738.423278809 3.80328655243 ; +1358 583.480758667 2.61241793633 ; +1359 590.937179565 0.814413189888 ; +1360 684.309143066 3.83803296089 ; +1361 482.091156006 2.06132650375 ; +1362 871.761688232 3.98899483681 ; +1363 703.63394165 1.75846171379 ; +1364 846.767303467 3.18275117874 ; +1365 650.071365356 4.49854803085 ; +1366 609.646865845 0.352417290211 ; +1367 707.737579346 1.45592224598 ; +1368 868.636535645 3.74828362465 ; +1369 640.594543457 1.72506511211 ; +1370 716.856994629 4.15873384476 ; +1371 484.439453125 1.73988473415 ; +1372 624.335861206 4.1317243576 ; +1373 589.365066528 1.58710837364 ; +1374 853.15435791 1.65855491161 ; +1375 433.30229187 2.11629629135 ; +1376 759.452453613 3.17383885384 ; +1377 671.179321289 2.11358690262 ; +1378 705.695129395 3.18428373337 ; +1379 725.670806885 0.4939930439 ; +1380 654.141342163 3.53781747818 ; +1381 409.815649033 4.71618890762 ; +1382 898.99810791 1.61664366722 ; +1383 493.032325745 0.943639099598 ; +1384 874.293334961 4.48298168182 ; +1385 447.604938507 0.962722361088 ; +1386 447.466770172 2.74047613144 ; +1387 818.044494629 0.740565359592 ; +1388 568.200439453 4.4490609169 ; +1389 436.351543427 4.60472106934 ; +1390 555.291809082 4.89525079727 ; +1391 848.594024658 0.200964763761 ; +1392 661.506774902 1.44528698921 ; +1393 494.015296936 1.15101563931 ; +1394 412.049273491 0.121569365263 ; +1395 721.633056641 1.87096238136 ; +1396 426.601041794 0.837270736694 ; +1397 600.934844971 1.12211883068 ; +1398 845.092193604 1.6479395628 ; +1399 592.06439209 0.263381570578 ; +1400 565.409011841 0.291720479727 ; +1401 694.606567383 4.52990818024 ; +1402 816.667175293 4.2561674118 ; +1403 741.088867188 1.80986368656 ; +1404 737.980010986 4.30399894714 ; +1405 631.409500122 2.99439001083 ; +1406 571.709121704 4.1538143158 ; +1407 715.884246826 0.665841162205 ; +1408 479.239486694 2.78120398521 ; +1409 769.422729492 3.87834811211 ; +1410 739.646087646 4.31916475296 ; +1411 620.184112549 1.34414613247 ; +1412 506.335449219 1.8000228405 ; +1413 698.494293213 2.93872499466 ; +1414 515.001426697 3.29019880295 ; +1415 736.967895508 4.19516324997 ; +1416 710.826629639 0.632645010948 ; +1417 686.543945312 4.44396400452 ; +1418 870.308197021 4.70202684402 ; +1419 596.293457031 1.04308509827 ; +1420 513.190429688 3.91588926315 ; +1421 835.091522217 0.838368058205 ; +1422 445.214862823 4.26218938828 ; +1423 861.464813232 3.39056634903 ; +1424 425.176956177 1.49116778374 ; +1425 605.697631836 1.60269701481 ; +1426 552.993774414 3.66572833061 ; +1427 889.476623535 1.33986401558 ; +1428 809.417572021 0.815461099148 ; +1429 445.547454834 0.16109251976 ; +1430 648.192596436 3.73170590401 ; +1431 778.10168457 2.55231547356 ; +1432 577.022247314 2.12865519524 ; +1433 530.640380859 1.72884762287 ; +1434 574.087615967 3.90808606148 ; +1435 720.170654297 1.08422720432 ; +1436 660.626373291 3.47400188446 ; +1437 654.87991333 2.66955137253 ; +1438 615.224761963 2.82795453072 ; +1439 843.062988281 0.602903068066 ; +1440 699.171325684 1.72325539589 ; +1441 675.209014893 4.38351631165 ; +1442 776.416259766 4.2806763649 ; +1443 432.420780182 3.9603869915 ; +1444 622.674850464 4.96282434464 ; +1445 418.69364357 1.84084165096 ; +1446 802.404541016 2.13372778893 ; +1447 556.373977661 1.77776396275 ; +1448 787.87399292 4.98520708084 ; +1449 537.917984009 4.87641096115 ; +1450 683.745788574 4.15367841721 ; +1451 487.542098999 3.20077228546 ; +1452 438.359127045 2.01871395111 ; +1453 752.503967285 0.346145004034 ; +1454 665.923400879 3.74937105179 ; +1455 468.247421265 0.34482640028 ; +1456 449.722610474 1.87930834293 ; +1457 453.55613327 1.17975735664 ; +1458 718.337371826 2.96179103851 ; +1459 782.538024902 3.17235445976 ; +1460 675.800170898 3.74142670631 ; +1461 615.753173828 1.63740575314 ; +1462 887.776184082 0.55032491684 ; +1463 831.095977783 4.30293655396 ; +1464 845.537658691 1.51944887638 ; +1465 637.856063843 1.47053289413 ; +1466 424.664495468 0.362130612135 ; +1467 532.921661377 0.144047185779 ; +1468 500.112289429 0.873352050781 ; +1469 742.840942383 1.27931594849 ; +1470 546.233428955 2.45515727997 ; +1471 782.9503479 2.46835803986 ; +1472 469.564559937 1.71704614162 ; +1473 739.610443115 3.32788348198 ; +1474 573.657272339 1.57987260818 ; +1475 692.11138916 0.160602942109 ; +1476 825.38293457 4.10889720917 ; +1477 723.763366699 4.90912055969 ; +1478 659.051361084 3.76729273796 ; +1479 589.003890991 0.886062383652 ; +1480 605.05279541 3.22579646111 ; +1481 496.257919312 3.06978106499 ; +1482 780.89352417 1.7770409584 ; +1483 572.802780151 2.96529221535 ; +1484 667.028564453 4.49384498596 ; +1485 705.452178955 2.35333251953 ; +1486 646.218643188 1.96756923199 ; +1487 793.815551758 3.58351445198 ; +1488 712.716400146 3.24893641472 ; +1489 887.560760498 4.3377532959 ; +1490 862.291015625 2.25516676903 ; +1491 658.821777344 0.175779029727 ; +1492 831.821655273 1.26653146744 ; +1493 559.601867676 4.28880643845 ; +1494 597.31628418 2.94901180267 ; +1495 804.464599609 3.37171697617 ; +1496 744.5859375 4.56127309799 ; +1497 531.627365112 2.61077880859 ; +1498 836.039550781 0.169393509626 ; +1499 599.685836792 1.2006598711 ; +1500 848.987579346 1.34626805782 ; +1501 572.764968872 1.6083240509 ; +1502 510.186645508 4.07089185715 ; +1503 848.486694336 2.16474461555 ; +1504 686.309143066 4.97804880142 ; +1505 507.187934875 0.077873647213 ; +1506 782.243621826 3.68649530411 ; +1507 792.739501953 2.73537373543 ; +1508 742.613433838 3.04210186005 ; +1509 760.618103027 4.08856248856 ; +1510 546.646652222 1.9042057991 ; +1511 798.859436035 1.30605328083 ; +1512 483.754806519 1.67085158825 ; +1513 600.180358887 4.31490135193 ; +1514 454.626514435 1.07875525951 ; +1515 463.91463089 2.13317656517 ; +1516 630.005783081 2.07482814789 ; +1517 563.912399292 3.75655627251 ; +1518 543.861694336 3.83551359177 ; +1519 747.747558594 0.931557357311 ; +1520 568.465255737 3.95449209213 ; +1521 714.95703125 4.82991552353 ; +1522 539.311401367 4.06751918793 ; +1523 679.491363525 4.11553001404 ; +1524 871.401092529 3.38671731949 ; +1525 456.221004486 4.06486940384 ; +1526 726.189422607 2.65877175331 ; +1527 498.005615234 1.80480659008 ; +1528 738.542999268 3.92476439476 ; +1529 751.50567627 2.56170153618 ; +1530 851.879486084 2.39029145241 ; +1531 762.675292969 4.84065103531 ; +1532 582.500915527 2.93128633499 ; +1533 513.268737793 2.07769012451 ; +1534 873.768035889 1.19883644581 ; +1535 784.525726318 2.24452614784 ; +1536 775.227539062 4.49776983261 ; +1537 801.774475098 1.23927342892 ; +1538 746.740234375 1.63396370411 ; +1539 602.825378418 3.86241912842 ; +1540 467.734321594 4.10805892944 ; +1541 815.181243896 4.51339817047 ; +1542 568.768035889 4.84635829926 ; +1543 674.38168335 0.332100957632 ; +1544 562.071136475 4.29702377319 ; +1545 408.431859016 2.14259552956 ; +1546 460.488986969 1.38475680351 ; +1547 760.774841309 0.426486253738 ; +1548 695.414886475 0.382882386446 ; +1549 410.455373764 2.23477172852 ; +1550 880.811401367 4.97690582275 ; +1551 585.618637085 1.92353510857 ; +1552 785.511688232 2.95009016991 ; +1553 616.773910522 3.19314169884 ; +1554 613.217376709 0.446010947227 ; +1555 510.575088501 4.35580348969 ; +1556 699.070953369 4.85668611526 ; +1557 532.255187988 3.13168072701 ; +1558 815.81048584 0.271165370941 ; +1559 647.654800415 3.34320640564 ; +1560 826.974914551 1.67508780956 ; +1561 720.035858154 3.43115353584 ; +1562 639.768356323 2.8711476326 ; +1563 438.120277405 1.87538766861 ; +1564 864.058441162 4.30332899094 ; +1565 505.656715393 2.72454738617 ; +1566 546.559280396 2.21755433083 ; +1567 443.687644958 2.58263492584 ; +1568 534.598571777 1.98381328583 ; +1569 595.110778809 2.26989793777 ; +1570 417.317874908 0.615418493748 ; +1571 733.833953857 2.47464227676 ; +1572 531.289016724 0.74492764473 ; +1573 899.939239502 4.79069709778 ; +1574 624.38117981 1.74732971191 ; +1575 636.915908813 3.45797681808 ; +1576 721.541442871 1.47426366806 ; +1577 694.846313477 4.82099628448 ; +1578 548.456741333 1.1274664402 ; +1579 832.804656982 1.48013007641 ; +1580 554.611968994 0.633625328541 ; +1581 834.029876709 2.40720582008 ; +1582 690.854187012 3.86898159981 ; +1583 497.221298218 4.9834690094 ; +1584 616.6043396 4.69380950928 ; +1585 785.353973389 1.44550383091 ; +1586 858.285827637 4.09912919998 ; +1587 806.165496826 4.23897171021 ; +1588 839.931152344 4.23464679718 ; +1589 571.21812439 1.63108992577 ; +1590 772.848114014 4.58360528946 ; +1591 565.786880493 3.80415487289 ; +1592 543.133834839 1.50650548935 ; +1593 883.750488281 3.94970631599 ; +1594 671.539093018 2.57369804382 ; +1595 514.715927124 0.307198345661 ; +1596 708.2840271 3.30110478401 ; +1597 566.845153809 1.66610527039 ; +1598 623.161315918 1.72462999821 ; +1599 485.58454895 4.19562673569 ; +1600 489.949516296 2.81611943245 ; +1601 451.973796844 0.236795112491 ; +1602 881.559814453 0.761608183384 ; +1603 434.882236481 2.65737462044 ; +1604 649.687850952 0.0407273210585 ; +1605 850.407714844 0.0309254396707 ; +1606 876.385650635 1.14394044876 ; +1607 520.695121765 0.230033621192 ; +1608 517.511222839 0.1125228405 ; +1609 517.145935059 3.71856927872 ; +1610 699.237030029 2.76861000061 ; +1611 603.249679565 0.174730494618 ; +1612 569.534606934 3.68283605576 ; +1613 642.387252808 3.02725076675 ; +1614 800.166473389 0.980381429195 ; +1615 627.097763062 3.32280302048 ; +1616 534.994506836 3.52669620514 ; +1617 718.332702637 2.1833024025 ; +1618 876.159362793 3.11095571518 ; +1619 482.937965393 4.38432121277 ; +1620 628.726760864 2.10943078995 ; +1621 720.437530518 0.936836361885 ; +1622 440.860061646 2.35128855705 ; +1623 710.884735107 0.396471172571 ; +1624 749.072662354 3.64169502258 ; +1625 496.841392517 1.13289642334 ; +1626 459.063415527 1.7892665863 ; +1627 620.375686646 3.54347276688 ; +1628 414.671104431 0.772650897503 ; +1629 494.420387268 4.23455810547 ; +1630 422.399717331 4.72067451477 ; +1631 437.646579742 2.26102018356 ; +1632 496.767501831 3.71487474442 ; +1633 489.756530762 0.38059297204 ; +1634 562.593521118 2.09554314613 ; +1635 879.535583496 0.550549566746 ; +1636 708.659606934 1.42038154602 ; +1637 635.293670654 0.809342086315 ; +1638 661.306915283 2.85599732399 ; +1639 474.562217712 1.67316579819 ; +1640 489.780227661 4.36437129974 ; +1641 599.085586548 0.316646963358 ; +1642 588.55078125 4.72973680496 ; +1643 669.162078857 3.07092690468 ; +1644 707.111694336 1.26584112644 ; +1645 899.096099854 3.08348107338 ; +1646 806.733184814 4.65364408493 ; +1647 779.350280762 2.40584182739 ; +1648 898.326721191 3.77612996101 ; +1649 441.625301361 0.964284360409 ; +1650 572.736251831 1.78164553642 ; +1651 811.716247559 2.15658783913 ; +1652 477.550743103 3.95408773422 ; +1653 535.369918823 1.62233734131 ; +1654 562.369232178 4.39846611023 ; +1655 401.965164781 0.285265803337 ; +1656 846.241363525 4.78711938858 ; +1657 611.412979126 2.18253707886 ; +1658 590.294754028 2.84041404724 ; +1659 784.106628418 1.80407238007 ; +1660 504.387191772 4.35588550568 ; +1661 837.038116455 2.99566888809 ; +1662 720.677490234 1.27018690109 ; +1663 703.055206299 4.49132680893 ; +1664 473.671737671 2.0098195076 ; +1665 803.66519165 4.01224851608 ; +1666 786.408905029 3.74630355835 ; +1667 812.372314453 2.41565203667 ; +1668 886.553649902 0.073969759047 ; +1669 720.975646973 1.37808561325 ; +1670 548.456039429 1.00838816166 ; +1671 698.059997559 4.94515275955 ; +1672 718.436218262 4.5801076889 ; +1673 687.62789917 1.62337017059 ; +1674 798.1875 3.37416672707 ; +1675 861.980102539 4.99936008453 ; +1676 824.594238281 1.55606818199 ; +1677 683.887817383 3.0267264843 ; +1678 419.441667557 2.56125020981 ; +1679 593.375198364 0.569845557213 ; +1680 639.466796875 2.18554544449 ; +1681 646.536254883 0.351468831301 ; +1682 613.721389771 0.154366418719 ; +1683 843.651763916 4.55834197998 ; +1684 605.43270874 2.07629084587 ; +1685 522.261062622 3.4182703495 ; +1686 487.221702576 4.35139942169 ; +1687 797.458282471 0.82132434845 ; +1688 799.908966064 2.70529437065 ; +1689 688.290771484 3.0322842598 ; +1690 760.373809814 3.02798557281 ; +1691 535.324066162 3.91762900352 ; +1692 759.046600342 4.9610042572 ; +1693 860.402893066 4.91455888748 ; +1694 799.663696289 1.47946381569 ; +1695 434.928535461 0.439329326153 ; +1696 780.807403564 2.30271887779 ; +1697 579.650222778 3.81426548958 ; +1698 535.680252075 3.78195786476 ; +1699 736.65512085 1.62876713276 ; +1700 868.88684082 0.815722942352 ; +1701 885.561553955 3.33634233475 ; +1702 790.617034912 1.00887584686 ; +1703 517.723480225 0.786053061485 ; +1704 519.435050964 3.44977283478 ; +1705 433.169322968 4.76880311966 ; +1706 827.888244629 0.180790066719 ; +1707 753.859802246 3.21620798111 ; +1708 880.671844482 1.51669871807 ; +1709 515.551513672 0.743803143501 ; +1710 509.941513062 2.87073230743 ; +1711 739.518981934 2.95724630356 ; +1712 643.985992432 1.72932112217 ; +1713 870.127197266 4.2808508873 ; +1714 726.504425049 0.599659800529 ; +1715 748.261627197 2.33639574051 ; +1716 680.406646729 2.94469618797 ; +1717 550.903427124 2.33973836899 ; +1718 798.119689941 1.98034274578 ; +1719 761.937744141 0.881175518036 ; +1720 891.76348877 0.692662656307 ; +1721 558.144210815 4.29832601547 ; +1722 596.798187256 0.871223211288 ; +1723 664.851898193 3.65788388252 ; +1724 705.480194092 2.06054162979 ; +1725 552.255401611 4.56662988663 ; +1726 535.325164795 4.10229206085 ; +1727 622.457717896 3.46858167648 ; +1728 545.389160156 0.557525932789 ; +1729 433.86384964 1.49718344212 ; +1730 716.227996826 3.43802499771 ; +1731 688.695373535 1.03423726559 ; +1732 642.580123901 0.44160681963 ; +1733 608.575042725 0.209236770868 ; +1734 564.261306763 2.39848423004 ; +1735 532.757232666 2.50800251961 ; +1736 599.820999146 3.91790962219 ; +1737 730.831878662 2.91276431084 ; +1738 882.632751465 1.0938346386 ; +1739 807.885742188 3.36137032509 ; +1740 854.960845947 0.273628294468 ; +1741 787.095855713 4.20078516006 ; +1742 660.134429932 0.794593453407 ; +1743 873.191925049 4.36876535416 ; +1744 484.208068848 2.85081243515 ; +1745 760.483093262 1.39784383774 ; +1746 756.112548828 1.83975207806 ; +1747 471.38633728 2.9014775753 ; +1748 413.21985817 1.86162245274 ; +1749 728.845245361 4.02083349228 ; +1750 714.731536865 1.92806148529 ; +1751 893.118255615 3.38898038864 ; +1752 759.002929688 2.62750077248 ; +1753 440.809410095 3.83752942085 ; +1754 635.677139282 0.258827716112 ; +1755 411.771629333 3.45782089233 ; +1756 459.675060272 4.58803987503 ; +1757 518.568336487 2.7801053524 ; +1758 423.076564789 3.47851681709 ; +1759 743.468414307 1.7401894331 ; +1760 636.520858765 2.0641078949 ; +1761 546.2681427 3.28619384766 ; +1762 505.855964661 1.21365952492 ; +1763 697.643493652 4.94728040695 ; +1764 793.787811279 3.91919398308 ; +1765 889.387542725 1.36704134941 ; +1766 486.323448181 3.38343667984 ; +1767 442.183853149 4.8400182724 ; +1768 518.858215332 1.5003105402 ; +1769 471.955825806 3.61589956284 ; +1770 642.367553711 4.71665716171 ; +1771 685.959106445 1.15106630325 ; +1772 497.192344666 0.117541454732 ; +1773 451.933235168 3.4188144207 ; +1774 401.376849771 1.40715134144 ; +1775 899.31463623 4.81466674805 ; +1776 410.691307068 1.88808906078 ; +1777 711.165405273 2.57049894333 ; +1778 637.409362793 1.39162480831 ; +1779 803.734222412 0.613941073418 ; +1780 750.816558838 1.74184560776 ; +1781 419.953453064 3.57688331604 ; +1782 567.896148682 3.30737686157 ; +1783 608.307128906 0.180651694536 ; +1784 521.310966492 3.73552799225 ; +1785 701.930786133 0.509749650955 ; +1786 636.242660522 0.305973559618 ; +1787 649.737609863 3.4030854702 ; +1788 465.764160156 2.98361086845 ; +1789 455.006515503 4.94560670853 ; +1790 481.315498352 1.6967895031 ; +1791 694.211517334 3.13271307945 ; +1792 551.037857056 4.93583583832 ; +1793 559.467926025 1.77645111084 ; +1794 581.401367188 3.12985086441 ; +1795 740.642181396 1.73248171806 ; +1796 682.036621094 1.89884746075 ; +1797 792.981964111 3.48179984093 ; +1798 761.254394531 1.03104579449 ; +1799 778.801422119 0.156701266766 ; +1800 767.824615479 0.289603382349 ; +1801 636.402572632 2.18376040459 ; +1802 646.16847229 3.53688693047 ; +1803 845.970092773 4.19636583328 ; +1804 732.530426025 3.38928747177 ; +1805 775.570709229 2.17149782181 ; +1806 536.692901611 3.97735357285 ; +1807 638.031677246 0.985375761986 ; +1808 521.097938538 2.93121910095 ; +1809 899.997680664 4.61361217499 ; +1810 497.939933777 0.76524323225 ; +1811 544.298675537 2.28148889542 ; +1812 898.497070313 2.40729737282 ; +1813 844.892791748 3.13644385338 ; +1814 821.172729492 1.50243425369 ; +1815 541.37109375 0.240862429142 ; +1816 717.490325928 0.599077880383 ; +1817 770.145477295 0.354908108711 ; +1818 894.054656982 0.769322216511 ; +1819 899.873352051 3.71744084358 ; +1820 803.11907959 2.22314214706 ; +1821 835.025512695 4.74061536789 ; +1822 452.625053406 4.69334316254 ; +1823 502.083129883 2.11175227165 ; +1824 622.035217285 2.4605987072 ; +1825 428.278072357 2.69570279121 ; +1826 567.69581604 4.63735771179 ; +1827 407.625595093 1.63390338421 ; +1828 501.430847168 2.48427605629 ; +1829 722.982635498 3.6902179718 ; +1830 549.236953735 2.25601363182 ; +1831 582.242675781 4.52796411514 ; +1832 549.795883179 1.19396734238 ; +1833 600.906204224 1.30894076824 ; +1834 836.890289307 3.15281629562 ; +1835 838.276153564 1.07620918751 ; +1836 684.929412842 3.0879714489 ; +1837 853.951507568 0.636800646782 ; +1838 670.913269043 2.39602184296 ; +1839 893.914886475 2.27683138847 ; +1840 570.46862793 0.665754973888 ; +1841 834.369445801 4.47892951965 ; +1842 637.106216431 0.445678412914 ; +1843 451.697975159 3.8789794445 ; +1844 800.815643311 0.0907301828265 ; +1845 890.215179443 0.47151979804 ; +1846 883.288909912 1.3711732626 ; +1847 430.962213516 3.81967949867 ; +1848 635.372390747 4.04087591171 ; +1849 400.152673796 0.659886419773 ; +1850 471.140655518 1.61158812046 ; +1851 496.178016663 4.63910531998 ; +1852 844.145843506 2.59572863579 ; +1853 540.963668823 1.76451408863 ; +1854 518.981185913 2.16885185242 ; +1855 589.119873047 0.377204567194 ; +1856 867.732025146 1.72243058681 ; +1857 789.037719727 0.57235789299 ; +1858 861.972991943 3.80626916885 ; +1859 596.782897949 3.30272603035 ; +1860 791.951690674 0.325219333172 ; +1861 496.125686646 0.844731450081 ; +1862 640.198883057 0.229257807136 ; +1863 713.614624023 4.21134233475 ; +1864 403.652283192 3.83928084373 ; +1865 579.182449341 0.195412054658 ; +1866 829.054473877 1.19048643112 ; +1867 750.433013916 2.2774116993 ; +1868 545.771209717 4.76889419556 ; +1869 480.60811615 2.80707931519 ; +1870 758.314422607 1.9097007513 ; +1871 534.159088135 3.11752295494 ; +1872 520.670013428 1.01032924652 ; +1873 460.356807709 4.16898155212 ; +1874 707.308074951 4.27100992203 ; +1875 686.267364502 2.9581091404 ; +1876 593.742660522 2.3280775547 ; +1877 700.010620117 2.78522610664 ; +1878 529.562652588 0.596413969994 ; +1879 792.969207764 1.3379226923 ; +1880 546.623809814 3.06513690948 ; +1881 475.73764801 4.22735691071 ; +1882 818.833526611 3.35788369179 ; +1883 495.213417053 2.51930952072 ; +1884 603.669967651 0.812800228596 ; +1885 473.290046692 2.85910534859 ; +1886 698.706726074 3.64359974861 ; +1887 698.1746521 4.22071790695 ; +1888 660.278015137 4.92814207077 ; +1889 628.61932373 4.05239248276 ; +1890 756.188232422 4.55944156647 ; +1891 453.097618103 4.1172952652 ; +1892 837.935516357 3.82271790504 ; +1893 742.164398193 2.57766652107 ; +1894 684.543457031 3.22220134735 ; +1895 453.991714478 4.38788938522 ; +1896 625.748733521 1.59178984165 ; +1897 721.214691162 1.55796098709 ; +1898 865.04864502 0.728058516979 ; +1899 547.938308716 3.99297571182 ; +1900 894.06439209 2.40573763847 ; +1901 723.485626221 3.23425889015 ; +1902 718.72744751 3.52481269836 ; +1903 552.652450562 1.29941987991 ; +1904 834.990020752 3.77883958817 ; +1905 495.844352722 3.5611345768 ; +1906 598.958786011 4.00481700897 ; +1907 796.537078857 0.988974273205 ; +1908 569.038253784 0.262074738741 ; +1909 869.001068115 0.0123197324574 ; +1910 605.775115967 4.62667560577 ; +1911 453.62537384 2.8164730072 ; +1912 545.905212402 2.29115009308 ; +1913 636.053222656 3.46697306633 ; +1914 841.378570557 2.49949121475 ; +1915 795.045440674 0.291387945414 ; +1916 635.702072144 4.44926118851 ; +1917 773.793243408 3.43745708466 ; +1918 734.363555908 1.48613119125 ; +1919 640.80229187 1.64374196529 ; +1920 537.179489136 0.756612062454 ; +1921 537.849334717 3.34002947807 ; +1922 487.622322083 1.68455016613 ; +1923 623.496032715 2.98213744164 ; +1924 478.457618713 1.37262904644 ; +1925 877.778717041 0.272085607052 ; +1926 694.290130615 1.34706807137 ; +1927 417.339120865 4.18604278564 ; +1928 882.342407227 2.29078745842 ; +1929 526.257759094 0.141652226448 ; +1930 474.897102356 2.95595264435 ; +1931 469.35887146 2.14656448364 ; +1932 630.907409668 3.61079001427 ; +1933 554.684310913 2.79412031174 ; +1934 478.244911194 0.622752606869 ; +1935 560.377288818 4.61096382141 ; +1936 547.154174805 2.20247387886 ; +1937 598.014266968 0.259752184153 ; +1938 465.485931396 1.22097635269 ; +1939 495.053184509 0.589438199997 ; +1940 568.841094971 2.12557935715 ; +1941 861.421295166 1.08038544655 ; +1942 703.844329834 2.11799812317 ; +1943 619.450393677 3.02842855453 ; +1944 779.674377441 1.87717616558 ; +1945 870.029907227 2.92847418785 ; +1946 786.818664551 2.61749196053 ; +1947 619.022628784 1.13438296318 ; +1948 457.494842529 3.15880060196 ; +1949 896.393310547 3.82586526871 ; +1950 531.788284302 4.65714550018 ; +1951 664.86605835 1.04183506966 ; +1952 412.275954247 3.21970868111 ; +1953 764.598846436 3.13098216057 ; +1954 641.620300293 4.1276140213 ; +1955 681.165893555 0.550281643867 ; +1956 758.345977783 2.2078397274 ; +1957 616.265228271 2.69643592834 ; +1958 800.000701904 3.11936759949 ; +1959 621.434463501 1.49237406254 ; +1960 633.18119812 0.765905022621 ; +1961 656.550994873 3.52448630333 ; +1962 504.466163635 2.6287817955 ; +1963 593.604873657 4.17368602753 ; +1964 613.850662231 1.88345897198 ; +1965 429.382974625 3.39685773849 ; +1966 498.734870911 4.37040567398 ; +1967 741.273590088 2.85550522804 ; +1968 647.780654907 4.49608230591 ; +1969 465.740890503 4.07175683975 ; +1970 801.741760254 0.737414062023 ; +1971 771.77154541 3.64851379395 ; +1972 457.20129776 3.82219076157 ; +1973 855.894622803 2.213306427 ; +1974 804.45010376 0.93305939436 ; +1975 592.876296997 1.72090363503 ; +1976 722.841674805 0.00343742081895 ; +1977 677.273162842 1.30220413208 ; +1978 514.540588379 0.837083160877 ; +1979 785.696502686 4.01643276215 ; +1980 818.319488525 1.96130216122 ; +1981 760.508666992 0.692720472813 ; +1982 655.312484741 0.372413098812 ; +1983 814.675872803 4.57835197449 ; +1984 736.487976074 3.53566265106 ; +1985 787.912811279 1.50946438313 ; +1986 856.782043457 1.36312568188 ; +1987 405.368251324 2.24196624756 ; +1988 472.712371826 0.768964290619 ; +1989 798.319061279 0.485029488802 ; +1990 589.0418396 2.26549243927 ; +1991 513.239929199 2.23602414131 ; +1992 485.811271667 2.30034041405 ; +1993 582.089492798 3.78460979462 ; +1994 693.604156494 1.05161798 ; +1995 854.362487793 4.70724821091 ; +1996 872.772186279 3.82625579834 ; +1997 688.091949463 4.61552667618 ; +1998 715.974700928 0.869463443756 ; +1999 707.270843506 3.01417970657 ; +2000 832.025360107 0.505253493786 ; +2001 579.620956421 3.89629220963 ; +2002 898.380004883 2.73157024384 ; +2003 850.340240479 3.68828582764 ; +2004 802.056762695 3.68456292152 ; +2005 545.05065918 3.66436052322 ; +2006 591.075469971 4.05591249466 ; +2007 672.027282715 4.62703609467 ; +2008 559.867660522 3.96023535728 ; +2009 867.570404053 4.56308984756 ; +2010 585.414016724 2.53709053993 ; +2011 487.917480469 1.29214823246 ; +2012 613.586166382 2.42897725105 ; +2013 781.877563477 2.1623108387 ; +2014 595.951156616 3.51285338402 ; +2015 452.806575775 0.201391577721 ; +2016 878.816986084 4.77425384521 ; +2017 488.610435486 2.75642752647 ; +2018 627.659790039 2.78461456299 ; +2019 501.842979431 1.74991381168 ; +2020 480.08518219 4.9171872139 ; +2021 716.843017578 1.80961024761 ; +2022 811.959411621 3.02440142632 ; +2023 511.301124573 1.38157904148 ; +2024 419.907836914 0.910328567028 ; +2025 889.24520874 2.44586110115 ; +2026 658.684173584 2.05022740364 ; +2027 717.336639404 4.77037668228 ; +2028 471.995811462 0.33652022481 ; +2029 489.54209137 4.34090614319 ; +2030 660.76260376 1.36934065819 ; +2031 850.961090088 3.03515410423 ; +2032 583.467788696 0.431952387094 ; +2033 882.390625 0.39362308383 ; +2034 462.308689117 2.22185373306 ; +2035 669.680450439 0.19602625072 ; +2036 861.317382813 3.61384654045 ; +2037 692.206573486 1.16216266155 ; +2038 646.933303833 2.08249759674 ; +2039 453.786037445 4.81971645355 ; +2040 897.410461426 4.7782664299 ; +2041 732.420623779 4.93854379654 ; +2042 610.478179932 0.0683699920774 ; +2043 809.441802979 4.88748168945 ; +2044 790.8956604 2.83220410347 ; +2045 485.231513977 4.86149501801 ; +2046 615.086746216 4.63090896606 ; +2047 568.808547974 1.65212988853 ; +2048 634.669723511 0.942255079746 ; +2049 548.218139648 1.02284157276 ; +2050 489.79535675 1.90563261509 ; +2051 696.835510254 4.14279031754 ; +2052 687.659393311 1.91556096077 ; +2053 883.421722412 3.69303488731 ; +2054 783.900787354 2.20529818535 ; +2055 844.773742676 3.12555241585 ; +2056 516.042449951 3.2563533783 ; +2057 853.065155029 1.66604888439 ; +2058 528.454421997 4.33688640594 ; +2059 405.580669403 2.94316267967 ; +2060 473.609596252 1.56498193741 ; +2061 665.072998047 0.817406892776 ; +2062 715.7527771 3.57427024841 ; +2063 676.242523193 3.08219075203 ; +2064 638.034545898 1.46963238716 ; +2065 411.162077904 1.01052987576 ; +2066 797.688964844 4.58642673492 ; +2067 807.905334473 1.65087151527 ; +2068 519.734313965 3.74660015106 ; +2069 810.790710449 1.59834218025 ; +2070 733.694976807 4.11723470688 ; +2071 736.1065979 4.44110250473 ; +2072 561.317352295 2.60900235176 ; +2073 850.017486572 4.44246816635 ; +2074 856.490142822 2.29957771301 ; +2075 800.212402344 3.69909906387 ; +2076 475.684501648 0.293791234493 ; +2077 674.930389404 2.55075788498 ; +2078 458.604751587 4.70082044601 ; +2079 569.42817688 0.794729828835 ; +2080 602.453674316 1.39073514938 ; +2081 808.713775635 2.52720737457 ; +2082 877.552246094 2.20709085464 ; +2083 857.577636719 0.0755879357457 ; +2084 440.650707245 2.16494989395 ; +2085 531.326797485 2.09657406807 ; +2086 612.211578369 1.40203070641 ; +2087 793.137664795 4.65419626236 ; +2088 707.600708008 3.45715785027 ; +2089 845.36831665 3.05834817886 ; +2090 566.202178955 3.60202455521 ; +2091 822.964660645 2.67341065407 ; +2092 601.578720093 4.3392829895 ; +2093 433.202468872 0.339260846376 ; +2094 595.728225708 1.04688894749 ; +2095 406.324514866 2.96127223969 ; +2096 410.238337517 0.757512450218 ; +2097 551.206985474 3.35713911057 ; +2098 744.156555176 2.39189600945 ; +2099 459.509113312 1.69716858864 ; +2100 831.238830566 3.31537222862 ; +2101 546.237930298 3.21071505547 ; +2102 648.757095337 3.6061630249 ; +2103 777.938140869 0.0661460086703 ; +2104 571.595245361 0.0151327624917 ; +2105 833.633911133 0.854892194271 ; +2106 717.328796387 3.45116376877 ; +2107 771.038879395 0.503410995007 ; +2108 482.918395996 1.09536778927 ; +2109 884.717834473 1.52883160114 ; +2110 407.2935853 0.832986235619 ; +2111 400.013814307 2.32177066803 ; +2112 600.023040771 2.87488245964 ; +2113 714.81362915 0.728650689125 ; +2114 543.221588135 1.25584614277 ; +2115 600.690597534 0.0717554911971 ; +2116 499.45098114 4.72630834579 ; +2117 406.093767643 4.17957782745 ; +2118 516.230895996 4.92865228653 ; +2119 485.93547821 3.17628026009 ; +2120 774.392120361 4.08695268631 ; +2121 841.818206787 1.38918268681 ; +2122 699.284851074 0.810869932175 ; +2123 729.052581787 3.86973834038 ; +2124 769.115844727 2.30449199677 ; +2125 559.935562134 0.369203418493 ; +2126 420.174793243 0.777573049068 ; +2127 767.045288086 4.30510044098 ; +2128 482.263641357 1.05188107491 ; +2129 796.552368164 3.55754947662 ; +2130 573.476226807 1.15079247952 ; +2131 537.005737305 1.55580222607 ; +2132 736.790802002 4.43449401855 ; +2133 454.200630188 4.5003862381 ; +2134 699.403533936 0.755471944809 ; +2135 621.676315308 2.13874030113 ; +2136 480.760040283 3.34080481529 ; +2137 790.540618896 3.16349506378 ; +2138 786.324432373 4.54876089096 ; +2139 502.607521057 0.246844395995 ; +2140 771.396881104 0.675433635712 ; +2141 601.341018677 4.38637256622 ; +2142 576.195465088 3.17393422127 ; +2143 831.23248291 2.24895119667 ; +2144 712.336700439 4.42951250076 ; +2145 582.059509277 3.74239301682 ; +2146 740.065216064 4.76674032211 ; +2147 860.963195801 4.08687353134 ; +2148 708.233825684 4.86181354523 ; +2149 649.842987061 1.11310255527 ; +2150 691.460784912 0.82101982832 ; +2151 788.084014893 0.280293464661 ; +2152 489.232528687 2.31225967407 ; +2153 614.965148926 4.19410657883 ; +2154 435.035186768 3.36441516876 ; +2155 472.34589386 4.17438173294 ; +2156 783.290252686 4.59263563156 ; +2157 743.441314697 2.18348145485 ; +2158 677.650695801 4.75539302826 ; +2159 788.962219238 2.88139128685 ; +2160 654.629989624 0.661984086037 ; +2161 496.665657043 1.59739196301 ; +2162 636.653900146 4.42212772369 ; +2163 669.664825439 2.56840109825 ; +2164 611.618270874 1.68297290802 ; +2165 472.677391052 4.88987398148 ; +2166 811.211517334 2.32304978371 ; +2167 749.781890869 2.84442090988 ; +2168 518.122146606 2.79076981544 ; +2169 847.144805908 1.63323998451 ; +2170 886.439331055 0.859020113945 ; +2171 655.150787354 3.19327163696 ; +2172 831.991760254 4.8616194725 ; +2173 823.949035645 3.12043070793 ; +2174 408.041963577 1.61283624172 ; +2175 593.934555054 4.5803103447 ; +2176 527.891059875 4.64983224869 ; +2177 872.977874756 3.3987724781 ; +2178 716.77746582 0.790004074574 ; +2179 659.851074219 3.17469739914 ; +2180 614.076171875 4.78363037109 ; +2181 747.513641357 1.62025237083 ; +2182 558.245452881 1.3134790659 ; +2183 464.24281311 2.29010105133 ; +2184 872.733093262 2.25339698792 ; +2185 684.261413574 0.819761157036 ; +2186 672.620300293 4.29663133621 ; +2187 748.445861816 3.29892134666 ; +2188 897.076263428 3.60825777054 ; +2189 798.794677734 0.429043531418 ; +2190 493.496452332 3.95011806488 ; +2191 863.495758057 4.73601818085 ; +2192 725.869812012 3.94158649445 ; +2193 524.428985596 2.78130888939 ; +2194 446.020835876 4.72255373001 ; +2195 595.938751221 1.42818260193 ; +2196 746.512695312 3.38974499702 ; +2197 544.578018188 4.22906064987 ; +2198 682.243804932 1.71722948551 ; +2199 547.628936768 1.99747395515 ; +2200 554.520248413 0.219043195248 ; +2201 545.890579224 4.8327703476 ; +2202 836.820953369 1.50119149685 ; +2203 452.759674072 2.31871151924 ; +2204 458.564117432 2.87176585197 ; +2205 476.648170471 2.25874209404 ; +2206 667.892425537 4.68238639832 ; +2207 586.992355347 2.80643725395 ; +2208 678.952453613 3.5422501564 ; +2209 859.556518555 2.66783261299 ; +2210 726.273162842 1.73289263248 ; +2211 872.678497314 3.07768344879 ; +2212 562.441741943 1.58396649361 ; +2213 572.503479004 2.65981698036 ; +2214 754.481567383 2.72042536736 ; +2215 618.805892944 4.70909070969 ; +2216 468.981719971 3.75837349892 ; +2217 598.618835449 1.8686825037 ; +2218 594.685424805 0.78047567606 ; +2219 645.503005981 1.69220042229 ; +2220 481.37940979 2.43820738792 ; +2221 795.251922607 4.99123954773 ; +2222 676.368896484 4.32233095169 ; +2223 441.434314728 3.86564397812 ; +2224 887.765014648 3.67148756981 ; +2225 569.184921265 4.91126394272 ; +2226 761.1456604 2.75259971619 ; +2227 694.149475098 2.70474123955 ; +2228 758.838989258 0.0704634487629 ; +2229 827.915252686 4.7178144455 ; +2230 630.976226807 0.177537605166 ; +2231 787.469573975 2.01189875603 ; +2232 798.542114258 2.97826886177 ; +2233 476.443084717 2.79015946388 ; +2234 821.389556885 2.9465880394 ; +2235 730.491149902 0.650115966797 ; +2236 549.946594238 1.52530276775 ; +2237 476.412254333 2.60910320282 ; +2238 519.814491272 2.22329497337 ; +2239 591.7578125 3.73894906044 ; +2240 451.811676025 2.98936867714 ; +2241 632.155563354 3.38843941689 ; +2242 850.103210449 3.84799647331 ; +2243 727.9269104 4.67982244492 ; +2244 778.09475708 1.38696932793 ; +2245 479.356788635 2.49618029594 ; +2246 730.176025391 2.68719696999 ; +2247 771.803161621 3.96473169327 ; +2248 424.536499023 3.84939813614 ; +2249 583.405807495 0.0146635919809 ; +2250 545.099822998 1.929515481 ; +2251 836.499023438 2.39049625397 ; +2252 607.184265137 1.45961391926 ; +2253 573.178619385 1.13285791874 ; +2254 894.292358398 0.721919834614 ; +2255 730.729187012 0.658554792404 ; +2256 733.014251709 4.71039009094 ; +2257 653.176589966 1.3905903101 ; +2258 565.345001221 4.5366063118 ; +2259 574.453262329 0.362067937851 ; +2260 427.563079834 2.52700734138 ; +2261 541.264892578 2.39259243011 ; +2262 630.290908813 4.99365234375 ; +2263 731.609954834 3.6869726181 ; +2264 594.734985352 4.11070680618 ; +2265 764.597381592 2.88503861427 ; +2266 784.121063232 4.23036432266 ; +2267 873.126312256 3.33984589577 ; +2268 679.102935791 3.83077526093 ; +2269 783.892456055 0.806882619858 ; +2270 527.575210571 1.56658256054 ; +2271 855.485229492 3.40637254715 ; +2272 490.323875427 0.734023749828 ; +2273 573.69342041 2.65509176254 ; +2274 812.915985107 3.79195690155 ; +2275 541.87348938 4.67693853378 ; +2276 430.602083206 3.29245710373 ; +2277 532.698287964 2.6023235321 ; +2278 625.051300049 4.37371397018 ; +2279 800.934570312 0.0757162719965 ; +2280 656.337585449 2.66398429871 ; +2281 758.401153564 1.48643088341 ; +2282 644.507415771 4.3641910553 ; +2283 795.715942383 2.98151779175 ; +2284 437.249195099 0.472350269556 ; +2285 779.121887207 4.01632642746 ; +2286 640.175689697 1.32996499538 ; +2287 672.164855957 2.74969220161 ; +2288 807.454498291 0.882421076298 ; +2289 485.121620178 1.39149856567 ; +2290 591.698318481 3.73868846893 ; +2291 513.625 1.95485424995 ; +2292 423.573863983 2.05932736397 ; +2293 511.631362915 1.88395929337 ; +2294 770.432006836 3.5078189373 ; +2295 491.276573181 0.854925513268 ; +2296 773.291229248 4.0607047081 ; +2297 726.895233154 1.28109419346 ; +2298 535.049514771 2.77198600769 ; +2299 777.246063232 3.75041127205 ; +2300 716.243499756 1.04851055145 ; +2301 631.618896484 3.18945550919 ; +2302 417.730430603 4.95364570618 ; +2303 492.235023499 1.94097518921 ; +2304 596.892440796 1.714651227 ; +2305 714.301330566 4.62594938278 ; +2306 732.911315918 2.4091053009 ; +2307 883.578491211 0.0411332063377 ; +2308 532.581481934 2.97089362144 ; +2309 580.88684082 1.65167951584 ; +2310 877.793273926 2.72040867805 ; +2311 590.916625977 2.36001014709 ; +2312 869.416046143 4.76092243195 ; +2313 582.568313599 4.25807762146 ; +2314 451.195549011 4.43628978729 ; +2315 472.760818481 3.91085362434 ; +2316 871.726257324 3.03578877449 ; +2317 650.241027832 3.01408076286 ; +2318 665.832397461 3.45594143867 ; +2319 800.604125977 4.5407781601 ; +2320 586.093582153 1.74835348129 ; +2321 857.914916992 1.76565885544 ; +2322 442.878845215 1.64811003208 ; +2323 878.435150146 0.597752094269 ; +2324 541.950775146 2.66824173927 ; +2325 414.207120895 2.79098153114 ; +2326 702.696777344 4.25039339066 ; +2327 536.226654053 0.613952934742 ; +2328 770.746429443 1.35162067413 ; +2329 568.906417847 3.10249257088 ; +2330 759.66619873 4.10305690765 ; +2331 407.422327518 2.47066664696 ; +2332 849.608428955 0.690123140812 ; +2333 789.971130371 2.44766426086 ; +2334 689.496520996 0.684768080711 ; +2335 789.791259766 2.2185087204 ; +2336 547.670715332 4.01792287827 ; +2337 822.961151123 2.08318519592 ; +2338 609.349441528 0.363909810781 ; +2339 523.232566833 1.69805133343 ; +2340 815.024536133 3.1771569252 ; +2341 748.062225342 3.82282614708 ; +2342 423.763599396 3.94833850861 ; +2343 872.636993408 1.10556232929 ; +2344 518.585006714 0.58268904686 ; +2345 725.501068115 1.96636843681 ; +2346 775.367523193 3.02407050133 ; +2347 455.503692627 3.50595116615 ; +2348 852.346801758 0.932641863823 ; +2349 891.113128662 1.39009833336 ; +2350 738.219085693 4.48289632797 ; +2351 803.779724121 3.26339530945 ; +2352 688.460784912 1.60573244095 ; +2353 654.522583008 2.61089372635 ; +2354 529.288269043 4.48004198074 ; +2355 506.301483154 1.09123432636 ; +2356 437.613780975 1.74855613708 ; +2357 698.428527832 1.88421308994 ; +2358 697.039550781 3.44075798988 ; +2359 781.784088135 1.45533561707 ; +2360 882.635314941 1.52358055115 ; +2361 581.880447388 3.64961194992 ; +2362 802.835235596 4.52263450623 ; +2363 591.987976074 2.42066168785 ; +2364 806.29473877 0.960237920284 ; +2365 771.883514404 2.46784043312 ; +2366 599.507095337 1.15796744823 ; +2367 595.942016602 1.97622418404 ; +2368 839.874145508 4.65243196487 ; +2369 742.126800537 1.25486040115 ; +2370 443.946071625 1.01647996902 ; +2371 797.808807373 4.72829294205 ; +2372 741.524047852 4.95201921463 ; +2373 759.035980225 3.18113183975 ; +2374 428.024942398 0.152185618877 ; +2375 678.363494873 4.55433130264 ; +2376 865.113037109 1.55270981789 ; +2377 539.416397095 1.71410346031 ; +2378 793.81072998 2.77180242538 ; +2379 468.546691895 0.642944991589 ; +2380 497.717521667 3.38372516632 ; +2381 427.0900383 3.02279615402 ; +2382 813.410766602 1.94904768467 ; +2383 664.451416016 1.348564744 ; +2384 432.698978424 0.717934608459 ; +2385 532.671951294 3.17553329468 ; +2386 518.909454346 0.113347321749 ; +2387 402.847664833 3.60705494881 ; +2388 777.360931396 3.05293798447 ; +2389 472.853317261 4.45687961578 ; +2390 577.580764771 1.00161075592 ; +2391 807.170837402 3.20762300491 ; +2392 452.247486115 1.2350281477 ; +2393 611.936355591 0.145957946777 ; +2394 711.518127441 1.85250663757 ; +2395 408.105225563 2.2453892231 ; +2396 725.911621094 0.968805193901 ; +2397 670.888580322 3.24405455589 ; +2398 682.716125488 1.09735369682 ; +2399 722.319976807 2.31863546371 ; +2400 830.575561523 1.83958172798 ; +2401 685.011627197 1.90941798687 ; +2402 558.875411987 2.19185042381 ; +2403 742.861083984 4.66496419907 ; +2404 805.179595947 3.53951215744 ; +2405 758.332275391 4.91142654419 ; +2406 534.485519409 2.98279762268 ; +2407 587.829803467 3.5565662384 ; +2408 420.989236832 2.66108441353 ; +2409 884.658843994 1.61450445652 ; +2410 897.598266602 1.34490931034 ; +2411 789.276947021 0.776925504208 ; +2412 678.737762451 2.46073102951 ; +2413 650.777832031 3.23118305206 ; +2414 549.203155518 1.57661318779 ; +2415 713.801605225 0.635780513287 ; +2416 456.347522736 0.328958243132 ; +2417 780.152313232 2.20706939697 ; +2418 821.548950195 4.73351097107 ; +2419 511.549980164 3.20612668991 ; +2420 437.349380493 2.31043148041 ; +2421 542.320831299 4.86478996277 ; +2422 652.133422852 1.06673157215 ; +2423 755.786987305 2.12446975708 ; +2424 496.397514343 1.53124034405 ; +2425 455.565258026 3.85362434387 ; +2426 686.775054932 3.28740859032 ; +2427 547.630493164 2.25687909126 ; +2428 536.519058228 4.75744724274 ; +2429 741.752838135 3.40285420418 ; +2430 577.044052124 0.794996023178 ; +2431 549.863723755 2.59808301926 ; +2432 498.167709351 4.04812431335 ; +2433 582.213394165 4.60513877869 ; +2434 757.152770996 1.66828000546 ; +2435 778.28314209 3.05277228355 ; +2436 694.590667725 1.8539942503 ; +2437 408.152795792 0.240456014872 ; +2438 534.428283691 3.3637201786 ; +2439 804.4402771 4.27926921844 ; +2440 567.875045776 4.76027059555 ; +2441 486.904014587 0.958499848843 ; +2442 850.706848145 0.304351866245 ; +2443 424.208446503 3.71356582642 ; +2444 790.11239624 1.19243824482 ; +2445 530.961334229 0.674015104771 ; +2446 717.241119385 3.7146191597 ; +2447 560.527130127 4.79606342316 ; +2448 644.303070068 0.017191151157 ; +2449 793.16696167 4.57439994812 ; +2450 593.727935791 4.85506248474 ; +2451 803.211975098 2.83749222755 ; +2452 873.36907959 4.14090013504 ; +2453 511.120033264 0.944868087769 ; +2454 439.867855072 0.59033870697 ; +2455 582.265258789 3.32340121269 ; +2456 540.600784302 0.772992432117 ; +2457 568.37890625 4.44456005096 ; +2458 872.110839844 2.67467260361 ; +2459 722.153045654 4.26470184326 ; +2460 584.264511108 4.33796072006 ; +2461 710.623168945 1.43622457981 ; +2462 762.69934082 3.8832449913 ; +2463 469.640785217 4.52638626099 ; +2464 897.858032227 0.00266680493951 ; +2465 882.099029541 1.3896728754 ; +2466 523.178512573 2.61351490021 ; +2467 434.728050232 1.74336612225 ; +2468 475.349105835 3.9243273735 ; +2469 517.251373291 1.43962144852 ; +2470 471.761817932 1.00952339172 ; +2471 605.995773315 1.71122193336 ; +2472 450.696918488 0.631214976311 ; +2473 783.065948486 1.89657628536 ; +2474 475.862121582 0.146889790893 ; +2475 777.684143066 2.38187170029 ; +2476 611.550949097 0.370386660099 ; +2477 408.859134674 3.95493388176 ; +2478 457.217723846 1.583568573 ; +2479 403.673702002 2.43913650513 ; +2480 857.054779053 2.19743537903 ; +2481 629.847503662 0.472842633724 ; +2482 606.646957397 1.15430879593 ; +2483 446.720649719 2.34020471573 ; +2484 582.396255493 0.34015199542 ; +2485 593.47227478 1.88512527943 ; +2486 730.240936279 3.59848618507 ; +2487 875.612731934 1.23677635193 ; +2488 549.978866577 1.94878101349 ; +2489 716.286102295 3.20725131035 ; +2490 827.331451416 1.59964048862 ; +2491 415.972403526 4.48187017441 ; +2492 579.52885437 3.41620349884 ; +2493 513.112037659 0.740587949753 ; +2494 606.146591187 2.05871868134 ; +2495 488.756210327 2.25636768341 ; +2496 677.242401123 1.13140022755 ; +2497 444.41576004 4.95676231384 ; +2498 730.130462646 0.030346782878 ; +2499 403.838006735 0.05381539464 ; + +[RESERVOIRS] +;ID Head Pattern +2500 761.453430176 ; +2501 748.217681885 ; +2502 794.597076416 ; +2503 793.379821777 ; +2504 835.015777588 ; + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status +P-V-1 0 1 737.035888672 6.24083590508 155 0 Open ; +P-V-2 1 2 236.444705963 13.5236063004 155 0 Open ; +P-V-3 2 3 313.267692566 12.8011894226 155 0 Open ; +P-V-4 3 4 430.061050415 7.72321128845 155 0 Open ; +P-V-5 4 5 351.007232666 14.5749559402 155 0 Open ; +P-V-6 5 6 614.380767822 8.94438791275 155 0 Open ; +P-V-7 6 7 566.693145752 11.240404129 155 0 Open ; +P-V-8 7 8 423.655319214 14.4979076385 155 0 Open ; +P-V-9 8 9 667.458679199 6.55713438988 155 0 Open ; +P-V-10 9 10 237.962623596 7.75636291504 155 0 Open ; +P-V-11 10 11 609.583740234 4.49027109146 155 0 Open ; +P-V-12 11 12 349.312286377 8.83402585983 155 0 Open ; +P-V-13 12 13 223.766641617 11.9189414978 155 0 Open ; +P-V-14 13 14 632.777587891 12.8670988083 155 0 Open ; +P-V-15 14 15 616.7315979 7.15639400482 155 0 Open ; +P-V-16 15 16 426.051055908 3.80641746521 155 0 Open ; +P-V-17 16 17 472.946960449 11.3860788345 155 0 Open ; +P-V-18 17 18 441.337799072 6.2862598896 155 0 Open ; +P-V-19 18 19 608.731170654 5.89686203003 155 0 Open ; +P-V-20 19 20 378.109817505 4.8320428133 155 0 Open ; +P-V-21 20 21 757.211730957 8.15604162216 155 0 Open ; +P-V-22 21 22 479.864074707 8.51226091385 155 0 Open ; +P-V-23 22 23 428.42980957 11.3944759369 155 0 Open ; +P-V-24 23 24 298.429740906 5.17292428017 155 0 Open ; +P-V-25 24 25 416.99168396 6.58698821068 155 0 Open ; +P-V-26 25 26 725.45501709 13.4525699615 155 0 Open ; +P-V-27 26 27 616.964660645 13.5011053085 155 0 Open ; +P-V-28 27 28 604.081787109 3.05466319621 155 0 Open ; +P-V-29 28 29 536.216918945 14.9666414261 155 0 Open ; +P-V-30 29 30 367.776672363 11.4542713165 155 0 Open ; +P-V-31 30 31 747.542785645 10.0316209793 155 0 Open ; +P-V-32 31 32 423.123168945 3.62044757605 155 0 Open ; +P-V-33 32 33 793.159912109 7.77042818069 155 0 Open ; +P-V-34 33 34 429.65222168 14.2975521088 155 0 Open ; +P-V-35 34 35 297.917449951 12.9736728668 155 0 Open ; +P-V-36 35 36 776.116516113 14.7992897034 155 0 Open ; +P-V-37 36 37 733.29309082 8.14637374878 155 0 Open ; +P-V-38 37 38 755.191162109 12.9673442841 155 0 Open ; +P-V-39 38 39 258.258239746 13.9258413315 155 0 Open ; +P-V-40 39 40 531.210144043 11.9827880859 155 0 Open ; +P-V-41 40 41 285.821266174 14.9604940414 155 0 Open ; +P-V-42 41 42 601.250671387 11.4004058838 155 0 Open ; +P-V-43 42 43 481.09085083 12.881652832 155 0 Open ; +P-V-44 43 44 247.609283447 10.3859701157 155 0 Open ; +P-V-45 44 45 600.260345459 14.5237588882 155 0 Open ; +P-V-46 45 46 790.69543457 7.37190771103 155 0 Open ; +P-V-47 46 47 332.57623291 11.1762199402 155 0 Open ; +P-V-48 47 48 487.251708984 7.78751420975 155 0 Open ; +P-V-49 48 49 387.76524353 10.4141950607 155 0 Open ; +P-V-51 50 51 318.87853241 14.8309593201 155 0 Open ; +P-V-52 51 52 346.955688477 8.68705940247 155 0 Open ; +P-V-53 52 53 320.579269409 10.5154900551 155 0 Open ; +P-V-54 53 54 242.285171509 8.73821973801 155 0 Open ; +P-V-55 54 55 713.182861328 4.30453431606 155 0 Open ; +P-V-56 55 56 265.425537109 11.1397247314 155 0 Open ; +P-V-57 56 57 417.77986145 7.52467632294 155 0 Open ; +P-V-58 57 58 312.130111694 14.4159326553 155 0 Open ; +P-V-59 58 59 779.117797852 3.66274124384 155 0 Open ; +P-V-60 59 60 334.607650757 10.0155434608 155 0 Open ; +P-V-61 60 61 712.075256348 3.9876819849 155 0 Open ; +P-V-62 61 62 398.551696777 12.1693086624 155 0 Open ; +P-V-63 62 63 429.006057739 13.0987119675 155 0 Open ; +P-V-64 63 64 252.94234848 3.040737167 155 0 Open ; +P-V-65 64 65 233.478305817 12.3974552155 155 0 Open ; +P-V-66 65 66 751.91973877 5.30097985268 155 0 Open ; +P-V-67 66 67 628.509307861 6.12202835083 155 0 Open ; +P-V-68 67 68 596.676086426 9.7069606781 155 0 Open ; +P-V-69 68 69 594.698028564 4.79985380173 155 0 Open ; +P-V-70 69 70 707.189941406 5.82779765129 155 0 Open ; +P-V-71 70 71 539.737030029 10.2020072937 155 0 Open ; +P-V-72 71 72 207.080958366 7.19342374802 155 0 Open ; +P-V-73 72 73 343.879943848 6.80539798737 155 0 Open ; +P-V-74 73 74 666.279998779 6.35949349403 155 0 Open ; +P-V-75 74 75 350.59538269 8.13180541992 155 0 Open ; +P-V-76 75 76 513.05291748 4.606377244 155 0 Open ; +P-V-77 76 77 719.111328125 5.09230422974 155 0 Open ; +P-V-78 77 78 467.960449219 3.2274133265 155 0 Open ; +P-V-79 78 79 506.789031982 11.0594406128 155 0 Open ; +P-V-80 79 80 751.061401367 4.78697991371 155 0 Open ; +P-V-81 80 81 688.64630127 12.5739784241 155 0 Open ; +P-V-82 81 82 293.002510071 4.86400020123 155 0 Open ; +P-V-83 82 83 612.568267822 11.6961965561 155 0 Open ; +P-V-84 83 84 648.812164307 14.7278871536 155 0 Open ; +P-V-85 84 85 730.282470703 4.1586984396 155 0 Open ; +P-V-86 85 86 712.24041748 11.4983968735 155 0 Open ; +P-V-87 86 87 628.20098877 10.4864673615 155 0 Open ; +P-V-88 87 88 453.141265869 13.9048843384 155 0 Open ; +P-V-89 88 89 319.822555542 8.15373086929 155 0 Open ; +P-V-90 89 90 337.803771973 4.35884547234 155 0 Open ; +P-V-91 90 91 305.843292236 13.1661586761 155 0 Open ; +P-V-92 91 92 531.28314209 12.5096273422 155 0 Open ; +P-V-93 92 93 215.381455421 13.3227710724 155 0 Open ; +P-V-94 93 94 741.562255859 3.72824925184 155 0 Open ; +P-V-95 94 95 784.249633789 12.6871585846 155 0 Open ; +P-V-96 95 96 604.008361816 14.371922493 155 0 Open ; +P-V-97 96 97 395.019760132 12.946346283 155 0 Open ; +P-V-98 97 98 611.93371582 14.4030590057 155 0 Open ; +P-V-99 98 99 761.034362793 9.0973610878 155 0 Open ; +P-V-101 100 101 717.466064453 4.05009126663 155 0 Open ; +P-V-102 101 102 644.276153564 13.986456871 155 0 Open ; +P-V-103 102 103 469.707366943 14.4367046356 155 0 Open ; +P-V-104 103 104 235.63722229 6.09676265717 155 0 Open ; +P-V-105 104 105 364.509552002 5.24098205566 155 0 Open ; +P-V-106 105 106 609.38873291 10.9343481064 155 0 Open ; +P-V-107 106 107 629.493774414 13.0409870148 155 0 Open ; +P-V-108 107 108 343.955200195 8.10141277313 155 0 Open ; +P-V-109 108 109 772.53112793 9.61283683777 155 0 Open ; +P-V-110 109 110 697.655181885 4.82374203205 155 0 Open ; +P-V-111 110 111 381.65335083 7.95676374435 155 0 Open ; +P-V-112 111 112 416.729110718 14.3290214539 155 0 Open ; +P-V-113 112 113 343.61050415 12.2341756821 155 0 Open ; +P-V-114 113 114 340.079620361 13.3648080826 155 0 Open ; +P-V-115 114 115 666.870697021 12.9176120758 155 0 Open ; +P-V-116 115 116 465.610748291 5.39802265167 155 0 Open ; +P-V-117 116 117 578.400421143 10.5264186859 155 0 Open ; +P-V-118 117 118 426.152267456 13.8235120773 155 0 Open ; +P-V-119 118 119 338.602249146 8.76205015182 155 0 Open ; +P-V-120 119 120 339.147872925 12.1661891937 155 0 Open ; +P-V-121 120 121 207.357065678 4.00398910046 155 0 Open ; +P-V-122 121 122 302.292610168 7.63971233368 155 0 Open ; +P-V-123 122 123 382.25201416 5.19779348373 155 0 Open ; +P-V-124 123 124 315.740829468 4.12210857868 155 0 Open ; +P-V-125 124 125 563.94921875 12.8942718506 155 0 Open ; +P-V-126 125 126 651.366027832 9.17863368988 155 0 Open ; +P-V-127 126 127 614.532562256 11.9773550034 155 0 Open ; +P-V-128 127 128 521.144592285 12.5509433746 155 0 Open ; +P-V-129 128 129 735.196594238 11.9879360199 155 0 Open ; +P-V-130 129 130 412.687423706 11.7515859604 155 0 Open ; +P-V-131 130 131 395.105575562 5.78930282593 155 0 Open ; +P-V-132 131 132 590.771728516 5.01084280014 155 0 Open ; +P-V-133 132 133 411.81362915 6.032361269 155 0 Open ; +P-V-134 133 134 245.020549774 4.2087250948 155 0 Open ; +P-V-135 134 135 752.151123047 11.0714855194 155 0 Open ; +P-V-136 135 136 673.317993164 8.11899518967 155 0 Open ; +P-V-137 136 137 547.802185059 9.22084999084 155 0 Open ; +P-V-138 137 138 691.2578125 14.3984632492 155 0 Open ; +P-V-139 138 139 498.674194336 7.34385347366 155 0 Open ; +P-V-140 139 140 757.330932617 12.2099905014 155 0 Open ; +P-V-141 140 141 416.00982666 12.5422964096 155 0 Open ; +P-V-142 141 142 669.33782959 14.2174491882 155 0 Open ; +P-V-143 142 143 783.578369141 3.05067918822 155 0 Open ; +P-V-144 143 144 788.255859375 3.31870681047 155 0 Open ; +P-V-145 144 145 425.290206909 12.0547885895 155 0 Open ; +P-V-146 145 146 791.829467773 4.56874644756 155 0 Open ; +P-V-147 146 147 296.016777039 10.0797262192 155 0 Open ; +P-V-148 147 148 648.389648438 4.70746040344 155 0 Open ; +P-V-149 148 149 464.344451904 11.7400188446 155 0 Open ; +P-V-151 150 151 274.543647766 4.10142111778 155 0 Open ; +P-V-152 151 152 579.261810303 12.062792778 155 0 Open ; +P-V-153 152 153 318.232299805 13.606010437 155 0 Open ; +P-V-154 153 154 561.477508545 10.0547690392 155 0 Open ; +P-V-155 154 155 675.099060059 6.80215215683 155 0 Open ; +P-V-156 155 156 338.519515991 4.95198655128 155 0 Open ; +P-V-157 156 157 751.866271973 11.3264074326 155 0 Open ; +P-V-158 157 158 697.068359375 11.5579128265 155 0 Open ; +P-V-159 158 159 242.616889954 12.2413473129 155 0 Open ; +P-V-160 159 160 366.870758057 6.93522191048 155 0 Open ; +P-V-161 160 161 563.611907959 7.5099978447 155 0 Open ; +P-V-162 161 162 576.540283203 9.25270318985 155 0 Open ; +P-V-163 162 163 459.06072998 11.6738986969 155 0 Open ; +P-V-164 163 164 510.882904053 7.17896318436 155 0 Open ; +P-V-165 164 165 792.098632812 11.0458631516 155 0 Open ; +P-V-166 165 166 741.698913574 13.6760177612 155 0 Open ; +P-V-167 166 167 591.655029297 13.9283905029 155 0 Open ; +P-V-168 167 168 273.523780823 9.28390789032 155 0 Open ; +P-V-169 168 169 281.786773682 14.8073225021 155 0 Open ; +P-V-170 169 170 283.700950623 10.2377142906 155 0 Open ; +P-V-171 170 171 213.296175003 8.37607955933 155 0 Open ; +P-V-172 171 172 588.638214111 7.85285949707 155 0 Open ; +P-V-173 172 173 700.632080078 9.47194719315 155 0 Open ; +P-V-174 173 174 501.079864502 11.986489296 155 0 Open ; +P-V-175 174 175 396.629302979 13.9734535217 155 0 Open ; +P-V-176 175 176 342.385040283 8.30853843689 155 0 Open ; +P-V-177 176 177 230.529525757 5.19508314133 155 0 Open ; +P-V-178 177 178 438.1640625 7.46913909912 155 0 Open ; +P-V-179 178 179 441.200210571 8.04284238815 155 0 Open ; +P-V-180 179 180 752.751525879 8.90897846222 155 0 Open ; +P-V-181 180 181 210.225217819 8.10489702225 155 0 Open ; +P-V-182 181 182 700.333618164 5.13764309883 155 0 Open ; +P-V-183 182 183 768.419616699 7.57657909393 155 0 Open ; +P-V-184 183 184 728.226135254 8.94127893448 155 0 Open ; +P-V-185 184 185 353.614044189 14.8232402802 155 0 Open ; +P-V-186 185 186 460.833374023 7.53477287292 155 0 Open ; +P-V-187 186 187 396.35736084 6.56365251541 155 0 Open ; +P-V-188 187 188 315.638465881 5.71479082108 155 0 Open ; +P-V-189 188 189 374.58807373 9.03693580627 155 0 Open ; +P-V-190 189 190 338.777069092 7.52424621582 155 0 Open ; +P-V-191 190 191 550.655151367 8.22566413879 155 0 Open ; +P-V-192 191 192 787.22265625 4.02447879314 155 0 Open ; +P-V-193 192 193 720.766723633 9.53260135651 155 0 Open ; +P-V-194 193 194 471.79510498 8.20958089828 155 0 Open ; +P-V-195 194 195 471.314605713 14.6923837662 155 0 Open ; +P-V-196 195 196 295.253456116 5.49684381485 155 0 Open ; +P-V-197 196 197 222.694524765 11.5376472473 155 0 Open ; +P-V-198 197 198 611.6328125 9.25966501236 155 0 Open ; +P-V-199 198 199 309.547233582 10.2092418671 155 0 Open ; +P-V-201 200 201 286.531028748 13.5409116745 155 0 Open ; +P-V-202 201 202 455.471008301 5.02873587608 155 0 Open ; +P-V-203 202 203 448.289733887 3.11395995319 155 0 Open ; +P-V-204 203 204 566.251373291 6.74650526047 155 0 Open ; +P-V-205 204 205 375.720581055 5.71544933319 155 0 Open ; +P-V-206 205 206 327.985954285 4.19847404957 155 0 Open ; +P-V-207 206 207 537.746276855 13.0370111465 155 0 Open ; +P-V-208 207 208 602.352233887 9.679459095 155 0 Open ; +P-V-209 208 209 283.808418274 10.3606972694 155 0 Open ; +P-V-210 209 210 362.045593262 5.00972628593 155 0 Open ; +P-V-211 210 211 673.593170166 4.60996282101 155 0 Open ; +P-V-212 211 212 732.359008789 6.1562268734 155 0 Open ; +P-V-213 212 213 535.390441895 13.1538562775 155 0 Open ; +P-V-214 213 214 392.95300293 14.220208168 155 0 Open ; +P-V-215 214 215 702.248321533 12.7498569489 155 0 Open ; +P-V-216 215 216 492.309570313 3.93778967857 155 0 Open ; +P-V-217 216 217 471.561431885 13.6665172577 155 0 Open ; +P-V-218 217 218 408.598739624 5.38285303116 155 0 Open ; +P-V-219 218 219 430.536270142 11.4634151459 155 0 Open ; +P-V-220 219 220 631.174713135 14.0708808899 155 0 Open ; +P-V-221 220 221 615.45199585 9.03679609299 155 0 Open ; +P-V-222 221 222 221.696151733 11.9441843033 155 0 Open ; +P-V-223 222 223 246.15618515 13.9407930374 155 0 Open ; +P-V-224 223 224 495.904418945 12.3117656708 155 0 Open ; +P-V-225 224 225 742.717102051 7.92477321625 155 0 Open ; +P-V-226 225 226 533.423065186 11.8338861465 155 0 Open ; +P-V-227 226 227 556.935791016 7.3915271759 155 0 Open ; +P-V-228 227 228 619.868652344 5.6596622467 155 0 Open ; +P-V-229 228 229 247.326583862 11.3586015701 155 0 Open ; +P-V-230 229 230 751.076904297 9.99314308167 155 0 Open ; +P-V-231 230 231 488.095062256 3.2791453898 155 0 Open ; +P-V-232 231 232 779.850341797 9.89246463776 155 0 Open ; +P-V-233 232 233 482.689208984 10.1512589455 155 0 Open ; +P-V-234 233 234 760.841064453 4.13142120838 155 0 Open ; +P-V-235 234 235 589.878631592 4.80866122246 155 0 Open ; +P-V-236 235 236 308.54196167 8.29435396194 155 0 Open ; +P-V-237 236 237 310.425987244 5.59379220009 155 0 Open ; +P-V-238 237 238 693.451660156 7.84436750412 155 0 Open ; +P-V-239 238 239 764.575195312 11.3119382858 155 0 Open ; +P-V-240 239 240 537.36050415 3.36894264817 155 0 Open ; +P-V-241 240 241 640.965484619 5.14079976082 155 0 Open ; +P-V-242 241 242 421.272369385 5.49452877045 155 0 Open ; +P-V-243 242 243 677.295471191 13.1038227081 155 0 Open ; +P-V-244 243 244 347.815872192 9.82842111588 155 0 Open ; +P-V-245 244 245 663.897125244 9.38616704941 155 0 Open ; +P-V-246 245 246 415.687515259 12.2029314041 155 0 Open ; +P-V-247 246 247 483.73147583 12.5046272278 155 0 Open ; +P-V-248 247 248 213.588502884 10.639526844 155 0 Open ; +P-V-249 248 249 676.361297607 11.0945177078 155 0 Open ; +P-V-251 250 251 227.789888382 8.29310369492 155 0 Open ; +P-V-252 251 252 459.815734863 13.4663362503 155 0 Open ; +P-V-253 252 253 786.121276855 5.80478024483 155 0 Open ; +P-V-254 253 254 397.178436279 6.56432127953 155 0 Open ; +P-V-255 254 255 277.488822937 10.0925531387 155 0 Open ; +P-V-256 255 256 627.305236816 9.39254951477 155 0 Open ; +P-V-257 256 257 379.090530396 10.496465683 155 0 Open ; +P-V-258 257 258 455.426422119 14.0397672653 155 0 Open ; +P-V-259 258 259 268.619819641 4.86815583706 155 0 Open ; +P-V-260 259 260 504.80847168 5.32662034035 155 0 Open ; +P-V-261 260 261 575.413299561 14.4310112 155 0 Open ; +P-V-262 261 262 250.017471313 3.87357276678 155 0 Open ; +P-V-263 262 263 506.846710205 6.46022725105 155 0 Open ; +P-V-264 263 264 402.21282959 6.82016944885 155 0 Open ; +P-V-265 264 265 479.247558594 5.27879977226 155 0 Open ; +P-V-266 265 266 589.351928711 7.76313400269 155 0 Open ; +P-V-267 266 267 299.900505066 7.55662488937 155 0 Open ; +P-V-268 267 268 759.799560547 14.0277767181 155 0 Open ; +P-V-269 268 269 392.518463135 12.1551761627 155 0 Open ; +P-V-270 269 270 552.479736328 9.54550886154 155 0 Open ; +P-V-271 270 271 518.663909912 6.69465661049 155 0 Open ; +P-V-272 271 272 604.831207275 14.9615402222 155 0 Open ; +P-V-273 272 273 280.951789856 10.1358146667 155 0 Open ; +P-V-274 273 274 381.637298584 14.5588226318 155 0 Open ; +P-V-275 274 275 257.1823349 12.2710399628 155 0 Open ; +P-V-276 275 276 718.621032715 8.27732610703 155 0 Open ; +P-V-277 276 277 401.163574219 14.1284694672 155 0 Open ; +P-V-278 277 278 409.790649414 10.0349497795 155 0 Open ; +P-V-279 278 279 220.278493881 3.41315302253 155 0 Open ; +P-V-280 279 280 593.159881592 3.75562107563 155 0 Open ; +P-V-281 280 281 386.177444458 4.69228255749 155 0 Open ; +P-V-282 281 282 309.614974976 8.97805976868 155 0 Open ; +P-V-283 282 283 662.577484131 9.79087591171 155 0 Open ; +P-V-284 283 284 312.690887451 10.9175739288 155 0 Open ; +P-V-285 284 285 333.243240356 7.38141393661 155 0 Open ; +P-V-286 285 286 521.469421387 13.7394065857 155 0 Open ; +P-V-287 286 287 460.68850708 6.83337450027 155 0 Open ; +P-V-288 287 288 776.182983398 13.1458597183 155 0 Open ; +P-V-289 288 289 273.002250671 13.9779939651 155 0 Open ; +P-V-290 289 290 557.815185547 14.9981889725 155 0 Open ; +P-V-291 290 291 478.910705566 12.0421619415 155 0 Open ; +P-V-292 291 292 380.967971802 5.57600188255 155 0 Open ; +P-V-293 292 293 743.233093262 13.3743343353 155 0 Open ; +P-V-294 293 294 271.842407227 8.10543775558 155 0 Open ; +P-V-295 294 295 554.621459961 9.46050310135 155 0 Open ; +P-V-296 295 296 483.830688477 9.85313129425 155 0 Open ; +P-V-297 296 297 428.735519409 6.16403388977 155 0 Open ; +P-V-298 297 298 495.997894287 7.73488903046 155 0 Open ; +P-V-299 298 299 564.147277832 7.47275686264 155 0 Open ; +P-V-301 300 301 481.246917725 5.3406484127 155 0 Open ; +P-V-302 301 302 363.925827026 13.0310554504 155 0 Open ; +P-V-303 302 303 397.963546753 6.4665813446 155 0 Open ; +P-V-304 303 304 341.695343018 4.4717900753 155 0 Open ; +P-V-305 304 305 418.835739136 14.4486751556 155 0 Open ; +P-V-306 305 306 694.598815918 9.454621315 155 0 Open ; +P-V-307 306 307 341.182678223 12.146314621 155 0 Open ; +P-V-308 307 308 305.888191223 4.25834107399 155 0 Open ; +P-V-309 308 309 446.970535278 3.67842054367 155 0 Open ; +P-V-310 309 310 310.721351624 8.87698364258 155 0 Open ; +P-V-311 310 311 323.55695343 3.43708646297 155 0 Open ; +P-V-312 311 312 305.612457275 7.57306051254 155 0 Open ; +P-V-313 312 313 771.403503418 14.5741033554 155 0 Open ; +P-V-314 313 314 498.314910889 6.57662081718 155 0 Open ; +P-V-315 314 315 413.344238281 4.53700017929 155 0 Open ; +P-V-316 315 316 618.035522461 13.4620304108 155 0 Open ; +P-V-317 316 317 767.342712402 5.58903121948 155 0 Open ; +P-V-318 317 318 292.607009888 3.91993868351 155 0 Open ; +P-V-319 318 319 470.505889893 6.85935139656 155 0 Open ; +P-V-320 319 320 405.935089111 10.0204138756 155 0 Open ; +P-V-321 320 321 604.929870605 12.129160881 155 0 Open ; +P-V-322 321 322 291.030845642 14.1101150513 155 0 Open ; +P-V-323 322 323 585.181396484 9.88280344009 155 0 Open ; +P-V-324 323 324 764.304016113 4.15552318096 155 0 Open ; +P-V-325 324 325 443.985397339 8.25310611725 155 0 Open ; +P-V-326 325 326 447.85760498 13.8547306061 155 0 Open ; +P-V-327 326 327 773.016174316 4.66613066196 155 0 Open ; +P-V-328 327 328 532.954071045 10.1870803833 155 0 Open ; +P-V-329 328 329 263.146923065 13.2071819305 155 0 Open ; +P-V-330 329 330 205.661771297 10.1479172707 155 0 Open ; +P-V-331 330 331 352.481536865 6.14876556396 155 0 Open ; +P-V-332 331 332 265.299438477 4.75289154053 155 0 Open ; +P-V-333 332 333 242.43963623 12.660200119 155 0 Open ; +P-V-334 333 334 749.655883789 12.3348312378 155 0 Open ; +P-V-335 334 335 326.256095886 10.7257852554 155 0 Open ; +P-V-336 335 336 563.603271484 4.61117303371 155 0 Open ; +P-V-337 336 337 549.318969727 3.08620464802 155 0 Open ; +P-V-338 337 338 642.077575684 6.95129942894 155 0 Open ; +P-V-339 338 339 274.335777283 6.22947478294 155 0 Open ; +P-V-340 339 340 289.088150024 9.09151315689 155 0 Open ; +P-V-341 340 341 603.143280029 11.5745315552 155 0 Open ; +P-V-342 341 342 408.210891724 7.0119137764 155 0 Open ; +P-V-343 342 343 211.865656853 7.52197980881 155 0 Open ; +P-V-344 343 344 446.086288452 6.4446554184 155 0 Open ; +P-V-345 344 345 516.371582031 4.14800000191 155 0 Open ; +P-V-346 345 346 721.794189453 6.91102838516 155 0 Open ; +P-V-347 346 347 632.714355469 3.61615866423 155 0 Open ; +P-V-348 347 348 788.924316406 12.0250377655 155 0 Open ; +P-V-349 348 349 390.890487671 4.92667222023 155 0 Open ; +P-V-351 350 351 479.015106201 11.1396713257 155 0 Open ; +P-V-352 351 352 373.0521698 8.75549173355 155 0 Open ; +P-V-353 352 353 227.713768005 6.70585393906 155 0 Open ; +P-V-354 353 354 414.356002808 8.62774372101 155 0 Open ; +P-V-355 354 355 274.625984192 7.77840518951 155 0 Open ; +P-V-356 355 356 533.115936279 4.58967590332 155 0 Open ; +P-V-357 356 357 484.178833008 6.87798166275 155 0 Open ; +P-V-358 357 358 462.053039551 9.50647878647 155 0 Open ; +P-V-359 358 359 719.698059082 10.3086390495 155 0 Open ; +P-V-360 359 360 414.748306274 8.4947719574 155 0 Open ; +P-V-361 360 361 731.475646973 9.23323106766 155 0 Open ; +P-V-362 361 362 296.165290833 12.0010051727 155 0 Open ; +P-V-363 362 363 595.16217041 4.81561350822 155 0 Open ; +P-V-364 363 364 750.918762207 4.84057581425 155 0 Open ; +P-V-365 364 365 727.839294434 10.8904066086 155 0 Open ; +P-V-366 365 366 303.412612915 12.117061615 155 0 Open ; +P-V-367 366 367 323.534706116 7.95748758316 155 0 Open ; +P-V-368 367 368 425.021148682 5.61148118973 155 0 Open ; +P-V-369 368 369 558.309570312 13.1874465942 155 0 Open ; +P-V-370 369 370 421.179901123 10.4132614136 155 0 Open ; +P-V-371 370 371 734.394592285 6.39631319046 155 0 Open ; +P-V-372 371 372 691.880157471 7.59458971024 155 0 Open ; +P-V-373 372 373 263.770023346 6.65547466278 155 0 Open ; +P-V-374 373 374 678.134277344 7.0630197525 155 0 Open ; +P-V-375 374 375 558.647460938 6.76218366623 155 0 Open ; +P-V-376 375 376 351.186264038 14.7503128052 155 0 Open ; +P-V-377 376 377 375.346939087 12.1232595444 155 0 Open ; +P-V-378 377 378 731.679748535 5.84434986115 155 0 Open ; +P-V-379 378 379 649.455444336 14.9548797607 155 0 Open ; +P-V-380 379 380 683.438598633 14.0451450348 155 0 Open ; +P-V-381 380 381 587.939544678 12.9957580566 155 0 Open ; +P-V-382 381 382 735.778259277 3.51959842443 155 0 Open ; +P-V-383 382 383 644.569061279 4.4397097826 155 0 Open ; +P-V-384 383 384 460.152374268 6.6186375618 155 0 Open ; +P-V-385 384 385 321.944984436 13.5889606476 155 0 Open ; +P-V-386 385 386 633.154754639 7.64686155319 155 0 Open ; +P-V-387 386 387 390.23638916 13.0621080399 155 0 Open ; +P-V-388 387 388 692.892791748 11.989153862 155 0 Open ; +P-V-389 388 389 235.207263947 5.57045722008 155 0 Open ; +P-V-390 389 390 283.813545227 12.0878200531 155 0 Open ; +P-V-391 390 391 349.999969482 11.992228508 155 0 Open ; +P-V-392 391 392 419.148803711 11.6839141846 155 0 Open ; +P-V-393 392 393 528.020965576 7.96213293076 155 0 Open ; +P-V-394 393 394 728.676391602 4.28469610214 155 0 Open ; +P-V-395 394 395 394.36680603 9.45866918564 155 0 Open ; +P-V-396 395 396 742.497741699 6.18243694305 155 0 Open ; +P-V-397 396 397 360.977111816 5.85141134262 155 0 Open ; +P-V-398 397 398 583.494689941 6.91259622574 155 0 Open ; +P-V-399 398 399 750.385375977 5.54866147041 155 0 Open ; +P-V-401 400 401 567.785064697 6.26825881004 155 0 Open ; +P-V-402 401 402 481.282897949 5.43642711639 155 0 Open ; +P-V-403 402 403 451.734817505 9.14619398117 155 0 Open ; +P-V-404 403 404 353.828033447 14.756278038 155 0 Open ; +P-V-405 404 405 587.986175537 4.67886340618 155 0 Open ; +P-V-406 405 406 432.92350769 9.91263818741 155 0 Open ; +P-V-407 406 407 635.886993408 14.0514144897 155 0 Open ; +P-V-408 407 408 456.86730957 6.38417744637 155 0 Open ; +P-V-409 408 409 693.386871338 10.0706882477 155 0 Open ; +P-V-410 409 410 253.170669556 7.7899017334 155 0 Open ; +P-V-411 410 411 594.219390869 11.8998756409 155 0 Open ; +P-V-412 411 412 210.934998512 6.69038653374 155 0 Open ; +P-V-413 412 413 616.378295898 8.3982219696 155 0 Open ; +P-V-414 413 414 595.882781982 7.04205513 155 0 Open ; +P-V-415 414 415 341.145904541 11.7867250443 155 0 Open ; +P-V-416 415 416 524.291046143 14.1990022659 155 0 Open ; +P-V-417 416 417 282.173706055 12.8706855774 155 0 Open ; +P-V-418 417 418 630.617858887 6.8899872303 155 0 Open ; +P-V-419 418 419 350.87538147 6.2498755455 155 0 Open ; +P-V-420 419 420 632.917510986 11.8882379532 155 0 Open ; +P-V-421 420 421 631.365356445 6.15635490417 155 0 Open ; +P-V-422 421 422 642.981109619 10.6794791222 155 0 Open ; +P-V-423 422 423 650.438262939 9.32208013535 155 0 Open ; +P-V-424 423 424 560.014465332 10.2643823624 155 0 Open ; +P-V-425 424 425 424.05758667 5.71850419044 155 0 Open ; +P-V-426 425 426 495.111755371 9.87010002136 155 0 Open ; +P-V-427 426 427 288.358421326 3.79785490036 155 0 Open ; +P-V-428 427 428 477.342346191 12.8577718735 155 0 Open ; +P-V-429 428 429 578.964019775 7.96083784103 155 0 Open ; +P-V-430 429 430 240.264789581 13.6069049835 155 0 Open ; +P-V-431 430 431 713.330200195 5.81633758545 155 0 Open ; +P-V-432 431 432 509.344238281 5.97742080688 155 0 Open ; +P-V-433 432 433 275.609100342 14.2433719635 155 0 Open ; +P-V-434 433 434 368.194290161 7.8305978775 155 0 Open ; +P-V-435 434 435 593.169281006 6.92905712128 155 0 Open ; +P-V-436 435 436 783.294250488 3.53832614422 155 0 Open ; +P-V-437 436 437 782.389587402 11.4374856949 155 0 Open ; +P-V-438 437 438 441.121078491 5.44185876846 155 0 Open ; +P-V-439 438 439 215.960682869 4.02421247959 155 0 Open ; +P-V-440 439 440 497.015533447 13.8037948608 155 0 Open ; +P-V-441 440 441 568.996734619 5.56794857979 155 0 Open ; +P-V-442 441 442 575.657318115 12.457151413 155 0 Open ; +P-V-443 442 443 517.902618408 14.7981147766 155 0 Open ; +P-V-444 443 444 346.029495239 9.3560628891 155 0 Open ; +P-V-445 444 445 317.338638306 13.2111129761 155 0 Open ; +P-V-446 445 446 508.881072998 6.29130744934 155 0 Open ; +P-V-447 446 447 650.46206665 5.32676529884 155 0 Open ; +P-V-448 447 448 697.269866943 7.29823827744 155 0 Open ; +P-V-449 448 449 224.884050369 3.52465367317 155 0 Open ; +P-V-451 450 451 692.733215332 6.35085010529 155 0 Open ; +P-V-452 451 452 286.887290955 13.2930021286 155 0 Open ; +P-V-453 452 453 324.286445618 8.64659547806 155 0 Open ; +P-V-454 453 454 516.698455811 6.02139616013 155 0 Open ; +P-V-455 454 455 630.339477539 9.3118429184 155 0 Open ; +P-V-456 455 456 357.457214355 10.6679811478 155 0 Open ; +P-V-457 456 457 588.428527832 9.3703622818 155 0 Open ; +P-V-458 457 458 334.162002563 4.21827244759 155 0 Open ; +P-V-459 458 459 375.286239624 3.7172858119 155 0 Open ; +P-V-460 459 460 571.160461426 12.8859987259 155 0 Open ; +P-V-461 460 461 299.437011719 7.75715446472 155 0 Open ; +P-V-462 461 462 674.98638916 4.9236831665 155 0 Open ; +P-V-463 462 463 367.168518066 11.0221500397 155 0 Open ; +P-V-464 463 464 613.951751709 8.74688386917 155 0 Open ; +P-V-465 464 465 794.274963379 10.5780386925 155 0 Open ; +P-V-466 465 466 604.733642578 6.17296695709 155 0 Open ; +P-V-467 466 467 202.780503511 13.6384782791 155 0 Open ; +P-V-468 467 468 245.252624512 10.2176847458 155 0 Open ; +P-V-469 468 469 781.626220703 6.85140967369 155 0 Open ; +P-V-470 469 470 332.055053711 3.98507380486 155 0 Open ; +P-V-471 470 471 606.786376953 12.1748256683 155 0 Open ; +P-V-472 471 472 265.251731873 12.7174119949 155 0 Open ; +P-V-473 472 473 227.425754547 5.89313387871 155 0 Open ; +P-V-474 473 474 245.16097641 3.41102948785 155 0 Open ; +P-V-475 474 475 608.620880127 4.82344484329 155 0 Open ; +P-V-476 475 476 731.910766602 11.4880685806 155 0 Open ; +P-V-477 476 477 348.65574646 4.14562726021 155 0 Open ; +P-V-478 477 478 527.957763672 10.7297878265 155 0 Open ; +P-V-479 478 479 327.558372498 4.47158539295 155 0 Open ; +P-V-480 479 480 246.841892242 4.43387973309 155 0 Open ; +P-V-481 480 481 360.917205811 9.71403741837 155 0 Open ; +P-V-482 481 482 541.819854736 14.3289031982 155 0 Open ; +P-V-483 482 483 243.993339539 6.92252421379 155 0 Open ; +P-V-484 483 484 693.296600342 3.71802502871 155 0 Open ; +P-V-485 484 485 592.365997314 12.9154672623 155 0 Open ; +P-V-486 485 486 462.917724609 12.1647787094 155 0 Open ; +P-V-487 486 487 222.028396606 3.62528502941 155 0 Open ; +P-V-488 487 488 658.309143066 3.03650775179 155 0 Open ; +P-V-489 488 489 279.290802002 3.80901771784 155 0 Open ; +P-V-490 489 490 258.072372437 11.4473724365 155 0 Open ; +P-V-491 490 491 349.536773682 12.2921218872 155 0 Open ; +P-V-492 491 492 434.523529053 7.74499130249 155 0 Open ; +P-V-493 492 493 653.774719238 14.8419532776 155 0 Open ; +P-V-494 493 494 585.439849854 12.7645187378 155 0 Open ; +P-V-495 494 495 213.300080299 9.68921899796 155 0 Open ; +P-V-496 495 496 685.450500488 6.33623886108 155 0 Open ; +P-V-497 496 497 608.318817139 11.2901086807 155 0 Open ; +P-V-498 497 498 793.485778809 9.32037639618 155 0 Open ; +P-V-499 498 499 328.512054443 13.0416107178 155 0 Open ; +P-V-501 500 501 268.027664185 9.82110834122 155 0 Open ; +P-V-502 501 502 518.358062744 11.8847150803 155 0 Open ; +P-V-503 502 503 670.513702393 13.4761133194 155 0 Open ; +P-V-504 503 504 602.062164307 8.17110013962 155 0 Open ; +P-V-505 504 505 534.375335693 7.92052459717 155 0 Open ; +P-V-506 505 506 563.124206543 11.5716352463 155 0 Open ; +P-V-507 506 507 373.972137451 5.99468803406 155 0 Open ; +P-V-508 507 508 386.26121521 8.84213590622 155 0 Open ; +P-V-509 508 509 439.127075195 7.17850971222 155 0 Open ; +P-V-510 509 510 410.572555542 8.85933113098 155 0 Open ; +P-V-511 510 511 488.968292236 8.8049955368 155 0 Open ; +P-V-512 511 512 428.151901245 13.9767408371 155 0 Open ; +P-V-513 512 513 704.936859131 4.47771418095 155 0 Open ; +P-V-514 513 514 597.157928467 3.66640996933 155 0 Open ; +P-V-515 514 515 417.625808716 3.74094104767 155 0 Open ; +P-V-516 515 516 649.831604004 9.39804601669 155 0 Open ; +P-V-517 516 517 798.083740234 6.87716245651 155 0 Open ; +P-V-518 517 518 373.537582397 3.92514806986 155 0 Open ; +P-V-519 518 519 648.204345703 14.409122467 155 0 Open ; +P-V-520 519 520 456.357635498 3.0614479892 155 0 Open ; +P-V-521 520 521 237.817741394 7.05665445328 155 0 Open ; +P-V-522 521 522 610.017486572 6.28322720528 155 0 Open ; +P-V-523 522 523 460.097503662 12.174952507 155 0 Open ; +P-V-524 523 524 371.752960205 4.04183328152 155 0 Open ; +P-V-525 524 525 304.650184631 8.11303806305 155 0 Open ; +P-V-526 525 526 341.727676392 3.34318050742 155 0 Open ; +P-V-527 526 527 591.758331299 12.6447877884 155 0 Open ; +P-V-528 527 528 397.401382446 9.50662755966 155 0 Open ; +P-V-529 528 529 244.926235199 8.50544929504 155 0 Open ; +P-V-530 529 530 704.387664795 11.8753890991 155 0 Open ; +P-V-531 530 531 633.488067627 11.6762037277 155 0 Open ; +P-V-532 531 532 647.660400391 11.5722389221 155 0 Open ; +P-V-533 532 533 281.092689514 9.49740076065 155 0 Open ; +P-V-534 533 534 290.960289001 14.3902988434 155 0 Open ; +P-V-535 534 535 238.149337769 10.5189290047 155 0 Open ; +P-V-536 535 536 732.342651367 12.654132843 155 0 Open ; +P-V-537 536 537 450.599441528 11.500246048 155 0 Open ; +P-V-538 537 538 382.165740967 12.1969623566 155 0 Open ; +P-V-539 538 539 267.889701843 11.4437656403 155 0 Open ; +P-V-540 539 540 318.64691925 8.97855806351 155 0 Open ; +P-V-541 540 541 481.57623291 8.03600120544 155 0 Open ; +P-V-542 541 542 403.704177856 4.12522900105 155 0 Open ; +P-V-543 542 543 786.27911377 10.8647460938 155 0 Open ; +P-V-544 543 544 339.678787231 10.6308875084 155 0 Open ; +P-V-545 544 545 616.508483887 4.16600239277 155 0 Open ; +P-V-546 545 546 250.205135345 6.95442175865 155 0 Open ; +P-V-547 546 547 498.544006348 11.5813322067 155 0 Open ; +P-V-548 547 548 722.678222656 4.06440079212 155 0 Open ; +P-V-549 548 549 669.256134033 10.7672729492 155 0 Open ; +P-V-551 550 551 627.979309082 7.96603345871 155 0 Open ; +P-V-552 551 552 406.350448608 5.64127635956 155 0 Open ; +P-V-553 552 553 396.575698853 7.95605659485 155 0 Open ; +P-V-554 553 554 422.205245972 7.07210063934 155 0 Open ; +P-V-555 554 555 389.794219971 8.42714691162 155 0 Open ; +P-V-556 555 556 303.103393555 4.17636716366 155 0 Open ; +P-V-557 556 557 560.235656738 12.6151094437 155 0 Open ; +P-V-558 557 558 657.578491211 9.43630599976 155 0 Open ; +P-V-559 558 559 549.8855896 13.5429983139 155 0 Open ; +P-V-560 559 560 408.407119751 12.9691410065 155 0 Open ; +P-V-561 560 561 568.265380859 11.7335186005 155 0 Open ; +P-V-562 561 562 213.105952263 4.43504977226 155 0 Open ; +P-V-563 562 563 744.179992676 7.66200256348 155 0 Open ; +P-V-564 563 564 514.231689453 4.84618639946 155 0 Open ; +P-V-565 564 565 642.75869751 7.91833734512 155 0 Open ; +P-V-566 565 566 524.836853027 5.66118216515 155 0 Open ; +P-V-567 566 567 324.594741821 4.27755451202 155 0 Open ; +P-V-568 567 568 393.022323608 13.5275430679 155 0 Open ; +P-V-569 568 569 620.901062012 4.69083058834 155 0 Open ; +P-V-570 569 570 289.443305969 8.47469902039 155 0 Open ; +P-V-571 570 571 663.699554443 14.979924202 155 0 Open ; +P-V-572 571 572 729.988708496 13.40284729 155 0 Open ; +P-V-573 572 573 232.943393707 12.5922880173 155 0 Open ; +P-V-574 573 574 679.458190918 8.08180189133 155 0 Open ; +P-V-575 574 575 492.597015381 4.56596374512 155 0 Open ; +P-V-576 575 576 357.70425415 9.70973539352 155 0 Open ; +P-V-577 576 577 526.098327637 9.68635559082 155 0 Open ; +P-V-578 577 578 678.860748291 11.2529716492 155 0 Open ; +P-V-579 578 579 785.196594238 6.9939866066 155 0 Open ; +P-V-580 579 580 746.622924805 12.8344993591 155 0 Open ; +P-V-581 580 581 221.933177948 7.61837768555 155 0 Open ; +P-V-582 581 582 453.544281006 5.37633109093 155 0 Open ; +P-V-583 582 583 349.934921265 14.1284828186 155 0 Open ; +P-V-584 583 584 420.900970459 12.6558303833 155 0 Open ; +P-V-585 584 585 677.59387207 5.40769863129 155 0 Open ; +P-V-586 585 586 309.530082703 4.44483923912 155 0 Open ; +P-V-587 586 587 570.714630127 7.01932382584 155 0 Open ; +P-V-588 587 588 438.792694092 14.77876091 155 0 Open ; +P-V-589 588 589 282.126670837 9.06051206589 155 0 Open ; +P-V-590 589 590 351.096237183 8.48893594742 155 0 Open ; +P-V-591 590 591 627.380340576 10.6293029785 155 0 Open ; +P-V-592 591 592 485.135070801 4.30630981922 155 0 Open ; +P-V-593 592 593 557.546325684 8.61818218231 155 0 Open ; +P-V-594 593 594 639.27230835 11.9967088699 155 0 Open ; +P-V-595 594 595 584.244445801 6.9309527874 155 0 Open ; +P-V-596 595 596 576.332946777 11.560043335 155 0 Open ; +P-V-597 596 597 232.269618988 14.1093397141 155 0 Open ; +P-V-598 597 598 533.654968262 5.77935934067 155 0 Open ; +P-V-599 598 599 634.684051514 5.70107698441 155 0 Open ; +P-V-601 600 601 250.112205505 11.7179107666 155 0 Open ; +P-V-602 601 602 296.464820862 4.68665146828 155 0 Open ; +P-V-603 602 603 377.541671753 5.85964822769 155 0 Open ; +P-V-604 603 604 305.408042908 10.8595733643 155 0 Open ; +P-V-605 604 605 792.399902344 4.30261540413 155 0 Open ; +P-V-606 605 606 452.852233887 12.7516231537 155 0 Open ; +P-V-607 606 607 777.015625 5.03823709488 155 0 Open ; +P-V-608 607 608 632.571624756 3.63585054874 155 0 Open ; +P-V-609 608 609 537.032348633 13.0592107773 155 0 Open ; +P-V-610 609 610 657.682006836 8.23206186295 155 0 Open ; +P-V-611 610 611 763.42175293 7.60368537903 155 0 Open ; +P-V-612 611 612 707.163452148 8.92705535889 155 0 Open ; +P-V-613 612 613 401.259597778 10.4036026001 155 0 Open ; +P-V-614 613 614 417.709289551 7.80072879791 155 0 Open ; +P-V-615 614 615 692.500427246 12.0924482346 155 0 Open ; +P-V-616 615 616 638.792938232 6.86024951935 155 0 Open ; +P-V-617 616 617 560.699157715 12.4231262207 155 0 Open ; +P-V-618 617 618 724.354919434 3.66141194105 155 0 Open ; +P-V-619 618 619 417.532745361 8.45784759521 155 0 Open ; +P-V-620 619 620 302.106681824 5.14048743248 155 0 Open ; +P-V-621 620 621 758.667907715 5.64181280136 155 0 Open ; +P-V-622 621 622 247.43561554 12.0078926086 155 0 Open ; +P-V-623 622 623 382.485198975 11.5734968185 155 0 Open ; +P-V-624 623 624 738.253601074 7.56743001938 155 0 Open ; +P-V-625 624 625 239.945358276 14.2330951691 155 0 Open ; +P-V-626 625 626 731.723815918 8.64332532883 155 0 Open ; +P-V-627 626 627 768.558105469 6.12588238716 155 0 Open ; +P-V-628 627 628 235.351364136 6.00757479668 155 0 Open ; +P-V-629 628 629 415.586425781 14.2250938416 155 0 Open ; +P-V-630 629 630 607.753448486 13.2449512482 155 0 Open ; +P-V-631 630 631 745.231506348 13.120059967 155 0 Open ; +P-V-632 631 632 792.69934082 8.96318531036 155 0 Open ; +P-V-633 632 633 762.878051758 4.83620595932 155 0 Open ; +P-V-634 633 634 655.753753662 8.07100582123 155 0 Open ; +P-V-635 634 635 419.870620728 14.3171081543 155 0 Open ; +P-V-636 635 636 532.344329834 9.22808694839 155 0 Open ; +P-V-637 636 637 773.361022949 12.5721549988 155 0 Open ; +P-V-638 637 638 560.469512939 7.21508550644 155 0 Open ; +P-V-639 638 639 547.434112549 5.50774049759 155 0 Open ; +P-V-640 639 640 379.790740967 5.85977673531 155 0 Open ; +P-V-641 640 641 413.487060547 4.5443559885 155 0 Open ; +P-V-642 641 642 799.657287598 7.79985141754 155 0 Open ; +P-V-643 642 643 555.29397583 7.52721405029 155 0 Open ; +P-V-644 643 644 644.347717285 14.0421180725 155 0 Open ; +P-V-645 644 645 444.217681885 14.3361654282 155 0 Open ; +P-V-646 645 646 347.321670532 11.7058439255 155 0 Open ; +P-V-647 646 647 356.725692749 4.77241301537 155 0 Open ; +P-V-648 647 648 447.217102051 14.5594825745 155 0 Open ; +P-V-649 648 649 211.697816849 11.1045017242 155 0 Open ; +P-V-651 650 651 218.030269623 3.69486761093 155 0 Open ; +P-V-652 651 652 332.022155762 4.92970108986 155 0 Open ; +P-V-653 652 653 624.347595215 11.2087993622 155 0 Open ; +P-V-654 653 654 265.084106445 4.37318861485 155 0 Open ; +P-V-655 654 655 359.054580688 7.60916137695 155 0 Open ; +P-V-656 655 656 509.073272705 10.8940730095 155 0 Open ; +P-V-657 656 657 384.073471069 5.45882415771 155 0 Open ; +P-V-658 657 658 672.967956543 10.4594569206 155 0 Open ; +P-V-659 658 659 555.061309814 13.3091955185 155 0 Open ; +P-V-660 659 660 733.002685547 6.53282833099 155 0 Open ; +P-V-661 660 661 212.364465714 7.19164180756 155 0 Open ; +P-V-662 661 662 646.448181152 12.0960798264 155 0 Open ; +P-V-663 662 663 691.015899658 5.08787107468 155 0 Open ; +P-V-664 663 664 342.633728027 7.90270853043 155 0 Open ; +P-V-665 664 665 591.361206055 11.1571369171 155 0 Open ; +P-V-666 665 666 650.908355713 11.3465242386 155 0 Open ; +P-V-667 666 667 201.870996356 7.91673374176 155 0 Open ; +P-V-668 667 668 377.572784424 4.31498873234 155 0 Open ; +P-V-669 668 669 650.88973999 5.07675743103 155 0 Open ; +P-V-670 669 670 603.151824951 14.4482803345 155 0 Open ; +P-V-671 670 671 363.078536987 4.21896004677 155 0 Open ; +P-V-672 671 672 353.097702026 9.25835084915 155 0 Open ; +P-V-673 672 673 405.371749878 12.6631937027 155 0 Open ; +P-V-674 673 674 265.254463196 13.6366653442 155 0 Open ; +P-V-675 674 675 522.547973633 4.27185773849 155 0 Open ; +P-V-676 675 676 405.655731201 12.1196670532 155 0 Open ; +P-V-677 676 677 712.130310059 10.4958872795 155 0 Open ; +P-V-678 677 678 568.619995117 10.9267129898 155 0 Open ; +P-V-679 678 679 213.095035553 12.7656412125 155 0 Open ; +P-V-680 679 680 556.42767334 4.59548127651 155 0 Open ; +P-V-681 680 681 562.649047852 7.8613910675 155 0 Open ; +P-V-682 681 682 670.137298584 6.95593595505 155 0 Open ; +P-V-683 682 683 570.825195312 8.18271303177 155 0 Open ; +P-V-684 683 684 692.912353516 6.56151938438 155 0 Open ; +P-V-685 684 685 322.778488159 5.76308751106 155 0 Open ; +P-V-686 685 686 760.742797852 7.09631681442 155 0 Open ; +P-V-687 686 687 339.691040039 14.7436752319 155 0 Open ; +P-V-688 687 688 798.199523926 9.78523683548 155 0 Open ; +P-V-689 688 689 374.151443481 6.26875090599 155 0 Open ; +P-V-690 689 690 294.956604004 13.7153310776 155 0 Open ; +P-V-691 690 691 628.886901855 13.0428533554 155 0 Open ; +P-V-692 691 692 712.035583496 14.6430015564 155 0 Open ; +P-V-693 692 693 797.038635254 3.57927703857 155 0 Open ; +P-V-694 693 694 395.468978882 7.94433832169 155 0 Open ; +P-V-695 694 695 775.095581055 7.64198684692 155 0 Open ; +P-V-696 695 696 493.587585449 13.5302352905 155 0 Open ; +P-V-697 696 697 482.953460693 14.9766683578 155 0 Open ; +P-V-698 697 698 393.475204468 9.75809526443 155 0 Open ; +P-V-699 698 699 365.221923828 4.70073974133 155 0 Open ; +P-V-701 700 701 216.595329285 13.3542585373 155 0 Open ; +P-V-702 701 702 201.403787136 6.86902070045 155 0 Open ; +P-V-703 702 703 731.514221191 10.2068471909 155 0 Open ; +P-V-704 703 704 674.197723389 3.83150196075 155 0 Open ; +P-V-705 704 705 552.696533203 10.4097266197 155 0 Open ; +P-V-706 705 706 764.118408203 13.7599811554 155 0 Open ; +P-V-707 706 707 351.032180786 10.956433773 155 0 Open ; +P-V-708 707 708 589.399780273 11.8408756256 155 0 Open ; +P-V-709 708 709 430.1171875 14.5924310684 155 0 Open ; +P-V-710 709 710 299.830108643 7.89466190338 155 0 Open ; +P-V-711 710 711 429.133972168 8.09844398499 155 0 Open ; +P-V-712 711 712 677.645812988 10.869204998 155 0 Open ; +P-V-713 712 713 486.409057617 12.5464525223 155 0 Open ; +P-V-714 713 714 561.371429443 10.3959207535 155 0 Open ; +P-V-715 714 715 562.199035645 12.5865325928 155 0 Open ; +P-V-716 715 716 642.93572998 7.42313051224 155 0 Open ; +P-V-717 716 717 777.918640137 8.57604837418 155 0 Open ; +P-V-718 717 718 632.416229248 11.384598732 155 0 Open ; +P-V-719 718 719 397.668228149 3.20179738104 155 0 Open ; +P-V-720 719 720 580.433929443 10.0627889633 155 0 Open ; +P-V-721 720 721 215.054013252 11.2560958862 155 0 Open ; +P-V-722 721 722 410.156173706 12.8983974457 155 0 Open ; +P-V-723 722 723 518.323944092 12.415640831 155 0 Open ; +P-V-724 723 724 433.700866699 7.21275615692 155 0 Open ; +P-V-725 724 725 389.595855713 13.7507066727 155 0 Open ; +P-V-726 725 726 356.874679565 6.85813951492 155 0 Open ; +P-V-727 726 727 587.589813232 3.4466663897 155 0 Open ; +P-V-728 727 728 556.100738525 14.7102508545 155 0 Open ; +P-V-729 728 729 309.847045898 14.9853286743 155 0 Open ; +P-V-730 729 730 471.444519043 10.3600502014 155 0 Open ; +P-V-731 730 731 418.006484985 11.7059288025 155 0 Open ; +P-V-732 731 732 427.468231201 12.1737527847 155 0 Open ; +P-V-733 732 733 563.72442627 9.33033227921 155 0 Open ; +P-V-734 733 734 294.756782532 6.54620599747 155 0 Open ; +P-V-735 734 735 654.316223145 4.85838317871 155 0 Open ; +P-V-736 735 736 692.234527588 6.71142935753 155 0 Open ; +P-V-737 736 737 299.626045227 11.3005418777 155 0 Open ; +P-V-738 737 738 560.847625732 14.3193292618 155 0 Open ; +P-V-739 738 739 598.773742676 6.81011295319 155 0 Open ; +P-V-740 739 740 428.355957031 10.5721755028 155 0 Open ; +P-V-741 740 741 478.140655518 5.19852280617 155 0 Open ; +P-V-742 741 742 328.691101074 13.2303972244 155 0 Open ; +P-V-743 742 743 514.936065674 13.6187124252 155 0 Open ; +P-V-744 743 744 435.526016235 8.71724033356 155 0 Open ; +P-V-745 744 745 483.012023926 10.6616463661 155 0 Open ; +P-V-746 745 746 664.634765625 5.33174371719 155 0 Open ; +P-V-747 746 747 681.002685547 11.2494850159 155 0 Open ; +P-V-748 747 748 255.243457794 8.53749704361 155 0 Open ; +P-V-749 748 749 635.515960693 9.34053754807 155 0 Open ; +P-V-751 750 751 470.923522949 3.2341748178 155 0 Open ; +P-V-752 751 752 788.798828125 5.84162783623 155 0 Open ; +P-V-753 752 753 762.059692383 5.75573062897 155 0 Open ; +P-V-754 753 754 578.252319336 8.74460554123 155 0 Open ; +P-V-755 754 755 679.548980713 14.6022005081 155 0 Open ; +P-V-756 755 756 709.295440674 5.57366394997 155 0 Open ; +P-V-757 756 757 578.487243652 3.71226471663 155 0 Open ; +P-V-758 757 758 551.668945312 13.01167202 155 0 Open ; +P-V-759 758 759 308.360488892 7.29525613785 155 0 Open ; +P-V-760 759 760 718.695922852 9.44354867935 155 0 Open ; +P-V-761 760 761 636.280761719 14.4231491089 155 0 Open ; +P-V-762 761 762 244.161109924 3.31502100825 155 0 Open ; +P-V-763 762 763 327.92162323 6.57562446594 155 0 Open ; +P-V-764 763 764 776.154418945 3.54074424505 155 0 Open ; +P-V-765 764 765 414.47819519 13.700592041 155 0 Open ; +P-V-766 765 766 242.84986496 6.55412745476 155 0 Open ; +P-V-767 766 767 711.192687988 7.31375265121 155 0 Open ; +P-V-768 767 768 662.255004883 9.40023183823 155 0 Open ; +P-V-769 768 769 235.305164337 14.4786806107 155 0 Open ; +P-V-770 769 770 709.470092773 4.27932226658 155 0 Open ; +P-V-771 770 771 678.545501709 13.2788915634 155 0 Open ; +P-V-772 771 772 467.106933594 4.32163834572 155 0 Open ; +P-V-773 772 773 238.776515961 5.33783817291 155 0 Open ; +P-V-774 773 774 402.303253174 13.2181005478 155 0 Open ; +P-V-775 774 775 380.780548096 14.5744171143 155 0 Open ; +P-V-776 775 776 762.271728516 5.02393269539 155 0 Open ; +P-V-777 776 777 611.80380249 6.72778654099 155 0 Open ; +P-V-778 777 778 245.544830322 12.4399023056 155 0 Open ; +P-V-779 778 779 422.295959473 13.5642299652 155 0 Open ; +P-V-780 779 780 250.768096924 4.18842351437 155 0 Open ; +P-V-781 780 781 491.672576904 5.82363510132 155 0 Open ; +P-V-782 781 782 641.777252197 14.0152721405 155 0 Open ; +P-V-783 782 783 684.110351562 11.8599720001 155 0 Open ; +P-V-784 783 784 277.847869873 10.783056736 155 0 Open ; +P-V-785 784 785 691.468170166 13.1109609604 155 0 Open ; +P-V-786 785 786 346.770172119 6.32673740387 155 0 Open ; +P-V-787 786 787 423.628372192 5.44276785851 155 0 Open ; +P-V-788 787 788 380.107025146 4.17693352699 155 0 Open ; +P-V-789 788 789 436.100814819 9.93160820007 155 0 Open ; +P-V-790 789 790 376.862854004 5.68113255501 155 0 Open ; +P-V-791 790 791 289.668518066 12.1752872467 155 0 Open ; +P-V-792 791 792 652.79788208 10.4812774658 155 0 Open ; +P-V-793 792 793 291.770202637 10.6377854347 155 0 Open ; +P-V-794 793 794 413.223144531 11.8308010101 155 0 Open ; +P-V-795 794 795 363.926574707 13.2844419479 155 0 Open ; +P-V-796 795 796 331.334991455 13.9444923401 155 0 Open ; +P-V-797 796 797 604.528900146 9.34386825562 155 0 Open ; +P-V-798 797 798 269.966575623 13.5651702881 155 0 Open ; +P-V-799 798 799 440.802490234 6.3550567627 155 0 Open ; +P-V-801 800 801 222.042629242 8.40957593918 155 0 Open ; +P-V-802 801 802 537.111297607 3.59238684177 155 0 Open ; +P-V-803 802 803 612.303039551 6.55231690407 155 0 Open ; +P-V-804 803 804 389.394317627 6.00944280624 155 0 Open ; +P-V-805 804 805 785.38079834 8.90219497681 155 0 Open ; +P-V-806 805 806 509.826538086 12.0989685059 155 0 Open ; +P-V-807 806 807 719.070251465 3.28189313412 155 0 Open ; +P-V-808 807 808 688.912597656 6.07586789131 155 0 Open ; +P-V-809 808 809 205.649408817 5.99230313301 155 0 Open ; +P-V-810 809 810 782.051696777 5.85720777512 155 0 Open ; +P-V-811 810 811 654.677001953 6.13623929024 155 0 Open ; +P-V-812 811 812 538.793640137 5.09806156158 155 0 Open ; +P-V-813 812 813 506.060699463 6.2464466095 155 0 Open ; +P-V-814 813 814 751.500305176 8.32668781281 155 0 Open ; +P-V-815 814 815 482.224517822 9.95555591583 155 0 Open ; +P-V-816 815 816 701.271026611 8.24107503891 155 0 Open ; +P-V-817 816 817 537.584747314 6.73593950272 155 0 Open ; +P-V-818 817 818 496.729675293 13.7208995819 155 0 Open ; +P-V-819 818 819 507.892700195 10.0587391853 155 0 Open ; +P-V-820 819 820 411.757339478 11.112613678 155 0 Open ; +P-V-821 820 821 435.7996521 4.70105922222 155 0 Open ; +P-V-822 821 822 485.135253906 4.37214529514 155 0 Open ; +P-V-823 822 823 682.339996338 4.77015221119 155 0 Open ; +P-V-824 823 824 347.517807007 5.63470983505 155 0 Open ; +P-V-825 824 825 278.478225708 6.67026472092 155 0 Open ; +P-V-826 825 826 506.832855225 13.8014087677 155 0 Open ; +P-V-827 826 827 364.101638794 12.1288146973 155 0 Open ; +P-V-828 827 828 600.181030273 11.8598499298 155 0 Open ; +P-V-829 828 829 775.713745117 11.4203510284 155 0 Open ; +P-V-830 829 830 442.013519287 5.42652964592 155 0 Open ; +P-V-831 830 831 534.321929932 13.9791049957 155 0 Open ; +P-V-832 831 832 291.386772156 13.7516651154 155 0 Open ; +P-V-833 832 833 562.01083374 9.33109331131 155 0 Open ; +P-V-834 833 834 333.989578247 6.25849843025 155 0 Open ; +P-V-835 834 835 679.096099854 6.36028456688 155 0 Open ; +P-V-836 835 836 415.331192017 12.424826622 155 0 Open ; +P-V-837 836 837 353.335678101 5.25467658043 155 0 Open ; +P-V-838 837 838 717.527832031 12.8137931824 155 0 Open ; +P-V-839 838 839 221.256479263 8.15287542343 155 0 Open ; +P-V-840 839 840 218.737308502 13.3593177795 155 0 Open ; +P-V-841 840 841 253.413852692 5.53354263306 155 0 Open ; +P-V-842 841 842 462.704498291 12.4947080612 155 0 Open ; +P-V-843 842 843 278.359672546 14.820019722 155 0 Open ; +P-V-844 843 844 753.964599609 8.66669893265 155 0 Open ; +P-V-845 844 845 610.475311279 4.17149817944 155 0 Open ; +P-V-846 845 846 668.517456055 14.4593667984 155 0 Open ; +P-V-847 846 847 678.992126465 7.41548347473 155 0 Open ; +P-V-848 847 848 351.5131073 4.61638355255 155 0 Open ; +P-V-849 848 849 727.923706055 3.27749341726 155 0 Open ; +P-V-851 850 851 591.596435547 6.22603869438 155 0 Open ; +P-V-852 851 852 401.669723511 4.26644349098 155 0 Open ; +P-V-853 852 853 655.841339111 13.5153093338 155 0 Open ; +P-V-854 853 854 540.583129883 6.6154282093 155 0 Open ; +P-V-855 854 855 625.200378418 9.86654138565 155 0 Open ; +P-V-856 855 856 298.317512512 3.45092022419 155 0 Open ; +P-V-857 856 857 530.813720703 10.718752861 155 0 Open ; +P-V-858 857 858 654.212371826 5.95565629005 155 0 Open ; +P-V-859 858 859 585.773895264 5.03719782829 155 0 Open ; +P-V-860 859 860 359.369537354 5.48002743721 155 0 Open ; +P-V-861 860 861 491.145477295 8.64343166351 155 0 Open ; +P-V-862 861 862 258.022907257 6.82115888596 155 0 Open ; +P-V-863 862 863 710.910400391 8.43533563614 155 0 Open ; +P-V-864 863 864 584.430755615 9.55010890961 155 0 Open ; +P-V-865 864 865 784.170288086 10.0119810104 155 0 Open ; +P-V-866 865 866 718.305908203 10.3487019539 155 0 Open ; +P-V-867 866 867 481.64755249 8.01183271408 155 0 Open ; +P-V-868 867 868 493.9425354 12.850402832 155 0 Open ; +P-V-869 868 869 386.396286011 6.2480070591 155 0 Open ; +P-V-870 869 870 262.709903717 10.3072328568 155 0 Open ; +P-V-871 870 871 433.331253052 14.9677972794 155 0 Open ; +P-V-872 871 872 739.032226562 5.29674553871 155 0 Open ; +P-V-873 872 873 670.269287109 3.32825654745 155 0 Open ; +P-V-874 873 874 650.392913818 6.07258725166 155 0 Open ; +P-V-875 874 875 448.849960327 11.4286136627 155 0 Open ; +P-V-876 875 876 785.335083008 5.54282021523 155 0 Open ; +P-V-877 876 877 459.134765625 12.5644769669 155 0 Open ; +P-V-878 877 878 707.955169678 11.0541954041 155 0 Open ; +P-V-879 878 879 543.586791992 8.26383304596 155 0 Open ; +P-V-880 879 880 462.214935303 3.92710644007 155 0 Open ; +P-V-881 880 881 493.883178711 4.89410090446 155 0 Open ; +P-V-882 881 882 707.634765625 11.3490486145 155 0 Open ; +P-V-883 882 883 522.790435791 13.7839002609 155 0 Open ; +P-V-884 883 884 650.829528809 8.84180498123 155 0 Open ; +P-V-885 884 885 760.819824219 8.97743082047 155 0 Open ; +P-V-886 885 886 734.194213867 11.0509061813 155 0 Open ; +P-V-887 886 887 779.452453613 8.15584230423 155 0 Open ; +P-V-888 887 888 312.190383911 10.6746459007 155 0 Open ; +P-V-889 888 889 788.886047363 11.1513490677 155 0 Open ; +P-V-890 889 890 586.581939697 12.66492939 155 0 Open ; +P-V-891 890 891 523.724975586 3.91764545441 155 0 Open ; +P-V-892 891 892 343.397094727 12.501745224 155 0 Open ; +P-V-893 892 893 791.756103516 3.89633637667 155 0 Open ; +P-V-894 893 894 436.313598633 9.45845603943 155 0 Open ; +P-V-895 894 895 563.455413818 14.9090003967 155 0 Open ; +P-V-896 895 896 529.142333984 12.9046516418 155 0 Open ; +P-V-897 896 897 373.957885742 13.2023200989 155 0 Open ; +P-V-898 897 898 320.109184265 8.50156402588 155 0 Open ; +P-V-899 898 899 439.768005371 6.61942148209 155 0 Open ; +P-V-901 900 901 380.956588745 13.7472162247 155 0 Open ; +P-V-902 901 902 423.704879761 7.16103124619 155 0 Open ; +P-V-903 902 903 722.69543457 9.8486199379 155 0 Open ; +P-V-904 903 904 237.756534576 10.4815368652 155 0 Open ; +P-V-905 904 905 509.764343262 3.18265335262 155 0 Open ; +P-V-906 905 906 692.746490479 10.8116927147 155 0 Open ; +P-V-907 906 907 756.00402832 10.1921253204 155 0 Open ; +P-V-908 907 908 302.666107178 13.1855068207 155 0 Open ; +P-V-909 908 909 590.757781982 12.3235673904 155 0 Open ; +P-V-910 909 910 460.132537842 11.9600563049 155 0 Open ; +P-V-911 910 911 383.360046387 5.64810109138 155 0 Open ; +P-V-912 911 912 731.732849121 11.6744785309 155 0 Open ; +P-V-913 912 913 397.825500488 8.06716823578 155 0 Open ; +P-V-914 913 914 795.156066895 6.75862455368 155 0 Open ; +P-V-915 914 915 360.229675293 6.60495400429 155 0 Open ; +P-V-916 915 916 222.995605469 4.74293231964 155 0 Open ; +P-V-917 916 917 273.161399841 7.47467184067 155 0 Open ; +P-V-918 917 918 290.74446106 13.8417348862 155 0 Open ; +P-V-919 918 919 651.798431396 10.5274586678 155 0 Open ; +P-V-920 919 920 699.997680664 12.2274589539 155 0 Open ; +P-V-921 920 921 695.246612549 11.1986455917 155 0 Open ; +P-V-922 921 922 732.273864746 13.5459947586 155 0 Open ; +P-V-923 922 923 526.935882568 3.22593346238 155 0 Open ; +P-V-924 923 924 463.189880371 7.65177965164 155 0 Open ; +P-V-925 924 925 323.212081909 7.50993061066 155 0 Open ; +P-V-926 925 926 520.495635986 10.4106850624 155 0 Open ; +P-V-927 926 927 369.348480225 11.8020048141 155 0 Open ; +P-V-928 927 928 764.695800781 3.84429770708 155 0 Open ; +P-V-929 928 929 505.601959229 8.04111385345 155 0 Open ; +P-V-930 929 930 500.13671875 6.95946121216 155 0 Open ; +P-V-931 930 931 533.278137207 11.1155834198 155 0 Open ; +P-V-932 931 932 530.680267334 13.8662376404 155 0 Open ; +P-V-933 932 933 243.018222809 3.14563331008 155 0 Open ; +P-V-934 933 934 782.961547852 11.7034845352 155 0 Open ; +P-V-935 934 935 773.821105957 11.2308225632 155 0 Open ; +P-V-936 935 936 771.575134277 12.2649946213 155 0 Open ; +P-V-937 936 937 438.892578125 12.3571720123 155 0 Open ; +P-V-938 937 938 499.976928711 13.246963501 155 0 Open ; +P-V-939 938 939 636.046569824 7.69967365265 155 0 Open ; +P-V-940 939 940 370.990631104 11.7916021347 155 0 Open ; +P-V-941 940 941 423.06237793 7.19183921814 155 0 Open ; +P-V-942 941 942 212.276436806 13.6014862061 155 0 Open ; +P-V-943 942 943 358.824691772 14.3369760513 155 0 Open ; +P-V-944 943 944 427.966903687 11.7991800308 155 0 Open ; +P-V-945 944 945 791.507385254 4.3004758358 155 0 Open ; +P-V-946 945 946 454.873809814 8.28565120697 155 0 Open ; +P-V-947 946 947 797.289672852 3.95389264822 155 0 Open ; +P-V-948 947 948 203.712349176 14.8691225052 155 0 Open ; +P-V-949 948 949 617.397705078 3.06828673929 155 0 Open ; +P-V-951 950 951 584.761383057 12.6932544708 155 0 Open ; +P-V-952 951 952 327.252990723 9.82026863098 155 0 Open ; +P-V-953 952 953 412.918899536 5.55712270737 155 0 Open ; +P-V-954 953 954 478.071258545 5.87569189072 155 0 Open ; +P-V-955 954 955 587.797302246 13.1908864975 155 0 Open ; +P-V-956 955 956 311.439292908 10.2026729584 155 0 Open ; +P-V-957 956 957 766.428405762 10.2554931641 155 0 Open ; +P-V-958 957 958 754.015075684 13.634768486 155 0 Open ; +P-V-959 958 959 727.63092041 12.8687572479 155 0 Open ; +P-V-960 959 960 210.498384476 3.92717963457 155 0 Open ; +P-V-961 960 961 555.459503174 3.15429188311 155 0 Open ; +P-V-962 961 962 259.188724518 14.6992063522 155 0 Open ; +P-V-963 962 963 628.860961914 4.32562434673 155 0 Open ; +P-V-964 963 964 588.460998535 8.27819252014 155 0 Open ; +P-V-965 964 965 529.081634521 4.51276481152 155 0 Open ; +P-V-966 965 966 651.839477539 12.3335494995 155 0 Open ; +P-V-967 966 967 448.602615356 12.284866333 155 0 Open ; +P-V-968 967 968 337.642578125 10.1782684326 155 0 Open ; +P-V-969 968 969 658.010070801 10.5071387291 155 0 Open ; +P-V-970 969 970 424.238983154 6.69205665588 155 0 Open ; +P-V-971 970 971 219.874826431 11.724571228 155 0 Open ; +P-V-972 971 972 493.827758789 10.2668094635 155 0 Open ; +P-V-973 972 973 663.617248535 11.3010616302 155 0 Open ; +P-V-974 973 974 397.681106567 7.53068733215 155 0 Open ; +P-V-975 974 975 563.195281982 11.4561796188 155 0 Open ; +P-V-976 975 976 551.372436523 9.33938455582 155 0 Open ; +P-V-977 976 977 701.621429443 6.02833938599 155 0 Open ; +P-V-978 977 978 465.160736084 10.1264510155 155 0 Open ; +P-V-979 978 979 313.492431641 4.34784901142 155 0 Open ; +P-V-980 979 980 664.898468018 9.97908782959 155 0 Open ; +P-V-981 980 981 676.249023438 9.34386920929 155 0 Open ; +P-V-982 981 982 270.196670532 6.90938973427 155 0 Open ; +P-V-983 982 983 455.598968506 12.0413341522 155 0 Open ; +P-V-984 983 984 285.399406433 5.15757751465 155 0 Open ; +P-V-985 984 985 720.223022461 6.76484036446 155 0 Open ; +P-V-986 985 986 783.617370605 4.15173947811 155 0 Open ; +P-V-987 986 987 264.355407715 11.4262695312 155 0 Open ; +P-V-988 987 988 615.761962891 5.23059630394 155 0 Open ; +P-V-989 988 989 281.598625183 11.5626831055 155 0 Open ; +P-V-990 989 990 650.8621521 7.80842638016 155 0 Open ; +P-V-991 990 991 561.332702637 9.37910318375 155 0 Open ; +P-V-992 991 992 479.737060547 13.814658165 155 0 Open ; +P-V-993 992 993 697.96496582 12.9538660049 155 0 Open ; +P-V-994 993 994 331.983612061 3.97036063671 155 0 Open ; +P-V-995 994 995 242.561439514 5.60241150856 155 0 Open ; +P-V-996 995 996 736.441772461 10.5465159416 155 0 Open ; +P-V-997 996 997 514.932739258 12.4991350174 155 0 Open ; +P-V-998 997 998 398.342544556 13.8646888733 155 0 Open ; +P-V-999 998 999 742.078369141 9.24279975891 155 0 Open ; +P-V-1001 1000 1001 537.158630371 7.50530481339 155 0 Open ; +P-V-1002 1001 1002 233.228832245 12.5400381088 155 0 Open ; +P-V-1003 1002 1003 570.8359375 11.7983074188 155 0 Open ; +P-V-1004 1003 1004 657.973114014 10.0858454704 155 0 Open ; +P-V-1005 1004 1005 390.445755005 11.4403581619 155 0 Open ; +P-V-1006 1005 1006 455.195983887 8.5799369812 155 0 Open ; +P-V-1007 1006 1007 300.013023376 9.38005876541 155 0 Open ; +P-V-1008 1007 1008 682.464263916 10.5409874916 155 0 Open ; +P-V-1009 1008 1009 669.046569824 12.3154859543 155 0 Open ; +P-V-1010 1009 1010 269.223258972 3.70764291286 155 0 Open ; +P-V-1011 1010 1011 267.71270752 11.9507112503 155 0 Open ; +P-V-1012 1011 1012 330.899246216 11.4716749191 155 0 Open ; +P-V-1013 1012 1013 372.514648438 8.07981300354 155 0 Open ; +P-V-1014 1013 1014 620.997253418 13.0178985596 155 0 Open ; +P-V-1015 1014 1015 741.600036621 4.43739628792 155 0 Open ; +P-V-1016 1015 1016 316.035293579 7.10260725021 155 0 Open ; +P-V-1017 1016 1017 226.279809952 4.69554913044 155 0 Open ; +P-V-1018 1017 1018 654.778137207 4.13408136368 155 0 Open ; +P-V-1019 1018 1019 425.301010132 3.68494069576 155 0 Open ; +P-V-1020 1019 1020 389.904556274 9.51897144318 155 0 Open ; +P-V-1021 1020 1021 418.14630127 10.7040586472 155 0 Open ; +P-V-1022 1021 1022 306.047164917 9.69406700134 155 0 Open ; +P-V-1023 1022 1023 559.085083008 9.86771583557 155 0 Open ; +P-V-1024 1023 1024 685.247711182 10.1710357666 155 0 Open ; +P-V-1025 1024 1025 579.879547119 3.70507252216 155 0 Open ; +P-V-1026 1025 1026 507.705230713 7.03696346283 155 0 Open ; +P-V-1027 1026 1027 262.42131424 9.30048179626 155 0 Open ; +P-V-1028 1027 1028 409.894042969 8.78393554688 155 0 Open ; +P-V-1029 1028 1029 730.323608398 5.97643518448 155 0 Open ; +P-V-1030 1029 1030 647.256774902 7.89652395248 155 0 Open ; +P-V-1031 1030 1031 794.166809082 10.223739624 155 0 Open ; +P-V-1032 1031 1032 469.440917969 8.86841726303 155 0 Open ; +P-V-1033 1032 1033 324.660598755 14.4129056931 155 0 Open ; +P-V-1034 1033 1034 635.640167236 3.08272866905 155 0 Open ; +P-V-1035 1034 1035 721.03704834 4.39947223663 155 0 Open ; +P-V-1036 1035 1036 246.569736481 8.95091724396 155 0 Open ; +P-V-1037 1036 1037 653.408477783 11.7217378616 155 0 Open ; +P-V-1038 1037 1038 512.806762695 5.8626203537 155 0 Open ; +P-V-1039 1038 1039 403.082641602 11.2045583725 155 0 Open ; +P-V-1040 1039 1040 301.382865906 13.8380451202 155 0 Open ; +P-V-1041 1040 1041 551.377563477 11.0535469055 155 0 Open ; +P-V-1042 1041 1042 598.246948242 9.72842788696 155 0 Open ; +P-V-1043 1042 1043 634.485443115 10.9378581047 155 0 Open ; +P-V-1044 1043 1044 579.333770752 12.2478704453 155 0 Open ; +P-V-1045 1044 1045 448.185852051 4.19507944584 155 0 Open ; +P-V-1046 1045 1046 685.091033936 5.50288891792 155 0 Open ; +P-V-1047 1046 1047 502.770477295 4.26335656643 155 0 Open ; +P-V-1048 1047 1048 461.695770264 9.42248868942 155 0 Open ; +P-V-1049 1048 1049 338.156661987 14.9802751541 155 0 Open ; +P-V-1051 1050 1051 424.599838257 7.99433135986 155 0 Open ; +P-V-1052 1051 1052 786.328918457 3.59980916977 155 0 Open ; +P-V-1053 1052 1053 249.683006287 11.4464950562 155 0 Open ; +P-V-1054 1053 1054 211.903038979 8.08762264252 155 0 Open ; +P-V-1055 1054 1055 584.027740479 6.08091640472 155 0 Open ; +P-V-1056 1055 1056 248.202095032 5.65156149864 155 0 Open ; +P-V-1057 1056 1057 639.770568848 11.4886808395 155 0 Open ; +P-V-1058 1057 1058 262.909263611 5.31914234161 155 0 Open ; +P-V-1059 1058 1059 291.347503662 12.5525560379 155 0 Open ; +P-V-1060 1059 1060 290.640800476 3.00005363859 155 0 Open ; +P-V-1061 1060 1061 245.075191498 10.5747404099 155 0 Open ; +P-V-1062 1061 1062 233.29265213 9.99139595032 155 0 Open ; +P-V-1063 1062 1063 219.627151489 12.4707546234 155 0 Open ; +P-V-1064 1063 1064 548.762634277 8.06900644302 155 0 Open ; +P-V-1065 1064 1065 539.71975708 4.40529763699 155 0 Open ; +P-V-1066 1065 1066 341.865081787 13.5330648422 155 0 Open ; +P-V-1067 1066 1067 461.81439209 13.2922668457 155 0 Open ; +P-V-1068 1067 1068 306.940872192 10.1058697701 155 0 Open ; +P-V-1069 1068 1069 417.762649536 13.7386722565 155 0 Open ; +P-V-1070 1069 1070 444.098953247 10.4236550331 155 0 Open ; +P-V-1071 1070 1071 468.721282959 6.97519135475 155 0 Open ; +P-V-1072 1071 1072 552.076873779 6.11895442009 155 0 Open ; +P-V-1073 1072 1073 413.589202881 14.8720321655 155 0 Open ; +P-V-1074 1073 1074 662.591827393 14.6174287796 155 0 Open ; +P-V-1075 1074 1075 306.695846558 11.742193222 155 0 Open ; +P-V-1076 1075 1076 301.791114807 7.06779527664 155 0 Open ; +P-V-1077 1076 1077 371.771697998 10.3424048424 155 0 Open ; +P-V-1078 1077 1078 590.00604248 11.6440391541 155 0 Open ; +P-V-1079 1078 1079 618.567901611 12.4110555649 155 0 Open ; +P-V-1080 1079 1080 780.718200684 13.6308031082 155 0 Open ; +P-V-1081 1080 1081 395.757736206 9.00236797333 155 0 Open ; +P-V-1082 1081 1082 690.312225342 8.55191993713 155 0 Open ; +P-V-1083 1082 1083 756.079406738 11.5414848328 155 0 Open ; +P-V-1084 1083 1084 236.995429993 6.64472651482 155 0 Open ; +P-V-1085 1084 1085 645.782562256 4.35699403286 155 0 Open ; +P-V-1086 1085 1086 550.023681641 11.9665470123 155 0 Open ; +P-V-1087 1086 1087 438.07333374 12.9691200256 155 0 Open ; +P-V-1088 1087 1088 550.721801758 6.63140130043 155 0 Open ; +P-V-1089 1088 1089 248.215717316 10.2323355675 155 0 Open ; +P-V-1090 1089 1090 493.140594482 7.28376102448 155 0 Open ; +P-V-1091 1090 1091 659.020019531 13.9831991196 155 0 Open ; +P-V-1092 1091 1092 731.93536377 7.76642656326 155 0 Open ; +P-V-1093 1092 1093 666.579925537 11.1863889694 155 0 Open ; +P-V-1094 1093 1094 632.67489624 14.3406944275 155 0 Open ; +P-V-1095 1094 1095 553.421234131 14.0084753036 155 0 Open ; +P-V-1096 1095 1096 372.441741943 7.56574630737 155 0 Open ; +P-V-1097 1096 1097 624.920593262 11.8035068512 155 0 Open ; +P-V-1098 1097 1098 227.139242172 5.58568453789 155 0 Open ; +P-V-1099 1098 1099 479.946075439 12.0739154816 155 0 Open ; +P-V-1101 1100 1101 665.241638184 5.32133150101 155 0 Open ; +P-V-1102 1101 1102 330.959091187 7.5868844986 155 0 Open ; +P-V-1103 1102 1103 388.438720703 8.78923368454 155 0 Open ; +P-V-1104 1103 1104 382.53062439 14.8472194672 155 0 Open ; +P-V-1105 1104 1105 211.467712402 5.75727677345 155 0 Open ; +P-V-1106 1105 1106 677.708251953 7.85614585876 155 0 Open ; +P-V-1107 1106 1107 462.582824707 7.59908008575 155 0 Open ; +P-V-1108 1107 1108 437.219512939 13.9712133408 155 0 Open ; +P-V-1109 1108 1109 259.567214966 9.92394590378 155 0 Open ; +P-V-1110 1109 1110 537.989898682 10.9275369644 155 0 Open ; +P-V-1111 1110 1111 305.897766113 7.4749789238 155 0 Open ; +P-V-1112 1111 1112 548.516876221 9.46584224701 155 0 Open ; +P-V-1113 1112 1113 770.932373047 12.2115602493 155 0 Open ; +P-V-1114 1113 1114 534.835998535 6.77435040474 155 0 Open ; +P-V-1115 1114 1115 375.5440979 6.39585924149 155 0 Open ; +P-V-1116 1115 1116 310.415092468 13.9279518127 155 0 Open ; +P-V-1117 1116 1117 504.760925293 13.3338727951 155 0 Open ; +P-V-1118 1117 1118 470.215576172 5.26900339127 155 0 Open ; +P-V-1119 1118 1119 757.008544922 11.8588857651 155 0 Open ; +P-V-1120 1119 1120 565.069366455 5.42149162292 155 0 Open ; +P-V-1121 1120 1121 500.588012695 14.6554403305 155 0 Open ; +P-V-1122 1121 1122 449.744934082 12.2595653534 155 0 Open ; +P-V-1123 1122 1123 675.901733398 12.6124134064 155 0 Open ; +P-V-1124 1123 1124 791.309265137 9.69926309586 155 0 Open ; +P-V-1125 1124 1125 725.706115723 13.8457803726 155 0 Open ; +P-V-1126 1125 1126 451.897262573 3.74413520098 155 0 Open ; +P-V-1127 1126 1127 334.019561768 4.33591926098 155 0 Open ; +P-V-1128 1127 1128 239.742092133 5.90767073631 155 0 Open ; +P-V-1129 1128 1129 461.204589844 12.3061323166 155 0 Open ; +P-V-1130 1129 1130 208.502503395 5.03158521652 155 0 Open ; +P-V-1131 1130 1131 442.637481689 11.1690616608 155 0 Open ; +P-V-1132 1131 1132 471.528625488 14.6319007874 155 0 Open ; +P-V-1133 1132 1133 468.070678711 4.28214120865 155 0 Open ; +P-V-1134 1133 1134 647.376159668 12.0179052353 155 0 Open ; +P-V-1135 1134 1135 396.791656494 8.54923152924 155 0 Open ; +P-V-1136 1135 1136 296.825767517 6.01390767097 155 0 Open ; +P-V-1137 1136 1137 337.426742554 9.6270737648 155 0 Open ; +P-V-1138 1137 1138 661.824310303 8.63227987289 155 0 Open ; +P-V-1139 1138 1139 486.571807861 7.25559091568 155 0 Open ; +P-V-1140 1139 1140 386.007644653 7.61598014832 155 0 Open ; +P-V-1141 1140 1141 239.008659363 11.3722486496 155 0 Open ; +P-V-1142 1141 1142 219.822771072 6.226531744 155 0 Open ; +P-V-1143 1142 1143 216.029033661 14.9995517731 155 0 Open ; +P-V-1144 1143 1144 424.01965332 4.96700084209 155 0 Open ; +P-V-1145 1144 1145 769.200683594 6.11864733696 155 0 Open ; +P-V-1146 1145 1146 755.36126709 10.1379389763 155 0 Open ; +P-V-1147 1146 1147 367.228134155 7.0645737648 155 0 Open ; +P-V-1148 1147 1148 664.804321289 14.3268079758 155 0 Open ; +P-V-1149 1148 1149 283.49697113 13.6720514297 155 0 Open ; +P-V-1151 1150 1151 258.579689026 13.9779167175 155 0 Open ; +P-V-1152 1151 1152 492.360137939 8.93544244766 155 0 Open ; +P-V-1153 1152 1153 249.359050751 10.5518951416 155 0 Open ; +P-V-1154 1153 1154 235.454605103 4.71082317829 155 0 Open ; +P-V-1155 1154 1155 290.289848328 5.03087306023 155 0 Open ; +P-V-1156 1155 1156 444.281829834 11.8941192627 155 0 Open ; +P-V-1157 1156 1157 773.346618652 7.72277975082 155 0 Open ; +P-V-1158 1157 1158 588.255004883 11.0453472137 155 0 Open ; +P-V-1159 1158 1159 307.696998596 12.2720947266 155 0 Open ; +P-V-1160 1159 1160 405.239105225 4.07467794418 155 0 Open ; +P-V-1161 1160 1161 305.693778992 10.905371666 155 0 Open ; +P-V-1162 1161 1162 279.048141479 6.24259710312 155 0 Open ; +P-V-1163 1162 1163 516.670959473 8.77945566177 155 0 Open ; +P-V-1164 1163 1164 565.791473389 8.14381170273 155 0 Open ; +P-V-1165 1164 1165 402.52796936 4.75480425358 155 0 Open ; +P-V-1166 1165 1166 649.814666748 3.70032405853 155 0 Open ; +P-V-1167 1166 1167 717.365112305 6.11291956902 155 0 Open ; +P-V-1168 1167 1168 741.815490723 4.85203611851 155 0 Open ; +P-V-1169 1168 1169 758.654602051 13.1758041382 155 0 Open ; +P-V-1170 1169 1170 237.571872711 8.40925598145 155 0 Open ; +P-V-1171 1170 1171 268.651176453 3.40820914507 155 0 Open ; +P-V-1172 1171 1172 638.541137695 6.21581196785 155 0 Open ; +P-V-1173 1172 1173 207.616615772 7.24925422668 155 0 Open ; +P-V-1174 1173 1174 460.955413818 12.5518341064 155 0 Open ; +P-V-1175 1174 1175 284.513549805 7.38463783264 155 0 Open ; +P-V-1176 1175 1176 230.808216095 14.8739995956 155 0 Open ; +P-V-1177 1176 1177 515.610229492 12.2251615524 155 0 Open ; +P-V-1178 1177 1178 564.644104004 6.47166752815 155 0 Open ; +P-V-1179 1178 1179 415.879074097 4.59353971481 155 0 Open ; +P-V-1180 1179 1180 731.024841309 13.6876115799 155 0 Open ; +P-V-1181 1180 1181 734.897827148 7.54647350311 155 0 Open ; +P-V-1182 1181 1182 629.257415771 5.59360361099 155 0 Open ; +P-V-1183 1182 1183 534.822113037 14.1081123352 155 0 Open ; +P-V-1184 1183 1184 702.541748047 3.39066025615 155 0 Open ; +P-V-1185 1184 1185 291.332313538 7.44566202164 155 0 Open ; +P-V-1186 1185 1186 512.457275391 8.3927936554 155 0 Open ; +P-V-1187 1186 1187 234.141029358 7.1659154892 155 0 Open ; +P-V-1188 1187 1188 627.087677002 8.2502450943 155 0 Open ; +P-V-1189 1188 1189 443.601654053 11.2628316879 155 0 Open ; +P-V-1190 1189 1190 671.401092529 11.759393692 155 0 Open ; +P-V-1191 1190 1191 357.281402588 11.5737905502 155 0 Open ; +P-V-1192 1191 1192 385.272598267 12.5331201553 155 0 Open ; +P-V-1193 1192 1193 757.366577148 12.2115716934 155 0 Open ; +P-V-1194 1193 1194 544.37789917 10.1917767525 155 0 Open ; +P-V-1195 1194 1195 609.55291748 6.12067604065 155 0 Open ; +P-V-1196 1195 1196 660.230926514 13.0287513733 155 0 Open ; +P-V-1197 1196 1197 261.557003021 6.7711288929 155 0 Open ; +P-V-1198 1197 1198 668.393585205 8.8205780983 155 0 Open ; +P-V-1199 1198 1199 322.741439819 5.30770254135 155 0 Open ; +P-V-1201 1200 1201 278.019363403 8.4278345108 155 0 Open ; +P-V-1202 1201 1202 281.013458252 6.86495518684 155 0 Open ; +P-V-1203 1202 1203 315.073989868 7.97213792801 155 0 Open ; +P-V-1204 1203 1204 736.263122559 10.4935326576 155 0 Open ; +P-V-1205 1204 1205 390.209335327 3.9650812149 155 0 Open ; +P-V-1206 1205 1206 606.029022217 9.60926818848 155 0 Open ; +P-V-1207 1206 1207 698.570129395 12.3754472733 155 0 Open ; +P-V-1208 1207 1208 257.614372253 13.4958953857 155 0 Open ; +P-V-1209 1208 1209 426.157958984 3.73912578821 155 0 Open ; +P-V-1210 1209 1210 324.361106873 9.74313211441 155 0 Open ; +P-V-1211 1210 1211 391.192382812 10.4062871933 155 0 Open ; +P-V-1212 1211 1212 273.671180725 10.8324322701 155 0 Open ; +P-V-1213 1212 1213 784.470581055 14.9451904297 155 0 Open ; +P-V-1214 1213 1214 340.851135254 8.70028781891 155 0 Open ; +P-V-1215 1214 1215 637.185455322 6.52408432961 155 0 Open ; +P-V-1216 1215 1216 664.352264404 6.37791180611 155 0 Open ; +P-V-1217 1216 1217 228.272108078 14.3864774704 155 0 Open ; +P-V-1218 1217 1218 626.475036621 6.32569742203 155 0 Open ; +P-V-1219 1218 1219 749.815795898 6.08799529076 155 0 Open ; +P-V-1220 1219 1220 797.005004883 4.26694893837 155 0 Open ; +P-V-1221 1220 1221 480.597198486 14.9443740845 155 0 Open ; +P-V-1222 1221 1222 254.871433258 3.48382437229 155 0 Open ; +P-V-1223 1222 1223 581.816131592 6.67742300034 155 0 Open ; +P-V-1224 1223 1224 522.546539307 3.80011546612 155 0 Open ; +P-V-1225 1224 1225 577.069824219 7.25326633453 155 0 Open ; +P-V-1226 1225 1226 232.362758636 9.41788434982 155 0 Open ; +P-V-1227 1226 1227 669.424224854 7.26542568207 155 0 Open ; +P-V-1228 1227 1228 250.611339569 11.4954824448 155 0 Open ; +P-V-1229 1228 1229 578.977874756 12.6242580414 155 0 Open ; +P-V-1230 1229 1230 545.586914062 8.59418869019 155 0 Open ; +P-V-1231 1230 1231 276.710601807 12.5024213791 155 0 Open ; +P-V-1232 1231 1232 760.382507324 5.98243832588 155 0 Open ; +P-V-1233 1232 1233 292.118759155 7.79975414276 155 0 Open ; +P-V-1234 1233 1234 473.643066406 5.37849116325 155 0 Open ; +P-V-1235 1234 1235 365.142318726 13.9401912689 155 0 Open ; +P-V-1236 1235 1236 590.183227539 11.1881837845 155 0 Open ; +P-V-1237 1236 1237 340.24961853 10.5094819069 155 0 Open ; +P-V-1238 1237 1238 593.182861328 11.491517067 155 0 Open ; +P-V-1239 1238 1239 246.743076324 7.21695280075 155 0 Open ; +P-V-1240 1239 1240 316.434898376 9.42620706558 155 0 Open ; +P-V-1241 1240 1241 463.484161377 10.5713272095 155 0 Open ; +P-V-1242 1241 1242 364.72795105 6.65695905685 155 0 Open ; +P-V-1243 1242 1243 725.546386719 8.174888134 155 0 Open ; +P-V-1244 1243 1244 717.409790039 9.12611818314 155 0 Open ; +P-V-1245 1244 1245 283.534996033 14.4519176483 155 0 Open ; +P-V-1246 1245 1246 419.137969971 8.04305648804 155 0 Open ; +P-V-1247 1246 1247 332.761184692 13.3438262939 155 0 Open ; +P-V-1248 1247 1248 434.877822876 6.83478283882 155 0 Open ; +P-V-1249 1248 1249 759.900939941 12.1150274277 155 0 Open ; +P-V-1251 1250 1251 413.410400391 14.777256012 155 0 Open ; +P-V-1252 1251 1252 217.278963089 3.15095472336 155 0 Open ; +P-V-1253 1252 1253 454.797134399 6.50972342491 155 0 Open ; +P-V-1254 1253 1254 596.180114746 10.9821925163 155 0 Open ; +P-V-1255 1254 1255 635.348052979 12.8901882172 155 0 Open ; +P-V-1256 1255 1256 219.931997299 6.94203352928 155 0 Open ; +P-V-1257 1256 1257 287.921699524 13.0009317398 155 0 Open ; +P-V-1258 1257 1258 283.183990479 4.46611404419 155 0 Open ; +P-V-1259 1258 1259 449.031509399 12.4567308426 155 0 Open ; +P-V-1260 1259 1260 764.171081543 7.47759819031 155 0 Open ; +P-V-1261 1260 1261 350.040115356 13.4866104126 155 0 Open ; +P-V-1262 1261 1262 423.402420044 13.4925498962 155 0 Open ; +P-V-1263 1262 1263 614.544189453 3.8882240653 155 0 Open ; +P-V-1264 1263 1264 219.08893013 11.5528650284 155 0 Open ; +P-V-1265 1264 1265 200.47274211 5.90754055977 155 0 Open ; +P-V-1266 1265 1266 351.749679565 12.1344861984 155 0 Open ; +P-V-1267 1266 1267 565.829467773 8.92048501968 155 0 Open ; +P-V-1268 1267 1268 279.715393066 14.5329723358 155 0 Open ; +P-V-1269 1268 1269 733.752990723 6.73967528343 155 0 Open ; +P-V-1270 1269 1270 636.116485596 7.20160341263 155 0 Open ; +P-V-1271 1270 1271 617.421600342 11.1033067703 155 0 Open ; +P-V-1272 1271 1272 414.040130615 10.4533400536 155 0 Open ; +P-V-1273 1272 1273 214.475016594 8.63223028183 155 0 Open ; +P-V-1274 1273 1274 444.830673218 4.38280534744 155 0 Open ; +P-V-1275 1274 1275 640.582244873 8.3237080574 155 0 Open ; +P-V-1276 1275 1276 378.224655151 7.43376207352 155 0 Open ; +P-V-1277 1276 1277 712.066650391 13.0849123001 155 0 Open ; +P-V-1278 1277 1278 656.578125 9.17772817612 155 0 Open ; +P-V-1279 1278 1279 454.03956604 3.86142510176 155 0 Open ; +P-V-1280 1279 1280 498.623718262 14.3807611465 155 0 Open ; +P-V-1281 1280 1281 623.076904297 4.07771658897 155 0 Open ; +P-V-1282 1281 1282 459.103088379 13.9144468307 155 0 Open ; +P-V-1283 1282 1283 555.772583008 12.3990163803 155 0 Open ; +P-V-1284 1283 1284 263.800796509 5.00036931038 155 0 Open ; +P-V-1285 1284 1285 610.55267334 6.17789697647 155 0 Open ; +P-V-1286 1285 1286 745.866271973 10.4965953827 155 0 Open ; +P-V-1287 1286 1287 563.810668945 14.3240251541 155 0 Open ; +P-V-1288 1287 1288 344.484771729 6.11249494553 155 0 Open ; +P-V-1289 1288 1289 385.172515869 14.890376091 155 0 Open ; +P-V-1290 1289 1290 477.485412598 12.9493703842 155 0 Open ; +P-V-1291 1290 1291 754.223327637 11.634346962 155 0 Open ; +P-V-1292 1291 1292 273.717056274 14.2516317368 155 0 Open ; +P-V-1293 1292 1293 708.904968262 6.32676625252 155 0 Open ; +P-V-1294 1293 1294 448.046646118 5.40074801445 155 0 Open ; +P-V-1295 1294 1295 468.712280273 3.94516557455 155 0 Open ; +P-V-1296 1295 1296 669.881530762 4.98483502865 155 0 Open ; +P-V-1297 1296 1297 756.065429688 6.83946490288 155 0 Open ; +P-V-1298 1297 1298 494.454711914 5.01199412346 155 0 Open ; +P-V-1299 1298 1299 779.279663086 10.0628948212 155 0 Open ; +P-V-1301 1300 1301 303.65007782 7.93748235703 155 0 Open ; +P-V-1302 1301 1302 413.524490356 5.12286543846 155 0 Open ; +P-V-1303 1302 1303 350.00491333 13.6512622833 155 0 Open ; +P-V-1304 1303 1304 788.165344238 8.90011358261 155 0 Open ; +P-V-1305 1304 1305 560.769195557 11.9611196518 155 0 Open ; +P-V-1306 1305 1306 677.092254639 4.80244123936 155 0 Open ; +P-V-1307 1306 1307 481.50088501 6.71077823639 155 0 Open ; +P-V-1308 1307 1308 352.501785278 12.9528236389 155 0 Open ; +P-V-1309 1308 1309 655.104675293 5.88548016548 155 0 Open ; +P-V-1310 1309 1310 413.294189453 11.7099924088 155 0 Open ; +P-V-1311 1310 1311 242.734558105 3.79509830475 155 0 Open ; +P-V-1312 1311 1312 560.860717773 6.71790575981 155 0 Open ; +P-V-1313 1312 1313 342.158355713 4.11329293251 155 0 Open ; +P-V-1314 1313 1314 355.713134766 12.4149456024 155 0 Open ; +P-V-1315 1314 1315 450.235641479 9.21372747421 155 0 Open ; +P-V-1316 1315 1316 706.099822998 11.3964061737 155 0 Open ; +P-V-1317 1316 1317 720.004943848 5.45630383492 155 0 Open ; +P-V-1318 1317 1318 354.997512817 11.8610620499 155 0 Open ; +P-V-1319 1318 1319 593.889923096 9.16977453232 155 0 Open ; +P-V-1320 1319 1320 369.767684937 8.70858287811 155 0 Open ; +P-V-1321 1320 1321 407.733413696 14.5135231018 155 0 Open ; +P-V-1322 1321 1322 588.959960938 8.00486183167 155 0 Open ; +P-V-1323 1322 1323 635.506011963 5.99335598946 155 0 Open ; +P-V-1324 1323 1324 466.861877441 5.94997835159 155 0 Open ; +P-V-1325 1324 1325 614.3777771 7.94953107834 155 0 Open ; +P-V-1326 1325 1326 338.819274902 9.71426773071 155 0 Open ; +P-V-1327 1326 1327 735.146789551 7.25775718689 155 0 Open ; +P-V-1328 1327 1328 406.662200928 14.4336996078 155 0 Open ; +P-V-1329 1328 1329 709.595123291 10.314438343 155 0 Open ; +P-V-1330 1329 1330 488.475738525 11.2401885986 155 0 Open ; +P-V-1331 1330 1331 242.734699249 3.84308964014 155 0 Open ; +P-V-1332 1331 1332 690.3465271 8.08974123001 155 0 Open ; +P-V-1333 1332 1333 564.288818359 7.04199266434 155 0 Open ; +P-V-1334 1333 1334 288.599662781 12.8925333023 155 0 Open ; +P-V-1335 1334 1335 390.157852173 10.6592879295 155 0 Open ; +P-V-1336 1335 1336 482.941711426 11.0311450958 155 0 Open ; +P-V-1337 1336 1337 373.064590454 12.9358062744 155 0 Open ; +P-V-1338 1337 1338 754.80657959 3.68780857325 155 0 Open ; +P-V-1339 1338 1339 399.969223022 8.65779733658 155 0 Open ; +P-V-1340 1339 1340 330.031570435 7.81335353851 155 0 Open ; +P-V-1341 1340 1341 501.563446045 6.53751826286 155 0 Open ; +P-V-1342 1341 1342 553.473571777 7.60963582993 155 0 Open ; +P-V-1343 1342 1343 307.335296631 10.6887288094 155 0 Open ; +P-V-1344 1343 1344 623.225067139 5.87868833542 155 0 Open ; +P-V-1345 1344 1345 705.931640625 14.8575868607 155 0 Open ; +P-V-1346 1345 1346 523.855529785 11.8016004562 155 0 Open ; +P-V-1347 1346 1347 425.065795898 8.61951446533 155 0 Open ; +P-V-1348 1347 1348 559.282104492 4.08781599998 155 0 Open ; +P-V-1349 1348 1349 546.208862305 13.6541366577 155 0 Open ; +P-V-1351 1350 1351 203.930747271 4.28143692017 155 0 Open ; +P-V-1352 1351 1352 655.571136475 6.68553614616 155 0 Open ; +P-V-1353 1352 1353 740.264282227 11.4433193207 155 0 Open ; +P-V-1354 1353 1354 543.187805176 6.15389299393 155 0 Open ; +P-V-1355 1354 1355 374.091384888 10.0766243935 155 0 Open ; +P-V-1356 1355 1356 441.363464355 14.9168043137 155 0 Open ; +P-V-1357 1356 1357 486.67868042 7.1771235466 155 0 Open ; +P-V-1358 1357 1358 445.623748779 6.96863365173 155 0 Open ; +P-V-1359 1358 1359 441.24382019 10.7006611824 155 0 Open ; +P-V-1360 1359 1360 451.076873779 3.98238998652 155 0 Open ; +P-V-1361 1360 1361 751.449035645 3.0774327144 155 0 Open ; +P-V-1362 1361 1362 470.586273193 9.87028026581 155 0 Open ; +P-V-1363 1362 1363 440.193099976 5.51195669174 155 0 Open ; +P-V-1364 1363 1364 322.83506012 12.7781591415 155 0 Open ; +P-V-1365 1364 1365 276.476699829 5.87680673599 155 0 Open ; +P-V-1366 1365 1366 324.637199402 6.5479683876 155 0 Open ; +P-V-1367 1366 1367 335.322006226 10.1375055313 155 0 Open ; +P-V-1368 1367 1368 603.048400879 3.68511414528 155 0 Open ; +P-V-1369 1368 1369 535.70980835 12.4988336563 155 0 Open ; +P-V-1370 1369 1370 745.298828125 11.7432136536 155 0 Open ; +P-V-1371 1370 1371 559.680145264 5.88689255714 155 0 Open ; +P-V-1372 1371 1372 400.285171509 6.86122107506 155 0 Open ; +P-V-1373 1372 1373 777.288452148 12.7440633774 155 0 Open ; +P-V-1374 1373 1374 423.5831604 14.2453050613 155 0 Open ; +P-V-1375 1374 1375 792.103271484 12.605345726 155 0 Open ; +P-V-1376 1375 1376 252.682189941 11.5925188065 155 0 Open ; +P-V-1377 1376 1377 522.919403076 9.12811803818 155 0 Open ; +P-V-1378 1377 1378 763.897155762 11.3941345215 155 0 Open ; +P-V-1379 1378 1379 610.9609375 11.4091501236 155 0 Open ; +P-V-1380 1379 1380 629.023193359 10.8616747856 155 0 Open ; +P-V-1381 1380 1381 758.611083984 10.5309462547 155 0 Open ; +P-V-1382 1381 1382 630.575408936 4.61825859547 155 0 Open ; +P-V-1383 1382 1383 503.65826416 14.6982183456 155 0 Open ; +P-V-1384 1383 1384 398.109085083 7.38905906677 155 0 Open ; +P-V-1385 1384 1385 345.841690063 6.22872471809 155 0 Open ; +P-V-1386 1385 1386 258.918292999 7.79439401627 155 0 Open ; +P-V-1387 1386 1387 769.326477051 12.4096851349 155 0 Open ; +P-V-1388 1387 1388 229.575155258 8.39327144623 155 0 Open ; +P-V-1389 1388 1389 635.821594238 4.07468867302 155 0 Open ; +P-V-1390 1389 1390 314.644012451 7.4376616478 155 0 Open ; +P-V-1391 1390 1391 389.29460144 8.4884147644 155 0 Open ; +P-V-1392 1391 1392 789.283691406 12.8139648438 155 0 Open ; +P-V-1393 1392 1393 366.014572144 7.13761615753 155 0 Open ; +P-V-1394 1393 1394 245.897689819 11.0507202148 155 0 Open ; +P-V-1395 1394 1395 622.790466309 3.79158604145 155 0 Open ; +P-V-1396 1395 1396 609.334899902 4.84623134136 155 0 Open ; +P-V-1397 1396 1397 680.541290283 12.1548576355 155 0 Open ; +P-V-1398 1397 1398 285.090278625 9.24872016907 155 0 Open ; +P-V-1399 1398 1399 711.710083008 13.2249126434 155 0 Open ; +P-V-1401 1400 1401 705.611541748 3.27368623018 155 0 Open ; +P-V-1402 1401 1402 392.229888916 11.159318924 155 0 Open ; +P-V-1403 1402 1403 684.072601318 11.1642551422 155 0 Open ; +P-V-1404 1403 1404 632.004486084 4.98634064198 155 0 Open ; +P-V-1405 1404 1405 221.378044128 13.0159139633 155 0 Open ; +P-V-1406 1405 1406 273.709960938 11.8675632477 155 0 Open ; +P-V-1407 1406 1407 656.853790283 5.83351922035 155 0 Open ; +P-V-1408 1407 1408 547.887329102 13.8448877335 155 0 Open ; +P-V-1409 1408 1409 301.345314026 13.2141742706 155 0 Open ; +P-V-1410 1409 1410 681.37890625 5.7136888504 155 0 Open ; +P-V-1411 1410 1411 648.567382812 4.43662011623 155 0 Open ; +P-V-1412 1411 1412 263.691761017 4.34826135635 155 0 Open ; +P-V-1413 1412 1413 411.464202881 8.57962703705 155 0 Open ; +P-V-1414 1413 1414 640.005371094 6.41210484505 155 0 Open ; +P-V-1415 1414 1415 762.450317383 5.04733228683 155 0 Open ; +P-V-1416 1415 1416 475.885253906 3.0737228319 155 0 Open ; +P-V-1417 1416 1417 352.983383179 6.83516693115 155 0 Open ; +P-V-1418 1417 1418 482.518005371 12.60293293 155 0 Open ; +P-V-1419 1418 1419 624.880859375 10.4574184418 155 0 Open ; +P-V-1420 1419 1420 641.786102295 4.98669433594 155 0 Open ; +P-V-1421 1420 1421 518.557800293 7.02143955231 155 0 Open ; +P-V-1422 1421 1422 416.76222229 13.4545497894 155 0 Open ; +P-V-1423 1422 1423 481.285888672 6.44631052017 155 0 Open ; +P-V-1424 1423 1424 707.236358643 9.43454837799 155 0 Open ; +P-V-1425 1424 1425 272.749176025 12.9095239639 155 0 Open ; +P-V-1426 1425 1426 268.8645401 3.12796132267 155 0 Open ; +P-V-1427 1426 1427 332.30380249 3.60366213322 155 0 Open ; +P-V-1428 1427 1428 487.513000488 11.6254863739 155 0 Open ; +P-V-1429 1428 1429 627.416625977 10.8285784721 155 0 Open ; +P-V-1430 1429 1430 545.72958374 8.54622793198 155 0 Open ; +P-V-1431 1430 1431 772.878051758 6.22182583809 155 0 Open ; +P-V-1432 1431 1432 461.377166748 10.3217868805 155 0 Open ; +P-V-1433 1432 1433 663.683013916 9.41058683395 155 0 Open ; +P-V-1434 1433 1434 536.563903809 11.588309288 155 0 Open ; +P-V-1435 1434 1435 586.059448242 5.03293895721 155 0 Open ; +P-V-1436 1435 1436 380.233139038 10.5683684349 155 0 Open ; +P-V-1437 1436 1437 278.652023315 5.09201359749 155 0 Open ; +P-V-1438 1437 1438 223.650947571 9.02936840057 155 0 Open ; +P-V-1439 1438 1439 579.930297852 8.77447748184 155 0 Open ; +P-V-1440 1439 1440 582.424926758 7.31193494797 155 0 Open ; +P-V-1441 1440 1441 334.497634888 9.03848409653 155 0 Open ; +P-V-1442 1441 1442 440.538619995 13.6564350128 155 0 Open ; +P-V-1443 1442 1443 335.016921997 3.58912163973 155 0 Open ; +P-V-1444 1443 1444 268.3748703 6.52955460548 155 0 Open ; +P-V-1445 1444 1445 461.190612793 7.61519479752 155 0 Open ; +P-V-1446 1445 1446 778.837158203 5.33598923683 155 0 Open ; +P-V-1447 1446 1447 648.563903809 3.27337116003 155 0 Open ; +P-V-1448 1447 1448 727.465393066 5.21801280975 155 0 Open ; +P-V-1449 1448 1449 507.143798828 10.3195967674 155 0 Open ; +P-V-1451 1450 1451 622.916259766 10.07670784 155 0 Open ; +P-V-1452 1451 1452 511.420410156 7.86394023895 155 0 Open ; +P-V-1453 1452 1453 412.159790039 14.3929405212 155 0 Open ; +P-V-1454 1453 1454 658.272705078 14.7938432693 155 0 Open ; +P-V-1455 1454 1455 356.421401978 10.4931926727 155 0 Open ; +P-V-1456 1455 1456 704.924072266 12.1821641922 155 0 Open ; +P-V-1457 1456 1457 431.945465088 5.15169119835 155 0 Open ; +P-V-1458 1457 1458 573.785461426 7.24608373642 155 0 Open ; +P-V-1459 1458 1459 796.673034668 12.6781682968 155 0 Open ; +P-V-1460 1459 1460 249.431690216 10.9690403938 155 0 Open ; +P-V-1461 1460 1461 383.332855225 8.50890541077 155 0 Open ; +P-V-1462 1461 1462 608.588928223 6.09311699867 155 0 Open ; +P-V-1463 1462 1463 300.84286499 12.3222837448 155 0 Open ; +P-V-1464 1463 1464 581.352081299 6.69030785561 155 0 Open ; +P-V-1465 1464 1465 550.232940674 10.3028168678 155 0 Open ; +P-V-1466 1465 1466 321.941726685 12.4929552078 155 0 Open ; +P-V-1467 1466 1467 605.562194824 8.67754125595 155 0 Open ; +P-V-1468 1467 1468 722.012634277 8.33818101883 155 0 Open ; +P-V-1469 1468 1469 540.670135498 11.8610982895 155 0 Open ; +P-V-1470 1469 1470 624.459747314 12.9017829895 155 0 Open ; +P-V-1471 1470 1471 364.156173706 6.45688891411 155 0 Open ; +P-V-1472 1471 1472 596.562744141 7.60515832901 155 0 Open ; +P-V-1473 1472 1473 745.230895996 12.9165430069 155 0 Open ; +P-V-1474 1473 1474 767.267211914 4.2023870945 155 0 Open ; +P-V-1475 1474 1475 225.976547241 10.7569642067 155 0 Open ; +P-V-1476 1475 1476 365.019699097 8.72280550003 155 0 Open ; +P-V-1477 1476 1477 359.965759277 13.8933706284 155 0 Open ; +P-V-1478 1477 1478 244.641040802 8.6400642395 155 0 Open ; +P-V-1479 1478 1479 428.194046021 4.149294734 155 0 Open ; +P-V-1480 1479 1480 609.81137085 8.9987282753 155 0 Open ; +P-V-1481 1480 1481 631.242736816 12.9391565323 155 0 Open ; +P-V-1482 1481 1482 570.609039307 7.51919460297 155 0 Open ; +P-V-1483 1482 1483 505.209838867 8.23907613754 155 0 Open ; +P-V-1484 1483 1484 657.776672363 4.05123066902 155 0 Open ; +P-V-1485 1484 1485 401.763549805 11.803393364 155 0 Open ; +P-V-1486 1485 1486 731.551086426 10.5870985985 155 0 Open ; +P-V-1487 1486 1487 418.782897949 8.68889045715 155 0 Open ; +P-V-1488 1487 1488 659.310760498 3.72296875715 155 0 Open ; +P-V-1489 1488 1489 546.834472656 7.94476556778 155 0 Open ; +P-V-1490 1489 1490 533.856384277 13.4861555099 155 0 Open ; +P-V-1491 1490 1491 641.557006836 11.9711818695 155 0 Open ; +P-V-1492 1491 1492 733.116394043 8.75869417191 155 0 Open ; +P-V-1493 1492 1493 518.6824646 12.930519104 155 0 Open ; +P-V-1494 1493 1494 512.465484619 11.1477384567 155 0 Open ; +P-V-1495 1494 1495 551.827453613 6.28417062759 155 0 Open ; +P-V-1496 1495 1496 652.869567871 10.5799517632 155 0 Open ; +P-V-1497 1496 1497 412.864700317 11.3440961838 155 0 Open ; +P-V-1498 1497 1498 561.96383667 5.52862024307 155 0 Open ; +P-V-1499 1498 1499 526.127105713 7.37308359146 155 0 Open ; +P-V-1501 1500 1501 721.187561035 6.98267412186 155 0 Open ; +P-V-1502 1501 1502 240.340736389 3.13480056822 155 0 Open ; +P-V-1503 1502 1503 679.660675049 4.14416694641 155 0 Open ; +P-V-1504 1503 1504 500.709533691 7.49706697464 155 0 Open ; +P-V-1505 1504 1505 510.348175049 7.43164873123 155 0 Open ; +P-V-1506 1505 1506 736.003601074 7.26122760773 155 0 Open ; +P-V-1507 1506 1507 322.875389099 14.3353719711 155 0 Open ; +P-V-1508 1507 1508 279.998466492 13.6849679947 155 0 Open ; +P-V-1509 1508 1509 313.323402405 7.52944135666 155 0 Open ; +P-V-1510 1509 1510 715.951904297 11.0798540115 155 0 Open ; +P-V-1511 1510 1511 505.451660156 5.5255317688 155 0 Open ; +P-V-1512 1511 1512 330.690200806 13.2055616379 155 0 Open ; +P-V-1513 1512 1513 643.882904053 13.8020858765 155 0 Open ; +P-V-1514 1513 1514 333.145996094 10.6972751617 155 0 Open ; +P-V-1515 1514 1515 605.310394287 8.03949022293 155 0 Open ; +P-V-1516 1515 1516 335.671844482 7.7382516861 155 0 Open ; +P-V-1517 1516 1517 390.196014404 11.4895877838 155 0 Open ; +P-V-1518 1517 1518 424.975357056 14.2169809341 155 0 Open ; +P-V-1519 1518 1519 390.538146973 6.49626803398 155 0 Open ; +P-V-1520 1519 1520 688.975189209 3.12620291114 155 0 Open ; +P-V-1521 1520 1521 654.627380371 13.4480409622 155 0 Open ; +P-V-1522 1521 1522 411.203216553 4.8471237421 155 0 Open ; +P-V-1523 1522 1523 230.515663147 12.5350427628 155 0 Open ; +P-V-1524 1523 1524 574.058135986 14.9033546448 155 0 Open ; +P-V-1525 1524 1525 584.662658691 3.51220470667 155 0 Open ; +P-V-1526 1525 1526 431.231719971 5.22723531723 155 0 Open ; +P-V-1527 1526 1527 457.193450928 8.00456285477 155 0 Open ; +P-V-1528 1527 1528 384.25138855 5.26264739037 155 0 Open ; +P-V-1529 1528 1529 215.840251923 11.542473793 155 0 Open ; +P-V-1530 1529 1530 468.094787598 12.386847496 155 0 Open ; +P-V-1531 1530 1531 237.278179169 5.68777871132 155 0 Open ; +P-V-1532 1531 1532 475.052398682 11.120675087 155 0 Open ; +P-V-1533 1532 1533 609.367279053 3.72485333681 155 0 Open ; +P-V-1534 1533 1534 330.50970459 12.5302877426 155 0 Open ; +P-V-1535 1534 1535 777.528930664 9.57765388489 155 0 Open ; +P-V-1536 1535 1536 531.368041992 5.05327248573 155 0 Open ; +P-V-1537 1536 1537 667.660980225 14.5606126785 155 0 Open ; +P-V-1538 1537 1538 561.559204102 13.5130214691 155 0 Open ; +P-V-1539 1538 1539 418.048049927 13.6714897156 155 0 Open ; +P-V-1540 1539 1540 386.771728516 12.4452056885 155 0 Open ; +P-V-1541 1540 1541 678.874786377 3.9751843214 155 0 Open ; +P-V-1542 1541 1542 696.111999512 14.0884494781 155 0 Open ; +P-V-1543 1542 1543 378.992889404 13.6680707932 155 0 Open ; +P-V-1544 1543 1544 514.041809082 13.0225515366 155 0 Open ; +P-V-1545 1544 1545 451.641586304 13.8073139191 155 0 Open ; +P-V-1546 1545 1546 526.035400391 12.5439825058 155 0 Open ; +P-V-1547 1546 1547 285.663352966 9.87864494324 155 0 Open ; +P-V-1548 1547 1548 269.767539978 6.66135859489 155 0 Open ; +P-V-1549 1548 1549 222.782741547 5.19100856781 155 0 Open ; +P-V-1551 1550 1551 614.215179443 13.2873506546 155 0 Open ; +P-V-1552 1551 1552 375.519500732 10.126142025 155 0 Open ; +P-V-1553 1552 1553 653.37677002 13.0754652023 155 0 Open ; +P-V-1554 1553 1554 517.531097412 9.89799547195 155 0 Open ; +P-V-1555 1554 1555 330.89982605 11.6693687439 155 0 Open ; +P-V-1556 1555 1556 304.741088867 14.6702518463 155 0 Open ; +P-V-1557 1556 1557 296.113876343 6.7183163166 155 0 Open ; +P-V-1558 1557 1558 687.052337646 4.78440189362 155 0 Open ; +P-V-1559 1558 1559 322.172698975 6.12981891632 155 0 Open ; +P-V-1560 1559 1560 543.407348633 7.95802640915 155 0 Open ; +P-V-1561 1560 1561 277.656089783 6.31872391701 155 0 Open ; +P-V-1562 1561 1562 289.876609802 10.1258416176 155 0 Open ; +P-V-1563 1562 1563 401.248733521 6.75241398811 155 0 Open ; +P-V-1564 1563 1564 540.955505371 11.7833967209 155 0 Open ; +P-V-1565 1564 1565 727.793151855 7.38978147507 155 0 Open ; +P-V-1566 1565 1566 353.020812988 7.41771459579 155 0 Open ; +P-V-1567 1566 1567 426.54057312 12.3466901779 155 0 Open ; +P-V-1568 1567 1568 690.925598145 10.7382130623 155 0 Open ; +P-V-1569 1568 1569 207.354615688 3.18071772158 155 0 Open ; +P-V-1570 1569 1570 266.142097473 12.0046596527 155 0 Open ; +P-V-1571 1570 1571 666.018127441 14.3465557098 155 0 Open ; +P-V-1572 1571 1572 678.004394531 11.4048395157 155 0 Open ; +P-V-1573 1572 1573 607.084381104 4.34674906731 155 0 Open ; +P-V-1574 1573 1574 340.610534668 11.8280982971 155 0 Open ; +P-V-1575 1574 1575 492.182037354 9.07066774368 155 0 Open ; +P-V-1576 1575 1576 485.672088623 4.81462967396 155 0 Open ; +P-V-1577 1576 1577 524.0597229 8.44192695618 155 0 Open ; +P-V-1578 1577 1578 723.307250977 11.4924516678 155 0 Open ; +P-V-1579 1578 1579 431.673110962 9.60467767715 155 0 Open ; +P-V-1580 1579 1580 441.013793945 5.37982749939 155 0 Open ; +P-V-1581 1580 1581 288.025947571 12.0448150635 155 0 Open ; +P-V-1582 1581 1582 210.421960831 14.2379360199 155 0 Open ; +P-V-1583 1582 1583 599.976959229 3.26714017987 155 0 Open ; +P-V-1584 1583 1584 291.267478943 9.65019464493 155 0 Open ; +P-V-1585 1584 1585 290.992630005 13.265540123 155 0 Open ; +P-V-1586 1585 1586 646.901489258 8.47285985947 155 0 Open ; +P-V-1587 1586 1587 317.938438416 10.8276200294 155 0 Open ; +P-V-1588 1587 1588 340.738983154 7.0053319931 155 0 Open ; +P-V-1589 1588 1589 680.73727417 6.0278429985 155 0 Open ; +P-V-1590 1589 1590 647.85244751 4.12457096577 155 0 Open ; +P-V-1591 1590 1591 233.228740692 12.5087633133 155 0 Open ; +P-V-1592 1591 1592 689.585876465 4.39944028854 155 0 Open ; +P-V-1593 1592 1593 219.676765442 5.14796495438 155 0 Open ; +P-V-1594 1593 1594 442.400344849 3.45007202029 155 0 Open ; +P-V-1595 1594 1595 418.025558472 6.11149907112 155 0 Open ; +P-V-1596 1595 1596 748.372375488 12.9057569504 155 0 Open ; +P-V-1597 1596 1597 703.073120117 14.0034646988 155 0 Open ; +P-V-1598 1597 1598 361.538894653 14.6827926636 155 0 Open ; +P-V-1599 1598 1599 635.124633789 9.79470396042 155 0 Open ; +P-V-1601 1600 1601 529.615081787 3.8217716217 155 0 Open ; +P-V-1602 1601 1602 775.820129395 11.1977205276 155 0 Open ; +P-V-1603 1602 1603 555.326751709 6.52914834023 155 0 Open ; +P-V-1604 1603 1604 719.785583496 3.73500472307 155 0 Open ; +P-V-1605 1604 1605 461.230285645 8.94569253922 155 0 Open ; +P-V-1606 1605 1606 463.026611328 12.7691774368 155 0 Open ; +P-V-1607 1606 1607 528.399047852 3.05351057276 155 0 Open ; +P-V-1608 1607 1608 767.609863281 11.3719186783 155 0 Open ; +P-V-1609 1608 1609 541.891174316 14.3017301559 155 0 Open ; +P-V-1610 1609 1610 208.706179619 13.4952545166 155 0 Open ; +P-V-1611 1610 1611 487.331207275 10.5186667442 155 0 Open ; +P-V-1612 1611 1612 511.380737305 6.52667999268 155 0 Open ; +P-V-1613 1612 1613 445.537918091 14.1167535782 155 0 Open ; +P-V-1614 1613 1614 764.75189209 10.7028107643 155 0 Open ; +P-V-1615 1614 1615 457.240112305 11.692738533 155 0 Open ; +P-V-1616 1615 1616 743.22088623 9.28793621063 155 0 Open ; +P-V-1617 1616 1617 667.422424316 6.38734912872 155 0 Open ; +P-V-1618 1617 1618 359.087387085 6.63729858398 155 0 Open ; +P-V-1619 1618 1619 403.936904907 10.3535776138 155 0 Open ; +P-V-1620 1619 1620 379.118148804 7.77306175232 155 0 Open ; +P-V-1621 1620 1621 242.440731049 13.0281648636 155 0 Open ; +P-V-1622 1621 1622 368.688262939 5.87466049194 155 0 Open ; +P-V-1623 1622 1623 320.986221313 3.31021937728 155 0 Open ; +P-V-1624 1623 1624 492.85848999 8.46084880829 155 0 Open ; +P-V-1625 1624 1625 424.495407104 8.88602113724 155 0 Open ; +P-V-1626 1625 1626 718.137329102 13.6849737167 155 0 Open ; +P-V-1627 1626 1627 318.343231201 14.8961877823 155 0 Open ; +P-V-1628 1627 1628 561.205566406 14.6437454224 155 0 Open ; +P-V-1629 1628 1629 222.357749939 6.33397388458 155 0 Open ; +P-V-1630 1629 1630 505.107025146 9.68214988708 155 0 Open ; +P-V-1631 1630 1631 744.597595215 4.04255533218 155 0 Open ; +P-V-1632 1631 1632 311.378501892 13.7704954147 155 0 Open ; +P-V-1633 1632 1633 786.483398438 7.53052425385 155 0 Open ; +P-V-1634 1633 1634 425.964569092 10.7323322296 155 0 Open ; +P-V-1635 1634 1635 665.410949707 14.2419204712 155 0 Open ; +P-V-1636 1635 1636 347.773742676 7.66920423508 155 0 Open ; +P-V-1637 1636 1637 566.042175293 8.41662216187 155 0 Open ; +P-V-1638 1637 1638 458.593933105 10.7655572891 155 0 Open ; +P-V-1639 1638 1639 386.070953369 4.89039981365 155 0 Open ; +P-V-1640 1639 1640 597.484130859 5.31957221031 155 0 Open ; +P-V-1641 1640 1641 652.503143311 7.40798950195 155 0 Open ; +P-V-1642 1641 1642 653.838806152 12.3798084259 155 0 Open ; +P-V-1643 1642 1643 322.012809753 12.3869857788 155 0 Open ; +P-V-1644 1643 1644 354.152481079 3.81588810682 155 0 Open ; +P-V-1645 1644 1645 631.570892334 3.23827646673 155 0 Open ; +P-V-1646 1645 1646 635.630462646 11.8271150589 155 0 Open ; +P-V-1647 1646 1647 266.581474304 3.69754564762 155 0 Open ; +P-V-1648 1647 1648 782.475891113 4.43549859524 155 0 Open ; +P-V-1649 1648 1649 521.292022705 14.1022853851 155 0 Open ; +P-V-1651 1650 1651 605.56060791 8.14372014999 155 0 Open ; +P-V-1652 1651 1652 325.539985657 10.0103650093 155 0 Open ; +P-V-1653 1652 1653 560.260223389 8.87336921692 155 0 Open ; +P-V-1654 1653 1654 286.050697327 8.0826010704 155 0 Open ; +P-V-1655 1654 1655 563.925750732 5.00763940811 155 0 Open ; +P-V-1656 1655 1656 719.910461426 9.6954574585 155 0 Open ; +P-V-1657 1656 1657 527.635620117 10.4322156906 155 0 Open ; +P-V-1658 1657 1658 462.541473389 5.69118404388 155 0 Open ; +P-V-1659 1658 1659 336.437194824 12.9997749329 155 0 Open ; +P-V-1660 1659 1660 511.125427246 4.70809912682 155 0 Open ; +P-V-1661 1660 1661 401.198928833 14.0100250244 155 0 Open ; +P-V-1662 1661 1662 474.982788086 11.7212076187 155 0 Open ; +P-V-1663 1662 1663 667.572418213 8.79802656174 155 0 Open ; +P-V-1664 1663 1664 571.908294678 12.2574586868 155 0 Open ; +P-V-1665 1664 1665 706.013702393 6.45502495766 155 0 Open ; +P-V-1666 1665 1666 230.205734253 4.35598862171 155 0 Open ; +P-V-1667 1666 1667 305.015304565 10.845284462 155 0 Open ; +P-V-1668 1667 1668 784.799133301 5.37804675102 155 0 Open ; +P-V-1669 1668 1669 591.758758545 12.7919540405 155 0 Open ; +P-V-1670 1669 1670 469.229797363 9.90910625458 155 0 Open ; +P-V-1671 1670 1671 667.78024292 6.66058158875 155 0 Open ; +P-V-1672 1671 1672 769.81463623 8.5023522377 155 0 Open ; +P-V-1673 1672 1673 502.094848633 5.16581869125 155 0 Open ; +P-V-1674 1673 1674 445.921173096 10.9453039169 155 0 Open ; +P-V-1675 1674 1675 236.365707397 10.969769001 155 0 Open ; +P-V-1676 1675 1676 395.658599854 11.6828842163 155 0 Open ; +P-V-1677 1676 1677 262.271110535 6.81194758415 155 0 Open ; +P-V-1678 1677 1678 770.177307129 10.4020299911 155 0 Open ; +P-V-1679 1678 1679 295.671165466 13.9065093994 155 0 Open ; +P-V-1680 1679 1680 485.869903564 11.3137550354 155 0 Open ; +P-V-1681 1680 1681 264.282043457 10.7659749985 155 0 Open ; +P-V-1682 1681 1682 737.083618164 10.2863645554 155 0 Open ; +P-V-1683 1682 1683 296.184585571 6.48790740967 155 0 Open ; +P-V-1684 1683 1684 263.101081848 9.79812574387 155 0 Open ; +P-V-1685 1684 1685 404.876022339 14.0308389664 155 0 Open ; +P-V-1686 1685 1686 565.814575195 3.91464543343 155 0 Open ; +P-V-1687 1686 1687 222.327903748 8.30163288116 155 0 Open ; +P-V-1688 1687 1688 427.344024658 6.42141962051 155 0 Open ; +P-V-1689 1688 1689 789.962219238 12.9005365372 155 0 Open ; +P-V-1690 1689 1690 516.457336426 8.97057676315 155 0 Open ; +P-V-1691 1690 1691 374.412216187 9.9225525856 155 0 Open ; +P-V-1692 1691 1692 567.246429443 5.22527265549 155 0 Open ; +P-V-1693 1692 1693 607.992736816 9.67949151993 155 0 Open ; +P-V-1694 1693 1694 310.579292297 9.12385988235 155 0 Open ; +P-V-1695 1694 1695 785.610656738 14.182551384 155 0 Open ; +P-V-1696 1695 1696 257.205463409 8.04581785202 155 0 Open ; +P-V-1697 1696 1697 253.173229218 8.64923715591 155 0 Open ; +P-V-1698 1697 1698 336.676269531 9.36425304413 155 0 Open ; +P-V-1699 1698 1699 600.159240723 4.53305447102 155 0 Open ; +P-V-1701 1700 1701 302.311225891 13.8970813751 155 0 Open ; +P-V-1702 1701 1702 363.178405762 13.7874155045 155 0 Open ; +P-V-1703 1702 1703 605.144622803 12.3148326874 155 0 Open ; +P-V-1704 1703 1704 320.173713684 6.19400596619 155 0 Open ; +P-V-1705 1704 1705 483.060516357 14.9582128525 155 0 Open ; +P-V-1706 1705 1706 484.679260254 7.09235858917 155 0 Open ; +P-V-1707 1706 1707 613.917663574 9.28832817078 155 0 Open ; +P-V-1708 1707 1708 396.801467896 11.8482341766 155 0 Open ; +P-V-1709 1708 1709 613.556213379 7.79174041748 155 0 Open ; +P-V-1710 1709 1710 339.337188721 3.80405712128 155 0 Open ; +P-V-1711 1710 1711 289.427223206 3.06708528101 155 0 Open ; +P-V-1712 1711 1712 775.117492676 14.9937648773 155 0 Open ; +P-V-1713 1712 1713 360.421096802 10.9456920624 155 0 Open ; +P-V-1714 1713 1714 562.349609375 3.20880411565 155 0 Open ; +P-V-1715 1714 1715 468.538665771 5.58878231049 155 0 Open ; +P-V-1716 1715 1716 683.243774414 8.57252597809 155 0 Open ; +P-V-1717 1716 1717 672.531860352 7.86576938629 155 0 Open ; +P-V-1718 1717 1718 749.567077637 6.47654485703 155 0 Open ; +P-V-1719 1718 1719 314.401519775 9.92834234238 155 0 Open ; +P-V-1720 1719 1720 632.878295898 10.7169284821 155 0 Open ; +P-V-1721 1720 1721 321.106491089 7.73541975021 155 0 Open ; +P-V-1722 1721 1722 410.330169678 11.3849487305 155 0 Open ; +P-V-1723 1722 1723 691.786315918 12.0556678772 155 0 Open ; +P-V-1724 1723 1724 330.684143066 11.1711435318 155 0 Open ; +P-V-1725 1724 1725 420.942855835 14.7322130203 155 0 Open ; +P-V-1726 1725 1726 765.651367188 13.0505132675 155 0 Open ; +P-V-1727 1726 1727 548.973846436 7.07377290726 155 0 Open ; +P-V-1728 1727 1728 595.17376709 8.71333312988 155 0 Open ; +P-V-1729 1728 1729 799.688903809 6.4255566597 155 0 Open ; +P-V-1730 1729 1730 666.504302979 9.76105213165 155 0 Open ; +P-V-1731 1730 1731 449.903198242 5.4650080204 155 0 Open ; +P-V-1732 1731 1732 469.622375488 9.87070798874 155 0 Open ; +P-V-1733 1732 1733 799.761535645 6.85012102127 155 0 Open ; +P-V-1734 1733 1734 449.273742676 9.87297964096 155 0 Open ; +P-V-1735 1734 1735 308.218566895 7.59059286118 155 0 Open ; +P-V-1736 1735 1736 504.848846436 6.89716887474 155 0 Open ; +P-V-1737 1736 1737 385.95463562 13.790640831 155 0 Open ; +P-V-1738 1737 1738 315.694915771 12.6904172897 155 0 Open ; +P-V-1739 1738 1739 342.799331665 3.56660187244 155 0 Open ; +P-V-1740 1739 1740 543.889984131 14.1816616058 155 0 Open ; +P-V-1741 1740 1741 710.062683105 11.4730672836 155 0 Open ; +P-V-1742 1741 1742 342.2109375 9.78695631027 155 0 Open ; +P-V-1743 1742 1743 618.91015625 7.46563339233 155 0 Open ; +P-V-1744 1743 1744 495.28125 6.84459638596 155 0 Open ; +P-V-1745 1744 1745 606.787322998 12.4896335602 155 0 Open ; +P-V-1746 1745 1746 214.051245689 10.1858925819 155 0 Open ; +P-V-1747 1746 1747 464.571075439 3.92249166965 155 0 Open ; +P-V-1748 1747 1748 215.876520157 11.733672142 155 0 Open ; +P-V-1749 1748 1749 341.339447021 4.84207320213 155 0 Open ; +P-V-1751 1750 1751 786.263061523 5.47563385963 155 0 Open ; +P-V-1752 1751 1752 398.863250732 8.89570903778 155 0 Open ; +P-V-1753 1752 1753 459.386474609 13.1705961227 155 0 Open ; +P-V-1754 1753 1754 660.587219238 12.784409523 155 0 Open ; +P-V-1755 1754 1755 729.434020996 6.94501590729 155 0 Open ; +P-V-1756 1755 1756 394.025314331 14.6698741913 155 0 Open ; +P-V-1757 1756 1757 579.098937988 5.32538557053 155 0 Open ; +P-V-1758 1757 1758 737.871520996 11.1395273209 155 0 Open ; +P-V-1759 1758 1759 252.454078674 6.91379094124 155 0 Open ; +P-V-1760 1759 1760 554.182983398 6.07359719276 155 0 Open ; +P-V-1761 1760 1761 697.441253662 4.90986454487 155 0 Open ; +P-V-1762 1761 1762 754.725830078 12.5345020294 155 0 Open ; +P-V-1763 1762 1763 718.939086914 7.19423294067 155 0 Open ; +P-V-1764 1763 1764 423.966384888 11.0627717972 155 0 Open ; +P-V-1765 1764 1765 550.841705322 10.9351677895 155 0 Open ; +P-V-1766 1765 1766 718.671325684 13.1842556 155 0 Open ; +P-V-1767 1766 1767 739.659179688 12.0369520187 155 0 Open ; +P-V-1768 1767 1768 203.030062199 13.525103569 155 0 Open ; +P-V-1769 1768 1769 371.28767395 3.63941961527 155 0 Open ; +P-V-1770 1769 1770 536.277038574 11.1749219894 155 0 Open ; +P-V-1771 1770 1771 596.069549561 9.82218408585 155 0 Open ; +P-V-1772 1771 1772 222.444602966 11.5289297104 155 0 Open ; +P-V-1773 1772 1773 486.123016357 12.3949041367 155 0 Open ; +P-V-1774 1773 1774 407.793518066 10.7168254852 155 0 Open ; +P-V-1775 1774 1775 234.351184845 5.80778861046 155 0 Open ; +P-V-1776 1775 1776 525.333648682 4.65070152283 155 0 Open ; +P-V-1777 1776 1777 766.959594727 8.80405902863 155 0 Open ; +P-V-1778 1777 1778 241.113414764 10.8634142876 155 0 Open ; +P-V-1779 1778 1779 420.28414917 9.31718349457 155 0 Open ; +P-V-1780 1779 1780 645.122375488 10.4408259392 155 0 Open ; +P-V-1781 1780 1781 498.112213135 10.4368691444 155 0 Open ; +P-V-1782 1781 1782 772.949279785 6.18047070503 155 0 Open ; +P-V-1783 1782 1783 508.766387939 3.73767358065 155 0 Open ; +P-V-1784 1783 1784 304.015693665 10.8369941711 155 0 Open ; +P-V-1785 1784 1785 417.876327515 3.95467782021 155 0 Open ; +P-V-1786 1785 1786 263.536323547 12.0998268127 155 0 Open ; +P-V-1787 1786 1787 239.780269623 6.74013018608 155 0 Open ; +P-V-1788 1787 1788 418.459671021 8.03903770447 155 0 Open ; +P-V-1789 1788 1789 555.347869873 13.6358041763 155 0 Open ; +P-V-1790 1789 1790 398.442886353 11.5917701721 155 0 Open ; +P-V-1791 1790 1791 494.519866943 14.9079523087 155 0 Open ; +P-V-1792 1791 1792 248.00428772 11.162484169 155 0 Open ; +P-V-1793 1792 1793 344.274291992 7.36186647415 155 0 Open ; +P-V-1794 1793 1794 294.471343994 6.59836244583 155 0 Open ; +P-V-1795 1794 1795 684.015808105 4.07461369038 155 0 Open ; +P-V-1796 1795 1796 251.668346405 6.79834055901 155 0 Open ; +P-V-1797 1796 1797 735.509033203 9.00538349152 155 0 Open ; +P-V-1798 1797 1798 224.431112289 7.27419137955 155 0 Open ; +P-V-1799 1798 1799 416.805740356 4.08100128174 155 0 Open ; +P-V-1801 1800 1801 219.438489914 9.0535902977 155 0 Open ; +P-V-1802 1801 1802 534.973754883 5.07599616051 155 0 Open ; +P-V-1803 1802 1803 563.5809021 9.08733987808 155 0 Open ; +P-V-1804 1803 1804 696.148742676 14.4433441162 155 0 Open ; +P-V-1805 1804 1805 414.456359863 6.36421632767 155 0 Open ; +P-V-1806 1805 1806 719.334716797 8.16994428635 155 0 Open ; +P-V-1807 1806 1807 762.969482422 11.5675401688 155 0 Open ; +P-V-1808 1807 1808 532.775482178 10.1533498764 155 0 Open ; +P-V-1809 1808 1809 717.571411133 3.46222087741 155 0 Open ; +P-V-1810 1809 1810 427.31451416 8.4998998642 155 0 Open ; +P-V-1811 1810 1811 240.953205109 5.01116919518 155 0 Open ; +P-V-1812 1811 1812 686.115325928 13.8126401901 155 0 Open ; +P-V-1813 1812 1813 202.594973564 11.2743988037 155 0 Open ; +P-V-1814 1813 1814 791.394836426 14.454407692 155 0 Open ; +P-V-1815 1814 1815 711.844940186 10.5618486404 155 0 Open ; +P-V-1816 1815 1816 799.952514648 11.0307312012 155 0 Open ; +P-V-1817 1816 1817 625.470458984 4.65395915508 155 0 Open ; +P-V-1818 1817 1818 504.510864258 13.2870254517 155 0 Open ; +P-V-1819 1818 1819 702.100585938 11.0951128006 155 0 Open ; +P-V-1820 1819 1820 728.082702637 8.72448921204 155 0 Open ; +P-V-1821 1820 1821 574.431732178 8.48699808121 155 0 Open ; +P-V-1822 1821 1822 799.005615234 4.74531710148 155 0 Open ; +P-V-1823 1822 1823 477.225341797 9.52754306793 155 0 Open ; +P-V-1824 1823 1824 420.935516357 12.2661552429 155 0 Open ; +P-V-1825 1824 1825 214.106729507 4.83591103554 155 0 Open ; +P-V-1826 1825 1826 407.875427246 14.2483329773 155 0 Open ; +P-V-1827 1826 1827 336.985015869 5.14294266701 155 0 Open ; +P-V-1828 1827 1828 421.847579956 6.8452630043 155 0 Open ; +P-V-1829 1828 1829 566.867340088 9.79044342041 155 0 Open ; +P-V-1830 1829 1830 548.844543457 11.6083087921 155 0 Open ; +P-V-1831 1830 1831 592.935455322 12.32335186 155 0 Open ; +P-V-1832 1831 1832 279.155601501 6.36379575729 155 0 Open ; +P-V-1833 1832 1833 365.88961792 13.1350889206 155 0 Open ; +P-V-1834 1833 1834 222.134914398 3.42998528481 155 0 Open ; +P-V-1835 1834 1835 338.120162964 14.7129106522 155 0 Open ; +P-V-1836 1835 1836 745.067504883 5.98810982704 155 0 Open ; +P-V-1837 1836 1837 258.189804077 14.9211988449 155 0 Open ; +P-V-1838 1837 1838 580.332092285 11.8332548141 155 0 Open ; +P-V-1839 1838 1839 626.31262207 11.7292585373 155 0 Open ; +P-V-1840 1839 1840 232.387054443 5.58457589149 155 0 Open ; +P-V-1841 1840 1841 748.290344238 9.32945108414 155 0 Open ; +P-V-1842 1841 1842 754.32434082 9.58344602585 155 0 Open ; +P-V-1843 1842 1843 599.357208252 10.9285640717 155 0 Open ; +P-V-1844 1843 1844 569.09777832 3.52493697405 155 0 Open ; +P-V-1845 1844 1845 330.802001953 14.7842493057 155 0 Open ; +P-V-1846 1845 1846 694.062072754 9.02566099167 155 0 Open ; +P-V-1847 1846 1847 464.327819824 6.16053724289 155 0 Open ; +P-V-1848 1847 1848 557.470153809 7.02238559723 155 0 Open ; +P-V-1849 1848 1849 611.849334717 10.0371041298 155 0 Open ; +P-V-1851 1850 1851 230.451963425 3.12275491655 155 0 Open ; +P-V-1852 1851 1852 757.098815918 6.21267652512 155 0 Open ; +P-V-1853 1852 1853 572.946105957 13.1030931473 155 0 Open ; +P-V-1854 1853 1854 334.170608521 7.10901975632 155 0 Open ; +P-V-1855 1854 1855 215.157669067 10.0990920067 155 0 Open ; +P-V-1856 1855 1856 721.796813965 7.79280948639 155 0 Open ; +P-V-1857 1856 1857 637.690124512 8.15659952164 155 0 Open ; +P-V-1858 1857 1858 348.57749939 13.8441429138 155 0 Open ; +P-V-1859 1858 1859 275.570739746 13.3494911194 155 0 Open ; +P-V-1860 1859 1860 395.511108398 10.1071243286 155 0 Open ; +P-V-1861 1860 1861 272.012161255 5.16755843163 155 0 Open ; +P-V-1862 1861 1862 707.904174805 5.90946960449 155 0 Open ; +P-V-1863 1862 1863 772.883422852 8.04324102402 155 0 Open ; +P-V-1864 1863 1864 487.695098877 12.8372106552 155 0 Open ; +P-V-1865 1864 1865 700.078125 3.26421520114 155 0 Open ; +P-V-1866 1865 1866 233.239685059 4.18775200844 155 0 Open ; +P-V-1867 1866 1867 527.450836182 8.32687616348 155 0 Open ; +P-V-1868 1867 1868 640.647460938 6.23985886574 155 0 Open ; +P-V-1869 1868 1869 615.323974609 13.9950828552 155 0 Open ; +P-V-1870 1869 1870 518.557861328 7.04876899719 155 0 Open ; +P-V-1871 1870 1871 583.260009766 12.0283355713 155 0 Open ; +P-V-1872 1871 1872 761.598937988 6.8695037365 155 0 Open ; +P-V-1873 1872 1873 537.510284424 5.71434807777 155 0 Open ; +P-V-1874 1873 1874 602.528747559 9.01257324219 155 0 Open ; +P-V-1875 1874 1875 266.244171143 10.3172154427 155 0 Open ; +P-V-1876 1875 1876 422.402359009 13.3346500397 155 0 Open ; +P-V-1877 1876 1877 523.803527832 6.31351590157 155 0 Open ; +P-V-1878 1877 1878 713.070373535 14.4822263718 155 0 Open ; +P-V-1879 1878 1879 689.83291626 3.43368065357 155 0 Open ; +P-V-1880 1879 1880 443.532699585 12.0828485489 155 0 Open ; +P-V-1881 1880 1881 371.892745972 3.02822382934 155 0 Open ; +P-V-1882 1881 1882 517.894989014 12.2253684998 155 0 Open ; +P-V-1883 1882 1883 738.328430176 8.7297077179 155 0 Open ; +P-V-1884 1883 1884 760.310241699 5.70269298553 155 0 Open ; +P-V-1885 1884 1885 408.110931396 9.40870857239 155 0 Open ; +P-V-1886 1885 1886 758.429748535 9.5778670311 155 0 Open ; +P-V-1887 1886 1887 710.95501709 11.4273090363 155 0 Open ; +P-V-1888 1887 1888 289.626190186 9.94835662842 155 0 Open ; +P-V-1889 1888 1889 651.695739746 12.0144853592 155 0 Open ; +P-V-1890 1889 1890 522.629547119 7.69827318192 155 0 Open ; +P-V-1891 1890 1891 393.818603516 5.1865541935 155 0 Open ; +P-V-1892 1891 1892 470.945709229 10.6919846535 155 0 Open ; +P-V-1893 1892 1893 359.33001709 4.19799005985 155 0 Open ; +P-V-1894 1893 1894 731.055297852 11.9183979034 155 0 Open ; +P-V-1895 1894 1895 776.268615723 5.93575358391 155 0 Open ; +P-V-1896 1895 1896 660.530059814 5.58169341087 155 0 Open ; +P-V-1897 1896 1897 726.199707031 11.771320343 155 0 Open ; +P-V-1898 1897 1898 779.300964355 5.2382979393 155 0 Open ; +P-V-1899 1898 1899 753.703857422 5.03139853477 155 0 Open ; +P-V-1901 1900 1901 285.952018738 10.9125385284 155 0 Open ; +P-V-1902 1901 1902 301.857215881 5.28447818756 155 0 Open ; +P-V-1903 1902 1903 561.424255371 4.1480987072 155 0 Open ; +P-V-1904 1903 1904 204.750608921 3.86981248856 155 0 Open ; +P-V-1905 1904 1905 346.887527466 9.77492523193 155 0 Open ; +P-V-1906 1905 1906 708.533966064 13.6208658218 155 0 Open ; +P-V-1907 1906 1907 445.004501343 14.8157300949 155 0 Open ; +P-V-1908 1907 1908 749.198425293 14.5560674667 155 0 Open ; +P-V-1909 1908 1909 341.672714233 8.87103939056 155 0 Open ; +P-V-1910 1909 1910 727.996398926 3.71670883894 155 0 Open ; +P-V-1911 1910 1911 686.302825928 4.83112943172 155 0 Open ; +P-V-1912 1911 1912 589.637451172 7.73229646683 155 0 Open ; +P-V-1913 1912 1913 785.647644043 14.6092920303 155 0 Open ; +P-V-1914 1913 1914 668.513702393 13.1988201141 155 0 Open ; +P-V-1915 1914 1915 378.876663208 10.5998697281 155 0 Open ; +P-V-1916 1915 1916 350.270706177 6.99405694008 155 0 Open ; +P-V-1917 1916 1917 205.804377079 10.0834269524 155 0 Open ; +P-V-1918 1917 1918 758.258544922 12.0297288895 155 0 Open ; +P-V-1919 1918 1919 732.840148926 11.887834549 155 0 Open ; +P-V-1920 1919 1920 291.913818359 10.9128031731 155 0 Open ; +P-V-1921 1920 1921 524.462646484 11.8706417084 155 0 Open ; +P-V-1922 1921 1922 243.60344696 7.86214447021 155 0 Open ; +P-V-1923 1922 1923 703.284332275 12.9925460815 155 0 Open ; +P-V-1924 1923 1924 436.906509399 4.75776314735 155 0 Open ; +P-V-1925 1924 1925 736.205200195 3.02165121026 155 0 Open ; +P-V-1926 1925 1926 394.594543457 14.0131444931 155 0 Open ; +P-V-1927 1926 1927 696.537902832 13.2468624115 155 0 Open ; +P-V-1928 1927 1928 550.958282471 14.1230192184 155 0 Open ; +P-V-1929 1928 1929 629.927734375 14.9069166183 155 0 Open ; +P-V-1930 1929 1930 577.657226562 12.706363678 155 0 Open ; +P-V-1931 1930 1931 543.208953857 13.2574501038 155 0 Open ; +P-V-1932 1931 1932 448.300445557 6.71368288994 155 0 Open ; +P-V-1933 1932 1933 393.380432129 13.9032382965 155 0 Open ; +P-V-1934 1933 1934 736.264465332 10.9407625198 155 0 Open ; +P-V-1935 1934 1935 619.977600098 6.2756125927 155 0 Open ; +P-V-1936 1935 1936 661.185974121 10.0602827072 155 0 Open ; +P-V-1937 1936 1937 508.757324219 12.6929969788 155 0 Open ; +P-V-1938 1937 1938 709.883422852 11.2097110748 155 0 Open ; +P-V-1939 1938 1939 430.700241089 6.58184194565 155 0 Open ; +P-V-1940 1939 1940 600.819366455 10.4268708229 155 0 Open ; +P-V-1941 1940 1941 770.626586914 5.41796040535 155 0 Open ; +P-V-1942 1941 1942 533.063568115 10.9928359985 155 0 Open ; +P-V-1943 1942 1943 579.728210449 12.8491373062 155 0 Open ; +P-V-1944 1943 1944 522.4921875 9.5188126564 155 0 Open ; +P-V-1945 1944 1945 284.179222107 3.00536384247 155 0 Open ; +P-V-1946 1945 1946 507.5050354 11.738702774 155 0 Open ; +P-V-1947 1946 1947 369.175430298 13.628194809 155 0 Open ; +P-V-1948 1947 1948 603.734130859 6.19294524193 155 0 Open ; +P-V-1949 1948 1949 791.582275391 5.46153283119 155 0 Open ; +P-V-1951 1950 1951 549.243988037 13.880818367 155 0 Open ; +P-V-1952 1951 1952 496.205749512 5.60758686066 155 0 Open ; +P-V-1953 1952 1953 285.702331543 10.9821472168 155 0 Open ; +P-V-1954 1953 1954 597.8565979 10.5177817345 155 0 Open ; +P-V-1955 1954 1955 368.196548462 8.59019422531 155 0 Open ; +P-V-1956 1955 1956 519.747589111 10.9592084885 155 0 Open ; +P-V-1957 1956 1957 520.65447998 3.79532039165 155 0 Open ; +P-V-1958 1957 1958 747.528991699 5.39975690842 155 0 Open ; +P-V-1959 1958 1959 235.819103241 7.23382329941 155 0 Open ; +P-V-1960 1959 1960 693.646118164 13.2018451691 155 0 Open ; +P-V-1961 1960 1961 520.785888672 11.9764270782 155 0 Open ; +P-V-1962 1961 1962 340.534713745 10.3403992653 155 0 Open ; +P-V-1963 1962 1963 704.755523682 3.53177320957 155 0 Open ; +P-V-1964 1963 1964 675.660675049 3.58751475811 155 0 Open ; +P-V-1965 1964 1965 718.039733887 4.87479972839 155 0 Open ; +P-V-1966 1965 1966 687.957183838 8.92816209793 155 0 Open ; +P-V-1967 1966 1967 731.102722168 3.86503297091 155 0 Open ; +P-V-1968 1967 1968 530.433959961 3.07120272517 155 0 Open ; +P-V-1969 1968 1969 635.210113525 14.5318164825 155 0 Open ; +P-V-1970 1969 1970 362.600769043 11.6231775284 155 0 Open ; +P-V-1971 1970 1971 487.380218506 14.9886026382 155 0 Open ; +P-V-1972 1971 1972 222.679409027 6.45639252663 155 0 Open ; +P-V-1973 1972 1973 779.338989258 6.01544046402 155 0 Open ; +P-V-1974 1973 1974 425.504684448 12.1458864212 155 0 Open ; +P-V-1975 1974 1975 545.840759277 9.91792392731 155 0 Open ; +P-V-1976 1975 1976 277.486152649 9.19583892822 155 0 Open ; +P-V-1977 1976 1977 673.624542236 3.15715381503 155 0 Open ; +P-V-1978 1977 1978 264.214782715 12.1574726105 155 0 Open ; +P-V-1979 1978 1979 682.039794922 11.8558197021 155 0 Open ; +P-V-1980 1979 1980 388.429824829 5.80316066742 155 0 Open ; +P-V-1981 1980 1981 236.146224976 9.19258975983 155 0 Open ; +P-V-1982 1981 1982 342.901000977 13.745513916 155 0 Open ; +P-V-1983 1982 1983 793.310668945 10.4532756805 155 0 Open ; +P-V-1984 1983 1984 760.379150391 4.84839749336 155 0 Open ; +P-V-1985 1984 1985 700.843658447 8.5885682106 155 0 Open ; +P-V-1986 1985 1986 353.437271118 3.40579023957 155 0 Open ; +P-V-1987 1986 1987 405.837356567 13.1753025055 155 0 Open ; +P-V-1988 1987 1988 415.309509277 5.13897800446 155 0 Open ; +P-V-1989 1988 1989 690.218536377 13.0584535599 155 0 Open ; +P-V-1990 1989 1990 621.567230225 12.612865448 155 0 Open ; +P-V-1991 1990 1991 571.802307129 12.6260347366 155 0 Open ; +P-V-1992 1991 1992 238.534183502 7.88045454025 155 0 Open ; +P-V-1993 1992 1993 490.125061035 13.6435317993 155 0 Open ; +P-V-1994 1993 1994 292.717132568 4.93926012516 155 0 Open ; +P-V-1995 1994 1995 257.245368958 9.45933866501 155 0 Open ; +P-V-1996 1995 1996 705.005493164 3.5436835885 155 0 Open ; +P-V-1997 1996 1997 484.541381836 8.73924684525 155 0 Open ; +P-V-1998 1997 1998 376.256118774 5.73624897003 155 0 Open ; +P-V-1999 1998 1999 406.904418945 11.8554887772 155 0 Open ; +P-V-2001 2000 2001 710.080291748 5.39600086212 155 0 Open ; +P-V-2002 2001 2002 679.499145508 9.84995126724 155 0 Open ; +P-V-2003 2002 2003 756.442077637 13.4487686157 155 0 Open ; +P-V-2004 2003 2004 423.308242798 5.83379077911 155 0 Open ; +P-V-2005 2004 2005 776.127746582 6.57520008087 155 0 Open ; +P-V-2006 2005 2006 419.356491089 9.49011945724 155 0 Open ; +P-V-2007 2006 2007 772.323547363 11.8487062454 155 0 Open ; +P-V-2008 2007 2008 410.710021973 7.07138061523 155 0 Open ; +P-V-2009 2008 2009 384.775177002 13.3267478943 155 0 Open ; +P-V-2010 2009 2010 482.550048828 11.3727998734 155 0 Open ; +P-V-2011 2010 2011 682.394073486 10.9412913322 155 0 Open ; +P-V-2012 2011 2012 464.113098145 5.9820971489 155 0 Open ; +P-V-2013 2012 2013 605.37310791 5.11781215668 155 0 Open ; +P-V-2014 2013 2014 303.60634613 5.23862195015 155 0 Open ; +P-V-2015 2014 2015 425.991104126 7.65514469147 155 0 Open ; +P-V-2016 2015 2016 750.716491699 8.84733343124 155 0 Open ; +P-V-2017 2016 2017 606.814025879 9.46550893784 155 0 Open ; +P-V-2018 2017 2018 490.66696167 3.79539000988 155 0 Open ; +P-V-2019 2018 2019 206.006070614 5.88066601753 155 0 Open ; +P-V-2020 2019 2020 567.665466309 14.0749368668 155 0 Open ; +P-V-2021 2020 2021 423.890594482 9.58681344986 155 0 Open ; +P-V-2022 2021 2022 428.749328613 10.804256916 155 0 Open ; +P-V-2023 2022 2023 507.419830322 7.10799694061 155 0 Open ; +P-V-2024 2023 2024 555.578125 7.03674936295 155 0 Open ; +P-V-2025 2024 2025 682.533752441 9.9054236412 155 0 Open ; +P-V-2026 2025 2026 572.684448242 9.15289068222 155 0 Open ; +P-V-2027 2026 2027 581.925140381 7.31431674957 155 0 Open ; +P-V-2028 2027 2028 536.161987305 8.50163841248 155 0 Open ; +P-V-2029 2028 2029 502.137878418 7.63824701309 155 0 Open ; +P-V-2030 2029 2030 350.890228271 11.2398433685 155 0 Open ; +P-V-2031 2030 2031 552.373260498 9.75198459625 155 0 Open ; +P-V-2032 2031 2032 630.650970459 6.02265310287 155 0 Open ; +P-V-2033 2032 2033 486.673919678 5.57406377792 155 0 Open ; +P-V-2034 2033 2034 314.520263672 13.8416986465 155 0 Open ; +P-V-2035 2034 2035 621.782714844 13.0529565811 155 0 Open ; +P-V-2036 2035 2036 202.466019392 3.92774003744 155 0 Open ; +P-V-2037 2036 2037 426.337677002 4.15321791172 155 0 Open ; +P-V-2038 2037 2038 306.761787415 9.90675258636 155 0 Open ; +P-V-2039 2038 2039 489.360198975 8.54204320908 155 0 Open ; +P-V-2040 2039 2040 256.022304535 6.33837676048 155 0 Open ; +P-V-2041 2040 2041 604.916656494 7.69076490402 155 0 Open ; +P-V-2042 2041 2042 684.432922363 12.2870550156 155 0 Open ; +P-V-2043 2042 2043 377.230682373 9.3203291893 155 0 Open ; +P-V-2044 2043 2044 288.992019653 12.7773113251 155 0 Open ; +P-V-2045 2044 2045 763.392700195 9.82698488235 155 0 Open ; +P-V-2046 2045 2046 656.916046143 14.7585697174 155 0 Open ; +P-V-2047 2046 2047 714.01965332 9.57062721252 155 0 Open ; +P-V-2048 2047 2048 626.931243896 3.66615372896 155 0 Open ; +P-V-2049 2048 2049 202.284828424 3.02227704227 155 0 Open ; +P-V-2051 2050 2051 320.512481689 12.0650482178 155 0 Open ; +P-V-2052 2051 2052 414.099822998 6.51276278496 155 0 Open ; +P-V-2053 2052 2053 750.331359863 11.3869142532 155 0 Open ; +P-V-2054 2053 2054 543.45703125 12.6472578049 155 0 Open ; +P-V-2055 2054 2055 673.395935059 10.3095645905 155 0 Open ; +P-V-2056 2055 2056 592.512512207 14.162519455 155 0 Open ; +P-V-2057 2056 2057 223.821578979 6.38563585281 155 0 Open ; +P-V-2058 2057 2058 719.024475098 11.8938732147 155 0 Open ; +P-V-2059 2058 2059 566.805541992 13.0258951187 155 0 Open ; +P-V-2060 2059 2060 261.560173035 7.83651685715 155 0 Open ; +P-V-2061 2060 2061 767.194763184 3.86187779903 155 0 Open ; +P-V-2062 2061 2062 278.999359131 13.8461971283 155 0 Open ; +P-V-2063 2062 2063 201.825183988 4.51735079288 155 0 Open ; +P-V-2064 2063 2064 305.822349548 6.12608885765 155 0 Open ; +P-V-2065 2064 2065 408.800918579 13.3429422379 155 0 Open ; +P-V-2066 2065 2066 291.85798645 4.14416825771 155 0 Open ; +P-V-2067 2066 2067 501.822418213 9.59053659439 155 0 Open ; +P-V-2068 2067 2068 557.424987793 3.83262389898 155 0 Open ; +P-V-2069 2068 2069 295.50479126 5.98115372658 155 0 Open ; +P-V-2070 2069 2070 412.619812012 13.0266265869 155 0 Open ; +P-V-2071 2070 2071 275.947372437 7.95156431198 155 0 Open ; +P-V-2072 2071 2072 247.318824768 8.74960327148 155 0 Open ; +P-V-2073 2072 2073 679.224121094 13.4029359818 155 0 Open ; +P-V-2074 2073 2074 307.696166992 11.9928817749 155 0 Open ; +P-V-2075 2074 2075 368.132629395 11.0992031097 155 0 Open ; +P-V-2076 2075 2076 565.588439941 11.9014091492 155 0 Open ; +P-V-2077 2076 2077 299.651565552 7.8788690567 155 0 Open ; +P-V-2078 2077 2078 357.789016724 14.2008810043 155 0 Open ; +P-V-2079 2078 2079 660.60369873 6.32369565964 155 0 Open ; +P-V-2080 2079 2080 267.603477478 11.2351160049 155 0 Open ; +P-V-2081 2080 2081 780.08392334 4.40303218365 155 0 Open ; +P-V-2082 2081 2082 238.160251617 14.1874923706 155 0 Open ; +P-V-2083 2082 2083 209.790906906 6.11527991295 155 0 Open ; +P-V-2084 2083 2084 325.471366882 10.9461798668 155 0 Open ; +P-V-2085 2084 2085 372.407562256 8.07854604721 155 0 Open ; +P-V-2086 2085 2086 756.031860352 7.55822324753 155 0 Open ; +P-V-2087 2086 2087 302.987670898 13.2763690948 155 0 Open ; +P-V-2088 2087 2088 746.971618652 10.0561995506 155 0 Open ; +P-V-2089 2088 2089 677.17300415 7.9458861351 155 0 Open ; +P-V-2090 2089 2090 275.650352478 4.11163628101 155 0 Open ; +P-V-2091 2090 2091 763.608642578 10.4166846275 155 0 Open ; +P-V-2092 2091 2092 611.397674561 14.2116136551 155 0 Open ; +P-V-2093 2092 2093 679.619262695 14.2219009399 155 0 Open ; +P-V-2094 2093 2094 324.758239746 11.2342567444 155 0 Open ; +P-V-2095 2094 2095 657.824279785 8.05515384674 155 0 Open ; +P-V-2096 2095 2096 298.759353638 7.96980047226 155 0 Open ; +P-V-2097 2096 2097 572.179412842 7.3934006691 155 0 Open ; +P-V-2098 2097 2098 394.246154785 4.90733850002 155 0 Open ; +P-V-2099 2098 2099 431.876358032 5.92296481133 155 0 Open ; +P-V-2101 2100 2101 713.409851074 8.60496616364 155 0 Open ; +P-V-2102 2101 2102 333.635559082 7.25539159775 155 0 Open ; +P-V-2103 2102 2103 218.596927643 14.1717586517 155 0 Open ; +P-V-2104 2103 2104 787.803710938 7.34201097488 155 0 Open ; +P-V-2105 2104 2105 408.954177856 4.85911035538 155 0 Open ; +P-V-2106 2105 2106 703.461425781 12.5272989273 155 0 Open ; +P-V-2107 2106 2107 666.320953369 8.12980270386 155 0 Open ; +P-V-2108 2107 2108 629.661895752 9.56168031693 155 0 Open ; +P-V-2109 2108 2109 308.028717041 3.77419018745 155 0 Open ; +P-V-2110 2109 2110 390.777542114 14.9654626846 155 0 Open ; +P-V-2111 2110 2111 576.789276123 8.95036888123 155 0 Open ; +P-V-2112 2111 2112 792.67791748 13.7607336044 155 0 Open ; +P-V-2113 2112 2113 383.094451904 12.3702964783 155 0 Open ; +P-V-2114 2113 2114 728.583435059 9.03776025772 155 0 Open ; +P-V-2115 2114 2115 431.870941162 4.09769880772 155 0 Open ; +P-V-2116 2115 2116 451.262359619 6.33172416687 155 0 Open ; +P-V-2117 2116 2117 414.447189331 3.28028264642 155 0 Open ; +P-V-2118 2117 2118 535.525146484 10.4263658524 155 0 Open ; +P-V-2119 2118 2119 346.340316772 5.83424162865 155 0 Open ; +P-V-2120 2119 2120 555.094604492 12.5045976639 155 0 Open ; +P-V-2121 2120 2121 789.146728516 14.7892789841 155 0 Open ; +P-V-2122 2121 2122 720.940063477 7.80727720261 155 0 Open ; +P-V-2123 2122 2123 795.707458496 12.1023254395 155 0 Open ; +P-V-2124 2123 2124 539.479309082 7.57612085342 155 0 Open ; +P-V-2125 2124 2125 343.445846558 4.88649988174 155 0 Open ; +P-V-2126 2125 2126 320.190444946 11.8177213669 155 0 Open ; +P-V-2127 2126 2127 772.712890625 10.7185297012 155 0 Open ; +P-V-2128 2127 2128 466.619018555 8.31847381592 155 0 Open ; +P-V-2129 2128 2129 779.564086914 9.66775560379 155 0 Open ; +P-V-2130 2129 2130 648.349121094 3.07361208647 155 0 Open ; +P-V-2131 2130 2131 259.921592712 9.04454183578 155 0 Open ; +P-V-2132 2131 2132 730.752807617 6.26315975189 155 0 Open ; +P-V-2133 2132 2133 396.214248657 6.45956277847 155 0 Open ; +P-V-2134 2133 2134 443.663619995 8.09518718719 155 0 Open ; +P-V-2135 2134 2135 340.855285645 10.0956988335 155 0 Open ; +P-V-2136 2135 2136 270.259208679 3.93061047792 155 0 Open ; +P-V-2137 2136 2137 438.548355103 4.64527356625 155 0 Open ; +P-V-2138 2137 2138 405.62638855 14.253370285 155 0 Open ; +P-V-2139 2138 2139 369.652984619 6.15767240524 155 0 Open ; +P-V-2140 2139 2140 550.044525146 6.97440361977 155 0 Open ; +P-V-2141 2140 2141 490.078704834 10.0642991066 155 0 Open ; +P-V-2142 2141 2142 284.04813385 6.94005584717 155 0 Open ; +P-V-2143 2142 2143 426.154968262 14.7344074249 155 0 Open ; +P-V-2144 2143 2144 209.606575012 4.15429008007 155 0 Open ; +P-V-2145 2144 2145 607.725585938 3.87941747904 155 0 Open ; +P-V-2146 2145 2146 618.445983887 7.43278074265 155 0 Open ; +P-V-2147 2146 2147 487.625946045 13.5897941589 155 0 Open ; +P-V-2148 2147 2148 734.090698242 12.2375879288 155 0 Open ; +P-V-2149 2148 2149 207.376440525 10.5168118477 155 0 Open ; +P-V-2151 2150 2151 752.889221191 7.18705129623 155 0 Open ; +P-V-2152 2151 2152 388.671112061 14.9131469727 155 0 Open ; +P-V-2153 2152 2153 413.357406616 8.95811605453 155 0 Open ; +P-V-2154 2153 2154 702.861602783 14.9085388184 155 0 Open ; +P-V-2155 2154 2155 740.318908691 5.80144548416 155 0 Open ; +P-V-2156 2155 2156 594.824829102 11.4236383438 155 0 Open ; +P-V-2157 2156 2157 204.43386364 5.3990085125 155 0 Open ; +P-V-2158 2157 2158 206.780936241 14.3439874649 155 0 Open ; +P-V-2159 2158 2159 320.358932495 8.45318031311 155 0 Open ; +P-V-2160 2159 2160 580.292694092 10.5877518654 155 0 Open ; +P-V-2161 2160 2161 367.142166138 14.1698684692 155 0 Open ; +P-V-2162 2161 2162 399.573547363 7.65663433075 155 0 Open ; +P-V-2163 2162 2163 202.984113932 10.0800776482 155 0 Open ; +P-V-2164 2163 2164 343.118225098 14.7602806091 155 0 Open ; +P-V-2165 2164 2165 351.809783936 8.34257888794 155 0 Open ; +P-V-2166 2165 2166 636.276977539 13.1538686752 155 0 Open ; +P-V-2167 2166 2167 404.237045288 3.24386742711 155 0 Open ; +P-V-2168 2167 2168 534.001861572 14.3850603104 155 0 Open ; +P-V-2169 2168 2169 636.112426758 5.84488654137 155 0 Open ; +P-V-2170 2169 2170 500.489105225 5.40949368477 155 0 Open ; +P-V-2171 2170 2171 618.156646729 6.18720030785 155 0 Open ; +P-V-2172 2171 2172 763.831604004 13.3539199829 155 0 Open ; +P-V-2173 2172 2173 517.010742188 14.9922609329 155 0 Open ; +P-V-2174 2173 2174 296.437408447 7.47157096863 155 0 Open ; +P-V-2175 2174 2175 684.878112793 5.92908287048 155 0 Open ; +P-V-2176 2175 2176 454.841445923 9.40355443954 155 0 Open ; +P-V-2177 2176 2177 627.182373047 4.08969974518 155 0 Open ; +P-V-2178 2177 2178 329.240768433 5.99153542519 155 0 Open ; +P-V-2179 2178 2179 736.845825195 14.3521175385 155 0 Open ; +P-V-2180 2179 2180 551.915252686 11.7987241745 155 0 Open ; +P-V-2181 2180 2181 407.741394043 5.1916437149 155 0 Open ; +P-V-2182 2181 2182 547.899993896 6.10127401352 155 0 Open ; +P-V-2183 2182 2183 555.803161621 10.6798610687 155 0 Open ; +P-V-2184 2183 2184 370.956268311 12.2412900925 155 0 Open ; +P-V-2185 2184 2185 318.137519836 5.74523735046 155 0 Open ; +P-V-2186 2185 2186 760.391662598 9.0571680069 155 0 Open ; +P-V-2187 2186 2187 541.506347656 4.95147454739 155 0 Open ; +P-V-2188 2187 2188 321.644477844 8.57751846313 155 0 Open ; +P-V-2189 2188 2189 668.023040771 4.26447474957 155 0 Open ; +P-V-2190 2189 2190 201.362552881 5.00855183601 155 0 Open ; +P-V-2191 2190 2191 286.681755066 4.20366120338 155 0 Open ; +P-V-2192 2191 2192 696.745941162 11.1851139069 155 0 Open ; +P-V-2193 2192 2193 760.539001465 10.5825896263 155 0 Open ; +P-V-2194 2193 2194 229.212656021 6.54243087769 155 0 Open ; +P-V-2195 2194 2195 482.035186768 6.3112077713 155 0 Open ; +P-V-2196 2195 2196 573.536437988 7.53677225113 155 0 Open ; +P-V-2197 2196 2197 276.64440918 14.2506141663 155 0 Open ; +P-V-2198 2197 2198 453.650314331 5.0200586319 155 0 Open ; +P-V-2199 2198 2199 356.284622192 12.5146198273 155 0 Open ; +P-V-2201 2200 2201 210.882007599 12.8783836365 155 0 Open ; +P-V-2202 2201 2202 500.084075928 13.2678594589 155 0 Open ; +P-V-2203 2202 2203 795.850585938 12.2174978256 155 0 Open ; +P-V-2204 2203 2204 724.329528809 7.13286066055 155 0 Open ; +P-V-2205 2204 2205 449.607971191 14.2261447906 155 0 Open ; +P-V-2206 2205 2206 291.018707275 10.0265350342 155 0 Open ; +P-V-2207 2206 2207 348.441665649 4.18263161182 155 0 Open ; +P-V-2208 2207 2208 424.472320557 13.1285238266 155 0 Open ; +P-V-2209 2208 2209 705.356964111 13.689614296 155 0 Open ; +P-V-2210 2209 2210 617.805114746 8.01046419144 155 0 Open ; +P-V-2211 2210 2211 543.931152344 4.02015459538 155 0 Open ; +P-V-2212 2211 2212 686.989746094 7.73650884628 155 0 Open ; +P-V-2213 2212 2213 725.184204102 6.42294168472 155 0 Open ; +P-V-2214 2213 2214 269.197921753 7.19148874283 155 0 Open ; +P-V-2215 2214 2215 517.580749512 14.5978403091 155 0 Open ; +P-V-2216 2215 2216 644.901672363 8.26102638245 155 0 Open ; +P-V-2217 2216 2217 503.855926514 9.13930368423 155 0 Open ; +P-V-2218 2217 2218 564.119506836 10.1440377235 155 0 Open ; +P-V-2219 2218 2219 692.149139404 14.0208044052 155 0 Open ; +P-V-2220 2219 2220 533.363464355 3.79475021362 155 0 Open ; +P-V-2221 2220 2221 268.37676239 7.16583824158 155 0 Open ; +P-V-2222 2221 2222 562.299407959 10.3278894424 155 0 Open ; +P-V-2223 2222 2223 391.623458862 11.3123903275 155 0 Open ; +P-V-2224 2223 2224 317.656326294 12.0006694794 155 0 Open ; +P-V-2225 2224 2225 312.539459229 8.01580715179 155 0 Open ; +P-V-2226 2225 2226 233.765804291 13.0384960175 155 0 Open ; +P-V-2227 2226 2227 650.468719482 7.55934667587 155 0 Open ; +P-V-2228 2227 2228 647.049713135 10.2948694229 155 0 Open ; +P-V-2229 2228 2229 243.445701599 14.8378658295 155 0 Open ; +P-V-2230 2229 2230 751.399658203 10.4862499237 155 0 Open ; +P-V-2231 2230 2231 270.116920471 4.10291659832 155 0 Open ; +P-V-2232 2231 2232 635.999816895 3.98322880268 155 0 Open ; +P-V-2233 2232 2233 256.296539307 14.5198888779 155 0 Open ; +P-V-2234 2233 2234 539.266357422 7.99170255661 155 0 Open ; +P-V-2235 2234 2235 377.254776001 5.42588090897 155 0 Open ; +P-V-2236 2235 2236 589.1980896 4.05255949497 155 0 Open ; +P-V-2237 2236 2237 318.364181519 9.93729019165 155 0 Open ; +P-V-2238 2237 2238 351.837188721 5.55033373833 155 0 Open ; +P-V-2239 2238 2239 772.972106934 13.837852478 155 0 Open ; +P-V-2240 2239 2240 389.977478027 10.0297513008 155 0 Open ; +P-V-2241 2240 2241 651.929412842 6.56421589851 155 0 Open ; +P-V-2242 2241 2242 788.855163574 12.7835388184 155 0 Open ; +P-V-2243 2242 2243 597.031402588 9.13766860962 155 0 Open ; +P-V-2244 2243 2244 390.126846313 12.2407627106 155 0 Open ; +P-V-2245 2244 2245 475.147796631 7.18139648438 155 0 Open ; +P-V-2246 2245 2246 436.823730469 12.9272251129 155 0 Open ; +P-V-2247 2246 2247 743.780944824 5.5183467865 155 0 Open ; +P-V-2248 2247 2248 292.868591309 7.84797620773 155 0 Open ; +P-V-2249 2248 2249 797.000610352 14.7797813416 155 0 Open ; +P-V-2251 2250 2251 540.072052002 14.8210506439 155 0 Open ; +P-V-2252 2251 2252 419.968032837 11.0533704758 155 0 Open ; +P-V-2253 2252 2253 450.586837769 7.2594499588 155 0 Open ; +P-V-2254 2253 2254 628.871582031 7.8970785141 155 0 Open ; +P-V-2255 2254 2255 659.865478516 10.1885018349 155 0 Open ; +P-V-2256 2255 2256 257.411739349 5.3828163147 155 0 Open ; +P-V-2257 2256 2257 399.802124023 12.485534668 155 0 Open ; +P-V-2258 2257 2258 369.074447632 3.68952041864 155 0 Open ; +P-V-2259 2258 2259 638.510681152 7.98230171204 155 0 Open ; +P-V-2260 2259 2260 277.488273621 9.90932226181 155 0 Open ; +P-V-2261 2260 2261 249.170463562 7.16074609756 155 0 Open ; +P-V-2262 2261 2262 483.246124268 5.34990406036 155 0 Open ; +P-V-2263 2262 2263 341.802902222 4.63121271133 155 0 Open ; +P-V-2264 2263 2264 589.582275391 13.1807022095 155 0 Open ; +P-V-2265 2264 2265 753.304504395 14.7759819031 155 0 Open ; +P-V-2266 2265 2266 346.608169556 11.8703269958 155 0 Open ; +P-V-2267 2266 2267 579.904907227 12.2297725677 155 0 Open ; +P-V-2268 2267 2268 239.800415039 13.5108470917 155 0 Open ; +P-V-2269 2268 2269 390.716049194 6.29295372963 155 0 Open ; +P-V-2270 2269 2270 233.724330902 11.0971651077 155 0 Open ; +P-V-2271 2270 2271 653.21484375 6.64197158813 155 0 Open ; +P-V-2272 2271 2272 730.939758301 9.09738397598 155 0 Open ; +P-V-2273 2272 2273 736.97253418 8.94575452805 155 0 Open ; +P-V-2274 2273 2274 514.981201172 4.77823376656 155 0 Open ; +P-V-2275 2274 2275 538.769897461 9.11422538757 155 0 Open ; +P-V-2276 2275 2276 489.638671875 6.1451690197 155 0 Open ; +P-V-2277 2276 2277 242.871456146 13.8124580383 155 0 Open ; +P-V-2278 2277 2278 649.966644287 6.80166292191 155 0 Open ; +P-V-2279 2278 2279 527.52243042 8.39155292511 155 0 Open ; +P-V-2280 2279 2280 391.734375 12.5966501236 155 0 Open ; +P-V-2281 2280 2281 745.255981445 9.35202312469 155 0 Open ; +P-V-2282 2281 2282 522.823150635 12.7755975723 155 0 Open ; +P-V-2283 2282 2283 523.696105957 6.20292973518 155 0 Open ; +P-V-2284 2283 2284 782.113769531 14.7274103165 155 0 Open ; +P-V-2285 2284 2285 329.968399048 10.5798811913 155 0 Open ; +P-V-2286 2285 2286 353.373336792 5.9172410965 155 0 Open ; +P-V-2287 2286 2287 703.667694092 9.86636400223 155 0 Open ; +P-V-2288 2287 2288 749.248657227 7.44590473175 155 0 Open ; +P-V-2289 2288 2289 716.241882324 12.5374975204 155 0 Open ; +P-V-2290 2289 2290 236.641407013 7.64321613312 155 0 Open ; +P-V-2291 2290 2291 326.968849182 10.3119540215 155 0 Open ; +P-V-2292 2291 2292 200.727578521 7.5682477951 155 0 Open ; +P-V-2293 2292 2293 327.075531006 10.1706562042 155 0 Open ; +P-V-2294 2293 2294 261.075508118 12.921374321 155 0 Open ; +P-V-2295 2294 2295 627.147735596 4.4436866045 155 0 Open ; +P-V-2296 2295 2296 202.112224102 5.00305366516 155 0 Open ; +P-V-2297 2296 2297 466.270385742 11.1300201416 155 0 Open ; +P-V-2298 2297 2298 662.950408936 3.15165528655 155 0 Open ; +P-V-2299 2298 2299 443.531051636 11.533531189 155 0 Open ; +P-V-2301 2300 2301 753.179016113 8.60186958313 155 0 Open ; +P-V-2302 2301 2302 731.122009277 10.3585085869 155 0 Open ; +P-V-2303 2302 2303 322.959960938 6.76218533516 155 0 Open ; +P-V-2304 2303 2304 352.472915649 3.24656018615 155 0 Open ; +P-V-2305 2304 2305 396.861907959 8.16489362717 155 0 Open ; +P-V-2306 2305 2306 718.613586426 5.78215456009 155 0 Open ; +P-V-2307 2306 2307 583.590362549 3.0620690994 155 0 Open ; +P-V-2308 2307 2308 759.767700195 3.31538724899 155 0 Open ; +P-V-2309 2308 2309 635.681060791 4.83678996563 155 0 Open ; +P-V-2310 2309 2310 546.481201172 9.19269752502 155 0 Open ; +P-V-2311 2310 2311 433.661849976 6.09394550323 155 0 Open ; +P-V-2312 2311 2312 397.111114502 7.93027353287 155 0 Open ; +P-V-2313 2312 2313 355.477981567 5.36623764038 155 0 Open ; +P-V-2314 2313 2314 267.848976135 9.75553941727 155 0 Open ; +P-V-2315 2314 2315 617.996490479 12.3373031616 155 0 Open ; +P-V-2316 2315 2316 602.72958374 4.53097426891 155 0 Open ; +P-V-2317 2316 2317 354.235305786 7.65600538254 155 0 Open ; +P-V-2318 2317 2318 274.107818604 13.6024951935 155 0 Open ; +P-V-2319 2318 2319 606.744506836 10.0993828773 155 0 Open ; +P-V-2320 2319 2320 366.420974731 11.7472352982 155 0 Open ; +P-V-2321 2320 2321 339.882781982 7.1962685585 155 0 Open ; +P-V-2322 2321 2322 334.456954956 7.36237382889 155 0 Open ; +P-V-2323 2322 2323 720.912963867 10.6922183037 155 0 Open ; +P-V-2324 2323 2324 555.69052124 8.80777788162 155 0 Open ; +P-V-2325 2324 2325 366.347000122 10.8853969574 155 0 Open ; +P-V-2326 2325 2326 293.148399353 5.90377950668 155 0 Open ; +P-V-2327 2326 2327 791.133056641 10.4657006264 155 0 Open ; +P-V-2328 2327 2328 401.303588867 13.1889600754 155 0 Open ; +P-V-2329 2328 2329 493.024383545 4.21847069263 155 0 Open ; +P-V-2330 2329 2330 541.851715088 13.0398845673 155 0 Open ; +P-V-2331 2330 2331 616.990600586 10.2319526672 155 0 Open ; +P-V-2332 2331 2332 771.443908691 4.17273366451 155 0 Open ; +P-V-2333 2332 2333 506.735412598 5.04814767838 155 0 Open ; +P-V-2334 2333 2334 560.85534668 4.92269325256 155 0 Open ; +P-V-2335 2334 2335 735.266113281 11.364487648 155 0 Open ; +P-V-2336 2335 2336 297.350112915 14.2660284042 155 0 Open ; +P-V-2337 2336 2337 207.327659607 6.1196603775 155 0 Open ; +P-V-2338 2337 2338 406.66204834 14.3868350983 155 0 Open ; +P-V-2339 2338 2339 327.181381226 9.74976873398 155 0 Open ; +P-V-2340 2339 2340 568.626251221 13.0299711227 155 0 Open ; +P-V-2341 2340 2341 686.354278564 10.1399273872 155 0 Open ; +P-V-2342 2341 2342 238.250320435 8.46286296844 155 0 Open ; +P-V-2343 2342 2343 317.235771179 14.6315517426 155 0 Open ; +P-V-2344 2343 2344 775.337890625 5.07204055786 155 0 Open ; +P-V-2345 2344 2345 239.26795578 14.5310173035 155 0 Open ; +P-V-2346 2345 2346 290.703842163 12.1886329651 155 0 Open ; +P-V-2347 2346 2347 468.227661133 9.04288959503 155 0 Open ; +P-V-2348 2347 2348 542.240661621 11.7817926407 155 0 Open ; +P-V-2349 2348 2349 580.219146729 9.86565971375 155 0 Open ; +P-V-2351 2350 2351 757.345031738 4.96601307392 155 0 Open ; +P-V-2352 2351 2352 539.087432861 7.85175228119 155 0 Open ; +P-V-2353 2352 2353 370.136276245 12.6054868698 155 0 Open ; +P-V-2354 2353 2354 370.871322632 7.68759584427 155 0 Open ; +P-V-2355 2354 2355 421.132003784 6.31016230583 155 0 Open ; +P-V-2356 2355 2356 295.056221008 11.199262619 155 0 Open ; +P-V-2357 2356 2357 650.52822876 3.56185609102 155 0 Open ; +P-V-2358 2357 2358 755.766296387 14.2876501083 155 0 Open ; +P-V-2359 2358 2359 376.884078979 12.8189687729 155 0 Open ; +P-V-2360 2359 2360 370.653182983 6.36365699768 155 0 Open ; +P-V-2361 2360 2361 249.193752289 14.9882106781 155 0 Open ; +P-V-2362 2361 2362 493.417785645 4.45684409142 155 0 Open ; +P-V-2363 2362 2363 458.950012207 10.4560379982 155 0 Open ; +P-V-2364 2363 2364 681.612976074 12.3831624985 155 0 Open ; +P-V-2365 2364 2365 741.200927734 14.2833156586 155 0 Open ; +P-V-2366 2365 2366 334.255477905 11.6381082535 155 0 Open ; +P-V-2367 2366 2367 434.42288208 9.91103410721 155 0 Open ; +P-V-2368 2367 2368 487.331542969 10.6305212975 155 0 Open ; +P-V-2369 2368 2369 308.284156799 5.63794469833 155 0 Open ; +P-V-2370 2369 2370 596.922180176 8.42611169815 155 0 Open ; +P-V-2371 2370 2371 632.986450195 11.0644655228 155 0 Open ; +P-V-2372 2371 2372 773.966796875 12.1969709396 155 0 Open ; +P-V-2373 2372 2373 274.764381409 6.29962801933 155 0 Open ; +P-V-2374 2373 2374 442.361938477 14.5440759659 155 0 Open ; +P-V-2375 2374 2375 464.317565918 14.7109861374 155 0 Open ; +P-V-2376 2375 2376 327.695068359 14.4205741882 155 0 Open ; +P-V-2377 2376 2377 480.242004395 3.54954230785 155 0 Open ; +P-V-2378 2377 2378 607.903656006 3.73771220446 155 0 Open ; +P-V-2379 2378 2379 336.468521118 11.528840065 155 0 Open ; +P-V-2380 2379 2380 410.90536499 12.7274179459 155 0 Open ; +P-V-2381 2380 2381 236.162975311 14.8230676651 155 0 Open ; +P-V-2382 2381 2382 314.985862732 14.3488292694 155 0 Open ; +P-V-2383 2382 2383 788.936096191 3.99028390646 155 0 Open ; +P-V-2384 2383 2384 785.06237793 9.87437295914 155 0 Open ; +P-V-2385 2384 2385 279.347068787 10.7260408401 155 0 Open ; +P-V-2386 2385 2386 778.535705566 12.0043859482 155 0 Open ; +P-V-2387 2386 2387 436.040313721 13.5884628296 155 0 Open ; +P-V-2388 2387 2388 215.611715317 6.72230815887 155 0 Open ; +P-V-2389 2388 2389 441.813034058 10.0329437256 155 0 Open ; +P-V-2390 2389 2390 334.563079834 7.03399419785 155 0 Open ; +P-V-2391 2390 2391 767.296508789 14.0557231903 155 0 Open ; +P-V-2392 2391 2392 477.125030518 11.8127651215 155 0 Open ; +P-V-2393 2392 2393 207.364230633 6.41256976128 155 0 Open ; +P-V-2394 2393 2394 553.161437988 10.6888279915 155 0 Open ; +P-V-2395 2394 2395 707.022003174 9.38064098358 155 0 Open ; +P-V-2396 2395 2396 572.116363525 10.1968379021 155 0 Open ; +P-V-2397 2396 2397 662.666473389 3.72176086903 155 0 Open ; +P-V-2398 2397 2398 731.771606445 12.7099847794 155 0 Open ; +P-V-2399 2398 2399 585.899383545 11.2245521545 155 0 Open ; +P-V-2401 2400 2401 302.952568054 13.4760513306 155 0 Open ; +P-V-2402 2401 2402 549.891540527 3.55318528414 155 0 Open ; +P-V-2403 2402 2403 669.297546387 12.6849365234 155 0 Open ; +P-V-2404 2403 2404 536.719604492 3.93291431665 155 0 Open ; +P-V-2405 2404 2405 574.560424805 3.75063532591 155 0 Open ; +P-V-2406 2405 2406 396.419891357 3.58524930477 155 0 Open ; +P-V-2407 2406 2407 614.278533936 10.587785244 155 0 Open ; +P-V-2408 2407 2408 395.575378418 7.705555439 155 0 Open ; +P-V-2409 2408 2409 513.709075928 9.1752204895 155 0 Open ; +P-V-2410 2409 2410 746.35760498 7.65455579758 155 0 Open ; +P-V-2411 2410 2411 256.208930969 9.07060861588 155 0 Open ; +P-V-2412 2411 2412 435.652191162 3.1283980757 155 0 Open ; +P-V-2413 2412 2413 699.324523926 13.9474639893 155 0 Open ; +P-V-2414 2413 2414 701.339477539 7.25341844559 155 0 Open ; +P-V-2415 2414 2415 360.12197876 6.40110898018 155 0 Open ; +P-V-2416 2415 2416 521.824798584 13.1950960159 155 0 Open ; +P-V-2417 2416 2417 249.548301697 14.1664714813 155 0 Open ; +P-V-2418 2417 2418 544.701873779 11.0924806595 155 0 Open ; +P-V-2419 2418 2419 315.975097656 10.8696269989 155 0 Open ; +P-V-2420 2419 2420 241.323963165 9.63724040985 155 0 Open ; +P-V-2421 2420 2421 204.885534286 13.2233715057 155 0 Open ; +P-V-2422 2421 2422 610.541534424 14.4376745224 155 0 Open ; +P-V-2423 2422 2423 450.418609619 10.7131180763 155 0 Open ; +P-V-2424 2423 2424 718.90838623 8.86126565933 155 0 Open ; +P-V-2425 2424 2425 314.727462769 11.4904060364 155 0 Open ; +P-V-2426 2425 2426 512.762939453 3.13802669942 155 0 Open ; +P-V-2427 2426 2427 390.736907959 13.3065385818 155 0 Open ; +P-V-2428 2427 2428 300.012779236 9.29543972015 155 0 Open ; +P-V-2429 2428 2429 373.136001587 12.9362440109 155 0 Open ; +P-V-2430 2429 2430 522.785247803 12.0361156464 155 0 Open ; +P-V-2431 2430 2431 699.887115479 11.061252594 155 0 Open ; +P-V-2432 2431 2432 473.446777344 11.3979721069 155 0 Open ; +P-V-2433 2432 2433 235.919696808 5.04721355438 155 0 Open ; +P-V-2434 2433 2434 376.023910522 11.6824903488 155 0 Open ; +P-V-2435 2434 2435 531.31427002 10.9907011986 155 0 Open ; +P-V-2436 2435 2436 585.675506592 7.97025537491 155 0 Open ; +P-V-2437 2436 2437 354.395812988 13.6125907898 155 0 Open ; +P-V-2438 2437 2438 691.366210938 14.8371934891 155 0 Open ; +P-V-2439 2438 2439 785.449890137 8.11861896515 155 0 Open ; +P-V-2440 2439 2440 231.331968307 10.9285202026 155 0 Open ; +P-V-2441 2440 2441 532.207397461 11.1945734024 155 0 Open ; +P-V-2442 2441 2442 309.555297852 12.9190120697 155 0 Open ; +P-V-2443 2442 2443 442.411804199 7.30524730682 155 0 Open ; +P-V-2444 2443 2444 714.824829102 4.22594857216 155 0 Open ; +P-V-2445 2444 2445 225.931615829 7.65369939804 155 0 Open ; +P-V-2446 2445 2446 736.45690918 3.61687648296 155 0 Open ; +P-V-2447 2446 2447 792.196533203 7.94075107574 155 0 Open ; +P-V-2448 2447 2448 760.3359375 14.3160505295 155 0 Open ; +P-V-2449 2448 2449 243.209312439 7.37968254089 155 0 Open ; +P-V-2451 2450 2451 266.159210205 5.75760483742 155 0 Open ; +P-V-2452 2451 2452 353.268463135 6.66195201874 155 0 Open ; +P-V-2453 2452 2453 721.493041992 13.6835784912 155 0 Open ; +P-V-2454 2453 2454 345.435012817 13.5268793106 155 0 Open ; +P-V-2455 2454 2455 662.868438721 11.5957288742 155 0 Open ; +P-V-2456 2455 2456 221.002290726 6.70977258682 155 0 Open ; +P-V-2457 2456 2457 707.244506836 12.1735267639 155 0 Open ; +P-V-2458 2457 2458 373.581222534 6.59292221069 155 0 Open ; +P-V-2459 2458 2459 312.332992554 10.6125040054 155 0 Open ; +P-V-2460 2459 2460 767.729858398 3.7139095068 155 0 Open ; +P-V-2461 2460 2461 733.874694824 11.6300439835 155 0 Open ; +P-V-2462 2461 2462 257.586967468 4.28363311291 155 0 Open ; +P-V-2463 2462 2463 701.174560547 11.8264760971 155 0 Open ; +P-V-2464 2463 2464 329.496887207 8.08331918716 155 0 Open ; +P-V-2465 2464 2465 567.240203857 3.1294337064 155 0 Open ; +P-V-2466 2465 2466 369.624603271 8.61905002594 155 0 Open ; +P-V-2467 2466 2467 768.772888184 6.31981873512 155 0 Open ; +P-V-2468 2467 2468 609.689422607 4.01068615913 155 0 Open ; +P-V-2469 2468 2469 530.192474365 5.90270614624 155 0 Open ; +P-V-2470 2469 2470 489.173736572 5.860902071 155 0 Open ; +P-V-2471 2470 2471 759.220825195 11.4922866821 155 0 Open ; +P-V-2472 2471 2472 293.428138733 3.93488258123 155 0 Open ; +P-V-2473 2472 2473 428.602539062 9.46122121811 155 0 Open ; +P-V-2474 2473 2474 487.544311523 10.1434693336 155 0 Open ; +P-V-2475 2474 2475 214.321146965 4.91076135635 155 0 Open ; +P-V-2476 2475 2476 308.264297485 10.9608621597 155 0 Open ; +P-V-2477 2476 2477 710.570678711 14.2342700958 155 0 Open ; +P-V-2478 2477 2478 519.118896484 3.6303332448 155 0 Open ; +P-V-2479 2478 2479 700.580078125 3.98855859041 155 0 Open ; +P-V-2480 2479 2480 535.218078613 3.21239563823 155 0 Open ; +P-V-2481 2480 2481 486.684051514 8.97966098785 155 0 Open ; +P-V-2482 2481 2482 208.484453201 10.9640197754 155 0 Open ; +P-V-2483 2482 2483 364.433029175 3.519713521 155 0 Open ; +P-V-2484 2483 2484 741.274780273 3.11021807045 155 0 Open ; +P-V-2485 2484 2485 421.75553894 11.9084386826 155 0 Open ; +P-V-2486 2485 2486 207.037349701 4.53475964069 155 0 Open ; +P-V-2487 2486 2487 535.250549316 14.1266117096 155 0 Open ; +P-V-2488 2487 2488 648.345458984 13.8480958939 155 0 Open ; +P-V-2489 2488 2489 597.963104248 10.3183498383 155 0 Open ; +P-V-2490 2489 2490 775.409973145 5.30698776245 155 0 Open ; +P-V-2491 2490 2491 277.160812378 7.83719873428 155 0 Open ; +P-V-2492 2491 2492 740.249389648 6.42959046364 155 0 Open ; +P-V-2493 2492 2493 456.295806885 6.27238869667 155 0 Open ; +P-V-2494 2493 2494 351.71572876 12.7289934158 155 0 Open ; +P-V-2495 2494 2495 359.66619873 9.19476461411 155 0 Open ; +P-V-2496 2495 2496 370.932693481 4.31361627579 155 0 Open ; +P-V-2497 2496 2497 697.473876953 3.86775201559 155 0 Open ; +P-V-2498 2497 2498 415.430130005 9.68063497543 155 0 Open ; +P-V-2499 2498 2499 671.80456543 3.38974776864 155 0 Open ; +P-H-50 0 50 617.95022583 8.79967451096 155 0 Open ; +P-H-51 1 51 216.48315239 11.6469993591 155 0 Open ; +P-H-52 2 52 378.060638428 12.3022813797 155 0 Open ; +P-H-53 3 53 268.962333679 11.9996509552 155 0 Open ; +P-H-54 4 54 481.475982666 10.3423547745 155 0 Open ; +P-H-55 5 55 570.30065918 11.8620328903 155 0 Open ; +P-H-57 7 57 689.182983398 12.9675321579 155 0 Open ; +P-H-59 9 59 414.326446533 10.6931695938 155 0 Open ; +P-H-60 10 60 626.968017578 4.02705860138 155 0 Open ; +P-H-62 12 62 737.970397949 8.37767982483 155 0 Open ; +P-H-63 13 63 270.162757874 7.50953149796 155 0 Open ; +P-H-64 14 64 267.572319031 12.7604284286 155 0 Open ; +P-H-66 16 66 738.25201416 7.04121637344 155 0 Open ; +P-H-72 22 72 427.946182251 4.83443212509 155 0 Open ; +P-H-76 26 76 320.710334778 6.57356643677 155 0 Open ; +P-H-79 29 79 725.075561523 5.91039347649 155 0 Open ; +P-H-82 32 82 390.93637085 8.35103702545 155 0 Open ; +P-H-83 33 83 511.037994385 11.314040184 155 0 Open ; +P-H-84 34 84 684.893707275 11.1763811111 155 0 Open ; +P-H-85 35 85 628.51473999 7.94569730759 155 0 Open ; +P-H-86 36 86 741.835876465 11.7131004333 155 0 Open ; +P-H-88 38 88 648.804473877 12.1356058121 155 0 Open ; +P-H-90 40 90 315.675613403 6.20295262337 155 0 Open ; +P-H-94 44 94 683.834289551 3.06161644682 155 0 Open ; +P-H-96 46 96 750.206420898 5.38955235481 155 0 Open ; +P-H-97 47 97 636.301757812 9.48359918594 155 0 Open ; +P-H-98 48 98 753.898193359 10.3538451195 155 0 Open ; +P-H-99 49 99 724.380249023 12.1826372147 155 0 Open ; +P-H-104 54 104 603.361663818 12.9906024933 155 0 Open ; +P-H-105 55 105 715.985839844 10.499434948 155 0 Open ; +P-H-106 56 106 517.041564941 13.3596954346 155 0 Open ; +P-H-107 57 107 586.488830566 5.35431861877 155 0 Open ; +P-H-110 60 110 552.839447021 10.452583313 155 0 Open ; +P-H-111 61 111 226.177236557 6.21666741371 155 0 Open ; +P-H-115 65 115 417.887145996 7.59130954742 155 0 Open ; +P-H-116 66 116 384.562973022 14.0005044937 155 0 Open ; +P-H-118 68 118 248.929321289 10.1017560959 155 0 Open ; +P-H-119 69 119 505.432861328 11.2011051178 155 0 Open ; +P-H-121 71 121 668.762573242 12.8596715927 155 0 Open ; +P-H-123 73 123 347.971221924 14.0483045578 155 0 Open ; +P-H-125 75 125 379.449142456 11.0411167145 155 0 Open ; +P-H-127 77 127 666.106506348 8.04819059372 155 0 Open ; +P-H-130 80 130 768.598449707 7.68938732147 155 0 Open ; +P-H-131 81 131 516.120788574 3.84015893936 155 0 Open ; +P-H-132 82 132 790.542663574 4.01117146015 155 0 Open ; +P-H-134 84 134 362.334152222 6.00558328629 155 0 Open ; +P-H-135 85 135 799.560791016 11.3803682327 155 0 Open ; +P-H-140 90 140 427.031799316 9.47516059875 155 0 Open ; +P-H-142 92 142 288.837173462 8.72967004776 155 0 Open ; +P-H-143 93 143 739.881713867 14.835190773 155 0 Open ; +P-H-145 95 145 706.788635254 14.9429531097 155 0 Open ; +P-H-147 97 147 561.218109131 6.86641716957 155 0 Open ; +P-H-149 99 149 401.445968628 13.048491478 155 0 Open ; +P-H-150 100 150 384.148300171 6.61236786842 155 0 Open ; +P-H-152 102 152 438.771057129 7.50634241104 155 0 Open ; +P-H-153 103 153 324.1510849 11.1463384628 155 0 Open ; +P-H-154 104 154 564.624359131 11.8310241699 155 0 Open ; +P-H-155 105 155 675.00390625 10.8181600571 155 0 Open ; +P-H-156 106 156 635.209655762 14.3777933121 155 0 Open ; +P-H-157 107 157 515.521820068 6.51300811768 155 0 Open ; +P-H-159 109 159 280.917266846 10.5291523933 155 0 Open ; +P-H-162 112 162 640.130645752 12.5199117661 155 0 Open ; +P-H-164 114 164 248.634307861 6.93727493286 155 0 Open ; +P-H-166 116 166 309.278076172 3.73184275627 155 0 Open ; +P-H-170 120 170 244.983863831 3.87646460533 155 0 Open ; +P-H-171 121 171 429.296646118 14.7766838074 155 0 Open ; +P-H-173 123 173 225.682653427 7.96711540222 155 0 Open ; +P-H-174 124 174 223.358861923 6.84828615189 155 0 Open ; +P-H-175 125 175 726.161499023 10.9393305779 155 0 Open ; +P-H-176 126 176 392.085601807 10.6561779976 155 0 Open ; +P-H-179 129 179 515.460113525 9.76621103287 155 0 Open ; +P-H-180 130 180 463.893981934 4.32203149796 155 0 Open ; +P-H-181 131 181 552.924163818 14.9334926605 155 0 Open ; +P-H-182 132 182 441.456161499 10.0771493912 155 0 Open ; +P-H-189 139 189 486.659332275 12.667681694 155 0 Open ; +P-H-191 141 191 741.667541504 3.14075441658 155 0 Open ; +P-H-196 146 196 596.018280029 4.58588933945 155 0 Open ; +P-H-198 148 198 401.276031494 3.92833083868 155 0 Open ; +P-H-200 150 200 424.096740723 6.8785443306 155 0 Open ; +P-H-202 152 202 498.199859619 3.90756338835 155 0 Open ; +P-H-204 154 204 530.034698486 12.8672523499 155 0 Open ; +P-H-205 155 205 267.510253906 3.89623641968 155 0 Open ; +P-H-207 157 207 535.837402344 7.38727474213 155 0 Open ; +P-H-208 158 208 793.199951172 9.24734258652 155 0 Open ; +P-H-209 159 209 529.755371094 14.981719017 155 0 Open ; +P-H-212 162 212 378.096633911 12.405667305 155 0 Open ; +P-H-214 164 214 696.243438721 10.2802634239 155 0 Open ; +P-H-215 165 215 463.839752197 10.0929455757 155 0 Open ; +P-H-220 170 220 366.07989502 5.09724998474 155 0 Open ; +P-H-223 173 223 340.510665894 14.2575759888 155 0 Open ; +P-H-225 175 225 516.68838501 14.633266449 155 0 Open ; +P-H-229 179 229 485.46496582 7.19146776199 155 0 Open ; +P-H-230 180 230 682.631408691 6.73475718498 155 0 Open ; +P-H-231 181 231 292.137245178 14.0160827637 155 0 Open ; +P-H-232 182 232 628.690185547 6.92963075638 155 0 Open ; +P-H-233 183 233 535.309051514 9.78595066071 155 0 Open ; +P-H-236 186 236 626.081298828 5.97086763382 155 0 Open ; +P-H-237 187 237 513.23236084 4.93369066715 155 0 Open ; +P-H-240 190 240 552.00201416 4.96334457397 155 0 Open ; +P-H-241 191 241 408.908477783 13.4940061569 155 0 Open ; +P-H-242 192 242 644.485534668 12.372220993 155 0 Open ; +P-H-243 193 243 270.429916382 13.3129863739 155 0 Open ; +P-H-246 196 246 513.941772461 3.38215604424 155 0 Open ; +P-H-248 198 248 415.6328125 5.81672430038 155 0 Open ; +P-H-252 202 252 629.665802002 10.8712511063 155 0 Open ; +P-H-255 205 255 742.088256836 12.5385150909 155 0 Open ; +P-H-259 209 259 400.295913696 10.4743742943 155 0 Open ; +P-H-262 212 262 534.959869385 12.4158630371 155 0 Open ; +P-H-263 213 263 422.714614868 10.2884221077 155 0 Open ; +P-H-265 215 265 755.896911621 10.179681778 155 0 Open ; +P-H-266 216 266 486.071563721 7.09051990509 155 0 Open ; +P-H-271 221 271 215.532251358 4.01106655598 155 0 Open ; +P-H-276 226 276 636.073791504 4.84112370014 155 0 Open ; +P-H-277 227 277 399.364822388 9.49213886261 155 0 Open ; +P-H-278 228 278 579.092681885 3.21865230799 155 0 Open ; +P-H-280 230 280 588.598480225 6.49775528908 155 0 Open ; +P-H-281 231 281 770.781311035 9.42888021469 155 0 Open ; +P-H-283 233 283 245.563755035 6.80208349228 155 0 Open ; +P-H-285 235 285 452.300231934 7.19999170303 155 0 Open ; +P-H-290 240 290 391.739852905 14.4364728928 155 0 Open ; +P-H-291 241 291 702.558227539 8.9294757843 155 0 Open ; +P-H-292 242 292 769.972167969 13.4513092041 155 0 Open ; +P-H-293 243 293 436.324768066 13.2053461075 155 0 Open ; +P-H-295 245 295 712.540283203 4.28509712219 155 0 Open ; +P-H-296 246 296 645.321105957 5.24311375618 155 0 Open ; +P-H-297 247 297 744.433898926 9.00602388382 155 0 Open ; +P-H-298 248 298 253.429943085 10.9411568642 155 0 Open ; +P-H-300 250 300 647.927276611 5.27717542648 155 0 Open ; +P-H-306 256 306 364.164505005 9.25944900513 155 0 Open ; +P-H-307 257 307 441.309707642 8.84765863419 155 0 Open ; +P-H-309 259 309 775.154846191 3.54372376204 155 0 Open ; +P-H-310 260 310 467.444366455 9.74873828888 155 0 Open ; +P-H-312 262 312 644.451171875 12.8238801956 155 0 Open ; +P-H-314 264 314 442.756210327 3.07593832165 155 0 Open ; +P-H-317 267 317 217.159425735 10.9694671631 155 0 Open ; +P-H-318 268 318 706.767822266 7.94289207458 155 0 Open ; +P-H-319 269 319 542.254333496 4.37336790562 155 0 Open ; +P-H-320 270 320 269.804267883 7.00629758835 155 0 Open ; +P-H-324 274 324 561.043121338 8.04561710358 155 0 Open ; +P-H-325 275 325 580.990234375 5.05941963196 155 0 Open ; +P-H-328 278 328 524.125305176 6.48721241951 155 0 Open ; +P-H-331 281 331 561.397583008 7.18048810959 155 0 Open ; +P-H-336 286 336 697.935760498 3.13020811975 155 0 Open ; +P-H-338 288 338 360.281921387 12.1660108566 155 0 Open ; +P-H-339 289 339 657.212158203 6.30604219437 155 0 Open ; +P-H-342 292 342 770.567443848 9.54035997391 155 0 Open ; +P-H-346 296 346 432.669342041 8.47348022461 155 0 Open ; +P-H-348 298 348 735.018005371 11.9582443237 155 0 Open ; +P-H-349 299 349 444.948532104 7.99863433838 155 0 Open ; +P-H-351 301 351 257.413414001 5.94678449631 155 0 Open ; +P-H-356 306 356 750.86730957 11.5412626266 155 0 Open ; +P-H-357 307 357 747.674499512 6.32045030594 155 0 Open ; +P-H-358 308 358 285.637237549 13.1023426056 155 0 Open ; +P-H-364 314 364 645.48236084 11.4397497177 155 0 Open ; +P-H-365 315 365 402.490921021 4.29697751999 155 0 Open ; +P-H-366 316 366 514.149078369 13.0749092102 155 0 Open ; +P-H-367 317 367 442.926620483 12.3610162735 155 0 Open ; +P-H-368 318 368 523.005371094 14.0323076248 155 0 Open ; +P-H-369 319 369 542.897918701 4.71343564987 155 0 Open ; +P-H-370 320 370 613.411376953 7.09738588333 155 0 Open ; +P-H-371 321 371 371.552688599 8.72093868256 155 0 Open ; +P-H-372 322 372 611.507965088 3.29517397285 155 0 Open ; +P-H-374 324 374 453.842773438 9.71101140976 155 0 Open ; +P-H-377 327 377 413.041687012 10.8373389244 155 0 Open ; +P-H-378 328 378 508.501556396 10.7113771439 155 0 Open ; +P-H-380 330 380 610.953735352 8.99314928055 155 0 Open ; +P-H-381 331 381 624.935668945 4.87649703026 155 0 Open ; +P-H-383 333 383 747.261657715 11.535068512 155 0 Open ; +P-H-386 336 386 354.138824463 11.2263793945 155 0 Open ; +P-H-387 337 387 259.382804871 7.93684720993 155 0 Open ; +P-H-393 343 393 767.40057373 13.0399694443 155 0 Open ; +P-H-394 344 394 643.601623535 3.25218874216 155 0 Open ; +P-H-396 346 396 769.07244873 11.0103473663 155 0 Open ; +P-H-399 349 399 468.42300415 14.7052192688 155 0 Open ; +P-H-403 353 403 666.046386719 11.8388767242 155 0 Open ; +P-H-404 354 404 344.916931152 7.37529277802 155 0 Open ; +P-H-405 355 405 726.338867188 10.549498558 155 0 Open ; +P-H-406 356 406 411.331817627 12.0779838562 155 0 Open ; +P-H-408 358 408 669.773712158 4.73440730572 155 0 Open ; +P-H-411 361 411 483.659820557 12.4196643829 155 0 Open ; +P-H-413 363 413 505.372161865 14.804898262 155 0 Open ; +P-H-414 364 414 681.331481934 13.7702474594 155 0 Open ; +P-H-415 365 415 229.407119751 11.9094877243 155 0 Open ; +P-H-420 370 420 561.209869385 4.09118652344 155 0 Open ; +P-H-422 372 422 334.606964111 9.78610610962 155 0 Open ; +P-H-423 373 423 283.102828979 13.1837663651 155 0 Open ; +P-H-426 376 426 573.040374756 8.78730344772 155 0 Open ; +P-H-427 377 427 732.527587891 14.8280305862 155 0 Open ; +P-H-430 380 430 562.132720947 14.2916164398 155 0 Open ; +P-H-431 381 431 479.331817627 9.59676361084 155 0 Open ; +P-H-433 383 433 638.137268066 14.4653396606 155 0 Open ; +P-H-435 385 435 588.133026123 6.03730130196 155 0 Open ; +P-H-436 386 436 345.422042847 9.16633892059 155 0 Open ; +P-H-438 388 438 745.62713623 14.1157751083 155 0 Open ; +P-H-439 389 439 489.757843018 10.205974102 155 0 Open ; +P-H-440 390 440 437.637863159 10.5950093269 155 0 Open ; +P-H-443 393 443 497.273132324 4.39202070236 155 0 Open ; +P-H-444 394 444 445.103118896 11.9625015259 155 0 Open ; +P-H-445 395 445 529.88949585 12.0603847504 155 0 Open ; +P-H-446 396 446 269.754486084 14.2743339539 155 0 Open ; +P-H-447 397 447 408.064208984 5.70475459099 155 0 Open ; +P-H-451 401 451 527.547607422 4.85595929623 155 0 Open ; +P-H-454 404 454 345.284912109 11.0714969635 155 0 Open ; +P-H-455 405 455 547.898376465 5.56895589828 155 0 Open ; +P-H-457 407 457 593.587615967 3.54487025738 155 0 Open ; +P-H-459 409 459 277.262550354 6.03282904625 155 0 Open ; +P-H-460 410 460 483.708587646 4.80892717838 155 0 Open ; +P-H-461 411 461 695.189544678 4.01790547371 155 0 Open ; +P-H-462 412 462 255.602226257 9.13380146027 155 0 Open ; +P-H-463 413 463 779.664611816 7.45907497406 155 0 Open ; +P-H-468 418 468 211.359905243 5.51858878136 155 0 Open ; +P-H-470 420 470 343.450378418 6.4111392498 155 0 Open ; +P-H-471 421 471 338.966415405 11.1691579819 155 0 Open ; +P-H-472 422 472 216.677532196 4.98606932163 155 0 Open ; +P-H-473 423 473 352.099182129 9.62065458298 155 0 Open ; +P-H-474 424 474 383.152084351 7.74168729782 155 0 Open ; +P-H-478 428 478 427.076599121 12.5312795639 155 0 Open ; +P-H-482 432 482 262.181606293 12.7248792648 155 0 Open ; +P-H-483 433 483 737.49041748 3.03826741129 155 0 Open ; +P-H-484 434 484 626.910675049 8.7547492981 155 0 Open ; +P-H-487 437 487 728.991394043 14.1762228012 155 0 Open ; +P-H-489 439 489 558.264556885 10.0502786636 155 0 Open ; +P-H-490 440 490 451.253814697 3.4601354003 155 0 Open ; +P-H-492 442 492 723.664916992 11.7337522507 155 0 Open ; +P-H-494 444 494 574.544830322 10.5017399788 155 0 Open ; +P-H-495 445 495 213.751171112 5.31889390945 155 0 Open ; +P-H-496 446 496 749.596557617 4.38688826561 155 0 Open ; +P-H-499 449 499 704.162475586 8.18475627899 155 0 Open ; +P-H-500 450 500 315.241027832 4.12054598331 155 0 Open ; +P-H-503 453 503 582.287872314 9.25268745422 155 0 Open ; +P-H-506 456 506 750.395996094 9.11034822464 155 0 Open ; +P-H-508 458 508 389.844741821 13.4129667282 155 0 Open ; +P-H-510 460 510 513.141540527 10.399017334 155 0 Open ; +P-H-511 461 511 243.615207672 11.8164024353 155 0 Open ; +P-H-513 463 513 439.999206543 12.3389310837 155 0 Open ; +P-H-514 464 514 660.99520874 5.9323592186 155 0 Open ; +P-H-517 467 517 255.116027832 13.7022123337 155 0 Open ; +P-H-519 469 519 275.821350098 13.5903701782 155 0 Open ; +P-H-520 470 520 312.40814209 11.8728303909 155 0 Open ; +P-H-524 474 524 603.492919922 9.11056995392 155 0 Open ; +P-H-527 477 527 466.030426025 14.4719600677 155 0 Open ; +P-H-530 480 530 374.09324646 10.702671051 155 0 Open ; +P-H-532 482 532 703.746337891 12.2939786911 155 0 Open ; +P-H-533 483 533 758.078674316 11.571308136 155 0 Open ; +P-H-534 484 534 248.783485413 9.08057260513 155 0 Open ; +P-H-537 487 537 768.669555664 7.58172750473 155 0 Open ; +P-H-539 489 539 598.144744873 11.373796463 155 0 Open ; +P-H-543 493 543 285.970573425 5.14774417877 155 0 Open ; +P-H-545 495 545 705.969360352 3.54400706291 155 0 Open ; +P-H-546 496 546 446.959671021 12.0267620087 155 0 Open ; +P-H-547 497 547 226.166648865 14.6579856873 155 0 Open ; +P-H-548 498 548 562.962768555 5.30784845352 155 0 Open ; +P-H-550 500 550 660.806945801 14.6432971954 155 0 Open ; +P-H-552 502 552 478.354614258 5.11850476265 155 0 Open ; +P-H-554 504 554 700.081237793 4.3119468689 155 0 Open ; +P-H-556 506 556 347.973876953 14.9424829483 155 0 Open ; +P-H-561 511 561 611.944335938 5.97376227379 155 0 Open ; +P-H-563 513 563 644.275512695 13.7744874954 155 0 Open ; +P-H-564 514 564 531.107971191 13.6325712204 155 0 Open ; +P-H-565 515 565 249.979427338 3.08459664136 155 0 Open ; +P-H-570 520 570 761.798950195 14.0995807648 155 0 Open ; +P-H-571 521 571 377.653396606 7.41382360458 155 0 Open ; +P-H-572 522 572 226.363952637 8.9794216156 155 0 Open ; +P-H-573 523 573 316.003417969 8.39078092575 155 0 Open ; +P-H-578 528 578 373.57208252 3.52194899321 155 0 Open ; +P-H-581 531 581 262.157791138 4.72028839588 155 0 Open ; +P-H-583 533 583 676.276977539 6.74743938446 155 0 Open ; +P-H-584 534 584 691.926727295 11.2530879974 155 0 Open ; +P-H-586 536 586 569.651489258 9.65453052521 155 0 Open ; +P-H-588 538 588 205.094675064 11.524140358 155 0 Open ; +P-H-589 539 589 376.78843689 4.66818141937 155 0 Open ; +P-H-591 541 591 528.636627197 10.9147839546 155 0 Open ; +P-H-594 544 594 419.324493408 10.7381916046 155 0 Open ; +P-H-595 545 595 210.611631393 5.99376296997 155 0 Open ; +P-H-597 547 597 202.831772566 6.87204933167 155 0 Open ; +P-H-600 550 600 545.749206543 3.14188525081 155 0 Open ; +P-H-601 551 601 604.794769287 14.7089214325 155 0 Open ; +P-H-605 555 605 213.786784172 5.28985786438 155 0 Open ; +P-H-610 560 610 412.577575684 10.8305010796 155 0 Open ; +P-H-613 563 613 789.096862793 10.0197491646 155 0 Open ; +P-H-614 564 614 215.291577339 7.11107683182 155 0 Open ; +P-H-615 565 615 590.84387207 5.26513695717 155 0 Open ; +P-H-616 566 616 409.7449646 6.67444825172 155 0 Open ; +P-H-622 572 622 478.354522705 5.09418034554 155 0 Open ; +P-H-624 574 624 225.850749969 4.471372962 155 0 Open ; +P-H-625 575 625 468.438873291 8.04793739319 155 0 Open ; +P-H-628 578 628 546.888549805 14.1232299805 155 0 Open ; +P-H-630 580 630 233.278064728 5.08886432648 155 0 Open ; +P-H-631 581 631 461.48336792 10.028813839 155 0 Open ; +P-H-633 583 633 404.65826416 12.8322782516 155 0 Open ; +P-H-634 584 634 519.497802734 10.9889030457 155 0 Open ; +P-H-637 587 637 286.44708252 9.32447147369 155 0 Open ; +P-H-638 588 638 556.910247803 10.81057024 155 0 Open ; +P-H-642 592 642 233.315055847 5.52321195602 155 0 Open ; +P-H-643 593 643 241.552181244 14.3508110046 155 0 Open ; +P-H-644 594 644 461.639343262 14.4503355026 155 0 Open ; +P-H-648 598 648 687.815307617 9.24021577835 155 0 Open ; +P-H-649 599 649 414.581054688 12.2788381577 155 0 Open ; +P-H-650 600 650 691.585021973 4.39451444149 155 0 Open ; +P-H-655 605 655 208.542333603 6.42002987862 155 0 Open ; +P-H-657 607 657 343.642593384 11.0206661224 155 0 Open ; +P-H-658 608 658 587.719268799 10.9568338394 155 0 Open ; +P-H-662 612 662 306.802833557 11.7048597336 155 0 Open ; +P-H-663 613 663 344.101104736 9.14523029327 155 0 Open ; +P-H-664 614 664 763.734313965 4.66640043259 155 0 Open ; +P-H-665 615 665 393.542236328 8.29155826569 155 0 Open ; +P-H-671 621 671 545.744018555 13.39823246 155 0 Open ; +P-H-672 622 672 263.747631073 11.1287298203 155 0 Open ; +P-H-673 623 673 716.748962402 3.00267660432 155 0 Open ; +P-H-674 624 674 323.544326782 11.1901845932 155 0 Open ; +P-H-676 626 676 676.024139404 5.76039457321 155 0 Open ; +P-H-678 628 678 255.846179962 7.13533687592 155 0 Open ; +P-H-679 629 679 744.735046387 14.2467155457 155 0 Open ; +P-H-680 630 680 682.104156494 9.49829769135 155 0 Open ; +P-H-682 632 682 338.746810913 9.35168838501 155 0 Open ; +P-H-688 638 688 332.71055603 8.3272023201 155 0 Open ; +P-H-690 640 690 544.649108887 5.35927391052 155 0 Open ; +P-H-694 644 694 412.123550415 14.2147035599 155 0 Open ; +P-H-696 646 696 583.667419434 4.96788346767 155 0 Open ; +P-H-703 653 703 619.471008301 3.98690330982 155 0 Open ; +P-H-705 655 705 708.375671387 8.39372873306 155 0 Open ; +P-H-707 657 707 771.83782959 4.57442772388 155 0 Open ; +P-H-709 659 709 381.025344849 12.8606138229 155 0 Open ; +P-H-710 660 710 410.106048584 8.04631471634 155 0 Open ; +P-H-711 661 711 339.462799072 10.0293536186 155 0 Open ; +P-H-713 663 713 410.655563354 12.7590847015 155 0 Open ; +P-H-716 666 716 246.767906189 3.56452709436 155 0 Open ; +P-H-717 667 717 202.021972418 10.6657924652 155 0 Open ; +P-H-718 668 718 214.343000412 12.2564344406 155 0 Open ; +P-H-724 674 724 342.877990723 6.00914883614 155 0 Open ; +P-H-725 675 725 579.61428833 10.5521764755 155 0 Open ; +P-H-729 679 729 795.431030273 3.18910999596 155 0 Open ; +P-H-730 680 730 461.120056152 7.89434576035 155 0 Open ; +P-H-731 681 731 761.610595703 10.7902326584 155 0 Open ; +P-H-732 682 732 488.948822021 14.2552633286 155 0 Open ; +P-H-733 683 733 799.735107422 9.97633314133 155 0 Open ; +P-H-734 684 734 468.965209961 4.96799230576 155 0 Open ; +P-H-736 686 736 360.293869019 4.17943632603 155 0 Open ; +P-H-737 687 737 679.915374756 5.76289343834 155 0 Open ; +P-H-738 688 738 473.314422607 14.9125757217 155 0 Open ; +P-H-739 689 739 558.582183838 8.82462024689 155 0 Open ; +P-H-740 690 740 292.641487122 3.51035326719 155 0 Open ; +P-H-741 691 741 251.381206512 6.2796728611 155 0 Open ; +P-H-743 693 743 578.563812256 5.44987463951 155 0 Open ; +P-H-745 695 745 399.17250061 4.84579622746 155 0 Open ; +P-H-749 699 749 675.40914917 3.04300431907 155 0 Open ; +P-H-751 701 751 426.801895142 4.19067239761 155 0 Open ; +P-H-752 702 752 222.874181747 11.9274148941 155 0 Open ; +P-H-753 703 753 700.097167969 9.66969156265 155 0 Open ; +P-H-758 708 758 740.59552002 14.7762708664 155 0 Open ; +P-H-759 709 759 395.12272644 11.5570859909 155 0 Open ; +P-H-760 710 760 747.696533203 13.7066955566 155 0 Open ; +P-H-761 711 761 340.702041626 6.58544754982 155 0 Open ; +P-H-762 712 762 789.255126953 3.22049610317 155 0 Open ; +P-H-763 713 763 210.046676636 8.09004354477 155 0 Open ; +P-H-766 716 766 398.156906128 11.4635133743 155 0 Open ; +P-H-767 717 767 445.514801025 6.345921278 155 0 Open ; +P-H-770 720 770 498.582183838 12.4124765396 155 0 Open ; +P-H-771 721 771 292.780593872 14.2688083649 155 0 Open ; +P-H-772 722 772 544.527526855 12.4852466583 155 0 Open ; +P-H-773 723 773 639.776580811 13.5017795563 155 0 Open ; +P-H-774 724 774 556.005859375 6.8138833046 155 0 Open ; +P-H-775 725 775 524.73614502 7.81623601913 155 0 Open ; +P-H-776 726 776 409.812484741 5.37254691124 155 0 Open ; +P-H-777 727 777 633.588317871 9.37708187103 155 0 Open ; +P-H-778 728 778 423.538635254 11.2781248093 155 0 Open ; +P-H-783 733 783 290.794540405 6.67794537544 155 0 Open ; +P-H-787 737 787 320.495414734 6.32976031303 155 0 Open ; +P-H-788 738 788 792.148681641 3.85155183077 155 0 Open ; +P-H-789 739 789 303.70262146 13.5997819901 155 0 Open ; +P-H-790 740 790 401.731246948 12.9410190582 155 0 Open ; +P-H-793 743 793 569.237060547 14.3523263931 155 0 Open ; +P-H-794 744 794 250.942695618 14.8771762848 155 0 Open ; +P-H-795 745 795 214.138334274 3.46001949906 155 0 Open ; +P-H-800 750 800 289.135177612 12.8977422714 155 0 Open ; +P-H-801 751 801 707.525024414 10.4744524956 155 0 Open ; +P-H-802 752 802 241.87657547 3.39342239499 155 0 Open ; +P-H-804 754 804 365.81942749 13.5457229614 155 0 Open ; +P-H-806 756 806 345.178710938 11.3758335114 155 0 Open ; +P-H-808 758 808 758.352966309 7.77592420578 155 0 Open ; +P-H-810 760 810 693.609954834 13.0511255264 155 0 Open ; +P-H-813 763 813 351.234832764 7.0758061409 155 0 Open ; +P-H-814 764 814 580.057312012 3.4627828002 155 0 Open ; +P-H-817 767 817 715.678466797 3.17586433887 155 0 Open ; +P-H-819 769 819 224.552248001 11.9929742813 155 0 Open ; +P-H-826 776 826 784.507080078 3.21180340648 155 0 Open ; +P-H-827 777 827 558.419921875 14.2760782242 155 0 Open ; +P-H-830 780 830 755.311828613 5.53238725662 155 0 Open ; +P-H-831 781 831 350.291931152 14.1305780411 155 0 Open ; +P-H-833 783 833 701.993286133 11.0317668915 155 0 Open ; +P-H-835 785 835 635.177032471 3.4162440896 155 0 Open ; +P-H-836 786 836 377.050643921 8.80743741989 155 0 Open ; +P-H-837 787 837 742.605163574 6.30523204803 155 0 Open ; +P-H-840 790 840 794.164306641 9.3872256279 155 0 Open ; +P-H-841 791 841 387.457992554 3.13251142204 155 0 Open ; +P-H-842 792 842 473.956573486 14.7659683228 155 0 Open ; +P-H-844 794 844 660.795227051 10.714867115 155 0 Open ; +P-H-847 797 847 233.461017609 6.58618855476 155 0 Open ; +P-H-848 798 848 560.736114502 12.839630127 155 0 Open ; +P-H-851 801 851 527.446655273 6.91540646553 155 0 Open ; +P-H-852 802 852 366.560577393 10.6724867821 155 0 Open ; +P-H-853 803 853 675.991088867 6.64632439613 155 0 Open ; +P-H-854 804 854 564.006774902 8.23758172989 155 0 Open ; +P-H-855 805 855 352.316818237 10.7761073112 155 0 Open ; +P-H-859 809 859 604.778015137 9.08886814117 155 0 Open ; +P-H-860 810 860 727.649658203 7.17627906799 155 0 Open ; +P-H-863 813 863 315.973693848 10.398730278 155 0 Open ; +P-H-864 814 864 768.81072998 7.0365729332 155 0 Open ; +P-H-865 815 865 693.725402832 3.85720688105 155 0 Open ; +P-H-866 816 866 590.348602295 6.77600455284 155 0 Open ; +P-H-867 817 867 702.513702393 5.96746110916 155 0 Open ; +P-H-869 819 869 440.67527771 11.5903978348 155 0 Open ; +P-H-870 820 870 247.128276825 4.69897305965 155 0 Open ; +P-H-871 821 871 235.757389069 10.4894685745 155 0 Open ; +P-H-872 822 872 794.589172363 8.21824550629 155 0 Open ; +P-H-873 823 873 386.113510132 7.19791030884 155 0 Open ; +P-H-874 824 874 424.938110352 13.6946334839 155 0 Open ; +P-H-875 825 875 593.432495117 11.3954229355 155 0 Open ; +P-H-877 827 877 306.060272217 14.0997800827 155 0 Open ; +P-H-879 829 879 527.050933838 5.89752650261 155 0 Open ; +P-H-881 831 881 641.345031738 12.7212934494 155 0 Open ; +P-H-883 833 883 614.752075195 13.7681531906 155 0 Open ; +P-H-884 834 884 312.078697205 9.13436985016 155 0 Open ; +P-H-885 835 885 271.934799194 3.16285018623 155 0 Open ; +P-H-891 841 891 574.568267822 6.37935614586 155 0 Open ; +P-H-895 845 895 796.15057373 5.05124974251 155 0 Open ; +P-H-896 846 896 212.600633621 14.5770406723 155 0 Open ; +P-H-897 847 897 534.761413574 5.71106028557 155 0 Open ; +P-H-905 855 905 382.756210327 6.66989946365 155 0 Open ; +P-H-909 859 909 431.027938843 8.7336063385 155 0 Open ; +P-H-912 862 912 746.74420166 5.59169507027 155 0 Open ; +P-H-913 863 913 616.012207031 5.35530018806 155 0 Open ; +P-H-914 864 914 574.91595459 3.24727264047 155 0 Open ; +P-H-918 868 918 718.271362305 10.7346200943 155 0 Open ; +P-H-919 869 919 344.653305054 14.7598800659 155 0 Open ; +P-H-920 870 920 765.105407715 9.5429725647 155 0 Open ; +P-H-921 871 921 258.92282486 9.31922149658 155 0 Open ; +P-H-922 872 922 675.29095459 11.3140058517 155 0 Open ; +P-H-924 874 924 743.567749023 5.86339688301 155 0 Open ; +P-H-926 876 926 798.258789062 5.71627616882 155 0 Open ; +P-H-928 878 928 408.744750977 6.46602153778 155 0 Open ; +P-H-930 880 930 321.482696533 14.1935186386 155 0 Open ; +P-H-934 884 934 731.81652832 3.82179617882 155 0 Open ; +P-H-935 885 935 722.574707031 5.26038002968 155 0 Open ; +P-H-936 886 936 589.368255615 13.2499198914 155 0 Open ; +P-H-937 887 937 412.311218262 5.29207801819 155 0 Open ; +P-H-946 896 946 744.056518555 14.1635255814 155 0 Open ; +P-H-948 898 948 703.243225098 11.1808204651 155 0 Open ; +P-H-949 899 949 683.226165771 14.6480894089 155 0 Open ; +P-H-954 904 954 745.329101562 9.92873239517 155 0 Open ; +P-H-956 906 956 389.939682007 9.32361030579 155 0 Open ; +P-H-957 907 957 765.060546875 6.45332551003 155 0 Open ; +P-H-958 908 958 341.289382935 12.0150661469 155 0 Open ; +P-H-961 911 961 551.229187012 9.17875671387 155 0 Open ; +P-H-962 912 962 545.794433594 6.34000563622 155 0 Open ; +P-H-963 913 963 356.91645813 8.90390539169 155 0 Open ; +P-H-964 914 964 408.073043823 8.67157459259 155 0 Open ; +P-H-965 915 965 705.889312744 12.6408004761 155 0 Open ; +P-H-966 916 966 479.965270996 6.52907395363 155 0 Open ; +P-H-967 917 967 328.432830811 10.4133915901 155 0 Open ; +P-H-971 921 971 240.278427124 6.19115447998 155 0 Open ; +P-H-973 923 973 287.487915039 11.1901311874 155 0 Open ; +P-H-974 924 974 367.252624512 3.29860320687 155 0 Open ; +P-H-976 926 976 698.496734619 11.6893253326 155 0 Open ; +P-H-978 928 978 363.47215271 4.53246665001 155 0 Open ; +P-H-980 930 980 422.057418823 5.37988376617 155 0 Open ; +P-H-985 935 985 786.397583008 14.6810865402 155 0 Open ; +P-H-988 938 988 458.782348633 14.1061792374 155 0 Open ; +P-H-990 940 990 693.708465576 10.1739478111 155 0 Open ; +P-H-991 941 991 770.06817627 9.72700595856 155 0 Open ; +P-H-992 942 992 644.79284668 7.67259407043 155 0 Open ; +P-H-997 947 997 224.95549202 3.53861552477 155 0 Open ; +P-H-999 949 999 614.176574707 12.3182430267 155 0 Open ; +P-H-1000 950 1000 526.215545654 13.0993251801 155 0 Open ; +P-H-1001 951 1001 210.356031418 4.07628846169 155 0 Open ; +P-H-1004 954 1004 442.181747437 13.9744577408 155 0 Open ; +P-H-1005 955 1005 607.920166016 9.29512310028 155 0 Open ; +P-H-1006 956 1006 740.043334961 9.17298460007 155 0 Open ; +P-H-1007 957 1007 650.698028564 12.6405057907 155 0 Open ; +P-H-1009 959 1009 499.39074707 8.21348428726 155 0 Open ; +P-H-1010 960 1010 269.753158569 13.8277616501 155 0 Open ; +P-H-1014 964 1014 272.053855896 7.18298912048 155 0 Open ; +P-H-1015 965 1015 494.901763916 11.2793169022 155 0 Open ; +P-H-1016 966 1016 449.447097778 8.14774894714 155 0 Open ; +P-H-1017 967 1017 477.530059814 3.96407288313 155 0 Open ; +P-H-1019 969 1019 737.241638184 3.4101934731 155 0 Open ; +P-H-1020 970 1020 464.695159912 9.62749147415 155 0 Open ; +P-H-1022 972 1022 623.838989258 8.24145030975 155 0 Open ; +P-H-1027 977 1027 618.554138184 7.78689193726 155 0 Open ; +P-H-1030 980 1030 583.837341309 14.0847578049 155 0 Open ; +P-H-1032 982 1032 316.793746948 10.0504994392 155 0 Open ; +P-H-1033 983 1033 343.435668945 13.4680356979 155 0 Open ; +P-H-1036 986 1036 469.121734619 9.58730268478 155 0 Open ; +P-H-1038 988 1038 707.462127686 13.3263502121 155 0 Open ; +P-H-1039 989 1039 718.005432129 5.35294389725 155 0 Open ; +P-H-1042 992 1042 273.119522095 5.3979139328 155 0 Open ; +P-H-1045 995 1045 366.284881592 14.0007305145 155 0 Open ; +P-H-1047 997 1047 597.281158447 9.0926656723 155 0 Open ; +P-H-1050 1000 1050 537.97479248 5.84421634674 155 0 Open ; +P-H-1051 1001 1051 487.547454834 11.2058515549 155 0 Open ; +P-H-1052 1002 1052 539.980865479 8.16879367828 155 0 Open ; +P-H-1054 1004 1054 262.932685852 13.1945047379 155 0 Open ; +P-H-1059 1009 1059 534.512634277 6.07584881783 155 0 Open ; +P-H-1060 1010 1060 623.300598145 7.27124977112 155 0 Open ; +P-H-1063 1013 1063 285.508872986 5.95384740829 155 0 Open ; +P-H-1065 1015 1065 306.249794006 5.80874276161 155 0 Open ; +P-H-1066 1016 1066 613.239624023 9.37531471252 155 0 Open ; +P-H-1068 1018 1068 236.307983398 3.56616503 155 0 Open ; +P-H-1069 1019 1069 731.588989258 11.3193492889 155 0 Open ; +P-H-1070 1020 1070 732.5625 14.5668334961 155 0 Open ; +P-H-1072 1022 1072 350.410385132 5.95311784744 155 0 Open ; +P-H-1079 1029 1079 785.59173584 7.81173038483 155 0 Open ; +P-H-1081 1031 1081 534.153808594 5.4626390934 155 0 Open ; +P-H-1084 1034 1084 233.638767242 6.33507084846 155 0 Open ; +P-H-1086 1036 1086 418.81867981 8.7134809494 155 0 Open ; +P-H-1088 1038 1088 708.61895752 6.18367052078 155 0 Open ; +P-H-1089 1039 1089 338.77003479 5.15943074226 155 0 Open ; +P-H-1095 1045 1095 583.652648926 12.0075931549 155 0 Open ; +P-H-1096 1046 1096 435.232498169 6.05408501625 155 0 Open ; +P-H-1097 1047 1097 507.248687744 9.57000160217 155 0 Open ; +P-H-1098 1048 1098 788.088623047 7.10699892044 155 0 Open ; +P-H-1101 1051 1101 493.332672119 11.846329689 155 0 Open ; +P-H-1103 1053 1103 526.279632568 10.6351137161 155 0 Open ; +P-H-1104 1054 1104 417.48916626 5.80970168114 155 0 Open ; +P-H-1108 1058 1108 208.860660553 5.42240071297 155 0 Open ; +P-H-1109 1059 1109 712.423828125 13.1533126831 155 0 Open ; +P-H-1110 1060 1110 617.014465332 6.25269770622 155 0 Open ; +P-H-1111 1061 1111 235.435535431 10.3013081551 155 0 Open ; +P-H-1114 1064 1114 785.314941406 10.7758598328 155 0 Open ; +P-H-1115 1065 1115 300.055755615 11.7436380386 155 0 Open ; +P-H-1117 1067 1117 639.752380371 5.37096428871 155 0 Open ; +P-H-1118 1068 1118 237.544452667 11.191827774 155 0 Open ; +P-H-1121 1071 1121 696.481109619 6.16022610664 155 0 Open ; +P-H-1125 1075 1125 532.394744873 14.1781244278 155 0 Open ; +P-H-1126 1076 1126 467.737609863 12.3191041946 155 0 Open ; +P-H-1129 1079 1129 682.250976562 10.8436818123 155 0 Open ; +P-H-1130 1080 1130 550.185028076 6.19511556625 155 0 Open ; +P-H-1135 1085 1135 665.40612793 12.6159448624 155 0 Open ; +P-H-1136 1086 1136 556.49432373 3.00403560698 155 0 Open ; +P-H-1137 1087 1137 554.358184814 4.96427106857 155 0 Open ; +P-H-1141 1091 1141 259.113376617 13.3715419769 155 0 Open ; +P-H-1144 1094 1144 303.777412415 14.7386741638 155 0 Open ; +P-H-1145 1095 1145 487.776000977 4.02216696739 155 0 Open ; +P-H-1146 1096 1146 669.785095215 8.56723070145 155 0 Open ; +P-H-1149 1099 1149 341.895462036 11.73990345 155 0 Open ; +P-H-1150 1100 1150 226.463064194 6.29486656189 155 0 Open ; +P-H-1151 1101 1151 708.384735107 11.4453554153 155 0 Open ; +P-H-1153 1103 1153 723.079772949 7.04457044601 155 0 Open ; +P-H-1154 1104 1154 544.237030029 10.8354492188 155 0 Open ; +P-H-1156 1106 1156 489.908355713 12.8004455566 155 0 Open ; +P-H-1158 1108 1158 628.812194824 11.9359855652 155 0 Open ; +P-H-1159 1109 1159 492.954284668 4.6559650898 155 0 Open ; +P-H-1161 1111 1161 728.411804199 11.3520336151 155 0 Open ; +P-H-1162 1112 1162 300.832984924 9.00168085098 155 0 Open ; +P-H-1163 1113 1163 422.089279175 4.09208583832 155 0 Open ; +P-H-1164 1114 1164 477.971130371 8.21500968933 155 0 Open ; +P-H-1166 1116 1166 759.979553223 14.5427350998 155 0 Open ; +P-H-1167 1117 1167 378.00944519 7.09585189819 155 0 Open ; +P-H-1168 1118 1168 598.314727783 8.5116147995 155 0 Open ; +P-H-1170 1120 1170 540.635742188 12.2973566055 155 0 Open ; +P-H-1171 1121 1171 591.82244873 10.2018017769 155 0 Open ; +P-H-1172 1122 1172 592.546203613 13.4910955429 155 0 Open ; +P-H-1173 1123 1173 451.112457275 3.94264751673 155 0 Open ; +P-H-1176 1126 1176 488.124664307 13.2324085236 155 0 Open ; +P-H-1178 1128 1178 327.277961731 6.21311068535 155 0 Open ; +P-H-1180 1130 1180 639.494842529 14.8057479858 155 0 Open ; +P-H-1181 1131 1181 794.821105957 14.1738605499 155 0 Open ; +P-H-1182 1132 1182 664.815856934 6.21335220337 155 0 Open ; +P-H-1183 1133 1183 262.6316185 7.99250650406 155 0 Open ; +P-H-1185 1135 1185 405.183822632 9.49011898041 155 0 Open ; +P-H-1186 1136 1186 473.1222229 10.3084964752 155 0 Open ; +P-H-1191 1141 1191 541.115753174 5.65358018875 155 0 Open ; +P-H-1192 1142 1192 387.086151123 10.1370668411 155 0 Open ; +P-H-1194 1144 1194 457.770568848 9.99853038788 155 0 Open ; +P-H-1197 1147 1197 669.803527832 14.7602682114 155 0 Open ; +P-H-1201 1151 1201 400.99407959 5.15106153488 155 0 Open ; +P-H-1202 1152 1202 462.899536133 6.0535428524 155 0 Open ; +P-H-1203 1153 1203 234.91191864 14.2933702469 155 0 Open ; +P-H-1206 1156 1206 614.47756958 5.49028229713 155 0 Open ; +P-H-1207 1157 1207 746.395446777 8.37750864029 155 0 Open ; +P-H-1208 1158 1208 268.692260742 5.21730542183 155 0 Open ; +P-H-1209 1159 1209 471.28314209 4.1219022274 155 0 Open ; +P-H-1213 1163 1213 435.029052734 9.67193460464 155 0 Open ; +P-H-1214 1164 1214 459.020263672 10.0727334023 155 0 Open ; +P-H-1215 1165 1215 244.565624237 7.28910827637 155 0 Open ; +P-H-1217 1167 1217 676.555267334 4.28078532219 155 0 Open ; +P-H-1218 1168 1218 216.778215408 14.8295125961 155 0 Open ; +P-H-1220 1170 1220 402.386474609 5.18678927422 155 0 Open ; +P-H-1221 1171 1221 351.143478394 12.3720827103 155 0 Open ; +P-H-1223 1173 1223 431.321609497 11.4486036301 155 0 Open ; +P-H-1224 1174 1224 592.205596924 6.99644732475 155 0 Open ; +P-H-1226 1176 1226 319.354698181 6.88878846169 155 0 Open ; +P-H-1227 1177 1227 733.469055176 7.28996419907 155 0 Open ; +P-H-1230 1180 1230 487.967254639 8.31275367737 155 0 Open ; +P-H-1231 1181 1231 297.133468628 13.4447307587 155 0 Open ; +P-H-1232 1182 1232 789.696105957 7.44654512405 155 0 Open ; +P-H-1233 1183 1233 657.342254639 14.0373830795 155 0 Open ; +P-H-1234 1184 1234 362.892623901 13.7299718857 155 0 Open ; +P-H-1236 1186 1236 332.785171509 9.40852451324 155 0 Open ; +P-H-1237 1187 1237 742.512451172 11.1437597275 155 0 Open ; +P-H-1239 1189 1239 649.806182861 12.8508052826 155 0 Open ; +P-H-1240 1190 1240 462.997528076 14.9924764633 155 0 Open ; +P-H-1244 1194 1244 751.113098145 10.167154789 155 0 Open ; +P-H-1247 1197 1247 236.173305511 6.29562759399 155 0 Open ; +P-H-1248 1198 1248 471.514373779 9.84225702286 155 0 Open ; +P-H-1250 1200 1250 228.529367447 4.86181604862 155 0 Open ; +P-H-1251 1201 1251 340.432174683 11.876168251 155 0 Open ; +P-H-1252 1202 1252 695.626678467 6.95767521858 155 0 Open ; +P-H-1256 1206 1256 277.911720276 8.246717453 155 0 Open ; +P-H-1258 1208 1258 287.460044861 13.8199949265 155 0 Open ; +P-H-1260 1210 1260 225.542881012 8.98401212692 155 0 Open ; +P-H-1263 1213 1263 226.176935196 6.1150496006 155 0 Open ; +P-H-1264 1214 1264 462.108764648 4.24412190914 155 0 Open ; +P-H-1268 1218 1268 385.336303711 9.94794464111 155 0 Open ; +P-H-1270 1220 1270 786.2265625 5.21747326851 155 0 Open ; +P-H-1271 1221 1271 424.067337036 8.99750232697 155 0 Open ; +P-H-1273 1223 1273 474.781982422 4.22177886963 155 0 Open ; +P-H-1276 1226 1276 420.869934082 14.2185220718 155 0 Open ; +P-H-1278 1228 1278 535.273376465 9.7948884964 155 0 Open ; +P-H-1279 1229 1279 247.139160156 8.35852050781 155 0 Open ; +P-H-1281 1231 1281 431.097732544 8.19280385971 155 0 Open ; +P-H-1282 1232 1282 545.2215271 5.76511502266 155 0 Open ; +P-H-1283 1233 1283 555.925476074 3.78820955753 155 0 Open ; +P-H-1284 1234 1284 372.137680054 13.3612833023 155 0 Open ; +P-H-1285 1235 1285 798.411315918 8.97379779816 155 0 Open ; +P-H-1286 1236 1286 410.608657837 8.99530649185 155 0 Open ; +P-H-1287 1237 1287 535.453399658 10.307404995 155 0 Open ; +P-H-1288 1238 1288 779.946777344 6.30593633652 155 0 Open ; +P-H-1292 1242 1292 351.640594482 11.4739255905 155 0 Open ; +P-H-1294 1244 1294 606.747375488 11.0598659515 155 0 Open ; +P-H-1295 1245 1295 382.739868164 13.1764450073 155 0 Open ; +P-H-1296 1246 1296 511.816101074 8.86585378647 155 0 Open ; +P-H-1297 1247 1297 683.216400146 11.3647708893 155 0 Open ; +P-H-1298 1248 1298 409.089294434 14.2765331268 155 0 Open ; +P-H-1299 1249 1299 796.473937988 5.74918794632 155 0 Open ; +P-H-1304 1254 1304 316.569313049 6.60940241814 155 0 Open ; +P-H-1307 1257 1307 573.599334717 4.68543767929 155 0 Open ; +P-H-1308 1258 1308 606.580993652 3.13629426062 155 0 Open ; +P-H-1309 1259 1309 682.284088135 9.98198223114 155 0 Open ; +P-H-1310 1260 1310 718.186035156 6.05526590347 155 0 Open ; +P-H-1313 1263 1313 217.498285294 4.87385034561 155 0 Open ; +P-H-1316 1266 1316 453.365264893 5.20200753212 155 0 Open ; +P-H-1318 1268 1318 283.005226135 4.37716054916 155 0 Open ; +P-H-1319 1269 1319 608.030822754 10.4811458588 155 0 Open ; +P-H-1320 1270 1320 389.710830688 4.40220236778 155 0 Open ; +P-H-1321 1271 1321 321.842979431 3.30091696978 155 0 Open ; +P-H-1323 1273 1323 369.047958374 6.78041982651 155 0 Open ; +P-H-1324 1274 1324 309.870651245 10.9239912033 155 0 Open ; +P-H-1327 1277 1327 204.383179665 12.3620977402 155 0 Open ; +P-H-1330 1280 1330 688.23739624 7.11150360107 155 0 Open ; +P-H-1331 1281 1331 694.764068604 4.99585962296 155 0 Open ; +P-H-1336 1286 1336 663.270874023 14.8733320236 155 0 Open ; +P-H-1337 1287 1337 342.595214844 6.96036696434 155 0 Open ; +P-H-1338 1288 1338 786.27545166 9.63340806961 155 0 Open ; +P-H-1339 1289 1339 736.716796875 6.9876139164 155 0 Open ; +P-H-1340 1290 1340 385.8699646 9.3308634758 155 0 Open ; +P-H-1341 1291 1341 475.960449219 4.3508605957 155 0 Open ; +P-H-1342 1292 1342 628.42364502 13.3274383545 155 0 Open ; +P-H-1346 1296 1346 438.024047852 8.40489196777 155 0 Open ; +P-H-1348 1298 1348 223.575159073 7.55397319794 155 0 Open ; +P-H-1356 1306 1356 301.308120728 12.7147426605 155 0 Open ; +P-H-1358 1308 1358 525.742645264 10.143887043 155 0 Open ; +P-H-1359 1309 1359 738.403076172 9.82089185715 155 0 Open ; +P-H-1361 1311 1361 565.608123779 6.51650762558 155 0 Open ; +P-H-1364 1314 1364 755.924682617 7.52305221558 155 0 Open ; +P-H-1365 1315 1365 576.721862793 10.2948145866 155 0 Open ; +P-H-1366 1316 1366 481.5496521 11.1022005081 155 0 Open ; +P-H-1367 1317 1367 282.497177124 13.5999917984 155 0 Open ; +P-H-1369 1319 1369 510.073944092 11.255865097 155 0 Open ; +P-H-1372 1322 1372 209.108224869 4.6387450695 155 0 Open ; +P-H-1374 1324 1374 230.721561432 9.74534845352 155 0 Open ; +P-H-1377 1327 1377 720.071655273 3.88035446405 155 0 Open ; +P-H-1379 1329 1379 628.32925415 5.59626960754 155 0 Open ; +P-H-1383 1333 1383 519.355285645 11.0892686844 155 0 Open ; +P-H-1384 1334 1384 512.76574707 4.07174384594 155 0 Open ; +P-H-1390 1340 1390 686.594299316 6.81451773643 155 0 Open ; +P-H-1391 1341 1391 469.65524292 8.9197883606 155 0 Open ; +P-H-1393 1343 1393 611.706054688 9.87234449387 155 0 Open ; +P-H-1396 1346 1396 312.990768433 3.71695238352 155 0 Open ; +P-H-1400 1350 1400 620.993896484 11.8979454041 155 0 Open ; +P-H-1402 1352 1402 674.341369629 4.11093378067 155 0 Open ; +P-H-1403 1353 1403 280.548439026 6.55457949638 155 0 Open ; +P-H-1406 1356 1406 365.762405396 6.37794327736 155 0 Open ; +P-H-1409 1359 1409 260.860267639 12.5712547302 155 0 Open ; +P-H-1411 1361 1411 246.404541016 13.422451973 155 0 Open ; +P-H-1412 1362 1412 234.585456848 12.5549316406 155 0 Open ; +P-H-1414 1364 1414 419.718795776 11.2759695053 155 0 Open ; +P-H-1416 1366 1416 520.282806396 10.8731307983 155 0 Open ; +P-H-1417 1367 1417 695.302734375 6.07105875015 155 0 Open ; +P-H-1420 1370 1420 237.451114655 3.81819927692 155 0 Open ; +P-H-1421 1371 1421 434.806060791 6.71140837669 155 0 Open ; +P-H-1423 1373 1423 489.678894043 7.66603565216 155 0 Open ; +P-H-1432 1382 1432 303.755157471 7.25851297379 155 0 Open ; +P-H-1434 1384 1434 786.873962402 6.81508207321 155 0 Open ; +P-H-1436 1386 1436 699.589385986 6.98437285423 155 0 Open ; +P-H-1439 1389 1439 239.750549316 8.7506146431 155 0 Open ; +P-H-1441 1391 1441 687.388549805 9.79610967636 155 0 Open ; +P-H-1442 1392 1442 660.999542236 7.39670419693 155 0 Open ; +P-H-1443 1393 1443 521.262512207 4.17879354954 155 0 Open ; +P-H-1444 1394 1444 742.090576172 13.3241262436 155 0 Open ; +P-H-1445 1395 1445 629.557220459 10.3699727058 155 0 Open ; +P-H-1447 1397 1447 290.647483826 5.24747371674 155 0 Open ; +P-H-1448 1398 1448 359.953094482 9.6377363205 155 0 Open ; +P-H-1449 1399 1449 635.624420166 9.8027472496 155 0 Open ; +P-H-1450 1400 1450 791.245300293 12.2063941956 155 0 Open ; +P-H-1452 1402 1452 727.092773438 11.9635467529 155 0 Open ; +P-H-1454 1404 1454 318.15007019 9.96640539169 155 0 Open ; +P-H-1456 1406 1456 234.804027557 14.0265073776 155 0 Open ; +P-H-1457 1407 1457 759.268188477 3.40323314071 155 0 Open ; +P-H-1458 1408 1458 625.503112793 3.62105029821 155 0 Open ; +P-H-1459 1409 1459 601.25088501 11.4718761444 155 0 Open ; +P-H-1460 1410 1460 703.47277832 4.34519040585 155 0 Open ; +P-H-1463 1413 1463 560.325164795 6.70668578148 155 0 Open ; +P-H-1464 1414 1464 515.859619141 12.0553436279 155 0 Open ; +P-H-1465 1415 1465 573.390930176 6.62584614754 155 0 Open ; +P-H-1467 1417 1467 261.947517395 6.03878211975 155 0 Open ; +P-H-1470 1420 1470 613.646118164 14.0097284317 155 0 Open ; +P-H-1473 1423 1473 797.178039551 14.430803299 155 0 Open ; +P-H-1474 1424 1474 623.287841797 14.9748544693 155 0 Open ; +P-H-1475 1425 1475 406.904602051 11.9153137207 155 0 Open ; +P-H-1476 1426 1476 512.154205322 14.5115919113 155 0 Open ; +P-H-1477 1427 1477 442.643112183 13.0578155518 155 0 Open ; +P-H-1478 1428 1478 768.775878906 7.3150510788 155 0 Open ; +P-H-1479 1429 1479 340.293884277 13.3892250061 155 0 Open ; +P-H-1480 1430 1480 675.472259521 12.2424783707 155 0 Open ; +P-H-1481 1431 1481 327.021942139 4.15598213673 155 0 Open ; +P-H-1483 1433 1483 366.924728394 13.078748703 155 0 Open ; +P-H-1487 1437 1487 631.433746338 5.1377055645 155 0 Open ; +P-H-1491 1441 1491 747.751159668 8.07543468475 155 0 Open ; +P-H-1492 1442 1492 234.230148315 13.1218757629 155 0 Open ; +P-H-1493 1443 1493 400.105422974 6.44017910957 155 0 Open ; +P-H-1495 1445 1495 361.349472046 11.0122423172 155 0 Open ; +P-H-1496 1446 1496 616.189086914 4.81285369396 155 0 Open ; +P-H-1498 1448 1498 699.575256348 14.2353000641 155 0 Open ; +P-H-1499 1449 1499 651.319488525 5.53581857681 155 0 Open ; +P-H-1500 1450 1500 422.025726318 6.72741246223 155 0 Open ; +P-H-1501 1451 1501 698.576202393 14.4080810547 155 0 Open ; +P-H-1502 1452 1502 464.387756348 14.3008213043 155 0 Open ; +P-H-1503 1453 1503 284.562919617 11.982676506 155 0 Open ; +P-H-1504 1454 1504 577.581268311 11.173584938 155 0 Open ; +P-H-1505 1455 1505 621.594970703 9.94102096558 155 0 Open ; +P-H-1507 1457 1507 217.95608139 14.757519722 155 0 Open ; +P-H-1509 1459 1509 628.200073242 10.1738195419 155 0 Open ; +P-H-1510 1460 1510 499.173675537 7.24098062515 155 0 Open ; +P-H-1511 1461 1511 388.724990845 9.02051687241 155 0 Open ; +P-H-1514 1464 1514 268.431793213 13.6623973846 155 0 Open ; +P-H-1515 1465 1515 687.228668213 4.04285252094 155 0 Open ; +P-H-1516 1466 1516 530.578186035 3.55302453041 155 0 Open ; +P-H-1517 1467 1517 684.334564209 3.21663844585 155 0 Open ; +P-H-1520 1470 1520 571.120941162 11.5985145569 155 0 Open ; +P-H-1521 1471 1521 706.54083252 3.64415019751 155 0 Open ; +P-H-1524 1474 1524 531.228607178 6.17779755592 155 0 Open ; +P-H-1525 1475 1525 794.345458984 10.2888379097 155 0 Open ; +P-H-1526 1476 1526 603.975494385 3.32988587022 155 0 Open ; +P-H-1529 1479 1529 744.710388184 5.95971775055 155 0 Open ; +P-H-1531 1481 1531 302.710510254 4.11126959324 155 0 Open ; +P-H-1534 1484 1534 387.586593628 10.3589572906 155 0 Open ; +P-H-1535 1485 1535 284.128639221 10.0016059875 155 0 Open ; +P-H-1537 1487 1537 654.964385986 6.74177956581 155 0 Open ; +P-H-1538 1488 1538 646.534332275 5.05502390862 155 0 Open ; +P-H-1540 1490 1540 253.160728455 4.44816756248 155 0 Open ; +P-H-1542 1492 1542 397.538543701 7.60428714752 155 0 Open ; +P-H-1543 1493 1543 504.990631104 6.54538846016 155 0 Open ; +P-H-1544 1494 1544 795.571899414 14.5356702805 155 0 Open ; +P-H-1545 1495 1545 514.58291626 14.9054317474 155 0 Open ; +P-H-1546 1496 1546 755.250305176 8.84137630463 155 0 Open ; +P-H-1548 1498 1548 404.620269775 12.0569200516 155 0 Open ; +P-H-1549 1499 1549 377.674057007 14.3633575439 155 0 Open ; +P-H-1551 1501 1551 339.258239746 13.2660913467 155 0 Open ; +P-H-1552 1502 1552 565.818695068 5.28901839256 155 0 Open ; +P-H-1553 1503 1553 782.05267334 6.1792473793 155 0 Open ; +P-H-1554 1504 1554 339.201858521 6.31150126457 155 0 Open ; +P-H-1557 1507 1557 647.768829346 12.0151948929 155 0 Open ; +P-H-1558 1508 1558 564.95199585 13.9702978134 155 0 Open ; +P-H-1559 1509 1559 266.244941711 10.5752983093 155 0 Open ; +P-H-1560 1510 1560 358.787765503 13.9228200912 155 0 Open ; +P-H-1562 1512 1562 341.274581909 7.03956127167 155 0 Open ; +P-H-1563 1513 1563 765.179504395 10.4473557472 155 0 Open ; +P-H-1564 1514 1564 497.073852539 9.40781641006 155 0 Open ; +P-H-1565 1515 1565 508.007202148 12.5517969131 155 0 Open ; +P-H-1567 1517 1567 217.592151642 12.4262018204 155 0 Open ; +P-H-1570 1520 1570 781.334533691 4.79589354992 155 0 Open ; +P-H-1572 1522 1572 750.463806152 7.91363334656 155 0 Open ; +P-H-1573 1523 1573 705.94644165 7.83647346497 155 0 Open ; +P-H-1574 1524 1574 436.41053772 6.0384414196 155 0 Open ; +P-H-1575 1525 1575 500.664489746 4.36722385883 155 0 Open ; +P-H-1576 1526 1576 264.502258301 12.7888393402 155 0 Open ; +P-H-1580 1530 1580 751.238098145 4.17634999752 155 0 Open ; +P-H-1581 1531 1581 441.077651978 14.8443336487 155 0 Open ; +P-H-1582 1532 1582 556.710144043 3.55645090342 155 0 Open ; +P-H-1584 1534 1584 213.351732254 3.05145601556 155 0 Open ; +P-H-1587 1537 1587 702.35333252 12.0595235825 155 0 Open ; +P-H-1588 1538 1588 353.317687988 11.2086181641 155 0 Open ; +P-H-1589 1539 1589 328.393493652 9.19061565399 155 0 Open ; +P-H-1593 1543 1593 287.846008301 11.559346199 155 0 Open ; +P-H-1595 1545 1595 757.348999023 6.29417920113 155 0 Open ; +P-H-1596 1546 1596 304.867500305 9.16471338272 155 0 Open ; +P-H-1598 1548 1598 617.357299805 13.480550766 155 0 Open ; +P-H-1599 1549 1599 551.21685791 5.035820961 155 0 Open ; +P-H-1601 1551 1601 707.038543701 14.9409627914 155 0 Open ; +P-H-1605 1555 1605 418.947540283 4.02802062035 155 0 Open ; +P-H-1606 1556 1606 457.452178955 10.9739012718 155 0 Open ; +P-H-1608 1558 1608 409.649215698 10.4875965118 155 0 Open ; +P-H-1614 1564 1614 383.533126831 3.82679438591 155 0 Open ; +P-H-1615 1565 1615 691.177581787 11.4345855713 155 0 Open ; +P-H-1619 1569 1619 249.695384979 3.60783791542 155 0 Open ; +P-H-1621 1571 1621 781.244934082 10.6831860542 155 0 Open ; +P-H-1622 1572 1622 632.517944336 9.59628868103 155 0 Open ; +P-H-1623 1573 1623 447.425003052 12.4417600632 155 0 Open ; +P-H-1624 1574 1624 223.740346909 3.08056042343 155 0 Open ; +P-H-1625 1575 1625 536.595092773 10.0714492798 155 0 Open ; +P-H-1628 1578 1628 305.163085938 12.5205955505 155 0 Open ; +P-H-1631 1581 1631 754.188720703 12.001200676 155 0 Open ; +P-H-1632 1582 1632 423.914993286 5.7874083519 155 0 Open ; +P-H-1633 1583 1633 557.526916504 14.0950279236 155 0 Open ; +P-H-1634 1584 1634 602.517211914 5.13833284378 155 0 Open ; +P-H-1635 1585 1635 427.410079956 4.62514221668 155 0 Open ; +P-H-1638 1588 1638 396.690246582 10.4582247734 155 0 Open ; +P-H-1639 1589 1639 685.063659668 8.30048704147 155 0 Open ; +P-H-1640 1590 1640 270.670661926 10.2357974052 155 0 Open ; +P-H-1642 1592 1642 398.981903076 12.7806081772 155 0 Open ; +P-H-1643 1593 1643 256.283653259 10.1870546341 155 0 Open ; +P-H-1645 1595 1645 482.95300293 14.8279047012 155 0 Open ; +P-H-1646 1596 1646 610.606536865 12.2827310562 155 0 Open ; +P-H-1650 1600 1650 390.14692688 6.98771953583 155 0 Open ; +P-H-1653 1603 1653 695.362640381 14.2109670639 155 0 Open ; +P-H-1654 1604 1654 677.624481201 3.69352000952 155 0 Open ; +P-H-1656 1606 1656 463.373657227 9.42662715912 155 0 Open ; +P-H-1660 1610 1660 651.490020752 14.8612804413 155 0 Open ; +P-H-1661 1611 1661 674.868103027 13.1681060791 155 0 Open ; +P-H-1663 1613 1663 451.925201416 13.1420707703 155 0 Open ; +P-H-1664 1614 1664 361.461608887 12.7078561783 155 0 Open ; +P-H-1665 1615 1665 214.543551445 7.66946125031 155 0 Open ; +P-H-1666 1616 1666 393.644973755 6.82096719742 155 0 Open ; +P-H-1667 1617 1667 734.390808105 5.14337396622 155 0 Open ; +P-H-1668 1618 1668 711.367462158 6.05848073959 155 0 Open ; +P-H-1669 1619 1669 597.431396484 11.5963201523 155 0 Open ; +P-H-1670 1620 1670 692.098999023 9.16862773895 155 0 Open ; +P-H-1671 1621 1671 655.055084229 13.2190704346 155 0 Open ; +P-H-1672 1622 1672 203.213618517 3.22575756907 155 0 Open ; +P-H-1675 1625 1675 742.565124512 4.83113563061 155 0 Open ; +P-H-1676 1626 1676 503.544525146 12.4520664215 155 0 Open ; +P-H-1678 1628 1678 438.767303467 6.24438738823 155 0 Open ; +P-H-1681 1631 1681 699.807922363 8.43744659424 155 0 Open ; +P-H-1682 1632 1682 608.404327393 4.03041565418 155 0 Open ; +P-H-1684 1634 1684 396.534790039 6.20152568817 155 0 Open ; +P-H-1687 1637 1687 215.904237747 9.05046415329 155 0 Open ; +P-H-1692 1642 1692 475.022857666 13.1858196259 155 0 Open ; +P-H-1696 1646 1696 550.389007568 14.7654733658 155 0 Open ; +P-H-1697 1647 1697 488.066619873 5.71356892586 155 0 Open ; +P-H-1698 1648 1698 596.657501221 3.45494422317 155 0 Open ; +P-H-1700 1650 1700 503.620666504 14.0478630066 155 0 Open ; +P-H-1702 1652 1702 792.559814453 10.052585125 155 0 Open ; +P-H-1703 1653 1703 550.290802002 5.75093722343 155 0 Open ; +P-H-1704 1654 1704 671.356658936 8.83926677704 155 0 Open ; +P-H-1706 1656 1706 438.157714844 5.33385515213 155 0 Open ; +P-H-1707 1657 1707 786.578857422 3.62223821878 155 0 Open ; +P-H-1709 1659 1709 691.408294678 4.98823940754 155 0 Open ; +P-H-1710 1660 1710 661.81036377 3.93777340651 155 0 Open ; +P-H-1712 1662 1712 334.71105957 8.77842855453 155 0 Open ; +P-H-1716 1666 1716 480.571136475 6.18140769005 155 0 Open ; +P-H-1717 1667 1717 518.075592041 12.9258117676 155 0 Open ; +P-H-1718 1668 1718 399.042831421 9.26058912277 155 0 Open ; +P-H-1720 1670 1720 559.153564453 8.87977743149 155 0 Open ; +P-H-1726 1676 1726 373.409362793 8.82567644119 155 0 Open ; +P-H-1728 1678 1728 751.562805176 5.32677769661 155 0 Open ; +P-H-1729 1679 1729 771.256225586 13.0746030807 155 0 Open ; +P-H-1731 1681 1731 605.415374756 7.32840156555 155 0 Open ; +P-H-1733 1683 1733 312.057998657 14.1766653061 155 0 Open ; +P-H-1734 1684 1734 713.12109375 7.52636909485 155 0 Open ; +P-H-1735 1685 1735 680.733612061 4.78955483437 155 0 Open ; +P-H-1738 1688 1738 353.823013306 13.0692558289 155 0 Open ; +P-H-1739 1689 1739 320.901611328 10.8706331253 155 0 Open ; +P-H-1741 1691 1741 715.106079102 14.7744369507 155 0 Open ; +P-H-1743 1693 1743 644.84362793 12.7479152679 155 0 Open ; +P-H-1744 1694 1744 582.926513672 7.92367219925 155 0 Open ; +P-H-1749 1699 1749 221.767251968 11.8441324234 155 0 Open ; +P-H-1750 1700 1750 265.838188171 5.84875249863 155 0 Open ; +P-H-1751 1701 1751 714.334655762 7.45651960373 155 0 Open ; +P-H-1752 1702 1752 658.886566162 5.13293838501 155 0 Open ; +P-H-1757 1707 1757 532.016998291 7.19005537033 155 0 Open ; +P-H-1758 1708 1758 212.88912487 3.55035823584 155 0 Open ; +P-H-1759 1709 1759 246.657733917 14.5318689346 155 0 Open ; +P-H-1766 1716 1766 542.847930908 11.9010791779 155 0 Open ; +P-H-1767 1717 1767 654.722900391 9.5607919693 155 0 Open ; +P-H-1768 1718 1768 515.683868408 12.9818143845 155 0 Open ; +P-H-1771 1721 1771 304.927108765 5.20122027397 155 0 Open ; +P-H-1772 1722 1772 600.474182129 14.3920869827 155 0 Open ; +P-H-1773 1723 1773 508.5597229 6.26355695724 155 0 Open ; +P-H-1774 1724 1774 289.772583008 11.1592512131 155 0 Open ; +P-H-1775 1725 1775 416.937667847 12.4289035797 155 0 Open ; +P-H-1776 1726 1776 722.742980957 13.8298158646 155 0 Open ; +P-H-1780 1730 1780 675.335876465 14.4125747681 155 0 Open ; +P-H-1785 1735 1785 298.47190094 7.34604072571 155 0 Open ; +P-H-1786 1736 1786 325.57926178 11.2136058807 155 0 Open ; +P-H-1787 1737 1787 358.200942993 8.66657114029 155 0 Open ; +P-H-1788 1738 1788 790.251708984 14.216085434 155 0 Open ; +P-H-1793 1743 1793 492.469116211 9.57064580917 155 0 Open ; +P-H-1794 1744 1794 452.133453369 11.1420249939 155 0 Open ; +P-H-1795 1745 1795 444.05809021 8.6911945343 155 0 Open ; +P-H-1796 1746 1796 632.632751465 12.1740589142 155 0 Open ; +P-H-1805 1755 1805 291.370910645 8.419090271 155 0 Open ; +P-H-1806 1756 1806 354.438110352 3.82590425014 155 0 Open ; +P-H-1807 1757 1807 377.536270142 4.04058086872 155 0 Open ; +P-H-1811 1761 1811 440.564239502 10.265566349 155 0 Open ; +P-H-1813 1763 1813 592.550750732 3.01498376392 155 0 Open ; +P-H-1814 1764 1814 722.287231445 4.62713456154 155 0 Open ; +P-H-1815 1765 1815 305.594970703 13.6946430206 155 0 Open ; +P-H-1816 1766 1816 269.709098816 11.0176095963 155 0 Open ; +P-H-1819 1769 1819 317.820587158 7.21442079544 155 0 Open ; +P-H-1820 1770 1820 232.231025696 13.1374139786 155 0 Open ; +P-H-1822 1772 1822 230.571144104 7.18468666077 155 0 Open ; +P-H-1824 1774 1824 205.010854721 7.34864759445 155 0 Open ; +P-H-1825 1775 1825 298.614173889 7.17044734955 155 0 Open ; +P-H-1827 1777 1827 728.357421875 5.055798769 155 0 Open ; +P-H-1829 1779 1829 220.003715515 7.04906654358 155 0 Open ; +P-H-1838 1788 1838 492.888061523 6.39861631393 155 0 Open ; +P-H-1840 1790 1840 756.363037109 10.8676958084 155 0 Open ; +P-H-1843 1793 1843 631.697479248 9.79256248474 155 0 Open ; +P-H-1844 1794 1844 531.15322876 4.85933637619 155 0 Open ; +P-H-1848 1798 1848 536.627746582 9.055539608 155 0 Open ; +P-H-1850 1800 1850 578.145996094 9.0034866333 155 0 Open ; +P-H-1852 1802 1852 547.202331543 11.5956087112 155 0 Open ; +P-H-1853 1803 1853 571.444946289 12.5144319534 155 0 Open ; +P-H-1854 1804 1854 588.825744629 10.8818669319 155 0 Open ; +P-H-1856 1806 1856 716.621582031 8.18054056168 155 0 Open ; +P-H-1857 1807 1857 441.919494629 9.82036399841 155 0 Open ; +P-H-1866 1816 1866 445.025405884 9.84133672714 155 0 Open ; +P-H-1867 1817 1867 518.205871582 8.71847963333 155 0 Open ; +P-H-1869 1819 1869 395.798538208 10.7205533981 155 0 Open ; +P-H-1873 1823 1873 795.252563477 3.20074094832 155 0 Open ; +P-H-1875 1825 1875 383.178253174 4.54400479794 155 0 Open ; +P-H-1876 1826 1876 366.161605835 8.56292247772 155 0 Open ; +P-H-1880 1830 1880 268.552757263 6.32379841805 155 0 Open ; +P-H-1884 1834 1884 552.53717041 4.84571146965 155 0 Open ; +P-H-1888 1838 1888 274.128089905 8.41754055023 155 0 Open ; +P-H-1889 1839 1889 255.092193604 5.69029569626 155 0 Open ; +P-H-1890 1840 1890 203.896314383 4.70717597008 155 0 Open ; +P-H-1892 1842 1892 714.909362793 8.631254673 155 0 Open ; +P-H-1897 1847 1897 318.222312927 10.2492499352 155 0 Open ; +P-H-1899 1849 1899 631.28994751 4.80295705795 155 0 Open ; +P-H-1901 1851 1901 762.24005127 6.3807592392 155 0 Open ; +P-H-1903 1853 1903 254.634616852 7.88053894043 155 0 Open ; +P-H-1904 1854 1904 501.305236816 3.74051606655 155 0 Open ; +P-H-1909 1859 1909 732.711791992 4.74093580246 155 0 Open ; +P-H-1911 1861 1911 448.677825928 13.5665121078 155 0 Open ; +P-H-1915 1865 1915 592.386108398 7.66852807999 155 0 Open ; +P-H-1916 1866 1916 538.654418945 6.29339933395 155 0 Open ; +P-H-1917 1867 1917 214.484898567 11.9540548325 155 0 Open ; +P-H-1918 1868 1918 725.287902832 5.2736389637 155 0 Open ; +P-H-1920 1870 1920 402.533401489 6.58176064491 155 0 Open ; +P-H-1921 1871 1921 709.215789795 14.7994976044 155 0 Open ; +P-H-1925 1875 1925 320.579879761 10.7222943306 155 0 Open ; +P-H-1926 1876 1926 392.66267395 12.6347436905 155 0 Open ; +P-H-1934 1884 1934 704.552337646 7.22560119629 155 0 Open ; +P-H-1937 1887 1937 369.395324707 3.54446476698 155 0 Open ; +P-H-1938 1888 1938 287.405075073 7.34099817276 155 0 Open ; +P-H-1939 1889 1939 726.175109863 3.51137048006 155 0 Open ; +P-H-1941 1891 1941 586.24230957 6.48903393745 155 0 Open ; +P-H-1942 1892 1942 251.229293823 3.21496148407 155 0 Open ; +P-H-1947 1897 1947 576.614990234 10.3652992249 155 0 Open ; +P-H-1948 1898 1948 378.045547485 7.23436260223 155 0 Open ; +P-H-1949 1899 1949 284.324562073 3.85862517357 155 0 Open ; +P-H-1950 1900 1950 796.108398438 14.883392334 155 0 Open ; +P-H-1951 1901 1951 454.709594727 13.0854234695 155 0 Open ; +P-H-1958 1908 1958 338.943893433 3.60315638781 155 0 Open ; +P-H-1959 1909 1959 624.460723877 13.2267351151 155 0 Open ; +P-H-1961 1911 1961 554.236633301 12.1008558273 155 0 Open ; +P-H-1962 1912 1962 560.450439453 12.8083877563 155 0 Open ; +P-H-1965 1915 1965 473.408111572 10.4039759636 155 0 Open ; +P-H-1966 1916 1966 731.022888184 13.0448484421 155 0 Open ; +P-H-1967 1917 1967 209.628628731 11.5671138763 155 0 Open ; +P-H-1968 1918 1968 200.819384396 14.4278717041 155 0 Open ; +P-H-1969 1919 1969 756.772094727 4.36848843098 155 0 Open ; +P-H-1970 1920 1970 581.067016602 6.87084817886 155 0 Open ; +P-H-1975 1925 1975 555.113372803 6.80873847008 155 0 Open ; +P-H-1977 1927 1977 655.003295898 7.81701278687 155 0 Open ; +P-H-1978 1928 1978 577.034332275 7.31902360916 155 0 Open ; +P-H-1981 1931 1981 214.575485229 6.40401530266 155 0 Open ; +P-H-1982 1932 1982 353.277908325 9.8381114006 155 0 Open ; +P-H-1984 1934 1984 398.721923828 9.38930368423 155 0 Open ; +P-H-1985 1935 1985 630.911895752 9.73036336899 155 0 Open ; +P-H-1990 1940 1990 428.856552124 10.8409309387 155 0 Open ; +P-H-1991 1941 1991 596.307525635 5.8170068264 155 0 Open ; +P-H-1993 1943 1993 239.083770752 12.6198034286 155 0 Open ; +P-H-1995 1945 1995 765.007995605 12.796754837 155 0 Open ; +P-H-1999 1949 1999 450.09072876 8.4998383522 155 0 Open ; +P-H-2000 1950 2000 651.625915527 12.5417633057 155 0 Open ; +P-H-2003 1953 2003 560.619171143 9.53062582016 155 0 Open ; +P-H-2004 1954 2004 349.480224609 5.28634738922 155 0 Open ; +P-H-2011 1961 2011 213.849315643 14.3091058731 155 0 Open ; +P-H-2013 1963 2013 238.829025269 10.9884924889 155 0 Open ; +P-H-2014 1964 2014 389.45703125 3.08513533324 155 0 Open ; +P-H-2017 1967 2017 512.736724854 6.32594203949 155 0 Open ; +P-H-2021 1971 2021 540.239593506 11.1447057724 155 0 Open ; +P-H-2024 1974 2024 233.205341339 4.643638134 155 0 Open ; +P-H-2027 1977 2027 232.359657288 8.37578773499 155 0 Open ; +P-H-2030 1980 2030 273.614341736 3.72597956657 155 0 Open ; +P-H-2031 1981 2031 735.847900391 14.9191589355 155 0 Open ; +P-H-2032 1982 2032 471.690002441 8.8788766861 155 0 Open ; +P-H-2033 1983 2033 524.835723877 5.27612495422 155 0 Open ; +P-H-2034 1984 2034 274.785133362 13.2739562988 155 0 Open ; +P-H-2035 1985 2035 781.30267334 6.09571266174 155 0 Open ; +P-H-2036 1986 2036 404.57661438 9.38351154327 155 0 Open ; +P-H-2037 1987 2037 365.713409424 13.9078187943 155 0 Open ; +P-H-2039 1989 2039 216.982603073 11.5321054459 155 0 Open ; +P-H-2040 1990 2040 275.797332764 5.51599931717 155 0 Open ; +P-H-2041 1991 2041 665.225891113 12.0355262756 155 0 Open ; +P-H-2044 1994 2044 366.068054199 13.1195135117 155 0 Open ; +P-H-2050 2000 2050 794.988098145 10.2940940857 155 0 Open ; +P-H-2051 2001 2051 507.798431396 14.3683300018 155 0 Open ; +P-H-2056 2006 2056 653.244171143 4.49709236622 155 0 Open ; +P-H-2057 2007 2057 771.559936523 7.15857124329 155 0 Open ; +P-H-2060 2010 2060 340.208648682 8.73438310623 155 0 Open ; +P-H-2065 2015 2065 388.087188721 10.6278996468 155 0 Open ; +P-H-2066 2016 2066 277.236427307 9.25239419937 155 0 Open ; +P-H-2067 2017 2067 452.039001465 3.39132168889 155 0 Open ; +P-H-2069 2019 2069 673.739776611 5.89758753777 155 0 Open ; +P-H-2072 2022 2072 614.390167236 12.113409996 155 0 Open ; +P-H-2075 2025 2075 273.830627441 4.42706465721 155 0 Open ; +P-H-2076 2026 2076 797.247375488 13.7398281097 155 0 Open ; +P-H-2078 2028 2078 749.297912598 11.9981117249 155 0 Open ; +P-H-2079 2029 2079 619.517852783 7.73903656006 155 0 Open ; +P-H-2082 2032 2082 700.623382568 6.55725097656 155 0 Open ; +P-H-2084 2034 2084 272.522758484 8.79889726639 155 0 Open ; +P-H-2085 2035 2085 447.62840271 8.81273460388 155 0 Open ; +P-H-2091 2041 2091 386.342758179 12.2585020065 155 0 Open ; +P-H-2093 2043 2093 724.049438477 8.98229598999 155 0 Open ; +P-H-2094 2044 2094 733.549316406 10.2599458694 155 0 Open ; +P-H-2099 2049 2099 654.158691406 11.9115858078 155 0 Open ; +P-H-2105 2055 2105 498.5105896 12.3512744904 155 0 Open ; +P-H-2107 2057 2107 615.541290283 3.05831041187 155 0 Open ; +P-H-2108 2058 2108 232.31137085 4.14477467537 155 0 Open ; +P-H-2113 2063 2113 413.724411011 12.3270215988 155 0 Open ; +P-H-2117 2067 2117 261.24772644 10.8115568161 155 0 Open ; +P-H-2118 2068 2118 797.90814209 7.84185743332 155 0 Open ; +P-H-2122 2072 2122 797.895202637 3.49963125587 155 0 Open ; +P-H-2123 2073 2123 615.874450684 7.04557752609 155 0 Open ; +P-H-2126 2076 2126 479.006011963 8.08560276031 155 0 Open ; +P-H-2127 2077 2127 770.091125488 5.43059492111 155 0 Open ; +P-H-2130 2080 2130 273.589279175 7.30054855347 155 0 Open ; +P-H-2133 2083 2133 296.644950867 5.23551368713 155 0 Open ; +P-H-2135 2085 2135 501.339447021 3.24715726078 155 0 Open ; +P-H-2139 2089 2139 691.180847168 12.5307788849 155 0 Open ; +P-H-2140 2090 2140 632.76776123 9.56518507004 155 0 Open ; +P-H-2142 2092 2142 293.248168945 3.44002223015 155 0 Open ; +P-H-2144 2094 2144 725.90838623 9.84982299805 155 0 Open ; +P-H-2145 2095 2145 245.21887207 10.8724865913 155 0 Open ; +P-H-2148 2098 2148 360.225708008 5.27171611786 155 0 Open ; +P-H-2149 2099 2149 543.254302979 4.49595463276 155 0 Open ; +P-H-2151 2101 2151 234.863670349 10.073720932 155 0 Open ; +P-H-2153 2103 2153 544.077728271 5.28711771965 155 0 Open ; +P-H-2156 2106 2156 752.569152832 7.58605670929 155 0 Open ; +P-H-2160 2110 2160 265.240859985 9.06162118912 155 0 Open ; +P-H-2161 2111 2161 528.993621826 10.9227962494 155 0 Open ; +P-H-2162 2112 2162 485.448669434 13.7186756134 155 0 Open ; +P-H-2166 2116 2166 646.938293457 8.8450345993 155 0 Open ; +P-H-2169 2119 2169 775.139221191 10.3031864166 155 0 Open ; +P-H-2170 2120 2170 601.257293701 13.6204023361 155 0 Open ; +P-H-2171 2121 2171 693.246276855 10.8140063286 155 0 Open ; +P-H-2175 2125 2175 543.660064697 8.89961528778 155 0 Open ; +P-H-2176 2126 2176 465.773468018 12.0937309265 155 0 Open ; +P-H-2177 2127 2177 406.387252808 6.01561141014 155 0 Open ; +P-H-2178 2128 2178 328.791091919 10.8368902206 155 0 Open ; +P-H-2182 2132 2182 507.900299072 12.6200284958 155 0 Open ; +P-H-2183 2133 2183 526.63885498 11.3927669525 155 0 Open ; +P-H-2184 2134 2184 758.092956543 4.38142609596 155 0 Open ; +P-H-2185 2135 2185 751.455566406 5.28625321388 155 0 Open ; +P-H-2187 2137 2187 435.664718628 7.34383678436 155 0 Open ; +P-H-2188 2138 2188 354.305221558 7.16084575653 155 0 Open ; +P-H-2189 2139 2189 349.968978882 13.5722942352 155 0 Open ; +P-H-2192 2142 2192 452.772460937 9.94036102295 155 0 Open ; +P-H-2193 2143 2193 777.483703613 6.37549495697 155 0 Open ; +P-H-2194 2144 2194 255.924598694 9.49476718903 155 0 Open ; +P-H-2196 2146 2196 686.661895752 5.52670383453 155 0 Open ; +P-H-2197 2147 2197 504.147857666 11.2718315125 155 0 Open ; +P-H-2199 2149 2199 604.336608887 4.7116137743 155 0 Open ; +P-H-2201 2151 2201 455.419540405 11.7268867493 155 0 Open ; +P-H-2202 2152 2202 718.045959473 6.97458314896 155 0 Open ; +P-H-2203 2153 2203 390.684280396 7.6178483963 155 0 Open ; +P-H-2204 2154 2204 224.126712799 12.9535541534 155 0 Open ; +P-H-2205 2155 2205 602.015869141 4.6172246933 155 0 Open ; +P-H-2207 2157 2207 633.355163574 3.01255424693 155 0 Open ; +P-H-2208 2158 2208 201.492564321 12.7105903625 155 0 Open ; +P-H-2212 2162 2212 796.067932129 13.2732105255 155 0 Open ; +P-H-2214 2164 2214 308.380348206 13.9698028564 155 0 Open ; +P-H-2216 2166 2216 520.016174316 5.2406976223 155 0 Open ; +P-H-2221 2171 2221 292.524291992 12.115322113 155 0 Open ; +P-H-2222 2172 2222 246.043712616 12.1334190369 155 0 Open ; +P-H-2225 2175 2225 500.141723633 8.63784170151 155 0 Open ; +P-H-2229 2179 2229 254.789543152 11.9576692581 155 0 Open ; +P-H-2230 2180 2230 458.815490723 13.2373418808 155 0 Open ; +P-H-2233 2183 2233 341.804931641 5.31173110008 155 0 Open ; +P-H-2234 2184 2234 778.733886719 6.6123611927 155 0 Open ; +P-H-2236 2186 2236 574.689819336 11.2429590225 155 0 Open ; +P-H-2237 2187 2237 710.634796143 11.7834892273 155 0 Open ; +P-H-2240 2190 2240 234.66280365 14.5555076599 155 0 Open ; +P-H-2242 2192 2242 642.752441406 5.8056871891 155 0 Open ; +P-H-2243 2193 2243 728.02545166 13.4752836227 155 0 Open ; +P-H-2244 2194 2244 700.884460449 10.3038425446 155 0 Open ; +P-H-2245 2195 2245 420.951950073 5.78853583336 155 0 Open ; +P-H-2246 2196 2246 500.92578125 8.19439506531 155 0 Open ; +P-H-2251 2201 2251 493.051879883 13.4583444595 155 0 Open ; +P-H-2252 2202 2252 386.405532837 9.35476255417 155 0 Open ; +P-H-2255 2205 2255 762.518066406 3.81924951077 155 0 Open ; +P-H-2257 2207 2257 291.475868225 7.69983100891 155 0 Open ; +P-H-2258 2208 2258 625.0027771 3.43240624666 155 0 Open ; +P-H-2259 2209 2259 633.673370361 13.9714422226 155 0 Open ; +P-H-2261 2211 2261 236.545982361 11.5663404465 155 0 Open ; +P-H-2262 2212 2262 727.00982666 8.09525442123 155 0 Open ; +P-H-2265 2215 2265 736.604125977 5.12708330154 155 0 Open ; +P-H-2268 2218 2268 467.511505127 8.31779575348 155 0 Open ; +P-H-2271 2221 2271 268.087554932 5.95031070709 155 0 Open ; +P-H-2274 2224 2274 444.662750244 7.93762159348 155 0 Open ; +P-H-2275 2225 2275 386.553985596 11.2560367584 155 0 Open ; +P-H-2279 2229 2279 311.274085999 14.6705446243 155 0 Open ; +P-H-2280 2230 2280 480.108673096 6.73083686829 155 0 Open ; +P-H-2282 2232 2282 602.084686279 3.74959301949 155 0 Open ; +P-H-2283 2233 2283 335.54776001 14.0274295807 155 0 Open ; +P-H-2284 2234 2284 789.521057129 8.6138176918 155 0 Open ; +P-H-2285 2235 2285 578.610351562 9.08508253098 155 0 Open ; +P-H-2286 2236 2286 281.40914917 7.87100124359 155 0 Open ; +P-H-2288 2238 2288 204.592483521 10.7175264359 155 0 Open ; +P-H-2292 2242 2292 679.976531982 14.3155651093 155 0 Open ; +P-H-2295 2245 2295 402.79498291 10.5116763115 155 0 Open ; +P-H-2296 2246 2296 572.501220703 7.5582690239 155 0 Open ; +P-H-2300 2250 2300 329.603500366 7.92239284515 155 0 Open ; +P-H-2302 2252 2302 754.970275879 10.7118487358 155 0 Open ; +P-H-2304 2254 2304 519.176605225 11.0216341019 155 0 Open ; +P-H-2305 2255 2305 761.404846191 13.6324272156 155 0 Open ; +P-H-2306 2256 2306 714.106811523 14.8607196808 155 0 Open ; +P-H-2307 2257 2307 625.860229492 3.66061848402 155 0 Open ; +P-H-2309 2259 2309 648.83480835 10.3384995461 155 0 Open ; +P-H-2315 2265 2315 741.858947754 7.46740484238 155 0 Open ; +P-H-2316 2266 2316 742.297424316 10.8575978279 155 0 Open ; +P-H-2318 2268 2318 298.542396545 7.04406738281 155 0 Open ; +P-H-2320 2270 2320 398.54335022 9.3619594574 155 0 Open ; +P-H-2324 2274 2324 756.6796875 9.30544137955 155 0 Open ; +P-H-2326 2276 2326 724.482055664 10.3928246498 155 0 Open ; +P-H-2334 2284 2334 778.182617188 13.304441452 155 0 Open ; +P-H-2336 2286 2336 301.659759521 10.9112005234 155 0 Open ; +P-H-2339 2289 2339 248.653865814 13.5112371445 155 0 Open ; +P-H-2340 2290 2340 693.679077148 12.2887735367 155 0 Open ; +P-H-2341 2291 2341 627.155609131 7.09137868881 155 0 Open ; +P-H-2344 2294 2344 470.875305176 11.0275793076 155 0 Open ; +P-H-2346 2296 2346 461.240570068 12.4090490341 155 0 Open ; +P-H-2350 2300 2350 502.35836792 9.74366426468 155 0 Open ; +P-H-2353 2303 2353 368.4296875 14.9572572708 155 0 Open ; +P-H-2356 2306 2356 297.955696106 13.8267936707 155 0 Open ; +P-H-2357 2307 2357 716.512268066 7.43911790848 155 0 Open ; +P-H-2363 2313 2363 615.430786133 13.9136095047 155 0 Open ; +P-H-2367 2317 2367 388.836669922 10.5602293015 155 0 Open ; +P-H-2368 2318 2368 497.120422363 13.0598344803 155 0 Open ; +P-H-2369 2319 2369 764.442199707 14.6198320389 155 0 Open ; +P-H-2370 2320 2370 422.280166626 8.25616693497 155 0 Open ; +P-H-2371 2321 2371 225.098089218 3.47177758813 155 0 Open ; +P-H-2372 2322 2372 429.226028442 3.03930642083 155 0 Open ; +P-H-2374 2324 2374 333.176452637 8.93604469299 155 0 Open ; +P-H-2375 2325 2375 507.309936523 6.1620247364 155 0 Open ; +P-H-2376 2326 2376 348.492111206 9.13830375671 155 0 Open ; +P-H-2378 2328 2378 522.247406006 11.2541227341 155 0 Open ; +P-H-2379 2329 2379 711.530029297 12.7104234695 155 0 Open ; +P-H-2382 2332 2382 384.272094727 12.2259864807 155 0 Open ; +P-H-2383 2333 2383 387.729003906 10.2264719009 155 0 Open ; +P-H-2385 2335 2385 380.003707886 5.44785809517 155 0 Open ; +P-H-2387 2337 2387 463.062713623 12.9000806808 155 0 Open ; +P-H-2388 2338 2388 366.266693115 7.89127874374 155 0 Open ; +P-H-2389 2339 2389 722.623413086 9.64504051208 155 0 Open ; +P-H-2390 2340 2390 532.07434082 14.4741039276 155 0 Open ; +P-H-2392 2342 2392 556.850769043 14.8203639984 155 0 Open ; +P-H-2394 2344 2394 796.636413574 12.3642225266 155 0 Open ; +P-H-2396 2346 2396 760.914489746 4.79969894886 155 0 Open ; +P-H-2397 2347 2397 773.516113281 4.70225441456 155 0 Open ; +P-H-2401 2351 2401 653.748291016 5.95670747757 155 0 Open ; +P-H-2403 2353 2403 230.291473389 9.17565393448 155 0 Open ; +P-H-2404 2354 2404 488.581420898 10.7687745094 155 0 Open ; +P-H-2405 2355 2405 538.186309814 4.94581067562 155 0 Open ; +P-H-2407 2357 2407 389.087982178 11.0406885147 155 0 Open ; +P-H-2408 2358 2408 583.678466797 8.69026136398 155 0 Open ; +P-H-2409 2359 2409 715.817871094 14.0142421722 155 0 Open ; +P-H-2411 2361 2411 721.588256836 9.68550872803 155 0 Open ; +P-H-2412 2362 2412 581.103515625 7.14300203323 155 0 Open ; +P-H-2413 2363 2413 295.27155304 11.5809373856 155 0 Open ; +P-H-2416 2366 2416 349.28767395 12.5590496063 155 0 Open ; +P-H-2420 2370 2420 320.387168884 5.94277834892 155 0 Open ; +P-H-2421 2371 2421 356.529907227 10.9662027359 155 0 Open ; +P-H-2423 2373 2423 750.325378418 9.39072036743 155 0 Open ; +P-H-2424 2374 2424 447.688949585 5.1652700901 155 0 Open ; +P-H-2425 2375 2425 606.009307861 14.9627084732 155 0 Open ; +P-H-2426 2376 2426 702.218139648 14.6104507446 155 0 Open ; +P-H-2429 2379 2429 363.434616089 3.91188263893 155 0 Open ; +P-H-2431 2381 2431 504.030609131 7.85031557083 155 0 Open ; +P-H-2434 2384 2434 537.178100586 14.0436725616 155 0 Open ; +P-H-2435 2385 2435 369.157424927 7.57913160324 155 0 Open ; +P-H-2438 2388 2438 320.079956055 10.6780934334 155 0 Open ; +P-H-2439 2389 2439 497.676513672 7.98114442825 155 0 Open ; +P-H-2440 2390 2440 607.921966553 9.88782978058 155 0 Open ; +P-H-2441 2391 2441 515.15637207 3.66477525234 155 0 Open ; +P-H-2443 2393 2443 621.169067383 10.7715268135 155 0 Open ; +P-H-2444 2394 2444 407.510528564 11.5928163528 155 0 Open ; +P-H-2445 2395 2445 403.132751465 4.04283618927 155 0 Open ; +P-H-2446 2396 2446 428.832061768 14.6133813858 155 0 Open ; +P-H-2447 2397 2447 713.757019043 5.2793211937 155 0 Open ; +P-H-2449 2399 2449 632.921691895 13.2975482941 155 0 Open ; +P-H-2450 2400 2450 725.89666748 5.90617847443 155 0 Open ; +P-H-2454 2404 2454 276.338722229 7.50030946732 155 0 Open ; +P-H-2456 2406 2456 223.095245361 14.2362546921 155 0 Open ; +P-H-2461 2411 2461 261.034515381 11.1412982941 155 0 Open ; +P-H-2462 2412 2462 450.918502808 10.7473640442 155 0 Open ; +P-H-2463 2413 2463 331.550979614 14.5451803207 155 0 Open ; +P-H-2464 2414 2464 733.339233398 11.6561079025 155 0 Open ; +P-H-2465 2415 2465 509.56439209 7.97380113602 155 0 Open ; +P-H-2468 2418 2468 546.702758789 11.6682395935 155 0 Open ; +P-H-2469 2419 2469 660.271270752 14.5900020599 155 0 Open ; +P-H-2470 2420 2470 473.581848145 8.80506372452 155 0 Open ; +P-H-2475 2425 2475 791.070556641 13.4587545395 155 0 Open ; +P-H-2483 2433 2483 589.712738037 9.04249334335 155 0 Open ; +P-H-2486 2436 2486 213.249548912 4.70358753204 155 0 Open ; +P-H-2489 2439 2489 764.63079834 5.99595475197 155 0 Open ; +P-H-2492 2442 2492 494.547485352 12.1943149567 155 0 Open ; +P-H-2496 2446 2496 573.702301025 3.29364266992 155 0 Open ; +P-H-2499 2449 2499 571.069091797 6.16762518883 155 0 Open ; +P-S-0 2500 0 30 30 155 0 Open ; +P-S-1 2501 50 30 30 155 0 Open ; +P-S-2 2502 100 30 30 155 0 Open ; +P-S-3 2503 150 30 30 155 0 Open ; +P-S-4 2504 200 30 30 155 0 Open ; +[PUMPS] +;ID Node1 Node2 Parameters + +[CURVES] +;ID X-Value Y-Value +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers + +[CONTROLS] + + + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0:30 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] \ No newline at end of file diff --git a/benchmarks/small/valves_test.inp b/benchmarks/small/valves_test.inp new file mode 100644 index 0000000..81cc350 --- /dev/null +++ b/benchmarks/small/valves_test.inp @@ -0,0 +1,173 @@ +[JUNCTIONS] +;ID Elev Demand Pattern +2 50 0.1 ; +3 55 0.1 ; +4 35 0.1 ; +5 25 0.1 ; +6 67 0.1 ; +7 22 0.1 ; +8 56 0.1 ; +9 48 0.1 ; +10 52 0.1 ; +11 62 0.1 ; +12 35 0.1 ; +13 49 0.1 ; +14 65 0.1 ; +15 19 0.1 ; + +[RESERVOIRS] +;ID Head Pattern +1 100 ; + + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status +P1 1 2 100 5 155 0 Open ; +P2 2 4 100 5 155 0 Open ; +P3 4 5 100 5 155 0 Open ; +P4 2 3 100 5 155 0 Open ; +P5 4 6 100 5 155 0 Open ; +P6 5 7 100 5 155 0 Open ; +P7 3 6 100 5 155 0 Open ; +P8 6 13 100 5 155 0 Open ; +P9 3 8 100 5 155 0 Open ; +P10 6 8 100 5 155 0 Open ; +P11 6 9 100 5 155 0 Open ; +P12 7 9 100 5 155 0 Open ; +P13 8 9 100 5 155 0 Open ; +P14 7 10 100 5 155 0 Open ; +P15 10 11 100 5 155 0 Open ; +P16 10 12 100 5 155 0 Open ; +P17 13 15 100 5 155 0 Open ; +P18 13 14 100 5 155 0 Open ; +P19 14 15 100 5 155 0 Open ; +P20 15 7 100 5 155 0 Open ; + + +[PUMPS] +;ID Node1 Node2 Parameters + +[CURVES] +;ID X-Value Y-Value +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers + +[CONTROLS] + + + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0:30 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[ISOVALVES] +;ID Node Pipe +V1 2 P1 ; +V2 4 P3 ; +V3 2 P4 ; +V4 3 P4 ; +V5 6 P5 ; +V6 5 P6 ; +V7 3 P7 ; +V8 6 P8 ; +V9 3 P9 ; +V10 6 P10 ; +V11 8 P13 ; +V12 9 P13 ; +V13 7 P14 ; +V14 10 P15 ; +V15 13 P17 ; +V16 14 P19 ; +V17 7 P20 ; +[END] \ No newline at end of file diff --git a/benchmarks/todini_network_node.csv b/benchmarks/todini_network_node.csv deleted file mode 100644 index 035b0e4..0000000 --- a/benchmarks/todini_network_node.csv +++ /dev/null @@ -1,6 +0,0 @@ -Node_id,Node_coord1,Node_coord2,Node_coord3,Node_head,Node_discharge -0,1,3,0,100,-1 -1,0,2,0,85,10 -2,2,2,0,80,20 -3,0,0,0,70,30 -4,2,0,0,20,40 diff --git a/benchmarks/todini_network_node_iotest.csv b/benchmarks/todini_network_node_iotest.csv deleted file mode 100644 index 2741d18..0000000 --- a/benchmarks/todini_network_node_iotest.csv +++ /dev/null @@ -1,6 +0,0 @@ -Node_id,Node_coord1,Node_coord2,Node_coord3,Node_head,Node_discharge -0,1,3,0,100,-100 -1,0,2,0,99,10 -2,2,2,0,98,20 -3,0,0,0,97,30 -4,2,0,0,NA,40 diff --git a/benchmarks/todini_network_pipe.csv b/benchmarks/todini_network_pipe.csv deleted file mode 100644 index 183df49..0000000 --- a/benchmarks/todini_network_pipe.csv +++ /dev/null @@ -1,8 +0,0 @@ -Pipe_id,Pipe_node1,Pipe_node2,Pipe_diameter,Pipe_roughness,Pipe_status,Pipe_discharge -0,0,1,0.1,147683.3637,1,10 -1,0,2,0.2,4102.777965,1,10 -2,1,2,0.3,1238.160737,1,10 -3,1,3,0.4,1598.561076,1,30 -4,1,4,0.5,430.5609768,1,10 -5,2,4,0.6,137.5889198,1,10 -6,3,4,0.7,133.3735196,1,30 diff --git a/benchmarks/todini_network_pipe_iotest.csv b/benchmarks/todini_network_pipe_iotest.csv deleted file mode 100644 index 2eadde8..0000000 --- a/benchmarks/todini_network_pipe_iotest.csv +++ /dev/null @@ -1,8 +0,0 @@ -Pipe_id,Pipe_node1,Pipe_node2,Pipe_diameter,Pipe_roughness,Pipe_status,Pipe_discharge -0,0,1,0.1,147683.3637,1,80 -1,0,2,0.2,4102.777965,1,20 -2,1,2,0.3,1238.160737,1,10 -3,1,3,0.4,1598.561076,1,40 -4,1,4,0.5,430.5609768,1,20 -5,2,4,0.6,137.5889198,1,NA -6,3,4,0.7,133.3735196,1,10 diff --git a/clang-tools/format.sh b/clang-tools/format.sh new file mode 100644 index 0000000..bb3a7b5 --- /dev/null +++ b/clang-tools/format.sh @@ -0,0 +1,4 @@ +#!/bin/bash +find ../include/ -iname *.h -o -iname *.cc | xargs clang-format -i +find ../src/ -iname *.h -o -iname *.cc | xargs clang-format -i +find ../tests/ -iname *.h -o -iname *.cc | xargs clang-format -i diff --git a/clang-tools/run-clang-format.py b/clang-tools/run-clang-format.py new file mode 100644 index 0000000..975ace3 --- /dev/null +++ b/clang-tools/run-clang-format.py @@ -0,0 +1,326 @@ +#!/usr/bin/env python +"""A wrapper script around clang-format, suitable for linting multiple files +and to use for continuous integration. + +This is an alternative API for the clang-format command line. +It runs over multiple files and directories in parallel. +A diff output is produced and a sensible exit code is returned. + +""" + +from __future__ import print_function, unicode_literals + +import argparse +import codecs +import difflib +import fnmatch +import io +import multiprocessing +import os +import signal +import subprocess +import sys +import traceback + +from functools import partial + +DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx' + + +class ExitStatus: + SUCCESS = 0 + DIFF = 1 + TROUBLE = 2 + + +def list_files(files, recursive=False, extensions=None, exclude=None): + if extensions is None: + extensions = [] + if exclude is None: + exclude = [] + + out = [] + for file in files: + if recursive and os.path.isdir(file): + for dirpath, dnames, fnames in os.walk(file): + fpaths = [os.path.join(dirpath, fname) for fname in fnames] + for pattern in exclude: + # os.walk() supports trimming down the dnames list + # by modifying it in-place, + # to avoid unnecessary directory listings. + dnames[:] = [ + x for x in dnames + if + not fnmatch.fnmatch(os.path.join(dirpath, x), pattern) + ] + fpaths = [ + x for x in fpaths if not fnmatch.fnmatch(x, pattern) + ] + for f in fpaths: + ext = os.path.splitext(f)[1][1:] + if ext in extensions: + out.append(f) + else: + out.append(file) + return out + + +def make_diff(file, original, reformatted): + return list( + difflib.unified_diff( + original, + reformatted, + fromfile='{}\t(original)'.format(file), + tofile='{}\t(reformatted)'.format(file), + n=3)) + + +class DiffError(Exception): + def __init__(self, message, errs=None): + super(DiffError, self).__init__(message) + self.errs = errs or [] + + +class UnexpectedError(Exception): + def __init__(self, message, exc=None): + super(UnexpectedError, self).__init__(message) + self.formatted_traceback = traceback.format_exc() + self.exc = exc + + +def run_clang_format_diff_wrapper(args, file): + try: + ret = run_clang_format_diff(args, file) + return ret + except DiffError: + raise + except Exception as e: + raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__, + e), e) + + +def run_clang_format_diff(args, file): + try: + with io.open(file, 'r', encoding='utf-8') as f: + original = f.readlines() + except IOError as exc: + raise DiffError(str(exc)) + invocation = [args.clang_format_executable, file] + + # Use of utf-8 to decode the process output. + # + # Hopefully, this is the correct thing to do. + # + # It's done due to the following assumptions (which may be incorrect): + # - clang-format will returns the bytes read from the files as-is, + # without conversion, and it is already assumed that the files use utf-8. + # - if the diagnostics were internationalized, they would use utf-8: + # > Adding Translations to Clang + # > + # > Not possible yet! + # > Diagnostic strings should be written in UTF-8, + # > the client can translate to the relevant code page if needed. + # > Each translation completely replaces the format string + # > for the diagnostic. + # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation + # + # It's not pretty, due to Python 2 & 3 compatibility. + encoding_py3 = {} + if sys.version_info[0] >= 3: + encoding_py3['encoding'] = 'utf-8' + + try: + proc = subprocess.Popen( + invocation, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + **encoding_py3) + except OSError as exc: + raise DiffError(str(exc)) + proc_stdout = proc.stdout + proc_stderr = proc.stderr + if sys.version_info[0] < 3: + # make the pipes compatible with Python 3, + # reading lines should output unicode + encoding = 'utf-8' + proc_stdout = codecs.getreader(encoding)(proc_stdout) + proc_stderr = codecs.getreader(encoding)(proc_stderr) + # hopefully the stderr pipe won't get full and block the process + outs = list(proc_stdout.readlines()) + errs = list(proc_stderr.readlines()) + proc.wait() + if proc.returncode: + raise DiffError("clang-format exited with status {}: '{}'".format( + proc.returncode, file), errs) + return make_diff(file, original, outs), errs + + +def bold_red(s): + return '\x1b[1m\x1b[31m' + s + '\x1b[0m' + + +def colorize(diff_lines): + def bold(s): + return '\x1b[1m' + s + '\x1b[0m' + + def cyan(s): + return '\x1b[36m' + s + '\x1b[0m' + + def green(s): + return '\x1b[32m' + s + '\x1b[0m' + + def red(s): + return '\x1b[31m' + s + '\x1b[0m' + + for line in diff_lines: + if line[:4] in ['--- ', '+++ ']: + yield bold(line) + elif line.startswith('@@ '): + yield cyan(line) + elif line.startswith('+'): + yield green(line) + elif line.startswith('-'): + yield red(line) + else: + yield line + + +def print_diff(diff_lines, use_color): + if use_color: + diff_lines = colorize(diff_lines) + if sys.version_info[0] < 3: + sys.stdout.writelines((l.encode('utf-8') for l in diff_lines)) + else: + sys.stdout.writelines(diff_lines) + + +def print_trouble(prog, message, use_colors): + error_text = 'error:' + if use_colors: + error_text = bold_red(error_text) + print("{}: {} {}".format(prog, error_text, message), file=sys.stderr) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '--clang-format-executable', + metavar='EXECUTABLE', + help='path to the clang-format executable', + default='clang-format') + parser.add_argument( + '--extensions', + help='comma separated list of file extensions (default: {})'.format( + DEFAULT_EXTENSIONS), + default=DEFAULT_EXTENSIONS) + parser.add_argument( + '-r', + '--recursive', + action='store_true', + help='run recursively over directories') + parser.add_argument('files', metavar='file', nargs='+') + parser.add_argument( + '-q', + '--quiet', + action='store_true') + parser.add_argument( + '-j', + metavar='N', + type=int, + default=0, + help='run N clang-format jobs in parallel' + ' (default number of cpus + 1)') + parser.add_argument( + '--color', + default='auto', + choices=['auto', 'always', 'never'], + help='show colored diff (default: auto)') + parser.add_argument( + '-e', + '--exclude', + metavar='PATTERN', + action='append', + default=[], + help='exclude paths matching the given glob-like pattern(s)' + ' from recursive search') + + args = parser.parse_args() + + # use default signal handling, like diff return SIGINT value on ^C + # https://bugs.python.org/issue14229#msg156446 + signal.signal(signal.SIGINT, signal.SIG_DFL) + try: + signal.SIGPIPE + except AttributeError: + # compatibility, SIGPIPE does not exist on Windows + pass + else: + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + colored_stdout = False + colored_stderr = False + if args.color == 'always': + colored_stdout = True + colored_stderr = True + elif args.color == 'auto': + colored_stdout = sys.stdout.isatty() + colored_stderr = sys.stderr.isatty() + + retcode = ExitStatus.SUCCESS + files = list_files( + args.files, + recursive=args.recursive, + exclude=args.exclude, + extensions=args.extensions.split(',')) + + if not files: + return + + njobs = args.j + if njobs == 0: + njobs = multiprocessing.cpu_count() + 1 + njobs = min(len(files), njobs) + + if njobs == 1: + # execute directly instead of in a pool, + # less overhead, simpler stacktraces + it = (run_clang_format_diff_wrapper(args, file) for file in files) + pool = None + else: + pool = multiprocessing.Pool(njobs) + it = pool.imap_unordered( + partial(run_clang_format_diff_wrapper, args), files) + while True: + try: + outs, errs = next(it) + except StopIteration: + break + except DiffError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + retcode = ExitStatus.TROUBLE + sys.stderr.writelines(e.errs) + except UnexpectedError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + sys.stderr.write(e.formatted_traceback) + retcode = ExitStatus.TROUBLE + # stop at the first unexpected error, + # something could be very wrong, + # don't process all files unnecessarily + if pool: + pool.terminate() + break + else: + sys.stderr.writelines(errs) + if outs == []: + continue + if not args.quiet: + print_diff(outs, use_color=colored_stdout) + if retcode == ExitStatus.SUCCESS: + retcode = ExitStatus.DIFF + return retcode + + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/clang-tools/run-clang-tidy.py b/clang-tools/run-clang-tidy.py new file mode 100644 index 0000000..ce46c0e --- /dev/null +++ b/clang-tools/run-clang-tidy.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python +# +#===- run-clang-tidy.py - Parallel clang-tidy runner ---------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# FIXME: Integrate with clang-tidy-diff.py + +""" +Parallel clang-tidy runner +========================== + +Runs clang-tidy over all files in a compilation database. Requires clang-tidy +and clang-apply-replacements in $PATH. + +Example invocations. +- Run clang-tidy on all files in the current working directory with a default + set of checks and show warnings in the cpp files and all project headers. + run-clang-tidy.py $PWD + +- Fix all header guards. + run-clang-tidy.py -fix -checks=-*,llvm-header-guard + +- Fix all header guards included from clang-tidy and header guards + for clang-tidy headers. + run-clang-tidy.py -fix -checks=-*,llvm-header-guard extra/clang-tidy \ + -header-filter=extra/clang-tidy + +Compilation database setup: +http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +""" + +from __future__ import print_function + +import argparse +import glob +import json +import multiprocessing +import os +import re +import shutil +import subprocess +import sys +import tempfile +import threading +import traceback +import yaml + +is_py2 = sys.version[0] == '2' + +if is_py2: + import Queue as queue +else: + import queue as queue + +def find_compilation_database(path): + """Adjusts the directory until a compilation database is found.""" + result = './' + while not os.path.isfile(os.path.join(result, path)): + if os.path.realpath(result) == '/': + print('Error: could not find compilation database.') + sys.exit(1) + result += '../' + return os.path.realpath(result) + + +def make_absolute(f, directory): + if os.path.isabs(f): + return f + return os.path.normpath(os.path.join(directory, f)) + + +def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path, + header_filter, extra_arg, extra_arg_before, quiet, + config): + """Gets a command line for clang-tidy.""" + start = [clang_tidy_binary] + if header_filter is not None: + start.append('-header-filter=' + header_filter) + else: + # Show warnings in all in-project headers by default. + start.append('-header-filter=^' + build_path + '/.*') + if checks: + start.append('-checks=' + checks) + if tmpdir is not None: + start.append('-export-fixes') + # Get a temporary file. We immediately close the handle so clang-tidy can + # overwrite it. + (handle, name) = tempfile.mkstemp(suffix='.yaml', dir=tmpdir) + os.close(handle) + start.append(name) + for arg in extra_arg: + start.append('-extra-arg=%s' % arg) + for arg in extra_arg_before: + start.append('-extra-arg-before=%s' % arg) + start.append('-p=' + build_path) + if quiet: + start.append('-quiet') + if config: + start.append('-config=' + config) + start.append(f) + return start + + +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # The fixes suggested by clang-tidy >= 4.0.0 are given under + # the top level key 'Diagnostics' in the output yaml files + mergekey="Diagnostics" + merged=[] + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): + content = yaml.safe_load(open(replacefile, 'r')) + if not content: + continue # Skip empty files. + merged.extend(content.get(mergekey, [])) + + if merged: + # MainSourceFile: The key is required by the definition inside + # include/clang/Tooling/ReplacementsYaml.h, but the value + # is actually never used inside clang-apply-replacements, + # so we set it to '' here. + output = { 'MainSourceFile': '', mergekey: merged } + with open(mergefile, 'w') as out: + yaml.safe_dump(output, out) + else: + # Empty the file: + open(mergefile, 'w').close() + + +def check_clang_apply_replacements_binary(args): + """Checks if invoking supplied clang-apply-replacements binary works.""" + try: + subprocess.check_call([args.clang_apply_replacements_binary, '--version']) + except: + print('Unable to run clang-apply-replacements. Is clang-apply-replacements ' + 'binary correctly specified?', file=sys.stderr) + traceback.print_exc() + sys.exit(1) + + +def apply_fixes(args, tmpdir): + """Calls clang-apply-fixes on a given directory.""" + invocation = [args.clang_apply_replacements_binary] + if args.format: + invocation.append('-format') + if args.style: + invocation.append('-style=' + args.style) + invocation.append(tmpdir) + subprocess.call(invocation) + + +def run_tidy(args, tmpdir, build_path, queue, failed_files): + """Takes filenames out of queue and runs clang-tidy on them.""" + while True: + name = queue.get() + invocation = get_tidy_invocation(name, args.clang_tidy_binary, args.checks, + tmpdir, build_path, args.header_filter, + args.extra_arg, args.extra_arg_before, + args.quiet, args.config) + sys.stdout.write(' '.join(invocation) + '\n') + return_code = subprocess.call(invocation) + if return_code != 0: + failed_files.append(name) + queue.task_done() + + +def main(): + parser = argparse.ArgumentParser(description='Runs clang-tidy over all files ' + 'in a compilation database. Requires ' + 'clang-tidy and clang-apply-replacements in ' + '$PATH.') + parser.add_argument('-clang-tidy-binary', metavar='PATH', + default='clang-tidy', + help='path to clang-tidy binary') + parser.add_argument('-clang-apply-replacements-binary', metavar='PATH', + default='clang-apply-replacements', + help='path to clang-apply-replacements binary') + parser.add_argument('-checks', default=None, + help='checks filter, when not specified, use clang-tidy ' + 'default') + parser.add_argument('-config', default=None, + help='Specifies a configuration in YAML/JSON format: ' + ' -config="{Checks: \'*\', ' + ' CheckOptions: [{key: x, ' + ' value: y}]}" ' + 'When the value is empty, clang-tidy will ' + 'attempt to find a file named .clang-tidy for ' + 'each source file in its parent directories.') + parser.add_argument('-header-filter', default=None, + help='regular expression matching the names of the ' + 'headers to output diagnostics from. Diagnostics from ' + 'the main file of each translation unit are always ' + 'displayed.') + parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes', + help='Create a yaml file to store suggested fixes in, ' + 'which can be applied with clang-apply-replacements.') + parser.add_argument('-j', type=int, default=0, + help='number of tidy instances to be run in parallel.') + parser.add_argument('files', nargs='*', default=['.*'], + help='files to be processed (regex on path)') + parser.add_argument('-fix', action='store_true', help='apply fix-its') + parser.add_argument('-format', action='store_true', help='Reformat code ' + 'after applying fixes') + parser.add_argument('-style', default='file', help='The style of reformat ' + 'code after applying fixes') + parser.add_argument('-p', dest='build_path', + help='Path used to read a compile command database.') + parser.add_argument('-extra-arg', dest='extra_arg', + action='append', default=[], + help='Additional argument to append to the compiler ' + 'command line.') + parser.add_argument('-extra-arg-before', dest='extra_arg_before', + action='append', default=[], + help='Additional argument to prepend to the compiler ' + 'command line.') + parser.add_argument('-quiet', action='store_true', + help='Run clang-tidy in quiet mode') + args = parser.parse_args() + + db_path = 'compile_commands.json' + + if args.build_path is not None: + build_path = args.build_path + else: + # Find our database + build_path = find_compilation_database(db_path) + + try: + invocation = [args.clang_tidy_binary, '-list-checks'] + invocation.append('-p=' + build_path) + if args.checks: + invocation.append('-checks=' + args.checks) + invocation.append('-') + subprocess.check_call(invocation) + except: + print("Unable to run clang-tidy.", file=sys.stderr) + sys.exit(1) + + # Load the database and extract all files. + database = json.load(open(os.path.join(build_path, db_path))) + files = [make_absolute(entry['file'], entry['directory']) + for entry in database] + + max_task = args.j + if max_task == 0: + max_task = multiprocessing.cpu_count() + + tmpdir = None + if args.fix or args.export_fixes: + check_clang_apply_replacements_binary(args) + tmpdir = tempfile.mkdtemp() + + # Build up a big regexy filter from all command line arguments. + file_name_re = re.compile('|'.join(args.files)) + + return_code = 0 + try: + # Spin up a bunch of tidy-launching threads. + task_queue = queue.Queue(max_task) + # List of files with a non-zero return code. + failed_files = [] + for _ in range(max_task): + t = threading.Thread(target=run_tidy, + args=(args, tmpdir, build_path, task_queue, failed_files)) + t.daemon = True + t.start() + + # Fill the queue with files. + for name in files: + if file_name_re.search(name): + task_queue.put(name) + + # Wait for all threads to be done. + task_queue.join() + if len(failed_files): + return_code = 1 + + except KeyboardInterrupt: + # This is a sad hack. Unfortunately subprocess goes + # bonkers with ctrl-c and we start forking merrily. + print('\nCtrl-C detected, goodbye.') + if tmpdir: + shutil.rmtree(tmpdir) + os.kill(0, 9) + + if args.export_fixes: + print('Writing fixes to ' + args.export_fixes + ' ...') + try: + merge_replacement_files(tmpdir, args.export_fixes) + except: + print('Error exporting fixes.\n', file=sys.stderr) + traceback.print_exc() + return_code=1 + + if args.fix: + print('Applying fixes ...') + try: + apply_fixes(args, tmpdir) + except: + print('Error applying fixes.\n', file=sys.stderr) + traceback.print_exc() + return_code=1 + + if tmpdir: + shutil.rmtree(tmpdir) + sys.exit(return_code) + +if __name__ == '__main__': + main() diff --git a/cmake/FindMKL.cmake b/cmake/FindMKL.cmake new file mode 100644 index 0000000..3ef3ebf --- /dev/null +++ b/cmake/FindMKL.cmake @@ -0,0 +1,24 @@ +# +# FindMKL++ +# ---------- +# +# Try to find the Intel Math Kernel Library + +if(NOT MKL_FOUND) + set(MKL_INCLUDE_PATH "/opt/intel/mkl/include") + set(MKL_LIBRARY_PATH "/opt/intel/mkl/lib") + set(INTEL_LIBRARY_PATH "/opt/intel/lib") + + find_path(MKL_INCLUDE_DIR mkl.h HINTS ${MKL_INCLUDE_PATH} ENV CPATH) + find_library(MKL_CORE mkl_core HINTS ${MKL_LIBRARY_PATH} ENV LD_LIBRARY_PATH) + find_library(MKL_THREAD mkl_intel_thread HINTS ${MKL_LIBRARY_PATH} ENV LD_LIBRARY_PATH) + find_library(MKL_LP mkl_intel_lp64 HINTS ${MKL_LIBRARY_PATH} ENV LD_LIBRARY_PATH) + find_library(IOMP5 iomp5 HINTS ${INTEL_LIBRARY_PATH} ENV LD_LIBRARY_PATH) + + set(MKL_LIBRARIES ${MKL_LP} ${MKL_THREAD} ${MKL_CORE} ${IOMP5}) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(MKL DEFAULT_MSG MKL_INCLUDE_DIR MKL_LIBRARIES) + + mark_as_advanced(MKL_INCLUDE_DIR MKL_LIBRARIES) +endif() \ No newline at end of file diff --git a/external/EigenDenseBaseAddons.h b/external/EigenDenseBaseAddons.h index 5a529f7..de0ff9e 100644 --- a/external/EigenDenseBaseAddons.h +++ b/external/EigenDenseBaseAddons.h @@ -1,26 +1,25 @@ friend class boost::serialization::access; -template -void save(Archive & ar, const unsigned int version) const { +template +void save(Archive &ar, const unsigned int version) const { derived().eval(); const Index rows = derived().rows(), cols = derived().cols(); - ar & rows; - ar & cols; - for (Index j = 0; j < cols; ++j ) - for (Index i = 0; i < rows; ++i ) - ar & derived().coeff(i, j); + ar &rows; + ar &cols; + for (Index j = 0; j < cols; ++j) + for (Index i = 0; i < rows; ++i) + ar &derived().coeff(i, j); } -template -void load(Archive & ar, const unsigned int version) { +template void load(Archive &ar, const unsigned int version) { Index rows, cols; - ar & rows; - ar & cols; - if (rows != derived().rows() || cols != derived().cols() ) + ar &rows; + ar &cols; + if (rows != derived().rows() || cols != derived().cols()) derived().resize(rows, cols); - ar & boost::serialization::make_array(derived().data(), derived().size()); + ar &boost::serialization::make_array(derived().data(), derived().size()); } -template -void serialize(Archive & ar, const unsigned int file_version) { +template +void serialize(Archive &ar, const unsigned int file_version) { boost::serialization::split_member(ar, *this, file_version); } diff --git a/external/csv.h b/external/csv.h index 93e9034..2c9af94 100644 --- a/external/csv.h +++ b/external/csv.h @@ -9,11 +9,11 @@ // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // -//2. Redistributions in binary form must reproduce the above copyright notice, +// 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // -//3. Neither the name of the copyright holder nor the names of its contributors +// 3. Neither the name of the copyright holder nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // @@ -32,1237 +32,1161 @@ #ifndef CSV_H #define CSV_H -#include -#include -#include #include -#include #include +#include #include +#include +#include +#include #ifndef CSV_IO_NO_THREAD +#include #include #include -#include #endif -#include #include #include #include +#include + +namespace io { +//////////////////////////////////////////////////////////////////////////// +// LineReader // +//////////////////////////////////////////////////////////////////////////// + +namespace error { +struct base : std::exception { + virtual void format_error_message() const = 0; + + const char *what() const throw() { + format_error_message(); + return error_message_buffer; + } + + mutable char error_message_buffer[512]; +}; + +const int max_file_name_length = 255; + +struct with_file_name { + with_file_name() { std::memset(file_name, 0, sizeof(file_name)); } + + void set_file_name(const char *file_name) { + if (file_name != nullptr) { + strncpy(this->file_name, file_name, sizeof(this->file_name)); + this->file_name[sizeof(this->file_name) - 1] = '\0'; + } else { + this->file_name[0] = '\0'; + } + } + + char file_name[max_file_name_length + 1]; +}; + +struct with_file_line { + with_file_line() { file_line = -1; } + + void set_file_line(int file_line) { this->file_line = file_line; } + + int file_line; +}; + +struct with_errno { + with_errno() { errno_value = 0; } + + void set_errno(int errno_value) { this->errno_value = errno_value; } + + int errno_value; +}; + +struct can_not_open_file : base, with_file_name, with_errno { + void format_error_message() const { + if (errno_value != 0) + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Can not open file \"%s\" because \"%s\".", file_name, + std::strerror(errno_value)); + else + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Can not open file \"%s\".", file_name); + } +}; + +struct line_length_limit_exceeded : base, with_file_name, with_file_line { + void format_error_message() const { + std::snprintf( + error_message_buffer, sizeof(error_message_buffer), + "Line number %d in file \"%s\" exceeds the maximum length of 2^24-1.", + file_line, file_name); + } +}; +} // namespace error + +class ByteSourceBase { +public: + virtual int read(char *buffer, int size) = 0; + virtual ~ByteSourceBase() {} +}; + +namespace detail { + +class OwningStdIOByteSourceBase : public ByteSourceBase { +public: + explicit OwningStdIOByteSourceBase(FILE *file) : file(file) { + // Tell the std library that we want to do the buffering ourself. + std::setvbuf(file, 0, _IONBF, 0); + } + + int read(char *buffer, int size) { return std::fread(buffer, 1, size, file); } + + ~OwningStdIOByteSourceBase() { std::fclose(file); } + +private: + FILE *file; +}; + +class NonOwningIStreamByteSource : public ByteSourceBase { +public: + explicit NonOwningIStreamByteSource(std::istream &in) : in(in) {} + + int read(char *buffer, int size) { + in.read(buffer, size); + return in.gcount(); + } + + ~NonOwningIStreamByteSource() {} + +private: + std::istream ∈ +}; + +class NonOwningStringByteSource : public ByteSourceBase { +public: + NonOwningStringByteSource(const char *str, long long size) + : str(str), remaining_byte_count(size) {} + + int read(char *buffer, int desired_byte_count) { + int to_copy_byte_count = desired_byte_count; + if (remaining_byte_count < to_copy_byte_count) + to_copy_byte_count = remaining_byte_count; + std::memcpy(buffer, str, to_copy_byte_count); + remaining_byte_count -= to_copy_byte_count; + str += to_copy_byte_count; + return to_copy_byte_count; + } + + ~NonOwningStringByteSource() {} + +private: + const char *str; + long long remaining_byte_count; +}; -namespace io{ - //////////////////////////////////////////////////////////////////////////// - // LineReader // - //////////////////////////////////////////////////////////////////////////// - - namespace error{ - struct base : std::exception{ - virtual void format_error_message()const = 0; - - const char*what()const throw(){ - format_error_message(); - return error_message_buffer; - } - - mutable char error_message_buffer[512]; - }; - - const int max_file_name_length = 255; - - struct with_file_name{ - with_file_name(){ - std::memset(file_name, 0, sizeof(file_name)); - } - - void set_file_name(const char*file_name){ - if(file_name != nullptr){ - strncpy(this->file_name, file_name, sizeof(this->file_name)); - this->file_name[sizeof(this->file_name)-1] = '\0'; - }else{ - this->file_name[0] = '\0'; - } - } - - char file_name[max_file_name_length+1]; - }; - - struct with_file_line{ - with_file_line(){ - file_line = -1; - } - - void set_file_line(int file_line){ - this->file_line = file_line; - } - - int file_line; - }; - - struct with_errno{ - with_errno(){ - errno_value = 0; - } - - void set_errno(int errno_value){ - this->errno_value = errno_value; - } - - int errno_value; - }; - - struct can_not_open_file : - base, - with_file_name, - with_errno{ - void format_error_message()const{ - if(errno_value != 0) - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Can not open file \"%s\" because \"%s\"." - , file_name, std::strerror(errno_value)); - else - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Can not open file \"%s\"." - , file_name); - } - }; - - struct line_length_limit_exceeded : - base, - with_file_name, - with_file_line{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Line number %d in file \"%s\" exceeds the maximum length of 2^24-1." - , file_line, file_name); - } - }; +#ifndef CSV_IO_NO_THREAD +class AsynchronousReader { +public: + void init(std::unique_ptr arg_byte_source) { + std::unique_lock guard(lock); + byte_source = std::move(arg_byte_source); + desired_byte_count = -1; + termination_requested = false; + worker = std::thread([&] { + std::unique_lock guard(lock); + try { + for (;;) { + read_requested_condition.wait(guard, [&] { + return desired_byte_count != -1 || termination_requested; + }); + if (termination_requested) + return; + + read_byte_count = byte_source->read(buffer, desired_byte_count); + desired_byte_count = -1; + if (read_byte_count == 0) + break; + read_finished_condition.notify_one(); + } + } catch (...) { + read_error = std::current_exception(); + } + read_finished_condition.notify_one(); + }); + } + + bool is_valid() const { return byte_source != nullptr; } + + void start_read(char *arg_buffer, int arg_desired_byte_count) { + std::unique_lock guard(lock); + buffer = arg_buffer; + desired_byte_count = arg_desired_byte_count; + read_byte_count = -1; + read_requested_condition.notify_one(); + } + + int finish_read() { + std::unique_lock guard(lock); + read_finished_condition.wait( + guard, [&] { return read_byte_count != -1 || read_error; }); + if (read_error) + std::rethrow_exception(read_error); + else + return read_byte_count; + } + + ~AsynchronousReader() { + if (byte_source != nullptr) { + { + std::unique_lock guard(lock); + termination_requested = true; + } + read_requested_condition.notify_one(); + worker.join(); + } + } + +private: + std::unique_ptr byte_source; + + std::thread worker; + + bool termination_requested; + std::exception_ptr read_error; + char *buffer; + int desired_byte_count; + int read_byte_count; + + std::mutex lock; + std::condition_variable read_finished_condition; + std::condition_variable read_requested_condition; +}; +#endif + +class SynchronousReader { +public: + void init(std::unique_ptr arg_byte_source) { + byte_source = std::move(arg_byte_source); + } + + bool is_valid() const { return byte_source != nullptr; } + + void start_read(char *arg_buffer, int arg_desired_byte_count) { + buffer = arg_buffer; + desired_byte_count = arg_desired_byte_count; + } + + int finish_read() { return byte_source->read(buffer, desired_byte_count); } + +private: + std::unique_ptr byte_source; + char *buffer; + int desired_byte_count; +}; +} // namespace detail + +class LineReader { +private: + static const int block_len = 1 << 24; + std::unique_ptr buffer; // must be constructed before (and thus + // destructed after) the reader! +#ifdef CSV_IO_NO_THREAD + detail::SynchronousReader reader; +#else + detail::AsynchronousReader reader; +#endif + int data_begin; + int data_end; + + char file_name[error::max_file_name_length + 1]; + unsigned file_line; + + static std::unique_ptr open_file(const char *file_name) { + // We open the file in binary mode as it makes no difference under *nix + // and under Windows we handle \r\n newlines ourself. + FILE *file = std::fopen(file_name, "rb"); + if (file == 0) { + int x = errno; // store errno as soon as possible, doing it after + // constructor call can fail. + error::can_not_open_file err; + err.set_errno(x); + err.set_file_name(file_name); + throw err; + } + return std::unique_ptr( + new detail::OwningStdIOByteSourceBase(file)); + } + + void init(std::unique_ptr byte_source) { + file_line = 0; + + buffer = std::unique_ptr(new char[3 * block_len]); + data_begin = 0; + data_end = byte_source->read(buffer.get(), 2 * block_len); + + // Ignore UTF-8 BOM + if (data_end >= 3 && buffer[0] == '\xEF' && buffer[1] == '\xBB' && + buffer[2] == '\xBF') + data_begin = 3; + + if (data_end == 2 * block_len) { + reader.init(std::move(byte_source)); + reader.start_read(buffer.get() + 2 * block_len, block_len); + } + } + +public: + LineReader() = delete; + LineReader(const LineReader &) = delete; + LineReader &operator=(const LineReader &) = delete; + + explicit LineReader(const char *file_name) { + set_file_name(file_name); + init(open_file(file_name)); + } + + explicit LineReader(const std::string &file_name) { + set_file_name(file_name.c_str()); + init(open_file(file_name.c_str())); + } + + LineReader(const char *file_name, + std::unique_ptr byte_source) { + set_file_name(file_name); + init(std::move(byte_source)); + } + + LineReader(const std::string &file_name, + std::unique_ptr byte_source) { + set_file_name(file_name.c_str()); + init(std::move(byte_source)); + } + + LineReader(const char *file_name, const char *data_begin, + const char *data_end) { + set_file_name(file_name); + init(std::unique_ptr(new detail::NonOwningStringByteSource( + data_begin, data_end - data_begin))); + } + + LineReader(const std::string &file_name, const char *data_begin, + const char *data_end) { + set_file_name(file_name.c_str()); + init(std::unique_ptr(new detail::NonOwningStringByteSource( + data_begin, data_end - data_begin))); + } + + LineReader(const char *file_name, FILE *file) { + set_file_name(file_name); + init(std::unique_ptr( + new detail::OwningStdIOByteSourceBase(file))); + } + + LineReader(const std::string &file_name, FILE *file) { + set_file_name(file_name.c_str()); + init(std::unique_ptr( + new detail::OwningStdIOByteSourceBase(file))); + } + + LineReader(const char *file_name, std::istream &in) { + set_file_name(file_name); + init(std::unique_ptr( + new detail::NonOwningIStreamByteSource(in))); + } + + LineReader(const std::string &file_name, std::istream &in) { + set_file_name(file_name.c_str()); + init(std::unique_ptr( + new detail::NonOwningIStreamByteSource(in))); + } + + void set_file_name(const std::string &file_name) { + set_file_name(file_name.c_str()); + } + + void set_file_name(const char *file_name) { + if (file_name != nullptr) { + strncpy(this->file_name, file_name, sizeof(this->file_name)); + this->file_name[sizeof(this->file_name) - 1] = '\0'; + } else { + this->file_name[0] = '\0'; + } + } + + const char *get_truncated_file_name() const { return file_name; } + + void set_file_line(unsigned file_line) { this->file_line = file_line; } + + unsigned get_file_line() const { return file_line; } + + char *next_line() { + if (data_begin == data_end) + return 0; + + ++file_line; + + assert(data_begin < data_end); + assert(data_end <= block_len * 2); + + if (data_begin >= block_len) { + std::memcpy(buffer.get(), buffer.get() + block_len, block_len); + data_begin -= block_len; + data_end -= block_len; + if (reader.is_valid()) { + data_end += reader.finish_read(); + std::memcpy(buffer.get() + block_len, buffer.get() + 2 * block_len, + block_len); + reader.start_read(buffer.get() + 2 * block_len, block_len); + } + } + + int line_end = data_begin; + while (buffer[line_end] != '\n' && line_end != data_end) { + ++line_end; + } + + if (line_end - data_begin + 1 > block_len) { + error::line_length_limit_exceeded err; + err.set_file_name(file_name); + err.set_file_line(file_line); + throw err; + } + + if (buffer[line_end] == '\n' && line_end != data_end) { + buffer[line_end] = '\0'; + } else { + // some files are missing the newline at the end of the + // last line + ++data_end; + buffer[line_end] = '\0'; + } + + // handle windows \r\n-line breaks + if (line_end != data_begin && buffer[line_end - 1] == '\r') + buffer[line_end - 1] = '\0'; + + char *ret = buffer.get() + data_begin; + data_begin = line_end + 1; + return ret; + } +}; + +//////////////////////////////////////////////////////////////////////////// +// CSV // +//////////////////////////////////////////////////////////////////////////// + +namespace error { +const int max_column_name_length = 63; +struct with_column_name { + with_column_name() { + std::memset(column_name, 0, max_column_name_length + 1); + } + + void set_column_name(const char *column_name) { + if (column_name != nullptr) { + std::strncpy(this->column_name, column_name, max_column_name_length); + this->column_name[max_column_name_length] = '\0'; + } else { + this->column_name[0] = '\0'; + } + } + + char column_name[max_column_name_length + 1]; +}; + +const int max_column_content_length = 63; + +struct with_column_content { + with_column_content() { + std::memset(column_content, 0, max_column_content_length + 1); + } + + void set_column_content(const char *column_content) { + if (column_content != nullptr) { + std::strncpy(this->column_content, column_content, + max_column_content_length); + this->column_content[max_column_content_length] = '\0'; + } else { + this->column_content[0] = '\0'; + } + } + + char column_content[max_column_content_length + 1]; +}; + +struct extra_column_in_header : base, with_file_name, with_column_name { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Extra column \"%s\" in header of file \"%s\".", column_name, + file_name); + } +}; + +struct missing_column_in_header : base, with_file_name, with_column_name { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Missing column \"%s\" in header of file \"%s\".", + column_name, file_name); + } +}; + +struct duplicated_column_in_header : base, with_file_name, with_column_name { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Duplicated column \"%s\" in header of file \"%s\".", + column_name, file_name); + } +}; + +struct header_missing : base, with_file_name { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Header missing in file \"%s\".", file_name); + } +}; + +struct too_few_columns : base, with_file_name, with_file_line { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Too few columns in line %d in file \"%s\".", file_line, + file_name); + } +}; + +struct too_many_columns : base, with_file_name, with_file_line { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Too many columns in line %d in file \"%s\".", file_line, + file_name); + } +}; + +struct escaped_string_not_closed : base, with_file_name, with_file_line { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Escaped string was not closed in line %d in file \"%s\".", + file_line, file_name); + } +}; + +struct integer_must_be_positive : base, + with_file_name, + with_file_line, + with_column_name, + with_column_content { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "The integer \"%s\" must be positive or 0 in column \"%s\" " + "in file \"%s\" in line \"%d\".", + column_content, column_name, file_name, file_line); + } +}; + +struct no_digit : base, + with_file_name, + with_file_line, + with_column_name, + with_column_content { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "The integer \"%s\" contains an invalid digit in column " + "\"%s\" in file \"%s\" in line \"%d\".", + column_content, column_name, file_name, file_line); + } +}; + +struct integer_overflow : base, + with_file_name, + with_file_line, + with_column_name, + with_column_content { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "The integer \"%s\" overflows in column \"%s\" in file " + "\"%s\" in line \"%d\".", + column_content, column_name, file_name, file_line); + } +}; + +struct integer_underflow : base, + with_file_name, + with_file_line, + with_column_name, + with_column_content { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "The integer \"%s\" underflows in column \"%s\" in file " + "\"%s\" in line \"%d\".", + column_content, column_name, file_name, file_line); + } +}; + +struct invalid_single_character : base, + with_file_name, + with_file_line, + with_column_name, + with_column_content { + void format_error_message() const { + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "The content \"%s\" of column \"%s\" in file \"%s\" in line " + "\"%d\" is not a single character.", + column_content, column_name, file_name, file_line); + } +}; +} // namespace error + +typedef unsigned ignore_column; +static const ignore_column ignore_no_column = 0; +static const ignore_column ignore_extra_column = 1; +static const ignore_column ignore_missing_column = 2; + +template struct trim_chars { +private: + constexpr static bool is_trim_char(char) { return false; } + + template + constexpr static bool is_trim_char(char c, char trim_char, + OtherTrimChars... other_trim_chars) { + return c == trim_char || is_trim_char(c, other_trim_chars...); + } + +public: + static void trim(char *&str_begin, char *&str_end) { + while (str_begin != str_end && is_trim_char(*str_begin, trim_char_list...)) + ++str_begin; + while (str_begin != str_end && + is_trim_char(*(str_end - 1), trim_char_list...)) + --str_end; + *str_end = '\0'; + } +}; + +struct no_comment { + static bool is_comment(const char *) { return false; } +}; + +template struct single_line_comment { +private: + constexpr static bool is_comment_start_char(char) { return false; } + + template + constexpr static bool + is_comment_start_char(char c, char comment_start_char, + OtherCommentStartChars... other_comment_start_chars) { + return c == comment_start_char || + is_comment_start_char(c, other_comment_start_chars...); + } + +public: + static bool is_comment(const char *line) { + return is_comment_start_char(*line, comment_start_char_list...); + } +}; + +struct empty_line_comment { + static bool is_comment(const char *line) { + if (*line == '\0') + return true; + while (*line == ' ' || *line == '\t') { + ++line; + if (*line == 0) + return true; + } + return false; + } +}; + +template +struct single_and_empty_line_comment { + static bool is_comment(const char *line) { + return single_line_comment::is_comment(line) || + empty_line_comment::is_comment(line); + } +}; + +template struct no_quote_escape { + static const char *find_next_column_end(const char *col_begin) { + while (*col_begin != sep && *col_begin != '\0') + ++col_begin; + return col_begin; + } + + static void unescape(char *&, char *&) {} +}; + +template struct double_quote_escape { + static const char *find_next_column_end(const char *col_begin) { + while (*col_begin != sep && *col_begin != '\0') + if (*col_begin != quote) + ++col_begin; + else { + do { + ++col_begin; + while (*col_begin != quote) { + if (*col_begin == '\0') + throw error::escaped_string_not_closed(); + ++col_begin; + } + ++col_begin; + } while (*col_begin == quote); + } + return col_begin; + } + + static void unescape(char *&col_begin, char *&col_end) { + if (col_end - col_begin >= 2) { + if (*col_begin == quote && *(col_end - 1) == quote) { + ++col_begin; + --col_end; + char *out = col_begin; + for (char *in = col_begin; in != col_end; ++in) { + if (*in == quote && (in + 1) != col_end && *(in + 1) == quote) { + ++in; + } + *out = *in; + ++out; } + col_end = out; + *col_end = '\0'; + } + } + } +}; + +struct throw_on_overflow { + template static void on_overflow(T &) { + throw error::integer_overflow(); + } + + template static void on_underflow(T &) { + throw error::integer_underflow(); + } +}; + +struct ignore_overflow { + template static void on_overflow(T &) {} + + template static void on_underflow(T &) {} +}; + +struct set_to_max_on_overflow { + template static void on_overflow(T &x) { + x = std::numeric_limits::max(); + } + + template static void on_underflow(T &x) { + x = std::numeric_limits::min(); + } +}; + +namespace detail { +template +void chop_next_column(char *&line, char *&col_begin, char *&col_end) { + assert(line != nullptr); + + col_begin = line; + // the col_begin + (... - col_begin) removes the constness + col_end = + col_begin + (quote_policy::find_next_column_end(col_begin) - col_begin); + + if (*col_end == '\0') { + line = nullptr; + } else { + *col_end = '\0'; + line = col_end + 1; + } +} - class ByteSourceBase{ - public: - virtual int read(char*buffer, int size)=0; - virtual ~ByteSourceBase(){} - }; - - namespace detail{ - - class OwningStdIOByteSourceBase : public ByteSourceBase{ - public: - explicit OwningStdIOByteSourceBase(FILE*file):file(file){ - // Tell the std library that we want to do the buffering ourself. - std::setvbuf(file, 0, _IONBF, 0); - } - - int read(char*buffer, int size){ - return std::fread(buffer, 1, size, file); - } - - ~OwningStdIOByteSourceBase(){ - std::fclose(file); - } - - private: - FILE*file; - }; - - class NonOwningIStreamByteSource : public ByteSourceBase{ - public: - explicit NonOwningIStreamByteSource(std::istream&in):in(in){} - - int read(char*buffer, int size){ - in.read(buffer, size); - return in.gcount(); - } - - ~NonOwningIStreamByteSource(){} - - private: - std::istream∈ - }; - - class NonOwningStringByteSource : public ByteSourceBase{ - public: - NonOwningStringByteSource(const char*str, long long size):str(str), remaining_byte_count(size){} - - int read(char*buffer, int desired_byte_count){ - int to_copy_byte_count = desired_byte_count; - if(remaining_byte_count < to_copy_byte_count) - to_copy_byte_count = remaining_byte_count; - std::memcpy(buffer, str, to_copy_byte_count); - remaining_byte_count -= to_copy_byte_count; - str += to_copy_byte_count; - return to_copy_byte_count; - } - - ~NonOwningStringByteSource(){} - - private: - const char*str; - long long remaining_byte_count; - }; - - #ifndef CSV_IO_NO_THREAD - class AsynchronousReader{ - public: - void init(std::unique_ptrarg_byte_source){ - std::unique_lockguard(lock); - byte_source = std::move(arg_byte_source); - desired_byte_count = -1; - termination_requested = false; - worker = std::thread( - [&]{ - std::unique_lockguard(lock); - try{ - for(;;){ - read_requested_condition.wait( - guard, - [&]{ - return desired_byte_count != -1 || termination_requested; - } - ); - if(termination_requested) - return; - - read_byte_count = byte_source->read(buffer, desired_byte_count); - desired_byte_count = -1; - if(read_byte_count == 0) - break; - read_finished_condition.notify_one(); - } - }catch(...){ - read_error = std::current_exception(); - } - read_finished_condition.notify_one(); - } - ); - } - - bool is_valid()const{ - return byte_source != nullptr; - } - - void start_read(char*arg_buffer, int arg_desired_byte_count){ - std::unique_lockguard(lock); - buffer = arg_buffer; - desired_byte_count = arg_desired_byte_count; - read_byte_count = -1; - read_requested_condition.notify_one(); - } - - int finish_read(){ - std::unique_lockguard(lock); - read_finished_condition.wait( - guard, - [&]{ - return read_byte_count != -1 || read_error; - } - ); - if(read_error) - std::rethrow_exception(read_error); - else - return read_byte_count; - } - - ~AsynchronousReader(){ - if(byte_source != nullptr){ - { - std::unique_lockguard(lock); - termination_requested = true; - } - read_requested_condition.notify_one(); - worker.join(); - } - } - - private: - std::unique_ptrbyte_source; - - std::thread worker; - - bool termination_requested; - std::exception_ptr read_error; - char*buffer; - int desired_byte_count; - int read_byte_count; - - std::mutex lock; - std::condition_variable read_finished_condition; - std::condition_variable read_requested_condition; - }; - #endif - - class SynchronousReader{ - public: - void init(std::unique_ptrarg_byte_source){ - byte_source = std::move(arg_byte_source); - } - - bool is_valid()const{ - return byte_source != nullptr; - } - - void start_read(char*arg_buffer, int arg_desired_byte_count){ - buffer = arg_buffer; - desired_byte_count = arg_desired_byte_count; - } - - int finish_read(){ - return byte_source->read(buffer, desired_byte_count); - } - private: - std::unique_ptrbyte_source; - char*buffer; - int desired_byte_count; - }; +template +void parse_line(char *line, char **sorted_col, + const std::vector &col_order) { + for (std::size_t i = 0; i < col_order.size(); ++i) { + if (line == nullptr) + throw ::io::error::too_few_columns(); + char *col_begin, *col_end; + chop_next_column(line, col_begin, col_end); + + if (col_order[i] != -1) { + trim_policy::trim(col_begin, col_end); + quote_policy::unescape(col_begin, col_end); + + sorted_col[col_order[i]] = col_begin; + } + } + if (line != nullptr) + throw ::io::error::too_many_columns(); +} + +template +void parse_header_line(char *line, std::vector &col_order, + const std::string *col_name, + ignore_column ignore_policy) { + col_order.clear(); + + bool found[column_count]; + std::fill(found, found + column_count, false); + while (line) { + char *col_begin, *col_end; + chop_next_column(line, col_begin, col_end); + + trim_policy::trim(col_begin, col_end); + quote_policy::unescape(col_begin, col_end); + + for (unsigned i = 0; i < column_count; ++i) + if (col_begin == col_name[i]) { + if (found[i]) { + error::duplicated_column_in_header err; + err.set_column_name(col_begin); + throw err; } + found[i] = true; + col_order.push_back(i); + col_begin = 0; + break; + } + if (col_begin) { + if (ignore_policy & ::io::ignore_extra_column) + col_order.push_back(-1); + else { + error::extra_column_in_header err; + err.set_column_name(col_begin); + throw err; + } + } + } + if (!(ignore_policy & ::io::ignore_missing_column)) { + for (unsigned i = 0; i < column_count; ++i) { + if (!found[i]) { + error::missing_column_in_header err; + err.set_column_name(col_name[i].c_str()); + throw err; + } + } + } +} + +template void parse(char *col, char &x) { + if (!*col) + throw error::invalid_single_character(); + x = *col; + ++col; + if (*col) + throw error::invalid_single_character(); +} + +template void parse(char *col, std::string &x) { + x = col; +} + +template void parse(char *col, const char *&x) { + x = col; +} - class LineReader{ - private: - static const int block_len = 1<<24; - std::unique_ptrbuffer; // must be constructed before (and thus destructed after) the reader! - #ifdef CSV_IO_NO_THREAD - detail::SynchronousReader reader; - #else - detail::AsynchronousReader reader; - #endif - int data_begin; - int data_end; - - char file_name[error::max_file_name_length+1]; - unsigned file_line; - - static std::unique_ptr open_file(const char*file_name){ - // We open the file in binary mode as it makes no difference under *nix - // and under Windows we handle \r\n newlines ourself. - FILE*file = std::fopen(file_name, "rb"); - if(file == 0){ - int x = errno; // store errno as soon as possible, doing it after constructor call can fail. - error::can_not_open_file err; - err.set_errno(x); - err.set_file_name(file_name); - throw err; - } - return std::unique_ptr(new detail::OwningStdIOByteSourceBase(file)); - } - - void init(std::unique_ptrbyte_source){ - file_line = 0; - - buffer = std::unique_ptr(new char[3*block_len]); - data_begin = 0; - data_end = byte_source->read(buffer.get(), 2*block_len); - - // Ignore UTF-8 BOM - if(data_end >= 3 && buffer[0] == '\xEF' && buffer[1] == '\xBB' && buffer[2] == '\xBF') - data_begin = 3; - - if(data_end == 2*block_len){ - reader.init(std::move(byte_source)); - reader.start_read(buffer.get() + 2*block_len, block_len); - } - } - - public: - LineReader() = delete; - LineReader(const LineReader&) = delete; - LineReader&operator=(const LineReader&) = delete; - - explicit LineReader(const char*file_name){ - set_file_name(file_name); - init(open_file(file_name)); - } - - explicit LineReader(const std::string&file_name){ - set_file_name(file_name.c_str()); - init(open_file(file_name.c_str())); - } - - LineReader(const char*file_name, std::unique_ptrbyte_source){ - set_file_name(file_name); - init(std::move(byte_source)); - } - - LineReader(const std::string&file_name, std::unique_ptrbyte_source){ - set_file_name(file_name.c_str()); - init(std::move(byte_source)); - } - - LineReader(const char*file_name, const char*data_begin, const char*data_end){ - set_file_name(file_name); - init(std::unique_ptr(new detail::NonOwningStringByteSource(data_begin, data_end-data_begin))); - } - - LineReader(const std::string&file_name, const char*data_begin, const char*data_end){ - set_file_name(file_name.c_str()); - init(std::unique_ptr(new detail::NonOwningStringByteSource(data_begin, data_end-data_begin))); - } - - LineReader(const char*file_name, FILE*file){ - set_file_name(file_name); - init(std::unique_ptr(new detail::OwningStdIOByteSourceBase(file))); - } - - LineReader(const std::string&file_name, FILE*file){ - set_file_name(file_name.c_str()); - init(std::unique_ptr(new detail::OwningStdIOByteSourceBase(file))); - } - - LineReader(const char*file_name, std::istream&in){ - set_file_name(file_name); - init(std::unique_ptr(new detail::NonOwningIStreamByteSource(in))); - } - - LineReader(const std::string&file_name, std::istream&in){ - set_file_name(file_name.c_str()); - init(std::unique_ptr(new detail::NonOwningIStreamByteSource(in))); - } - - void set_file_name(const std::string&file_name){ - set_file_name(file_name.c_str()); - } - - void set_file_name(const char*file_name){ - if(file_name != nullptr){ - strncpy(this->file_name, file_name, sizeof(this->file_name)); - this->file_name[sizeof(this->file_name)-1] = '\0'; - }else{ - this->file_name[0] = '\0'; - } - } - - const char*get_truncated_file_name()const{ - return file_name; - } - - void set_file_line(unsigned file_line){ - this->file_line = file_line; - } - - unsigned get_file_line()const{ - return file_line; - } - - char*next_line(){ - if(data_begin == data_end) - return 0; - - ++file_line; - - assert(data_begin < data_end); - assert(data_end <= block_len*2); - - if(data_begin >= block_len){ - std::memcpy(buffer.get(), buffer.get()+block_len, block_len); - data_begin -= block_len; - data_end -= block_len; - if(reader.is_valid()) - { - data_end += reader.finish_read(); - std::memcpy(buffer.get()+block_len, buffer.get()+2*block_len, block_len); - reader.start_read(buffer.get() + 2*block_len, block_len); - } - } - - int line_end = data_begin; - while(buffer[line_end] != '\n' && line_end != data_end){ - ++line_end; - } - - if(line_end - data_begin + 1 > block_len){ - error::line_length_limit_exceeded err; - err.set_file_name(file_name); - err.set_file_line(file_line); - throw err; - } - - if(buffer[line_end] == '\n' && line_end != data_end){ - buffer[line_end] = '\0'; - }else{ - // some files are missing the newline at the end of the - // last line - ++data_end; - buffer[line_end] = '\0'; - } - - // handle windows \r\n-line breaks - if(line_end != data_begin && buffer[line_end-1] == '\r') - buffer[line_end-1] = '\0'; - - char*ret = buffer.get() + data_begin; - data_begin = line_end+1; - return ret; - } - }; - - - //////////////////////////////////////////////////////////////////////////// - // CSV // - //////////////////////////////////////////////////////////////////////////// - - namespace error{ - const int max_column_name_length = 63; - struct with_column_name{ - with_column_name(){ - std::memset(column_name, 0, max_column_name_length+1); - } - - void set_column_name(const char*column_name){ - if(column_name != nullptr){ - std::strncpy(this->column_name, column_name, max_column_name_length); - this->column_name[max_column_name_length] = '\0'; - }else{ - this->column_name[0] = '\0'; - } - } - - char column_name[max_column_name_length+1]; - }; - - - const int max_column_content_length = 63; - - struct with_column_content{ - with_column_content(){ - std::memset(column_content, 0, max_column_content_length+1); - } - - void set_column_content(const char*column_content){ - if(column_content != nullptr){ - std::strncpy(this->column_content, column_content, max_column_content_length); - this->column_content[max_column_content_length] = '\0'; - }else{ - this->column_content[0] = '\0'; - } - } - - char column_content[max_column_content_length+1]; - }; - - - struct extra_column_in_header : - base, - with_file_name, - with_column_name{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Extra column \"%s\" in header of file \"%s\"." - , column_name, file_name); - } - }; - - struct missing_column_in_header : - base, - with_file_name, - with_column_name{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Missing column \"%s\" in header of file \"%s\"." - , column_name, file_name); - } - }; - - struct duplicated_column_in_header : - base, - with_file_name, - with_column_name{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Duplicated column \"%s\" in header of file \"%s\"." - , column_name, file_name); - } - }; - - struct header_missing : - base, - with_file_name{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Header missing in file \"%s\"." - , file_name); - } - }; - - struct too_few_columns : - base, - with_file_name, - with_file_line{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Too few columns in line %d in file \"%s\"." - , file_line, file_name); - } - }; - - struct too_many_columns : - base, - with_file_name, - with_file_line{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Too many columns in line %d in file \"%s\"." - , file_line, file_name); - } - }; - - struct escaped_string_not_closed : - base, - with_file_name, - with_file_line{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "Escaped string was not closed in line %d in file \"%s\"." - , file_line, file_name); - } - }; - - struct integer_must_be_positive : - base, - with_file_name, - with_file_line, - with_column_name, - with_column_content{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "The integer \"%s\" must be positive or 0 in column \"%s\" in file \"%s\" in line \"%d\"." - , column_content, column_name, file_name, file_line); - } - }; - - struct no_digit : - base, - with_file_name, - with_file_line, - with_column_name, - with_column_content{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "The integer \"%s\" contains an invalid digit in column \"%s\" in file \"%s\" in line \"%d\"." - , column_content, column_name, file_name, file_line); - } - }; - - struct integer_overflow : - base, - with_file_name, - with_file_line, - with_column_name, - with_column_content{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "The integer \"%s\" overflows in column \"%s\" in file \"%s\" in line \"%d\"." - , column_content, column_name, file_name, file_line); - } - }; - - struct integer_underflow : - base, - with_file_name, - with_file_line, - with_column_name, - with_column_content{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "The integer \"%s\" underflows in column \"%s\" in file \"%s\" in line \"%d\"." - , column_content, column_name, file_name, file_line); - } - }; - - struct invalid_single_character : - base, - with_file_name, - with_file_line, - with_column_name, - with_column_content{ - void format_error_message()const{ - std::snprintf(error_message_buffer, sizeof(error_message_buffer), - "The content \"%s\" of column \"%s\" in file \"%s\" in line \"%d\" is not a single character." - , column_content, column_name, file_name, file_line); - } - }; +template void parse(char *col, char *&x) { x = col; } + +template +void parse_unsigned_integer(const char *col, T &x) { + x = 0; + while (*col != '\0') { + if ('0' <= *col && *col <= '9') { + T y = *col - '0'; + if (x > (std::numeric_limits::max() - y) / 10) { + overflow_policy::on_overflow(x); + return; + } + x = 10 * x + y; + } else + throw error::no_digit(); + ++col; + } +} + +template void parse(char *col, unsigned char &x) { + parse_unsigned_integer(col, x); +} +template void parse(char *col, unsigned short &x) { + parse_unsigned_integer(col, x); +} +template void parse(char *col, unsigned int &x) { + parse_unsigned_integer(col, x); +} +template void parse(char *col, unsigned long &x) { + parse_unsigned_integer(col, x); +} +template void parse(char *col, unsigned long long &x) { + parse_unsigned_integer(col, x); +} + +template +void parse_signed_integer(const char *col, T &x) { + if (*col == '-') { + ++col; + + x = 0; + while (*col != '\0') { + if ('0' <= *col && *col <= '9') { + T y = *col - '0'; + if (x < (std::numeric_limits::min() + y) / 10) { + overflow_policy::on_underflow(x); + return; } + x = 10 * x - y; + } else + throw error::no_digit(); + ++col; + } + return; + } else if (*col == '+') + ++col; + parse_unsigned_integer(col, x); +} - typedef unsigned ignore_column; - static const ignore_column ignore_no_column = 0; - static const ignore_column ignore_extra_column = 1; - static const ignore_column ignore_missing_column = 2; - - template - struct trim_chars{ - private: - constexpr static bool is_trim_char(char){ - return false; - } - - template - constexpr static bool is_trim_char(char c, char trim_char, OtherTrimChars...other_trim_chars){ - return c == trim_char || is_trim_char(c, other_trim_chars...); - } - - public: - static void trim(char*&str_begin, char*&str_end){ - while(str_begin != str_end && is_trim_char(*str_begin, trim_char_list...)) - ++str_begin; - while(str_begin != str_end && is_trim_char(*(str_end-1), trim_char_list...)) - --str_end; - *str_end = '\0'; - } - }; - - - struct no_comment{ - static bool is_comment(const char*){ - return false; - } - }; - - template - struct single_line_comment{ - private: - constexpr static bool is_comment_start_char(char){ - return false; - } - - template - constexpr static bool is_comment_start_char(char c, char comment_start_char, OtherCommentStartChars...other_comment_start_chars){ - return c == comment_start_char || is_comment_start_char(c, other_comment_start_chars...); - } - - public: - - static bool is_comment(const char*line){ - return is_comment_start_char(*line, comment_start_char_list...); - } - }; - - struct empty_line_comment{ - static bool is_comment(const char*line){ - if(*line == '\0') - return true; - while(*line == ' ' || *line == '\t'){ - ++line; - if(*line == 0) - return true; - } - return false; - } - }; - - template - struct single_and_empty_line_comment{ - static bool is_comment(const char*line){ - return single_line_comment::is_comment(line) || empty_line_comment::is_comment(line); - } - }; - - template - struct no_quote_escape{ - static const char*find_next_column_end(const char*col_begin){ - while(*col_begin != sep && *col_begin != '\0') - ++col_begin; - return col_begin; - } - - static void unescape(char*&, char*&){ - - } - }; - - template - struct double_quote_escape{ - static const char*find_next_column_end(const char*col_begin){ - while(*col_begin != sep && *col_begin != '\0') - if(*col_begin != quote) - ++col_begin; - else{ - do{ - ++col_begin; - while(*col_begin != quote){ - if(*col_begin == '\0') - throw error::escaped_string_not_closed(); - ++col_begin; - } - ++col_begin; - }while(*col_begin == quote); - } - return col_begin; - } - - static void unescape(char*&col_begin, char*&col_end){ - if(col_end - col_begin >= 2){ - if(*col_begin == quote && *(col_end-1) == quote){ - ++col_begin; - --col_end; - char*out = col_begin; - for(char*in = col_begin; in!=col_end; ++in){ - if(*in == quote && (in+1) != col_end && *(in+1) == quote){ - ++in; - } - *out = *in; - ++out; - } - col_end = out; - *col_end = '\0'; - } - } - - } - }; - - struct throw_on_overflow{ - template - static void on_overflow(T&){ - throw error::integer_overflow(); - } - - template - static void on_underflow(T&){ - throw error::integer_underflow(); - } - }; - - struct ignore_overflow{ - template - static void on_overflow(T&){} - - template - static void on_underflow(T&){} - }; - - struct set_to_max_on_overflow{ - template - static void on_overflow(T&x){ - x = std::numeric_limits::max(); - } - - template - static void on_underflow(T&x){ - x = std::numeric_limits::min(); - } - }; - - - namespace detail{ - template - void chop_next_column( - char*&line, char*&col_begin, char*&col_end - ){ - assert(line != nullptr); - - col_begin = line; - // the col_begin + (... - col_begin) removes the constness - col_end = col_begin + (quote_policy::find_next_column_end(col_begin) - col_begin); - - if(*col_end == '\0'){ - line = nullptr; - }else{ - *col_end = '\0'; - line = col_end + 1; - } - } - - template - void parse_line( - char*line, - char**sorted_col, - const std::vector&col_order - ){ - for(std::size_t i=0; i(line, col_begin, col_end); - - if(col_order[i] != -1){ - trim_policy::trim(col_begin, col_end); - quote_policy::unescape(col_begin, col_end); - - sorted_col[col_order[i]] = col_begin; - } - } - if(line != nullptr) - throw ::io::error::too_many_columns(); - } - - template - void parse_header_line( - char*line, - std::vector&col_order, - const std::string*col_name, - ignore_column ignore_policy - ){ - col_order.clear(); - - bool found[column_count]; - std::fill(found, found + column_count, false); - while(line){ - char*col_begin,*col_end; - chop_next_column(line, col_begin, col_end); - - trim_policy::trim(col_begin, col_end); - quote_policy::unescape(col_begin, col_end); - - for(unsigned i=0; i - void parse(char*col, char &x){ - if(!*col) - throw error::invalid_single_character(); - x = *col; - ++col; - if(*col) - throw error::invalid_single_character(); - } - - template - void parse(char*col, std::string&x){ - x = col; - } - - template - void parse(char*col, const char*&x){ - x = col; - } - - template - void parse(char*col, char*&x){ - x = col; - } - - template - void parse_unsigned_integer(const char*col, T&x){ - x = 0; - while(*col != '\0'){ - if('0' <= *col && *col <= '9'){ - T y = *col - '0'; - if(x > (std::numeric_limits::max()-y)/10){ - overflow_policy::on_overflow(x); - return; - } - x = 10*x+y; - }else - throw error::no_digit(); - ++col; - } - } - - templatevoid parse(char*col, unsigned char &x) - {parse_unsigned_integer(col, x);} - templatevoid parse(char*col, unsigned short &x) - {parse_unsigned_integer(col, x);} - templatevoid parse(char*col, unsigned int &x) - {parse_unsigned_integer(col, x);} - templatevoid parse(char*col, unsigned long &x) - {parse_unsigned_integer(col, x);} - templatevoid parse(char*col, unsigned long long &x) - {parse_unsigned_integer(col, x);} - - template - void parse_signed_integer(const char*col, T&x){ - if(*col == '-'){ - ++col; - - x = 0; - while(*col != '\0'){ - if('0' <= *col && *col <= '9'){ - T y = *col - '0'; - if(x < (std::numeric_limits::min()+y)/10){ - overflow_policy::on_underflow(x); - return; - } - x = 10*x-y; - }else - throw error::no_digit(); - ++col; - } - return; - }else if(*col == '+') - ++col; - parse_unsigned_integer(col, x); - } - - templatevoid parse(char*col, signed char &x) - {parse_signed_integer(col, x);} - templatevoid parse(char*col, signed short &x) - {parse_signed_integer(col, x);} - templatevoid parse(char*col, signed int &x) - {parse_signed_integer(col, x);} - templatevoid parse(char*col, signed long &x) - {parse_signed_integer(col, x);} - templatevoid parse(char*col, signed long long &x) - {parse_signed_integer(col, x);} - - template - void parse_float(const char*col, T&x){ - bool is_neg = false; - if(*col == '-'){ - is_neg = true; - ++col; - }else if(*col == '+') - ++col; - - x = 0; - while('0' <= *col && *col <= '9'){ - int y = *col - '0'; - x *= 10; - x += y; - ++col; - } - - if(*col == '.'|| *col == ','){ - ++col; - T pos = 1; - while('0' <= *col && *col <= '9'){ - pos /= 10; - int y = *col - '0'; - ++col; - x += y*pos; - } - } - - if(*col == 'e' || *col == 'E'){ - ++col; - int e; - - parse_signed_integer(col, e); - - if(e != 0){ - T base; - if(e < 0){ - base = 0.1; - e = -e; - }else{ - base = 10; - } - - while(e != 1){ - if((e & 1) == 0){ - base = base*base; - e >>= 1; - }else{ - x *= base; - --e; - } - } - x *= base; - } - }else{ - if(*col != '\0') - throw error::no_digit(); - } - - if(is_neg) - x = -x; - } - - template void parse(char*col, float&x) { parse_float(col, x); } - template void parse(char*col, double&x) { parse_float(col, x); } - template void parse(char*col, long double&x) { parse_float(col, x); } - - template - void parse(char*col, T&x){ - // Mute unused variable compiler warning - (void)col; - (void)x; - // GCC evalutes "false" when reading the template and - // "sizeof(T)!=sizeof(T)" only when instantiating it. This is why - // this strange construct is used. - static_assert(sizeof(T)!=sizeof(T), - "Can not parse this type. Only buildin integrals, floats, char, char*, const char* and std::string are supported"); - } +template void parse(char *col, signed char &x) { + parse_signed_integer(col, x); +} +template void parse(char *col, signed short &x) { + parse_signed_integer(col, x); +} +template void parse(char *col, signed int &x) { + parse_signed_integer(col, x); +} +template void parse(char *col, signed long &x) { + parse_signed_integer(col, x); +} +template void parse(char *col, signed long long &x) { + parse_signed_integer(col, x); +} +template void parse_float(const char *col, T &x) { + bool is_neg = false; + if (*col == '-') { + is_neg = true; + ++col; + } else if (*col == '+') + ++col; + + x = 0; + while ('0' <= *col && *col <= '9') { + int y = *col - '0'; + x *= 10; + x += y; + ++col; + } + + if (*col == '.' || *col == ',') { + ++col; + T pos = 1; + while ('0' <= *col && *col <= '9') { + pos /= 10; + int y = *col - '0'; + ++col; + x += y * pos; + } + } + + if (*col == 'e' || *col == 'E') { + ++col; + int e; + + parse_signed_integer(col, e); + + if (e != 0) { + T base; + if (e < 0) { + base = 0.1; + e = -e; + } else { + base = 10; + } + + while (e != 1) { + if ((e & 1) == 0) { + base = base * base; + e >>= 1; + } else { + x *= base; + --e; } + } + x *= base; + } + } else { + if (*col != '\0') + throw error::no_digit(); + } + + if (is_neg) + x = -x; +} - template, - class quote_policy = no_quote_escape<','>, - class overflow_policy = throw_on_overflow, - class comment_policy = no_comment - > - class CSVReader{ - private: - LineReader in; - - char*row[column_count]; - std::string column_names[column_count]; - - std::vectorcol_order; - - template - void set_column_names(std::string s, ColNames...cols){ - column_names[column_count-sizeof...(ColNames)-1] = std::move(s); - set_column_names(std::forward(cols)...); - } - - void set_column_names(){} - - - public: - CSVReader() = delete; - CSVReader(const CSVReader&) = delete; - CSVReader&operator=(const CSVReader&); - - template - explicit CSVReader(Args&&...args):in(std::forward(args)...){ - std::fill(row, row+column_count, nullptr); - col_order.resize(column_count); - for(unsigned i=0; i - void read_header(ignore_column ignore_policy, ColNames...cols){ - static_assert(sizeof...(ColNames)>=column_count, "not enough column names specified"); - static_assert(sizeof...(ColNames)<=column_count, "too many column names specified"); - try{ - set_column_names(std::forward(cols)...); - - char*line; - do{ - line = in.next_line(); - if(!line) - throw error::header_missing(); - }while(comment_policy::is_comment(line)); - - detail::parse_header_line - - (line, col_order, column_names, ignore_policy); - }catch(error::with_file_name&err){ - err.set_file_name(in.get_truncated_file_name()); - throw; - } - } - - template - void set_header(ColNames...cols){ - static_assert(sizeof...(ColNames)>=column_count, - "not enough column names specified"); - static_assert(sizeof...(ColNames)<=column_count, - "too many column names specified"); - set_column_names(std::forward(cols)...); - std::fill(row, row+column_count, nullptr); - col_order.resize(column_count); - for(unsigned i=0; i - void parse_helper(std::size_t r, T&t, ColType&...cols){ - if(row[r]){ - try{ - try{ - ::io::detail::parse(row[r], t); - }catch(error::with_column_content&err){ - err.set_column_content(row[r]); - throw; - } - }catch(error::with_column_name&err){ - err.set_column_name(column_names[r].c_str()); - throw; - } - } - parse_helper(r+1, cols...); - } - - - public: - template - bool read_row(ColType& ...cols){ - static_assert(sizeof...(ColType)>=column_count, - "not enough columns specified"); - static_assert(sizeof...(ColType)<=column_count, - "too many columns specified"); - try{ - try{ - - char*line; - do{ - line = in.next_line(); - if(!line) - return false; - }while(comment_policy::is_comment(line)); - - detail::parse_line - (line, row, col_order); - - parse_helper(0, cols...); - }catch(error::with_file_name&err){ - err.set_file_name(in.get_truncated_file_name()); - throw; - } - }catch(error::with_file_line&err){ - err.set_file_line(in.get_file_line()); - throw; - } - - return true; - } - }; +template void parse(char *col, float &x) { + parse_float(col, x); +} +template void parse(char *col, double &x) { + parse_float(col, x); +} +template void parse(char *col, long double &x) { + parse_float(col, x); +} + +template void parse(char *col, T &x) { + // Mute unused variable compiler warning + (void)col; + (void)x; + // GCC evalutes "false" when reading the template and + // "sizeof(T)!=sizeof(T)" only when instantiating it. This is why + // this strange construct is used. + static_assert(sizeof(T) != sizeof(T), + "Can not parse this type. Only buildin integrals, floats, " + "char, char*, const char* and std::string are supported"); } -#endif +} // namespace detail + +template , + class quote_policy = no_quote_escape<','>, + class overflow_policy = throw_on_overflow, + class comment_policy = no_comment> +class CSVReader { +private: + LineReader in; + + char *row[column_count]; + std::string column_names[column_count]; + + std::vector col_order; + + template + void set_column_names(std::string s, ColNames... cols) { + column_names[column_count - sizeof...(ColNames) - 1] = std::move(s); + set_column_names(std::forward(cols)...); + } + + void set_column_names() {} + +public: + CSVReader() = delete; + CSVReader(const CSVReader &) = delete; + CSVReader &operator=(const CSVReader &); + + template + explicit CSVReader(Args &&... args) : in(std::forward(args)...) { + std::fill(row, row + column_count, nullptr); + col_order.resize(column_count); + for (unsigned i = 0; i < column_count; ++i) + col_order[i] = i; + for (unsigned i = 1; i <= column_count; ++i) + column_names[i - 1] = "col" + std::to_string(i); + } + + char *next_line() { return in.next_line(); } + + template + void read_header(ignore_column ignore_policy, ColNames... cols) { + static_assert(sizeof...(ColNames) >= column_count, + "not enough column names specified"); + static_assert(sizeof...(ColNames) <= column_count, + "too many column names specified"); + try { + set_column_names(std::forward(cols)...); + + char *line; + do { + line = in.next_line(); + if (!line) + throw error::header_missing(); + } while (comment_policy::is_comment(line)); + + detail::parse_header_line( + line, col_order, column_names, ignore_policy); + } catch (error::with_file_name &err) { + err.set_file_name(in.get_truncated_file_name()); + throw; + } + } + + template void set_header(ColNames... cols) { + static_assert(sizeof...(ColNames) >= column_count, + "not enough column names specified"); + static_assert(sizeof...(ColNames) <= column_count, + "too many column names specified"); + set_column_names(std::forward(cols)...); + std::fill(row, row + column_count, nullptr); + col_order.resize(column_count); + for (unsigned i = 0; i < column_count; ++i) + col_order[i] = i; + } + + bool has_column(const std::string &name) const { + return col_order.end() != + std::find(col_order.begin(), col_order.end(), + std::find(std::begin(column_names), std::end(column_names), + name) - + std::begin(column_names)); + } + + void set_file_name(const std::string &file_name) { + in.set_file_name(file_name); + } + + void set_file_name(const char *file_name) { in.set_file_name(file_name); } + + const char *get_truncated_file_name() const { + return in.get_truncated_file_name(); + } + + void set_file_line(unsigned file_line) { in.set_file_line(file_line); } + + unsigned get_file_line() const { return in.get_file_line(); } + +private: + void parse_helper(std::size_t) {} + + template + void parse_helper(std::size_t r, T &t, ColType &... cols) { + if (row[r]) { + try { + try { + ::io::detail::parse(row[r], t); + } catch (error::with_column_content &err) { + err.set_column_content(row[r]); + throw; + } + } catch (error::with_column_name &err) { + err.set_column_name(column_names[r].c_str()); + throw; + } + } + parse_helper(r + 1, cols...); + } + +public: + template bool read_row(ColType &... cols) { + static_assert(sizeof...(ColType) >= column_count, + "not enough columns specified"); + static_assert(sizeof...(ColType) <= column_count, + "too many columns specified"); + try { + try { + + char *line; + do { + line = in.next_line(); + if (!line) + return false; + } while (comment_policy::is_comment(line)); + + detail::parse_line(line, row, col_order); + + parse_helper(0, cols...); + } catch (error::with_file_name &err) { + err.set_file_name(in.get_truncated_file_name()); + throw; + } + } catch (error::with_file_line &err) { + err.set_file_line(in.get_file_line()); + throw; + } + + return true; + } +}; +} // namespace io +#endif diff --git a/external/spdlog/async_logger.h b/external/spdlog/async_logger.h index 1c42fd9..e5fae23 100644 --- a/external/spdlog/async_logger.h +++ b/external/spdlog/async_logger.h @@ -5,73 +5,75 @@ #pragma once -// Very fast asynchronous logger (millions of logs per second on an average desktop) -// Uses pre allocated lockfree queue for maximum throughput even under large number of threads. -// Creates a single back thread to pop messages from the queue and log them. +// Very fast asynchronous logger (millions of logs per second on an average +// desktop) Uses pre allocated lockfree queue for maximum throughput even under +// large number of threads. Creates a single back thread to pop messages from +// the queue and log them. // // Upon each log write the logger: // 1. Checks if its log level is enough to log the message -// 2. Push a new copy of the message to a queue (or block the caller until space is available in the queue) +// 2. Push a new copy of the message to a queue (or block the caller until +// space is available in the queue) // 3. will throw spdlog_ex upon log exceptions -// Upon destruction, logs all remaining messages in the queue before destructing.. +// Upon destruction, logs all remaining messages in the queue before +// destructing.. #include #include #include #include -#include #include +#include -namespace spdlog -{ +namespace spdlog { -namespace details -{ +namespace details { class async_log_helper; } -class async_logger :public logger -{ +class async_logger : public logger { public: - template - async_logger(const std::string& name, - const It& begin, - const It& end, - size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr, - const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function& worker_teardown_cb = nullptr); + template + async_logger(const std::string &name, const It &begin, const It &end, + size_t queue_size, + const async_overflow_policy overflow_policy = + async_overflow_policy::block_retry, + const std::function &worker_warmup_cb = nullptr, + const std::chrono::milliseconds &flush_interval_ms = + std::chrono::milliseconds::zero(), + const std::function &worker_teardown_cb = nullptr); + + async_logger(const std::string &logger_name, sinks_init_list sinks, + size_t queue_size, + const async_overflow_policy overflow_policy = + async_overflow_policy::block_retry, + const std::function &worker_warmup_cb = nullptr, + const std::chrono::milliseconds &flush_interval_ms = + std::chrono::milliseconds::zero(), + const std::function &worker_teardown_cb = nullptr); - async_logger(const std::string& logger_name, - sinks_init_list sinks, - size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr, - const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function& worker_teardown_cb = nullptr); + async_logger(const std::string &logger_name, sink_ptr single_sink, + size_t queue_size, + const async_overflow_policy overflow_policy = + async_overflow_policy::block_retry, + const std::function &worker_warmup_cb = nullptr, + const std::chrono::milliseconds &flush_interval_ms = + std::chrono::milliseconds::zero(), + const std::function &worker_teardown_cb = nullptr); - async_logger(const std::string& logger_name, - sink_ptr single_sink, - size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr, - const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function& worker_teardown_cb = nullptr); + // Wait for the queue to be empty, and flush synchronously + // Warning: this can potentialy last forever as we wait it to complete + void flush() override; - //Wait for the queue to be empty, and flush synchronously - //Warning: this can potentialy last forever as we wait it to complete - void flush() override; protected: - void _sink_it(details::log_msg& msg) override; - void _set_formatter(spdlog::formatter_ptr msg_formatter) override; - void _set_pattern(const std::string& pattern) override; + void _sink_it(details::log_msg &msg) override; + void _set_formatter(spdlog::formatter_ptr msg_formatter) override; + void _set_pattern(const std::string &pattern) override; private: - std::unique_ptr _async_log_helper; + std::unique_ptr _async_log_helper; }; -} - +} // namespace spdlog #include diff --git a/external/spdlog/common.h b/external/spdlog/common.h index a0a227e..dc0b7be 100644 --- a/external/spdlog/common.h +++ b/external/spdlog/common.h @@ -5,13 +5,13 @@ #pragma once -#include -#include -#include -#include #include +#include #include -#include +#include +#include +#include +#include #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) #include @@ -20,7 +20,7 @@ #include -//visual studio upto 2013 does not support noexcept nor constexpr +// visual studio upto 2013 does not support noexcept nor constexpr #if defined(_MSC_VER) && (_MSC_VER < 1900) #define SPDLOG_NOEXCEPT throw() #define SPDLOG_CONSTEXPR @@ -29,7 +29,7 @@ #define SPDLOG_CONSTEXPR constexpr #endif -#if defined(__GNUC__) || defined(__clang__) +#if defined(__GNUC__) || defined(__clang__) #define SPDLOG_DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) #define SPDLOG_DEPRECATED __declspec(deprecated) @@ -37,22 +37,19 @@ #define SPDLOG_DEPRECATED #endif - #include -namespace spdlog -{ +namespace spdlog { class formatter; -namespace sinks -{ +namespace sinks { class sink; } using log_clock = std::chrono::system_clock; -using sink_ptr = std::shared_ptr < sinks::sink >; -using sinks_init_list = std::initializer_list < sink_ptr >; +using sink_ptr = std::shared_ptr; +using sinks_init_list = std::initializer_list; using formatter_ptr = std::shared_ptr; #if defined(SPDLOG_NO_ATOMIC_LEVELS) using level_t = details::null_atomic_int; @@ -62,72 +59,58 @@ using level_t = std::atomic; using log_err_handler = std::function; -//Log level enum -namespace level -{ -typedef enum -{ - trace = 0, - debug = 1, - info = 2, - warn = 3, - err = 4, - critical = 5, - off = 6 +// Log level enum +namespace level { +typedef enum { + trace = 0, + debug = 1, + info = 2, + warn = 3, + err = 4, + critical = 5, + off = 6 } level_enum; -static const char* level_names[] { "trace", "debug", "info", "warning", "error", "critical", "off" }; +static const char *level_names[]{"trace", "debug", "info", "warning", + "error", "critical", "off"}; -static const char* short_level_names[] { "T", "D", "I", "W", "E", "C", "O" }; +static const char *short_level_names[]{"T", "D", "I", "W", "E", "C", "O"}; -inline const char* to_str(spdlog::level::level_enum l) -{ - return level_names[l]; +inline const char *to_str(spdlog::level::level_enum l) { + return level_names[l]; } -inline const char* to_short_str(spdlog::level::level_enum l) -{ - return short_level_names[l]; +inline const char *to_short_str(spdlog::level::level_enum l) { + return short_level_names[l]; } -} //level - +} // namespace level // // Async overflow policy - block by default. // -enum class async_overflow_policy -{ - block_retry, // Block / yield / sleep until message can be enqueued - discard_log_msg // Discard the message it enqueue fails +enum class async_overflow_policy { + block_retry, // Block / yield / sleep until message can be enqueued + discard_log_msg // Discard the message it enqueue fails }; - // // Log exception // -namespace details -{ -namespace os -{ +namespace details { +namespace os { std::string errno_str(int err_num); } -} -class spdlog_ex: public std::exception -{ +} // namespace details +class spdlog_ex : public std::exception { public: - spdlog_ex(const std::string& msg):_msg(msg) - {} - spdlog_ex(const std::string& msg, int last_errno) - { - _msg = msg + ": " + details::os::errno_str(last_errno); - } - const char* what() const SPDLOG_NOEXCEPT override - { - return _msg.c_str(); - } -private: - std::string _msg; + spdlog_ex(const std::string &msg) : _msg(msg) {} + spdlog_ex(const std::string &msg, int last_errno) { + _msg = msg + ": " + details::os::errno_str(last_errno); + } + const char *what() const SPDLOG_NOEXCEPT override { return _msg.c_str(); } +private: + std::string _msg; }; // @@ -139,5 +122,4 @@ using filename_t = std::wstring; using filename_t = std::string; #endif - -} //spdlog +} // namespace spdlog diff --git a/external/spdlog/details/async_log_helper.h b/external/spdlog/details/async_log_helper.h index deb8dcc..0cc4c39 100644 --- a/external/spdlog/details/async_log_helper.h +++ b/external/spdlog/details/async_log_helper.h @@ -15,11 +15,11 @@ #pragma once #include -#include -#include #include +#include #include #include +#include #include #include @@ -30,349 +30,309 @@ #include #include -namespace spdlog -{ -namespace details -{ - -class async_log_helper -{ - // Async msg to move to/from the queue - // Movable only. should never be copied - enum class async_msg_type - { - log, - flush, - terminate - }; - struct async_msg - { - std::string logger_name; - level::level_enum level; - log_clock::time_point time; - size_t thread_id; - std::string txt; - async_msg_type msg_type; - - async_msg() = default; - ~async_msg() = default; - - -async_msg(async_msg&& other) SPDLOG_NOEXCEPT: - logger_name(std::move(other.logger_name)), - level(std::move(other.level)), - time(std::move(other.time)), - txt(std::move(other.txt)), - msg_type(std::move(other.msg_type)) - {} - - async_msg(async_msg_type m_type) :msg_type(m_type) - {} - - async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT - { - logger_name = std::move(other.logger_name); - level = other.level; - time = std::move(other.time); - thread_id = other.thread_id; - txt = std::move(other.txt); - msg_type = other.msg_type; - return *this; - } +namespace spdlog { +namespace details { + +class async_log_helper { + // Async msg to move to/from the queue + // Movable only. should never be copied + enum class async_msg_type { log, flush, terminate }; + struct async_msg { + std::string logger_name; + level::level_enum level; + log_clock::time_point time; + size_t thread_id; + std::string txt; + async_msg_type msg_type; + + async_msg() = default; + ~async_msg() = default; + + async_msg(async_msg &&other) SPDLOG_NOEXCEPT + : logger_name(std::move(other.logger_name)), + level(std::move(other.level)), + time(std::move(other.time)), + txt(std::move(other.txt)), + msg_type(std::move(other.msg_type)) {} + + async_msg(async_msg_type m_type) : msg_type(m_type) {} + + async_msg &operator=(async_msg &&other) SPDLOG_NOEXCEPT { + logger_name = std::move(other.logger_name); + level = other.level; + time = std::move(other.time); + thread_id = other.thread_id; + txt = std::move(other.txt); + msg_type = other.msg_type; + return *this; + } + + // never copy or assign. should only be moved.. + async_msg(const async_msg &) = delete; + async_msg &operator=(const async_msg &other) = delete; - // never copy or assign. should only be moved.. - async_msg(const async_msg&) = delete; - async_msg& operator=(const async_msg& other) = delete; - - // construct from log_msg - async_msg(const details::log_msg& m) : - level(m.level), - time(m.time), - thread_id(m.thread_id), - txt(m.raw.data(), m.raw.size()), - msg_type(async_msg_type::log) - { + // construct from log_msg + async_msg(const details::log_msg &m) + : level(m.level), time(m.time), thread_id(m.thread_id), + txt(m.raw.data(), m.raw.size()), msg_type(async_msg_type::log) { #ifndef SPDLOG_NO_NAME - logger_name = *m.logger_name; + logger_name = *m.logger_name; #endif - } - + } - // copy into log_msg - void fill_log_msg(log_msg &msg) - { - msg.logger_name = &logger_name; - msg.level = level; - msg.time = time; - msg.thread_id = thread_id; - msg.raw << txt; - } - }; + // copy into log_msg + void fill_log_msg(log_msg &msg) { + msg.logger_name = &logger_name; + msg.level = level; + msg.time = time; + msg.thread_id = thread_id; + msg.raw << txt; + } + }; public: + using item_type = async_msg; + using q_type = details::mpmc_bounded_queue; - using item_type = async_msg; - using q_type = details::mpmc_bounded_queue; - - using clock = std::chrono::steady_clock; + using clock = std::chrono::steady_clock; + async_log_helper(formatter_ptr formatter, const std::vector &sinks, + size_t queue_size, const log_err_handler err_handler, + const async_overflow_policy overflow_policy = + async_overflow_policy::block_retry, + const std::function &worker_warmup_cb = nullptr, + const std::chrono::milliseconds &flush_interval_ms = + std::chrono::milliseconds::zero(), + const std::function &worker_teardown_cb = nullptr); - async_log_helper(formatter_ptr formatter, - const std::vector& sinks, - size_t queue_size, - const log_err_handler err_handler, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr, - const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function& worker_teardown_cb = nullptr); + void log(const details::log_msg &msg); - void log(const details::log_msg& msg); + // stop logging and join the back thread + ~async_log_helper(); - // stop logging and join the back thread - ~async_log_helper(); - - void set_formatter(formatter_ptr); - - void flush(bool wait_for_q); + void set_formatter(formatter_ptr); + void flush(bool wait_for_q); private: - formatter_ptr _formatter; - std::vector> _sinks; - - // queue of messages to log - q_type _q; - - log_err_handler _err_handler; + formatter_ptr _formatter; + std::vector> _sinks; - bool _flush_requested; + // queue of messages to log + q_type _q; - bool _terminate_requested; + log_err_handler _err_handler; + bool _flush_requested; - // overflow policy - const async_overflow_policy _overflow_policy; + bool _terminate_requested; - // worker thread warmup callback - one can set thread priority, affinity, etc - const std::function _worker_warmup_cb; + // overflow policy + const async_overflow_policy _overflow_policy; - // auto periodic sink flush parameter - const std::chrono::milliseconds _flush_interval_ms; + // worker thread warmup callback - one can set thread priority, affinity, etc + const std::function _worker_warmup_cb; - // worker thread teardown callback - const std::function _worker_teardown_cb; + // auto periodic sink flush parameter + const std::chrono::milliseconds _flush_interval_ms; - // worker thread - std::thread _worker_thread; + // worker thread teardown callback + const std::function _worker_teardown_cb; - void push_msg(async_msg&& new_msg); + // worker thread + std::thread _worker_thread; - // worker thread main loop - void worker_loop(); + void push_msg(async_msg &&new_msg); - // pop next message from the queue and process it. will set the last_pop to the pop time - // return false if termination of the queue is required - bool process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush); + // worker thread main loop + void worker_loop(); - void handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush); + // pop next message from the queue and process it. will set the last_pop to + // the pop time return false if termination of the queue is required + bool process_next_msg(log_clock::time_point &last_pop, + log_clock::time_point &last_flush); - // sleep,yield or return immediatly using the time passed since last message as a hint - static void sleep_or_yield(const spdlog::log_clock::time_point& now, const log_clock::time_point& last_op_time); + void handle_flush_interval(log_clock::time_point &now, + log_clock::time_point &last_flush); - // wait until the queue is empty - void wait_empty_q(); + // sleep,yield or return immediatly using the time passed since last message + // as a hint + static void sleep_or_yield(const spdlog::log_clock::time_point &now, + const log_clock::time_point &last_op_time); + // wait until the queue is empty + void wait_empty_q(); }; -} -} +} // namespace details +} // namespace spdlog /////////////////////////////////////////////////////////////////////////////// // async_sink class implementation /////////////////////////////////////////////////////////////////////////////// inline spdlog::details::async_log_helper::async_log_helper( - formatter_ptr formatter, - const std::vector& sinks, - size_t queue_size, - log_err_handler err_handler, + formatter_ptr formatter, const std::vector &sinks, + size_t queue_size, log_err_handler err_handler, const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb, - const std::chrono::milliseconds& flush_interval_ms, - const std::function& worker_teardown_cb): - _formatter(formatter), - _sinks(sinks), - _q(queue_size), - _err_handler(err_handler), - _flush_requested(false), - _terminate_requested(false), - _overflow_policy(overflow_policy), - _worker_warmup_cb(worker_warmup_cb), - _flush_interval_ms(flush_interval_ms), - _worker_teardown_cb(worker_teardown_cb), - _worker_thread(&async_log_helper::worker_loop, this) -{} + const std::function &worker_warmup_cb, + const std::chrono::milliseconds &flush_interval_ms, + const std::function &worker_teardown_cb) + : _formatter(formatter), _sinks(sinks), _q(queue_size), + _err_handler(err_handler), _flush_requested(false), + _terminate_requested(false), _overflow_policy(overflow_policy), + _worker_warmup_cb(worker_warmup_cb), + _flush_interval_ms(flush_interval_ms), + _worker_teardown_cb(worker_teardown_cb), + _worker_thread(&async_log_helper::worker_loop, this) {} // Send to the worker thread termination message(level=off) // and wait for it to finish gracefully -inline spdlog::details::async_log_helper::~async_log_helper() -{ - try - { - push_msg(async_msg(async_msg_type::terminate)); - _worker_thread.join(); - } - catch (...) // don't crash in destructor - {} +inline spdlog::details::async_log_helper::~async_log_helper() { + try { + push_msg(async_msg(async_msg_type::terminate)); + _worker_thread.join(); + } catch (...) // don't crash in destructor + { + } } - -//Try to push and block until succeeded (if the policy is not to discard when the queue is full) -inline void spdlog::details::async_log_helper::log(const details::log_msg& msg) -{ - push_msg(async_msg(msg)); +// Try to push and block until succeeded (if the policy is not to discard when +// the queue is full) +inline void +spdlog::details::async_log_helper::log(const details::log_msg &msg) { + push_msg(async_msg(msg)); } -inline void spdlog::details::async_log_helper::push_msg(details::async_log_helper::async_msg&& new_msg) -{ - if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg) - { - auto last_op_time = details::os::now(); - auto now = last_op_time; - do - { - now = details::os::now(); - sleep_or_yield(now, last_op_time); - } - while (!_q.enqueue(std::move(new_msg))); - } +inline void spdlog::details::async_log_helper::push_msg( + details::async_log_helper::async_msg &&new_msg) { + if (!_q.enqueue(std::move(new_msg)) && + _overflow_policy != async_overflow_policy::discard_log_msg) { + auto last_op_time = details::os::now(); + auto now = last_op_time; + do { + now = details::os::now(); + sleep_or_yield(now, last_op_time); + } while (!_q.enqueue(std::move(new_msg))); + } } // optionally wait for the queue be empty and request flush from the sinks -inline void spdlog::details::async_log_helper::flush(bool wait_for_q) -{ - push_msg(async_msg(async_msg_type::flush)); - if(wait_for_q) - wait_empty_q(); //return only make after the above flush message was processed +inline void spdlog::details::async_log_helper::flush(bool wait_for_q) { + push_msg(async_msg(async_msg_type::flush)); + if (wait_for_q) + wait_empty_q(); // return only make after the above flush message was + // processed } -inline void spdlog::details::async_log_helper::worker_loop() -{ - try - { - if (_worker_warmup_cb) _worker_warmup_cb(); - auto last_pop = details::os::now(); - auto last_flush = last_pop; - while(process_next_msg(last_pop, last_flush)); - if (_worker_teardown_cb) _worker_teardown_cb(); - } - catch (const std::exception &ex) - { - _err_handler(ex.what()); - } - catch (...) - { - _err_handler("Unknown exception"); - } +inline void spdlog::details::async_log_helper::worker_loop() { + try { + if (_worker_warmup_cb) + _worker_warmup_cb(); + auto last_pop = details::os::now(); + auto last_flush = last_pop; + while (process_next_msg(last_pop, last_flush)) + ; + if (_worker_teardown_cb) + _worker_teardown_cb(); + } catch (const std::exception &ex) { + _err_handler(ex.what()); + } catch (...) { + _err_handler("Unknown exception"); + } } // process next message in the queue -// return true if this thread should still be active (while no terminate msg was received) -inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush) -{ - async_msg incoming_async_msg; - - if (_q.dequeue(incoming_async_msg)) - { - last_pop = details::os::now(); - switch (incoming_async_msg.msg_type) - { - case async_msg_type::flush: - _flush_requested = true; - break; - - case async_msg_type::terminate: - _flush_requested = true; - _terminate_requested = true; - break; - - default: - log_msg incoming_log_msg; - incoming_async_msg.fill_log_msg(incoming_log_msg); - _formatter->format(incoming_log_msg); - for (auto &s : _sinks) - { - if(s->should_log( incoming_log_msg.level)) - { - s->log(incoming_log_msg); - } - } +// return true if this thread should still be active (while no terminate msg was +// received) +inline bool spdlog::details::async_log_helper::process_next_msg( + log_clock::time_point &last_pop, log_clock::time_point &last_flush) { + async_msg incoming_async_msg; + + if (_q.dequeue(incoming_async_msg)) { + last_pop = details::os::now(); + switch (incoming_async_msg.msg_type) { + case async_msg_type::flush: + _flush_requested = true; + break; + + case async_msg_type::terminate: + _flush_requested = true; + _terminate_requested = true; + break; + + default: + log_msg incoming_log_msg; + incoming_async_msg.fill_log_msg(incoming_log_msg); + _formatter->format(incoming_log_msg); + for (auto &s : _sinks) { + if (s->should_log(incoming_log_msg.level)) { + s->log(incoming_log_msg); } - return true; - } - - // Handle empty queue.. - // This is the only place where the queue can terminate or flush to avoid losing messages already in the queue - else - { - auto now = details::os::now(); - handle_flush_interval(now, last_flush); - sleep_or_yield(now, last_pop); - return !_terminate_requested; + } } + return true; + } + + // Handle empty queue.. + // This is the only place where the queue can terminate or flush to avoid + // losing messages already in the queue + else { + auto now = details::os::now(); + handle_flush_interval(now, last_flush); + sleep_or_yield(now, last_pop); + return !_terminate_requested; + } } // flush all sinks if _flush_interval_ms has expired -inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush) -{ - auto should_flush = _flush_requested || (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms); - if (should_flush) - { - for (auto &s : _sinks) - s->flush(); - now = last_flush = details::os::now(); - _flush_requested = false; - } +inline void spdlog::details::async_log_helper::handle_flush_interval( + log_clock::time_point &now, log_clock::time_point &last_flush) { + auto should_flush = + _flush_requested || + (_flush_interval_ms != std::chrono::milliseconds::zero() && + now - last_flush >= _flush_interval_ms); + if (should_flush) { + for (auto &s : _sinks) + s->flush(); + now = last_flush = details::os::now(); + _flush_requested = false; + } } -inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter) -{ - _formatter = msg_formatter; +inline void +spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter) { + _formatter = msg_formatter; } - // spin, yield or sleep. use the time passed since last message as a hint -inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time) -{ - using namespace std::this_thread; - using std::chrono::milliseconds; - using std::chrono::microseconds; +inline void spdlog::details::async_log_helper::sleep_or_yield( + const spdlog::log_clock::time_point &now, + const spdlog::log_clock::time_point &last_op_time) { + using namespace std::this_thread; + using std::chrono::microseconds; + using std::chrono::milliseconds; - auto time_since_op = now - last_op_time; + auto time_since_op = now - last_op_time; - // spin upto 50 micros - if (time_since_op <= microseconds(50)) - return; + // spin upto 50 micros + if (time_since_op <= microseconds(50)) + return; - // yield upto 150 micros - if (time_since_op <= microseconds(100)) - return std::this_thread::yield(); + // yield upto 150 micros + if (time_since_op <= microseconds(100)) + return std::this_thread::yield(); - // sleep for 20 ms upto 200 ms - if (time_since_op <= milliseconds(200)) - return sleep_for(milliseconds(20)); + // sleep for 20 ms upto 200 ms + if (time_since_op <= milliseconds(200)) + return sleep_for(milliseconds(20)); - // sleep for 200 ms - return sleep_for(milliseconds(200)); + // sleep for 200 ms + return sleep_for(milliseconds(200)); } // wait for the queue to be empty -inline void spdlog::details::async_log_helper::wait_empty_q() -{ - auto last_op = details::os::now(); - while (_q.approx_size() > 0) - { - sleep_or_yield(details::os::now(), last_op); - } +inline void spdlog::details::async_log_helper::wait_empty_q() { + auto last_op = details::os::now(); + while (_q.approx_size() > 0) { + sleep_or_yield(details::os::now(), last_op); + } } - - - diff --git a/external/spdlog/details/async_logger_impl.h b/external/spdlog/details/async_logger_impl.h index 2092f06..06b6d0a 100644 --- a/external/spdlog/details/async_logger_impl.h +++ b/external/spdlog/details/async_logger_impl.h @@ -6,84 +6,69 @@ #pragma once // Async Logger implementation -// Use an async_sink (queue per logger) to perform the logging in a worker thread +// Use an async_sink (queue per logger) to perform the logging in a worker +// thread -#include #include +#include -#include -#include #include +#include #include +#include -template -inline spdlog::async_logger::async_logger(const std::string& logger_name, - const It& begin, - const It& end, - size_t queue_size, - const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb, - const std::chrono::milliseconds& flush_interval_ms, - const std::function& worker_teardown_cb) : - logger(logger_name, begin, end), - _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)) -{ -} +template +inline spdlog::async_logger::async_logger( + const std::string &logger_name, const It &begin, const It &end, + size_t queue_size, const async_overflow_policy overflow_policy, + const std::function &worker_warmup_cb, + const std::chrono::milliseconds &flush_interval_ms, + const std::function &worker_teardown_cb) + : logger(logger_name, begin, end), + _async_log_helper(new details::async_log_helper( + _formatter, _sinks, queue_size, _err_handler, overflow_policy, + worker_warmup_cb, flush_interval_ms, worker_teardown_cb)) {} -inline spdlog::async_logger::async_logger(const std::string& logger_name, - sinks_init_list sinks_list, - size_t queue_size, - const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb, - const std::chrono::milliseconds& flush_interval_ms, - const std::function& worker_teardown_cb) : - async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} +inline spdlog::async_logger::async_logger( + const std::string &logger_name, sinks_init_list sinks_list, + size_t queue_size, const async_overflow_policy overflow_policy, + const std::function &worker_warmup_cb, + const std::chrono::milliseconds &flush_interval_ms, + const std::function &worker_teardown_cb) + : async_logger(logger_name, sinks_list.begin(), sinks_list.end(), + queue_size, overflow_policy, worker_warmup_cb, + flush_interval_ms, worker_teardown_cb) {} -inline spdlog::async_logger::async_logger(const std::string& logger_name, - sink_ptr single_sink, - size_t queue_size, - const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb, - const std::chrono::milliseconds& flush_interval_ms, - const std::function& worker_teardown_cb) : - async_logger(logger_name, -{ - single_sink -}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} +inline spdlog::async_logger::async_logger( + const std::string &logger_name, sink_ptr single_sink, size_t queue_size, + const async_overflow_policy overflow_policy, + const std::function &worker_warmup_cb, + const std::chrono::milliseconds &flush_interval_ms, + const std::function &worker_teardown_cb) + : async_logger(logger_name, {single_sink}, queue_size, overflow_policy, + worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} +inline void spdlog::async_logger::flush() { _async_log_helper->flush(true); } -inline void spdlog::async_logger::flush() -{ - _async_log_helper->flush(true); +inline void +spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) { + _formatter = msg_formatter; + _async_log_helper->set_formatter(_formatter); } -inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) -{ - _formatter = msg_formatter; - _async_log_helper->set_formatter(_formatter); +inline void spdlog::async_logger::_set_pattern(const std::string &pattern) { + _formatter = std::make_shared(pattern); + _async_log_helper->set_formatter(_formatter); } -inline void spdlog::async_logger::_set_pattern(const std::string& pattern) -{ - _formatter = std::make_shared(pattern); - _async_log_helper->set_formatter(_formatter); -} - - -inline void spdlog::async_logger::_sink_it(details::log_msg& msg) -{ - try - { - _async_log_helper->log(msg); - if (_should_flush_on(msg)) - _async_log_helper->flush(false); // do async flush - } - catch (const std::exception &ex) - { - _err_handler(ex.what()); - } - catch (...) - { - _err_handler("Unknown exception"); - } +inline void spdlog::async_logger::_sink_it(details::log_msg &msg) { + try { + _async_log_helper->log(msg); + if (_should_flush_on(msg)) + _async_log_helper->flush(false); // do async flush + } catch (const std::exception &ex) { + _err_handler(ex.what()); + } catch (...) { + _err_handler("Unknown exception"); + } } diff --git a/external/spdlog/details/file_helper.h b/external/spdlog/details/file_helper.h index 074d9b8..8d897f9 100644 --- a/external/spdlog/details/file_helper.h +++ b/external/spdlog/details/file_helper.h @@ -6,113 +6,93 @@ #pragma once // Helper class for file sink -// When failing to open a file, retry several times(5) with small delay between the tries(10 ms) -// Can be set to auto flush on every line -// Throw spdlog_ex exception on errors +// When failing to open a file, retry several times(5) with small delay between +// the tries(10 ms) Can be set to auto flush on every line Throw spdlog_ex +// exception on errors -#include #include +#include +#include #include #include #include #include -#include -namespace spdlog -{ -namespace details -{ +namespace spdlog { +namespace details { -class file_helper -{ +class file_helper { public: - const int open_tries = 5; - const int open_interval = 10; + const int open_tries = 5; + const int open_interval = 10; - explicit file_helper() : - _fd(nullptr) - {} - - file_helper(const file_helper&) = delete; - file_helper& operator=(const file_helper&) = delete; - - ~file_helper() - { - close(); - } + explicit file_helper() : _fd(nullptr) {} + file_helper(const file_helper &) = delete; + file_helper &operator=(const file_helper &) = delete; - void open(const filename_t& fname, bool truncate = false) - { + ~file_helper() { close(); } - close(); - auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); - _filename = fname; - for (int tries = 0; tries < open_tries; ++tries) - { - if (!os::fopen_s(&_fd, fname, mode)) - return; + void open(const filename_t &fname, bool truncate = false) { - std::this_thread::sleep_for(std::chrono::milliseconds(open_interval)); - } + close(); + auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); + _filename = fname; + for (int tries = 0; tries < open_tries; ++tries) { + if (!os::fopen_s(&_fd, fname, mode)) + return; - throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno); + std::this_thread::sleep_for(std::chrono::milliseconds(open_interval)); } - void reopen(bool truncate) - { - if (_filename.empty()) - throw spdlog_ex("Failed re opening file - was not opened before"); - open(_filename, truncate); + throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + + " for writing", + errno); + } - } + void reopen(bool truncate) { + if (_filename.empty()) + throw spdlog_ex("Failed re opening file - was not opened before"); + open(_filename, truncate); + } - void flush() - { - std::fflush(_fd); - } + void flush() { std::fflush(_fd); } - void close() - { - if (_fd) - { - std::fclose(_fd); - _fd = nullptr; - } + void close() { + if (_fd) { + std::fclose(_fd); + _fd = nullptr; } + } - void write(const log_msg& msg) - { + void write(const log_msg &msg) { - size_t msg_size = msg.formatted.size(); - auto data = msg.formatted.data(); - if (std::fwrite(data, 1, msg_size, _fd) != msg_size) - throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno); - } + size_t msg_size = msg.formatted.size(); + auto data = msg.formatted.data(); + if (std::fwrite(data, 1, msg_size, _fd) != msg_size) + throw spdlog_ex( + "Failed writing to file " + os::filename_to_str(_filename), errno); + } - size_t size() - { - if (!_fd) - throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename)); - return os::filesize(_fd); - } + size_t size() { + if (!_fd) + throw spdlog_ex("Cannot use size() on closed file " + + os::filename_to_str(_filename)); + return os::filesize(_fd); + } - const filename_t& filename() const - { - return _filename; - } + const filename_t &filename() const { return _filename; } - static bool file_exists(const filename_t& name) - { + static bool file_exists(const filename_t &name) { - return os::file_exists(name); - } + return os::file_exists(name); + } private: - FILE* _fd; - filename_t _filename; + FILE *_fd; + filename_t _filename; }; -} -} +} // namespace details +} // namespace spdlog diff --git a/external/spdlog/details/log_msg.h b/external/spdlog/details/log_msg.h index ecdc73d..ceee01f 100644 --- a/external/spdlog/details/log_msg.h +++ b/external/spdlog/details/log_msg.h @@ -8,39 +8,34 @@ #include #include - #include #include -namespace spdlog -{ -namespace details -{ -struct log_msg -{ - log_msg() = default; - log_msg(const std::string *loggers_name, level::level_enum lvl) : logger_name(loggers_name), level(lvl) - { +namespace spdlog { +namespace details { +struct log_msg { + log_msg() = default; + log_msg(const std::string *loggers_name, level::level_enum lvl) + : logger_name(loggers_name), level(lvl) { #ifndef SPDLOG_NO_DATETIME - time = os::now(); + time = os::now(); #endif #ifndef SPDLOG_NO_THREAD_ID - thread_id = os::thread_id(); + thread_id = os::thread_id(); #endif - } - - log_msg(const log_msg& other) = delete; - log_msg& operator=(log_msg&& other) = delete; - log_msg(log_msg&& other) = delete; - - - const std::string *logger_name; - level::level_enum level; - log_clock::time_point time; - size_t thread_id; - fmt::MemoryWriter raw; - fmt::MemoryWriter formatted; + } + + log_msg(const log_msg &other) = delete; + log_msg &operator=(log_msg &&other) = delete; + log_msg(log_msg &&other) = delete; + + const std::string *logger_name; + level::level_enum level; + log_clock::time_point time; + size_t thread_id; + fmt::MemoryWriter raw; + fmt::MemoryWriter formatted; }; -} -} +} // namespace details +} // namespace spdlog diff --git a/external/spdlog/details/logger_impl.h b/external/spdlog/details/logger_impl.h index 2b27f10..dabf448 100644 --- a/external/spdlog/details/logger_impl.h +++ b/external/spdlog/details/logger_impl.h @@ -11,288 +11,221 @@ #include #include - // create logger with given name, sinks and the default pattern formatter // all other ctors will call this one -template -inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end): - _name(logger_name), - _sinks(begin, end), - _formatter(std::make_shared("%+")) -{ - _level = level::info; - _flush_level = level::off; - _last_err_time = 0; - _err_handler = [this](const std::string &msg) - { - this->_default_err_handler(msg); - }; +template +inline spdlog::logger::logger(const std::string &logger_name, const It &begin, + const It &end) + : _name(logger_name), _sinks(begin, end), + _formatter(std::make_shared("%+")) { + _level = level::info; + _flush_level = level::off; + _last_err_time = 0; + _err_handler = [this](const std::string &msg) { + this->_default_err_handler(msg); + }; } // ctor with sinks as init list -inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list): - logger(logger_name, sinks_list.begin(), sinks_list.end()) -{} - +inline spdlog::logger::logger(const std::string &logger_name, + sinks_init_list sinks_list) + : logger(logger_name, sinks_list.begin(), sinks_list.end()) {} // ctor with single sink -inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink): - logger(logger_name, -{ - single_sink -}) -{} - +inline spdlog::logger::logger(const std::string &logger_name, + spdlog::sink_ptr single_sink) + : logger(logger_name, {single_sink}) {} inline spdlog::logger::~logger() = default; - -inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter) -{ - _set_formatter(msg_formatter); +inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter) { + _set_formatter(msg_formatter); } -inline void spdlog::logger::set_pattern(const std::string& pattern) -{ - _set_pattern(pattern); +inline void spdlog::logger::set_pattern(const std::string &pattern) { + _set_pattern(pattern); } - template -inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args) -{ - if (!should_log(lvl)) return; - - try - { - details::log_msg log_msg(&_name, lvl); - log_msg.raw.write(fmt, args...); - _sink_it(log_msg); - } - catch (const std::exception &ex) - { - _err_handler(ex.what()); - } - catch (...) - { - _err_handler("Unknown exception"); - } +inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, + const Args &... args) { + if (!should_log(lvl)) + return; + + try { + details::log_msg log_msg(&_name, lvl); + log_msg.raw.write(fmt, args...); + _sink_it(log_msg); + } catch (const std::exception &ex) { + _err_handler(ex.what()); + } catch (...) { + _err_handler("Unknown exception"); + } } template -inline void spdlog::logger::log(level::level_enum lvl, const char* msg) -{ - if (!should_log(lvl)) return; - try - { - details::log_msg log_msg(&_name, lvl); - log_msg.raw << msg; - _sink_it(log_msg); - } - catch (const std::exception &ex) - { - _err_handler(ex.what()); - } - catch (...) - { - _err_handler("Unknown exception"); - } - +inline void spdlog::logger::log(level::level_enum lvl, const char *msg) { + if (!should_log(lvl)) + return; + try { + details::log_msg log_msg(&_name, lvl); + log_msg.raw << msg; + _sink_it(log_msg); + } catch (const std::exception &ex) { + _err_handler(ex.what()); + } catch (...) { + _err_handler("Unknown exception"); + } +} + +template +inline void spdlog::logger::log(level::level_enum lvl, const T &msg) { + if (!should_log(lvl)) + return; + try { + details::log_msg log_msg(&_name, lvl); + log_msg.raw << msg; + _sink_it(log_msg); + } catch (const std::exception &ex) { + _err_handler(ex.what()); + } catch (...) { + _err_handler("Unknown exception"); + } } -template -inline void spdlog::logger::log(level::level_enum lvl, const T& msg) -{ - if (!should_log(lvl)) return; - try - { - details::log_msg log_msg(&_name, lvl); - log_msg.raw << msg; - _sink_it(log_msg); - } - catch (const std::exception &ex) - { - _err_handler(ex.what()); - } - catch (...) - { - _err_handler("Unknown exception"); - } -} - - template -inline void spdlog::logger::trace(const char* fmt, const Args&... args) -{ - log(level::trace, fmt, args...); +inline void spdlog::logger::trace(const char *fmt, const Args &... args) { + log(level::trace, fmt, args...); } template -inline void spdlog::logger::debug(const char* fmt, const Args&... args) -{ - log(level::debug, fmt, args...); +inline void spdlog::logger::debug(const char *fmt, const Args &... args) { + log(level::debug, fmt, args...); } template -inline void spdlog::logger::info(const char* fmt, const Args&... args) -{ - log(level::info, fmt, args...); +inline void spdlog::logger::info(const char *fmt, const Args &... args) { + log(level::info, fmt, args...); } - template -inline void spdlog::logger::warn(const char* fmt, const Args&... args) -{ - log(level::warn, fmt, args...); +inline void spdlog::logger::warn(const char *fmt, const Args &... args) { + log(level::warn, fmt, args...); } template -inline void spdlog::logger::error(const char* fmt, const Args&... args) -{ - log(level::err, fmt, args...); +inline void spdlog::logger::error(const char *fmt, const Args &... args) { + log(level::err, fmt, args...); } template -inline void spdlog::logger::critical(const char* fmt, const Args&... args) -{ - log(level::critical, fmt, args...); +inline void spdlog::logger::critical(const char *fmt, const Args &... args) { + log(level::critical, fmt, args...); } - -template -inline void spdlog::logger::trace(const T& msg) -{ - log(level::trace, msg); +template inline void spdlog::logger::trace(const T &msg) { + log(level::trace, msg); } -template -inline void spdlog::logger::debug(const T& msg) -{ - log(level::debug, msg); +template inline void spdlog::logger::debug(const T &msg) { + log(level::debug, msg); } - -template -inline void spdlog::logger::info(const T& msg) -{ - log(level::info, msg); +template inline void spdlog::logger::info(const T &msg) { + log(level::info, msg); } - -template -inline void spdlog::logger::warn(const T& msg) -{ - log(level::warn, msg); +template inline void spdlog::logger::warn(const T &msg) { + log(level::warn, msg); } -template -inline void spdlog::logger::error(const T& msg) -{ - log(level::err, msg); +template inline void spdlog::logger::error(const T &msg) { + log(level::err, msg); } -template -inline void spdlog::logger::critical(const T& msg) -{ - log(level::critical, msg); +template inline void spdlog::logger::critical(const T &msg) { + log(level::critical, msg); } - - - // // name and level // -inline const std::string& spdlog::logger::name() const -{ - return _name; -} +inline const std::string &spdlog::logger::name() const { return _name; } -inline void spdlog::logger::set_level(spdlog::level::level_enum log_level) -{ - _level.store(log_level); +inline void spdlog::logger::set_level(spdlog::level::level_enum log_level) { + _level.store(log_level); } -inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler) -{ - _err_handler = err_handler; +inline void +spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler) { + _err_handler = err_handler; } -inline spdlog::log_err_handler spdlog::logger::error_handler() -{ - return _err_handler; +inline spdlog::log_err_handler spdlog::logger::error_handler() { + return _err_handler; } - -inline void spdlog::logger::flush_on(level::level_enum log_level) -{ - _flush_level.store(log_level); +inline void spdlog::logger::flush_on(level::level_enum log_level) { + _flush_level.store(log_level); } -inline spdlog::level::level_enum spdlog::logger::level() const -{ - return static_cast(_level.load(std::memory_order_relaxed)); +inline spdlog::level::level_enum spdlog::logger::level() const { + return static_cast( + _level.load(std::memory_order_relaxed)); } -inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const -{ - return msg_level >= _level.load(std::memory_order_relaxed); +inline bool +spdlog::logger::should_log(spdlog::level::level_enum msg_level) const { + return msg_level >= _level.load(std::memory_order_relaxed); } // -// protected virtual called at end of each user log call (if enabled) by the line_logger +// protected virtual called at end of each user log call (if enabled) by the +// line_logger // -inline void spdlog::logger::_sink_it(details::log_msg& msg) -{ - _formatter->format(msg); - for (auto &sink : _sinks) - { - if( sink->should_log( msg.level)) - { - sink->log(msg); - } +inline void spdlog::logger::_sink_it(details::log_msg &msg) { + _formatter->format(msg); + for (auto &sink : _sinks) { + if (sink->should_log(msg.level)) { + sink->log(msg); } + } - if(_should_flush_on(msg)) - flush(); + if (_should_flush_on(msg)) + flush(); } -inline void spdlog::logger::_set_pattern(const std::string& pattern) -{ - _formatter = std::make_shared(pattern); +inline void spdlog::logger::_set_pattern(const std::string &pattern) { + _formatter = std::make_shared(pattern); } -inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) -{ - _formatter = msg_formatter; +inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) { + _formatter = msg_formatter; } -inline void spdlog::logger::flush() -{ - for (auto& sink : _sinks) - sink->flush(); +inline void spdlog::logger::flush() { + for (auto &sink : _sinks) + sink->flush(); } -inline void spdlog::logger::_default_err_handler(const std::string &msg) -{ - auto now = time(nullptr); - if (now - _last_err_time < 60) - return; - auto tm_time = details::os::localtime(now); - char date_buf[100]; - std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); - details::log_msg err_msg; - err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol); - sinks::stderr_sink_mt::instance()->log(err_msg); - _last_err_time = now; +inline void spdlog::logger::_default_err_handler(const std::string &msg) { + auto now = time(nullptr); + if (now - _last_err_time < 60) + return; + auto tm_time = details::os::localtime(now); + char date_buf[100]; + std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); + details::log_msg err_msg; + err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, + date_buf, details::os::eol); + sinks::stderr_sink_mt::instance()->log(err_msg); + _last_err_time = now; } -inline bool spdlog::logger::_should_flush_on(const details::log_msg &msg) -{ - const auto flush_level = _flush_level.load(std::memory_order_relaxed); - return (msg.level >= flush_level) && (msg.level != level::off); +inline bool spdlog::logger::_should_flush_on(const details::log_msg &msg) { + const auto flush_level = _flush_level.load(std::memory_order_relaxed); + return (msg.level >= flush_level) && (msg.level != level::off); } -inline const std::vector& spdlog::logger::sinks() const -{ - return _sinks; +inline const std::vector &spdlog::logger::sinks() const { + return _sinks; } diff --git a/external/spdlog/details/mpmc_bounded_q.h b/external/spdlog/details/mpmc_bounded_q.h index 3a46e8e..b271543 100644 --- a/external/spdlog/details/mpmc_bounded_q.h +++ b/external/spdlog/details/mpmc_bounded_q.h @@ -11,12 +11,12 @@ Simplified BSD license Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this list of -conditions and the following disclaimer. +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list -of conditions and the following disclaimer in the documentation and/or other materials -provided with the distribution. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -29,8 +29,9 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -The views and conclusions contained in the software and documentation are those of the authors and -should not be interpreted as representing official policies, either expressed or implied, of Dmitry Vyukov. +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of Dmitry Vyukov. */ /* @@ -48,125 +49,102 @@ Distributed under the MIT License (http://opensource.org/licenses/MIT) #include #include -namespace spdlog -{ -namespace details -{ +namespace spdlog { +namespace details { -template -class mpmc_bounded_queue -{ +template class mpmc_bounded_queue { public: - - using item_type = T; - mpmc_bounded_queue(size_t buffer_size) - :max_size_(buffer_size), - buffer_(new cell_t [buffer_size]), - buffer_mask_(buffer_size - 1) - { - //queue size must be power of two - if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0))) - throw spdlog_ex("async logger queue size must be power of two"); - - for (size_t i = 0; i != buffer_size; i += 1) - buffer_[i].sequence_.store(i, std::memory_order_relaxed); - enqueue_pos_.store(0, std::memory_order_relaxed); - dequeue_pos_.store(0, std::memory_order_relaxed); - } - - ~mpmc_bounded_queue() - { - delete [] buffer_; + using item_type = T; + mpmc_bounded_queue(size_t buffer_size) + : max_size_(buffer_size), buffer_(new cell_t[buffer_size]), + buffer_mask_(buffer_size - 1) { + // queue size must be power of two + if (!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0))) + throw spdlog_ex("async logger queue size must be power of two"); + + for (size_t i = 0; i != buffer_size; i += 1) + buffer_[i].sequence_.store(i, std::memory_order_relaxed); + enqueue_pos_.store(0, std::memory_order_relaxed); + dequeue_pos_.store(0, std::memory_order_relaxed); + } + + ~mpmc_bounded_queue() { delete[] buffer_; } + + bool enqueue(T &&data) { + cell_t *cell; + size_t pos = enqueue_pos_.load(std::memory_order_relaxed); + for (;;) { + cell = &buffer_[pos & buffer_mask_]; + size_t seq = cell->sequence_.load(std::memory_order_acquire); + intptr_t dif = (intptr_t)seq - (intptr_t)pos; + if (dif == 0) { + if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, + std::memory_order_relaxed)) + break; + } else if (dif < 0) { + return false; + } else { + pos = enqueue_pos_.load(std::memory_order_relaxed); + } } - - - bool enqueue(T&& data) - { - cell_t* cell; - size_t pos = enqueue_pos_.load(std::memory_order_relaxed); - for (;;) - { - cell = &buffer_[pos & buffer_mask_]; - size_t seq = cell->sequence_.load(std::memory_order_acquire); - intptr_t dif = (intptr_t)seq - (intptr_t)pos; - if (dif == 0) - { - if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) - break; - } - else if (dif < 0) - { - return false; - } - else - { - pos = enqueue_pos_.load(std::memory_order_relaxed); - } - } - cell->data_ = std::move(data); - cell->sequence_.store(pos + 1, std::memory_order_release); - return true; - } - - bool dequeue(T& data) - { - cell_t* cell; - size_t pos = dequeue_pos_.load(std::memory_order_relaxed); - for (;;) - { - cell = &buffer_[pos & buffer_mask_]; - size_t seq = - cell->sequence_.load(std::memory_order_acquire); - intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1); - if (dif == 0) - { - if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) - break; - } - else if (dif < 0) - return false; - else - pos = dequeue_pos_.load(std::memory_order_relaxed); - } - data = std::move(cell->data_); - cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release); - return true; - } - - size_t approx_size() - { - size_t first_pos = dequeue_pos_.load(std::memory_order_relaxed); - size_t last_pos = enqueue_pos_.load(std::memory_order_relaxed); - if (last_pos <= first_pos) - return 0; - auto size = last_pos - first_pos; - return size < max_size_ ? size : max_size_; + cell->data_ = std::move(data); + cell->sequence_.store(pos + 1, std::memory_order_release); + return true; + } + + bool dequeue(T &data) { + cell_t *cell; + size_t pos = dequeue_pos_.load(std::memory_order_relaxed); + for (;;) { + cell = &buffer_[pos & buffer_mask_]; + size_t seq = cell->sequence_.load(std::memory_order_acquire); + intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1); + if (dif == 0) { + if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, + std::memory_order_relaxed)) + break; + } else if (dif < 0) + return false; + else + pos = dequeue_pos_.load(std::memory_order_relaxed); } + data = std::move(cell->data_); + cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release); + return true; + } + + size_t approx_size() { + size_t first_pos = dequeue_pos_.load(std::memory_order_relaxed); + size_t last_pos = enqueue_pos_.load(std::memory_order_relaxed); + if (last_pos <= first_pos) + return 0; + auto size = last_pos - first_pos; + return size < max_size_ ? size : max_size_; + } private: - struct cell_t - { - std::atomic sequence_; - T data_; - }; - - size_t const max_size_; - - static size_t const cacheline_size = 64; - typedef char cacheline_pad_t [cacheline_size]; - - cacheline_pad_t pad0_; - cell_t* const buffer_; - size_t const buffer_mask_; - cacheline_pad_t pad1_; - std::atomic enqueue_pos_; - cacheline_pad_t pad2_; - std::atomic dequeue_pos_; - cacheline_pad_t pad3_; - - mpmc_bounded_queue(mpmc_bounded_queue const&) = delete; - void operator= (mpmc_bounded_queue const&) = delete; + struct cell_t { + std::atomic sequence_; + T data_; + }; + + size_t const max_size_; + + static size_t const cacheline_size = 64; + typedef char cacheline_pad_t[cacheline_size]; + + cacheline_pad_t pad0_; + cell_t *const buffer_; + size_t const buffer_mask_; + cacheline_pad_t pad1_; + std::atomic enqueue_pos_; + cacheline_pad_t pad2_; + std::atomic dequeue_pos_; + cacheline_pad_t pad3_; + + mpmc_bounded_queue(mpmc_bounded_queue const &) = delete; + void operator=(mpmc_bounded_queue const &) = delete; }; -} // ns details -} // ns spdlog +} // namespace details +} // namespace spdlog diff --git a/external/spdlog/details/null_mutex.h b/external/spdlog/details/null_mutex.h index 67b0aee..656b09f 100644 --- a/external/spdlog/details/null_mutex.h +++ b/external/spdlog/details/null_mutex.h @@ -8,38 +8,24 @@ #include // null, no cost dummy "mutex" and dummy "atomic" int -namespace spdlog -{ -namespace details -{ -struct null_mutex -{ - void lock() {} - void unlock() {} - bool try_lock() - { - return true; - } +namespace spdlog { +namespace details { +struct null_mutex { + void lock() {} + void unlock() {} + bool try_lock() { return true; } }; -struct null_atomic_int -{ - int value; - null_atomic_int() = default; +struct null_atomic_int { + int value; + null_atomic_int() = default; - null_atomic_int(int val):value(val) - {} + null_atomic_int(int val) : value(val) {} - int load(std::memory_order) const - { - return value; - } + int load(std::memory_order) const { return value; } - void store(int val) - { - value = val; - } + void store(int val) { value = val; } }; -} -} +} // namespace details +} // namespace spdlog diff --git a/external/spdlog/details/os.h b/external/spdlog/details/os.h index b63ce66..091b4aa 100644 --- a/external/spdlog/details/os.h +++ b/external/spdlog/details/os.h @@ -6,29 +6,29 @@ #include +#include #include #include #include -#include -#include -#include #include #include +#include #include #include +#include #ifdef _WIN32 #ifndef NOMINMAX -#define NOMINMAX //prevent windows redefining min/max +#define NOMINMAX // prevent windows redefining min/max #endif #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif -#include +#include // _get_osfhandle support #include // _get_pid support -#include // _get_osfhandle support +#include #ifdef __MINGW32__ #include @@ -36,8 +36,8 @@ #else // unix -#include #include +#include #ifdef __linux__ #include //Use gettid() syscall under linux to get thread id @@ -46,92 +46,76 @@ #include //Use thr_self() syscall under FreeBSD to get thread id #endif -#endif //unix +#endif // unix -#ifndef __has_feature // Clang - feature checking macros. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. +#ifndef __has_feature // Clang - feature checking macros. +#define __has_feature(x) 0 // Compatibility with non-clang compilers. #endif +namespace spdlog { +namespace details { +namespace os { -namespace spdlog -{ -namespace details -{ -namespace os -{ - -inline spdlog::log_clock::time_point now() -{ +inline spdlog::log_clock::time_point now() { #if defined __linux__ && defined SPDLOG_CLOCK_COARSE - timespec ts; - ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); - return std::chrono::time_point( - std::chrono::duration_cast( - std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); - + timespec ts; + ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); + return std::chrono::time_point( + std::chrono::duration_cast( + std::chrono::seconds(ts.tv_sec) + + std::chrono::nanoseconds(ts.tv_nsec))); #else - return log_clock::now(); + return log_clock::now(); #endif - } -inline std::tm localtime(const std::time_t &time_tt) -{ +inline std::tm localtime(const std::time_t &time_tt) { #ifdef _WIN32 - std::tm tm; - localtime_s(&tm, &time_tt); + std::tm tm; + localtime_s(&tm, &time_tt); #else - std::tm tm; - localtime_r(&time_tt, &tm); + std::tm tm; + localtime_r(&time_tt, &tm); #endif - return tm; + return tm; } -inline std::tm localtime() -{ - std::time_t now_t = time(nullptr); - return localtime(now_t); +inline std::tm localtime() { + std::time_t now_t = time(nullptr); + return localtime(now_t); } - -inline std::tm gmtime(const std::time_t &time_tt) -{ +inline std::tm gmtime(const std::time_t &time_tt) { #ifdef _WIN32 - std::tm tm; - gmtime_s(&tm, &time_tt); + std::tm tm; + gmtime_s(&tm, &time_tt); #else - std::tm tm; - gmtime_r(&time_tt, &tm); + std::tm tm; + gmtime_r(&time_tt, &tm); #endif - return tm; + return tm; } -inline std::tm gmtime() -{ - std::time_t now_t = time(nullptr); - return gmtime(now_t); +inline std::tm gmtime() { + std::time_t now_t = time(nullptr); + return gmtime(now_t); } -inline bool operator==(const std::tm& tm1, const std::tm& tm2) -{ - return (tm1.tm_sec == tm2.tm_sec && - tm1.tm_min == tm2.tm_min && - tm1.tm_hour == tm2.tm_hour && - tm1.tm_mday == tm2.tm_mday && - tm1.tm_mon == tm2.tm_mon && - tm1.tm_year == tm2.tm_year && - tm1.tm_isdst == tm2.tm_isdst); +inline bool operator==(const std::tm &tm1, const std::tm &tm2) { + return (tm1.tm_sec == tm2.tm_sec && tm1.tm_min == tm2.tm_min && + tm1.tm_hour == tm2.tm_hour && tm1.tm_mday == tm2.tm_mday && + tm1.tm_mon == tm2.tm_mon && tm1.tm_year == tm2.tm_year && + tm1.tm_isdst == tm2.tm_isdst); } -inline bool operator!=(const std::tm& tm1, const std::tm& tm2) -{ - return !(tm1 == tm2); +inline bool operator!=(const std::tm &tm1, const std::tm &tm2) { + return !(tm1 == tm2); } // eol definition -#if !defined (SPDLOG_EOL) +#if !defined(SPDLOG_EOL) #ifdef _WIN32 #define SPDLOG_EOL "\r\n" #else @@ -139,268 +123,249 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2) #endif #endif -SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL; +SPDLOG_CONSTEXPR static const char *eol = SPDLOG_EOL; SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1; -inline void prevent_child_fd(FILE *f) -{ +inline void prevent_child_fd(FILE *f) { #ifdef _WIN32 - auto file_handle = (HANDLE)_get_osfhandle(_fileno(f)); - if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) - throw spdlog_ex("SetHandleInformation failed", errno); + auto file_handle = (HANDLE)_get_osfhandle(_fileno(f)); + if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) + throw spdlog_ex("SetHandleInformation failed", errno); #else - auto fd = fileno(f); - if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno); + auto fd = fileno(f); + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno); #endif } - -//fopen_s on non windows for writing -inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode) -{ +// fopen_s on non windows for writing +inline int fopen_s(FILE **fp, const filename_t &filename, + const filename_t &mode) { #ifdef _WIN32 #ifdef SPDLOG_WCHAR_FILENAMES - *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYWR); + *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYWR); #else - *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR); + *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR); #endif -#else //unix - *fp = fopen((filename.c_str()), mode.c_str()); +#else // unix + *fp = fopen((filename.c_str()), mode.c_str()); #endif #ifdef SPDLOG_PREVENT_CHILD_FD - if(*fp != nullptr) - prevent_child_fd(*fp); + if (*fp != nullptr) + prevent_child_fd(*fp); #endif - return *fp == nullptr; + return *fp == nullptr; } - -inline int remove(const filename_t &filename) -{ +inline int remove(const filename_t &filename) { #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) - return _wremove(filename.c_str()); + return _wremove(filename.c_str()); #else - return std::remove(filename.c_str()); + return std::remove(filename.c_str()); #endif } -inline int rename(const filename_t& filename1, const filename_t& filename2) -{ +inline int rename(const filename_t &filename1, const filename_t &filename2) { #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) - return _wrename(filename1.c_str(), filename2.c_str()); + return _wrename(filename1.c_str(), filename2.c_str()); #else - return std::rename(filename1.c_str(), filename2.c_str()); + return std::rename(filename1.c_str(), filename2.c_str()); #endif } - -//Return if file exists -inline bool file_exists(const filename_t& filename) -{ +// Return if file exists +inline bool file_exists(const filename_t &filename) { #ifdef _WIN32 #ifdef SPDLOG_WCHAR_FILENAMES - auto attribs = GetFileAttributesW(filename.c_str()); + auto attribs = GetFileAttributesW(filename.c_str()); #else - auto attribs = GetFileAttributesA(filename.c_str()); + auto attribs = GetFileAttributesA(filename.c_str()); #endif - return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)); -#else //common linux/unix all have the stat system call - struct stat buffer; - return (stat (filename.c_str(), &buffer) == 0); + return (attribs != INVALID_FILE_ATTRIBUTES && + !(attribs & FILE_ATTRIBUTE_DIRECTORY)); +#else // common linux/unix all have the stat system call + struct stat buffer; + return (stat(filename.c_str(), &buffer) == 0); #endif } - - - -//Return file size according to open FILE* object -inline size_t filesize(FILE *f) -{ - if (f == nullptr) - throw spdlog_ex("Failed getting file size. fd is null"); +// Return file size according to open FILE* object +inline size_t filesize(FILE *f) { + if (f == nullptr) + throw spdlog_ex("Failed getting file size. fd is null"); #ifdef _WIN32 - int fd = _fileno(f); -#if _WIN64 //64 bits - struct _stat64 st; - if (_fstat64(fd, &st) == 0) - return st.st_size; - -#else //windows 32 bits - long ret = _filelength(fd); - if (ret >= 0) - return static_cast(ret); + int fd = _fileno(f); +#if _WIN64 // 64 bits + struct _stat64 st; + if (_fstat64(fd, &st) == 0) + return st.st_size; + +#else // windows 32 bits + long ret = _filelength(fd); + if (ret >= 0) + return static_cast(ret); #endif #else // unix - int fd = fileno(f); - //64 bits(but not in osx, where fstat64 is deprecated) -#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) - struct stat64 st; - if (fstat64(fd, &st) == 0) - return static_cast(st.st_size); + int fd = fileno(f); + // 64 bits(but not in osx, where fstat64 is deprecated) +#if !defined(__FreeBSD__) && !defined(__APPLE__) && \ + (defined(__x86_64__) || defined(__ppc64__)) + struct stat64 st; + if (fstat64(fd, &st) == 0) + return static_cast(st.st_size); #else // unix 32 bits or osx - struct stat st; - if (fstat(fd, &st) == 0) - return static_cast(st.st_size); + struct stat st; + if (fstat(fd, &st) == 0) + return static_cast(st.st_size); #endif #endif - throw spdlog_ex("Failed getting file size from fd", errno); + throw spdlog_ex("Failed getting file size from fd", errno); } - - - -//Return utc offset in minutes or throw spdlog_ex on failure -inline int utc_minutes_offset(const std::tm& tm = details::os::localtime()) -{ +// Return utc offset in minutes or throw spdlog_ex on failure +inline int utc_minutes_offset(const std::tm &tm = details::os::localtime()) { #ifdef _WIN32 #if _WIN32_WINNT < _WIN32_WINNT_WS08 - TIME_ZONE_INFORMATION tzinfo; - auto rv = GetTimeZoneInformation(&tzinfo); + TIME_ZONE_INFORMATION tzinfo; + auto rv = GetTimeZoneInformation(&tzinfo); #else - DYNAMIC_TIME_ZONE_INFORMATION tzinfo; - auto rv = GetDynamicTimeZoneInformation(&tzinfo); + DYNAMIC_TIME_ZONE_INFORMATION tzinfo; + auto rv = GetDynamicTimeZoneInformation(&tzinfo); #endif - if (rv == TIME_ZONE_ID_INVALID) - throw spdlog::spdlog_ex("Failed getting timezone info. ", errno); - - int offset = -tzinfo.Bias; - if (tm.tm_isdst) - offset -= tzinfo.DaylightBias; - else - offset -= tzinfo.StandardBias; - return offset; + if (rv == TIME_ZONE_ID_INVALID) + throw spdlog::spdlog_ex("Failed getting timezone info. ", errno); + + int offset = -tzinfo.Bias; + if (tm.tm_isdst) + offset -= tzinfo.DaylightBias; + else + offset -= tzinfo.StandardBias; + return offset; #else #if defined(sun) || defined(__sun) - // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris - struct helper - { - static long int calculate_gmt_offset(const std::tm & localtm = details::os::localtime(), const std::tm & gmtm = details::os::gmtime()) - { - int local_year = localtm.tm_year + (1900 - 1); - int gmt_year = gmtm.tm_year + (1900 - 1); - - long int days = ( - // difference in day of year - localtm.tm_yday - gmtm.tm_yday - - // + intervening leap days - + ((local_year >> 2) - (gmt_year >> 2)) - - (local_year / 100 - gmt_year / 100) - + ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) - - // + difference in years * 365 */ - + (long int)(local_year - gmt_year) * 365 - ); - - long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); - long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); - long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); - - return secs; - } - }; - - long int offset_seconds = helper::calculate_gmt_offset(tm); + // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris + struct helper { + static long int + calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), + const std::tm &gmtm = details::os::gmtime()) { + int local_year = localtm.tm_year + (1900 - 1); + int gmt_year = gmtm.tm_year + (1900 - 1); + + long int days = ( + // difference in day of year + localtm.tm_yday - + gmtm.tm_yday + + // + intervening leap days + + ((local_year >> 2) - (gmt_year >> 2)) - + (local_year / 100 - gmt_year / 100) + + ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) + + // + difference in years * 365 */ + + (long int)(local_year - gmt_year) * 365); + + long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); + long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); + long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); + + return secs; + } + }; + + long int offset_seconds = helper::calculate_gmt_offset(tm); #else - long int offset_seconds = tm.tm_gmtoff; + long int offset_seconds = tm.tm_gmtoff; #endif - return static_cast(offset_seconds / 60); + return static_cast(offset_seconds / 60); #endif } -//Return current thread id as size_t -//It exists because the std::this_thread::get_id() is much slower(espcially under VS 2013) -inline size_t _thread_id() -{ +// Return current thread id as size_t +// It exists because the std::this_thread::get_id() is much slower(espcially +// under VS 2013) +inline size_t _thread_id() { #ifdef _WIN32 - return static_cast(::GetCurrentThreadId()); + return static_cast(::GetCurrentThreadId()); #elif __linux__ -# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) -# define SYS_gettid __NR_gettid -# endif - return static_cast(syscall(SYS_gettid)); +#if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) +#define SYS_gettid __NR_gettid +#endif + return static_cast(syscall(SYS_gettid)); #elif __FreeBSD__ - long tid; - thr_self(&tid); - return static_cast(tid); -#else //Default to standard C++11 (OSX and other Unix) - return static_cast(std::hash()(std::this_thread::get_id())); + long tid; + thr_self(&tid); + return static_cast(tid); +#else // Default to standard C++11 (OSX and other Unix) + return static_cast( + std::hash()(std::this_thread::get_id())); #endif } -//Return current thread id as size_t (from thread local storage) -inline size_t thread_id() -{ -#if defined(_MSC_VER) && (_MSC_VER < 1900) || defined(__clang__) && !__has_feature(cxx_thread_local) - return _thread_id(); +// Return current thread id as size_t (from thread local storage) +inline size_t thread_id() { +#if defined(_MSC_VER) && (_MSC_VER < 1900) || \ + defined(__clang__) && !__has_feature(cxx_thread_local) + return _thread_id(); #else - static thread_local const size_t tid = _thread_id(); - return tid; + static thread_local const size_t tid = _thread_id(); + return tid; #endif } - - - // wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) -#define SPDLOG_FILENAME_T(s) L ## s -inline std::string filename_to_str(const filename_t& filename) -{ - std::wstring_convert, wchar_t> c; - return c.to_bytes(filename); +#define SPDLOG_FILENAME_T(s) L##s +inline std::string filename_to_str(const filename_t &filename) { + std::wstring_convert, wchar_t> c; + return c.to_bytes(filename); } #else #define SPDLOG_FILENAME_T(s) s -inline std::string filename_to_str(const filename_t& filename) -{ - return filename; +inline std::string filename_to_str(const filename_t &filename) { + return filename; } #endif - // Return errno string (thread safe) -inline std::string errno_str(int err_num) -{ - char buf[256]; - SPDLOG_CONSTEXPR auto buf_size = sizeof(buf); +inline std::string errno_str(int err_num) { + char buf[256]; + SPDLOG_CONSTEXPR auto buf_size = sizeof(buf); #ifdef _WIN32 - if(strerror_s(buf, buf_size, err_num) == 0) - return std::string(buf); - else - return "Unkown error"; - -#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \ - ((_POSIX_C_SOURCE >= 200112L) && ! defined(_GNU_SOURCE)) // posix version - - if (strerror_r(err_num, buf, buf_size) == 0) - return std::string(buf); - else - return "Unkown error"; - -#else // gnu version (might not use the given buf, so its retval pointer must be used) - return std::string(strerror_r(err_num, buf, buf_size)); + if (strerror_s(buf, buf_size, err_num) == 0) + return std::string(buf); + else + return "Unkown error"; + +#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || \ + defined(__SUNPRO_CC) || \ + ((_POSIX_C_SOURCE >= 200112L) && !defined(_GNU_SOURCE)) // posix version + + if (strerror_r(err_num, buf, buf_size) == 0) + return std::string(buf); + else + return "Unkown error"; + +#else // gnu version (might not use the given buf, so its retval pointer must be + // used) + return std::string(strerror_r(err_num, buf, buf_size)); #endif } -inline int pid() -{ +inline int pid() { #ifdef _WIN32 - return ::_getpid(); + return ::_getpid(); #else - return static_cast(::getpid()); + return static_cast(::getpid()); #endif - } -} //os -} //details -} //spdlog +} // namespace os +} // namespace details +} // namespace spdlog diff --git a/external/spdlog/details/pattern_formatter_impl.h b/external/spdlog/details/pattern_formatter_impl.h index 70b9dc8..c19e2ac 100644 --- a/external/spdlog/details/pattern_formatter_impl.h +++ b/external/spdlog/details/pattern_formatter_impl.h @@ -5,11 +5,12 @@ #pragma once -#include #include #include #include +#include +#include #include #include #include @@ -18,653 +19,603 @@ #include #include #include -#include -namespace spdlog -{ -namespace details -{ -class flag_formatter -{ +namespace spdlog { +namespace details { +class flag_formatter { public: - virtual ~flag_formatter() - {} - virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0; + virtual ~flag_formatter() {} + virtual void format(details::log_msg &msg, const std::tm &tm_time) = 0; }; /////////////////////////////////////////////////////////////////////// // name & level pattern appenders /////////////////////////////////////////////////////////////////////// -namespace -{ -class name_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << *msg.logger_name; - } +namespace { +class name_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << *msg.logger_name; + } }; -} +} // namespace // log level appender -class level_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << level::to_str(msg.level); - } +class level_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << level::to_str(msg.level); + } }; // short log level appender -class short_level_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << level::to_short_str(msg.level); - } +class short_level_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << level::to_short_str(msg.level); + } }; /////////////////////////////////////////////////////////////////////// // Date time pattern appenders /////////////////////////////////////////////////////////////////////// -static const char* ampm(const tm& t) -{ - return t.tm_hour >= 12 ? "PM" : "AM"; -} +static const char *ampm(const tm &t) { return t.tm_hour >= 12 ? "PM" : "AM"; } -static int to12h(const tm& t) -{ - return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour; +static int to12h(const tm &t) { + return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour; } -//Abbreviated weekday name +// Abbreviated weekday name using days_array = std::array; -static const days_array& days() -{ - static const days_array arr{ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } }; - return arr; +static const days_array &days() { + static const days_array arr{ + {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}}; + return arr; } -class a_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << days()[tm_time.tm_wday]; - } +class a_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << days()[tm_time.tm_wday]; + } }; -//Full weekday name -static const days_array& full_days() -{ - static const days_array arr{ { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } }; - return arr; +// Full weekday name +static const days_array &full_days() { + static const days_array arr{{"Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}}; + return arr; } -class A_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << full_days()[tm_time.tm_wday]; - } +class A_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << full_days()[tm_time.tm_wday]; + } }; -//Abbreviated month +// Abbreviated month using months_array = std::array; -static const months_array& months() -{ - static const months_array arr{ { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" } }; - return arr; +static const months_array &months() { + static const months_array arr{{"Jan", "Feb", "Mar", "Apr", "May", "June", + "July", "Aug", "Sept", "Oct", "Nov", "Dec"}}; + return arr; } -class b_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << months()[tm_time.tm_mon]; - } -}; - -//Full month name -static const months_array& full_months() -{ - static const months_array arr{ { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" } }; - return arr; +class b_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << months()[tm_time.tm_mon]; + } +}; + +// Full month name +static const months_array &full_months() { + static const months_array arr{{"January", "February", "March", "April", "May", + "June", "July", "August", "September", + "October", "November", "December"}}; + return arr; } -class B_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << full_months()[tm_time.tm_mon]; - } +class B_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << full_months()[tm_time.tm_mon]; + } }; - -//write 2 ints seperated by sep with padding of 2 -static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep) -{ - w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0'); - return w; +// write 2 ints seperated by sep with padding of 2 +static fmt::MemoryWriter &pad_n_join(fmt::MemoryWriter &w, int v1, int v2, + char sep) { + w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0'); + return w; } -//write 3 ints seperated by sep with padding of 2 -static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep) -{ - w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0'); - return w; +// write 3 ints seperated by sep with padding of 2 +static fmt::MemoryWriter &pad_n_join(fmt::MemoryWriter &w, int v1, int v2, + int v3, char sep) { + w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep + << fmt::pad(v3, 2, '0'); + return w; } - -//Date and time representation (Thu Aug 23 15:35:46 2014) -class c_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << days()[tm_time.tm_wday] << ' ' << months()[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' '; - pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900; - } +// Date and time representation (Thu Aug 23 15:35:46 2014) +class c_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << days()[tm_time.tm_wday] << ' ' << months()[tm_time.tm_mon] + << ' ' << tm_time.tm_mday << ' '; + pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, + ':') + << ' ' << tm_time.tm_year + 1900; + } }; - // year - 2 digit -class C_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0'); - } +class C_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0'); + } }; - - // Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01 -class D_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/'); - } +class D_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, + tm_time.tm_year % 100, '/'); + } }; - // year - 4 digit -class Y_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << tm_time.tm_year + 1900; - } +class Y_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << tm_time.tm_year + 1900; + } }; // month 1-12 -class m_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0'); - } +class m_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0'); + } }; // day of month 1-31 -class d_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0'); - } +class d_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0'); + } }; // hours in 24 format 0-23 -class H_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0'); - } +class H_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0'); + } }; // hours in 12 format 1-12 -class I_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << fmt::pad(to12h(tm_time), 2, '0'); - } +class I_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << fmt::pad(to12h(tm_time), 2, '0'); + } }; // minutes 0-59 -class M_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << fmt::pad(tm_time.tm_min, 2, '0'); - } +class M_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << fmt::pad(tm_time.tm_min, 2, '0'); + } }; // seconds 0-59 -class S_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0'); - } +class S_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0'); + } }; // milliseconds -class e_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - auto duration = msg.time.time_since_epoch(); - auto millis = std::chrono::duration_cast(duration).count() % 1000; - msg.formatted << fmt::pad(static_cast(millis), 3, '0'); - } +class e_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + auto duration = msg.time.time_since_epoch(); + auto millis = + std::chrono::duration_cast(duration) + .count() % + 1000; + msg.formatted << fmt::pad(static_cast(millis), 3, '0'); + } }; // microseconds -class f_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - auto duration = msg.time.time_since_epoch(); - auto micros = std::chrono::duration_cast(duration).count() % 1000000; - msg.formatted << fmt::pad(static_cast(micros), 6, '0'); - } +class f_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + auto duration = msg.time.time_since_epoch(); + auto micros = + std::chrono::duration_cast(duration) + .count() % + 1000000; + msg.formatted << fmt::pad(static_cast(micros), 6, '0'); + } }; // nanoseconds -class F_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - auto duration = msg.time.time_since_epoch(); - auto ns = std::chrono::duration_cast(duration).count() % 1000000000; - msg.formatted << fmt::pad(static_cast(ns), 9, '0'); - } +class F_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + auto duration = msg.time.time_since_epoch(); + auto ns = + std::chrono::duration_cast(duration).count() % + 1000000000; + msg.formatted << fmt::pad(static_cast(ns), 9, '0'); + } }; // AM/PM -class p_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - msg.formatted << ampm(tm_time); - } +class p_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + msg.formatted << ampm(tm_time); + } }; - // 12 hour clock 02:55:02 pm -class r_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time); - } +class r_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, + ':') + << ' ' << ampm(tm_time); + } }; // 24-hour HH:MM time, equivalent to %H:%M -class R_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':'); - } +class R_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':'); + } }; // ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S -class T_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { - pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':'); - } +class T_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { + pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, + ':'); + } }; - // ISO 8601 offset from UTC in timezone (+-HH:MM) -class z_formatter:public flag_formatter -{ +class z_formatter : public flag_formatter { public: - const std::chrono::seconds cache_refresh = std::chrono::seconds(5); + const std::chrono::seconds cache_refresh = std::chrono::seconds(5); - z_formatter():_last_update(std::chrono::seconds(0)) - {} - z_formatter(const z_formatter&) = delete; - z_formatter& operator=(const z_formatter&) = delete; + z_formatter() : _last_update(std::chrono::seconds(0)) {} + z_formatter(const z_formatter &) = delete; + z_formatter &operator=(const z_formatter &) = delete; - void format(details::log_msg& msg, const std::tm& tm_time) override - { + void format(details::log_msg &msg, const std::tm &tm_time) override { #ifdef _WIN32 - int total_minutes = get_cached_offset(msg, tm_time); + int total_minutes = get_cached_offset(msg, tm_time); #else - // No need to chache under gcc, - // it is very fast (already stored in tm.tm_gmtoff) - int total_minutes = os::utc_minutes_offset(tm_time); + // No need to chache under gcc, + // it is very fast (already stored in tm.tm_gmtoff) + int total_minutes = os::utc_minutes_offset(tm_time); #endif - bool is_negative = total_minutes < 0; - char sign; - if (is_negative) - { - total_minutes = -total_minutes; - sign = '-'; - } - else - { - sign = '+'; - } - - int h = total_minutes / 60; - int m = total_minutes % 60; - msg.formatted << sign; - pad_n_join(msg.formatted, h, m, ':'); + bool is_negative = total_minutes < 0; + char sign; + if (is_negative) { + total_minutes = -total_minutes; + sign = '-'; + } else { + sign = '+'; } + + int h = total_minutes / 60; + int m = total_minutes % 60; + msg.formatted << sign; + pad_n_join(msg.formatted, h, m, ':'); + } + private: - log_clock::time_point _last_update; - int _offset_minutes; - std::mutex _mutex; + log_clock::time_point _last_update; + int _offset_minutes; + std::mutex _mutex; - int get_cached_offset(const log_msg& msg, const std::tm& tm_time) - { - using namespace std::chrono; - std::lock_guard l(_mutex); - if (msg.time - _last_update >= cache_refresh) - { - _offset_minutes = os::utc_minutes_offset(tm_time); - _last_update = msg.time; - } - return _offset_minutes; + int get_cached_offset(const log_msg &msg, const std::tm &tm_time) { + using namespace std::chrono; + std::lock_guard l(_mutex); + if (msg.time - _last_update >= cache_refresh) { + _offset_minutes = os::utc_minutes_offset(tm_time); + _last_update = msg.time; } + return _offset_minutes; + } }; - - // Thread id -class t_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << msg.thread_id; - } +class t_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << msg.thread_id; + } }; // Current pid -class pid_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << details::os::pid(); - } +class pid_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << details::os::pid(); + } }; - -class v_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size()); - } +class v_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size()); + } }; -class ch_formatter:public flag_formatter -{ +class ch_formatter : public flag_formatter { public: - explicit ch_formatter(char ch): _ch(ch) - {} - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << _ch; - } + explicit ch_formatter(char ch) : _ch(ch) {} + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << _ch; + } + private: - char _ch; + char _ch; }; - -//aggregate user chars to display as is -class aggregate_formatter:public flag_formatter -{ +// aggregate user chars to display as is +class aggregate_formatter : public flag_formatter { public: - aggregate_formatter() - {} - void add_ch(char ch) - { - _str += ch; - } - void format(details::log_msg& msg, const std::tm&) override - { - msg.formatted << _str; - } + aggregate_formatter() {} + void add_ch(char ch) { _str += ch; } + void format(details::log_msg &msg, const std::tm &) override { + msg.formatted << _str; + } + private: - std::string _str; + std::string _str; }; // Full info formatter // pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v -class full_formatter:public flag_formatter -{ - void format(details::log_msg& msg, const std::tm& tm_time) override - { +class full_formatter : public flag_formatter { + void format(details::log_msg &msg, const std::tm &tm_time) override { #ifndef SPDLOG_NO_DATETIME - auto duration = msg.time.time_since_epoch(); - auto millis = std::chrono::duration_cast(duration).count() % 1000; - - /* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads), - msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ", - tm_time.tm_year + 1900, - tm_time.tm_mon + 1, - tm_time.tm_mday, - tm_time.tm_hour, - tm_time.tm_min, - tm_time.tm_sec, - static_cast(millis), - msg.logger_name, - level::to_str(msg.level), - msg.raw.str());*/ - - - // Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads) - msg.formatted << '[' << static_cast(tm_time.tm_year + 1900) << '-' - << fmt::pad(static_cast(tm_time.tm_mon + 1), 2, '0') << '-' - << fmt::pad(static_cast(tm_time.tm_mday), 2, '0') << ' ' - << fmt::pad(static_cast(tm_time.tm_hour), 2, '0') << ':' - << fmt::pad(static_cast(tm_time.tm_min), 2, '0') << ':' - << fmt::pad(static_cast(tm_time.tm_sec), 2, '0') << '.' - << fmt::pad(static_cast(millis), 3, '0') << "] "; - - //no datetime needed + auto duration = msg.time.time_since_epoch(); + auto millis = + std::chrono::duration_cast(duration) + .count() % + 1000; + + /* Slower version(while still very fast - about 3.2 million lines/sec under + 10 threads), msg.formatted.write("[{:d}-{:02d}-{:02d} + {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ", tm_time.tm_year + 1900, + tm_time.tm_mon + 1, + tm_time.tm_mday, + tm_time.tm_hour, + tm_time.tm_min, + tm_time.tm_sec, + static_cast(millis), + msg.logger_name, + level::to_str(msg.level), + msg.raw.str());*/ + + // Faster (albeit uglier) way to format the line (5.6 million lines/sec + // under 10 threads) + msg.formatted + << '[' << static_cast(tm_time.tm_year + 1900) << '-' + << fmt::pad(static_cast(tm_time.tm_mon + 1), 2, '0') + << '-' << fmt::pad(static_cast(tm_time.tm_mday), 2, '0') + << ' ' << fmt::pad(static_cast(tm_time.tm_hour), 2, '0') + << ':' << fmt::pad(static_cast(tm_time.tm_min), 2, '0') + << ':' << fmt::pad(static_cast(tm_time.tm_sec), 2, '0') + << '.' << fmt::pad(static_cast(millis), 3, '0') << "] "; + + // no datetime needed #else - (void)tm_time; + (void)tm_time; #endif #ifndef SPDLOG_NO_NAME - msg.formatted << '[' << *msg.logger_name << "] "; + msg.formatted << '[' << *msg.logger_name << "] "; #endif - msg.formatted << '[' << level::to_str(msg.level) << "] "; - msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size()); - } + msg.formatted << '[' << level::to_str(msg.level) << "] "; + msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size()); + } }; - - -} -} +} // namespace details +} // namespace spdlog /////////////////////////////////////////////////////////////////////////////// // pattern_formatter inline impl /////////////////////////////////////////////////////////////////////////////// -inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern) -{ - compile_pattern(pattern); +inline spdlog::pattern_formatter::pattern_formatter( + const std::string &pattern) { + compile_pattern(pattern); } -inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern) -{ - auto end = pattern.end(); - std::unique_ptr user_chars; - for (auto it = pattern.begin(); it != end; ++it) - { - if (*it == '%') - { - if (user_chars) //append user chars found so far - _formatters.push_back(std::move(user_chars)); - - if (++it != end) - handle_flag(*it); - else - break; - } - else // chars not following the % sign should be displayed as is - { - if (!user_chars) - user_chars = std::unique_ptr(new details::aggregate_formatter()); - user_chars->add_ch(*it); - } - } - if (user_chars) //append raw chars found so far - { +inline void +spdlog::pattern_formatter::compile_pattern(const std::string &pattern) { + auto end = pattern.end(); + std::unique_ptr user_chars; + for (auto it = pattern.begin(); it != end; ++it) { + if (*it == '%') { + if (user_chars) // append user chars found so far _formatters.push_back(std::move(user_chars)); - } - -} -inline void spdlog::pattern_formatter::handle_flag(char flag) -{ - switch (flag) - { - // logger name - case 'n': - _formatters.push_back(std::unique_ptr(new details::name_formatter())); - break; - - case 'l': - _formatters.push_back(std::unique_ptr(new details::level_formatter())); - break; - - case 'L': - _formatters.push_back(std::unique_ptr(new details::short_level_formatter())); - break; - - case('t'): - _formatters.push_back(std::unique_ptr(new details::t_formatter())); - break; - - case('v'): - _formatters.push_back(std::unique_ptr(new details::v_formatter())); - break; - - case('a'): - _formatters.push_back(std::unique_ptr(new details::a_formatter())); - break; - - case('A'): - _formatters.push_back(std::unique_ptr(new details::A_formatter())); - break; - - case('b'): - case('h'): - _formatters.push_back(std::unique_ptr(new details::b_formatter())); - break; - - case('B'): - _formatters.push_back(std::unique_ptr(new details::B_formatter())); - break; - case('c'): - _formatters.push_back(std::unique_ptr(new details::c_formatter())); - break; - - case('C'): - _formatters.push_back(std::unique_ptr(new details::C_formatter())); - break; - - case('Y'): - _formatters.push_back(std::unique_ptr(new details::Y_formatter())); - break; - - case('D'): - case('x'): - - _formatters.push_back(std::unique_ptr(new details::D_formatter())); - break; - - case('m'): - _formatters.push_back(std::unique_ptr(new details::m_formatter())); - break; - - case('d'): - _formatters.push_back(std::unique_ptr(new details::d_formatter())); - break; - - case('H'): - _formatters.push_back(std::unique_ptr(new details::H_formatter())); - break; - - case('I'): - _formatters.push_back(std::unique_ptr(new details::I_formatter())); - break; - - case('M'): - _formatters.push_back(std::unique_ptr(new details::M_formatter())); - break; - - case('S'): - _formatters.push_back(std::unique_ptr(new details::S_formatter())); - break; - - case('e'): - _formatters.push_back(std::unique_ptr(new details::e_formatter())); - break; - - case('f'): - _formatters.push_back(std::unique_ptr(new details::f_formatter())); - break; - case('F'): - _formatters.push_back(std::unique_ptr(new details::F_formatter())); - break; - - case('p'): - _formatters.push_back(std::unique_ptr(new details::p_formatter())); - break; - - case('r'): - _formatters.push_back(std::unique_ptr(new details::r_formatter())); - break; - - case('R'): - _formatters.push_back(std::unique_ptr(new details::R_formatter())); - break; - - case('T'): - case('X'): - _formatters.push_back(std::unique_ptr(new details::T_formatter())); - break; - - case('z'): - _formatters.push_back(std::unique_ptr(new details::z_formatter())); - break; - - case ('+'): - _formatters.push_back(std::unique_ptr(new details::full_formatter())); - break; - - case ('P'): - _formatters.push_back(std::unique_ptr(new details::pid_formatter())); - break; - default: //Unkown flag appears as is - _formatters.push_back(std::unique_ptr(new details::ch_formatter('%'))); - _formatters.push_back(std::unique_ptr(new details::ch_formatter(flag))); + if (++it != end) + handle_flag(*it); + else break; - } + } else // chars not following the % sign should be displayed as is + { + if (!user_chars) + user_chars = std::unique_ptr( + new details::aggregate_formatter()); + user_chars->add_ch(*it); + } + } + if (user_chars) // append raw chars found so far + { + _formatters.push_back(std::move(user_chars)); + } +} +inline void spdlog::pattern_formatter::handle_flag(char flag) { + switch (flag) { + // logger name + case 'n': + _formatters.push_back(std::unique_ptr( + new details::name_formatter())); + break; + + case 'l': + _formatters.push_back(std::unique_ptr( + new details::level_formatter())); + break; + + case 'L': + _formatters.push_back(std::unique_ptr( + new details::short_level_formatter())); + break; + + case ('t'): + _formatters.push_back( + std::unique_ptr(new details::t_formatter())); + break; + + case ('v'): + _formatters.push_back( + std::unique_ptr(new details::v_formatter())); + break; + + case ('a'): + _formatters.push_back( + std::unique_ptr(new details::a_formatter())); + break; + + case ('A'): + _formatters.push_back( + std::unique_ptr(new details::A_formatter())); + break; + + case ('b'): + case ('h'): + _formatters.push_back( + std::unique_ptr(new details::b_formatter())); + break; + + case ('B'): + _formatters.push_back( + std::unique_ptr(new details::B_formatter())); + break; + case ('c'): + _formatters.push_back( + std::unique_ptr(new details::c_formatter())); + break; + + case ('C'): + _formatters.push_back( + std::unique_ptr(new details::C_formatter())); + break; + + case ('Y'): + _formatters.push_back( + std::unique_ptr(new details::Y_formatter())); + break; + + case ('D'): + case ('x'): + + _formatters.push_back( + std::unique_ptr(new details::D_formatter())); + break; + + case ('m'): + _formatters.push_back( + std::unique_ptr(new details::m_formatter())); + break; + + case ('d'): + _formatters.push_back( + std::unique_ptr(new details::d_formatter())); + break; + + case ('H'): + _formatters.push_back( + std::unique_ptr(new details::H_formatter())); + break; + + case ('I'): + _formatters.push_back( + std::unique_ptr(new details::I_formatter())); + break; + + case ('M'): + _formatters.push_back( + std::unique_ptr(new details::M_formatter())); + break; + + case ('S'): + _formatters.push_back( + std::unique_ptr(new details::S_formatter())); + break; + + case ('e'): + _formatters.push_back( + std::unique_ptr(new details::e_formatter())); + break; + + case ('f'): + _formatters.push_back( + std::unique_ptr(new details::f_formatter())); + break; + case ('F'): + _formatters.push_back( + std::unique_ptr(new details::F_formatter())); + break; + + case ('p'): + _formatters.push_back( + std::unique_ptr(new details::p_formatter())); + break; + + case ('r'): + _formatters.push_back( + std::unique_ptr(new details::r_formatter())); + break; + + case ('R'): + _formatters.push_back( + std::unique_ptr(new details::R_formatter())); + break; + + case ('T'): + case ('X'): + _formatters.push_back( + std::unique_ptr(new details::T_formatter())); + break; + + case ('z'): + _formatters.push_back( + std::unique_ptr(new details::z_formatter())); + break; + + case ('+'): + _formatters.push_back(std::unique_ptr( + new details::full_formatter())); + break; + + case ('P'): + _formatters.push_back( + std::unique_ptr(new details::pid_formatter())); + break; + + default: // Unkown flag appears as is + _formatters.push_back(std::unique_ptr( + new details::ch_formatter('%'))); + _formatters.push_back(std::unique_ptr( + new details::ch_formatter(flag))); + break; + } } - -inline void spdlog::pattern_formatter::format(details::log_msg& msg) -{ +inline void spdlog::pattern_formatter::format(details::log_msg &msg) { #ifndef SPDLOG_NO_DATETIME - auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time)); + auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time)); #else - std::tm tm_time; + std::tm tm_time; #endif - for (auto &f : _formatters) - { - f->format(msg, tm_time); - } - //write eol - msg.formatted.write(details::os::eol, details::os::eol_size); + for (auto &f : _formatters) { + f->format(msg, tm_time); + } + // write eol + msg.formatted.write(details::os::eol, details::os::eol_size); } diff --git a/external/spdlog/details/registry.h b/external/spdlog/details/registry.h index ee14adf..87b21f8 100644 --- a/external/spdlog/details/registry.h +++ b/external/spdlog/details/registry.h @@ -10,10 +10,10 @@ // If user requests a non existing logger, nullptr will be returned // This class is thread safe -#include -#include #include #include +#include +#include #include #include @@ -22,164 +22,151 @@ #include #include -namespace spdlog -{ -namespace details -{ -template class registry_t -{ +namespace spdlog { +namespace details { +template class registry_t { public: - - void register_logger(std::shared_ptr logger) - { - std::lock_guard lock(_mutex); - auto logger_name = logger->name(); - throw_if_exists(logger_name); - _loggers[logger_name] = logger; - } - - - std::shared_ptr get(const std::string& logger_name) - { - std::lock_guard lock(_mutex); - auto found = _loggers.find(logger_name); - return found == _loggers.end() ? nullptr : found->second; - } - - template - std::shared_ptr create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) - { - std::lock_guard lock(_mutex); - throw_if_exists(logger_name); - std::shared_ptr new_logger; - if (_async_mode) - new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb); - else - new_logger = std::make_shared(logger_name, sinks_begin, sinks_end); - - if (_formatter) - new_logger->set_formatter(_formatter); - - if (_err_handler) - new_logger->set_error_handler(_err_handler); - - new_logger->set_level(_level); - - - //Add to registry - _loggers[logger_name] = new_logger; - return new_logger; - } - - void apply_all(std::function)> fun) - { - std::lock_guard lock(_mutex); - for (auto &l : _loggers) - fun(l.second); - } - - void drop(const std::string& logger_name) - { - std::lock_guard lock(_mutex); - _loggers.erase(logger_name); - } - - void drop_all() - { - std::lock_guard lock(_mutex); - _loggers.clear(); - } - std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks) - { - return create(logger_name, sinks.begin(), sinks.end()); - } - - std::shared_ptr create(const std::string& logger_name, sink_ptr sink) - { - return create(logger_name, { sink }); - } - - - void formatter(formatter_ptr f) - { - std::lock_guard lock(_mutex); - _formatter = f; - for (auto& l : _loggers) - l.second->set_formatter(_formatter); - } - - void set_pattern(const std::string& pattern) - { - std::lock_guard lock(_mutex); - _formatter = std::make_shared(pattern); - for (auto& l : _loggers) - l.second->set_formatter(_formatter); - } - - void set_level(level::level_enum log_level) - { - std::lock_guard lock(_mutex); - for (auto& l : _loggers) - l.second->set_level(log_level); - _level = log_level; - } - - void set_error_handler(log_err_handler handler) - { - for (auto& l : _loggers) - l.second->set_error_handler(handler); - _err_handler = handler; - } - - void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb) - { - std::lock_guard lock(_mutex); - _async_mode = true; - _async_q_size = q_size; - _overflow_policy = overflow_policy; - _worker_warmup_cb = worker_warmup_cb; - _flush_interval_ms = flush_interval_ms; - _worker_teardown_cb = worker_teardown_cb; - } - - void set_sync_mode() - { - std::lock_guard lock(_mutex); - _async_mode = false; - } - - static registry_t& instance() - { - static registry_t s_instance; - return s_instance; - } + void register_logger(std::shared_ptr logger) { + std::lock_guard lock(_mutex); + auto logger_name = logger->name(); + throw_if_exists(logger_name); + _loggers[logger_name] = logger; + } + + std::shared_ptr get(const std::string &logger_name) { + std::lock_guard lock(_mutex); + auto found = _loggers.find(logger_name); + return found == _loggers.end() ? nullptr : found->second; + } + + template + std::shared_ptr create(const std::string &logger_name, + const It &sinks_begin, const It &sinks_end) { + std::lock_guard lock(_mutex); + throw_if_exists(logger_name); + std::shared_ptr new_logger; + if (_async_mode) + new_logger = std::make_shared( + logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, + _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb); + else + new_logger = + std::make_shared(logger_name, sinks_begin, sinks_end); + + if (_formatter) + new_logger->set_formatter(_formatter); + + if (_err_handler) + new_logger->set_error_handler(_err_handler); + + new_logger->set_level(_level); + + // Add to registry + _loggers[logger_name] = new_logger; + return new_logger; + } + + void apply_all(std::function)> fun) { + std::lock_guard lock(_mutex); + for (auto &l : _loggers) + fun(l.second); + } + + void drop(const std::string &logger_name) { + std::lock_guard lock(_mutex); + _loggers.erase(logger_name); + } + + void drop_all() { + std::lock_guard lock(_mutex); + _loggers.clear(); + } + std::shared_ptr create(const std::string &logger_name, + sinks_init_list sinks) { + return create(logger_name, sinks.begin(), sinks.end()); + } + + std::shared_ptr create(const std::string &logger_name, + sink_ptr sink) { + return create(logger_name, {sink}); + } + + void formatter(formatter_ptr f) { + std::lock_guard lock(_mutex); + _formatter = f; + for (auto &l : _loggers) + l.second->set_formatter(_formatter); + } + + void set_pattern(const std::string &pattern) { + std::lock_guard lock(_mutex); + _formatter = std::make_shared(pattern); + for (auto &l : _loggers) + l.second->set_formatter(_formatter); + } + + void set_level(level::level_enum log_level) { + std::lock_guard lock(_mutex); + for (auto &l : _loggers) + l.second->set_level(log_level); + _level = log_level; + } + + void set_error_handler(log_err_handler handler) { + for (auto &l : _loggers) + l.second->set_error_handler(handler); + _err_handler = handler; + } + + void set_async_mode(size_t q_size, + const async_overflow_policy overflow_policy, + const std::function &worker_warmup_cb, + const std::chrono::milliseconds &flush_interval_ms, + const std::function &worker_teardown_cb) { + std::lock_guard lock(_mutex); + _async_mode = true; + _async_q_size = q_size; + _overflow_policy = overflow_policy; + _worker_warmup_cb = worker_warmup_cb; + _flush_interval_ms = flush_interval_ms; + _worker_teardown_cb = worker_teardown_cb; + } + + void set_sync_mode() { + std::lock_guard lock(_mutex); + _async_mode = false; + } + + static registry_t &instance() { + static registry_t s_instance; + return s_instance; + } private: - registry_t() {} - registry_t(const registry_t&) = delete; - registry_t& operator=(const registry_t&) = delete; - - void throw_if_exists(const std::string &logger_name) - { - if (_loggers.find(logger_name) != _loggers.end()) - throw spdlog_ex("logger with name '" + logger_name + "' already exists"); - } - Mutex _mutex; - std::unordered_map > _loggers; - formatter_ptr _formatter; - level::level_enum _level = level::info; - log_err_handler _err_handler; - bool _async_mode = false; - size_t _async_q_size = 0; - async_overflow_policy _overflow_policy = async_overflow_policy::block_retry; - std::function _worker_warmup_cb = nullptr; - std::chrono::milliseconds _flush_interval_ms; - std::function _worker_teardown_cb = nullptr; + registry_t() {} + registry_t(const registry_t &) = delete; + registry_t &operator=(const registry_t &) = delete; + + void throw_if_exists(const std::string &logger_name) { + if (_loggers.find(logger_name) != _loggers.end()) + throw spdlog_ex("logger with name '" + logger_name + "' already exists"); + } + Mutex _mutex; + std::unordered_map> _loggers; + formatter_ptr _formatter; + level::level_enum _level = level::info; + log_err_handler _err_handler; + bool _async_mode = false; + size_t _async_q_size = 0; + async_overflow_policy _overflow_policy = async_overflow_policy::block_retry; + std::function _worker_warmup_cb = nullptr; + std::chrono::milliseconds _flush_interval_ms; + std::function _worker_teardown_cb = nullptr; }; #ifdef SPDLOG_NO_REGISTRY_MUTEX typedef registry_t registry; #else typedef registry_t registry; #endif -} -} +} // namespace details +} // namespace spdlog diff --git a/external/spdlog/details/spdlog_impl.h b/external/spdlog/details/spdlog_impl.h index 79d3ac4..82a99e7 100644 --- a/external/spdlog/details/spdlog_impl.h +++ b/external/spdlog/details/spdlog_impl.h @@ -8,10 +8,10 @@ // // Global registry functions // -#include #include #include #include +#include #ifdef SPDLOG_ENABLE_SYSLOG #include #endif @@ -22,7 +22,6 @@ #include #endif - #ifdef __ANDROID__ #include #endif @@ -32,214 +31,230 @@ #include #include -inline void spdlog::register_logger(std::shared_ptr logger) -{ - return details::registry::instance().register_logger(logger); +inline void spdlog::register_logger(std::shared_ptr logger) { + return details::registry::instance().register_logger(logger); } -inline std::shared_ptr spdlog::get(const std::string& name) -{ - return details::registry::instance().get(name); +inline std::shared_ptr spdlog::get(const std::string &name) { + return details::registry::instance().get(name); } -inline void spdlog::drop(const std::string &name) -{ - details::registry::instance().drop(name); +inline void spdlog::drop(const std::string &name) { + details::registry::instance().drop(name); } // Create multi/single threaded simple file logger -inline std::shared_ptr spdlog::basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate) -{ - return create(logger_name, filename, truncate); +inline std::shared_ptr +spdlog::basic_logger_mt(const std::string &logger_name, + const filename_t &filename, bool truncate) { + return create(logger_name, filename, + truncate); } -inline std::shared_ptr spdlog::basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate) -{ - return create(logger_name, filename, truncate); +inline std::shared_ptr +spdlog::basic_logger_st(const std::string &logger_name, + const filename_t &filename, bool truncate) { + return create(logger_name, filename, + truncate); } // Create multi/single threaded rotating file logger -inline std::shared_ptr spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) -{ - return create(logger_name, filename, max_file_size, max_files); +inline std::shared_ptr +spdlog::rotating_logger_mt(const std::string &logger_name, + const filename_t &filename, size_t max_file_size, + size_t max_files) { + return create(logger_name, filename, + max_file_size, max_files); } -inline std::shared_ptr spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) -{ - return create(logger_name, filename, max_file_size, max_files); +inline std::shared_ptr +spdlog::rotating_logger_st(const std::string &logger_name, + const filename_t &filename, size_t max_file_size, + size_t max_files) { + return create(logger_name, filename, + max_file_size, max_files); } // Create file logger which creates new file at midnight): -inline std::shared_ptr spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute) -{ - return create(logger_name, filename, hour, minute); +inline std::shared_ptr +spdlog::daily_logger_mt(const std::string &logger_name, + const filename_t &filename, int hour, int minute) { + return create(logger_name, filename, hour, + minute); } -inline std::shared_ptr spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute) -{ - return create(logger_name, filename, hour, minute); +inline std::shared_ptr +spdlog::daily_logger_st(const std::string &logger_name, + const filename_t &filename, int hour, int minute) { + return create(logger_name, filename, hour, + minute); } - // // stdout/stderr loggers // -inline std::shared_ptr spdlog::stdout_logger_mt(const std::string& logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance()); +inline std::shared_ptr +spdlog::stdout_logger_mt(const std::string &logger_name) { + return spdlog::details::registry::instance().create( + logger_name, spdlog::sinks::stdout_sink_mt::instance()); } -inline std::shared_ptr spdlog::stdout_logger_st(const std::string& logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance()); +inline std::shared_ptr +spdlog::stdout_logger_st(const std::string &logger_name) { + return spdlog::details::registry::instance().create( + logger_name, spdlog::sinks::stdout_sink_st::instance()); } -inline std::shared_ptr spdlog::stderr_logger_mt(const std::string& logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance()); +inline std::shared_ptr +spdlog::stderr_logger_mt(const std::string &logger_name) { + return spdlog::details::registry::instance().create( + logger_name, spdlog::sinks::stderr_sink_mt::instance()); } -inline std::shared_ptr spdlog::stderr_logger_st(const std::string& logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance()); +inline std::shared_ptr +spdlog::stderr_logger_st(const std::string &logger_name) { + return spdlog::details::registry::instance().create( + logger_name, spdlog::sinks::stderr_sink_st::instance()); } // // stdout/stderr color loggers // #ifdef _WIN32 -inline std::shared_ptr spdlog::stdout_color_mt(const std::string& logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stdout_color_mt(const std::string &logger_name) { + auto sink = std::make_shared(); + return spdlog::details::registry::instance().create(logger_name, sink); } -inline std::shared_ptr spdlog::stdout_color_st(const std::string& logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stdout_color_st(const std::string &logger_name) { + auto sink = std::make_shared(); + return spdlog::details::registry::instance().create(logger_name, sink); } -inline std::shared_ptr spdlog::stderr_color_mt(const std::string& logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stderr_color_mt(const std::string &logger_name) { + auto sink = std::make_shared(); + return spdlog::details::registry::instance().create(logger_name, sink); } - -inline std::shared_ptr spdlog::stderr_color_st(const std::string& logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stderr_color_st(const std::string &logger_name) { + auto sink = std::make_shared(); + return spdlog::details::registry::instance().create(logger_name, sink); } -#else //ansi terminal colors +#else // ansi terminal colors -inline std::shared_ptr spdlog::stdout_color_mt(const std::string& logger_name) -{ - auto sink = std::make_shared(spdlog::sinks::stdout_sink_mt::instance()); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stdout_color_mt(const std::string &logger_name) { + auto sink = std::make_shared( + spdlog::sinks::stdout_sink_mt::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); } -inline std::shared_ptr spdlog::stdout_color_st(const std::string& logger_name) -{ - auto sink = std::make_shared(spdlog::sinks::stdout_sink_st::instance()); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stdout_color_st(const std::string &logger_name) { + auto sink = std::make_shared( + spdlog::sinks::stdout_sink_st::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); } -inline std::shared_ptr spdlog::stderr_color_mt(const std::string& logger_name) -{ - auto sink = std::make_shared(spdlog::sinks::stderr_sink_mt::instance()); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stderr_color_mt(const std::string &logger_name) { + auto sink = std::make_shared( + spdlog::sinks::stderr_sink_mt::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); } -inline std::shared_ptr spdlog::stderr_color_st(const std::string& logger_name) -{ - auto sink = std::make_shared(spdlog::sinks::stderr_sink_st::instance()); - return spdlog::details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::stderr_color_st(const std::string &logger_name) { + auto sink = std::make_shared( + spdlog::sinks::stderr_sink_st::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); } #endif #ifdef SPDLOG_ENABLE_SYSLOG // Create syslog logger -inline std::shared_ptr spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option) -{ - return create(logger_name, syslog_ident, syslog_option); +inline std::shared_ptr +spdlog::syslog_logger(const std::string &logger_name, + const std::string &syslog_ident, int syslog_option) { + return create(logger_name, syslog_ident, + syslog_option); } #endif #ifdef __ANDROID__ -inline std::shared_ptr spdlog::android_logger(const std::string& logger_name, const std::string& tag) -{ - return create(logger_name, tag); +inline std::shared_ptr +spdlog::android_logger(const std::string &logger_name, const std::string &tag) { + return create(logger_name, tag); } #endif // Create and register a logger a single sink -inline std::shared_ptr spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink) -{ - return details::registry::instance().create(logger_name, sink); +inline std::shared_ptr +spdlog::create(const std::string &logger_name, const spdlog::sink_ptr &sink) { + return details::registry::instance().create(logger_name, sink); } -//Create logger with multiple sinks +// Create logger with multiple sinks -inline std::shared_ptr spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks) -{ - return details::registry::instance().create(logger_name, sinks); +inline std::shared_ptr +spdlog::create(const std::string &logger_name, spdlog::sinks_init_list sinks) { + return details::registry::instance().create(logger_name, sinks); } - template -inline std::shared_ptr spdlog::create(const std::string& logger_name, Args... args) -{ - sink_ptr sink = std::make_shared(args...); - return details::registry::instance().create(logger_name, { sink }); +inline std::shared_ptr +spdlog::create(const std::string &logger_name, Args... args) { + sink_ptr sink = std::make_shared(args...); + return details::registry::instance().create(logger_name, {sink}); } - -template -inline std::shared_ptr spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) -{ - return details::registry::instance().create(logger_name, sinks_begin, sinks_end); +template +inline std::shared_ptr +spdlog::create(const std::string &logger_name, const It &sinks_begin, + const It &sinks_end) { + return details::registry::instance().create(logger_name, sinks_begin, + sinks_end); } -inline void spdlog::set_formatter(spdlog::formatter_ptr f) -{ - details::registry::instance().formatter(f); +inline void spdlog::set_formatter(spdlog::formatter_ptr f) { + details::registry::instance().formatter(f); } -inline void spdlog::set_pattern(const std::string& format_string) -{ - return details::registry::instance().set_pattern(format_string); +inline void spdlog::set_pattern(const std::string &format_string) { + return details::registry::instance().set_pattern(format_string); } -inline void spdlog::set_level(level::level_enum log_level) -{ - return details::registry::instance().set_level(log_level); +inline void spdlog::set_level(level::level_enum log_level) { + return details::registry::instance().set_level(log_level); } -inline void spdlog::set_error_handler(log_err_handler handler) -{ - return details::registry::instance().set_error_handler(handler); +inline void spdlog::set_error_handler(log_err_handler handler) { + return details::registry::instance().set_error_handler(handler); } - -inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb) -{ - details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); +inline void +spdlog::set_async_mode(size_t queue_size, + const async_overflow_policy overflow_policy, + const std::function &worker_warmup_cb, + const std::chrono::milliseconds &flush_interval_ms, + const std::function &worker_teardown_cb) { + details::registry::instance().set_async_mode( + queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, + worker_teardown_cb); } -inline void spdlog::set_sync_mode() -{ - details::registry::instance().set_sync_mode(); +inline void spdlog::set_sync_mode() { + details::registry::instance().set_sync_mode(); } -inline void spdlog::apply_all(std::function)> fun) -{ - details::registry::instance().apply_all(fun); +inline void +spdlog::apply_all(std::function)> fun) { + details::registry::instance().apply_all(fun); } -inline void spdlog::drop_all() -{ - details::registry::instance().drop_all(); -} +inline void spdlog::drop_all() { details::registry::instance().drop_all(); } diff --git a/external/spdlog/fmt/bundled/format.cc b/external/spdlog/fmt/bundled/format.cc index 2bd774e..c55bbc8 100644 --- a/external/spdlog/fmt/bundled/format.cc +++ b/external/spdlog/fmt/bundled/format.cc @@ -34,39 +34,39 @@ #include #include #include -#include // for std::ptrdiff_t +#include // for std::ptrdiff_t #if defined(_WIN32) && defined(__MINGW32__) -# include +#include #endif #if FMT_USE_WINDOWS_H -# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX) -# include -# else -# define NOMINMAX -# include -# undef NOMINMAX -# endif +#if defined(NOMINMAX) || defined(FMT_WIN_MINMAX) +#include +#else +#define NOMINMAX +#include +#undef NOMINMAX +#endif #endif using fmt::internal::Arg; #if FMT_EXCEPTIONS -# define FMT_TRY try -# define FMT_CATCH(x) catch (x) +#define FMT_TRY try +#define FMT_CATCH(x) catch (x) #else -# define FMT_TRY if (true) -# define FMT_CATCH(x) if (false) +#define FMT_TRY if (true) +#define FMT_CATCH(x) if (false) #endif #ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant -# pragma warning(disable: 4702) // unreachable code +#pragma warning(push) +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4702) // unreachable code // Disable deprecation warning for strerror. The latter is not called but // MSVC fails to detect it. -# pragma warning(disable: 4996) +#pragma warning(disable : 4996) #endif // Dummy implementations of strerror_r and strerror_s called if corresponding @@ -87,8 +87,8 @@ FMT_FUNC SystemError::~SystemError() throw() {} namespace { #ifndef _MSC_VER -# define FMT_SNPRINTF snprintf -#else // _MSC_VER +#define FMT_SNPRINTF snprintf +#else // _MSC_VER inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) { va_list args; va_start(args, format); @@ -96,31 +96,27 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) { va_end(args); return result; } -# define FMT_SNPRINTF fmt_snprintf -#endif // _MSC_VER +#define FMT_SNPRINTF fmt_snprintf +#endif // _MSC_VER #if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) -# define FMT_SWPRINTF snwprintf +#define FMT_SWPRINTF snwprintf #else -# define FMT_SWPRINTF swprintf +#define FMT_SWPRINTF swprintf #endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) // Checks if a value fits in int - used to avoid warnings about comparing // signed and unsigned integers. -template -struct IntChecker { - template - static bool fits_in_int(T value) { +template struct IntChecker { + template static bool fits_in_int(T value) { unsigned max = INT_MAX; return value <= max; } static bool fits_in_int(bool) { return true; } }; -template <> -struct IntChecker { - template - static bool fits_in_int(T value) { +template <> struct IntChecker { + template static bool fits_in_int(T value) { return value >= INT_MIN && value <= INT_MAX; } static bool fits_in_int(int) { return true; } @@ -139,12 +135,12 @@ typedef void (*FormatFunc)(Writer &, int, StringRef); // ERANGE - buffer is not large enough to store the error message // other - failure // Buffer should be at least of size 1. -int safe_strerror( - int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { +int safe_strerror(int error_code, char *&buffer, + std::size_t buffer_size) FMT_NOEXCEPT { FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer"); class StrError { - private: + private: int error_code_; char *&buffer_; std::size_t buffer_size_; @@ -175,8 +171,8 @@ int safe_strerror( // Fallback to strerror_s when strerror_r is not available. int fallback(int result) { // If the buffer is full then the message is probably truncated. - return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? - ERANGE : result; + return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? ERANGE + : result; } // Fallback to strerror if strerror_r and strerror_s are not available. @@ -186,12 +182,12 @@ int safe_strerror( return errno; } - public: + public: StrError(int err_code, char *&buf, std::size_t buf_size) - : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} + : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} int run() { - strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r. + strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r. return handle(strerror_r(error_code_, buffer_, buffer_size_)); } }; @@ -233,28 +229,26 @@ void report_error(FormatFunc func, int error_code, // IsZeroInt::visit(arg) returns true iff arg is a zero integer. class IsZeroInt : public ArgVisitor { - public: - template - bool visit_any_int(T value) { return value == 0; } +public: + template bool visit_any_int(T value) { return value == 0; } }; // Checks if an argument is a valid printf width specifier and sets // left alignment if it is negative. class WidthHandler : public ArgVisitor { - private: +private: FormatSpec &spec_; FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); - public: +public: explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} void report_unhandled_arg() { FMT_THROW(FormatError("width is not integer")); } - template - unsigned visit_any_int(T value) { + template unsigned visit_any_int(T value) { typedef typename internal::IntTraits::MainType UnsignedType; UnsignedType width = static_cast(value); if (internal::is_negative(value)) { @@ -268,26 +262,23 @@ class WidthHandler : public ArgVisitor { }; class PrecisionHandler : public ArgVisitor { - public: +public: void report_unhandled_arg() { FMT_THROW(FormatError("precision is not integer")); } - template - int visit_any_int(T value) { + template int visit_any_int(T value) { if (!IntChecker::is_signed>::fits_in_int(value)) FMT_THROW(FormatError("number is too big")); return static_cast(value); } }; -template -struct is_same { +template struct is_same { enum { value = 0 }; }; -template -struct is_same { +template struct is_same { enum { value = 1 }; }; @@ -297,27 +288,25 @@ struct is_same { // 'd' and 'i' - signed, other - unsigned) template class ArgConverter : public ArgVisitor, void> { - private: +private: internal::Arg &arg_; wchar_t type_; FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); - public: - ArgConverter(internal::Arg &arg, wchar_t type) - : arg_(arg), type_(type) {} +public: + ArgConverter(internal::Arg &arg, wchar_t type) : arg_(arg), type_(type) {} void visit_bool(bool value) { if (type_ != 's') visit_any_int(value); } - template - void visit_any_int(U value) { + template void visit_any_int(U value) { bool is_signed = type_ == 'd' || type_ == 'i'; using internal::Arg; - typedef typename internal::Conditional< - is_same::value, U, T>::type TargetType; + typedef typename internal::Conditional::value, U, T>::type + TargetType; if (sizeof(TargetType) <= sizeof(int)) { // Extra casts are used to silence warnings. if (is_signed) { @@ -346,27 +335,26 @@ class ArgConverter : public ArgVisitor, void> { // Converts an integer argument to char for printf. class CharConverter : public ArgVisitor { - private: +private: internal::Arg &arg_; FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); - public: +public: explicit CharConverter(internal::Arg &arg) : arg_(arg) {} - template - void visit_any_int(T value) { + template void visit_any_int(T value) { arg_.type = internal::Arg::CHAR; arg_.int_value = static_cast(value); } }; -} // namespace +} // namespace namespace internal { template -class PrintfArgFormatter : - public ArgFormatterBase, Char> { +class PrintfArgFormatter + : public ArgFormatterBase, Char> { void write_null_pointer() { this->spec().type_ = 0; @@ -375,9 +363,9 @@ class PrintfArgFormatter : typedef ArgFormatterBase, Char> Base; - public: +public: PrintfArgFormatter(BasicWriter &w, FormatSpec &s) - : ArgFormatterBase, Char>(w, s) {} + : ArgFormatterBase, Char>(w, s) {} void visit_bool(bool value) { FormatSpec &fmt_spec = this->spec(); @@ -432,11 +420,11 @@ class PrintfArgFormatter : c.format(&formatter, c.value, &format); } }; -} // namespace internal -} // namespace fmt +} // namespace internal +} // namespace fmt -FMT_FUNC void fmt::SystemError::init( - int err_code, CStringRef format_str, ArgList args) { +FMT_FUNC void fmt::SystemError::init(int err_code, CStringRef format_str, + ArgList args) { error_code_ = err_code; MemoryWriter w; internal::format_system_error(w, err_code, format(format_str, args)); @@ -445,31 +433,33 @@ FMT_FUNC void fmt::SystemError::init( } template -int fmt::internal::CharTraits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, T value) { +int fmt::internal::CharTraits::format_float(char *buffer, + std::size_t size, + const char *format, + unsigned width, int precision, + T value) { if (width == 0) { - return precision < 0 ? - FMT_SNPRINTF(buffer, size, format, value) : - FMT_SNPRINTF(buffer, size, format, precision, value); + return precision < 0 ? FMT_SNPRINTF(buffer, size, format, value) + : FMT_SNPRINTF(buffer, size, format, precision, value); } - return precision < 0 ? - FMT_SNPRINTF(buffer, size, format, width, value) : - FMT_SNPRINTF(buffer, size, format, width, precision, value); + return precision < 0 + ? FMT_SNPRINTF(buffer, size, format, width, value) + : FMT_SNPRINTF(buffer, size, format, width, precision, value); } template -int fmt::internal::CharTraits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, T value) { +int fmt::internal::CharTraits::format_float(wchar_t *buffer, + std::size_t size, + const wchar_t *format, + unsigned width, + int precision, T value) { if (width == 0) { - return precision < 0 ? - FMT_SWPRINTF(buffer, size, format, value) : - FMT_SWPRINTF(buffer, size, format, precision, value); + return precision < 0 ? FMT_SWPRINTF(buffer, size, format, value) + : FMT_SWPRINTF(buffer, size, format, precision, value); } - return precision < 0 ? - FMT_SWPRINTF(buffer, size, format, width, value) : - FMT_SWPRINTF(buffer, size, format, width, precision, value); + return precision < 0 + ? FMT_SWPRINTF(buffer, size, format, width, value) + : FMT_SWPRINTF(buffer, size, format, width, precision, value); } template @@ -480,31 +470,21 @@ const char fmt::internal::BasicData::DIGITS[] = "6061626364656667686970717273747576777879" "8081828384858687888990919293949596979899"; -#define FMT_POWERS_OF_10(factor) \ - factor * 10, \ - factor * 100, \ - factor * 1000, \ - factor * 10000, \ - factor * 100000, \ - factor * 1000000, \ - factor * 10000000, \ - factor * 100000000, \ - factor * 1000000000 +#define FMT_POWERS_OF_10(factor) \ + factor * 10, factor * 100, factor * 1000, factor * 10000, factor * 100000, \ + factor * 1000000, factor * 10000000, factor * 100000000, \ + factor * 1000000000 template const uint32_t fmt::internal::BasicData::POWERS_OF_10_32[] = { - 0, FMT_POWERS_OF_10(1) -}; + 0, FMT_POWERS_OF_10(1)}; template const uint64_t fmt::internal::BasicData::POWERS_OF_10_64[] = { - 0, - FMT_POWERS_OF_10(1), - FMT_POWERS_OF_10(fmt::ULongLong(1000000000)), - // Multiply several constants instead of using a single long long constant - // to avoid warnings about C++98 not supporting long long. - fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10 -}; + 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(fmt::ULongLong(1000000000)), + // Multiply several constants instead of using a single long long constant + // to avoid warnings about C++98 not supporting long long. + fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10}; FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { (void)type; @@ -512,9 +492,9 @@ FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { FMT_THROW(fmt::FormatError( fmt::format("unknown format code '{}' for {}", code, type))); } - FMT_THROW(fmt::FormatError( - fmt::format("unknown format code '\\x{:02x}' for {}", - static_cast(code), type))); + FMT_THROW( + fmt::FormatError(fmt::format("unknown format code '\\x{:02x}' for {}", + static_cast(code), type))); } #if FMT_USE_WINDOWS_H @@ -524,13 +504,13 @@ FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { if (s.size() > INT_MAX) FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG)); int s_size = static_cast(s.size()); - int length = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0); + int length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), + s_size, 0, 0); if (length == 0) FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); buffer_.resize(length + 1); - length = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length); + length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, + &buffer_[0], length); if (length == 0) FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); buffer_[length] = 0; @@ -538,8 +518,8 @@ FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) { if (int error_code = convert(s)) { - FMT_THROW(WindowsError(error_code, - "cannot convert string from UTF-16 to UTF-8")); + FMT_THROW( + WindowsError(error_code, "cannot convert string from UTF-16 to UTF-8")); } } @@ -551,16 +531,16 @@ FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { if (length == 0) return GetLastError(); buffer_.resize(length + 1); - length = WideCharToMultiByte( - CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0); + length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, &buffer_[0], + length, 0, 0); if (length == 0) return GetLastError(); buffer_[length] = 0; return 0; } -FMT_FUNC void fmt::WindowsError::init( - int err_code, CStringRef format_str, ArgList args) { +FMT_FUNC void fmt::WindowsError::init(int err_code, CStringRef format_str, + ArgList args) { error_code_ = err_code; MemoryWriter w; internal::format_windows_error(w, err_code, format(format_str, args)); @@ -568,17 +548,18 @@ FMT_FUNC void fmt::WindowsError::init( base = std::runtime_error(w.str()); } -FMT_FUNC void fmt::internal::format_windows_error( - fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT { +FMT_FUNC void +fmt::internal::format_windows_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { FMT_TRY { MemoryBuffer buffer; buffer.resize(INLINE_BUFFER_SIZE); for (;;) { wchar_t *system_message = &buffer[0]; - int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - system_message, static_cast(buffer.size()), 0); + int result = FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, + error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), system_message, + static_cast(buffer.size()), 0); if (result != 0) { UTF16ToUTF8 utf8_message; if (utf8_message.convert(system_message) == ERROR_SUCCESS) { @@ -588,18 +569,19 @@ FMT_FUNC void fmt::internal::format_windows_error( break; } if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - break; // Can't get error message, report error code instead. + break; // Can't get error message, report error code instead. buffer.resize(buffer.size() * 2); } - } FMT_CATCH(...) {} - fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. + } + FMT_CATCH(...) {} + fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. } -#endif // FMT_USE_WINDOWS_H +#endif // FMT_USE_WINDOWS_H -FMT_FUNC void fmt::internal::format_system_error( - fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT { +FMT_FUNC void +fmt::internal::format_system_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { FMT_TRY { MemoryBuffer buffer; buffer.resize(INLINE_BUFFER_SIZE); @@ -611,11 +593,12 @@ FMT_FUNC void fmt::internal::format_system_error( return; } if (result != ERANGE) - break; // Can't get error message, report error code instead. + break; // Can't get error message, report error code instead. buffer.resize(buffer.size() * 2); } - } FMT_CATCH(...) {} - fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. + } + FMT_CATCH(...) {} + fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. } template @@ -627,17 +610,17 @@ void fmt::internal::ArgMap::init(const ArgList &args) { bool use_values = args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE; if (use_values) { - for (unsigned i = 0;/*nothing*/; ++i) { + for (unsigned i = 0; /*nothing*/; ++i) { internal::Arg::Type arg_type = args.type(i); switch (arg_type) { case internal::Arg::NONE: return; case internal::Arg::NAMED_ARG: - named_arg = static_cast(args.values_[i].pointer); + named_arg = static_cast(args.values_[i].pointer); map_.push_back(Pair(named_arg->name, *named_arg)); break; default: - /*nothing*/; + /*nothing*/; } } return; @@ -645,20 +628,20 @@ void fmt::internal::ArgMap::init(const ArgList &args) { for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) { internal::Arg::Type arg_type = args.type(i); if (arg_type == internal::Arg::NAMED_ARG) { - named_arg = static_cast(args.args_[i].pointer); + named_arg = static_cast(args.args_[i].pointer); map_.push_back(Pair(named_arg->name, *named_arg)); } } - for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) { + for (unsigned i = ArgList::MAX_PACKED_ARGS; /*nothing*/; ++i) { switch (args.args_[i].type) { case internal::Arg::NONE: return; case internal::Arg::NAMED_ARG: - named_arg = static_cast(args.args_[i].pointer); + named_arg = static_cast(args.args_[i].pointer); map_.push_back(Pair(named_arg->name, *named_arg)); break; default: - /*nothing*/; + /*nothing*/; } } } @@ -668,71 +651,72 @@ void fmt::internal::FixedBuffer::grow(std::size_t) { FMT_THROW(std::runtime_error("buffer overflow")); } -FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg( - unsigned arg_index, const char *&error) { +FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(unsigned arg_index, + const char *&error) { Arg arg = args_[arg_index]; switch (arg.type) { case Arg::NONE: error = "argument index out of range"; break; case Arg::NAMED_ARG: - arg = *static_cast(arg.pointer); + arg = *static_cast(arg.pointer); break; default: - /*nothing*/; + /*nothing*/; } return arg; } template -void fmt::internal::PrintfFormatter::parse_flags( - FormatSpec &spec, const Char *&s) { +void fmt::internal::PrintfFormatter::parse_flags(FormatSpec &spec, + const Char *&s) { for (;;) { switch (*s++) { - case '-': - spec.align_ = ALIGN_LEFT; - break; - case '+': - spec.flags_ |= SIGN_FLAG | PLUS_FLAG; - break; - case '0': - spec.fill_ = '0'; - break; - case ' ': - spec.flags_ |= SIGN_FLAG; - break; - case '#': - spec.flags_ |= HASH_FLAG; - break; - default: - --s; - return; + case '-': + spec.align_ = ALIGN_LEFT; + break; + case '+': + spec.flags_ |= SIGN_FLAG | PLUS_FLAG; + break; + case '0': + spec.fill_ = '0'; + break; + case ' ': + spec.flags_ |= SIGN_FLAG; + break; + case '#': + spec.flags_ |= HASH_FLAG; + break; + default: + --s; + return; } } } template -Arg fmt::internal::PrintfFormatter::get_arg( - const Char *s, unsigned arg_index) { +Arg fmt::internal::PrintfFormatter::get_arg(const Char *s, + unsigned arg_index) { (void)s; const char *error = 0; - Arg arg = arg_index == UINT_MAX ? - next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); + Arg arg = arg_index == UINT_MAX + ? next_arg(error) + : FormatterBase::get_arg(arg_index - 1, error); if (error) FMT_THROW(FormatError(!*s ? "invalid format string" : error)); return arg; } template -unsigned fmt::internal::PrintfFormatter::parse_header( - const Char *&s, FormatSpec &spec) { +unsigned fmt::internal::PrintfFormatter::parse_header(const Char *&s, + FormatSpec &spec) { unsigned arg_index = UINT_MAX; Char c = *s; if (c >= '0' && c <= '9') { // Parse an argument index (if followed by '$') or a width possibly // preceded with '0' flag(s). unsigned value = parse_nonnegative_int(s); - if (*s == '$') { // value is an argument index + if (*s == '$') { // value is an argument index ++s; arg_index = value; } else { @@ -764,7 +748,8 @@ void fmt::internal::PrintfFormatter::format( const Char *s = start; while (*s) { Char c = *s++; - if (c != '%') continue; + if (c != '%') + continue; if (*s == c) { write(writer, start, s); start = ++s; @@ -796,7 +781,7 @@ void fmt::internal::PrintfFormatter::format( if (arg.type <= Arg::LAST_NUMERIC_TYPE) spec.align_ = ALIGN_NUMERIC; else - spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. + spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. } // Parse length and convert the argument to the required type. @@ -838,7 +823,8 @@ void fmt::internal::PrintfFormatter::format( if (arg.type <= Arg::LAST_INTEGER_TYPE) { // Normalize type. switch (spec.type_) { - case 'i': case 'u': + case 'i': + case 'u': spec.type_ = 'd'; break; case 'c': @@ -856,15 +842,15 @@ void fmt::internal::PrintfFormatter::format( write(writer, start, s); } -FMT_FUNC void fmt::report_system_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { +FMT_FUNC void fmt::report_system_error(int error_code, + fmt::StringRef message) FMT_NOEXCEPT { // 'fmt::' is for bcc32. fmt::report_error(internal::format_system_error, error_code, message); } #if FMT_USE_WINDOWS_H -FMT_FUNC void fmt::report_windows_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { +FMT_FUNC void fmt::report_windows_error(int error_code, + fmt::StringRef message) FMT_NOEXCEPT { // 'fmt::' is for bcc32. fmt::report_error(internal::format_windows_error, error_code, message); } @@ -905,16 +891,17 @@ template void fmt::internal::FixedBuffer::grow(std::size_t); template void fmt::internal::ArgMap::init(const fmt::ArgList &args); -template void fmt::internal::PrintfFormatter::format( - BasicWriter &writer, CStringRef format); +template void +fmt::internal::PrintfFormatter::format(BasicWriter &writer, + CStringRef format); template int fmt::internal::CharTraits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, double value); + char *buffer, std::size_t size, const char *format, unsigned width, + int precision, double value); template int fmt::internal::CharTraits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, long double value); + char *buffer, std::size_t size, const char *format, unsigned width, + int precision, long double value); // Explicit instantiations for wchar_t. @@ -922,19 +909,20 @@ template void fmt::internal::FixedBuffer::grow(std::size_t); template void fmt::internal::ArgMap::init(const fmt::ArgList &args); -template void fmt::internal::PrintfFormatter::format( - BasicWriter &writer, WCStringRef format); +template void +fmt::internal::PrintfFormatter::format(BasicWriter &writer, + WCStringRef format); template int fmt::internal::CharTraits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, double value); + wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, + int precision, double value); template int fmt::internal::CharTraits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, long double value); + wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, + int precision, long double value); -#endif // FMT_HEADER_ONLY +#endif // FMT_HEADER_ONLY #ifdef _MSC_VER -# pragma warning(pop) +#pragma warning(pop) #endif diff --git a/external/spdlog/fmt/bundled/format.h b/external/spdlog/fmt/bundled/format.h index f8ce147..e03b41b 100644 --- a/external/spdlog/fmt/bundled/format.h +++ b/external/spdlog/fmt/bundled/format.h @@ -37,191 +37,188 @@ #include #include #include -#include #include +#include #ifdef _SECURE_SCL -# define FMT_SECURE_SCL _SECURE_SCL +#define FMT_SECURE_SCL _SECURE_SCL #else -# define FMT_SECURE_SCL 0 +#define FMT_SECURE_SCL 0 #endif #if FMT_SECURE_SCL -# include +#include #endif #ifdef _MSC_VER -# define FMT_MSC_VER _MSC_VER +#define FMT_MSC_VER _MSC_VER #else -# define FMT_MSC_VER 0 +#define FMT_MSC_VER 0 #endif #if FMT_MSC_VER && FMT_MSC_VER <= 1500 typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; -typedef __int64 intmax_t; +typedef __int64 intmax_t; #else #include #endif #if !defined(FMT_HEADER_ONLY) && defined(_WIN32) -# ifdef FMT_EXPORT -# define FMT_API __declspec(dllexport) -# elif defined(FMT_SHARED) -# define FMT_API __declspec(dllimport) -# endif +#ifdef FMT_EXPORT +#define FMT_API __declspec(dllexport) +#elif defined(FMT_SHARED) +#define FMT_API __declspec(dllimport) +#endif #endif #ifndef FMT_API -# define FMT_API +#define FMT_API #endif #ifdef __GNUC__ -# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -# define FMT_GCC_EXTENSION __extension__ -# if FMT_GCC_VERSION >= 406 -# pragma GCC diagnostic push +#define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#define FMT_GCC_EXTENSION __extension__ +#if FMT_GCC_VERSION >= 406 +#pragma GCC diagnostic push // Disable the warning about "long long" which is sometimes reported even // when using __extension__. -# pragma GCC diagnostic ignored "-Wlong-long" +#pragma GCC diagnostic ignored "-Wlong-long" // Disable the warning about declaration shadowing because it affects too // many valid cases. -# pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wshadow" // Disable the warning about implicit conversions that may change the sign of // an integer; silencing it otherwise would require many explicit casts. -# pragma GCC diagnostic ignored "-Wsign-conversion" -# endif -# if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__ -# define FMT_HAS_GXX_CXX11 1 -# endif +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif +#if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__ +#define FMT_HAS_GXX_CXX11 1 +#endif #else -# define FMT_GCC_EXTENSION +#define FMT_GCC_EXTENSION #endif #if defined(__INTEL_COMPILER) -# define FMT_ICC_VERSION __INTEL_COMPILER +#define FMT_ICC_VERSION __INTEL_COMPILER #elif defined(__ICL) -# define FMT_ICC_VERSION __ICL +#define FMT_ICC_VERSION __ICL #endif #if defined(__clang__) && !defined(FMT_ICC_VERSION) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdocumentation-unknown-command" -# pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#pragma clang diagnostic ignored "-Wpadded" #endif #ifdef __GNUC_LIBSTD__ -# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__) +#define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__) #endif #ifdef __has_feature -# define FMT_HAS_FEATURE(x) __has_feature(x) +#define FMT_HAS_FEATURE(x) __has_feature(x) #else -# define FMT_HAS_FEATURE(x) 0 +#define FMT_HAS_FEATURE(x) 0 #endif #ifdef __has_builtin -# define FMT_HAS_BUILTIN(x) __has_builtin(x) +#define FMT_HAS_BUILTIN(x) __has_builtin(x) #else -# define FMT_HAS_BUILTIN(x) 0 +#define FMT_HAS_BUILTIN(x) 0 #endif #ifdef __has_cpp_attribute -# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else -# define FMT_HAS_CPP_ATTRIBUTE(x) 0 +#define FMT_HAS_CPP_ATTRIBUTE(x) 0 #endif #ifndef FMT_USE_VARIADIC_TEMPLATES // Variadic templates are available in GCC since version 4.4 // (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++ // since version 2013. -# define FMT_USE_VARIADIC_TEMPLATES \ - (FMT_HAS_FEATURE(cxx_variadic_templates) || \ - (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800) +#define FMT_USE_VARIADIC_TEMPLATES \ + (FMT_HAS_FEATURE(cxx_variadic_templates) || \ + (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800) #endif #ifndef FMT_USE_RVALUE_REFERENCES // Don't use rvalue references when compiling with clang and an old libstdc++ // as the latter doesn't provide std::move. -# if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402 -# define FMT_USE_RVALUE_REFERENCES 0 -# else -# define FMT_USE_RVALUE_REFERENCES \ - (FMT_HAS_FEATURE(cxx_rvalue_references) || \ - (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600) -# endif +#if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402 +#define FMT_USE_RVALUE_REFERENCES 0 +#else +#define FMT_USE_RVALUE_REFERENCES \ + (FMT_HAS_FEATURE(cxx_rvalue_references) || \ + (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600) +#endif #endif #if FMT_USE_RVALUE_REFERENCES -# include // for std::move +#include // for std::move #endif // Check if exceptions are disabled. #if defined(__GNUC__) && !defined(__EXCEPTIONS) -# define FMT_EXCEPTIONS 0 +#define FMT_EXCEPTIONS 0 #endif #if FMT_MSC_VER && !_HAS_EXCEPTIONS -# define FMT_EXCEPTIONS 0 +#define FMT_EXCEPTIONS 0 #endif #ifndef FMT_EXCEPTIONS -# define FMT_EXCEPTIONS 1 +#define FMT_EXCEPTIONS 1 #endif #ifndef FMT_THROW -# if FMT_EXCEPTIONS -# define FMT_THROW(x) throw x -# else -# define FMT_THROW(x) assert(false) -# endif +#if FMT_EXCEPTIONS +#define FMT_THROW(x) throw x +#else +#define FMT_THROW(x) assert(false) +#endif #endif // Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). #ifndef FMT_USE_NOEXCEPT -# define FMT_USE_NOEXCEPT 0 +#define FMT_USE_NOEXCEPT 0 #endif #ifndef FMT_NOEXCEPT -# if FMT_EXCEPTIONS -# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ - (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - FMT_MSC_VER >= 1900 -# define FMT_NOEXCEPT noexcept -# else -# define FMT_NOEXCEPT throw() -# endif -# else -# define FMT_NOEXCEPT -# endif +#if FMT_EXCEPTIONS +#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 +#define FMT_NOEXCEPT noexcept +#else +#define FMT_NOEXCEPT throw() +#endif +#else +#define FMT_NOEXCEPT +#endif #endif #ifndef FMT_OVERRIDE -# if FMT_USE_OVERRIDE || FMT_HAS_FEATURE(cxx_override) || \ - (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - FMT_MSC_VER >= 1900 -# define FMT_OVERRIDE override -# else -# define FMT_OVERRIDE -# endif +#if FMT_USE_OVERRIDE || FMT_HAS_FEATURE(cxx_override) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 +#define FMT_OVERRIDE override +#else +#define FMT_OVERRIDE +#endif #endif - // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #ifndef FMT_USE_DELETED_FUNCTIONS -# define FMT_USE_DELETED_FUNCTIONS 0 +#define FMT_USE_DELETED_FUNCTIONS 0 #endif -#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \ - (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800 -# define FMT_DELETED_OR_UNDEFINED = delete -# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&) = delete; \ - TypeName& operator=(const TypeName&) = delete +#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \ + (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800 +#define FMT_DELETED_OR_UNDEFINED = delete +#define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName &) = delete; \ + TypeName &operator=(const TypeName &) = delete #else -# define FMT_DELETED_OR_UNDEFINED -# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - TypeName& operator=(const TypeName&) +#define FMT_DELETED_OR_UNDEFINED +#define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName &); \ + TypeName &operator=(const TypeName &) #endif #ifndef FMT_USE_USER_DEFINED_LITERALS @@ -229,23 +226,24 @@ typedef __int64 intmax_t; // makes the fmt::literals implementation easier. However, an explicit check // for variadic templates is added here just in case. // For Intel's compiler both it and the system gcc/msc must support UDLs. -# define FMT_USE_USER_DEFINED_LITERALS \ - FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \ - (FMT_HAS_FEATURE(cxx_user_literals) || \ - (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \ - (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500) +#define FMT_USE_USER_DEFINED_LITERALS \ + FMT_USE_VARIADIC_TEMPLATES &&FMT_USE_RVALUE_REFERENCES && \ + (FMT_HAS_FEATURE(cxx_user_literals) || \ + (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || \ + FMT_MSC_VER >= 1900) && \ + (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500) #endif #ifndef FMT_ASSERT -# define FMT_ASSERT(condition, message) assert((condition) && message) +#define FMT_ASSERT(condition, message) assert((condition) && message) #endif #if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) -# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +#define FMT_BUILTIN_CLZ(n) __builtin_clz(n) #endif #if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll) -# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +#define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) #endif // Some compilers masquerade as both MSVC and GCC-likes or @@ -253,11 +251,11 @@ typedef __int64 intmax_t; // only define FMT_BUILTIN_CLZ using the MSVC intrinsics // if the clz and clzll builtins are not available. #if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) -# include // _BitScanReverse, _BitScanReverse64 +#include // _BitScanReverse, _BitScanReverse64 namespace fmt { namespace internal { -# pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanReverse) inline uint32_t clz(uint32_t x) { unsigned long r = 0; _BitScanReverse(&r, x); @@ -266,38 +264,38 @@ inline uint32_t clz(uint32_t x) { // Static analysis complains about using uninitialized data // "r", but the only way that can happen is if "x" is 0, // which the callers guarantee to not happen. -# pragma warning(suppress: 6102) +#pragma warning(suppress : 6102) return 31 - r; } -# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n) +#define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n) -# ifdef _WIN64 -# pragma intrinsic(_BitScanReverse64) -# endif +#ifdef _WIN64 +#pragma intrinsic(_BitScanReverse64) +#endif inline uint32_t clzll(uint64_t x) { unsigned long r = 0; -# ifdef _WIN64 +#ifdef _WIN64 _BitScanReverse64(&r, x); -# else +#else // Scan the high 32 bits. if (_BitScanReverse(&r, static_cast(x >> 32))) return 63 - (r + 32); // Scan the low 32 bits. _BitScanReverse(&r, static_cast(x)); -# endif +#endif assert(x != 0); // Static analysis complains about using uninitialized data // "r", but the only way that can happen is if "x" is 0, // which the callers guarantee to not happen. -# pragma warning(suppress: 6102) +#pragma warning(suppress : 6102) return 63 - r; } -# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n) -} -} +#define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n) +} // namespace internal +} // namespace fmt #endif namespace fmt { @@ -319,10 +317,9 @@ inline DummyInt _isnan(...) { return DummyInt(); } // A helper function to suppress bogus "conditional expression is constant" // warnings. -template -inline T const_check(T value) { return value; } -} -} // namespace fmt +template inline T const_check(T value) { return value; } +} // namespace internal +} // namespace fmt namespace std { // Standard permits specialization of std::numeric_limits. This specialization @@ -330,12 +327,11 @@ namespace std { // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891 // and the same for isnan and signbit. template <> -class numeric_limits : - public std::numeric_limits { - public: +class numeric_limits + : public std::numeric_limits { +public: // Portable version of isinf. - template - static bool isinfinity(T x) { + template static bool isinfinity(T x) { using namespace fmt::internal; // The resolution "priority" is: // isinf macro > std::isinf > ::isinf > fmt::internal::isinf @@ -347,8 +343,7 @@ class numeric_limits : } // Portable version of isnan. - template - static bool isnotanumber(T x) { + template static bool isnotanumber(T x) { using namespace fmt::internal; if (const_check(sizeof(isnan(x)) == sizeof(bool) || sizeof(isnan(x)) == sizeof(int))) { @@ -362,15 +357,17 @@ class numeric_limits : using namespace fmt::internal; if (const_check(sizeof(signbit(x)) == sizeof(int))) return signbit(x) != 0; - if (x < 0) return true; - if (!isnotanumber(x)) return false; + if (x < 0) + return true; + if (!isnotanumber(x)) + return false; int dec = 0, sign = 0; - char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail. + char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail. _ecvt_s(buffer, sizeof(buffer), x, 0, &dec, &sign); return sign != 0; } }; -} // namespace std +} // namespace std namespace fmt { @@ -383,17 +380,15 @@ FMT_GCC_EXTENSION typedef unsigned long long ULongLong; using std::move; #endif -template -class BasicWriter; +template class BasicWriter; typedef BasicWriter Writer; typedef BasicWriter WWriter; -template -class ArgFormatter; +template class ArgFormatter; template > + typename ArgFormatter = fmt::ArgFormatter> class BasicFormatter; /** @@ -420,13 +415,12 @@ class BasicFormatter; format(std::string("{}"), 42); \endrst */ -template -class BasicStringRef { - private: +template class BasicStringRef { +private: const Char *data_; std::size_t size_; - public: +public: /** Constructs a string reference object from a C string and a size. */ BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {} @@ -437,7 +431,7 @@ class BasicStringRef { \endrst */ BasicStringRef(const Char *s) - : data_(s), size_(std::char_traits::length(s)) {} + : data_(s), size_(std::char_traits::length(s)) {} /** \rst @@ -445,7 +439,7 @@ class BasicStringRef { \endrst */ BasicStringRef(const std::basic_string &s) - : data_(s.c_str()), size_(s.size()) {} + : data_(s.c_str()), size_(s.size()) {} /** \rst @@ -519,12 +513,11 @@ typedef BasicStringRef WStringRef; format(std::string("{}"), 42); \endrst */ -template -class BasicCStringRef { - private: +template class BasicCStringRef { +private: const Char *data_; - public: +public: /** Constructs a string reference object from a C string. */ BasicCStringRef(const Char *s) : data_(s) {} @@ -544,21 +537,19 @@ typedef BasicCStringRef WCStringRef; /** A formatting error such as invalid format string. */ class FormatError : public std::runtime_error { - public: +public: explicit FormatError(CStringRef message) - : std::runtime_error(message.c_str()) {} + : std::runtime_error(message.c_str()) {} ~FormatError() throw(); }; namespace internal { // MakeUnsigned::Type gives an unsigned type corresponding to integer type T. -template -struct MakeUnsigned { typedef T Type; }; +template struct MakeUnsigned { typedef T Type; }; -#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \ - template <> \ - struct MakeUnsigned { typedef U Type; } +#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \ + template <> struct MakeUnsigned { typedef U Type; } FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char); FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char); @@ -581,32 +572,30 @@ enum { INLINE_BUFFER_SIZE = 500 }; #if FMT_SECURE_SCL // Use checked iterator to avoid warnings on MSVC. template -inline stdext::checked_array_iterator make_ptr(T *ptr, std::size_t size) { - return stdext::checked_array_iterator(ptr, size); +inline stdext::checked_array_iterator make_ptr(T *ptr, std::size_t size) { + return stdext::checked_array_iterator(ptr, size); } #else -template -inline T *make_ptr(T *ptr, std::size_t) { return ptr; } +template inline T *make_ptr(T *ptr, std::size_t) { return ptr; } #endif -} // namespace internal +} // namespace internal /** \rst A buffer supporting a subset of ``std::vector``'s operations. \endrst */ -template -class Buffer { - private: +template class Buffer { +private: FMT_DISALLOW_COPY_AND_ASSIGN(Buffer); - protected: +protected: T *ptr_; std::size_t size_; std::size_t capacity_; Buffer(T *ptr = 0, std::size_t capacity = 0) - : ptr_(ptr), size_(0), capacity_(capacity) {} + : ptr_(ptr), size_(0), capacity_(capacity) {} /** \rst @@ -616,7 +605,7 @@ class Buffer { */ virtual void grow(std::size_t size) = 0; - public: +public: virtual ~Buffer() {} /** Returns the size of this buffer. */ @@ -653,8 +642,7 @@ class Buffer { } /** Appends data to the end of the buffer. */ - template - void append(const U *begin, const U *end); + template void append(const U *begin, const U *end); T &operator[](std::size_t index) { return ptr_[index]; } const T &operator[](std::size_t index) const { return ptr_[index]; } @@ -675,26 +663,27 @@ namespace internal { // A memory buffer for trivially copyable/constructible types with the first // SIZE elements stored in the object itself. -template > +template > class MemoryBuffer : private Allocator, public Buffer { - private: +private: T data_[SIZE]; // Deallocate memory allocated by the buffer. void deallocate() { - if (this->ptr_ != data_) Allocator::deallocate(this->ptr_, this->capacity_); + if (this->ptr_ != data_) + Allocator::deallocate(this->ptr_, this->capacity_); } - protected: +protected: void grow(std::size_t size) FMT_OVERRIDE; - public: +public: explicit MemoryBuffer(const Allocator &alloc = Allocator()) : Allocator(alloc), Buffer(data_, SIZE) {} ~MemoryBuffer() { deallocate(); } #if FMT_USE_RVALUE_REFERENCES - private: +private: // Move data from other to this buffer. void move(MemoryBuffer &other) { Allocator &this_alloc = *this, &other_alloc = other; @@ -713,10 +702,8 @@ class MemoryBuffer : private Allocator, public Buffer { } } - public: - MemoryBuffer(MemoryBuffer &&other) { - move(other); - } +public: + MemoryBuffer(MemoryBuffer &&other) { move(other); } MemoryBuffer &operator=(MemoryBuffer &&other) { assert(this != &other); @@ -734,7 +721,7 @@ template void MemoryBuffer::grow(std::size_t size) { std::size_t new_capacity = this->capacity_ + this->capacity_ / 2; if (size > new_capacity) - new_capacity = size; + new_capacity = size; T *new_ptr = this->allocate(new_capacity); // The following code doesn't throw, so the raw pointer above doesn't leak. std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_, @@ -751,96 +738,84 @@ void MemoryBuffer::grow(std::size_t size) { } // A fixed-size buffer. -template -class FixedBuffer : public fmt::Buffer { - public: +template class FixedBuffer : public fmt::Buffer { +public: FixedBuffer(Char *array, std::size_t size) : fmt::Buffer(array, size) {} - protected: +protected: FMT_API void grow(std::size_t size); }; -template -class BasicCharTraits { - public: +template class BasicCharTraits { +public: #if FMT_SECURE_SCL - typedef stdext::checked_array_iterator CharPtr; + typedef stdext::checked_array_iterator CharPtr; #else typedef Char *CharPtr; #endif static Char cast(int value) { return static_cast(value); } }; -template -class CharTraits; +template class CharTraits; -template <> -class CharTraits : public BasicCharTraits { - private: +template <> class CharTraits : public BasicCharTraits { +private: // Conversion from wchar_t to char is not allowed. static char convert(wchar_t); - public: +public: static char convert(char value) { return value; } // Formats a floating-point number. template FMT_API static int format_float(char *buffer, std::size_t size, - const char *format, unsigned width, int precision, T value); + const char *format, unsigned width, + int precision, T value); }; -template <> -class CharTraits : public BasicCharTraits { - public: +template <> class CharTraits : public BasicCharTraits { +public: static wchar_t convert(char value) { return value; } static wchar_t convert(wchar_t value) { return value; } template FMT_API static int format_float(wchar_t *buffer, std::size_t size, - const wchar_t *format, unsigned width, int precision, T value); + const wchar_t *format, unsigned width, + int precision, T value); }; // Checks if a number is negative - used to avoid warnings. -template -struct SignChecker { - template - static bool is_negative(T value) { return value < 0; } +template struct SignChecker { + template static bool is_negative(T value) { return value < 0; } }; -template <> -struct SignChecker { - template - static bool is_negative(T) { return false; } +template <> struct SignChecker { + template static bool is_negative(T) { return false; } }; // Returns true if value is negative, false otherwise. // Same as (value < 0) but doesn't produce warnings if T is an unsigned type. -template -inline bool is_negative(T value) { +template inline bool is_negative(T value) { return SignChecker::is_signed>::is_negative(value); } // Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise. -template -struct TypeSelector { typedef uint32_t Type; }; +template struct TypeSelector { typedef uint32_t Type; }; -template <> -struct TypeSelector { typedef uint64_t Type; }; +template <> struct TypeSelector { typedef uint64_t Type; }; -template -struct IntTraits { +template struct IntTraits { // Smallest of uint32_t and uint64_t that is large enough to represent // all values of T. - typedef typename - TypeSelector::digits <= 32>::Type MainType; + typedef typename TypeSelector::digits <= 32>::Type + MainType; }; FMT_API void report_unknown_type(char code, const char *type); // Static data is placed in this class template to allow header-only // configuration. -template -struct FMT_API BasicData { +template struct FMT_API BasicData { static const uint32_t POWERS_OF_10_32[]; static const uint64_t POWERS_OF_10_64[]; static const char DIGITS[]; @@ -849,7 +824,7 @@ struct FMT_API BasicData { #ifndef FMT_USE_EXTERN_TEMPLATES // Clang doesn't have a feature check for extern templates so we check // for variadic templates which were introduced in the same version. -# define FMT_USE_EXTERN_TEMPLATES (__clang__ && FMT_USE_VARIADIC_TEMPLATES) +#define FMT_USE_EXTERN_TEMPLATES (__clang__ && FMT_USE_VARIADIC_TEMPLATES) #endif #if FMT_USE_EXTERN_TEMPLATES && !defined(FMT_HEADER_ONLY) @@ -875,10 +850,14 @@ inline unsigned count_digits(uint64_t n) { // Integer division is slow so do it for a group of four digits instead // of for every digit. The idea comes from the talk by Alexandrescu // "Three Optimization Tips for C++". See speed-test for a comparison. - if (n < 10) return count; - if (n < 100) return count + 1; - if (n < 1000) return count + 2; - if (n < 10000) return count + 3; + if (n < 10) + return count; + if (n < 100) + return count + 1; + if (n < 1000) + return count + 2; + if (n < 10000) + return count + 3; n /= 10000u; count += 4; } @@ -895,23 +874,21 @@ inline unsigned count_digits(uint32_t n) { // A functor that doesn't add a thousands separator. struct NoThousandsSep { - template - void operator()(Char *) {} + template void operator()(Char *) {} }; // A functor that adds a thousands separator. class ThousandsSep { - private: +private: fmt::StringRef sep_; // Index of a decimal digit with the least significant digit having index 0. unsigned digit_index_; - public: +public: explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {} - template - void operator()(Char *&buffer) { + template void operator()(Char *&buffer) { if (++digit_index_ % 3 != 0) return; buffer -= sep_.size(); @@ -954,9 +931,9 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { } #ifndef _WIN32 -# define FMT_USE_WINDOWS_H 0 +#define FMT_USE_WINDOWS_H 0 #elif !defined(FMT_USE_WINDOWS_H) -# define FMT_USE_WINDOWS_H 1 +#define FMT_USE_WINDOWS_H 1 #endif // Define FMT_USE_WINDOWS_H to 0 to disable use of windows.h. @@ -965,10 +942,10 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { // A converter from UTF-8 to UTF-16. // It is only provided for Windows since other systems support UTF-8 natively. class UTF8ToUTF16 { - private: +private: MemoryBuffer buffer_; - public: +public: FMT_API explicit UTF8ToUTF16(StringRef s); operator WStringRef() const { return WStringRef(&buffer_[0], size()); } size_t size() const { return buffer_.size() - 1; } @@ -979,10 +956,10 @@ class UTF8ToUTF16 { // A converter from UTF-16 to UTF-8. // It is only provided for Windows since other systems support UTF-8 natively. class UTF16ToUTF8 { - private: +private: MemoryBuffer buffer_; - public: +public: UTF16ToUTF8() {} FMT_API explicit UTF16ToUTF8(WStringRef s); operator StringRef() const { return StringRef(&buffer_[0], size()); } @@ -1005,14 +982,13 @@ FMT_API void format_system_error(fmt::Writer &out, int error_code, // A formatting argument value. struct Value { - template - struct StringValue { + template struct StringValue { const Char *value; std::size_t size; }; - typedef void (*FormatFunc)( - void *formatter, const void *arg, void *format_str_ptr); + typedef void (*FormatFunc)(void *formatter, const void *arg, + void *format_str_ptr); struct CustomValue { const void *value; @@ -1035,12 +1011,25 @@ struct Value { }; enum Type { - NONE, NAMED_ARG, + NONE, + NAMED_ARG, // Integer types should go first, - INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR, + INT, + UINT, + LONG_LONG, + ULONG_LONG, + BOOL, + CHAR, + LAST_INTEGER_TYPE = CHAR, // followed by floating-point types. - DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, - CSTRING, STRING, WSTRING, POINTER, CUSTOM + DOUBLE, + LONG_DOUBLE, + LAST_NUMERIC_TYPE = LONG_DOUBLE, + CSTRING, + STRING, + WSTRING, + POINTER, + CUSTOM }; }; @@ -1050,22 +1039,18 @@ struct Arg : Value { Type type; }; -template -struct NamedArg; +template struct NamedArg; -template -struct Null {}; +template struct Null {}; // A helper class template to enable or disable overloads taking wide // characters and strings in MakeValue. -template -struct WCharHelper { +template struct WCharHelper { typedef Null Supported; typedef T Unsupported; }; -template -struct WCharHelper { +template struct WCharHelper { typedef T Supported; typedef Null Unsupported; }; @@ -1073,66 +1058,60 @@ struct WCharHelper { typedef char Yes[1]; typedef char No[2]; -template -T &get(); +template T &get(); // These are non-members to workaround an overload resolution bug in bcc32. Yes &convert(fmt::ULongLong); No &convert(...); -template -struct ConvertToIntImpl { +template struct ConvertToIntImpl { enum { value = ENABLE_CONVERSION }; }; -template -struct ConvertToIntImpl2 { +template struct ConvertToIntImpl2 { enum { value = false }; }; -template -struct ConvertToIntImpl2 { +template struct ConvertToIntImpl2 { enum { // Don't convert numeric types. value = ConvertToIntImpl::is_specialized>::value }; }; -template -struct ConvertToInt { +template struct ConvertToInt { enum { enable_conversion = sizeof(convert(get())) == sizeof(Yes) }; enum { value = ConvertToIntImpl2::value }; }; -#define FMT_DISABLE_CONVERSION_TO_INT(Type) \ - template <> \ - struct ConvertToInt { enum { value = 0 }; } +#define FMT_DISABLE_CONVERSION_TO_INT(Type) \ + template <> struct ConvertToInt { \ + enum { value = 0 }; \ + } // Silence warnings about convering float to int. FMT_DISABLE_CONVERSION_TO_INT(float); FMT_DISABLE_CONVERSION_TO_INT(double); FMT_DISABLE_CONVERSION_TO_INT(long double); -template -struct EnableIf {}; +template struct EnableIf {}; -template -struct EnableIf { typedef T type; }; +template struct EnableIf { typedef T type; }; -template -struct Conditional { typedef T type; }; +template struct Conditional { typedef T type; }; -template -struct Conditional { typedef F type; }; +template struct Conditional { typedef F type; }; // For bcc32 which doesn't understand ! in template arguments. -template -struct Not { enum { value = 0 }; }; +template struct Not { + enum { value = 0 }; +}; -template<> -struct Not { enum { value = 1 }; }; +template <> struct Not { + enum { value = 1 }; +}; -template struct LConvCheck { +template struct LConvCheck { LConvCheck(int) {} }; @@ -1140,29 +1119,27 @@ template struct LConvCheck { // We check if ``lconv`` contains ``thousands_sep`` because on Android // ``lconv`` is stubbed as an empty struct. template -inline StringRef thousands_sep( - LConv *lc, LConvCheck = 0) { +inline StringRef +thousands_sep(LConv *lc, + LConvCheck = 0) { return lc->thousands_sep; } inline fmt::StringRef thousands_sep(...) { return ""; } // Makes an Arg object from any type. -template -class MakeValue : public Arg { - public: +template class MakeValue : public Arg { +public: typedef typename Formatter::Char Char; - private: +private: // The following two methods are private to disallow formatting of // arbitrary pointers. If you want to output a pointer cast it to // "void *" or "const void *". In particular, this forbids formatting // of "[const] volatile char *" which is printed as bool by iostreams. // Do not implement! - template - MakeValue(const T *value); - template - MakeValue(T *value); + template MakeValue(const T *value); + template MakeValue(T *value); // The following methods are private to disallow formatting of wide // characters and strings into narrow strings as in @@ -1188,21 +1165,21 @@ class MakeValue : public Arg { // Formats an argument of a custom type, such as a user-defined class. template - static void format_custom_arg( - void *formatter, const void *arg, void *format_str_ptr) { - format(*static_cast(formatter), - *static_cast(format_str_ptr), - *static_cast(arg)); + static void format_custom_arg(void *formatter, const void *arg, + void *format_str_ptr) { + format(*static_cast(formatter), + *static_cast(format_str_ptr), + *static_cast(arg)); } - public: +public: MakeValue() {} -#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \ - MakeValue(Type value) { field = rhs; } \ +#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \ + MakeValue(Type value) { field = rhs; } \ static uint64_t type(Type) { return Arg::TYPE; } -#define FMT_MAKE_VALUE(Type, field, TYPE) \ +#define FMT_MAKE_VALUE(Type, field, TYPE) \ FMT_MAKE_VALUE_(Type, field, TYPE, value) FMT_MAKE_VALUE(bool, int_value, BOOL) @@ -1230,8 +1207,8 @@ class MakeValue : public Arg { ulong_long_value = value; } static uint64_t type(unsigned long) { - return sizeof(unsigned long) == sizeof(unsigned) ? - Arg::UINT : Arg::ULONG_LONG; + return sizeof(unsigned long) == sizeof(unsigned) ? Arg::UINT + : Arg::ULONG_LONG; } FMT_MAKE_VALUE(LongLong, long_long_value, LONG_LONG) @@ -1250,8 +1227,8 @@ class MakeValue : public Arg { static uint64_t type(wchar_t) { return Arg::CHAR; } #endif -#define FMT_MAKE_STR_VALUE(Type, TYPE) \ - MakeValue(Type value) { set_string(value); } \ +#define FMT_MAKE_STR_VALUE(Type, TYPE) \ + MakeValue(Type value) { set_string(value); } \ static uint64_t type(Type) { return Arg::TYPE; } FMT_MAKE_VALUE(char *, string.value, CSTRING) @@ -1264,10 +1241,10 @@ class MakeValue : public Arg { FMT_MAKE_STR_VALUE(StringRef, STRING) FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str()) -#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \ - MakeValue(typename WCharHelper::Supported value) { \ - set_string(value); \ - } \ +#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \ + MakeValue(typename WCharHelper::Supported value) { \ + set_string(value); \ + } \ static uint64_t type(Type) { return Arg::TYPE; } FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING) @@ -1279,9 +1256,9 @@ class MakeValue : public Arg { FMT_MAKE_VALUE(const void *, pointer, POINTER) template - MakeValue(const T &value, - typename EnableIf::value>::value, int>::type = 0) { + MakeValue( + const T &value, + typename EnableIf::value>::value, int>::type = 0) { custom.value = &value; custom.format = &format_custom_arg; } @@ -1292,59 +1269,53 @@ class MakeValue : public Arg { int_value = value; } - template - static uint64_t type(const T &) { + template static uint64_t type(const T &) { return ConvertToInt::value ? Arg::INT : Arg::CUSTOM; } // Additional template param `Char_` is needed here because make_type always // uses char. - template - MakeValue(const NamedArg &value) { pointer = &value; } + template MakeValue(const NamedArg &value) { + pointer = &value; + } - template - static uint64_t type(const NamedArg &) { return Arg::NAMED_ARG; } + template static uint64_t type(const NamedArg &) { + return Arg::NAMED_ARG; + } }; -template -class MakeArg : public Arg { +template class MakeArg : public Arg { public: - MakeArg() { - type = Arg::NONE; - } + MakeArg() { type = Arg::NONE; } template - MakeArg(const T &value) - : Arg(MakeValue(value)) { + MakeArg(const T &value) : Arg(MakeValue(value)) { type = static_cast(MakeValue::type(value)); } }; -template -struct NamedArg : Arg { +template struct NamedArg : Arg { BasicStringRef name; template NamedArg(BasicStringRef argname, const T &value) - : Arg(MakeArg< BasicFormatter >(value)), name(argname) {} + : Arg(MakeArg>(value)), name(argname) {} }; class RuntimeError : public std::runtime_error { - protected: +protected: RuntimeError() : std::runtime_error("") {} ~RuntimeError() throw(); }; -template -class PrintfArgFormatter; +template class PrintfArgFormatter; -template -class ArgMap; -} // namespace internal +template class ArgMap; +} // namespace internal /** An argument list. */ class ArgList { - private: +private: // To reduce compiled code size per formatting function call, types of first // MAX_PACKED_ARGS arguments are passed in the types_ field. uint64_t types_; @@ -1361,23 +1332,22 @@ class ArgList { internal::Arg::Type type(unsigned index) const { unsigned shift = index * 4; uint64_t mask = 0xf; - return static_cast( - (types_ & (mask << shift)) >> shift); + return static_cast((types_ & (mask << shift)) >> + shift); } - template - friend class internal::ArgMap; + template friend class internal::ArgMap; - public: +public: // Maximum number of arguments with packed types. enum { MAX_PACKED_ARGS = 16 }; ArgList() : types_(0) {} ArgList(ULongLong types, const internal::Value *values) - : types_(types), values_(values) {} + : types_(types), values_(values) {} ArgList(ULongLong types, const internal::Arg *args) - : types_(types), args_(args) {} + : types_(types), args_(args) {} /** Returns the argument at specified index. */ internal::Arg operator[](unsigned index) const { @@ -1406,7 +1376,7 @@ class ArgList { } }; -#define FMT_DISPATCH(call) static_cast(this)->call +#define FMT_DISPATCH(call) static_cast(this)->call /** \rst @@ -1432,12 +1402,11 @@ class ArgList { }; \endrst */ -template -class ArgVisitor { - private: +template class ArgVisitor { +private: typedef internal::Arg Arg; - public: +public: void report_unhandled_arg() {} Result visit_unhandled_arg() { @@ -1446,9 +1415,7 @@ class ArgVisitor { } /** Visits an ``int`` argument. **/ - Result visit_int(int value) { - return FMT_DISPATCH(visit_any_int(value)); - } + Result visit_int(int value) { return FMT_DISPATCH(visit_any_int(value)); } /** Visits a ``long long`` argument. **/ Result visit_long_long(LongLong value) { @@ -1466,18 +1433,13 @@ class ArgVisitor { } /** Visits a ``bool`` argument. **/ - Result visit_bool(bool value) { - return FMT_DISPATCH(visit_any_int(value)); - } + Result visit_bool(bool value) { return FMT_DISPATCH(visit_any_int(value)); } /** Visits a ``char`` or ``wchar_t`` argument. **/ - Result visit_char(int value) { - return FMT_DISPATCH(visit_any_int(value)); - } + Result visit_char(int value) { return FMT_DISPATCH(visit_any_int(value)); } /** Visits an argument of any integral type. **/ - template - Result visit_any_int(T) { + template Result visit_any_int(T) { return FMT_DISPATCH(visit_unhandled_arg()); } @@ -1492,8 +1454,7 @@ class ArgVisitor { } /** Visits a ``double`` or ``long double`` argument. **/ - template - Result visit_any_double(T) { + template Result visit_any_double(T) { return FMT_DISPATCH(visit_unhandled_arg()); } @@ -1568,21 +1529,27 @@ class ArgVisitor { }; enum Alignment { - ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC + ALIGN_DEFAULT, + ALIGN_LEFT, + ALIGN_RIGHT, + ALIGN_CENTER, + ALIGN_NUMERIC }; // Flags. enum { - SIGN_FLAG = 1, PLUS_FLAG = 2, MINUS_FLAG = 4, HASH_FLAG = 8, - CHAR_FLAG = 0x10 // Argument has char type - used in error reporting. + SIGN_FLAG = 1, + PLUS_FLAG = 2, + MINUS_FLAG = 4, + HASH_FLAG = 8, + CHAR_FLAG = 0x10 // Argument has char type - used in error reporting. }; // An empty format specifier. struct EmptySpec {}; // A type specifier. -template -struct TypeSpec : EmptySpec { +template struct TypeSpec : EmptySpec { Alignment align() const { return ALIGN_DEFAULT; } unsigned width() const { return 0; } int precision() const { return -1; } @@ -1609,7 +1576,7 @@ struct AlignSpec : WidthSpec { Alignment align_; AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT) - : WidthSpec(width, fill), align_(align) {} + : WidthSpec(width, fill), align_(align) {} Alignment align() const { return align_; } @@ -1617,8 +1584,7 @@ struct AlignSpec : WidthSpec { }; // An alignment and type specifier. -template -struct AlignTypeSpec : AlignSpec { +template struct AlignTypeSpec : AlignSpec { AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {} bool flag(unsigned) const { return false; } @@ -1631,9 +1597,8 @@ struct FormatSpec : AlignSpec { int precision_; char type_; - FormatSpec( - unsigned width = 0, char type = 0, wchar_t fill = ' ') - : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {} + FormatSpec(unsigned width = 0, char type = 0, wchar_t fill = ' ') + : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {} bool flag(unsigned f) const { return (flags_ & f) != 0; } int precision() const { return precision_; } @@ -1643,26 +1608,25 @@ struct FormatSpec : AlignSpec { // An integer format specifier. template , typename Char = char> class IntFormatSpec : public SpecT { - private: +private: T value_; - public: +public: IntFormatSpec(T val, const SpecT &spec = SpecT()) - : SpecT(spec), value_(val) {} + : SpecT(spec), value_(val) {} T value() const { return value_; } }; // A string format specifier. -template -class StrFormatSpec : public AlignSpec { - private: +template class StrFormatSpec : public AlignSpec { +private: const Char *str_; - public: +public: template StrFormatSpec(const Char *str, unsigned width, FillChar fill) - : AlignSpec(width, fill), str_(str) { + : AlignSpec(width, fill), str_(str) { internal::CharTraits::convert(FillChar()); } @@ -1672,24 +1636,24 @@ class StrFormatSpec : public AlignSpec { /** Returns an integer format specifier to format the value in base 2. */ -IntFormatSpec > bin(int value); +IntFormatSpec> bin(int value); /** Returns an integer format specifier to format the value in base 8. */ -IntFormatSpec > oct(int value); +IntFormatSpec> oct(int value); /** Returns an integer format specifier to format the value in base 16 using lower-case letters for the digits above 9. */ -IntFormatSpec > hex(int value); +IntFormatSpec> hex(int value); /** Returns an integer formatter format specifier to format in base 16 using upper-case letters for the digits above 9. */ -IntFormatSpec > hexu(int value); +IntFormatSpec> hexu(int value); /** \rst @@ -1706,57 +1670,59 @@ IntFormatSpec > hexu(int value); \endrst */ template -IntFormatSpec, Char> pad( - int value, unsigned width, Char fill = ' '); - -#define FMT_DEFINE_INT_FORMATTERS(TYPE) \ -inline IntFormatSpec > bin(TYPE value) { \ - return IntFormatSpec >(value, TypeSpec<'b'>()); \ -} \ - \ -inline IntFormatSpec > oct(TYPE value) { \ - return IntFormatSpec >(value, TypeSpec<'o'>()); \ -} \ - \ -inline IntFormatSpec > hex(TYPE value) { \ - return IntFormatSpec >(value, TypeSpec<'x'>()); \ -} \ - \ -inline IntFormatSpec > hexu(TYPE value) { \ - return IntFormatSpec >(value, TypeSpec<'X'>()); \ -} \ - \ -template \ -inline IntFormatSpec > pad( \ - IntFormatSpec > f, unsigned width) { \ - return IntFormatSpec >( \ - f.value(), AlignTypeSpec(width, ' ')); \ -} \ - \ -/* For compatibility with older compilers we provide two overloads for pad, */ \ -/* one that takes a fill character and one that doesn't. In the future this */ \ -/* can be replaced with one overload making the template argument Char */ \ -/* default to char (C++11). */ \ -template \ -inline IntFormatSpec, Char> pad( \ - IntFormatSpec, Char> f, \ - unsigned width, Char fill) { \ - return IntFormatSpec, Char>( \ - f.value(), AlignTypeSpec(width, fill)); \ -} \ - \ -inline IntFormatSpec > pad( \ - TYPE value, unsigned width) { \ - return IntFormatSpec >( \ - value, AlignTypeSpec<0>(width, ' ')); \ -} \ - \ -template \ -inline IntFormatSpec, Char> pad( \ - TYPE value, unsigned width, Char fill) { \ - return IntFormatSpec, Char>( \ - value, AlignTypeSpec<0>(width, fill)); \ -} +IntFormatSpec, Char> +pad(int value, unsigned width, Char fill = ' '); + +#define FMT_DEFINE_INT_FORMATTERS(TYPE) \ + inline IntFormatSpec> bin(TYPE value) { \ + return IntFormatSpec>(value, TypeSpec<'b'>()); \ + } \ + \ + inline IntFormatSpec> oct(TYPE value) { \ + return IntFormatSpec>(value, TypeSpec<'o'>()); \ + } \ + \ + inline IntFormatSpec> hex(TYPE value) { \ + return IntFormatSpec>(value, TypeSpec<'x'>()); \ + } \ + \ + inline IntFormatSpec> hexu(TYPE value) { \ + return IntFormatSpec>(value, TypeSpec<'X'>()); \ + } \ + \ + template \ + inline IntFormatSpec> pad( \ + IntFormatSpec> f, unsigned width) { \ + return IntFormatSpec>( \ + f.value(), AlignTypeSpec(width, ' ')); \ + } \ + \ + /* For compatibility with older compilers we provide two overloads for pad, \ + */ \ + /* one that takes a fill character and one that doesn't. In the future this \ + */ \ + /* can be replaced with one overload making the template argument Char */ \ + /* default to char (C++11). */ \ + template \ + inline IntFormatSpec, Char> pad( \ + IntFormatSpec, Char> f, unsigned width, \ + Char fill) { \ + return IntFormatSpec, Char>( \ + f.value(), AlignTypeSpec(width, fill)); \ + } \ + \ + inline IntFormatSpec> pad(TYPE value, \ + unsigned width) { \ + return IntFormatSpec>( \ + value, AlignTypeSpec<0>(width, ' ')); \ + } \ + \ + template \ + inline IntFormatSpec, Char> pad( \ + TYPE value, unsigned width, Char fill) { \ + return IntFormatSpec, Char>( \ + value, AlignTypeSpec<0>(width, fill)); \ + } FMT_DEFINE_INT_FORMATTERS(int) FMT_DEFINE_INT_FORMATTERS(long) @@ -1778,31 +1744,30 @@ FMT_DEFINE_INT_FORMATTERS(ULongLong) \endrst */ template -inline StrFormatSpec pad( - const Char *str, unsigned width, Char fill = ' ') { +inline StrFormatSpec pad(const Char *str, unsigned width, + Char fill = ' ') { return StrFormatSpec(str, width, fill); } -inline StrFormatSpec pad( - const wchar_t *str, unsigned width, char fill = ' ') { +inline StrFormatSpec pad(const wchar_t *str, unsigned width, + char fill = ' ') { return StrFormatSpec(str, width, fill); } namespace internal { -template -class ArgMap { - private: - typedef std::vector< - std::pair, internal::Arg> > MapType; +template class ArgMap { +private: + typedef std::vector, internal::Arg>> + MapType; typedef typename MapType::value_type Pair; MapType map_; - public: +public: FMT_API void init(const ArgList &args); - const internal::Arg* find(const fmt::BasicStringRef &name) const { + const internal::Arg *find(const fmt::BasicStringRef &name) const { // The list is unsorted, so just return the first matching name. for (typename MapType::const_iterator it = map_.begin(), end = map_.end(); it != end; ++it) { @@ -1815,7 +1780,7 @@ class ArgMap { template class ArgFormatterBase : public ArgVisitor { - private: +private: BasicWriter &writer_; FormatSpec &spec_; @@ -1827,13 +1792,13 @@ class ArgFormatterBase : public ArgVisitor { writer_.write_int(reinterpret_cast(p), spec_); } - protected: +protected: BasicWriter &writer() { return writer_; } FormatSpec &spec() { return spec_; } void write(bool value) { const char *str_value = value ? "true" : "false"; - Arg::StringValue str = { str_value, std::strlen(str_value) }; + Arg::StringValue str = {str_value, std::strlen(str_value)}; writer_.write_str(str, spec_); } @@ -1842,15 +1807,17 @@ class ArgFormatterBase : public ArgVisitor { writer_.write_str(str, spec_); } - public: +public: ArgFormatterBase(BasicWriter &w, FormatSpec &s) - : writer_(w), spec_(s) {} + : writer_(w), spec_(s) {} - template - void visit_any_int(T value) { writer_.write_int(value, spec_); } + template void visit_any_int(T value) { + writer_.write_int(value, spec_); + } - template - void visit_any_double(T value) { writer_.write_double(value, spec_); } + template void visit_any_double(T value) { + writer_.write_double(value, spec_); + } void visit_bool(bool value) { if (spec_.type_) @@ -1879,8 +1846,8 @@ class ArgFormatterBase : public ArgVisitor { out = writer_.fill_padding(out, spec_.width_, internal::const_check(CHAR_SIZE), fill); } else { - std::uninitialized_fill_n(out + CHAR_SIZE, - spec_.width_ - CHAR_SIZE, fill); + std::uninitialized_fill_n(out + CHAR_SIZE, spec_.width_ - CHAR_SIZE, + fill); } } else { out = writer_.grow_buffer(CHAR_SIZE); @@ -1912,14 +1879,14 @@ class ArgFormatterBase : public ArgVisitor { }; class FormatterBase { - private: +private: ArgList args_; int next_arg_index_; // Returns the argument with specified index. FMT_API Arg do_get_arg(unsigned arg_index, const char *&error); - protected: +protected: const ArgList &args() const { return args_; } explicit FormatterBase(const ArgList &args) { @@ -1958,25 +1925,24 @@ class FormatterBase { }; // A printf formatter. -template -class PrintfFormatter : private FormatterBase { - private: +template class PrintfFormatter : private FormatterBase { +private: void parse_flags(FormatSpec &spec, const Char *&s); // Returns the argument with specified index or, if arg_index is equal // to the maximum unsigned value, the next argument. Arg get_arg(const Char *s, - unsigned arg_index = (std::numeric_limits::max)()); + unsigned arg_index = (std::numeric_limits::max)()); // Parses argument index, flags and width and returns the argument index. unsigned parse_header(const Char *&s, FormatSpec &spec); - public: +public: explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {} FMT_API void format(BasicWriter &writer, BasicCStringRef format_str); }; -} // namespace internal +} // namespace internal /** \rst @@ -1997,11 +1963,11 @@ class PrintfFormatter : private FormatterBase { */ template class BasicArgFormatter : public internal::ArgFormatterBase { - private: +private: BasicFormatter &formatter_; const Char *format_; - public: +public: /** \rst Constructs an argument formatter object. @@ -2010,10 +1976,10 @@ class BasicArgFormatter : public internal::ArgFormatterBase { to the part of the format string being parsed for custom argument types. \endrst */ - BasicArgFormatter(BasicFormatter &formatter, - FormatSpec &spec, const Char *fmt) - : internal::ArgFormatterBase(formatter.writer(), spec), - formatter_(formatter), format_(fmt) {} + BasicArgFormatter(BasicFormatter &formatter, FormatSpec &spec, + const Char *fmt) + : internal::ArgFormatterBase(formatter.writer(), spec), + formatter_(formatter), format_(fmt) {} /** Formats argument of a custom (user-defined) type. */ void visit_custom(internal::Arg::CustomValue c) { @@ -2024,21 +1990,21 @@ class BasicArgFormatter : public internal::ArgFormatterBase { /** The default argument formatter. */ template class ArgFormatter : public BasicArgFormatter, Char> { - public: +public: /** Constructs an argument formatter object. */ - ArgFormatter(BasicFormatter &formatter, - FormatSpec &spec, const Char *fmt) - : BasicArgFormatter, Char>(formatter, spec, fmt) {} + ArgFormatter(BasicFormatter &formatter, FormatSpec &spec, + const Char *fmt) + : BasicArgFormatter, Char>(formatter, spec, fmt) {} }; /** This template formats data and writes the output to a writer. */ template class BasicFormatter : private internal::FormatterBase { - public: +public: /** The character type for the output. */ typedef CharType Char; - private: +private: BasicWriter &writer_; internal::ArgMap map_; @@ -2056,7 +2022,7 @@ class BasicFormatter : private internal::FormatterBase { // Parses argument name and returns corresponding argument. internal::Arg parse_arg_name(const Char *&s); - public: +public: /** \rst Constructs a ``BasicFormatter`` object. References to the arguments and @@ -2065,7 +2031,7 @@ class BasicFormatter : private internal::FormatterBase { \endrst */ BasicFormatter(const ArgList &args, BasicWriter &w) - : internal::FormatterBase(args), writer_(w) {} + : internal::FormatterBase(args), writer_(w) {} /** Returns a reference to the writer associated with this formatter. */ BasicWriter &writer() { return writer_; } @@ -2079,40 +2045,37 @@ class BasicFormatter : private internal::FormatterBase { // Generates a comma-separated list with results of applying f to // numbers 0..n-1. -# define FMT_GEN(n, f) FMT_GEN##n(f) -# define FMT_GEN1(f) f(0) -# define FMT_GEN2(f) FMT_GEN1(f), f(1) -# define FMT_GEN3(f) FMT_GEN2(f), f(2) -# define FMT_GEN4(f) FMT_GEN3(f), f(3) -# define FMT_GEN5(f) FMT_GEN4(f), f(4) -# define FMT_GEN6(f) FMT_GEN5(f), f(5) -# define FMT_GEN7(f) FMT_GEN6(f), f(6) -# define FMT_GEN8(f) FMT_GEN7(f), f(7) -# define FMT_GEN9(f) FMT_GEN8(f), f(8) -# define FMT_GEN10(f) FMT_GEN9(f), f(9) -# define FMT_GEN11(f) FMT_GEN10(f), f(10) -# define FMT_GEN12(f) FMT_GEN11(f), f(11) -# define FMT_GEN13(f) FMT_GEN12(f), f(12) -# define FMT_GEN14(f) FMT_GEN13(f), f(13) -# define FMT_GEN15(f) FMT_GEN14(f), f(14) +#define FMT_GEN(n, f) FMT_GEN##n(f) +#define FMT_GEN1(f) f(0) +#define FMT_GEN2(f) FMT_GEN1(f), f(1) +#define FMT_GEN3(f) FMT_GEN2(f), f(2) +#define FMT_GEN4(f) FMT_GEN3(f), f(3) +#define FMT_GEN5(f) FMT_GEN4(f), f(4) +#define FMT_GEN6(f) FMT_GEN5(f), f(5) +#define FMT_GEN7(f) FMT_GEN6(f), f(6) +#define FMT_GEN8(f) FMT_GEN7(f), f(7) +#define FMT_GEN9(f) FMT_GEN8(f), f(8) +#define FMT_GEN10(f) FMT_GEN9(f), f(9) +#define FMT_GEN11(f) FMT_GEN10(f), f(10) +#define FMT_GEN12(f) FMT_GEN11(f), f(11) +#define FMT_GEN13(f) FMT_GEN12(f), f(12) +#define FMT_GEN14(f) FMT_GEN13(f), f(13) +#define FMT_GEN15(f) FMT_GEN14(f), f(14) namespace internal { inline uint64_t make_type() { return 0; } -template -inline uint64_t make_type(const T &arg) { - return MakeValue< BasicFormatter >::type(arg); +template inline uint64_t make_type(const T &arg) { + return MakeValue>::type(arg); } -template +template struct ArgArray; -template -struct ArgArray { +template struct ArgArray { typedef Value Type[N > 0 ? N : 1]; - template - static Value make(const T &value) { + template static Value make(const T &value) { #ifdef __clang__ Value result = MakeValue(value); // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang: @@ -2125,17 +2088,17 @@ struct ArgArray { } }; -template -struct ArgArray { +template struct ArgArray { typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE - template - static Arg make(const T &value) { return MakeArg(value); } + template static Arg make(const T &value) { + return MakeArg(value); + } }; #if FMT_USE_VARIADIC_TEMPLATES template -inline uint64_t make_type(const Arg &first, const Args & ... tail) { +inline uint64_t make_type(const Arg &first, const Args &... tail) { return make_type(first) | (make_type(tail...) << 4); } @@ -2146,117 +2109,119 @@ struct ArgType { ArgType() : type(0) {} - template - ArgType(const T &arg) : type(make_type(arg)) {} + template ArgType(const T &arg) : type(make_type(arg)) {} }; -# define FMT_ARG_TYPE_DEFAULT(n) ArgType t##n = ArgType() +#define FMT_ARG_TYPE_DEFAULT(n) ArgType t##n = ArgType() inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { return t0.type | (t1.type << 4) | (t2.type << 8) | (t3.type << 12) | - (t4.type << 16) | (t5.type << 20) | (t6.type << 24) | (t7.type << 28) | - (t8.type << 32) | (t9.type << 36) | (t10.type << 40) | (t11.type << 44) | - (t12.type << 48) | (t13.type << 52) | (t14.type << 56); + (t4.type << 16) | (t5.type << 20) | (t6.type << 24) | (t7.type << 28) | + (t8.type << 32) | (t9.type << 36) | (t10.type << 40) | + (t11.type << 44) | (t12.type << 48) | (t13.type << 52) | + (t14.type << 56); } #endif -} // namespace internal +} // namespace internal -# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n -# define FMT_MAKE_ARG_TYPE(n) T##n -# define FMT_MAKE_ARG(n) const T##n &v##n -# define FMT_ASSIGN_char(n) \ - arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) -# define FMT_ASSIGN_wchar_t(n) \ - arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) +#define FMT_MAKE_TEMPLATE_ARG(n) typename T##n +#define FMT_MAKE_ARG_TYPE(n) T##n +#define FMT_MAKE_ARG(n) const T##n &v##n +#define FMT_ASSIGN_char(n) \ + arr[n] = fmt::internal::MakeValue>(v##n) +#define FMT_ASSIGN_wchar_t(n) \ + arr[n] = fmt::internal::MakeValue>(v##n) #if FMT_USE_VARIADIC_TEMPLATES // Defines a variadic function returning void. -# define FMT_VARIADIC_VOID(func, arg_type) \ - template \ - void func(arg_type arg0, const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \ +#define FMT_VARIADIC_VOID(func, arg_type) \ + template void func(arg_type arg0, const Args &... args) { \ + typedef fmt::internal::ArgArray ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make>(args)...}; \ + func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \ } // Defines a variadic constructor. -# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ - template \ - ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \ +#define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ + template \ + ctor(arg0_type arg0, arg1_type arg1, const Args &... args) { \ + typedef fmt::internal::ArgArray ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make>(args)...}; \ + func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \ } #else -# define FMT_MAKE_REF(n) \ - fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) -# define FMT_MAKE_REF2(n) v##n +#define FMT_MAKE_REF(n) \ + fmt::internal::MakeValue>(v##n) +#define FMT_MAKE_REF2(n) v##n // Defines a wrapper for a function taking one argument of type arg_type // and n additional arguments of arbitrary types. -# define FMT_WRAP1(func, arg_type, n) \ - template \ - inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ +#define FMT_WRAP1(func, arg_type, n) \ + template \ + inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ const fmt::internal::ArgArray::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \ - func(arg1, fmt::ArgList( \ - fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \ + func(arg1, \ + fmt::ArgList(fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), \ + array)); \ } // Emulates a variadic function returning void on a pre-C++11 compiler. -# define FMT_VARIADIC_VOID(func, arg_type) \ - inline void func(arg_type arg) { func(arg, fmt::ArgList()); } \ - FMT_WRAP1(func, arg_type, 1) FMT_WRAP1(func, arg_type, 2) \ - FMT_WRAP1(func, arg_type, 3) FMT_WRAP1(func, arg_type, 4) \ - FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \ - FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \ +#define FMT_VARIADIC_VOID(func, arg_type) \ + inline void func(arg_type arg) { func(arg, fmt::ArgList()); } \ + FMT_WRAP1(func, arg_type, 1) \ + FMT_WRAP1(func, arg_type, 2) \ + FMT_WRAP1(func, arg_type, 3) \ + FMT_WRAP1(func, arg_type, 4) \ + FMT_WRAP1(func, arg_type, 5) \ + FMT_WRAP1(func, arg_type, 6) \ + FMT_WRAP1(func, arg_type, 7) \ + FMT_WRAP1(func, arg_type, 8) \ FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10) -# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \ - template \ - ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ +#define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \ + template \ + ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \ const fmt::internal::ArgArray::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \ - func(arg0, arg1, fmt::ArgList( \ - fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \ + func(arg0, arg1, \ + fmt::ArgList(fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), \ + array)); \ } // Emulates a variadic constructor on a pre-C++11 compiler. -# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \ - FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \ +#define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \ + FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \ FMT_CTOR(ctor, func, arg0_type, arg1_type, 10) #endif // Generates a comma-separated list with results of applying f to pairs // (argument, index). #define FMT_FOR_EACH1(f, x0) f(x0, 0) -#define FMT_FOR_EACH2(f, x0, x1) \ - FMT_FOR_EACH1(f, x0), f(x1, 1) -#define FMT_FOR_EACH3(f, x0, x1, x2) \ - FMT_FOR_EACH2(f, x0 ,x1), f(x2, 2) -#define FMT_FOR_EACH4(f, x0, x1, x2, x3) \ - FMT_FOR_EACH3(f, x0, x1, x2), f(x3, 3) -#define FMT_FOR_EACH5(f, x0, x1, x2, x3, x4) \ +#define FMT_FOR_EACH2(f, x0, x1) FMT_FOR_EACH1(f, x0), f(x1, 1) +#define FMT_FOR_EACH3(f, x0, x1, x2) FMT_FOR_EACH2(f, x0, x1), f(x2, 2) +#define FMT_FOR_EACH4(f, x0, x1, x2, x3) FMT_FOR_EACH3(f, x0, x1, x2), f(x3, 3) +#define FMT_FOR_EACH5(f, x0, x1, x2, x3, x4) \ FMT_FOR_EACH4(f, x0, x1, x2, x3), f(x4, 4) -#define FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5) \ +#define FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5) \ FMT_FOR_EACH5(f, x0, x1, x2, x3, x4), f(x5, 5) -#define FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6) \ +#define FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6) \ FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5), f(x6, 6) -#define FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7) \ +#define FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7) \ FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6), f(x7, 7) -#define FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8) \ +#define FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8) \ FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7), f(x8, 8) -#define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \ +#define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \ FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9) /** @@ -2264,17 +2229,17 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { for example a file opening error. */ class SystemError : public internal::RuntimeError { - private: +private: void init(int err_code, CStringRef format_str, ArgList args); - protected: +protected: int error_code_; - typedef char Char; // For FMT_VARIADIC_CTOR. + typedef char Char; // For FMT_VARIADIC_CTOR. SystemError() {} - public: +public: /** \rst Constructs a :class:`fmt::SystemError` object with the description @@ -2328,9 +2293,8 @@ class SystemError : public internal::RuntimeError { \endrst */ -template -class BasicWriter { - private: +template class BasicWriter { +private: // Output buffer. Buffer &buffer_; @@ -2347,8 +2311,8 @@ class BasicWriter { // Fills the padding around the content and returns the pointer to the // content area. - static CharPtr fill_padding(CharPtr buffer, - unsigned total_size, std::size_t content_size, wchar_t fill); + static CharPtr fill_padding(CharPtr buffer, unsigned total_size, + std::size_t content_size, wchar_t fill); // Grows the buffer by n characters and returns a pointer to the newly // allocated area. @@ -2368,8 +2332,7 @@ class BasicWriter { } // Writes a decimal integer. - template - void write_decimal(Int value) { + template void write_decimal(Int value) { typedef typename internal::IntTraits::MainType MainType; MainType abs_value = static_cast(value); if (internal::is_negative(value)) { @@ -2381,8 +2344,8 @@ class BasicWriter { } // Prepare a buffer for integer formatting. - CharPtr prepare_int_buffer(unsigned num_digits, - const EmptySpec &, const char *prefix, unsigned prefix_size) { + CharPtr prepare_int_buffer(unsigned num_digits, const EmptySpec &, + const char *prefix, unsigned prefix_size) { unsigned size = prefix_size + num_digits; CharPtr p = grow_buffer(size); std::uninitialized_copy(prefix, prefix + prefix_size, p); @@ -2390,16 +2353,14 @@ class BasicWriter { } template - CharPtr prepare_int_buffer(unsigned num_digits, - const Spec &spec, const char *prefix, unsigned prefix_size); + CharPtr prepare_int_buffer(unsigned num_digits, const Spec &spec, + const char *prefix, unsigned prefix_size); // Formats an integer. - template - void write_int(T value, Spec spec); + template void write_int(T value, Spec spec); // Formats a floating-point number (double or long double). - template - void write_double(T value, const FormatSpec &spec); + template void write_double(T value, const FormatSpec &spec); // Writes a formatted string. template @@ -2423,21 +2384,20 @@ class BasicWriter { *format_ptr++ = 'L'; } - template - void append_float_length(Char *&, T) {} + template void append_float_length(Char *&, T) {} template friend class internal::ArgFormatterBase; friend class internal::PrintfArgFormatter; - protected: +protected: /** Constructs a ``BasicWriter`` object. */ explicit BasicWriter(Buffer &b) : buffer_(b) {} - public: +public: /** \rst Destroys a ``BasicWriter`` object. @@ -2558,8 +2518,8 @@ class BasicWriter { return *this; } - BasicWriter &operator<<( - typename internal::WCharHelper::Supported value) { + BasicWriter & + operator<<(typename internal::WCharHelper::Supported value) { buffer_.push_back(value); return *this; } @@ -2575,8 +2535,8 @@ class BasicWriter { return *this; } - BasicWriter &operator<<( - typename internal::WCharHelper::Supported value) { + BasicWriter & + operator<<(typename internal::WCharHelper::Supported value) { const char *str = value.data(); buffer_.append(str, str + value.size()); return *this; @@ -2603,8 +2563,9 @@ class BasicWriter { template template -typename BasicWriter::CharPtr BasicWriter::write_str( - const StrChar *s, std::size_t size, const AlignSpec &spec) { +typename BasicWriter::CharPtr +BasicWriter::write_str(const StrChar *s, std::size_t size, + const AlignSpec &spec) { CharPtr out = CharPtr(); if (spec.width() > size) { out = grow_buffer(spec.width()); @@ -2626,8 +2587,8 @@ typename BasicWriter::CharPtr BasicWriter::write_str( template template -void BasicWriter::write_str( - const internal::Arg::StringValue &s, const FormatSpec &spec) { +void BasicWriter::write_str(const internal::Arg::StringValue &s, + const FormatSpec &spec) { // Check if StrChar is convertible to Char. internal::CharTraits::convert(StrChar()); if (spec.type_ && spec.type_ != 's') @@ -2647,26 +2608,25 @@ void BasicWriter::write_str( template typename BasicWriter::CharPtr - BasicWriter::fill_padding( - CharPtr buffer, unsigned total_size, - std::size_t content_size, wchar_t fill) { +BasicWriter::fill_padding(CharPtr buffer, unsigned total_size, + std::size_t content_size, wchar_t fill) { std::size_t padding = total_size - content_size; std::size_t left_padding = padding / 2; Char fill_char = internal::CharTraits::cast(fill); std::uninitialized_fill_n(buffer, left_padding, fill_char); buffer += left_padding; CharPtr content = buffer; - std::uninitialized_fill_n(buffer + content_size, - padding - left_padding, fill_char); + std::uninitialized_fill_n(buffer + content_size, padding - left_padding, + fill_char); return content; } template template typename BasicWriter::CharPtr - BasicWriter::prepare_int_buffer( - unsigned num_digits, const Spec &spec, - const char *prefix, unsigned prefix_size) { +BasicWriter::prepare_int_buffer(unsigned num_digits, const Spec &spec, + const char *prefix, + unsigned prefix_size) { unsigned width = spec.width(); Alignment align = spec.align(); Char fill = internal::CharTraits::cast(spec.fill()); @@ -2686,8 +2646,8 @@ typename BasicWriter::CharPtr CharPtr p = grow_buffer(fill_size); std::uninitialized_fill(p, p + fill_size, fill); } - CharPtr result = prepare_int_buffer( - num_digits, subspec, prefix, prefix_size); + CharPtr result = + prepare_int_buffer(num_digits, subspec, prefix, prefix_size); if (align == ALIGN_LEFT) { CharPtr p = grow_buffer(fill_size); std::uninitialized_fill(p, p + fill_size, fill); @@ -2741,13 +2701,15 @@ void BasicWriter::write_int(T value, Spec spec) { ++prefix_size; } switch (spec.type()) { - case 0: case 'd': { + case 0: + case 'd': { unsigned num_digits = internal::count_digits(abs_value); CharPtr p = prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1; internal::format_decimal(get(p), abs_value, 0); break; } - case 'x': case 'X': { + case 'x': + case 'X': { UnsignedType n = abs_value; if (spec.flag(HASH_FLAG)) { prefix[prefix_size++] = '0'; @@ -2757,17 +2719,17 @@ void BasicWriter::write_int(T value, Spec spec) { do { ++num_digits; } while ((n >>= 4) != 0); - Char *p = get(prepare_int_buffer( - num_digits, spec, prefix, prefix_size)); + Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size)); n = abs_value; - const char *digits = spec.type() == 'x' ? - "0123456789abcdef" : "0123456789ABCDEF"; + const char *digits = + spec.type() == 'x' ? "0123456789abcdef" : "0123456789ABCDEF"; do { *p-- = digits[n & 0xf]; } while ((n >>= 4) != 0); break; } - case 'b': case 'B': { + case 'b': + case 'B': { UnsignedType n = abs_value; if (spec.flag(HASH_FLAG)) { prefix[prefix_size++] = '0'; @@ -2805,15 +2767,15 @@ void BasicWriter::write_int(T value, Spec spec) { #ifndef ANDROID sep = internal::thousands_sep(std::localeconv()); #endif - unsigned size = static_cast( - num_digits + sep.size() * ((num_digits - 1) / 3)); + unsigned size = + static_cast(num_digits + sep.size() * ((num_digits - 1) / 3)); CharPtr p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1; internal::format_decimal(get(p), abs_value, 0, internal::ThousandsSep(sep)); break; } default: - internal::report_unknown_type( - spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer"); + internal::report_unknown_type(spec.type(), + spec.flag(CHAR_FLAG) ? "char" : "integer"); break; } } @@ -2828,7 +2790,10 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) { case 0: type = 'g'; break; - case 'e': case 'f': case 'g': case 'a': + case 'e': + case 'f': + case 'g': + case 'a': break; case 'F': #if FMT_MSC_VER @@ -2836,7 +2801,9 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) { type = 'f'; #endif // Fall through. - case 'E': case 'G': case 'A': + case 'E': + case 'G': + case 'A': upper = true; break; default: @@ -2894,7 +2861,7 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) { } // Build format string. - enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg + enum { MAX_FORMAT_SIZE = 10 }; // longest format: %#-*.*Lg Char format[MAX_FORMAT_SIZE]; Char *format_ptr = format; *format_ptr++ = '%'; @@ -2939,7 +2906,7 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) { if (result >= 0) { n = internal::to_unsigned(result); if (offset + n < buffer_.capacity()) - break; // The buffer is large enough - continue with formatting. + break; // The buffer is large enough - continue with formatting. buffer_.reserve(offset + n + 1); } else { // If result is negative we ask to increase the capacity by at least 1, @@ -3007,14 +2974,14 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) { accessed as a C string with ``out.c_str()``. \endrst */ -template > +template > class BasicMemoryWriter : public BasicWriter { - private: +private: internal::MemoryBuffer buffer_; - public: - explicit BasicMemoryWriter(const Allocator& alloc = Allocator()) - : BasicWriter(buffer_), buffer_(alloc) {} +public: + explicit BasicMemoryWriter(const Allocator &alloc = Allocator()) + : BasicWriter(buffer_), buffer_(alloc) {} #if FMT_USE_RVALUE_REFERENCES /** @@ -3024,8 +2991,7 @@ class BasicMemoryWriter : public BasicWriter { \endrst */ BasicMemoryWriter(BasicMemoryWriter &&other) - : BasicWriter(buffer_), buffer_(std::move(other.buffer_)) { - } + : BasicWriter(buffer_), buffer_(std::move(other.buffer_)) {} /** \rst @@ -3062,12 +3028,11 @@ typedef BasicMemoryWriter WMemoryWriter; +--------------+---------------------------+ \endrst */ -template -class BasicArrayWriter : public BasicWriter { - private: +template class BasicArrayWriter : public BasicWriter { +private: internal::FixedBuffer buffer_; - public: +public: /** \rst Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the @@ -3075,7 +3040,7 @@ class BasicArrayWriter : public BasicWriter { \endrst */ BasicArrayWriter(Char *array, std::size_t size) - : BasicWriter(buffer_), buffer_(array, size) {} + : BasicWriter(buffer_), buffer_(array, size) {} /** \rst @@ -3085,7 +3050,7 @@ class BasicArrayWriter : public BasicWriter { */ template explicit BasicArrayWriter(Char (&array)[SIZE]) - : BasicWriter(buffer_), buffer_(array, SIZE) {} + : BasicWriter(buffer_), buffer_(array, SIZE) {} }; typedef BasicArrayWriter ArrayWriter; @@ -3100,10 +3065,10 @@ FMT_API void report_system_error(int error_code, /** A Windows error. */ class WindowsError : public SystemError { - private: +private: FMT_API void init(int error_code, CStringRef format_str, ArgList args); - public: +public: /** \rst Constructs a :class:`fmt::WindowsError` object with the description @@ -3252,10 +3217,10 @@ inline int printf(CStringRef format, ArgList args) { Fast integer formatter. */ class FormatInt { - private: +private: // Buffer should be large enough to hold all digits (digits10 + 1), // a sign and a null character. - enum {BUFFER_SIZE = std::numeric_limits::digits10 + 3}; + enum { BUFFER_SIZE = std::numeric_limits::digits10 + 3 }; mutable char buffer_[BUFFER_SIZE]; char *str_; @@ -3291,7 +3256,7 @@ class FormatInt { *--str_ = '-'; } - public: +public: explicit FormatInt(int value) { FormatSigned(value); } explicit FormatInt(long value) { FormatSigned(value); } explicit FormatInt(LongLong value) { FormatSigned(value); } @@ -3330,8 +3295,7 @@ class FormatInt { // Formats a decimal integer value writing into buffer and returns // a pointer to the end of the formatted string. This function doesn't // write a terminating null character. -template -inline void format_decimal(char *&buffer, T value) { +template inline void format_decimal(char *&buffer, T value) { typedef typename internal::IntTraits::MainType MainType; MainType abs_value = static_cast(value); if (internal::is_negative(value)) { @@ -3376,17 +3340,17 @@ inline internal::NamedArg arg(WStringRef name, const T &arg) { // The following two functions are deleted intentionally to disable // nested named arguments as in ``format("{}", arg("a", arg("b", 42)))``. template -void arg(StringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; +void arg(StringRef, const internal::NamedArg &) FMT_DELETED_OR_UNDEFINED; template -void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; -} +void arg(WStringRef, const internal::NamedArg &) FMT_DELETED_OR_UNDEFINED; +} // namespace fmt #if FMT_GCC_VERSION // Use the system_header pragma to suppress warnings about variadic macros // because suppressing -Wvariadic-macros with the diagnostic pragma doesn't // work. It is used at the end because we want to suppress as little warnings // as possible. -# pragma GCC system_header +#pragma GCC system_header #endif // This is used to work around VC++ bugs in handling variadic macros. @@ -3400,58 +3364,59 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; #define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define FMT_CONCAT(a, b) a##b -#define FMT_FOR_EACH_(N, f, ...) \ +#define FMT_FOR_EACH_(N, f, ...) \ FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__)) -#define FMT_FOR_EACH(f, ...) \ +#define FMT_FOR_EACH(f, ...) \ FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__)) #define FMT_ADD_ARG_NAME(type, index) type arg##index #define FMT_GET_ARG_NAME(type, index) arg##index #if FMT_USE_VARIADIC_TEMPLATES -# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ - template \ - ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ - const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ - fmt::ArgList(fmt::internal::make_type(args...), array)); \ +#define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ + template \ + ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ + const Args &... args) { \ + typedef fmt::internal::ArgArray ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make>(args)...}; \ + call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ + fmt::ArgList(fmt::internal::make_type(args...), array)); \ } #else // Defines a wrapper for a function taking __VA_ARGS__ arguments // and n additional arguments of arbitrary types. -# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \ - template \ - inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ - FMT_GEN(n, FMT_MAKE_ARG)) { \ - fmt::internal::ArgArray::Type arr; \ - FMT_GEN(n, FMT_ASSIGN_##Char); \ - call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \ - fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \ - } - -# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ - inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \ - call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \ - } \ - FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 11, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 12, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 13, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 14, __VA_ARGS__) \ +#define FMT_WRAP(Char, ReturnType, func, call, n, ...) \ + template \ + inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ + FMT_GEN(n, FMT_MAKE_ARG)) { \ + fmt::internal::ArgArray::Type arr; \ + FMT_GEN(n, FMT_ASSIGN_##Char); \ + call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ + fmt::ArgList(fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), \ + arr)); \ + } + +#define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ + inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \ + call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \ + } \ + FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 11, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 12, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 13, __VA_ARGS__) \ + FMT_WRAP(Char, ReturnType, func, call, 14, __VA_ARGS__) \ FMT_WRAP(Char, ReturnType, func, call, 15, __VA_ARGS__) -#endif // FMT_USE_VARIADIC_TEMPLATES +#endif // FMT_USE_VARIADIC_TEMPLATES /** \rst @@ -3480,15 +3445,15 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; } \endrst */ -#define FMT_VARIADIC(ReturnType, func, ...) \ +#define FMT_VARIADIC(ReturnType, func, ...) \ FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__) -#define FMT_VARIADIC_W(ReturnType, func, ...) \ +#define FMT_VARIADIC_W(ReturnType, func, ...) \ FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__) #define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id) -#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id) +#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L## #id, id) /** \rst @@ -3521,15 +3486,13 @@ FMT_VARIADIC(int, printf, CStringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) namespace internal { -template -inline bool is_name_start(Char c) { +template inline bool is_name_start(Char c) { return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c; } // Parses an unsigned integer advancing s to the end of the parsed input. // This function assumes that the first character of s is a digit. -template -unsigned parse_nonnegative_int(const Char *&s) { +template unsigned parse_nonnegative_int(const Char *&s) { assert('0' <= *s && *s <= '9'); unsigned value = 0; do { @@ -3556,21 +3519,21 @@ inline void require_numeric_argument(const Arg &arg, char spec) { } } -template -void check_sign(const Char *&s, const Arg &arg) { +template void check_sign(const Char *&s, const Arg &arg) { char sign = static_cast(*s); require_numeric_argument(arg, sign); if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) { - FMT_THROW(FormatError(fmt::format( - "format specifier '{}' requires signed argument", sign))); + FMT_THROW(FormatError( + fmt::format("format specifier '{}' requires signed argument", sign))); } ++s; } -} // namespace internal +} // namespace internal template -inline internal::Arg BasicFormatter::get_arg( - BasicStringRef arg_name, const char *&error) { +inline internal::Arg +BasicFormatter::get_arg(BasicStringRef arg_name, + const char *&error) { if (check_no_auto_index(error)) { map_.init(args()); const internal::Arg *arg = map_.find(arg_name); @@ -3584,11 +3547,12 @@ inline internal::Arg BasicFormatter::get_arg( template inline internal::Arg BasicFormatter::parse_arg_index(const Char *&s) { const char *error = 0; - internal::Arg arg = *s < '0' || *s > '9' ? - next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error); + internal::Arg arg = *s < '0' || *s > '9' + ? next_arg(error) + : get_arg(internal::parse_nonnegative_int(s), error); if (error) { - FMT_THROW(FormatError( - *s != '}' && *s != ':' ? "invalid format string" : error)); + FMT_THROW( + FormatError(*s != '}' && *s != ':' ? "invalid format string" : error)); } return arg; } @@ -3609,8 +3573,9 @@ inline internal::Arg BasicFormatter::parse_arg_name(const Char *&s) { } template -const Char *BasicFormatter::format( - const Char *&format_str, const internal::Arg &arg) { +const Char * +BasicFormatter::format(const Char *&format_str, + const internal::Arg &arg) { using internal::Arg; const Char *s = format_str; FormatSpec spec; @@ -3626,27 +3591,29 @@ const Char *BasicFormatter::format( spec.align_ = ALIGN_DEFAULT; do { switch (*p) { - case '<': - spec.align_ = ALIGN_LEFT; - break; - case '>': - spec.align_ = ALIGN_RIGHT; - break; - case '=': - spec.align_ = ALIGN_NUMERIC; - break; - case '^': - spec.align_ = ALIGN_CENTER; - break; + case '<': + spec.align_ = ALIGN_LEFT; + break; + case '>': + spec.align_ = ALIGN_RIGHT; + break; + case '=': + spec.align_ = ALIGN_NUMERIC; + break; + case '^': + spec.align_ = ALIGN_CENTER; + break; } if (spec.align_ != ALIGN_DEFAULT) { if (p != s) { - if (c == '}') break; + if (c == '}') + break; if (c == '{') FMT_THROW(FormatError("invalid fill character '{'")); s += 2; spec.fill_ = c; - } else ++s; + } else + ++s; if (spec.align_ == ALIGN_NUMERIC) require_numeric_argument(arg, '='); break; @@ -3656,18 +3623,18 @@ const Char *BasicFormatter::format( // Parse sign. switch (*s) { - case '+': - check_sign(s, arg); - spec.flags_ |= SIGN_FLAG | PLUS_FLAG; - break; - case '-': - check_sign(s, arg); - spec.flags_ |= MINUS_FLAG; - break; - case ' ': - check_sign(s, arg); - spec.flags_ |= SIGN_FLAG; - break; + case '+': + check_sign(s, arg); + spec.flags_ |= SIGN_FLAG | PLUS_FLAG; + break; + case '-': + check_sign(s, arg); + spec.flags_ |= MINUS_FLAG; + break; + case ' ': + check_sign(s, arg); + spec.flags_ |= SIGN_FLAG; + break; } if (*s == '#') { @@ -3689,8 +3656,8 @@ const Char *BasicFormatter::format( spec.width_ = internal::parse_nonnegative_int(s); } else if (*s == '{') { ++s; - Arg width_arg = internal::is_name_start(*s) ? - parse_arg_name(s) : parse_arg_index(s); + Arg width_arg = + internal::is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s); if (*s++ != '}') FMT_THROW(FormatError("invalid format string")); ULongLong value = 0; @@ -3727,30 +3694,30 @@ const Char *BasicFormatter::format( spec.precision_ = internal::parse_nonnegative_int(s); } else if (*s == '{') { ++s; - Arg precision_arg = internal::is_name_start(*s) ? - parse_arg_name(s) : parse_arg_index(s); + Arg precision_arg = internal::is_name_start(*s) ? parse_arg_name(s) + : parse_arg_index(s); if (*s++ != '}') FMT_THROW(FormatError("invalid format string")); ULongLong value = 0; switch (precision_arg.type) { - case Arg::INT: - if (precision_arg.int_value < 0) - FMT_THROW(FormatError("negative precision")); - value = precision_arg.int_value; - break; - case Arg::UINT: - value = precision_arg.uint_value; - break; - case Arg::LONG_LONG: - if (precision_arg.long_long_value < 0) - FMT_THROW(FormatError("negative precision")); - value = precision_arg.long_long_value; - break; - case Arg::ULONG_LONG: - value = precision_arg.ulong_long_value; - break; - default: - FMT_THROW(FormatError("precision is not integer")); + case Arg::INT: + if (precision_arg.int_value < 0) + FMT_THROW(FormatError("negative precision")); + value = precision_arg.int_value; + break; + case Arg::UINT: + value = precision_arg.uint_value; + break; + case Arg::LONG_LONG: + if (precision_arg.long_long_value < 0) + FMT_THROW(FormatError("negative precision")); + value = precision_arg.long_long_value; + break; + case Arg::ULONG_LONG: + value = precision_arg.ulong_long_value; + break; + default: + FMT_THROW(FormatError("precision is not integer")); } if (value > (std::numeric_limits::max)()) FMT_THROW(FormatError("number is too big")); @@ -3761,7 +3728,7 @@ const Char *BasicFormatter::format( if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) { FMT_THROW(FormatError( fmt::format("precision not allowed in {} format specifier", - arg.type == Arg::POINTER ? "pointer" : "integer"))); + arg.type == Arg::POINTER ? "pointer" : "integer"))); } } @@ -3784,7 +3751,8 @@ void BasicFormatter::format(BasicCStringRef format_str) { const Char *start = s; while (*s) { Char c = *s++; - if (c != '{' && c != '}') continue; + if (c != '{' && c != '}') + continue; if (*s == c) { write(writer_, start, s); start = ++s; @@ -3793,35 +3761,32 @@ void BasicFormatter::format(BasicCStringRef format_str) { if (c == '}') FMT_THROW(FormatError("unmatched '}' in format string")); write(writer_, start, s - 1); - internal::Arg arg = internal::is_name_start(*s) ? - parse_arg_name(s) : parse_arg_index(s); + internal::Arg arg = + internal::is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s); start = s = format(s, arg); } write(writer_, start, s); } -} // namespace fmt +} // namespace fmt #if FMT_USE_USER_DEFINED_LITERALS namespace fmt { namespace internal { -template -struct UdlFormat { +template struct UdlFormat { const Char *str; template - auto operator()(Args && ... args) const - -> decltype(format(str, std::forward(args)...)) { + auto operator()(Args &&... args) const + -> decltype(format(str, std::forward(args)...)) { return format(str, std::forward(args)...); } }; -template -struct UdlArg { +template struct UdlArg { const Char *str; - template - NamedArg operator=(T &&value) const { + template NamedArg operator=(T &&value) const { return {str, std::forward(value)}; } }; @@ -3840,10 +3805,14 @@ inline namespace literals { std::string message = "The answer is {}"_format(42); \endrst */ -inline internal::UdlFormat -operator"" _format(const char *s, std::size_t) { return {s}; } -inline internal::UdlFormat -operator"" _format(const wchar_t *s, std::size_t) { return {s}; } +inline internal::UdlFormat operator"" _format(const char *s, + std::size_t) { + return {s}; +} +inline internal::UdlFormat operator"" _format(const wchar_t *s, + std::size_t) { + return {s}; +} /** \rst @@ -3855,29 +3824,31 @@ operator"" _format(const wchar_t *s, std::size_t) { return {s}; } print("Elapsed time: {s:.2f} seconds", "s"_a=1.23); \endrst */ -inline internal::UdlArg -operator"" _a(const char *s, std::size_t) { return {s}; } -inline internal::UdlArg -operator"" _a(const wchar_t *s, std::size_t) { return {s}; } +inline internal::UdlArg operator"" _a(const char *s, std::size_t) { + return {s}; +} +inline internal::UdlArg operator"" _a(const wchar_t *s, std::size_t) { + return {s}; +} -} // inline namespace literals +} // namespace literals } // namespace fmt #endif // FMT_USE_USER_DEFINED_LITERALS // Restore warnings. #if FMT_GCC_VERSION >= 406 -# pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif #if defined(__clang__) && !defined(FMT_ICC_VERSION) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif #ifdef FMT_HEADER_ONLY -# define FMT_FUNC inline -# include "format.cc" +#define FMT_FUNC inline +#include "format.cc" #else -# define FMT_FUNC +#define FMT_FUNC #endif -#endif // FMT_FORMAT_H_ +#endif // FMT_FORMAT_H_ diff --git a/external/spdlog/fmt/bundled/ostream.cc b/external/spdlog/fmt/bundled/ostream.cc index bcb67fe..f3873ae 100644 --- a/external/spdlog/fmt/bundled/ostream.cc +++ b/external/spdlog/fmt/bundled/ostream.cc @@ -26,7 +26,7 @@ void write(std::ostream &os, Writer &w) { size -= n; } while (size != 0); } -} +} // namespace FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) { MemoryWriter w; @@ -40,4 +40,4 @@ FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) { write(os, w); return static_cast(w.size()); } -} // namespace fmt +} // namespace fmt diff --git a/external/spdlog/fmt/bundled/ostream.h b/external/spdlog/fmt/bundled/ostream.h index 29483c1..a35f74d 100644 --- a/external/spdlog/fmt/bundled/ostream.h +++ b/external/spdlog/fmt/bundled/ostream.h @@ -17,16 +17,15 @@ namespace fmt { namespace internal { -template -class FormatBuf : public std::basic_streambuf { - private: +template class FormatBuf : public std::basic_streambuf { +private: typedef typename std::basic_streambuf::int_type int_type; typedef typename std::basic_streambuf::traits_type traits_type; Buffer &buffer_; Char *start_; - public: +public: FormatBuf(Buffer &buffer) : buffer_(buffer), start_(&buffer[0]) { this->setp(start_, start_ + buffer_.capacity()); } @@ -39,39 +38,36 @@ class FormatBuf : public std::basic_streambuf { start_ = &buffer_[0]; start_[buf_size] = traits_type::to_char_type(ch); - this->setp(start_+ buf_size + 1, start_ + buf_size * 2); + this->setp(start_ + buf_size + 1, start_ + buf_size * 2); } return ch; } - size_t size() const { - return to_unsigned(this->pptr() - start_); - } + size_t size() const { return to_unsigned(this->pptr() - start_); } }; Yes &convert(std::ostream &); struct DummyStream : std::ostream { - DummyStream(); // Suppress a bogus warning in MSVC. + DummyStream(); // Suppress a bogus warning in MSVC. // Hide all operator<< overloads from std::ostream. void operator<<(Null<>); }; No &operator<<(std::ostream &, int); -template -struct ConvertToIntImpl { +template struct ConvertToIntImpl { // Convert to int only if T doesn't have an overloaded operator<<. enum { value = sizeof(convert(get() << get())) == sizeof(No) }; }; -} // namespace internal +} // namespace internal // Formats a value. template -void format(BasicFormatter &f, - const Char *&format_str, const T &value) { +void format(BasicFormatter &f, const Char *&format_str, + const T &value) { internal::MemoryBuffer buffer; internal::FormatBuf format_buf(buffer); @@ -79,7 +75,7 @@ void format(BasicFormatter &f, output << value; BasicStringRef str(&buffer[0], format_buf.size()); - typedef internal::MakeArg< BasicFormatter > MakeArg; + typedef internal::MakeArg> MakeArg; format_str = f.format(format_str, MakeArg(str)); } @@ -106,10 +102,10 @@ FMT_VARIADIC(void, print, std::ostream &, CStringRef) */ FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args); FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) -} // namespace fmt +} // namespace fmt #ifdef FMT_HEADER_ONLY -# include "ostream.cc" +#include "ostream.cc" #endif -#endif // FMT_OSTREAM_H_ +#endif // FMT_OSTREAM_H_ diff --git a/external/spdlog/fmt/bundled/posix.cc b/external/spdlog/fmt/bundled/posix.cc index 76eb7f0..096218e 100644 --- a/external/spdlog/fmt/bundled/posix.cc +++ b/external/spdlog/fmt/bundled/posix.cc @@ -9,40 +9,40 @@ // Disable bogus MSVC warnings. #ifndef _CRT_SECURE_NO_WARNINGS -# define _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS #endif #include "posix.h" #include -#include #include +#include #ifndef _WIN32 -# include +#include #else -# include -# include +#include +#include -# define O_CREAT _O_CREAT -# define O_TRUNC _O_TRUNC +#define O_CREAT _O_CREAT +#define O_TRUNC _O_TRUNC -# ifndef S_IRUSR -# define S_IRUSR _S_IREAD -# endif +#ifndef S_IRUSR +#define S_IRUSR _S_IREAD +#endif -# ifndef S_IWUSR -# define S_IWUSR _S_IWRITE -# endif +#ifndef S_IWUSR +#define S_IWUSR _S_IWRITE +#endif -# ifdef __MINGW32__ -# define _SH_DENYNO 0x40 -# endif +#ifdef __MINGW32__ +#define _SH_DENYNO 0x40 +#endif -#endif // _WIN32 +#endif // _WIN32 #ifdef fileno -# undef fileno +#undef fileno #endif namespace { @@ -61,15 +61,15 @@ typedef ssize_t RWResult; inline std::size_t convert_rwcount(std::size_t count) { return count; } #endif -} +} // namespace fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT { if (file_ && FMT_SYSTEM(fclose(file_)) != 0) fmt::report_system_error(errno, "cannot close file"); } -fmt::BufferedFile::BufferedFile( - fmt::CStringRef filename, fmt::CStringRef mode) { +fmt::BufferedFile::BufferedFile(fmt::CStringRef filename, + fmt::CStringRef mode) { FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0); if (!file_) FMT_THROW(SystemError(errno, "cannot open file {}", filename)); @@ -145,7 +145,7 @@ fmt::LongLong fmt::File::size() const { if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1) FMT_THROW(SystemError(errno, "cannot get file attributes")); FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size), - "return type of File::size is not large enough"); + "return type of File::size is not large enough"); return file_stat.st_size; #endif } @@ -179,8 +179,8 @@ void fmt::File::dup2(int fd) { int result = 0; FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); if (result == -1) { - FMT_THROW(SystemError(errno, - "cannot duplicate file descriptor {} to {}", fd_, fd)); + FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {} to {}", + fd_, fd)); } } @@ -218,7 +218,8 @@ fmt::BufferedFile fmt::File::fdopen(const char *mode) { // Don't retry as fdopen doesn't return EINTR. FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode)); if (!f) - FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor")); + FMT_THROW( + SystemError(errno, "cannot associate stream with file descriptor")); BufferedFile file(f); fd_ = -1; return file; diff --git a/external/spdlog/fmt/bundled/posix.h b/external/spdlog/fmt/bundled/posix.h index be1286c..76ff8fd 100644 --- a/external/spdlog/fmt/bundled/posix.h +++ b/external/spdlog/fmt/bundled/posix.h @@ -12,73 +12,73 @@ #if defined(__MINGW32__) || defined(__CYGWIN__) // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/. -# undef __STRICT_ANSI__ +#undef __STRICT_ANSI__ #endif #include -#include // for O_RDONLY -#include // for locale_t +#include // for O_RDONLY +#include // for locale_t #include -#include // for strtod_l +#include // for strtod_l #include #if defined __APPLE__ || defined(__FreeBSD__) -# include // for LC_NUMERIC_MASK on OS X +#include // for LC_NUMERIC_MASK on OS X #endif #include "format.h" #ifndef FMT_POSIX -# if defined(_WIN32) && !defined(__MINGW32__) +#if defined(_WIN32) && !defined(__MINGW32__) // Fix warnings about deprecated symbols. -# define FMT_POSIX(call) _##call -# else -# define FMT_POSIX(call) call -# endif +#define FMT_POSIX(call) _##call +#else +#define FMT_POSIX(call) call +#endif #endif // Calls to system functions are wrapped in FMT_SYSTEM for testability. #ifdef FMT_SYSTEM -# define FMT_POSIX_CALL(call) FMT_SYSTEM(call) +#define FMT_POSIX_CALL(call) FMT_SYSTEM(call) #else -# define FMT_SYSTEM(call) call -# ifdef _WIN32 +#define FMT_SYSTEM(call) call +#ifdef _WIN32 // Fix warnings about deprecated symbols. -# define FMT_POSIX_CALL(call) ::_##call -# else -# define FMT_POSIX_CALL(call) ::call -# endif +#define FMT_POSIX_CALL(call) ::_##call +#else +#define FMT_POSIX_CALL(call) ::call +#endif #endif #if FMT_GCC_VERSION >= 407 -# define FMT_UNUSED __attribute__((unused)) +#define FMT_UNUSED __attribute__((unused)) #else -# define FMT_UNUSED +#define FMT_UNUSED #endif #ifndef FMT_USE_STATIC_ASSERT -# define FMT_USE_STATIC_ASSERT 0 +#define FMT_USE_STATIC_ASSERT 0 #endif -#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \ - (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600 -# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message) +#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \ + (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600 +#define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message) #else -# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b) -# define FMT_STATIC_ASSERT(cond, message) \ +#define FMT_CONCAT_(a, b) FMT_CONCAT(a, b) +#define FMT_STATIC_ASSERT(cond, message) \ typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED #endif // Retries the expression while it evaluates to error_result and errno // equals to EINTR. #ifndef _WIN32 -# define FMT_RETRY_VAL(result, expression, error_result) \ - do { \ - result = (expression); \ +#define FMT_RETRY_VAL(result, expression, error_result) \ + do { \ + result = (expression); \ } while (result == error_result && errno == EINTR) #else -# define FMT_RETRY_VAL(result, expression, error_result) result = (expression) +#define FMT_RETRY_VAL(result, expression, error_result) result = (expression) #endif #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) @@ -87,10 +87,10 @@ namespace fmt { // An error code. class ErrorCode { - private: +private: int value_; - public: +public: explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {} int get() const FMT_NOEXCEPT { return value_; } @@ -98,14 +98,14 @@ class ErrorCode { // A buffered file. class BufferedFile { - private: +private: FILE *file_; friend class File; explicit BufferedFile(FILE *f) : file_(f) {} - public: +public: // Constructs a BufferedFile object which doesn't represent any file. BufferedFile() FMT_NOEXCEPT : file_(0) {} @@ -116,7 +116,7 @@ class BufferedFile { // Emulate a move constructor and a move assignment operator if rvalue // references are not supported. - private: +private: // A proxy object to emulate a move constructor. // It is private to make it impossible call operator Proxy directly. struct Proxy { @@ -128,9 +128,7 @@ class BufferedFile { BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {} // A "move constructor" for moving from an lvalue. - BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) { - f.file_ = 0; - } + BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) { f.file_ = 0; } // A "move assignment operator" for moving from a temporary. BufferedFile &operator=(Proxy p) { @@ -156,15 +154,15 @@ class BufferedFile { } #else - private: +private: FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile); - public: +public: BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) { other.file_ = 0; } - BufferedFile& operator=(BufferedFile &&other) { + BufferedFile &operator=(BufferedFile &&other) { close(); file_ = other.file_; other.file_ = 0; @@ -183,7 +181,7 @@ class BufferedFile { // We place parentheses around fileno to workaround a bug in some versions // of MinGW that define fileno as a macro. - int (fileno)() const; + int(fileno)() const; void print(CStringRef format_str, const ArgList &args) { fmt::print(file_, format_str, args); @@ -198,18 +196,18 @@ class BufferedFile { // than an exception. You can get standard behavior by overriding the // invalid parameter handler with _set_invalid_parameter_handler. class File { - private: - int fd_; // File descriptor. +private: + int fd_; // File descriptor. // Constructs a File object with a given descriptor. explicit File(int fd) : fd_(fd) {} - public: +public: // Possible values for the oflag argument to the constructor. enum { RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only. WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only. - RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing. + RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing. }; // Constructs a File object which doesn't represent any file. @@ -222,21 +220,19 @@ class File { // Emulate a move constructor and a move assignment operator if rvalue // references are not supported. - private: +private: // A proxy object to emulate a move constructor. // It is private to make it impossible call operator Proxy directly. struct Proxy { int fd; }; - public: +public: // A "move constructor" for moving from a temporary. File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {} // A "move constructor" for moving from an lvalue. - File(File &other) FMT_NOEXCEPT : fd_(other.fd_) { - other.fd_ = -1; - } + File(File &other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } // A "move assignment operator" for moving from a temporary. File &operator=(Proxy p) { @@ -262,15 +258,13 @@ class File { } #else - private: +private: FMT_DISALLOW_COPY_AND_ASSIGN(File); - public: - File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) { - other.fd_ = -1; - } +public: + File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } - File& operator=(File &&other) { + File &operator=(File &&other) { close(); fd_ = other.fd_; other.fd_ = -1; @@ -321,16 +315,16 @@ class File { // Returns the memory page size. long getpagesize(); -#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \ +#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \ !defined(__ANDROID__) && !defined(__CYGWIN__) -# define FMT_LOCALE +#define FMT_LOCALE #endif #ifdef FMT_LOCALE // A "C" numeric locale. class Locale { - private: -# ifdef _MSC_VER +private: +#ifdef _MSC_VER typedef _locale_t locale_t; enum { LC_NUMERIC_MASK = LC_NUMERIC }; @@ -339,20 +333,18 @@ class Locale { return _create_locale(category_mask, locale); } - static void freelocale(locale_t locale) { - _free_locale(locale); - } + static void freelocale(locale_t locale) { _free_locale(locale); } static double strtod_l(const char *nptr, char **endptr, _locale_t locale) { return _strtod_l(nptr, endptr, locale); } -# endif +#endif locale_t locale_; FMT_DISALLOW_COPY_AND_ASSIGN(Locale); - public: +public: typedef locale_t Type; Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) { @@ -372,15 +364,15 @@ class Locale { return result; } }; -#endif // FMT_LOCALE -} // namespace fmt +#endif // FMT_LOCALE +} // namespace fmt #if !FMT_USE_RVALUE_REFERENCES namespace std { // For compatibility with C++98. inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; } inline fmt::File &move(fmt::File &f) { return f; } -} +} // namespace std #endif -#endif // FMT_POSIX_H_ +#endif // FMT_POSIX_H_ diff --git a/external/spdlog/fmt/bundled/time.h b/external/spdlog/fmt/bundled/time.h index 10225c0..a420ebe 100644 --- a/external/spdlog/fmt/bundled/time.h +++ b/external/spdlog/fmt/bundled/time.h @@ -15,8 +15,8 @@ namespace fmt { template -void format(BasicFormatter &f, - const char *&format_str, const std::tm &tm) { +void format(BasicFormatter &f, const char *&format_str, + const std::tm &tm) { if (*format_str == ':') ++format_str; const char *end = format_str; @@ -48,6 +48,6 @@ void format(BasicFormatter &f, } format_str = end + 1; } -} +} // namespace fmt -#endif // FMT_TIME_H_ +#endif // FMT_TIME_H_ diff --git a/external/spdlog/fmt/fmt.h b/external/spdlog/fmt/fmt.h index dd035fd..c1dd7c6 100644 --- a/external/spdlog/fmt/fmt.h +++ b/external/spdlog/fmt/fmt.h @@ -20,9 +20,8 @@ #endif #include -#else //external fmtlib +#else // external fmtlib #include #endif - diff --git a/external/spdlog/fmt/ostr.h b/external/spdlog/fmt/ostr.h index 7a65186..2f7efb8 100644 --- a/external/spdlog/fmt/ostr.h +++ b/external/spdlog/fmt/ostr.h @@ -8,10 +8,8 @@ // include external or bundled copy of fmtlib's ostream support // #if !defined(SPDLOG_FMT_EXTERNAL) -#include #include +#include #else #include #endif - - diff --git a/external/spdlog/formatter.h b/external/spdlog/formatter.h index 0ffcec0..1705677 100644 --- a/external/spdlog/formatter.h +++ b/external/spdlog/formatter.h @@ -7,39 +7,35 @@ #include -#include -#include #include +#include +#include -namespace spdlog -{ -namespace details -{ +namespace spdlog { +namespace details { class flag_formatter; } -class formatter -{ +class formatter { public: - virtual ~formatter() {} - virtual void format(details::log_msg& msg) = 0; + virtual ~formatter() {} + virtual void format(details::log_msg &msg) = 0; }; -class pattern_formatter : public formatter -{ +class pattern_formatter : public formatter { public: - explicit pattern_formatter(const std::string& pattern); - pattern_formatter(const pattern_formatter&) = delete; - pattern_formatter& operator=(const pattern_formatter&) = delete; - void format(details::log_msg& msg) override; + explicit pattern_formatter(const std::string &pattern); + pattern_formatter(const pattern_formatter &) = delete; + pattern_formatter &operator=(const pattern_formatter &) = delete; + void format(details::log_msg &msg) override; + private: - const std::string _pattern; - std::vector> _formatters; - void handle_flag(char flag); - void compile_pattern(const std::string& pattern); + const std::string _pattern; + std::vector> _formatters; + void handle_flag(char flag); + void compile_pattern(const std::string &pattern); }; -} +} // namespace spdlog #include - diff --git a/external/spdlog/logger.h b/external/spdlog/logger.h index a2deb51..7b124f5 100644 --- a/external/spdlog/logger.h +++ b/external/spdlog/logger.h @@ -5,90 +5,90 @@ #pragma once -// Thread safe logger (except for set_pattern(..), set_formatter(..) and set_error_handler()) -// Has name, log level, vector of std::shared sink pointers and formatter -// Upon each log write the logger: +// Thread safe logger (except for set_pattern(..), set_formatter(..) and +// set_error_handler()) Has name, log level, vector of std::shared sink pointers +// and formatter Upon each log write the logger: // 1. Checks if its log level is enough to log the message // 2. Format the message using the formatter function // 3. Pass the formatted message to its sinks to performa the actual logging -#include #include +#include -#include #include #include +#include -namespace spdlog -{ +namespace spdlog { -class logger -{ +class logger { public: - logger(const std::string& logger_name, sink_ptr single_sink); - logger(const std::string& name, sinks_init_list); - template - logger(const std::string& name, const It& begin, const It& end); - - virtual ~logger(); - logger(const logger&) = delete; - logger& operator=(const logger&) = delete; - - - template void log(level::level_enum lvl, const char* fmt, const Args&... args); - template void log(level::level_enum lvl, const char* msg); - template void trace(const char* fmt, const Args&... args); - template void debug(const char* fmt, const Args&... args); - template void info(const char* fmt, const Args&... args); - template void warn(const char* fmt, const Args&... args); - template void error(const char* fmt, const Args&... args); - template void critical(const char* fmt, const Args&... args); - - template void log(level::level_enum lvl, const T&); - template void trace(const T&); - template void debug(const T&); - template void info(const T&); - template void warn(const T&); - template void error(const T&); - template void critical(const T&); - - bool should_log(level::level_enum) const; - void set_level(level::level_enum); - level::level_enum level() const; - const std::string& name() const; - void set_pattern(const std::string&); - void set_formatter(formatter_ptr); - - // error handler - void set_error_handler(log_err_handler); - log_err_handler error_handler(); - - // automatically call flush() if message level >= log_level - void flush_on(level::level_enum log_level); - - virtual void flush(); - - const std::vector& sinks() const; + logger(const std::string &logger_name, sink_ptr single_sink); + logger(const std::string &name, sinks_init_list); + template + logger(const std::string &name, const It &begin, const It &end); + + virtual ~logger(); + logger(const logger &) = delete; + logger &operator=(const logger &) = delete; + + template + void log(level::level_enum lvl, const char *fmt, const Args &... args); + template void log(level::level_enum lvl, const char *msg); + template void trace(const char *fmt, const Args &... args); + template void debug(const char *fmt, const Args &... args); + template void info(const char *fmt, const Args &... args); + template void warn(const char *fmt, const Args &... args); + template void error(const char *fmt, const Args &... args); + template + void critical(const char *fmt, const Args &... args); + + template void log(level::level_enum lvl, const T &); + template void trace(const T &); + template void debug(const T &); + template void info(const T &); + template void warn(const T &); + template void error(const T &); + template void critical(const T &); + + bool should_log(level::level_enum) const; + void set_level(level::level_enum); + level::level_enum level() const; + const std::string &name() const; + void set_pattern(const std::string &); + void set_formatter(formatter_ptr); + + // error handler + void set_error_handler(log_err_handler); + log_err_handler error_handler(); + + // automatically call flush() if message level >= log_level + void flush_on(level::level_enum log_level); + + virtual void flush(); + + const std::vector &sinks() const; protected: - virtual void _sink_it(details::log_msg&); - virtual void _set_pattern(const std::string&); - virtual void _set_formatter(formatter_ptr); - - // default error handler: print the error to stderr with the max rate of 1 message/minute - virtual void _default_err_handler(const std::string &msg); - - // return true if the given message level should trigger a flush - bool _should_flush_on(const details::log_msg&); - - const std::string _name; - std::vector _sinks; - formatter_ptr _formatter; - spdlog::level_t _level; - spdlog::level_t _flush_level; - log_err_handler _err_handler; - std::atomic _last_err_time; + virtual void _sink_it(details::log_msg &); + virtual void _set_pattern(const std::string &); + virtual void _set_formatter(formatter_ptr); + + // default error handler: print the error to stderr with the max rate of 1 + // message/minute + virtual void _default_err_handler(const std::string &msg); + + // return true if the given message level should trigger a flush + bool _should_flush_on(const details::log_msg &); + + const std::string _name; + std::vector _sinks; + formatter_ptr _formatter; + spdlog::level_t _level; + spdlog::level_t _flush_level; + log_err_handler _err_handler; + std::atomic _last_err_time; }; -} +} // namespace spdlog #include diff --git a/external/spdlog/sinks/android_sink.h b/external/spdlog/sinks/android_sink.h index d8c97e0..1ab4a61 100644 --- a/external/spdlog/sinks/android_sink.h +++ b/external/spdlog/sinks/android_sink.h @@ -9,67 +9,58 @@ #include +#include #include #include -#include -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { /* -* Android sink (logging using __android_log_write) -* __android_log_write is thread-safe. No lock is needed. -*/ -class android_sink : public sink -{ + * Android sink (logging using __android_log_write) + * __android_log_write is thread-safe. No lock is needed. + */ +class android_sink : public sink { public: - explicit android_sink(const std::string& tag = "spdlog"): _tag(tag) {} + explicit android_sink(const std::string &tag = "spdlog") : _tag(tag) {} - void log(const details::log_msg& msg) override - { - const android_LogPriority priority = convert_to_android(msg.level); - // See system/core/liblog/logger_write.c for explanation of return value - const int ret = __android_log_write( - priority, _tag.c_str(), msg.formatted.c_str() - ); - if (ret < 0) - { - throw spdlog_ex("__android_log_write() failed", ret); - } + void log(const details::log_msg &msg) override { + const android_LogPriority priority = convert_to_android(msg.level); + // See system/core/liblog/logger_write.c for explanation of return value + const int ret = + __android_log_write(priority, _tag.c_str(), msg.formatted.c_str()); + if (ret < 0) { + throw spdlog_ex("__android_log_write() failed", ret); } + } - void flush() override - { - } + void flush() override {} private: - static android_LogPriority convert_to_android(spdlog::level::level_enum level) - { - switch(level) - { - case spdlog::level::trace: - return ANDROID_LOG_VERBOSE; - case spdlog::level::debug: - return ANDROID_LOG_DEBUG; - case spdlog::level::info: - return ANDROID_LOG_INFO; - case spdlog::level::warn: - return ANDROID_LOG_WARN; - case spdlog::level::err: - return ANDROID_LOG_ERROR; - case spdlog::level::critical: - return ANDROID_LOG_FATAL; - default: - return ANDROID_LOG_DEFAULT; - } + static android_LogPriority + convert_to_android(spdlog::level::level_enum level) { + switch (level) { + case spdlog::level::trace: + return ANDROID_LOG_VERBOSE; + case spdlog::level::debug: + return ANDROID_LOG_DEBUG; + case spdlog::level::info: + return ANDROID_LOG_INFO; + case spdlog::level::warn: + return ANDROID_LOG_WARN; + case spdlog::level::err: + return ANDROID_LOG_ERROR; + case spdlog::level::critical: + return ANDROID_LOG_FATAL; + default: + return ANDROID_LOG_DEFAULT; } + } - std::string _tag; + std::string _tag; }; -} -} +} // namespace sinks +} // namespace spdlog #endif diff --git a/external/spdlog/sinks/ansicolor_sink.h b/external/spdlog/sinks/ansicolor_sink.h index 96e1014..e6b9896 100644 --- a/external/spdlog/sinks/ansicolor_sink.h +++ b/external/spdlog/sinks/ansicolor_sink.h @@ -5,112 +5,100 @@ #pragma once -#include #include +#include -#include #include +#include -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { /** * @brief The ansi_color_sink is a decorator around another sink and prefixes * the output with an ANSI escape sequence color code depending on the severity * of the message. */ -class ansicolor_sink : public sink -{ +class ansicolor_sink : public sink { public: - ansicolor_sink(sink_ptr wrapped_sink); - virtual ~ansicolor_sink(); - - ansicolor_sink(const ansicolor_sink& other) = delete; - ansicolor_sink& operator=(const ansicolor_sink& other) = delete; - - virtual void log(const details::log_msg& msg) override; - virtual void flush() override; - - void set_color(level::level_enum color_level, const std::string& color); - - /// Formatting codes - const std::string reset = "\033[00m"; - const std::string bold = "\033[1m"; - const std::string dark = "\033[2m"; - const std::string underline = "\033[4m"; - const std::string blink = "\033[5m"; - const std::string reverse = "\033[7m"; - const std::string concealed = "\033[8m"; - - // Foreground colors - const std::string grey = "\033[30m"; - const std::string red = "\033[31m"; - const std::string green = "\033[32m"; - const std::string yellow = "\033[33m"; - const std::string blue = "\033[34m"; - const std::string magenta = "\033[35m"; - const std::string cyan = "\033[36m"; - const std::string white = "\033[37m"; - - /// Background colors - const std::string on_grey = "\033[40m"; - const std::string on_red = "\033[41m"; - const std::string on_green = "\033[42m"; - const std::string on_yellow = "\033[43m"; - const std::string on_blue = "\033[44m"; - const std::string on_magenta = "\033[45m"; - const std::string on_cyan = "\033[46m"; - const std::string on_white = "\033[47m"; - + ansicolor_sink(sink_ptr wrapped_sink); + virtual ~ansicolor_sink(); + + ansicolor_sink(const ansicolor_sink &other) = delete; + ansicolor_sink &operator=(const ansicolor_sink &other) = delete; + + virtual void log(const details::log_msg &msg) override; + virtual void flush() override; + + void set_color(level::level_enum color_level, const std::string &color); + + /// Formatting codes + const std::string reset = "\033[00m"; + const std::string bold = "\033[1m"; + const std::string dark = "\033[2m"; + const std::string underline = "\033[4m"; + const std::string blink = "\033[5m"; + const std::string reverse = "\033[7m"; + const std::string concealed = "\033[8m"; + + // Foreground colors + const std::string grey = "\033[30m"; + const std::string red = "\033[31m"; + const std::string green = "\033[32m"; + const std::string yellow = "\033[33m"; + const std::string blue = "\033[34m"; + const std::string magenta = "\033[35m"; + const std::string cyan = "\033[36m"; + const std::string white = "\033[37m"; + + /// Background colors + const std::string on_grey = "\033[40m"; + const std::string on_red = "\033[41m"; + const std::string on_green = "\033[42m"; + const std::string on_yellow = "\033[43m"; + const std::string on_blue = "\033[44m"; + const std::string on_magenta = "\033[45m"; + const std::string on_cyan = "\033[46m"; + const std::string on_white = "\033[47m"; protected: - sink_ptr sink_; - std::map colors_; + sink_ptr sink_; + std::map colors_; }; -inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sink) -{ - colors_[level::trace] = cyan; - colors_[level::debug] = cyan; - colors_[level::info] = bold; - colors_[level::warn] = yellow + bold; - colors_[level::err] = red + bold; - colors_[level::critical] = bold + on_red; - colors_[level::off] = reset; +inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) + : sink_(wrapped_sink) { + colors_[level::trace] = cyan; + colors_[level::debug] = cyan; + colors_[level::info] = bold; + colors_[level::warn] = yellow + bold; + colors_[level::err] = red + bold; + colors_[level::critical] = bold + on_red; + colors_[level::off] = reset; } -inline void ansicolor_sink::log(const details::log_msg& msg) -{ - // Wrap the originally formatted message in color codes - const std::string& prefix = colors_[msg.level]; - const std::string& s = msg.formatted.str(); - const std::string& suffix = reset; - details::log_msg m; - m.level = msg.level; - m.logger_name = msg.logger_name; - m.time = msg.time; - m.thread_id = msg.thread_id; - m.formatted << prefix << s << suffix; - sink_->log(m); +inline void ansicolor_sink::log(const details::log_msg &msg) { + // Wrap the originally formatted message in color codes + const std::string &prefix = colors_[msg.level]; + const std::string &s = msg.formatted.str(); + const std::string &suffix = reset; + details::log_msg m; + m.level = msg.level; + m.logger_name = msg.logger_name; + m.time = msg.time; + m.thread_id = msg.thread_id; + m.formatted << prefix << s << suffix; + sink_->log(m); } -inline void ansicolor_sink::flush() -{ - sink_->flush(); -} +inline void ansicolor_sink::flush() { sink_->flush(); } -inline void ansicolor_sink::set_color(level::level_enum color_level, const std::string& color) -{ - colors_[color_level] = color; +inline void ansicolor_sink::set_color(level::level_enum color_level, + const std::string &color) { + colors_[color_level] = color; } -inline ansicolor_sink::~ansicolor_sink() -{ - flush(); -} +inline ansicolor_sink::~ansicolor_sink() { flush(); } } // namespace sinks } // namespace spdlog - diff --git a/external/spdlog/sinks/base_sink.h b/external/spdlog/sinks/base_sink.h index 7f1a31d..70d03b1 100644 --- a/external/spdlog/sinks/base_sink.h +++ b/external/spdlog/sinks/base_sink.h @@ -10,36 +10,31 @@ // all locking is taken care of here so no locking needed by the implementers.. // -#include -#include #include #include +#include +#include #include -namespace spdlog -{ -namespace sinks -{ -template -class base_sink:public sink -{ +namespace spdlog { +namespace sinks { +template class base_sink : public sink { public: - base_sink():_mutex() {} - virtual ~base_sink() = default; + base_sink() : _mutex() {} + virtual ~base_sink() = default; - base_sink(const base_sink&) = delete; - base_sink& operator=(const base_sink&) = delete; + base_sink(const base_sink &) = delete; + base_sink &operator=(const base_sink &) = delete; - void log(const details::log_msg& msg) override - { - std::lock_guard lock(_mutex); - _sink_it(msg); - } + void log(const details::log_msg &msg) override { + std::lock_guard lock(_mutex); + _sink_it(msg); + } protected: - virtual void _sink_it(const details::log_msg& msg) = 0; - Mutex _mutex; + virtual void _sink_it(const details::log_msg &msg) = 0; + Mutex _mutex; }; -} -} +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/sinks/dist_sink.h b/external/spdlog/sinks/dist_sink.h index cef08bf..581a01f 100644 --- a/external/spdlog/sinks/dist_sink.h +++ b/external/spdlog/sinks/dist_sink.h @@ -11,61 +11,52 @@ #include #include -#include #include +#include #include -// Distribution sink (mux). Stores a vector of sinks which get called when log is called +// Distribution sink (mux). Stores a vector of sinks which get called when log +// is called -namespace spdlog -{ -namespace sinks -{ -template -class dist_sink: public base_sink -{ +namespace spdlog { +namespace sinks { +template class dist_sink : public base_sink { public: - explicit dist_sink() :_sinks() {} - dist_sink(const dist_sink&) = delete; - dist_sink& operator=(const dist_sink&) = delete; - virtual ~dist_sink() = default; + explicit dist_sink() : _sinks() {} + dist_sink(const dist_sink &) = delete; + dist_sink &operator=(const dist_sink &) = delete; + virtual ~dist_sink() = default; protected: - std::vector> _sinks; + std::vector> _sinks; - void _sink_it(const details::log_msg& msg) override - { - for (auto &sink : _sinks) - { - if( sink->should_log( msg.level)) - { - sink->log(msg); - } - } + void _sink_it(const details::log_msg &msg) override { + for (auto &sink : _sinks) { + if (sink->should_log(msg.level)) { + sink->log(msg); + } } + } public: - void flush() override - { - std::lock_guard lock(base_sink::_mutex); - for (auto &sink : _sinks) - sink->flush(); - } - - void add_sink(std::shared_ptr sink) - { - std::lock_guard lock(base_sink::_mutex); - _sinks.push_back(sink); - } - - void remove_sink(std::shared_ptr sink) - { - std::lock_guard lock(base_sink::_mutex); - _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink), _sinks.end()); - } + void flush() override { + std::lock_guard lock(base_sink::_mutex); + for (auto &sink : _sinks) + sink->flush(); + } + + void add_sink(std::shared_ptr sink) { + std::lock_guard lock(base_sink::_mutex); + _sinks.push_back(sink); + } + + void remove_sink(std::shared_ptr sink) { + std::lock_guard lock(base_sink::_mutex); + _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink), _sinks.end()); + } }; typedef dist_sink dist_sink_mt; typedef dist_sink dist_sink_st; -} -} +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/sinks/file_sinks.h b/external/spdlog/sinks/file_sinks.h index 721a96d..58f96fa 100644 --- a/external/spdlog/sinks/file_sinks.h +++ b/external/spdlog/sinks/file_sinks.h @@ -5,53 +5,43 @@ #pragma once -#include -#include #include +#include #include +#include #include +#include #include #include #include #include #include -#include -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { /* * Trivial file sink with single file as target */ -template -class simple_file_sink : public base_sink < Mutex > -{ +template class simple_file_sink : public base_sink { public: - explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false) - { - _file_helper.open(filename, truncate); - } - void flush() override - { - _file_helper.flush(); - } - void set_force_flush(bool force_flush) - { - _force_flush = force_flush; - } + explicit simple_file_sink(const filename_t &filename, bool truncate = false) + : _force_flush(false) { + _file_helper.open(filename, truncate); + } + void flush() override { _file_helper.flush(); } + void set_force_flush(bool force_flush) { _force_flush = force_flush; } protected: - void _sink_it(const details::log_msg& msg) override - { - _file_helper.write(msg); - if(_force_flush) - _file_helper.flush(); - } + void _sink_it(const details::log_msg &msg) override { + _file_helper.write(msg); + if (_force_flush) + _file_helper.flush(); + } + private: - details::file_helper _file_helper; - bool _force_flush; + details::file_helper _file_helper; + bool _force_flush; }; typedef simple_file_sink simple_file_sink_mt; @@ -60,180 +50,165 @@ typedef simple_file_sink simple_file_sink_st; /* * Rotating file sink based on size */ -template -class rotating_file_sink : public base_sink < Mutex > -{ +template class rotating_file_sink : public base_sink { public: - rotating_file_sink(const filename_t &base_filename, - std::size_t max_size, std::size_t max_files) : - _base_filename(base_filename), - _max_size(max_size), - _max_files(max_files), - _current_size(0), - _file_helper() - { - _file_helper.open(calc_filename(_base_filename, 0)); - _current_size = _file_helper.size(); //expensive. called only once - } + rotating_file_sink(const filename_t &base_filename, std::size_t max_size, + std::size_t max_files) + : _base_filename(base_filename), _max_size(max_size), + _max_files(max_files), _current_size(0), _file_helper() { + _file_helper.open(calc_filename(_base_filename, 0)); + _current_size = _file_helper.size(); // expensive. called only once + } - void flush() override - { - _file_helper.flush(); - } + void flush() override { _file_helper.flush(); } protected: - void _sink_it(const details::log_msg& msg) override - { - _current_size += msg.formatted.size(); - if (_current_size > _max_size) - { - _rotate(); - _current_size = msg.formatted.size(); - } - _file_helper.write(msg); + void _sink_it(const details::log_msg &msg) override { + _current_size += msg.formatted.size(); + if (_current_size > _max_size) { + _rotate(); + _current_size = msg.formatted.size(); } + _file_helper.write(msg); + } private: - static filename_t calc_filename(const filename_t& filename, std::size_t index) - { - std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; - if (index) - w.write(SPDLOG_FILENAME_T("{}.{}"), filename, index); - else - w.write(SPDLOG_FILENAME_T("{}"), filename); - return w.str(); - } - - // Rotate files: - // log.txt -> log.txt.1 - // log.txt.1 -> log.txt.2 - // log.txt.2 -> log.txt.3 - // lo3.txt.3 -> delete - - void _rotate() - { - using details::os::filename_to_str; - _file_helper.close(); - for (auto i = _max_files; i > 0; --i) - { - filename_t src = calc_filename(_base_filename, i - 1); - filename_t target = calc_filename(_base_filename, i); - - if (details::file_helper::file_exists(target)) - { - if (details::os::remove(target) != 0) - { - throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno); - } - } - if (details::file_helper::file_exists(src) && details::os::rename(src, target)) - { - throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno); - } + static filename_t calc_filename(const filename_t &filename, + std::size_t index) { + std::conditional::value, + fmt::MemoryWriter, fmt::WMemoryWriter>::type w; + if (index) + w.write(SPDLOG_FILENAME_T("{}.{}"), filename, index); + else + w.write(SPDLOG_FILENAME_T("{}"), filename); + return w.str(); + } + + // Rotate files: + // log.txt -> log.txt.1 + // log.txt.1 -> log.txt.2 + // log.txt.2 -> log.txt.3 + // lo3.txt.3 -> delete + + void _rotate() { + using details::os::filename_to_str; + _file_helper.close(); + for (auto i = _max_files; i > 0; --i) { + filename_t src = calc_filename(_base_filename, i - 1); + filename_t target = calc_filename(_base_filename, i); + + if (details::file_helper::file_exists(target)) { + if (details::os::remove(target) != 0) { + throw spdlog_ex("rotating_file_sink: failed removing " + + filename_to_str(target), + errno); } - _file_helper.reopen(true); + } + if (details::file_helper::file_exists(src) && + details::os::rename(src, target)) { + throw spdlog_ex("rotating_file_sink: failed renaming " + + filename_to_str(src) + " to " + + filename_to_str(target), + errno); + } } - filename_t _base_filename; - std::size_t _max_size; - std::size_t _max_files; - std::size_t _current_size; - details::file_helper _file_helper; + _file_helper.reopen(true); + } + filename_t _base_filename; + std::size_t _max_size; + std::size_t _max_files; + std::size_t _current_size; + details::file_helper _file_helper; }; typedef rotating_file_sink rotating_file_sink_mt; -typedef rotating_file_sinkrotating_file_sink_st; +typedef rotating_file_sink rotating_file_sink_st; /* * Default generator of daily log file names. */ -struct default_daily_file_name_calculator -{ - // Create filename for the form basename.YYYY-MM-DD_hh-mm - static filename_t calc_filename(const filename_t& basename) - { - std::tm tm = spdlog::details::os::localtime(); - std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; - w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min); - return w.str(); - } +struct default_daily_file_name_calculator { + // Create filename for the form basename.YYYY-MM-DD_hh-mm + static filename_t calc_filename(const filename_t &basename) { + std::tm tm = spdlog::details::os::localtime(); + std::conditional::value, + fmt::MemoryWriter, fmt::WMemoryWriter>::type w; + w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}"), + basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, + tm.tm_min); + return w.str(); + } }; /* * Generator of daily log file names in format basename.YYYY-MM-DD */ -struct dateonly_daily_file_name_calculator -{ - // Create filename for the form basename.YYYY-MM-DD - static filename_t calc_filename(const filename_t& basename) - { - std::tm tm = spdlog::details::os::localtime(); - std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; - w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); - return w.str(); - } +struct dateonly_daily_file_name_calculator { + // Create filename for the form basename.YYYY-MM-DD + static filename_t calc_filename(const filename_t &basename) { + std::tm tm = spdlog::details::os::localtime(); + std::conditional::value, + fmt::MemoryWriter, fmt::WMemoryWriter>::type w; + w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + return w.str(); + } }; /* * Rotating file sink based on date. rotates at midnight */ -template -class daily_file_sink :public base_sink < Mutex > -{ +template +class daily_file_sink : public base_sink { public: - //create daily file sink which rotates on given time - daily_file_sink( - const filename_t& base_filename, - int rotation_hour, - int rotation_minute) : _base_filename(base_filename), - _rotation_h(rotation_hour), - _rotation_m(rotation_minute) - { - if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59) - throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); - _rotation_tp = _next_rotation_tp(); - _file_helper.open(FileNameCalc::calc_filename(_base_filename)); - } - - void flush() override - { - _file_helper.flush(); - } + // create daily file sink which rotates on given time + daily_file_sink(const filename_t &base_filename, int rotation_hour, + int rotation_minute) + : _base_filename(base_filename), _rotation_h(rotation_hour), + _rotation_m(rotation_minute) { + if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || + rotation_minute > 59) + throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); + _rotation_tp = _next_rotation_tp(); + _file_helper.open(FileNameCalc::calc_filename(_base_filename)); + } + + void flush() override { _file_helper.flush(); } protected: - void _sink_it(const details::log_msg& msg) override - { - if (std::chrono::system_clock::now() >= _rotation_tp) - { - _file_helper.open(FileNameCalc::calc_filename(_base_filename)); - _rotation_tp = _next_rotation_tp(); - } - _file_helper.write(msg); + void _sink_it(const details::log_msg &msg) override { + if (std::chrono::system_clock::now() >= _rotation_tp) { + _file_helper.open(FileNameCalc::calc_filename(_base_filename)); + _rotation_tp = _next_rotation_tp(); } + _file_helper.write(msg); + } private: - std::chrono::system_clock::time_point _next_rotation_tp() - { - auto now = std::chrono::system_clock::now(); - time_t tnow = std::chrono::system_clock::to_time_t(now); - tm date = spdlog::details::os::localtime(tnow); - date.tm_hour = _rotation_h; - date.tm_min = _rotation_m; - date.tm_sec = 0; - auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date)); - if (rotation_time > now) - return rotation_time; - else - return std::chrono::system_clock::time_point(rotation_time + std::chrono::hours(24)); - } - - filename_t _base_filename; - int _rotation_h; - int _rotation_m; - std::chrono::system_clock::time_point _rotation_tp; - details::file_helper _file_helper; + std::chrono::system_clock::time_point _next_rotation_tp() { + auto now = std::chrono::system_clock::now(); + time_t tnow = std::chrono::system_clock::to_time_t(now); + tm date = spdlog::details::os::localtime(tnow); + date.tm_hour = _rotation_h; + date.tm_min = _rotation_m; + date.tm_sec = 0; + auto rotation_time = + std::chrono::system_clock::from_time_t(std::mktime(&date)); + if (rotation_time > now) + return rotation_time; + else + return std::chrono::system_clock::time_point(rotation_time + + std::chrono::hours(24)); + } + + filename_t _base_filename; + int _rotation_h; + int _rotation_m; + std::chrono::system_clock::time_point _rotation_tp; + details::file_helper _file_helper; }; typedef daily_file_sink daily_file_sink_mt; typedef daily_file_sink daily_file_sink_st; -} -} +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/sinks/msvc_sink.h b/external/spdlog/sinks/msvc_sink.h index 16342ca..6cfe9c5 100644 --- a/external/spdlog/sinks/msvc_sink.h +++ b/external/spdlog/sinks/msvc_sink.h @@ -7,44 +7,35 @@ #if defined(_MSC_VER) -#include #include +#include #include #include #include -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { /* -* MSVC sink (logging using OutputDebugStringA) -*/ -template -class msvc_sink : public base_sink < Mutex > -{ + * MSVC sink (logging using OutputDebugStringA) + */ +template class msvc_sink : public base_sink { public: - explicit msvc_sink() - { - } + explicit msvc_sink() {} - void flush() override - { - } + void flush() override {} protected: - void _sink_it(const details::log_msg& msg) override - { - OutputDebugStringA(msg.formatted.c_str()); - } + void _sink_it(const details::log_msg &msg) override { + OutputDebugStringA(msg.formatted.c_str()); + } }; typedef msvc_sink msvc_sink_mt; typedef msvc_sink msvc_sink_st; -} -} +} // namespace sinks +} // namespace spdlog #endif diff --git a/external/spdlog/sinks/null_sink.h b/external/spdlog/sinks/null_sink.h index 1d427aa..3c461af 100644 --- a/external/spdlog/sinks/null_sink.h +++ b/external/spdlog/sinks/null_sink.h @@ -5,30 +5,22 @@ #pragma once -#include #include +#include #include -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { -template -class null_sink : public base_sink < Mutex > -{ +template class null_sink : public base_sink { protected: - void _sink_it(const details::log_msg&) override - {} - - void flush() override - {} + void _sink_it(const details::log_msg &) override {} + void flush() override {} }; typedef null_sink null_sink_st; typedef null_sink null_sink_mt; -} -} - +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/sinks/ostream_sink.h b/external/spdlog/sinks/ostream_sink.h index feb5efa..e263393 100644 --- a/external/spdlog/sinks/ostream_sink.h +++ b/external/spdlog/sinks/ostream_sink.h @@ -8,40 +8,33 @@ #include #include -#include #include +#include -namespace spdlog -{ -namespace sinks -{ -template -class ostream_sink: public base_sink -{ +namespace spdlog { +namespace sinks { +template class ostream_sink : public base_sink { public: - explicit ostream_sink(std::ostream& os, bool force_flush=false) :_ostream(os), _force_flush(force_flush) {} - ostream_sink(const ostream_sink&) = delete; - ostream_sink& operator=(const ostream_sink&) = delete; - virtual ~ostream_sink() = default; + explicit ostream_sink(std::ostream &os, bool force_flush = false) + : _ostream(os), _force_flush(force_flush) {} + ostream_sink(const ostream_sink &) = delete; + ostream_sink &operator=(const ostream_sink &) = delete; + virtual ~ostream_sink() = default; protected: - void _sink_it(const details::log_msg& msg) override - { - _ostream.write(msg.formatted.data(), msg.formatted.size()); - if (_force_flush) - _ostream.flush(); - } - - void flush() override - { - _ostream.flush(); - } - - std::ostream& _ostream; - bool _force_flush; + void _sink_it(const details::log_msg &msg) override { + _ostream.write(msg.formatted.data(), msg.formatted.size()); + if (_force_flush) + _ostream.flush(); + } + + void flush() override { _ostream.flush(); } + + std::ostream &_ostream; + bool _force_flush; }; typedef ostream_sink ostream_sink_mt; typedef ostream_sink ostream_sink_st; -} -} +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/sinks/sink.h b/external/spdlog/sinks/sink.h index b48dd8b..bdb3230 100644 --- a/external/spdlog/sinks/sink.h +++ b/external/spdlog/sinks/sink.h @@ -3,51 +3,40 @@ // Distributed under the MIT License (http://opensource.org/licenses/MIT) // - #pragma once #include -namespace spdlog -{ -namespace sinks -{ -class sink -{ +namespace spdlog { +namespace sinks { +class sink { public: - sink() - { - _level = level::trace; - } + sink() { _level = level::trace; } - virtual ~sink() {} - virtual void log(const details::log_msg& msg) = 0; - virtual void flush() = 0; + virtual ~sink() {} + virtual void log(const details::log_msg &msg) = 0; + virtual void flush() = 0; - bool should_log(level::level_enum msg_level) const; - void set_level(level::level_enum log_level); - level::level_enum level() const; + bool should_log(level::level_enum msg_level) const; + void set_level(level::level_enum log_level); + level::level_enum level() const; private: - level_t _level; - + level_t _level; }; -inline bool sink::should_log(level::level_enum msg_level) const -{ - return msg_level >= _level.load(std::memory_order_relaxed); +inline bool sink::should_log(level::level_enum msg_level) const { + return msg_level >= _level.load(std::memory_order_relaxed); } -inline void sink::set_level(level::level_enum log_level) -{ - _level.store(log_level); +inline void sink::set_level(level::level_enum log_level) { + _level.store(log_level); } -inline level::level_enum sink::level() const -{ - return static_cast(_level.load(std::memory_order_relaxed)); -} - -} +inline level::level_enum sink::level() const { + return static_cast( + _level.load(std::memory_order_relaxed)); } +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/sinks/stdout_sinks.h b/external/spdlog/sinks/stdout_sinks.h index c05f80d..206c087 100644 --- a/external/spdlog/sinks/stdout_sinks.h +++ b/external/spdlog/sinks/stdout_sinks.h @@ -12,66 +12,49 @@ #include #include -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { -template -class stdout_sink: public base_sink -{ - using MyType = stdout_sink; -public: - stdout_sink() - {} - static std::shared_ptr instance() - { - static std::shared_ptr instance = std::make_shared(); - return instance; - } - - void _sink_it(const details::log_msg& msg) override - { - fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout); - flush(); - } +template class stdout_sink : public base_sink { + using MyType = stdout_sink; - void flush() override - { - fflush(stdout); - } +public: + stdout_sink() {} + static std::shared_ptr instance() { + static std::shared_ptr instance = std::make_shared(); + return instance; + } + + void _sink_it(const details::log_msg &msg) override { + fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout); + flush(); + } + + void flush() override { fflush(stdout); } }; typedef stdout_sink stdout_sink_st; typedef stdout_sink stdout_sink_mt; +template class stderr_sink : public base_sink { + using MyType = stderr_sink; -template -class stderr_sink: public base_sink -{ - using MyType = stderr_sink; public: - stderr_sink() - {} - static std::shared_ptr instance() - { - static std::shared_ptr instance = std::make_shared(); - return instance; - } - - void _sink_it(const details::log_msg& msg) override - { - fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr); - flush(); - } - - void flush() override - { - fflush(stderr); - } + stderr_sink() {} + static std::shared_ptr instance() { + static std::shared_ptr instance = std::make_shared(); + return instance; + } + + void _sink_it(const details::log_msg &msg) override { + fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr); + flush(); + } + + void flush() override { fflush(stderr); } }; typedef stderr_sink stderr_sink_mt; typedef stderr_sink stderr_sink_st; -} -} +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/sinks/syslog_sink.h b/external/spdlog/sinks/syslog_sink.h index 0d8633c..5dfd415 100644 --- a/external/spdlog/sinks/syslog_sink.h +++ b/external/spdlog/sinks/syslog_sink.h @@ -9,73 +9,63 @@ #ifdef SPDLOG_ENABLE_SYSLOG -#include #include +#include #include #include #include - -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { /** * Sink that write to syslog using the `syscall()` library call. * * Locking is not needed, as `syslog()` itself is thread-safe. */ -class syslog_sink : public sink -{ +class syslog_sink : public sink { public: - // - syslog_sink(const std::string& ident = "", int syslog_option=0, int syslog_facility=LOG_USER): - _ident(ident) - { - _priorities[static_cast(level::trace)] = LOG_DEBUG; - _priorities[static_cast(level::debug)] = LOG_DEBUG; - _priorities[static_cast(level::info)] = LOG_INFO; - _priorities[static_cast(level::warn)] = LOG_WARNING; - _priorities[static_cast(level::err)] = LOG_ERR; - _priorities[static_cast(level::critical)] = LOG_CRIT; - _priorities[static_cast(level::off)] = LOG_INFO; - - //set ident to be program name if empty - ::openlog(_ident.empty()? nullptr:_ident.c_str(), syslog_option, syslog_facility); - } - ~syslog_sink() - { - ::closelog(); - } + // + syslog_sink(const std::string &ident = "", int syslog_option = 0, + int syslog_facility = LOG_USER) + : _ident(ident) { + _priorities[static_cast(level::trace)] = LOG_DEBUG; + _priorities[static_cast(level::debug)] = LOG_DEBUG; + _priorities[static_cast(level::info)] = LOG_INFO; + _priorities[static_cast(level::warn)] = LOG_WARNING; + _priorities[static_cast(level::err)] = LOG_ERR; + _priorities[static_cast(level::critical)] = LOG_CRIT; + _priorities[static_cast(level::off)] = LOG_INFO; - syslog_sink(const syslog_sink&) = delete; - syslog_sink& operator=(const syslog_sink&) = delete; + // set ident to be program name if empty + ::openlog(_ident.empty() ? nullptr : _ident.c_str(), syslog_option, + syslog_facility); + } + ~syslog_sink() { ::closelog(); } - void log(const details::log_msg &msg) override - { - ::syslog(syslog_prio_from_level(msg), "%s", msg.raw.str().c_str()); - } + syslog_sink(const syslog_sink &) = delete; + syslog_sink &operator=(const syslog_sink &) = delete; - void flush() override - { - } + void log(const details::log_msg &msg) override { + ::syslog(syslog_prio_from_level(msg), "%s", msg.raw.str().c_str()); + } + void flush() override {} private: - std::array _priorities; - //must store the ident because the man says openlog might use the pointer as is and not a string copy - const std::string _ident; + std::array _priorities; + // must store the ident because the man says openlog might use the pointer as + // is and not a string copy + const std::string _ident; - // - // Simply maps spdlog's log level to syslog priority level. - // - int syslog_prio_from_level(const details::log_msg &msg) const - { - return _priorities[static_cast(msg.level)]; - } + // + // Simply maps spdlog's log level to syslog priority level. + // + int syslog_prio_from_level(const details::log_msg &msg) const { + return _priorities[static_cast(msg.level)]; + } }; -} -} +} // namespace sinks +} // namespace spdlog #endif diff --git a/external/spdlog/sinks/wincolor_sink.h b/external/spdlog/sinks/wincolor_sink.h index 63ecbe2..6ddc844 100644 --- a/external/spdlog/sinks/wincolor_sink.h +++ b/external/spdlog/sinks/wincolor_sink.h @@ -5,94 +5,84 @@ #pragma once -#include -#include #include +#include +#include +#include #include #include -#include #include -namespace spdlog -{ -namespace sinks -{ +namespace spdlog { +namespace sinks { /* - * Windows color console sink. Uses WriteConsoleA to write to the console with colors + * Windows color console sink. Uses WriteConsoleA to write to the console with + * colors */ -template -class wincolor_sink: public base_sink -{ +template class wincolor_sink : public base_sink { public: - const WORD BOLD = FOREGROUND_INTENSITY; - const WORD RED = FOREGROUND_RED; - const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE; - const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN; - - wincolor_sink(HANDLE std_handle): out_handle_(std_handle) - { - colors_[level::trace] = CYAN; - colors_[level::debug] = CYAN; - colors_[level::info] = WHITE | BOLD; - colors_[level::warn] = YELLOW | BOLD; - colors_[level::err] = RED | BOLD; // red bold - colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background - colors_[level::off] = 0; - } - - virtual ~wincolor_sink() - { - flush(); - } - - wincolor_sink(const wincolor_sink& other) = delete; - wincolor_sink& operator=(const wincolor_sink& other) = delete; - - virtual void _sink_it(const details::log_msg& msg) override - { - auto color = colors_[msg.level]; - auto orig_attribs = set_console_attribs(color); - WriteConsoleA(out_handle_, msg.formatted.data(), static_cast(msg.formatted.size()), nullptr, nullptr); - SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors - } - - virtual void flush() override - { - // windows console always flushed? - } - - // change the color for the given level - void set_color(level::level_enum level, WORD color) - { - std::lock_guard lock(base_sink::_mutex); - colors_[level] = color; - } + const WORD BOLD = FOREGROUND_INTENSITY; + const WORD RED = FOREGROUND_RED; + const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE; + const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN; + + wincolor_sink(HANDLE std_handle) : out_handle_(std_handle) { + colors_[level::trace] = CYAN; + colors_[level::debug] = CYAN; + colors_[level::info] = WHITE | BOLD; + colors_[level::warn] = YELLOW | BOLD; + colors_[level::err] = RED | BOLD; // red bold + colors_[level::critical] = + BACKGROUND_RED | WHITE | BOLD; // white bold on red background + colors_[level::off] = 0; + } + + virtual ~wincolor_sink() { flush(); } + + wincolor_sink(const wincolor_sink &other) = delete; + wincolor_sink &operator=(const wincolor_sink &other) = delete; + + virtual void _sink_it(const details::log_msg &msg) override { + auto color = colors_[msg.level]; + auto orig_attribs = set_console_attribs(color); + WriteConsoleA(out_handle_, msg.formatted.data(), + static_cast(msg.formatted.size()), nullptr, nullptr); + SetConsoleTextAttribute(out_handle_, orig_attribs); // reset to orig colors + } + + virtual void flush() override { + // windows console always flushed? + } + + // change the color for the given level + void set_color(level::level_enum level, WORD color) { + std::lock_guard lock(base_sink::_mutex); + colors_[level] = color; + } private: - HANDLE out_handle_; - std::map colors_; - - // set color and return the orig console attributes (for resetting later) - WORD set_console_attribs(WORD attribs) - { - CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; - GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info); - SetConsoleTextAttribute(out_handle_, attribs); - return orig_buffer_info.wAttributes; //return orig attribs - } + HANDLE out_handle_; + std::map colors_; + + // set color and return the orig console attributes (for resetting later) + WORD set_console_attribs(WORD attribs) { + CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; + GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info); + SetConsoleTextAttribute(out_handle_, attribs); + return orig_buffer_info.wAttributes; // return orig attribs + } }; // // windows color console to stdout // -template -class wincolor_stdout_sink: public wincolor_sink -{ +template +class wincolor_stdout_sink : public wincolor_sink { public: - wincolor_stdout_sink() : wincolor_sink(GetStdHandle(STD_OUTPUT_HANDLE)) - {} + wincolor_stdout_sink() + : wincolor_sink(GetStdHandle(STD_OUTPUT_HANDLE)) {} }; typedef wincolor_stdout_sink wincolor_stdout_sink_mt; @@ -101,16 +91,15 @@ typedef wincolor_stdout_sink wincolor_stdout_sink_st; // // windows color console to stderr // -template -class wincolor_stderr_sink: public wincolor_sink -{ +template +class wincolor_stderr_sink : public wincolor_sink { public: - wincolor_stderr_sink() : wincolor_sink(GetStdHandle(STD_ERROR_HANDLE)) - {} + wincolor_stderr_sink() + : wincolor_sink(GetStdHandle(STD_ERROR_HANDLE)) {} }; typedef wincolor_stderr_sink wincolor_stderr_sink_mt; typedef wincolor_stderr_sink wincolor_stderr_sink_st; -} -} +} // namespace sinks +} // namespace spdlog diff --git a/external/spdlog/spdlog.h b/external/spdlog/spdlog.h index a505b00..38b8ac0 100644 --- a/external/spdlog/spdlog.h +++ b/external/spdlog/spdlog.h @@ -9,30 +9,28 @@ #define SPDLOG_VERSION "0.12.0" -#include #include #include +#include -#include -#include #include +#include +#include #include -namespace spdlog -{ +namespace spdlog { // -// Return an existing logger or nullptr if a logger with such name doesn't exist. -// example: spdlog::get("my_logger")->info("hello {}", "world"); +// Return an existing logger or nullptr if a logger with such name doesn't +// exist. example: spdlog::get("my_logger")->info("hello {}", "world"); // -std::shared_ptr get(const std::string& name); - +std::shared_ptr get(const std::string &name); // // Set global formatting // example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); // -void set_pattern(const std::string& format_string); +void set_pattern(const std::string &format_string); void set_formatter(formatter_ptr f); // @@ -46,88 +44,114 @@ void set_level(level::level_enum log_level); void set_error_handler(log_err_handler); // -// Turn on async mode (off by default) and set the queue size for each async_logger. -// effective only for loggers created after this call. -// queue_size: size of queue (must be power of 2): -// Each logger will pre-allocate a dedicated queue with queue_size entries upon construction. +// Turn on async mode (off by default) and set the queue size for each +// async_logger. effective only for loggers created after this call. queue_size: +// size of queue (must be power of 2): +// Each logger will pre-allocate a dedicated queue with queue_size entries +// upon construction. // // async_overflow_policy (optional, block_retry by default): -// async_overflow_policy::block_retry - if queue is full, block until queue has room for the new log entry. -// async_overflow_policy::discard_log_msg - never block and discard any new messages when queue overflows. +// async_overflow_policy::block_retry - if queue is full, block until queue +// has room for the new log entry. async_overflow_policy::discard_log_msg - +// never block and discard any new messages when queue overflows. // // worker_warmup_cb (optional): -// callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity) +// callback function that will be called in worker thread upon start (can be +// used to init stuff like thread affinity) // // worker_teardown_cb (optional): // callback function that will be called in worker thread upon exit // -void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); +void set_async_mode(size_t queue_size, + const async_overflow_policy overflow_policy = + async_overflow_policy::block_retry, + const std::function &worker_warmup_cb = nullptr, + const std::chrono::milliseconds &flush_interval_ms = + std::chrono::milliseconds::zero(), + const std::function &worker_teardown_cb = nullptr); // Turn off async mode void set_sync_mode(); - // // Create and register multi/single threaded basic file logger. // Basic logger simply writes to given file without any limitatons or rotations. // -std::shared_ptr basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate = false); -std::shared_ptr basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate = false); +std::shared_ptr basic_logger_mt(const std::string &logger_name, + const filename_t &filename, + bool truncate = false); +std::shared_ptr basic_logger_st(const std::string &logger_name, + const filename_t &filename, + bool truncate = false); // // Create and register multi/single threaded rotating file logger // -std::shared_ptr rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files); -std::shared_ptr rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files); +std::shared_ptr rotating_logger_mt(const std::string &logger_name, + const filename_t &filename, + size_t max_file_size, + size_t max_files); +std::shared_ptr rotating_logger_st(const std::string &logger_name, + const filename_t &filename, + size_t max_file_size, + size_t max_files); // -// Create file logger which creates new file on the given time (default in midnight): +// Create file logger which creates new file on the given time (default in +// midnight): // -std::shared_ptr daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); -std::shared_ptr daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); +std::shared_ptr daily_logger_mt(const std::string &logger_name, + const filename_t &filename, + int hour = 0, int minute = 0); +std::shared_ptr daily_logger_st(const std::string &logger_name, + const filename_t &filename, + int hour = 0, int minute = 0); // // Create and register stdout/stderr loggers // -std::shared_ptr stdout_logger_mt(const std::string& logger_name); -std::shared_ptr stdout_logger_st(const std::string& logger_name); -std::shared_ptr stderr_logger_mt(const std::string& logger_name); -std::shared_ptr stderr_logger_st(const std::string& logger_name); +std::shared_ptr stdout_logger_mt(const std::string &logger_name); +std::shared_ptr stdout_logger_st(const std::string &logger_name); +std::shared_ptr stderr_logger_mt(const std::string &logger_name); +std::shared_ptr stderr_logger_st(const std::string &logger_name); // // Create and register colored stdout/stderr loggers // -std::shared_ptr stdout_color_mt(const std::string& logger_name); -std::shared_ptr stdout_color_st(const std::string& logger_name); -std::shared_ptr stderr_color_mt(const std::string& logger_name); -std::shared_ptr stderr_color_st(const std::string& logger_name); - +std::shared_ptr stdout_color_mt(const std::string &logger_name); +std::shared_ptr stdout_color_st(const std::string &logger_name); +std::shared_ptr stderr_color_mt(const std::string &logger_name); +std::shared_ptr stderr_color_st(const std::string &logger_name); // // Create and register a syslog logger // #ifdef SPDLOG_ENABLE_SYSLOG -std::shared_ptr syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0); +std::shared_ptr syslog_logger(const std::string &logger_name, + const std::string &ident = "", + int syslog_option = 0); #endif #if defined(__ANDROID__) -std::shared_ptr android_logger(const std::string& logger_name, const std::string& tag = "spdlog"); +std::shared_ptr android_logger(const std::string &logger_name, + const std::string &tag = "spdlog"); #endif // Create and register a logger a single sink -std::shared_ptr create(const std::string& logger_name, const sink_ptr& sink); +std::shared_ptr create(const std::string &logger_name, + const sink_ptr &sink); // Create and register a logger with multiple sinks -std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks); -template -std::shared_ptr create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end); - +std::shared_ptr create(const std::string &logger_name, + sinks_init_list sinks); +template +std::shared_ptr create(const std::string &logger_name, + const It &sinks_begin, const It &sinks_end); // Create and register a logger with templated sink type // Example: // spdlog::create("mylog", "dailylog_filename"); template -std::shared_ptr create(const std::string& logger_name, Args...); - +std::shared_ptr create(const std::string &logger_name, Args...); // Register the given logger with the given name void register_logger(std::shared_ptr logger); @@ -143,11 +167,10 @@ void drop(const std::string &name); // Drop all references from the registry void drop_all(); - /////////////////////////////////////////////////////////////////////////////// // -// Trace & Debug can be switched on/off at compile time for zero cost debug statements. -// Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in teakme.h to enable. +// Trace & Debug can be switched on/off at compile time for zero cost debug +// statements. Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in teakme.h to enable. // SPDLOG_TRACE(..) will also print current file and line. // // Example: @@ -160,7 +183,9 @@ void drop_all(); #ifdef SPDLOG_TRACE_ON #define SPDLOG_STR_H(x) #x #define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x) -#define SPDLOG_TRACE(logger, ...) logger->trace("[" __FILE__ " line #" SPDLOG_STR_HELPER(__LINE__) "] " __VA_ARGS__) +#define SPDLOG_TRACE(logger, ...) \ + logger->trace("[" __FILE__ \ + " line #" SPDLOG_STR_HELPER(__LINE__) "] " __VA_ARGS__) #else #define SPDLOG_TRACE(logger, ...) #endif @@ -171,8 +196,6 @@ void drop_all(); #define SPDLOG_DEBUG(logger, ...) #endif - -} - +} // namespace spdlog #include diff --git a/external/spdlog/tweakme.h b/external/spdlog/tweakme.h index 86f66b9..2cdbed1 100644 --- a/external/spdlog/tweakme.h +++ b/external/spdlog/tweakme.h @@ -7,41 +7,41 @@ /////////////////////////////////////////////////////////////////////////////// // -// Edit this file to squeeze more performance, and to customize supported features +// Edit this file to squeeze more performance, and to customize supported +// features // /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// // Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used. -// This clock is less accurate - can be off by dozens of millis - depending on the kernel HZ. -// Uncomment to use it instead of the regular clock. +// This clock is less accurate - can be off by dozens of millis - depending on +// the kernel HZ. Uncomment to use it instead of the regular clock. // // #define SPDLOG_CLOCK_COARSE /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// -// Uncomment if date/time logging is not needed and never appear in the log pattern. -// This will prevent spdlog from quering the clock on each log call. +// Uncomment if date/time logging is not needed and never appear in the log +// pattern. This will prevent spdlog from quering the clock on each log call. // -// WARNING: If the log pattern contains any date/time while this flag is on, the result is undefined. -// You must set new pattern(spdlog::set_pattern(..") without any date/time in it +// WARNING: If the log pattern contains any date/time while this flag is on, the +// result is undefined. +// You must set new pattern(spdlog::set_pattern(..") without any +// date/time in it // // #define SPDLOG_NO_DATETIME /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// // Uncomment if thread id logging is not needed (i.e. no %t in the log pattern). // This will prevent spdlog from quering the thread id on each log call. // -// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is on, the result is undefined. +// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is +// on, the result is undefined. // // #define SPDLOG_NO_THREAD_ID /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// // Uncomment if logger name logging is not needed. // This will prevent spdlog from copying the logger name on each log call. @@ -56,19 +56,19 @@ // #define SPDLOG_TRACE_ON /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// -// Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()). -// Use only if your code never modifes concurrently the registry. -// Note that upon creating a logger the registry is modified by spdlog.. +// Uncomment to avoid locking in the registry operations (spdlog::get(), +// spdlog::drop() spdlog::register()). Use only if your code never modifes +// concurrently the registry. Note that upon creating a logger the registry is +// modified by spdlog.. // // #define SPDLOG_NO_REGISTRY_MUTEX /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// // Uncomment to avoid spdlog's usage of atomic log levels -// Use only if your code never modifies a logger's log levels concurrently by different threads. +// Use only if your code never modifies a logger's log levels concurrently by +// different threads. // // #define SPDLOG_NO_ATOMIC_LEVELS /////////////////////////////////////////////////////////////////////////////// @@ -85,22 +85,20 @@ // #define SPDLOG_EOL ";-)\n" /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// // Uncomment to use your own copy of the fmt library instead of spdlog's copy. -// In this case spdlog will try to include so set your -I flag accordingly. +// In this case spdlog will try to include so set your -I flag +// accordingly. // // #define SPDLOG_FMT_EXTERNAL /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// // Uncomment to enable syslog (disabled by default) // // #define SPDLOG_ENABLE_SYSLOG /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// // Uncomment to prevent child processes from inheriting log file descriptors // diff --git a/external/tclap/Arg.h b/external/tclap/Arg.h index b28eef1..b0289f5 100644 --- a/external/tclap/Arg.h +++ b/external/tclap/Arg.h @@ -21,7 +21,6 @@ * *****************************************************************************/ - #ifndef TCLAP_ARGUMENT_H #define TCLAP_ARGUMENT_H @@ -31,12 +30,12 @@ #define HAVE_SSTREAM #endif +#include +#include +#include +#include #include #include -#include -#include -#include -#include #if defined(HAVE_SSTREAM) #include @@ -49,10 +48,10 @@ typedef std::istrstream istringstream; #endif #include -#include -#include #include +#include #include +#include namespace TCLAP { @@ -61,349 +60,349 @@ namespace TCLAP { * This class, or one of its existing children, must be subclassed to do * anything. */ -class Arg -{ - private: - /** - * Prevent accidental copying. - */ - Arg(const Arg& rhs); - - /** - * Prevent accidental copying. - */ - Arg& operator=(const Arg& rhs); - - /** - * Indicates whether the rest of the arguments should be ignored. - */ - static bool& ignoreRestRef() { static bool ign = false; return ign; } - - /** - * The delimiter that separates an argument flag/name from the - * value. - */ - static char& delimiterRef() { static char delim = ' '; return delim; } - - protected: - - /** - * The single char flag used to identify the argument. - * This value (preceded by a dash {-}), can be used to identify - * an argument on the command line. The _flag can be blank, - * in fact this is how unlabeled args work. Unlabeled args must - * override appropriate functions to get correct handling. Note - * that the _flag does NOT include the dash as part of the flag. - */ - std::string _flag; - - /** - * A single work namd indentifying the argument. - * This value (preceded by two dashed {--}) can also be used - * to identify an argument on the command line. Note that the - * _name does NOT include the two dashes as part of the _name. The - * _name cannot be blank. - */ - std::string _name; - - /** - * Description of the argument. - */ - std::string _description; - - /** - * Indicating whether the argument is required. - */ - bool _required; - - /** - * Label to be used in usage description. Normally set to - * "required", but can be changed when necessary. - */ - std::string _requireLabel; - - /** - * Indicates whether a value is required for the argument. - * Note that the value may be required but the argument/value - * combination may not be, as specified by _required. - */ - bool _valueRequired; - - /** - * Indicates whether the argument has been set. - * Indicates that a value on the command line has matched the - * name/flag of this argument and the values have been set accordingly. - */ - bool _alreadySet; - - /** - * A pointer to a vistitor object. - * The visitor allows special handling to occur as soon as the - * argument is matched. This defaults to NULL and should not - * be used unless absolutely necessary. - */ - Visitor* _visitor; - - /** - * Whether this argument can be ignored, if desired. - */ - bool _ignoreable; - - /** - * Indicates that the arg was set as part of an XOR and not on the - * command line. - */ - bool _xorSet; - - bool _acceptsMultipleValues; - - /** - * Performs the special handling described by the Vistitor. - */ - void _checkWithVisitor() const; - - /** - * Primary constructor. YOU (yes you) should NEVER construct an Arg - * directly, this is a base class that is extended by various children - * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, - * UnlabeledValueArg, or UnlabeledMultiArg instead. - * - * \param flag - The flag identifying the argument. - * \param name - The name identifying the argument. - * \param desc - The description of the argument, used in the usage. - * \param req - Whether the argument is required. - * \param valreq - Whether the a value is required for the argument. - * \param v - The visitor checked by the argument. Defaults to NULL. - */ - Arg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - bool valreq, - Visitor* v = NULL ); - - public: - /** - * Destructor. - */ - virtual ~Arg(); - - /** - * Adds this to the specified list of Args. - * \param argList - The list to add this to. - */ - virtual void addToList( std::list& argList ) const; - - /** - * Begin ignoring arguments since the "--" argument was specified. - */ - static void beginIgnoring() { ignoreRestRef() = true; } - - /** - * Whether to ignore the rest. - */ - static bool ignoreRest() { return ignoreRestRef(); } - - /** - * The delimiter that separates an argument flag/name from the - * value. - */ - static char delimiter() { return delimiterRef(); } - - /** - * The char used as a place holder when SwitchArgs are combined. - * Currently set to the bell char (ASCII 7). - */ - static char blankChar() { return (char)7; } - - /** - * The char that indicates the beginning of a flag. Defaults to '-', but - * clients can define TCLAP_FLAGSTARTCHAR to override. - */ +class Arg { +private: + /** + * Prevent accidental copying. + */ + Arg(const Arg &rhs); + + /** + * Prevent accidental copying. + */ + Arg &operator=(const Arg &rhs); + + /** + * Indicates whether the rest of the arguments should be ignored. + */ + static bool &ignoreRestRef() { + static bool ign = false; + return ign; + } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char &delimiterRef() { + static char delim = ' '; + return delim; + } + +protected: + /** + * The single char flag used to identify the argument. + * This value (preceded by a dash {-}), can be used to identify + * an argument on the command line. The _flag can be blank, + * in fact this is how unlabeled args work. Unlabeled args must + * override appropriate functions to get correct handling. Note + * that the _flag does NOT include the dash as part of the flag. + */ + std::string _flag; + + /** + * A single work namd indentifying the argument. + * This value (preceded by two dashed {--}) can also be used + * to identify an argument on the command line. Note that the + * _name does NOT include the two dashes as part of the _name. The + * _name cannot be blank. + */ + std::string _name; + + /** + * Description of the argument. + */ + std::string _description; + + /** + * Indicating whether the argument is required. + */ + bool _required; + + /** + * Label to be used in usage description. Normally set to + * "required", but can be changed when necessary. + */ + std::string _requireLabel; + + /** + * Indicates whether a value is required for the argument. + * Note that the value may be required but the argument/value + * combination may not be, as specified by _required. + */ + bool _valueRequired; + + /** + * Indicates whether the argument has been set. + * Indicates that a value on the command line has matched the + * name/flag of this argument and the values have been set accordingly. + */ + bool _alreadySet; + + /** + * A pointer to a vistitor object. + * The visitor allows special handling to occur as soon as the + * argument is matched. This defaults to NULL and should not + * be used unless absolutely necessary. + */ + Visitor *_visitor; + + /** + * Whether this argument can be ignored, if desired. + */ + bool _ignoreable; + + /** + * Indicates that the arg was set as part of an XOR and not on the + * command line. + */ + bool _xorSet; + + bool _acceptsMultipleValues; + + /** + * Performs the special handling described by the Vistitor. + */ + void _checkWithVisitor() const; + + /** + * Primary constructor. YOU (yes you) should NEVER construct an Arg + * directly, this is a base class that is extended by various children + * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, + * UnlabeledValueArg, or UnlabeledMultiArg instead. + * + * \param flag - The flag identifying the argument. + * \param name - The name identifying the argument. + * \param desc - The description of the argument, used in the usage. + * \param req - Whether the argument is required. + * \param valreq - Whether the a value is required for the argument. + * \param v - The visitor checked by the argument. Defaults to NULL. + */ + Arg(const std::string &flag, const std::string &name, const std::string &desc, + bool req, bool valreq, Visitor *v = NULL); + +public: + /** + * Destructor. + */ + virtual ~Arg(); + + /** + * Adds this to the specified list of Args. + * \param argList - The list to add this to. + */ + virtual void addToList(std::list &argList) const; + + /** + * Begin ignoring arguments since the "--" argument was specified. + */ + static void beginIgnoring() { ignoreRestRef() = true; } + + /** + * Whether to ignore the rest. + */ + static bool ignoreRest() { return ignoreRestRef(); } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char delimiter() { return delimiterRef(); } + + /** + * The char used as a place holder when SwitchArgs are combined. + * Currently set to the bell char (ASCII 7). + */ + static char blankChar() { return (char)7; } + + /** + * The char that indicates the beginning of a flag. Defaults to '-', but + * clients can define TCLAP_FLAGSTARTCHAR to override. + */ #ifndef TCLAP_FLAGSTARTCHAR #define TCLAP_FLAGSTARTCHAR '-' #endif - static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; } + static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; } - /** - * The sting that indicates the beginning of a flag. Defaults to "-", but - * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same - * as TCLAP_FLAGSTARTCHAR. - */ + /** + * The sting that indicates the beginning of a flag. Defaults to "-", but + * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same + * as TCLAP_FLAGSTARTCHAR. + */ #ifndef TCLAP_FLAGSTARTSTRING #define TCLAP_FLAGSTARTSTRING "-" #endif - static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; } + static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; } - /** - * The sting that indicates the beginning of a name. Defaults to "--", but - * clients can define TCLAP_NAMESTARTSTRING to override. - */ + /** + * The sting that indicates the beginning of a name. Defaults to "--", but + * clients can define TCLAP_NAMESTARTSTRING to override. + */ #ifndef TCLAP_NAMESTARTSTRING #define TCLAP_NAMESTARTSTRING "--" #endif - static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; } - - /** - * The name used to identify the ignore rest argument. - */ - static const std::string ignoreNameString() { return "ignore_rest"; } - - /** - * Sets the delimiter for all arguments. - * \param c - The character that delimits flags/names from values. - */ - static void setDelimiter( char c ) { delimiterRef() = c; } - - /** - * Pure virtual method meant to handle the parsing and value assignment - * of the string on the command line. - * \param i - Pointer the the current argument in the list. - * \param args - Mutable list of strings. What is - * passed in from main. - */ - virtual bool processArg(int *i, std::vector& args) = 0; - - /** - * Operator ==. - * Equality operator. Must be virtual to handle unlabeled args. - * \param a - The Arg to be compared to this. - */ - virtual bool operator==(const Arg& a) const; - - /** - * Returns the argument flag. - */ - const std::string& getFlag() const; - - /** - * Returns the argument name. - */ - const std::string& getName() const; - - /** - * Returns the argument description. - */ - std::string getDescription() const; - - /** - * Indicates whether the argument is required. - */ - virtual bool isRequired() const; - - /** - * Sets _required to true. This is used by the XorHandler. - * You really have no reason to ever use it. - */ - void forceRequired(); - - /** - * Sets the _alreadySet value to true. This is used by the XorHandler. - * You really have no reason to ever use it. - */ - void xorSet(); - - /** - * Indicates whether a value must be specified for argument. - */ - bool isValueRequired() const; - - /** - * Indicates whether the argument has already been set. Only true - * if the arg has been matched on the command line. - */ - bool isSet() const; - - /** - * Indicates whether the argument can be ignored, if desired. - */ - bool isIgnoreable() const; - - /** - * A method that tests whether a string matches this argument. - * This is generally called by the processArg() method. This - * method could be re-implemented by a child to change how - * arguments are specified on the command line. - * \param s - The string to be compared to the flag/name to determine - * whether the arg matches. - */ - virtual bool argMatches( const std::string& s ) const; - - /** - * Returns a simple string representation of the argument. - * Primarily for debugging. - */ - virtual std::string toString() const; - - /** - * Returns a short ID for the usage. - * \param valueId - The value used in the id. - */ - virtual std::string shortID( const std::string& valueId = "val" ) const; - - /** - * Returns a long ID for the usage. - * \param valueId - The value used in the id. - */ - virtual std::string longID( const std::string& valueId = "val" ) const; - - /** - * Trims a value off of the flag. - * \param flag - The string from which the flag and value will be - * trimmed. Contains the flag once the value has been trimmed. - * \param value - Where the value trimmed from the string will - * be stored. - */ - virtual void trimFlag( std::string& flag, std::string& value ) const; - - /** - * Checks whether a given string has blank chars, indicating that - * it is a combined SwitchArg. If so, return true, otherwise return - * false. - * \param s - string to be checked. - */ - bool _hasBlanks( const std::string& s ) const; - - /** - * Sets the requireLabel. Used by XorHandler. You shouldn't ever - * use this. - * \param s - Set the requireLabel to this value. - */ - void setRequireLabel( const std::string& s ); - - /** - * Used for MultiArgs and XorHandler to determine whether args - * can still be set. - */ - virtual bool allowMore(); - - /** - * Use by output classes to determine whether an Arg accepts - * multiple values. - */ - virtual bool acceptsMultipleValues(); - - /** - * Clears the Arg object and allows it to be reused by new - * command lines. - */ - virtual void reset(); + static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; } + + /** + * The name used to identify the ignore rest argument. + */ + static const std::string ignoreNameString() { return "ignore_rest"; } + + /** + * Sets the delimiter for all arguments. + * \param c - The character that delimits flags/names from values. + */ + static void setDelimiter(char c) { delimiterRef() = c; } + + /** + * Pure virtual method meant to handle the parsing and value assignment + * of the string on the command line. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. What is + * passed in from main. + */ + virtual bool processArg(int *i, std::vector &args) = 0; + + /** + * Operator ==. + * Equality operator. Must be virtual to handle unlabeled args. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg &a) const; + + /** + * Returns the argument flag. + */ + const std::string &getFlag() const; + + /** + * Returns the argument name. + */ + const std::string &getName() const; + + /** + * Returns the argument description. + */ + std::string getDescription() const; + + /** + * Indicates whether the argument is required. + */ + virtual bool isRequired() const; + + /** + * Sets _required to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void forceRequired(); + + /** + * Sets the _alreadySet value to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void xorSet(); + + /** + * Indicates whether a value must be specified for argument. + */ + bool isValueRequired() const; + + /** + * Indicates whether the argument has already been set. Only true + * if the arg has been matched on the command line. + */ + bool isSet() const; + + /** + * Indicates whether the argument can be ignored, if desired. + */ + bool isIgnoreable() const; + + /** + * A method that tests whether a string matches this argument. + * This is generally called by the processArg() method. This + * method could be re-implemented by a child to change how + * arguments are specified on the command line. + * \param s - The string to be compared to the flag/name to determine + * whether the arg matches. + */ + virtual bool argMatches(const std::string &s) const; + + /** + * Returns a simple string representation of the argument. + * Primarily for debugging. + */ + virtual std::string toString() const; + + /** + * Returns a short ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string shortID(const std::string &valueId = "val") const; + + /** + * Returns a long ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string longID(const std::string &valueId = "val") const; + + /** + * Trims a value off of the flag. + * \param flag - The string from which the flag and value will be + * trimmed. Contains the flag once the value has been trimmed. + * \param value - Where the value trimmed from the string will + * be stored. + */ + virtual void trimFlag(std::string &flag, std::string &value) const; + + /** + * Checks whether a given string has blank chars, indicating that + * it is a combined SwitchArg. If so, return true, otherwise return + * false. + * \param s - string to be checked. + */ + bool _hasBlanks(const std::string &s) const; + + /** + * Sets the requireLabel. Used by XorHandler. You shouldn't ever + * use this. + * \param s - Set the requireLabel to this value. + */ + void setRequireLabel(const std::string &s); + + /** + * Used for MultiArgs and XorHandler to determine whether args + * can still be set. + */ + virtual bool allowMore(); + + /** + * Use by output classes to determine whether an Arg accepts + * multiple values. + */ + virtual bool acceptsMultipleValues(); + + /** + * Clears the Arg object and allows it to be reused by new + * command lines. + */ + virtual void reset(); }; /** * Typedef of an Arg list iterator. */ -typedef std::list::iterator ArgListIterator; +typedef std::list::iterator ArgListIterator; /** * Typedef of an Arg vector iterator. */ -typedef std::vector::iterator ArgVectorIterator; +typedef std::vector::iterator ArgVectorIterator; /** * Typedef of a Visitor list iterator. */ -typedef std::list::iterator VisitorListIterator; +typedef std::list::iterator VisitorListIterator; /* * Extract a value of type T from it's string representation contained @@ -411,35 +410,34 @@ typedef std::list::iterator VisitorListIterator; * specialization of ExtractValue depending on the value traits of T. * ValueLike traits use operator>> to assign the value from strVal. */ -template void -ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) -{ - static_cast(vl); // Avoid warning about unused vl - std::istringstream is(strVal); - - int valuesRead = 0; - while ( is.good() ) { - if ( is.peek() != EOF ) +template +void ExtractValue(T &destVal, const std::string &strVal, ValueLike vl) { + static_cast(vl); // Avoid warning about unused vl + std::istringstream is(strVal); + + int valuesRead = 0; + while (is.good()) { + if (is.peek() != EOF) #ifdef TCLAP_SETBASE_ZERO - is >> std::setbase(0) >> destVal; + is >> std::setbase(0) >> destVal; #else - is >> destVal; + is >> destVal; #endif - else - break; - - valuesRead++; - } + else + break; - if ( is.fail() ) - throw( ArgParseException("Couldn't read argument value " - "from string '" + strVal + "'")); + valuesRead++; + } + if (is.fail()) + throw(ArgParseException("Couldn't read argument value " + "from string '" + + strVal + "'")); - if ( valuesRead > 1 ) - throw( ArgParseException("More than one valid value parsed from " - "string '" + strVal + "'")); - + if (valuesRead > 1) + throw(ArgParseException("More than one valid value parsed from " + "string '" + + strVal + "'")); } /* @@ -448,245 +446,201 @@ ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) * specialization of ExtractValue depending on the value traits of T. * StringLike uses assignment (operator=) to assign from strVal. */ -template void -ExtractValue(T &destVal, const std::string& strVal, StringLike sl) -{ - static_cast(sl); // Avoid warning about unused sl - SetString(destVal, strVal); +template +void ExtractValue(T &destVal, const std::string &strVal, StringLike sl) { + static_cast(sl); // Avoid warning about unused sl + SetString(destVal, strVal); } ////////////////////////////////////////////////////////////////////// -//BEGIN Arg.cpp +// BEGIN Arg.cpp ////////////////////////////////////////////////////////////////////// -inline Arg::Arg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - bool valreq, - Visitor* v) : - _flag(flag), - _name(name), - _description(desc), - _required(req), - _requireLabel("required"), - _valueRequired(valreq), - _alreadySet(false), - _visitor( v ), - _ignoreable(true), - _xorSet(false), - _acceptsMultipleValues(false) -{ - if ( _flag.length() > 1 ) - throw(SpecificationException( - "Argument flag can only be one character long", toString() ) ); - - if ( _name != ignoreNameString() && - ( _flag == Arg::flagStartString() || - _flag == Arg::nameStartString() || - _flag == " " ) ) - throw(SpecificationException("Argument flag cannot be either '" + - Arg::flagStartString() + "' or '" + - Arg::nameStartString() + "' or a space.", - toString() ) ); - - if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) || - ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) || - ( _name.find( " ", 0 ) != std::string::npos ) ) - throw(SpecificationException("Argument name begin with either '" + - Arg::flagStartString() + "' or '" + - Arg::nameStartString() + "' or space.", - toString() ) ); - +inline Arg::Arg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, bool valreq, Visitor *v) + : _flag(flag), _name(name), _description(desc), _required(req), + _requireLabel("required"), _valueRequired(valreq), _alreadySet(false), + _visitor(v), _ignoreable(true), _xorSet(false), + _acceptsMultipleValues(false) { + if (_flag.length() > 1) + throw(SpecificationException("Argument flag can only be one character long", + toString())); + + if (_name != ignoreNameString() && + (_flag == Arg::flagStartString() || _flag == Arg::nameStartString() || + _flag == " ")) + throw(SpecificationException("Argument flag cannot be either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or a space.", + toString())); + + if ((_name.substr(0, Arg::flagStartString().length()) == + Arg::flagStartString()) || + (_name.substr(0, Arg::nameStartString().length()) == + Arg::nameStartString()) || + (_name.find(" ", 0) != std::string::npos)) + throw(SpecificationException("Argument name begin with either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or space.", + toString())); } -inline Arg::~Arg() { } +inline Arg::~Arg() {} -inline std::string Arg::shortID( const std::string& valueId ) const -{ - std::string id = ""; +inline std::string Arg::shortID(const std::string &valueId) const { + std::string id = ""; - if ( _flag != "" ) - id = Arg::flagStartString() + _flag; - else - id = Arg::nameStartString() + _name; + if (_flag != "") + id = Arg::flagStartString() + _flag; + else + id = Arg::nameStartString() + _name; - if ( _valueRequired ) - id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + if (_valueRequired) + id += std::string(1, Arg::delimiter()) + "<" + valueId + ">"; - if ( !_required ) - id = "[" + id + "]"; + if (!_required) + id = "[" + id + "]"; - return id; + return id; } -inline std::string Arg::longID( const std::string& valueId ) const -{ - std::string id = ""; - - if ( _flag != "" ) - { - id += Arg::flagStartString() + _flag; +inline std::string Arg::longID(const std::string &valueId) const { + std::string id = ""; - if ( _valueRequired ) - id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + if (_flag != "") { + id += Arg::flagStartString() + _flag; - id += ", "; - } + if (_valueRequired) + id += std::string(1, Arg::delimiter()) + "<" + valueId + ">"; - id += Arg::nameStartString() + _name; + id += ", "; + } - if ( _valueRequired ) - id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + id += Arg::nameStartString() + _name; - return id; + if (_valueRequired) + id += std::string(1, Arg::delimiter()) + "<" + valueId + ">"; + return id; } -inline bool Arg::operator==(const Arg& a) const -{ - if ( ( _flag != "" && _flag == a._flag ) || _name == a._name) - return true; - else - return false; +inline bool Arg::operator==(const Arg &a) const { + if ((_flag != "" && _flag == a._flag) || _name == a._name) + return true; + else + return false; } -inline std::string Arg::getDescription() const -{ - std::string desc = ""; - if ( _required ) - desc = "(" + _requireLabel + ") "; +inline std::string Arg::getDescription() const { + std::string desc = ""; + if (_required) + desc = "(" + _requireLabel + ") "; -// if ( _valueRequired ) -// desc += "(value required) "; + // if ( _valueRequired ) + // desc += "(value required) "; - desc += _description; - return desc; + desc += _description; + return desc; } -inline const std::string& Arg::getFlag() const { return _flag; } +inline const std::string &Arg::getFlag() const { return _flag; } -inline const std::string& Arg::getName() const { return _name; } +inline const std::string &Arg::getName() const { return _name; } inline bool Arg::isRequired() const { return _required; } inline bool Arg::isValueRequired() const { return _valueRequired; } -inline bool Arg::isSet() const -{ - if ( _alreadySet && !_xorSet ) - return true; - else - return false; +inline bool Arg::isSet() const { + if (_alreadySet && !_xorSet) + return true; + else + return false; } inline bool Arg::isIgnoreable() const { return _ignoreable; } -inline void Arg::setRequireLabel( const std::string& s) -{ - _requireLabel = s; -} +inline void Arg::setRequireLabel(const std::string &s) { _requireLabel = s; } -inline bool Arg::argMatches( const std::string& argFlag ) const -{ - if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) || - argFlag == Arg::nameStartString() + _name ) - return true; - else - return false; +inline bool Arg::argMatches(const std::string &argFlag) const { + if ((argFlag == Arg::flagStartString() + _flag && _flag != "") || + argFlag == Arg::nameStartString() + _name) + return true; + else + return false; } -inline std::string Arg::toString() const -{ - std::string s = ""; +inline std::string Arg::toString() const { + std::string s = ""; - if ( _flag != "" ) - s += Arg::flagStartString() + _flag + " "; + if (_flag != "") + s += Arg::flagStartString() + _flag + " "; - s += "(" + Arg::nameStartString() + _name + ")"; + s += "(" + Arg::nameStartString() + _name + ")"; - return s; + return s; } -inline void Arg::_checkWithVisitor() const -{ - if ( _visitor != NULL ) - _visitor->visit(); +inline void Arg::_checkWithVisitor() const { + if (_visitor != NULL) + _visitor->visit(); } /** * Implementation of trimFlag. */ -inline void Arg::trimFlag(std::string& flag, std::string& value) const -{ - int stop = 0; - for ( int i = 0; static_cast(i) < flag.length(); i++ ) - if ( flag[i] == Arg::delimiter() ) - { - stop = i; - break; - } - - if ( stop > 1 ) - { - value = flag.substr(stop+1); - flag = flag.substr(0,stop); - } +inline void Arg::trimFlag(std::string &flag, std::string &value) const { + int stop = 0; + for (int i = 0; static_cast(i) < flag.length(); i++) + if (flag[i] == Arg::delimiter()) { + stop = i; + break; + } + if (stop > 1) { + value = flag.substr(stop + 1); + flag = flag.substr(0, stop); + } } /** * Implementation of _hasBlanks. */ -inline bool Arg::_hasBlanks( const std::string& s ) const -{ - for ( int i = 1; static_cast(i) < s.length(); i++ ) - if ( s[i] == Arg::blankChar() ) - return true; +inline bool Arg::_hasBlanks(const std::string &s) const { + for (int i = 1; static_cast(i) < s.length(); i++) + if (s[i] == Arg::blankChar()) + return true; - return false; + return false; } -inline void Arg::forceRequired() -{ - _required = true; -} +inline void Arg::forceRequired() { _required = true; } -inline void Arg::xorSet() -{ - _alreadySet = true; - _xorSet = true; +inline void Arg::xorSet() { + _alreadySet = true; + _xorSet = true; } /** * Overridden by Args that need to added to the end of the list. */ -inline void Arg::addToList( std::list& argList ) const -{ - argList.push_front( const_cast(this) ); +inline void Arg::addToList(std::list &argList) const { + argList.push_front(const_cast(this)); } -inline bool Arg::allowMore() -{ - return false; -} +inline bool Arg::allowMore() { return false; } -inline bool Arg::acceptsMultipleValues() -{ - return _acceptsMultipleValues; -} +inline bool Arg::acceptsMultipleValues() { return _acceptsMultipleValues; } -inline void Arg::reset() -{ - _xorSet = false; - _alreadySet = false; +inline void Arg::reset() { + _xorSet = false; + _alreadySet = false; } ////////////////////////////////////////////////////////////////////// -//END Arg.cpp +// END Arg.cpp ////////////////////////////////////////////////////////////////////// -} //namespace TCLAP +} // namespace TCLAP #endif - diff --git a/external/tclap/ArgException.h b/external/tclap/ArgException.h index 3411aa9..5e6bc0f 100644 --- a/external/tclap/ArgException.h +++ b/external/tclap/ArgException.h @@ -1,31 +1,30 @@ // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- -/****************************************************************************** - * +/****************************************************************************** + * * file: ArgException.h - * + * * Copyright (c) 2003, Michael E. Smoot . * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_ARG_EXCEPTION_H #define TCLAP_ARG_EXCEPTION_H -#include #include +#include namespace TCLAP { @@ -33,168 +32,143 @@ namespace TCLAP { * A simple class that defines and argument exception. Should be caught * whenever a CmdLine is created and parsed. */ -class ArgException : public std::exception -{ - public: - - /** - * Constructor. - * \param text - The text of the exception. - * \param id - The text identifying the argument source. - * \param td - Text describing the type of ArgException it is. - * of the exception. - */ - ArgException( const std::string& text = "undefined exception", - const std::string& id = "undefined", - const std::string& td = "Generic ArgException") - : std::exception(), - _errorText(text), - _argId( id ), - _typeDescription(td) - { } - - /** - * Destructor. - */ - virtual ~ArgException() throw() { } - - /** - * Returns the error text. - */ - std::string error() const { return ( _errorText ); } - - /** - * Returns the argument id. - */ - std::string argId() const - { - if ( _argId == "undefined" ) - return " "; - else - return ( "Argument: " + _argId ); - } - - /** - * Returns the arg id and error text. - */ - const char* what() const throw() - { - static std::string ex; - ex = _argId + " -- " + _errorText; - return ex.c_str(); - } - - /** - * Returns the type of the exception. Used to explain and distinguish - * between different child exceptions. - */ - std::string typeDescription() const - { - return _typeDescription; - } - - - private: - - /** - * The text of the exception message. - */ - std::string _errorText; - - /** - * The argument related to this exception. - */ - std::string _argId; - - /** - * Describes the type of the exception. Used to distinguish - * between different child exceptions. - */ - std::string _typeDescription; +class ArgException : public std::exception { +public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source. + * \param td - Text describing the type of ArgException it is. + * of the exception. + */ + ArgException(const std::string &text = "undefined exception", + const std::string &id = "undefined", + const std::string &td = "Generic ArgException") + : std::exception(), _errorText(text), _argId(id), _typeDescription(td) {} + + /** + * Destructor. + */ + virtual ~ArgException() throw() {} + + /** + * Returns the error text. + */ + std::string error() const { return (_errorText); } + + /** + * Returns the argument id. + */ + std::string argId() const { + if (_argId == "undefined") + return " "; + else + return ("Argument: " + _argId); + } + + /** + * Returns the arg id and error text. + */ + const char *what() const throw() { + static std::string ex; + ex = _argId + " -- " + _errorText; + return ex.c_str(); + } + + /** + * Returns the type of the exception. Used to explain and distinguish + * between different child exceptions. + */ + std::string typeDescription() const { return _typeDescription; } +private: + /** + * The text of the exception message. + */ + std::string _errorText; + + /** + * The argument related to this exception. + */ + std::string _argId; + + /** + * Describes the type of the exception. Used to distinguish + * between different child exceptions. + */ + std::string _typeDescription; }; /** * Thrown from within the child Arg classes when it fails to properly * parse the argument it has been passed. */ -class ArgParseException : public ArgException -{ - public: - /** - * Constructor. - * \param text - The text of the exception. - * \param id - The text identifying the argument source - * of the exception. - */ - ArgParseException( const std::string& text = "undefined exception", - const std::string& id = "undefined" ) - : ArgException( text, - id, - std::string( "Exception found while parsing " ) + - std::string( "the value the Arg has been passed." )) - { } +class ArgParseException : public ArgException { +public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + ArgParseException(const std::string &text = "undefined exception", + const std::string &id = "undefined") + : ArgException(text, id, + std::string("Exception found while parsing ") + + std::string("the value the Arg has been passed.")) {} }; /** * Thrown from CmdLine when the arguments on the command line are not * properly specified, e.g. too many arguments, required argument missing, etc. */ -class CmdLineParseException : public ArgException -{ - public: - /** - * Constructor. - * \param text - The text of the exception. - * \param id - The text identifying the argument source - * of the exception. - */ - CmdLineParseException( const std::string& text = "undefined exception", - const std::string& id = "undefined" ) - : ArgException( text, - id, - std::string( "Exception found when the values ") + - std::string( "on the command line do not meet ") + - std::string( "the requirements of the defined ") + - std::string( "Args." )) - { } +class CmdLineParseException : public ArgException { +public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + CmdLineParseException(const std::string &text = "undefined exception", + const std::string &id = "undefined") + : ArgException(text, id, + std::string("Exception found when the values ") + + std::string("on the command line do not meet ") + + std::string("the requirements of the defined ") + + std::string("Args.")) {} }; /** - * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. + * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. * same flag as another Arg, same name, etc. */ -class SpecificationException : public ArgException -{ - public: - /** - * Constructor. - * \param text - The text of the exception. - * \param id - The text identifying the argument source - * of the exception. - */ - SpecificationException( const std::string& text = "undefined exception", - const std::string& id = "undefined" ) - : ArgException( text, - id, - std::string("Exception found when an Arg object ")+ - std::string("is improperly defined by the ") + - std::string("developer." )) - { } - +class SpecificationException : public ArgException { +public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + SpecificationException(const std::string &text = "undefined exception", + const std::string &id = "undefined") + : ArgException(text, id, + std::string("Exception found when an Arg object ") + + std::string("is improperly defined by the ") + + std::string("developer.")) {} }; class ExitException { public: - ExitException(int estat) : _estat(estat) {} + ExitException(int estat) : _estat(estat) {} - int getExitStatus() const { return _estat; } + int getExitStatus() const { return _estat; } private: - int _estat; + int _estat; }; } // namespace TCLAP #endif - diff --git a/external/tclap/ArgTraits.h b/external/tclap/ArgTraits.h index 0b2c18f..d34d412 100644 --- a/external/tclap/ArgTraits.h +++ b/external/tclap/ArgTraits.h @@ -36,8 +36,8 @@ namespace TCLAP { * operator>>. This is the default value type. */ struct ValueLike { - typedef ValueLike ValueCategory; - virtual ~ValueLike() {} + typedef ValueLike ValueCategory; + virtual ~ValueLike() {} }; /** @@ -46,7 +46,7 @@ struct ValueLike { * will be broken up into individual tokens by operator>>. */ struct StringLike { - virtual ~StringLike() {} + virtual ~StringLike() {} }; /** @@ -55,8 +55,8 @@ struct StringLike { * to the inherenting class. */ struct StringLikeTrait { - typedef StringLike ValueCategory; - virtual ~StringLikeTrait() {} + typedef StringLike ValueCategory; + virtual ~StringLikeTrait() {} }; /** @@ -65,8 +65,8 @@ struct StringLikeTrait { * to the inherenting class. */ struct ValueLikeTrait { - typedef ValueLike ValueCategory; - virtual ~ValueLikeTrait() {} + typedef ValueLike ValueCategory; + virtual ~ValueLikeTrait() {} }; /** @@ -75,11 +75,10 @@ struct ValueLikeTrait { * values gets assigned to any particular type during parsing. The two * supported types are StringLike and ValueLike. */ -template -struct ArgTraits { - typedef typename T::ValueCategory ValueCategory; - virtual ~ArgTraits() {} - //typedef ValueLike ValueCategory; +template struct ArgTraits { + typedef typename T::ValueCategory ValueCategory; + virtual ~ArgTraits() {} + // typedef ValueLike ValueCategory; }; #endif diff --git a/external/tclap/CmdLine.h b/external/tclap/CmdLine.h index 0fec8d8..6de435c 100644 --- a/external/tclap/CmdLine.h +++ b/external/tclap/CmdLine.h @@ -24,15 +24,15 @@ #ifndef TCLAP_CMDLINE_H #define TCLAP_CMDLINE_H -#include #include -#include +#include #include +#include -#include #include -#include #include +#include +#include #include #include @@ -40,594 +40,511 @@ #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include #include // Needed for exit(), which isn't defined in some envs. +#include +#include namespace TCLAP { -template void DelPtr(T ptr) -{ - delete ptr; -} +template void DelPtr(T ptr) { delete ptr; } -template void ClearContainer(C &c) -{ - typedef typename C::value_type value_type; - std::for_each(c.begin(), c.end(), DelPtr); - c.clear(); +template void ClearContainer(C &c) { + typedef typename C::value_type value_type; + std::for_each(c.begin(), c.end(), DelPtr); + c.clear(); } - /** * The base class that manages the command line definition and passes * along the parsing to the appropriate Arg classes. */ -class CmdLine : public CmdLineInterface -{ - protected: - - /** - * The list of arguments that will be tested against the - * command line. - */ - std::list _argList; - - /** - * The name of the program. Set to argv[0]. - */ - std::string _progName; - - /** - * A message used to describe the program. Used in the usage output. - */ - std::string _message; - - /** - * The version to be displayed with the --version switch. - */ - std::string _version; - - /** - * The number of arguments that are required to be present on - * the command line. This is set dynamically, based on the - * Args added to the CmdLine object. - */ - int _numRequired; - - /** - * The character that is used to separate the argument flag/name - * from the value. Defaults to ' ' (space). - */ - char _delimiter; - - /** - * The handler that manages xoring lists of args. - */ - XorHandler _xorHandler; - - /** - * A list of Args to be explicitly deleted when the destructor - * is called. At the moment, this only includes the three default - * Args. - */ - std::list _argDeleteOnExitList; - - /** - * A list of Visitors to be explicitly deleted when the destructor - * is called. At the moment, these are the Vistors created for the - * default Args. - */ - std::list _visitorDeleteOnExitList; - - /** - * Object that handles all output for the CmdLine. - */ - CmdLineOutput* _output; - - /** - * Should CmdLine handle parsing exceptions internally? - */ - bool _handleExceptions; - - /** - * Throws an exception listing the missing args. - */ - void missingArgsException(); - - /** - * Checks whether a name/flag string matches entirely matches - * the Arg::blankChar. Used when multiple switches are combined - * into a single argument. - * \param s - The message to be used in the usage. - */ - bool _emptyCombined(const std::string& s); - - /** - * Perform a delete ptr; operation on ptr when this object is deleted. - */ - void deleteOnExit(Arg* ptr); - - /** - * Perform a delete ptr; operation on ptr when this object is deleted. - */ - void deleteOnExit(Visitor* ptr); +class CmdLine : public CmdLineInterface { +protected: + /** + * The list of arguments that will be tested against the + * command line. + */ + std::list _argList; + + /** + * The name of the program. Set to argv[0]. + */ + std::string _progName; + + /** + * A message used to describe the program. Used in the usage output. + */ + std::string _message; + + /** + * The version to be displayed with the --version switch. + */ + std::string _version; + + /** + * The number of arguments that are required to be present on + * the command line. This is set dynamically, based on the + * Args added to the CmdLine object. + */ + int _numRequired; + + /** + * The character that is used to separate the argument flag/name + * from the value. Defaults to ' ' (space). + */ + char _delimiter; + + /** + * The handler that manages xoring lists of args. + */ + XorHandler _xorHandler; + + /** + * A list of Args to be explicitly deleted when the destructor + * is called. At the moment, this only includes the three default + * Args. + */ + std::list _argDeleteOnExitList; + + /** + * A list of Visitors to be explicitly deleted when the destructor + * is called. At the moment, these are the Vistors created for the + * default Args. + */ + std::list _visitorDeleteOnExitList; + + /** + * Object that handles all output for the CmdLine. + */ + CmdLineOutput *_output; + + /** + * Should CmdLine handle parsing exceptions internally? + */ + bool _handleExceptions; + + /** + * Throws an exception listing the missing args. + */ + void missingArgsException(); + + /** + * Checks whether a name/flag string matches entirely matches + * the Arg::blankChar. Used when multiple switches are combined + * into a single argument. + * \param s - The message to be used in the usage. + */ + bool _emptyCombined(const std::string &s); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Arg *ptr); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Visitor *ptr); private: - - /** - * Prevent accidental copying. - */ - CmdLine(const CmdLine& rhs); - CmdLine& operator=(const CmdLine& rhs); - - /** - * Encapsulates the code common to the constructors - * (which is all of it). - */ - void _constructor(); - - - /** - * Is set to true when a user sets the output object. We use this so - * that we don't delete objects that are created outside of this lib. - */ - bool _userSetOutput; - - /** - * Whether or not to automatically create help and version switches. - */ - bool _helpAndVersion; - - public: - - /** - * Command line constructor. Defines how the arguments will be - * parsed. - * \param message - The message to be used in the usage - * output. - * \param delimiter - The character that is used to separate - * the argument flag/name from the value. Defaults to ' ' (space). - * \param version - The version number to be used in the - * --version switch. - * \param helpAndVersion - Whether or not to create the Help and - * Version switches. Defaults to true. - */ - CmdLine(const std::string& message, - const char delimiter = ' ', - const std::string& version = "none", - bool helpAndVersion = true); - - /** - * Deletes any resources allocated by a CmdLine object. - */ - virtual ~CmdLine(); - - /** - * Adds an argument to the list of arguments to be parsed. - * \param a - Argument to be added. - */ - void add( Arg& a ); - - /** - * An alternative add. Functionally identical. - * \param a - Argument to be added. - */ - void add( Arg* a ); - - /** - * Add two Args that will be xor'd. If this method is used, add does - * not need to be called. - * \param a - Argument to be added and xor'd. - * \param b - Argument to be added and xor'd. - */ - void xorAdd( Arg& a, Arg& b ); - - /** - * Add a list of Args that will be xor'd. If this method is used, - * add does not need to be called. - * \param xors - List of Args to be added and xor'd. - */ - void xorAdd( std::vector& xors ); - - /** - * Parses the command line. - * \param argc - Number of arguments. - * \param argv - Array of arguments. - */ - void parse(int argc, const char * const * argv); - - /** - * Parses the command line. - * \param args - A vector of strings representing the args. - * args[0] is still the program name. - */ - void parse(std::vector& args); - - /** - * - */ - CmdLineOutput* getOutput(); - - /** - * - */ - void setOutput(CmdLineOutput* co); - - /** - * - */ - std::string& getVersion(); - - /** - * - */ - std::string& getProgramName(); - - /** - * - */ - std::list& getArgList(); - - /** - * - */ - XorHandler& getXorHandler(); - - /** - * - */ - char getDelimiter(); - - /** - * - */ - std::string& getMessage(); - - /** - * - */ - bool hasHelpAndVersion(); - - /** - * Disables or enables CmdLine's internal parsing exception handling. - * - * @param state Should CmdLine handle parsing exceptions internally? - */ - void setExceptionHandling(const bool state); - - /** - * Returns the current state of the internal exception handling. - * - * @retval true Parsing exceptions are handled internally. - * @retval false Parsing exceptions are propagated to the caller. - */ - bool getExceptionHandling() const; - - /** - * Allows the CmdLine object to be reused. - */ - void reset(); - + /** + * Prevent accidental copying. + */ + CmdLine(const CmdLine &rhs); + CmdLine &operator=(const CmdLine &rhs); + + /** + * Encapsulates the code common to the constructors + * (which is all of it). + */ + void _constructor(); + + /** + * Is set to true when a user sets the output object. We use this so + * that we don't delete objects that are created outside of this lib. + */ + bool _userSetOutput; + + /** + * Whether or not to automatically create help and version switches. + */ + bool _helpAndVersion; + +public: + /** + * Command line constructor. Defines how the arguments will be + * parsed. + * \param message - The message to be used in the usage + * output. + * \param delimiter - The character that is used to separate + * the argument flag/name from the value. Defaults to ' ' (space). + * \param version - The version number to be used in the + * --version switch. + * \param helpAndVersion - Whether or not to create the Help and + * Version switches. Defaults to true. + */ + CmdLine(const std::string &message, const char delimiter = ' ', + const std::string &version = "none", bool helpAndVersion = true); + + /** + * Deletes any resources allocated by a CmdLine object. + */ + virtual ~CmdLine(); + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + void add(Arg &a); + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + void add(Arg *a); + + /** + * Add two Args that will be xor'd. If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + void xorAdd(Arg &a, Arg &b); + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + void xorAdd(std::vector &xors); + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + void parse(int argc, const char *const *argv); + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector &args); + + /** + * + */ + CmdLineOutput *getOutput(); + + /** + * + */ + void setOutput(CmdLineOutput *co); + + /** + * + */ + std::string &getVersion(); + + /** + * + */ + std::string &getProgramName(); + + /** + * + */ + std::list &getArgList(); + + /** + * + */ + XorHandler &getXorHandler(); + + /** + * + */ + char getDelimiter(); + + /** + * + */ + std::string &getMessage(); + + /** + * + */ + bool hasHelpAndVersion(); + + /** + * Disables or enables CmdLine's internal parsing exception handling. + * + * @param state Should CmdLine handle parsing exceptions internally? + */ + void setExceptionHandling(const bool state); + + /** + * Returns the current state of the internal exception handling. + * + * @retval true Parsing exceptions are handled internally. + * @retval false Parsing exceptions are propagated to the caller. + */ + bool getExceptionHandling() const; + + /** + * Allows the CmdLine object to be reused. + */ + void reset(); }; - /////////////////////////////////////////////////////////////////////////////// -//Begin CmdLine.cpp +// Begin CmdLine.cpp /////////////////////////////////////////////////////////////////////////////// -inline CmdLine::CmdLine(const std::string& m, - char delim, - const std::string& v, - bool help ) - : - _argList(std::list()), - _progName("not_set_yet"), - _message(m), - _version(v), - _numRequired(0), - _delimiter(delim), - _xorHandler(XorHandler()), - _argDeleteOnExitList(std::list()), - _visitorDeleteOnExitList(std::list()), - _output(0), - _handleExceptions(true), - _userSetOutput(false), - _helpAndVersion(help) -{ - _constructor(); +inline CmdLine::CmdLine(const std::string &m, char delim, const std::string &v, + bool help) + : _argList(std::list()), _progName("not_set_yet"), _message(m), + _version(v), _numRequired(0), _delimiter(delim), + _xorHandler(XorHandler()), _argDeleteOnExitList(std::list()), + _visitorDeleteOnExitList(std::list()), _output(0), + _handleExceptions(true), _userSetOutput(false), _helpAndVersion(help) { + _constructor(); } -inline CmdLine::~CmdLine() -{ - ClearContainer(_argDeleteOnExitList); - ClearContainer(_visitorDeleteOnExitList); +inline CmdLine::~CmdLine() { + ClearContainer(_argDeleteOnExitList); + ClearContainer(_visitorDeleteOnExitList); - if ( !_userSetOutput ) { - delete _output; - _output = 0; - } + if (!_userSetOutput) { + delete _output; + _output = 0; + } } -inline void CmdLine::_constructor() -{ - _output = new StdOutput; - - Arg::setDelimiter( _delimiter ); - - Visitor* v; - - if ( _helpAndVersion ) - { - v = new HelpVisitor( this, &_output ); - SwitchArg* help = new SwitchArg("h","help", - "Displays usage information and exits.", - false, v); - add( help ); - deleteOnExit(help); - deleteOnExit(v); - - v = new VersionVisitor( this, &_output ); - SwitchArg* vers = new SwitchArg("","version", - "Displays version information and exits.", - false, v); - add( vers ); - deleteOnExit(vers); - deleteOnExit(v); - } - - v = new IgnoreRestVisitor(); - SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), - Arg::ignoreNameString(), - "Ignores the rest of the labeled arguments following this flag.", - false, v); - add( ignore ); - deleteOnExit(ignore); - deleteOnExit(v); +inline void CmdLine::_constructor() { + _output = new StdOutput; + + Arg::setDelimiter(_delimiter); + + Visitor *v; + + if (_helpAndVersion) { + v = new HelpVisitor(this, &_output); + SwitchArg *help = new SwitchArg( + "h", "help", "Displays usage information and exits.", false, v); + add(help); + deleteOnExit(help); + deleteOnExit(v); + + v = new VersionVisitor(this, &_output); + SwitchArg *vers = new SwitchArg( + "", "version", "Displays version information and exits.", false, v); + add(vers); + deleteOnExit(vers); + deleteOnExit(v); + } + + v = new IgnoreRestVisitor(); + SwitchArg *ignore = new SwitchArg( + Arg::flagStartString(), Arg::ignoreNameString(), + "Ignores the rest of the labeled arguments following this flag.", false, + v); + add(ignore); + deleteOnExit(ignore); + deleteOnExit(v); } -inline void CmdLine::xorAdd( std::vector& ors ) -{ - _xorHandler.add( ors ); +inline void CmdLine::xorAdd(std::vector &ors) { + _xorHandler.add(ors); - for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) - { - (*it)->forceRequired(); - (*it)->setRequireLabel( "OR required" ); - add( *it ); - } + for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) { + (*it)->forceRequired(); + (*it)->setRequireLabel("OR required"); + add(*it); + } } -inline void CmdLine::xorAdd( Arg& a, Arg& b ) -{ - std::vector ors; - ors.push_back( &a ); - ors.push_back( &b ); - xorAdd( ors ); +inline void CmdLine::xorAdd(Arg &a, Arg &b) { + std::vector ors; + ors.push_back(&a); + ors.push_back(&b); + xorAdd(ors); } -inline void CmdLine::add( Arg& a ) -{ - add( &a ); -} +inline void CmdLine::add(Arg &a) { add(&a); } -inline void CmdLine::add( Arg* a ) -{ - for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) - if ( *a == *(*it) ) - throw( SpecificationException( - "Argument with same flag/name already exists!", - a->longID() ) ); +inline void CmdLine::add(Arg *a) { + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) + if (*a == *(*it)) + throw(SpecificationException( + "Argument with same flag/name already exists!", a->longID())); - a->addToList( _argList ); + a->addToList(_argList); - if ( a->isRequired() ) - _numRequired++; + if (a->isRequired()) + _numRequired++; } +inline void CmdLine::parse(int argc, const char *const *argv) { + // this step is necessary so that we have easy access to + // mutable strings. + std::vector args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); -inline void CmdLine::parse(int argc, const char * const * argv) -{ - // this step is necessary so that we have easy access to - // mutable strings. - std::vector args; - for (int i = 0; i < argc; i++) - args.push_back(argv[i]); - - parse(args); + parse(args); } -inline void CmdLine::parse(std::vector& args) -{ - bool shouldExit = false; - int estat = 0; - - try { - _progName = args.front(); - args.erase(args.begin()); - - int requiredCount = 0; - - for (int i = 0; static_cast(i) < args.size(); i++) - { - bool matched = false; - for (ArgListIterator it = _argList.begin(); - it != _argList.end(); it++) { - if ( (*it)->processArg( &i, args ) ) - { - requiredCount += _xorHandler.check( *it ); - matched = true; - break; - } - } - - // checks to see if the argument is an empty combined - // switch and if so, then we've actually matched it - if ( !matched && _emptyCombined( args[i] ) ) - matched = true; - - if ( !matched && !Arg::ignoreRest() ) - throw(CmdLineParseException("Couldn't find match " - "for argument", - args[i])); - } - - if ( requiredCount < _numRequired ) - missingArgsException(); - - if ( requiredCount > _numRequired ) - throw(CmdLineParseException("Too many arguments!")); - - } catch ( ArgException& e ) { - // If we're not handling the exceptions, rethrow. - if ( !_handleExceptions) { - throw; - } - - try { - _output->failure(*this,e); - } catch ( ExitException &ee ) { - estat = ee.getExitStatus(); - shouldExit = true; - } - } catch (ExitException &ee) { - // If we're not handling the exceptions, rethrow. - if ( !_handleExceptions) { - throw; - } - - estat = ee.getExitStatus(); - shouldExit = true; - } - - if (shouldExit) - exit(estat); +inline void CmdLine::parse(std::vector &args) { + bool shouldExit = false; + int estat = 0; + + try { + _progName = args.front(); + args.erase(args.begin()); + + int requiredCount = 0; + + for (int i = 0; static_cast(i) < args.size(); i++) { + bool matched = false; + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) { + if ((*it)->processArg(&i, args)) { + requiredCount += _xorHandler.check(*it); + matched = true; + break; + } + } + + // checks to see if the argument is an empty combined + // switch and if so, then we've actually matched it + if (!matched && _emptyCombined(args[i])) + matched = true; + + if (!matched && !Arg::ignoreRest()) + throw(CmdLineParseException("Couldn't find match " + "for argument", + args[i])); + } + + if (requiredCount < _numRequired) + missingArgsException(); + + if (requiredCount > _numRequired) + throw(CmdLineParseException("Too many arguments!")); + + } catch (ArgException &e) { + // If we're not handling the exceptions, rethrow. + if (!_handleExceptions) { + throw; + } + + try { + _output->failure(*this, e); + } catch (ExitException &ee) { + estat = ee.getExitStatus(); + shouldExit = true; + } + } catch (ExitException &ee) { + // If we're not handling the exceptions, rethrow. + if (!_handleExceptions) { + throw; + } + + estat = ee.getExitStatus(); + shouldExit = true; + } + + if (shouldExit) + exit(estat); } -inline bool CmdLine::_emptyCombined(const std::string& s) -{ - if ( s.length() > 0 && s[0] != Arg::flagStartChar() ) - return false; +inline bool CmdLine::_emptyCombined(const std::string &s) { + if (s.length() > 0 && s[0] != Arg::flagStartChar()) + return false; - for ( int i = 1; static_cast(i) < s.length(); i++ ) - if ( s[i] != Arg::blankChar() ) - return false; + for (int i = 1; static_cast(i) < s.length(); i++) + if (s[i] != Arg::blankChar()) + return false; - return true; + return true; } -inline void CmdLine::missingArgsException() -{ - int count = 0; - - std::string missingArgList; - for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) - { - if ( (*it)->isRequired() && !(*it)->isSet() ) - { - missingArgList += (*it)->getName(); - missingArgList += ", "; - count++; - } - } - missingArgList = missingArgList.substr(0,missingArgList.length()-2); - - std::string msg; - if ( count > 1 ) - msg = "Required arguments missing: "; - else - msg = "Required argument missing: "; - - msg += missingArgList; - - throw(CmdLineParseException(msg)); -} +inline void CmdLine::missingArgsException() { + int count = 0; -inline void CmdLine::deleteOnExit(Arg* ptr) -{ - _argDeleteOnExitList.push_back(ptr); -} + std::string missingArgList; + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) { + if ((*it)->isRequired() && !(*it)->isSet()) { + missingArgList += (*it)->getName(); + missingArgList += ", "; + count++; + } + } + missingArgList = missingArgList.substr(0, missingArgList.length() - 2); -inline void CmdLine::deleteOnExit(Visitor* ptr) -{ - _visitorDeleteOnExitList.push_back(ptr); -} + std::string msg; + if (count > 1) + msg = "Required arguments missing: "; + else + msg = "Required argument missing: "; -inline CmdLineOutput* CmdLine::getOutput() -{ - return _output; -} + msg += missingArgList; -inline void CmdLine::setOutput(CmdLineOutput* co) -{ - if ( !_userSetOutput ) - delete _output; - _userSetOutput = true; - _output = co; + throw(CmdLineParseException(msg)); } -inline std::string& CmdLine::getVersion() -{ - return _version; +inline void CmdLine::deleteOnExit(Arg *ptr) { + _argDeleteOnExitList.push_back(ptr); } -inline std::string& CmdLine::getProgramName() -{ - return _progName; +inline void CmdLine::deleteOnExit(Visitor *ptr) { + _visitorDeleteOnExitList.push_back(ptr); } -inline std::list& CmdLine::getArgList() -{ - return _argList; -} +inline CmdLineOutput *CmdLine::getOutput() { return _output; } -inline XorHandler& CmdLine::getXorHandler() -{ - return _xorHandler; +inline void CmdLine::setOutput(CmdLineOutput *co) { + if (!_userSetOutput) + delete _output; + _userSetOutput = true; + _output = co; } -inline char CmdLine::getDelimiter() -{ - return _delimiter; -} +inline std::string &CmdLine::getVersion() { return _version; } -inline std::string& CmdLine::getMessage() -{ - return _message; -} +inline std::string &CmdLine::getProgramName() { return _progName; } -inline bool CmdLine::hasHelpAndVersion() -{ - return _helpAndVersion; -} +inline std::list &CmdLine::getArgList() { return _argList; } -inline void CmdLine::setExceptionHandling(const bool state) -{ - _handleExceptions = state; -} +inline XorHandler &CmdLine::getXorHandler() { return _xorHandler; } + +inline char CmdLine::getDelimiter() { return _delimiter; } + +inline std::string &CmdLine::getMessage() { return _message; } -inline bool CmdLine::getExceptionHandling() const -{ - return _handleExceptions; +inline bool CmdLine::hasHelpAndVersion() { return _helpAndVersion; } + +inline void CmdLine::setExceptionHandling(const bool state) { + _handleExceptions = state; } -inline void CmdLine::reset() -{ - for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) - (*it)->reset(); - - _progName.clear(); +inline bool CmdLine::getExceptionHandling() const { return _handleExceptions; } + +inline void CmdLine::reset() { + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) + (*it)->reset(); + + _progName.clear(); } /////////////////////////////////////////////////////////////////////////////// -//End CmdLine.cpp +// End CmdLine.cpp /////////////////////////////////////////////////////////////////////////////// - - -} //namespace TCLAP +} // namespace TCLAP #endif diff --git a/external/tclap/CmdLineInterface.h b/external/tclap/CmdLineInterface.h index 1b25e9b..9ead83a 100644 --- a/external/tclap/CmdLineInterface.h +++ b/external/tclap/CmdLineInterface.h @@ -1,37 +1,36 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: CmdLineInterface.h - * + * * Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * All rights reverved. * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_COMMANDLINE_INTERFACE_H #define TCLAP_COMMANDLINE_INTERFACE_H +#include +#include +#include #include #include -#include -#include -#include - namespace TCLAP { - + class Arg; class CmdLineOutput; class XorHandler; @@ -40,111 +39,108 @@ class XorHandler; * The base class that manages the command line definition and passes * along the parsing to the appropriate Arg classes. */ -class CmdLineInterface -{ - public: - - /** - * Destructor - */ - virtual ~CmdLineInterface() {} - - /** - * Adds an argument to the list of arguments to be parsed. - * \param a - Argument to be added. - */ - virtual void add( Arg& a )=0; - - /** - * An alternative add. Functionally identical. - * \param a - Argument to be added. - */ - virtual void add( Arg* a )=0; - - /** - * Add two Args that will be xor'd. - * If this method is used, add does - * not need to be called. - * \param a - Argument to be added and xor'd. - * \param b - Argument to be added and xor'd. - */ - virtual void xorAdd( Arg& a, Arg& b )=0; - - /** - * Add a list of Args that will be xor'd. If this method is used, - * add does not need to be called. - * \param xors - List of Args to be added and xor'd. - */ - virtual void xorAdd( std::vector& xors )=0; - - /** - * Parses the command line. - * \param argc - Number of arguments. - * \param argv - Array of arguments. - */ - virtual void parse(int argc, const char * const * argv)=0; - - /** - * Parses the command line. - * \param args - A vector of strings representing the args. - * args[0] is still the program name. - */ - void parse(std::vector& args); - - /** - * Returns the CmdLineOutput object. - */ - virtual CmdLineOutput* getOutput()=0; - - /** - * \param co - CmdLineOutput object that we want to use instead. - */ - virtual void setOutput(CmdLineOutput* co)=0; - - /** - * Returns the version string. - */ - virtual std::string& getVersion()=0; - - /** - * Returns the program name string. - */ - virtual std::string& getProgramName()=0; - - /** - * Returns the argList. - */ - virtual std::list& getArgList()=0; - - /** - * Returns the XorHandler. - */ - virtual XorHandler& getXorHandler()=0; - - /** - * Returns the delimiter string. - */ - virtual char getDelimiter()=0; - - /** - * Returns the message string. - */ - virtual std::string& getMessage()=0; - - /** - * Indicates whether or not the help and version switches were created - * automatically. - */ - virtual bool hasHelpAndVersion()=0; - - /** - * Resets the instance as if it had just been constructed so that the - * instance can be reused. - */ - virtual void reset()=0; +class CmdLineInterface { +public: + /** + * Destructor + */ + virtual ~CmdLineInterface() {} + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + virtual void add(Arg &a) = 0; + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + virtual void add(Arg *a) = 0; + + /** + * Add two Args that will be xor'd. + * If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + virtual void xorAdd(Arg &a, Arg &b) = 0; + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + virtual void xorAdd(std::vector &xors) = 0; + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + virtual void parse(int argc, const char *const *argv) = 0; + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector &args); + + /** + * Returns the CmdLineOutput object. + */ + virtual CmdLineOutput *getOutput() = 0; + + /** + * \param co - CmdLineOutput object that we want to use instead. + */ + virtual void setOutput(CmdLineOutput *co) = 0; + + /** + * Returns the version string. + */ + virtual std::string &getVersion() = 0; + + /** + * Returns the program name string. + */ + virtual std::string &getProgramName() = 0; + + /** + * Returns the argList. + */ + virtual std::list &getArgList() = 0; + + /** + * Returns the XorHandler. + */ + virtual XorHandler &getXorHandler() = 0; + + /** + * Returns the delimiter string. + */ + virtual char getDelimiter() = 0; + + /** + * Returns the message string. + */ + virtual std::string &getMessage() = 0; + + /** + * Indicates whether or not the help and version switches were created + * automatically. + */ + virtual bool hasHelpAndVersion() = 0; + + /** + * Resets the instance as if it had just been constructed so that the + * instance can be reused. + */ + virtual void reset() = 0; }; -} //namespace - +} // namespace TCLAP -#endif +#endif diff --git a/external/tclap/CmdLineOutput.h b/external/tclap/CmdLineOutput.h index 71ee5a3..d92a420 100644 --- a/external/tclap/CmdLineOutput.h +++ b/external/tclap/CmdLineOutput.h @@ -1,34 +1,34 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: CmdLineOutput.h - * + * * Copyright (c) 2004, Michael E. Smoot * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_CMDLINEOUTPUT_H #define TCLAP_CMDLINEOUTPUT_H +#include +#include +#include +#include #include #include -#include -#include -#include -#include namespace TCLAP { @@ -38,37 +38,33 @@ class ArgException; /** * The interface that any output object must implement. */ -class CmdLineOutput -{ - - public: - - /** - * Virtual destructor. - */ - virtual ~CmdLineOutput() {} +class CmdLineOutput { - /** - * Generates some sort of output for the USAGE. - * \param c - The CmdLine object the output is generated for. - */ - virtual void usage(CmdLineInterface& c)=0; +public: + /** + * Virtual destructor. + */ + virtual ~CmdLineOutput() {} - /** - * Generates some sort of output for the version. - * \param c - The CmdLine object the output is generated for. - */ - virtual void version(CmdLineInterface& c)=0; + /** + * Generates some sort of output for the USAGE. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface &c) = 0; - /** - * Generates some sort of output for a failure. - * \param c - The CmdLine object the output is generated for. - * \param e - The ArgException that caused the failure. - */ - virtual void failure( CmdLineInterface& c, - ArgException& e )=0; + /** + * Generates some sort of output for the version. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface &c) = 0; + /** + * Generates some sort of output for a failure. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface &c, ArgException &e) = 0; }; -} //namespace TCLAP -#endif +} // namespace TCLAP +#endif diff --git a/external/tclap/Constraint.h b/external/tclap/Constraint.h index a92acf9..cc6df16 100644 --- a/external/tclap/Constraint.h +++ b/external/tclap/Constraint.h @@ -22,47 +22,45 @@ #ifndef TCLAP_CONSTRAINT_H #define TCLAP_CONSTRAINT_H +#include +#include +#include +#include #include #include -#include -#include -#include -#include namespace TCLAP { /** * The interface that defines the interaction between the Arg and Constraint. */ -template -class Constraint -{ +template class Constraint { - public: - /** - * Returns a description of the Constraint. - */ - virtual std::string description() const =0; +public: + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const = 0; - /** - * Returns the short ID for the Constraint. - */ - virtual std::string shortID() const =0; + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const = 0; - /** - * The method used to verify that the value parsed from the command - * line meets the constraint. - * \param value - The value that will be checked. - */ - virtual bool check(const T& value) const =0; + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T &value) const = 0; - /** - * Destructor. - * Silences warnings about Constraint being a base class with virtual - * functions but without a virtual destructor. - */ - virtual ~Constraint() { ; } + /** + * Destructor. + * Silences warnings about Constraint being a base class with virtual + * functions but without a virtual destructor. + */ + virtual ~Constraint() { ; } }; -} //namespace TCLAP +} // namespace TCLAP #endif diff --git a/external/tclap/DocBookOutput.h b/external/tclap/DocBookOutput.h index a42ca27..a4d8acc 100644 --- a/external/tclap/DocBookOutput.h +++ b/external/tclap/DocBookOutput.h @@ -1,299 +1,279 @@ // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- -/****************************************************************************** - * +/****************************************************************************** + * * file: DocBookOutput.h - * + * * Copyright (c) 2004, Michael E. Smoot * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_DOCBOOKOUTPUT_H #define TCLAP_DOCBOOKOUTPUT_H +#include +#include +#include #include #include -#include -#include -#include +#include #include #include #include -#include namespace TCLAP { /** - * A class that generates DocBook output for usage() method for the + * A class that generates DocBook output for usage() method for the * given CmdLine and its Args. */ -class DocBookOutput : public CmdLineOutput -{ - - public: - - /** - * Prints the usage to stdout. Can be overridden to - * produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - */ - virtual void usage(CmdLineInterface& c); - - /** - * Prints the version to stdout. Can be overridden - * to produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - */ - virtual void version(CmdLineInterface& c); - - /** - * Prints (to stderr) an error message, short usage - * Can be overridden to produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - * \param e - The ArgException that caused the failure. - */ - virtual void failure(CmdLineInterface& c, - ArgException& e ); - - protected: - - /** - * Substitutes the char r for string x in string s. - * \param s - The string to operate on. - * \param r - The char to replace. - * \param x - What to replace r with. - */ - void substituteSpecialChars( std::string& s, char r, std::string& x ); - void removeChar( std::string& s, char r); - void basename( std::string& s ); - - void printShortArg(Arg* it); - void printLongArg(Arg* it); - - char theDelimiter; +class DocBookOutput : public CmdLineOutput { + +public: + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface &c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface &c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface &c, ArgException &e); + +protected: + /** + * Substitutes the char r for string x in string s. + * \param s - The string to operate on. + * \param r - The char to replace. + * \param x - What to replace r with. + */ + void substituteSpecialChars(std::string &s, char r, std::string &x); + void removeChar(std::string &s, char r); + void basename(std::string &s); + + void printShortArg(Arg *it); + void printLongArg(Arg *it); + + char theDelimiter; }; - -inline void DocBookOutput::version(CmdLineInterface& _cmd) -{ - std::cout << _cmd.getVersion() << std::endl; +inline void DocBookOutput::version(CmdLineInterface &_cmd) { + std::cout << _cmd.getVersion() << std::endl; } -inline void DocBookOutput::usage(CmdLineInterface& _cmd ) -{ - std::list argList = _cmd.getArgList(); - std::string progName = _cmd.getProgramName(); - std::string xversion = _cmd.getVersion(); - theDelimiter = _cmd.getDelimiter(); - XorHandler xorHandler = _cmd.getXorHandler(); - std::vector< std::vector > xorList = xorHandler.getXorList(); - basename(progName); - - std::cout << "" << std::endl; - std::cout << "" << std::endl << std::endl; - - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - std::cout << "" << progName << "" << std::endl; - std::cout << "1" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - std::cout << "" << progName << "" << std::endl; - std::cout << "" << _cmd.getMessage() << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << progName << "" << std::endl; - - // xor - for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) - { - std::cout << "" << std::endl; - for ( ArgVectorIterator it = xorList[i].begin(); - it != xorList[i].end(); it++ ) - printShortArg((*it)); - - std::cout << "" << std::endl; - } - - // rest of args - for (ArgListIterator it = argList.begin(); it != argList.end(); it++) - if ( !xorHandler.contains( (*it) ) ) - printShortArg((*it)); - - std::cout << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - std::cout << "Description" << std::endl; - std::cout << "" << std::endl; - std::cout << _cmd.getMessage() << std::endl; - std::cout << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - std::cout << "Options" << std::endl; - - std::cout << "" << std::endl; - - for (ArgListIterator it = argList.begin(); it != argList.end(); it++) - printLongArg((*it)); - - std::cout << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - std::cout << "Version" << std::endl; - std::cout << "" << std::endl; - std::cout << xversion << std::endl; - std::cout << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - +inline void DocBookOutput::usage(CmdLineInterface &_cmd) { + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector> xorList = xorHandler.getXorList(); + basename(progName); + + std::cout << "" << std::endl; + std::cout + << "" + << std::endl + << std::endl; + + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << progName << "" << std::endl; + std::cout << "1" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << progName << "" << std::endl; + std::cout << "" << _cmd.getMessage() << "" + << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << progName << "" << std::endl; + + // xor + for (int i = 0; (unsigned int)i < xorList.size(); i++) { + std::cout << "" << std::endl; + for (ArgVectorIterator it = xorList[i].begin(); it != xorList[i].end(); + it++) + printShortArg((*it)); + + std::cout << "" << std::endl; + } + + // rest of args + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if (!xorHandler.contains((*it))) + printShortArg((*it)); + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Description" << std::endl; + std::cout << "" << std::endl; + std::cout << _cmd.getMessage() << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Options" << std::endl; + + std::cout << "" << std::endl; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + printLongArg((*it)); + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Version" << std::endl; + std::cout << "" << std::endl; + std::cout << xversion << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; } -inline void DocBookOutput::failure( CmdLineInterface& _cmd, - ArgException& e ) -{ - static_cast(_cmd); // unused - std::cout << e.what() << std::endl; - throw ExitException(1); +inline void DocBookOutput::failure(CmdLineInterface &_cmd, ArgException &e) { + static_cast(_cmd); // unused + std::cout << e.what() << std::endl; + throw ExitException(1); } -inline void DocBookOutput::substituteSpecialChars( std::string& s, - char r, - std::string& x ) -{ - size_t p; - while ( (p = s.find_first_of(r)) != std::string::npos ) - { - s.erase(p,1); - s.insert(p,x); - } +inline void DocBookOutput::substituteSpecialChars(std::string &s, char r, + std::string &x) { + size_t p; + while ((p = s.find_first_of(r)) != std::string::npos) { + s.erase(p, 1); + s.insert(p, x); + } } -inline void DocBookOutput::removeChar( std::string& s, char r) -{ - size_t p; - while ( (p = s.find_first_of(r)) != std::string::npos ) - { - s.erase(p,1); - } +inline void DocBookOutput::removeChar(std::string &s, char r) { + size_t p; + while ((p = s.find_first_of(r)) != std::string::npos) { + s.erase(p, 1); + } } -inline void DocBookOutput::basename( std::string& s ) -{ - size_t p = s.find_last_of('/'); - if ( p != std::string::npos ) - { - s.erase(0, p + 1); - } +inline void DocBookOutput::basename(std::string &s) { + size_t p = s.find_last_of('/'); + if (p != std::string::npos) { + s.erase(0, p + 1); + } } -inline void DocBookOutput::printShortArg(Arg* a) -{ - std::string lt = "<"; - std::string gt = ">"; - - std::string id = a->shortID(); - substituteSpecialChars(id,'<',lt); - substituteSpecialChars(id,'>',gt); - removeChar(id,'['); - removeChar(id,']'); - - std::string choice = "opt"; - if ( a->isRequired() ) - choice = "plain"; - - std::cout << "acceptsMultipleValues() ) - std::cout << " rep='repeat'"; - - - std::cout << '>'; - if ( !a->getFlag().empty() ) - std::cout << a->flagStartChar() << a->getFlag(); - else - std::cout << a->nameStartString() << a->getName(); - if ( a->isValueRequired() ) - { - std::string arg = a->shortID(); - removeChar(arg,'['); - removeChar(arg,']'); - removeChar(arg,'<'); - removeChar(arg,'>'); - arg.erase(0, arg.find_last_of(theDelimiter) + 1); - std::cout << theDelimiter; - std::cout << "" << arg << ""; - } - std::cout << "" << std::endl; - +inline void DocBookOutput::printShortArg(Arg *a) { + std::string lt = "<"; + std::string gt = ">"; + + std::string id = a->shortID(); + substituteSpecialChars(id, '<', lt); + substituteSpecialChars(id, '>', gt); + removeChar(id, '['); + removeChar(id, ']'); + + std::string choice = "opt"; + if (a->isRequired()) + choice = "plain"; + + std::cout << "acceptsMultipleValues()) + std::cout << " rep='repeat'"; + + std::cout << '>'; + if (!a->getFlag().empty()) + std::cout << a->flagStartChar() << a->getFlag(); + else + std::cout << a->nameStartString() << a->getName(); + if (a->isValueRequired()) { + std::string arg = a->shortID(); + removeChar(arg, '['); + removeChar(arg, ']'); + removeChar(arg, '<'); + removeChar(arg, '>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "" << arg << ""; + } + std::cout << "" << std::endl; } -inline void DocBookOutput::printLongArg(Arg* a) -{ - std::string lt = "<"; - std::string gt = ">"; - - std::string desc = a->getDescription(); - substituteSpecialChars(desc,'<',lt); - substituteSpecialChars(desc,'>',gt); - - std::cout << "" << std::endl; - - if ( !a->getFlag().empty() ) - { - std::cout << "" << std::endl; - std::cout << "" << std::endl; - std::cout << "" << std::endl; - } - - std::cout << "" << std::endl; - std::cout << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; - std::cout << "" << std::endl; - std::cout << desc << std::endl; - std::cout << "" << std::endl; - std::cout << "" << std::endl; - - std::cout << "" << std::endl; +inline void DocBookOutput::printLongArg(Arg *a) { + std::string lt = "<"; + std::string gt = ">"; + + std::string desc = a->getDescription(); + substituteSpecialChars(desc, '<', lt); + substituteSpecialChars(desc, '>', gt); + + std::cout << "" << std::endl; + + if (!a->getFlag().empty()) { + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + } + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << desc << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; } -} //namespace TCLAP -#endif +} // namespace TCLAP +#endif diff --git a/external/tclap/HelpVisitor.h b/external/tclap/HelpVisitor.h index cc3bd07..f787a0f 100644 --- a/external/tclap/HelpVisitor.h +++ b/external/tclap/HelpVisitor.h @@ -1,23 +1,23 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: HelpVisitor.h - * + * * Copyright (c) 2003, Michael E. Smoot . * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_HELP_VISITOR_H #define TCLAP_HELP_VISITOR_H @@ -32,45 +32,44 @@ namespace TCLAP { * A Visitor object that calls the usage method of the given CmdLineOutput * object for the specified CmdLine object. */ -class HelpVisitor: public Visitor -{ - private: - /** - * Prevent accidental copying. - */ - HelpVisitor(const HelpVisitor& rhs); - HelpVisitor& operator=(const HelpVisitor& rhs); +class HelpVisitor : public Visitor { +private: + /** + * Prevent accidental copying. + */ + HelpVisitor(const HelpVisitor &rhs); + HelpVisitor &operator=(const HelpVisitor &rhs); - protected: +protected: + /** + * The CmdLine the output will be generated for. + */ + CmdLineInterface *_cmd; - /** - * The CmdLine the output will be generated for. - */ - CmdLineInterface* _cmd; + /** + * The output object. + */ + CmdLineOutput **_out; - /** - * The output object. - */ - CmdLineOutput** _out; +public: + /** + * Constructor. + * \param cmd - The CmdLine the output will be generated for. + * \param out - The type of output. + */ + HelpVisitor(CmdLineInterface *cmd, CmdLineOutput **out) + : Visitor(), _cmd(cmd), _out(out) {} - public: - - /** - * Constructor. - * \param cmd - The CmdLine the output will be generated for. - * \param out - The type of output. - */ - HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) - : Visitor(), _cmd( cmd ), _out( out ) { } - - /** - * Calls the usage method of the CmdLineOutput for the - * specified CmdLine. - */ - void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } - + /** + * Calls the usage method of the CmdLineOutput for the + * specified CmdLine. + */ + void visit() { + (*_out)->usage(*_cmd); + throw ExitException(0); + } }; -} +} // namespace TCLAP #endif diff --git a/external/tclap/IgnoreRestVisitor.h b/external/tclap/IgnoreRestVisitor.h index e328649..47d6ab3 100644 --- a/external/tclap/IgnoreRestVisitor.h +++ b/external/tclap/IgnoreRestVisitor.h @@ -1,30 +1,29 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: IgnoreRestVisitor.h - * + * * Copyright (c) 2003, Michael E. Smoot . * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_IGNORE_REST_VISITOR_H #define TCLAP_IGNORE_REST_VISITOR_H -#include #include +#include namespace TCLAP { @@ -32,21 +31,19 @@ namespace TCLAP { * A Vistor that tells the CmdLine to begin ignoring arguments after * this one is parsed. */ -class IgnoreRestVisitor: public Visitor -{ - public: - - /** - * Constructor. - */ - IgnoreRestVisitor() : Visitor() {} - - /** - * Sets Arg::_ignoreRest. - */ - void visit() { Arg::beginIgnoring(); } +class IgnoreRestVisitor : public Visitor { +public: + /** + * Constructor. + */ + IgnoreRestVisitor() : Visitor() {} + + /** + * Sets Arg::_ignoreRest. + */ + void visit() { Arg::beginIgnoring(); } }; -} +} // namespace TCLAP #endif diff --git a/external/tclap/MultiArg.h b/external/tclap/MultiArg.h index 34bb2d7..754354e 100644 --- a/external/tclap/MultiArg.h +++ b/external/tclap/MultiArg.h @@ -1,25 +1,24 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: MultiArg.h - * + * * Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * *****************************************************************************/ - #ifndef TCLAP_MULTIPLE_ARGUMENT_H #define TCLAP_MULTIPLE_ARGUMENT_H @@ -35,397 +34,334 @@ namespace TCLAP { * similar to a ValueArg, except a vector of values will be returned * instead of just one. */ -template -class MultiArg : public Arg -{ +template class MultiArg : public Arg { public: - typedef std::vector container_type; - typedef typename container_type::iterator iterator; - typedef typename container_type::const_iterator const_iterator; + typedef std::vector container_type; + typedef typename container_type::iterator iterator; + typedef typename container_type::const_iterator const_iterator; protected: - - /** - * The list of values parsed from the CmdLine. - */ - std::vector _values; - - /** - * The description of type T to be used in the usage. - */ - std::string _typeDesc; - - /** - * A list of constraint on this Arg. - */ - Constraint* _constraint; - - /** - * Extracts the value from the string. - * Attempts to parse string as type T, if this fails an exception - * is thrown. - * \param val - The string to be read. - */ - void _extractValue( const std::string& val ); - - /** - * Used by XorHandler to decide whether to keep parsing for this arg. - */ - bool _allowMore; + /** + * The list of values parsed from the CmdLine. + */ + std::vector _values; + + /** + * The description of type T to be used in the usage. + */ + std::string _typeDesc; + + /** + * A list of constraint on this Arg. + */ + Constraint *_constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - The string to be read. + */ + void _extractValue(const std::string &val); + + /** + * Used by XorHandler to decide whether to keep parsing for this arg. + */ + bool _allowMore; public: - - /** - * Constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - MultiArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - Visitor* v = NULL); - - /** - * Constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param parser - A CmdLine parser object to add this Arg to - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - MultiArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - CmdLineInterface& parser, - Visitor* v = NULL ); - - /** - * Constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - MultiArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - Visitor* v = NULL ); - - /** - * Constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param parser - A CmdLine parser object to add this Arg to - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - MultiArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - CmdLineInterface& parser, - Visitor* v = NULL ); - - /** - * Handles the processing of the argument. - * This re-implements the Arg version of this method to set the - * _value of the argument appropriately. It knows the difference - * between labeled and unlabeled. - * \param i - Pointer the the current argument in the list. - * \param args - Mutable list of strings. Passed from main(). - */ - virtual bool processArg(int* i, std::vector& args); - - /** - * Returns a vector of type T containing the values parsed from - * the command line. - */ - const std::vector& getValue(); - - /** - * Returns an iterator over the values parsed from the command - * line. - */ - const_iterator begin() const { return _values.begin(); } - - /** - * Returns the end of the values parsed from the command - * line. - */ - const_iterator end() const { return _values.end(); } - - /** - * Returns the a short id string. Used in the usage. - * \param val - value to be used. - */ - virtual std::string shortID(const std::string& val="val") const; - - /** - * Returns the a long id string. Used in the usage. - * \param val - value to be used. - */ - virtual std::string longID(const std::string& val="val") const; - - /** - * Once we've matched the first value, then the arg is no longer - * required. - */ - virtual bool isRequired() const; - - virtual bool allowMore(); - - virtual void reset(); + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, const std::string &typeDesc, + Visitor *v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, const std::string &typeDesc, + CmdLineInterface &parser, Visitor *v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, Constraint *constraint, + Visitor *v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, Constraint *constraint, + CmdLineInterface &parser, Visitor *v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int *i, std::vector &args); + + /** + * Returns a vector of type T containing the values parsed from + * the command line. + */ + const std::vector &getValue(); + + /** + * Returns an iterator over the values parsed from the command + * line. + */ + const_iterator begin() const { return _values.begin(); } + + /** + * Returns the end of the values parsed from the command + * line. + */ + const_iterator end() const { return _values.end(); } + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string &val = "val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string &val = "val") const; + + /** + * Once we've matched the first value, then the arg is no longer + * required. + */ + virtual bool isRequired() const; + + virtual bool allowMore(); + + virtual void reset(); private: - /** - * Prevent accidental copying - */ - MultiArg(const MultiArg& rhs); - MultiArg& operator=(const MultiArg& rhs); - + /** + * Prevent accidental copying + */ + MultiArg(const MultiArg &rhs); + MultiArg &operator=(const MultiArg &rhs); }; -template -MultiArg::MultiArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - Visitor* v) : - Arg( flag, name, desc, req, true, v ), - _values(std::vector()), - _typeDesc( typeDesc ), - _constraint( NULL ), - _allowMore(false) -{ - _acceptsMultipleValues = true; +template +MultiArg::MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, + const std::string &typeDesc, Visitor *v) + : Arg(flag, name, desc, req, true, v), _values(std::vector()), + _typeDesc(typeDesc), _constraint(NULL), _allowMore(false) { + _acceptsMultipleValues = true; } -template -MultiArg::MultiArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - CmdLineInterface& parser, - Visitor* v) -: Arg( flag, name, desc, req, true, v ), - _values(std::vector()), - _typeDesc( typeDesc ), - _constraint( NULL ), - _allowMore(false) -{ - parser.add( this ); - _acceptsMultipleValues = true; +template +MultiArg::MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, + const std::string &typeDesc, CmdLineInterface &parser, + Visitor *v) + : Arg(flag, name, desc, req, true, v), _values(std::vector()), + _typeDesc(typeDesc), _constraint(NULL), _allowMore(false) { + parser.add(this); + _acceptsMultipleValues = true; } /** * */ -template -MultiArg::MultiArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - Visitor* v) -: Arg( flag, name, desc, req, true, v ), - _values(std::vector()), - _typeDesc( constraint->shortID() ), - _constraint( constraint ), - _allowMore(false) -{ - _acceptsMultipleValues = true; +template +MultiArg::MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, + Constraint *constraint, Visitor *v) + : Arg(flag, name, desc, req, true, v), _values(std::vector()), + _typeDesc(constraint->shortID()), _constraint(constraint), + _allowMore(false) { + _acceptsMultipleValues = true; +} + +template +MultiArg::MultiArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, + Constraint *constraint, CmdLineInterface &parser, + Visitor *v) + : Arg(flag, name, desc, req, true, v), _values(std::vector()), + _typeDesc(constraint->shortID()), _constraint(constraint), + _allowMore(false) { + parser.add(this); + _acceptsMultipleValues = true; } -template -MultiArg::MultiArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - CmdLineInterface& parser, - Visitor* v) -: Arg( flag, name, desc, req, true, v ), - _values(std::vector()), - _typeDesc( constraint->shortID() ), - _constraint( constraint ), - _allowMore(false) -{ - parser.add( this ); - _acceptsMultipleValues = true; +template const std::vector &MultiArg::getValue() { + return _values; } -template -const std::vector& MultiArg::getValue() { return _values; } - -template -bool MultiArg::processArg(int *i, std::vector& args) -{ - if ( _ignoreable && Arg::ignoreRest() ) - return false; - - if ( _hasBlanks( args[*i] ) ) - return false; - - std::string flag = args[*i]; - std::string value = ""; - - trimFlag( flag, value ); - - if ( argMatches( flag ) ) - { - if ( Arg::delimiter() != ' ' && value == "" ) - throw( ArgParseException( - "Couldn't find delimiter for this argument!", - toString() ) ); - - // always take the first one, regardless of start string - if ( value == "" ) - { - (*i)++; - if ( static_cast(*i) < args.size() ) - _extractValue( args[*i] ); - else - throw( ArgParseException("Missing a value for this argument!", - toString() ) ); - } - else - _extractValue( value ); - - /* - // continuing taking the args until we hit one with a start string - while ( (unsigned int)(*i)+1 < args.size() && - args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && - args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) - _extractValue( args[++(*i)] ); - */ - - _alreadySet = true; - _checkWithVisitor(); - - return true; - } - else - return false; +template +bool MultiArg::processArg(int *i, std::vector &args) { + if (_ignoreable && Arg::ignoreRest()) + return false; + + if (_hasBlanks(args[*i])) + return false; + + std::string flag = args[*i]; + std::string value = ""; + + trimFlag(flag, value); + + if (argMatches(flag)) { + if (Arg::delimiter() != ' ' && value == "") + throw(ArgParseException("Couldn't find delimiter for this argument!", + toString())); + + // always take the first one, regardless of start string + if (value == "") { + (*i)++; + if (static_cast(*i) < args.size()) + _extractValue(args[*i]); + else + throw(ArgParseException("Missing a value for this argument!", + toString())); + } else + _extractValue(value); + + /* + // continuing taking the args until we hit one with a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + _checkWithVisitor(); + + return true; + } else + return false; } /** * */ -template -std::string MultiArg::shortID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - return Arg::shortID(_typeDesc) + " ... "; +template +std::string MultiArg::shortID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + return Arg::shortID(_typeDesc) + " ... "; } /** * */ -template -std::string MultiArg::longID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - return Arg::longID(_typeDesc) + " (accepted multiple times)"; +template +std::string MultiArg::longID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + return Arg::longID(_typeDesc) + " (accepted multiple times)"; } /** * Once we've matched the first value, then the arg is no longer * required. */ -template -bool MultiArg::isRequired() const -{ - if ( _required ) - { - if ( _values.size() > 1 ) - return false; - else - return true; - } - else - return false; - +template bool MultiArg::isRequired() const { + if (_required) { + if (_values.size() > 1) + return false; + else + return true; + } else + return false; } -template -void MultiArg::_extractValue( const std::string& val ) -{ - try { - T tmp; - ExtractValue(tmp, val, typename ArgTraits::ValueCategory()); - _values.push_back(tmp); - } catch( ArgParseException &e) { - throw ArgParseException(e.error(), toString()); - } - - if ( _constraint != NULL ) - if ( ! _constraint->check( _values.back() ) ) - throw( CmdLineParseException( "Value '" + val + - "' does not meet constraint: " + - _constraint->description(), - toString() ) ); +template void MultiArg::_extractValue(const std::string &val) { + try { + T tmp; + ExtractValue(tmp, val, typename ArgTraits::ValueCategory()); + _values.push_back(tmp); + } catch (ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if (_constraint != NULL) + if (!_constraint->check(_values.back())) + throw(CmdLineParseException( + "Value '" + val + + "' does not meet constraint: " + _constraint->description(), + toString())); } - -template -bool MultiArg::allowMore() -{ - bool am = _allowMore; - _allowMore = true; - return am; + +template bool MultiArg::allowMore() { + bool am = _allowMore; + _allowMore = true; + return am; } -template -void MultiArg::reset() -{ - Arg::reset(); - _values.clear(); +template void MultiArg::reset() { + Arg::reset(); + _values.clear(); } } // namespace TCLAP diff --git a/external/tclap/MultiSwitchArg.h b/external/tclap/MultiSwitchArg.h index 8820b64..751836d 100644 --- a/external/tclap/MultiSwitchArg.h +++ b/external/tclap/MultiSwitchArg.h @@ -1,26 +1,25 @@ -/****************************************************************************** -* -* file: MultiSwitchArg.h -* -* Copyright (c) 2003, Michael E. Smoot . -* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. -* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. -* All rights reverved. -* -* See the file COPYING in the top directory of this distribution for -* more information. -* -* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -* DEALINGS IN THE SOFTWARE. -* -*****************************************************************************/ - +/****************************************************************************** + * + * file: MultiSwitchArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_MULTI_SWITCH_ARG_H #define TCLAP_MULTI_SWITCH_ARG_H @@ -33,184 +32,153 @@ namespace TCLAP { /** -* A multiple switch argument. If the switch is set on the command line, then -* the getValue method will return the number of times the switch appears. -*/ -class MultiSwitchArg : public SwitchArg -{ - protected: - - /** - * The value of the switch. - */ - int _value; - - /** - * Used to support the reset() method so that ValueArg can be - * reset to their constructed value. - */ - int _default; - - public: - - /** - * MultiSwitchArg constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param init - Optional. The initial/default value of this Arg. - * Defaults to 0. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - MultiSwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - int init = 0, - Visitor* v = NULL); - - - /** - * MultiSwitchArg constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param parser - A CmdLine parser object to add this Arg to - * \param init - Optional. The initial/default value of this Arg. - * Defaults to 0. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - MultiSwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - CmdLineInterface& parser, - int init = 0, - Visitor* v = NULL); - - - /** - * Handles the processing of the argument. - * This re-implements the SwitchArg version of this method to set the - * _value of the argument appropriately. - * \param i - Pointer the the current argument in the list. - * \param args - Mutable list of strings. Passed - * in from main(). - */ - virtual bool processArg(int* i, std::vector& args); - - /** - * Returns int, the number of times the switch has been set. - */ - int getValue(); - - /** - * Returns the shortID for this Arg. - */ - std::string shortID(const std::string& val) const; - - /** - * Returns the longID for this Arg. - */ - std::string longID(const std::string& val) const; - - void reset(); - + * A multiple switch argument. If the switch is set on the command line, then + * the getValue method will return the number of times the switch appears. + */ +class MultiSwitchArg : public SwitchArg { +protected: + /** + * The value of the switch. + */ + int _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + int _default; + +public: + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string &flag, const std::string &name, + const std::string &desc, int init = 0, Visitor *v = NULL); + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string &flag, const std::string &name, + const std::string &desc, CmdLineInterface &parser, + int init = 0, Visitor *v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the SwitchArg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int *i, std::vector &args); + + /** + * Returns int, the number of times the switch has been set. + */ + int getValue(); + + /** + * Returns the shortID for this Arg. + */ + std::string shortID(const std::string &val) const; + + /** + * Returns the longID for this Arg. + */ + std::string longID(const std::string &val) const; + + void reset(); }; ////////////////////////////////////////////////////////////////////// -//BEGIN MultiSwitchArg.cpp +// BEGIN MultiSwitchArg.cpp ////////////////////////////////////////////////////////////////////// -inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - int init, - Visitor* v ) -: SwitchArg(flag, name, desc, false, v), -_value( init ), -_default( init ) -{ } - -inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - CmdLineInterface& parser, - int init, - Visitor* v ) -: SwitchArg(flag, name, desc, false, v), -_value( init ), -_default( init ) -{ - parser.add( this ); +inline MultiSwitchArg::MultiSwitchArg(const std::string &flag, + const std::string &name, + const std::string &desc, int init, + Visitor *v) + : SwitchArg(flag, name, desc, false, v), _value(init), _default(init) {} + +inline MultiSwitchArg::MultiSwitchArg(const std::string &flag, + const std::string &name, + const std::string &desc, + CmdLineInterface &parser, int init, + Visitor *v) + : SwitchArg(flag, name, desc, false, v), _value(init), _default(init) { + parser.add(this); } inline int MultiSwitchArg::getValue() { return _value; } -inline bool MultiSwitchArg::processArg(int *i, std::vector& args) -{ - if ( _ignoreable && Arg::ignoreRest() ) - return false; +inline bool MultiSwitchArg::processArg(int *i, std::vector &args) { + if (_ignoreable && Arg::ignoreRest()) + return false; - if ( argMatches( args[*i] )) - { - // so the isSet() method will work - _alreadySet = true; + if (argMatches(args[*i])) { + // so the isSet() method will work + _alreadySet = true; - // Matched argument: increment value. - ++_value; + // Matched argument: increment value. + ++_value; - _checkWithVisitor(); + _checkWithVisitor(); - return true; - } - else if ( combinedSwitchesMatch( args[*i] ) ) - { - // so the isSet() method will work - _alreadySet = true; + return true; + } else if (combinedSwitchesMatch(args[*i])) { + // so the isSet() method will work + _alreadySet = true; - // Matched argument: increment value. - ++_value; + // Matched argument: increment value. + ++_value; - // Check for more in argument and increment value. - while ( combinedSwitchesMatch( args[*i] ) ) - ++_value; + // Check for more in argument and increment value. + while (combinedSwitchesMatch(args[*i])) + ++_value; - _checkWithVisitor(); + _checkWithVisitor(); - return false; - } - else - return false; + return false; + } else + return false; } -inline std::string -MultiSwitchArg::shortID(const std::string& val) const -{ - return Arg::shortID(val) + " ... "; +inline std::string MultiSwitchArg::shortID(const std::string &val) const { + return Arg::shortID(val) + " ... "; } -inline std::string -MultiSwitchArg::longID(const std::string& val) const -{ - return Arg::longID(val) + " (accepted multiple times)"; +inline std::string MultiSwitchArg::longID(const std::string &val) const { + return Arg::longID(val) + " (accepted multiple times)"; } -inline void -MultiSwitchArg::reset() -{ - MultiSwitchArg::_value = MultiSwitchArg::_default; +inline void MultiSwitchArg::reset() { + MultiSwitchArg::_value = MultiSwitchArg::_default; } ////////////////////////////////////////////////////////////////////// -//END MultiSwitchArg.cpp +// END MultiSwitchArg.cpp ////////////////////////////////////////////////////////////////////// -} //namespace TCLAP +} // namespace TCLAP #endif diff --git a/external/tclap/OptionalUnlabeledTracker.h b/external/tclap/OptionalUnlabeledTracker.h index 8174c5f..18766c9 100644 --- a/external/tclap/OptionalUnlabeledTracker.h +++ b/external/tclap/OptionalUnlabeledTracker.h @@ -1,25 +1,24 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: OptionalUnlabeledTracker.h - * + * * Copyright (c) 2005, Michael E. Smoot . * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H #define TCLAP_OPTIONAL_UNLABELED_TRACKER_H @@ -28,35 +27,33 @@ namespace TCLAP { -class OptionalUnlabeledTracker -{ - - public: - - static void check( bool req, const std::string& argName ); +class OptionalUnlabeledTracker { - static void gotOptional() { alreadyOptionalRef() = true; } +public: + static void check(bool req, const std::string &argName); - static bool& alreadyOptional() { return alreadyOptionalRef(); } + static void gotOptional() { alreadyOptionalRef() = true; } - private: + static bool &alreadyOptional() { return alreadyOptionalRef(); } - static bool& alreadyOptionalRef() { static bool ct = false; return ct; } +private: + static bool &alreadyOptionalRef() { + static bool ct = false; + return ct; + } }; +inline void OptionalUnlabeledTracker::check(bool req, + const std::string &argName) { + if (OptionalUnlabeledTracker::alreadyOptional()) + throw(SpecificationException("You can't specify ANY Unlabeled Arg " + "following an optional Unlabeled Arg", + argName)); -inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) -{ - if ( OptionalUnlabeledTracker::alreadyOptional() ) - throw( SpecificationException( - "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", - argName ) ); - - if ( !req ) - OptionalUnlabeledTracker::gotOptional(); + if (!req) + OptionalUnlabeledTracker::gotOptional(); } - } // namespace TCLAP #endif diff --git a/external/tclap/StandardTraits.h b/external/tclap/StandardTraits.h index 46d7f6f..787dfd2 100644 --- a/external/tclap/StandardTraits.h +++ b/external/tclap/StandardTraits.h @@ -30,7 +30,7 @@ #include // To check for long long #endif -// If Microsoft has already typedef'd wchar_t as an unsigned +// If Microsoft has already typedef'd wchar_t as an unsigned // short, then compiles will break because it's as if we're // creating ArgTraits twice for unsigned short. Thus... #ifdef _MSC_VER @@ -48,43 +48,28 @@ namespace TCLAP { /** * longs have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; /** * ints have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; /** * shorts have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; /** * chars have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; #ifdef HAVE_LONG_LONG /** * long longs have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; #endif // ====================================================================== @@ -94,54 +79,43 @@ struct ArgTraits { /** * unsigned longs have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; +template <> struct ArgTraits { + typedef ValueLike ValueCategory; }; /** * unsigned ints have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; /** * unsigned shorts have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; +template <> struct ArgTraits { + typedef ValueLike ValueCategory; }; /** * unsigned chars have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; +template <> struct ArgTraits { + typedef ValueLike ValueCategory; }; -// Microsoft implements size_t awkwardly. +// Microsoft implements size_t awkwardly. #if defined(_MSC_VER) && defined(_M_X64) /** * size_ts have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; #endif - #ifdef HAVE_LONG_LONG /** * unsigned long longs have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; +template <> struct ArgTraits { + typedef ValueLike ValueCategory; }; #endif @@ -152,18 +126,12 @@ struct ArgTraits { /** * floats have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; /** * doubles have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; // ====================================================================== // Other types @@ -172,37 +140,24 @@ struct ArgTraits { /** * bools have value-like semantics. */ -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; - +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; /** * wchar_ts have value-like semantics. */ #ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS -template<> -struct ArgTraits { - typedef ValueLike ValueCategory; -}; +template <> struct ArgTraits { typedef ValueLike ValueCategory; }; #endif /** * Strings have string like argument traits. */ -template<> -struct ArgTraits { - typedef StringLike ValueCategory; -}; +template <> struct ArgTraits { typedef StringLike ValueCategory; }; -template -void SetString(T &dst, const std::string &src) -{ - dst = src; +template void SetString(T &dst, const std::string &src) { + dst = src; } -} // namespace +} // namespace TCLAP #endif - diff --git a/external/tclap/StdOutput.h b/external/tclap/StdOutput.h index 35f7b99..bf1ba8c 100644 --- a/external/tclap/StdOutput.h +++ b/external/tclap/StdOutput.h @@ -1,38 +1,38 @@ // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- -/****************************************************************************** - * +/****************************************************************************** + * * file: StdOutput.h - * + * * Copyright (c) 2004, Michael E. Smoot * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_STDCMDLINEOUTPUT_H #define TCLAP_STDCMDLINEOUTPUT_H +#include +#include +#include #include #include -#include -#include -#include +#include #include #include #include -#include namespace TCLAP { @@ -40,259 +40,227 @@ namespace TCLAP { * A class that isolates any output from the CmdLine object so that it * may be easily modified. */ -class StdOutput : public CmdLineOutput -{ - - public: - - /** - * Prints the usage to stdout. Can be overridden to - * produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - */ - virtual void usage(CmdLineInterface& c); - - /** - * Prints the version to stdout. Can be overridden - * to produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - */ - virtual void version(CmdLineInterface& c); - - /** - * Prints (to stderr) an error message, short usage - * Can be overridden to produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - * \param e - The ArgException that caused the failure. - */ - virtual void failure(CmdLineInterface& c, - ArgException& e ); - - protected: - - /** - * Writes a brief usage message with short args. - * \param c - The CmdLine object the output is generated for. - * \param os - The stream to write the message to. - */ - void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; - - /** - * Writes a longer usage message with long and short args, - * provides descriptions and prints message. - * \param c - The CmdLine object the output is generated for. - * \param os - The stream to write the message to. - */ - void _longUsage( CmdLineInterface& c, std::ostream& os ) const; - - /** - * This function inserts line breaks and indents long strings - * according the params input. It will only break lines at spaces, - * commas and pipes. - * \param os - The stream to be printed to. - * \param s - The string to be printed. - * \param maxWidth - The maxWidth allowed for the output line. - * \param indentSpaces - The number of spaces to indent the first line. - * \param secondLineOffset - The number of spaces to indent the second - * and all subsequent lines in addition to indentSpaces. - */ - void spacePrint( std::ostream& os, - const std::string& s, - int maxWidth, - int indentSpaces, - int secondLineOffset ) const; - +class StdOutput : public CmdLineOutput { + +public: + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface &c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface &c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface &c, ArgException &e); + +protected: + /** + * Writes a brief usage message with short args. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _shortUsage(CmdLineInterface &c, std::ostream &os) const; + + /** + * Writes a longer usage message with long and short args, + * provides descriptions and prints message. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _longUsage(CmdLineInterface &c, std::ostream &os) const; + + /** + * This function inserts line breaks and indents long strings + * according the params input. It will only break lines at spaces, + * commas and pipes. + * \param os - The stream to be printed to. + * \param s - The string to be printed. + * \param maxWidth - The maxWidth allowed for the output line. + * \param indentSpaces - The number of spaces to indent the first line. + * \param secondLineOffset - The number of spaces to indent the second + * and all subsequent lines in addition to indentSpaces. + */ + void spacePrint(std::ostream &os, const std::string &s, int maxWidth, + int indentSpaces, int secondLineOffset) const; }; +inline void StdOutput::version(CmdLineInterface &_cmd) { + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + + std::cout << std::endl + << progName << " version: " << xversion << std::endl + << std::endl; +} + +inline void StdOutput::usage(CmdLineInterface &_cmd) { + std::cout << std::endl << "USAGE: " << std::endl << std::endl; -inline void StdOutput::version(CmdLineInterface& _cmd) -{ - std::string progName = _cmd.getProgramName(); - std::string xversion = _cmd.getVersion(); + _shortUsage(_cmd, std::cout); - std::cout << std::endl << progName << " version: " - << xversion << std::endl << std::endl; + std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; + + _longUsage(_cmd, std::cout); + + std::cout << std::endl; } -inline void StdOutput::usage(CmdLineInterface& _cmd ) -{ - std::cout << std::endl << "USAGE: " << std::endl << std::endl; +inline void StdOutput::failure(CmdLineInterface &_cmd, ArgException &e) { + std::string progName = _cmd.getProgramName(); - _shortUsage( _cmd, std::cout ); + std::cerr << "PARSE ERROR: " << e.argId() << std::endl + << " " << e.error() << std::endl + << std::endl; - std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; + if (_cmd.hasHelpAndVersion()) { + std::cerr << "Brief USAGE: " << std::endl; - _longUsage( _cmd, std::cout ); + _shortUsage(_cmd, std::cerr); - std::cout << std::endl; + std::cerr << std::endl + << "For complete USAGE and HELP type: " << std::endl + << " " << progName << " --help" << std::endl + << std::endl; + } else + usage(_cmd); + throw ExitException(1); } -inline void StdOutput::failure( CmdLineInterface& _cmd, - ArgException& e ) -{ - std::string progName = _cmd.getProgramName(); +inline void StdOutput::_shortUsage(CmdLineInterface &_cmd, + std::ostream &os) const { + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector> xorList = xorHandler.getXorList(); - std::cerr << "PARSE ERROR: " << e.argId() << std::endl - << " " << e.error() << std::endl << std::endl; + std::string s = progName + " "; - if ( _cmd.hasHelpAndVersion() ) - { - std::cerr << "Brief USAGE: " << std::endl; + // first the xor + for (int i = 0; static_cast(i) < xorList.size(); i++) { + s += " {"; + for (ArgVectorIterator it = xorList[i].begin(); it != xorList[i].end(); + it++) + s += (*it)->shortID() + "|"; - _shortUsage( _cmd, std::cerr ); + s[s.length() - 1] = '}'; + } - std::cerr << std::endl << "For complete USAGE and HELP type: " - << std::endl << " " << progName << " --help" - << std::endl << std::endl; - } - else - usage(_cmd); + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if (!xorHandler.contains((*it))) + s += " " + (*it)->shortID(); - throw ExitException(1); -} + // if the program name is too long, then adjust the second line offset + int secondLineOffset = static_cast(progName.length()) + 2; + if (secondLineOffset > 75 / 2) + secondLineOffset = static_cast(75 / 2); -inline void -StdOutput::_shortUsage( CmdLineInterface& _cmd, - std::ostream& os ) const -{ - std::list argList = _cmd.getArgList(); - std::string progName = _cmd.getProgramName(); - XorHandler xorHandler = _cmd.getXorHandler(); - std::vector< std::vector > xorList = xorHandler.getXorList(); - - std::string s = progName + " "; - - // first the xor - for ( int i = 0; static_cast(i) < xorList.size(); i++ ) - { - s += " {"; - for ( ArgVectorIterator it = xorList[i].begin(); - it != xorList[i].end(); it++ ) - s += (*it)->shortID() + "|"; - - s[s.length()-1] = '}'; - } - - // then the rest - for (ArgListIterator it = argList.begin(); it != argList.end(); it++) - if ( !xorHandler.contains( (*it) ) ) - s += " " + (*it)->shortID(); - - // if the program name is too long, then adjust the second line offset - int secondLineOffset = static_cast(progName.length()) + 2; - if ( secondLineOffset > 75/2 ) - secondLineOffset = static_cast(75/2); - - spacePrint( os, s, 75, 3, secondLineOffset ); + spacePrint(os, s, 75, 3, secondLineOffset); } -inline void -StdOutput::_longUsage( CmdLineInterface& _cmd, - std::ostream& os ) const -{ - std::list argList = _cmd.getArgList(); - std::string message = _cmd.getMessage(); - XorHandler xorHandler = _cmd.getXorHandler(); - std::vector< std::vector > xorList = xorHandler.getXorList(); - - // first the xor - for ( int i = 0; static_cast(i) < xorList.size(); i++ ) - { - for ( ArgVectorIterator it = xorList[i].begin(); - it != xorList[i].end(); - it++ ) - { - spacePrint( os, (*it)->longID(), 75, 3, 3 ); - spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); - - if ( it+1 != xorList[i].end() ) - spacePrint(os, "-- OR --", 75, 9, 0); - } - os << std::endl << std::endl; - } - - // then the rest - for (ArgListIterator it = argList.begin(); it != argList.end(); it++) - if ( !xorHandler.contains( (*it) ) ) - { - spacePrint( os, (*it)->longID(), 75, 3, 3 ); - spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); - os << std::endl; - } - - os << std::endl; - - spacePrint( os, message, 75, 3, 0 ); +inline void StdOutput::_longUsage(CmdLineInterface &_cmd, + std::ostream &os) const { + std::list argList = _cmd.getArgList(); + std::string message = _cmd.getMessage(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector> xorList = xorHandler.getXorList(); + + // first the xor + for (int i = 0; static_cast(i) < xorList.size(); i++) { + for (ArgVectorIterator it = xorList[i].begin(); it != xorList[i].end(); + it++) { + spacePrint(os, (*it)->longID(), 75, 3, 3); + spacePrint(os, (*it)->getDescription(), 75, 5, 0); + + if (it + 1 != xorList[i].end()) + spacePrint(os, "-- OR --", 75, 9, 0); + } + os << std::endl << std::endl; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if (!xorHandler.contains((*it))) { + spacePrint(os, (*it)->longID(), 75, 3, 3); + spacePrint(os, (*it)->getDescription(), 75, 5, 0); + os << std::endl; + } + + os << std::endl; + + spacePrint(os, message, 75, 3, 0); } -inline void StdOutput::spacePrint( std::ostream& os, - const std::string& s, - int maxWidth, - int indentSpaces, - int secondLineOffset ) const -{ - int len = static_cast(s.length()); - - if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) - { - int allowedLen = maxWidth - indentSpaces; - int start = 0; - while ( start < len ) - { - // find the substring length - // int stringLen = std::min( len - start, allowedLen ); - // doing it this way to support a VisualC++ 2005 bug - using namespace std; - int stringLen = min( len - start, allowedLen ); - - // trim the length so it doesn't end in middle of a word - if ( stringLen == allowedLen ) - while ( stringLen >= 0 && - s[stringLen+start] != ' ' && - s[stringLen+start] != ',' && - s[stringLen+start] != '|' ) - stringLen--; - - // ok, the word is longer than the line, so just split - // wherever the line ends - if ( stringLen <= 0 ) - stringLen = allowedLen; - - // check for newlines - for ( int i = 0; i < stringLen; i++ ) - if ( s[start+i] == '\n' ) - stringLen = i+1; - - // print the indent - for ( int i = 0; i < indentSpaces; i++ ) - os << " "; - - if ( start == 0 ) - { - // handle second line offsets - indentSpaces += secondLineOffset; - - // adjust allowed len - allowedLen -= secondLineOffset; - } - - os << s.substr(start,stringLen) << std::endl; - - // so we don't start a line with a space - while ( s[stringLen+start] == ' ' && start < len ) - start++; - - start += stringLen; - } - } - else - { - for ( int i = 0; i < indentSpaces; i++ ) - os << " "; - os << s << std::endl; - } +inline void StdOutput::spacePrint(std::ostream &os, const std::string &s, + int maxWidth, int indentSpaces, + int secondLineOffset) const { + int len = static_cast(s.length()); + + if ((len + indentSpaces > maxWidth) && maxWidth > 0) { + int allowedLen = maxWidth - indentSpaces; + int start = 0; + while (start < len) { + // find the substring length + // int stringLen = std::min( len - start, allowedLen ); + // doing it this way to support a VisualC++ 2005 bug + using namespace std; + int stringLen = min(len - start, allowedLen); + + // trim the length so it doesn't end in middle of a word + if (stringLen == allowedLen) + while (stringLen >= 0 && s[stringLen + start] != ' ' && + s[stringLen + start] != ',' && s[stringLen + start] != '|') + stringLen--; + + // ok, the word is longer than the line, so just split + // wherever the line ends + if (stringLen <= 0) + stringLen = allowedLen; + + // check for newlines + for (int i = 0; i < stringLen; i++) + if (s[start + i] == '\n') + stringLen = i + 1; + + // print the indent + for (int i = 0; i < indentSpaces; i++) + os << " "; + + if (start == 0) { + // handle second line offsets + indentSpaces += secondLineOffset; + + // adjust allowed len + allowedLen -= secondLineOffset; + } + + os << s.substr(start, stringLen) << std::endl; + + // so we don't start a line with a space + while (s[stringLen + start] == ' ' && start < len) + start++; + + start += stringLen; + } + } else { + for (int i = 0; i < indentSpaces; i++) + os << " "; + os << s << std::endl; + } } -} //namespace TCLAP -#endif +} // namespace TCLAP +#endif diff --git a/external/tclap/SwitchArg.h b/external/tclap/SwitchArg.h index 3916109..a47e827 100644 --- a/external/tclap/SwitchArg.h +++ b/external/tclap/SwitchArg.h @@ -1,25 +1,24 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: SwitchArg.h - * + * * Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_SWITCH_ARG_H #define TCLAP_SWITCH_ARG_H @@ -36,231 +35,200 @@ namespace TCLAP { * the getValue method will return the opposite of the default value for the * switch. */ -class SwitchArg : public Arg -{ - protected: - - /** - * The value of the switch. - */ - bool _value; - - /** - * Used to support the reset() method so that ValueArg can be - * reset to their constructed value. - */ - bool _default; - - public: - - /** - * SwitchArg constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param def - The default value for this Switch. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - SwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool def = false, - Visitor* v = NULL); - - - /** - * SwitchArg constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param parser - A CmdLine parser object to add this Arg to - * \param def - The default value for this Switch. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - SwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - CmdLineInterface& parser, - bool def = false, - Visitor* v = NULL); - - - /** - * Handles the processing of the argument. - * This re-implements the Arg version of this method to set the - * _value of the argument appropriately. - * \param i - Pointer the the current argument in the list. - * \param args - Mutable list of strings. Passed - * in from main(). - */ - virtual bool processArg(int* i, std::vector& args); - - /** - * Checks a string to see if any of the chars in the string - * match the flag for this Switch. - */ - bool combinedSwitchesMatch(std::string& combined); - - /** - * Returns bool, whether or not the switch has been set. - */ - bool getValue(); - - virtual void reset(); - - private: - /** - * Checks to see if we've found the last match in - * a combined string. - */ - bool lastCombined(std::string& combined); - - /** - * Does the common processing of processArg. - */ - void commonProcessing(); +class SwitchArg : public Arg { +protected: + /** + * The value of the switch. + */ + bool _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + bool _default; + +public: + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string &flag, const std::string &name, + const std::string &desc, bool def = false, Visitor *v = NULL); + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string &flag, const std::string &name, + const std::string &desc, CmdLineInterface &parser, bool def = false, + Visitor *v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int *i, std::vector &args); + + /** + * Checks a string to see if any of the chars in the string + * match the flag for this Switch. + */ + bool combinedSwitchesMatch(std::string &combined); + + /** + * Returns bool, whether or not the switch has been set. + */ + bool getValue(); + + virtual void reset(); + +private: + /** + * Checks to see if we've found the last match in + * a combined string. + */ + bool lastCombined(std::string &combined); + + /** + * Does the common processing of processArg. + */ + void commonProcessing(); }; ////////////////////////////////////////////////////////////////////// -//BEGIN SwitchArg.cpp +// BEGIN SwitchArg.cpp ////////////////////////////////////////////////////////////////////// -inline SwitchArg::SwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool default_val, - Visitor* v ) -: Arg(flag, name, desc, false, false, v), - _value( default_val ), - _default( default_val ) -{ } - -inline SwitchArg::SwitchArg(const std::string& flag, - const std::string& name, - const std::string& desc, - CmdLineInterface& parser, - bool default_val, - Visitor* v ) -: Arg(flag, name, desc, false, false, v), - _value( default_val ), - _default(default_val) -{ - parser.add( this ); +inline SwitchArg::SwitchArg(const std::string &flag, const std::string &name, + const std::string &desc, bool default_val, + Visitor *v) + : Arg(flag, name, desc, false, false, v), _value(default_val), + _default(default_val) {} + +inline SwitchArg::SwitchArg(const std::string &flag, const std::string &name, + const std::string &desc, CmdLineInterface &parser, + bool default_val, Visitor *v) + : Arg(flag, name, desc, false, false, v), _value(default_val), + _default(default_val) { + parser.add(this); } inline bool SwitchArg::getValue() { return _value; } -inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) -{ - for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) - if ( combinedSwitches[i] != Arg::blankChar() ) - return false; - - return true; +inline bool SwitchArg::lastCombined(std::string &combinedSwitches) { + for (unsigned int i = 1; i < combinedSwitches.length(); i++) + if (combinedSwitches[i] != Arg::blankChar()) + return false; + + return true; } -inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) -{ - // make sure this is actually a combined switch - if ( combinedSwitches.length() > 0 && - combinedSwitches[0] != Arg::flagStartString()[0] ) - return false; - - // make sure it isn't a long name - if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == - Arg::nameStartString() ) - return false; - - // make sure the delimiter isn't in the string - if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) - return false; - - // ok, we're not specifying a ValueArg, so we know that we have - // a combined switch list. - for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) - if ( _flag.length() > 0 && - combinedSwitches[i] == _flag[0] && - _flag[0] != Arg::flagStartString()[0] ) - { - // update the combined switches so this one is no longer present - // this is necessary so that no unlabeled args are matched - // later in the processing. - //combinedSwitches.erase(i,1); - combinedSwitches[i] = Arg::blankChar(); - return true; - } - - // none of the switches passed in the list match. - return false; +inline bool SwitchArg::combinedSwitchesMatch(std::string &combinedSwitches) { + // make sure this is actually a combined switch + if (combinedSwitches.length() > 0 && + combinedSwitches[0] != Arg::flagStartString()[0]) + return false; + + // make sure it isn't a long name + if (combinedSwitches.substr(0, Arg::nameStartString().length()) == + Arg::nameStartString()) + return false; + + // make sure the delimiter isn't in the string + if (combinedSwitches.find_first_of(Arg::delimiter()) != std::string::npos) + return false; + + // ok, we're not specifying a ValueArg, so we know that we have + // a combined switch list. + for (unsigned int i = 1; i < combinedSwitches.length(); i++) + if (_flag.length() > 0 && combinedSwitches[i] == _flag[0] && + _flag[0] != Arg::flagStartString()[0]) { + // update the combined switches so this one is no longer present + // this is necessary so that no unlabeled args are matched + // later in the processing. + // combinedSwitches.erase(i,1); + combinedSwitches[i] = Arg::blankChar(); + return true; + } + + // none of the switches passed in the list match. + return false; } -inline void SwitchArg::commonProcessing() -{ - if ( _xorSet ) - throw(CmdLineParseException( - "Mutually exclusive argument already set!", toString())); +inline void SwitchArg::commonProcessing() { + if (_xorSet) + throw(CmdLineParseException("Mutually exclusive argument already set!", + toString())); - if ( _alreadySet ) - throw(CmdLineParseException("Argument already set!", toString())); + if (_alreadySet) + throw(CmdLineParseException("Argument already set!", toString())); - _alreadySet = true; + _alreadySet = true; - if ( _value == true ) - _value = false; - else - _value = true; + if (_value == true) + _value = false; + else + _value = true; - _checkWithVisitor(); + _checkWithVisitor(); } -inline bool SwitchArg::processArg(int *i, std::vector& args) -{ - if ( _ignoreable && Arg::ignoreRest() ) - return false; - - // if the whole string matches the flag or name string - if ( argMatches( args[*i] ) ) - { - commonProcessing(); - - return true; - } - // if a substring matches the flag as part of a combination - else if ( combinedSwitchesMatch( args[*i] ) ) - { - // check again to ensure we don't misinterpret - // this as a MultiSwitchArg - if ( combinedSwitchesMatch( args[*i] ) ) - throw(CmdLineParseException("Argument already set!", - toString())); - - commonProcessing(); - - // We only want to return true if we've found the last combined - // match in the string, otherwise we return true so that other - // switches in the combination will have a chance to match. - return lastCombined( args[*i] ); - } - else - return false; +inline bool SwitchArg::processArg(int *i, std::vector &args) { + if (_ignoreable && Arg::ignoreRest()) + return false; + + // if the whole string matches the flag or name string + if (argMatches(args[*i])) { + commonProcessing(); + + return true; + } + // if a substring matches the flag as part of a combination + else if (combinedSwitchesMatch(args[*i])) { + // check again to ensure we don't misinterpret + // this as a MultiSwitchArg + if (combinedSwitchesMatch(args[*i])) + throw(CmdLineParseException("Argument already set!", toString())); + + commonProcessing(); + + // We only want to return true if we've found the last combined + // match in the string, otherwise we return true so that other + // switches in the combination will have a chance to match. + return lastCombined(args[*i]); + } else + return false; } -inline void SwitchArg::reset() -{ - Arg::reset(); - _value = _default; +inline void SwitchArg::reset() { + Arg::reset(); + _value = _default; } ////////////////////////////////////////////////////////////////////// -//End SwitchArg.cpp +// End SwitchArg.cpp ////////////////////////////////////////////////////////////////////// -} //namespace TCLAP +} // namespace TCLAP #endif diff --git a/external/tclap/UnlabeledMultiArg.h b/external/tclap/UnlabeledMultiArg.h index d5e1781..50635dd 100644 --- a/external/tclap/UnlabeledMultiArg.h +++ b/external/tclap/UnlabeledMultiArg.h @@ -1,24 +1,23 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: UnlabeledMultiArg.h - * + * * Copyright (c) 2003, Michael E. Smoot. * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H #define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H @@ -33,269 +32,231 @@ namespace TCLAP { /** * Just like a MultiArg, except that the arguments are unlabeled. Basically, - * this Arg will slurp up everything that hasn't been matched to another + * this Arg will slurp up everything that hasn't been matched to another * Arg. */ -template -class UnlabeledMultiArg : public MultiArg -{ - - // If compiler has two stage name lookup (as gcc >= 3.4 does) - // this is requried to prevent undef. symbols - using MultiArg::_ignoreable; - using MultiArg::_hasBlanks; - using MultiArg::_extractValue; - using MultiArg::_typeDesc; - using MultiArg::_name; - using MultiArg::_description; - using MultiArg::_alreadySet; - using MultiArg::toString; - - public: - - /** - * Constructor. - * \param name - The name of the Arg. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param ignoreable - Whether or not this argument can be ignored - * using the "--" flag. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - UnlabeledMultiArg( const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - bool ignoreable = false, - Visitor* v = NULL ); - /** - * Constructor. - * \param name - The name of the Arg. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param parser - A CmdLine parser object to add this Arg to - * \param ignoreable - Whether or not this argument can be ignored - * using the "--" flag. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - UnlabeledMultiArg( const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - CmdLineInterface& parser, - bool ignoreable = false, - Visitor* v = NULL ); - - /** - * Constructor. - * \param name - The name of the Arg. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param ignoreable - Whether or not this argument can be ignored - * using the "--" flag. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - UnlabeledMultiArg( const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - bool ignoreable = false, - Visitor* v = NULL ); - - /** - * Constructor. - * \param name - The name of the Arg. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param parser - A CmdLine parser object to add this Arg to - * \param ignoreable - Whether or not this argument can be ignored - * using the "--" flag. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - UnlabeledMultiArg( const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - CmdLineInterface& parser, - bool ignoreable = false, - Visitor* v = NULL ); - - /** - * Handles the processing of the argument. - * This re-implements the Arg version of this method to set the - * _value of the argument appropriately. It knows the difference - * between labeled and unlabeled. - * \param i - Pointer the the current argument in the list. - * \param args - Mutable list of strings. Passed from main(). - */ - virtual bool processArg(int* i, std::vector& args); - - /** - * Returns the a short id string. Used in the usage. - * \param val - value to be used. - */ - virtual std::string shortID(const std::string& val="val") const; - - /** - * Returns the a long id string. Used in the usage. - * \param val - value to be used. - */ - virtual std::string longID(const std::string& val="val") const; - - /** - * Opertor ==. - * \param a - The Arg to be compared to this. - */ - virtual bool operator==(const Arg& a) const; - - /** - * Pushes this to back of list rather than front. - * \param argList - The list this should be added to. - */ - virtual void addToList( std::list& argList ) const; +template class UnlabeledMultiArg : public MultiArg { + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using MultiArg::_ignoreable; + using MultiArg::_hasBlanks; + using MultiArg::_extractValue; + using MultiArg::_typeDesc; + using MultiArg::_name; + using MultiArg::_description; + using MultiArg::_alreadySet; + using MultiArg::toString; + +public: + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg(const std::string &name, const std::string &desc, bool req, + const std::string &typeDesc, bool ignoreable = false, + Visitor *v = NULL); + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg(const std::string &name, const std::string &desc, bool req, + const std::string &typeDesc, CmdLineInterface &parser, + bool ignoreable = false, Visitor *v = NULL); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg(const std::string &name, const std::string &desc, bool req, + Constraint *constraint, bool ignoreable = false, + Visitor *v = NULL); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg(const std::string &name, const std::string &desc, bool req, + Constraint *constraint, CmdLineInterface &parser, + bool ignoreable = false, Visitor *v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int *i, std::vector &args); + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string &val = "val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string &val = "val") const; + + /** + * Opertor ==. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg &a) const; + + /** + * Pushes this to back of list rather than front. + * \param argList - The list this should be added to. + */ + virtual void addToList(std::list &argList) const; }; -template -UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - bool ignoreable, - Visitor* v) -: MultiArg("", name, desc, req, typeDesc, v) -{ - _ignoreable = ignoreable; - OptionalUnlabeledTracker::check(true, toString()); +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string &name, + const std::string &desc, bool req, + const std::string &typeDesc, + bool ignoreable, Visitor *v) + : MultiArg("", name, desc, req, typeDesc, v) { + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); } -template -UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, - const std::string& desc, - bool req, - const std::string& typeDesc, - CmdLineInterface& parser, - bool ignoreable, - Visitor* v) -: MultiArg("", name, desc, req, typeDesc, v) -{ - _ignoreable = ignoreable; - OptionalUnlabeledTracker::check(true, toString()); - parser.add( this ); +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string &name, + const std::string &desc, bool req, + const std::string &typeDesc, + CmdLineInterface &parser, + bool ignoreable, Visitor *v) + : MultiArg("", name, desc, req, typeDesc, v) { + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add(this); } - -template -UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - bool ignoreable, - Visitor* v) -: MultiArg("", name, desc, req, constraint, v) -{ - _ignoreable = ignoreable; - OptionalUnlabeledTracker::check(true, toString()); +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string &name, + const std::string &desc, bool req, + Constraint *constraint, + bool ignoreable, Visitor *v) + : MultiArg("", name, desc, req, constraint, v) { + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); } -template -UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, - const std::string& desc, - bool req, - Constraint* constraint, - CmdLineInterface& parser, - bool ignoreable, - Visitor* v) -: MultiArg("", name, desc, req, constraint, v) -{ - _ignoreable = ignoreable; - OptionalUnlabeledTracker::check(true, toString()); - parser.add( this ); +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string &name, + const std::string &desc, bool req, + Constraint *constraint, + CmdLineInterface &parser, + bool ignoreable, Visitor *v) + : MultiArg("", name, desc, req, constraint, v) { + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add(this); } +template +bool UnlabeledMultiArg::processArg(int *i, std::vector &args) { -template -bool UnlabeledMultiArg::processArg(int *i, std::vector& args) -{ - - if ( _hasBlanks( args[*i] ) ) - return false; + if (_hasBlanks(args[*i])) + return false; - // never ignore an unlabeled multi arg + // never ignore an unlabeled multi arg + // always take the first value, regardless of the start string + _extractValue(args[(*i)]); - // always take the first value, regardless of the start string - _extractValue( args[(*i)] ); + /* + // continue taking args until we hit the end or a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ - /* - // continue taking args until we hit the end or a start string - while ( (unsigned int)(*i)+1 < args.size() && - args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && - args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) - _extractValue( args[++(*i)] ); - */ + _alreadySet = true; - _alreadySet = true; - - return true; + return true; } -template -std::string UnlabeledMultiArg::shortID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - return std::string("<") + _typeDesc + "> ..."; +template +std::string UnlabeledMultiArg::shortID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> ..."; } -template -std::string UnlabeledMultiArg::longID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - return std::string("<") + _typeDesc + "> (accepted multiple times)"; +template +std::string UnlabeledMultiArg::longID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> (accepted multiple times)"; } -template -bool UnlabeledMultiArg::operator==(const Arg& a) const -{ - if ( _name == a.getName() || _description == a.getDescription() ) - return true; - else - return false; +template bool UnlabeledMultiArg::operator==(const Arg &a) const { + if (_name == a.getName() || _description == a.getDescription()) + return true; + else + return false; } -template -void UnlabeledMultiArg::addToList( std::list& argList ) const -{ - argList.push_back( const_cast(static_cast(this)) ); +template +void UnlabeledMultiArg::addToList(std::list &argList) const { + argList.push_back(const_cast(static_cast(this))); } -} +} // namespace TCLAP #endif diff --git a/external/tclap/UnlabeledValueArg.h b/external/tclap/UnlabeledValueArg.h index 5721d61..0cc264d 100644 --- a/external/tclap/UnlabeledValueArg.h +++ b/external/tclap/UnlabeledValueArg.h @@ -1,25 +1,24 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: UnlabeledValueArg.h - * + * * Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H #define TCLAP_UNLABELED_VALUE_ARGUMENT_H @@ -27,9 +26,8 @@ #include #include -#include #include - +#include namespace TCLAP { @@ -39,302 +37,258 @@ namespace TCLAP { * that a given object will attempt to parse when an UnlabeledValueArg * is reached in the list of args that the CmdLine iterates over. */ -template -class UnlabeledValueArg : public ValueArg -{ - - // If compiler has two stage name lookup (as gcc >= 3.4 does) - // this is requried to prevent undef. symbols - using ValueArg::_ignoreable; - using ValueArg::_hasBlanks; - using ValueArg::_extractValue; - using ValueArg::_typeDesc; - using ValueArg::_name; - using ValueArg::_description; - using ValueArg::_alreadySet; - using ValueArg::toString; - - public: - - /** - * UnlabeledValueArg constructor. - * \param name - A one word name for the argument. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param ignoreable - Allows you to specify that this argument can be - * ignored if the '--' flag is set. This defaults to false (cannot - * be ignored) and should generally stay that way unless you have - * some special need for certain arguments to be ignored. - * \param v - Optional Vistor. You should leave this blank unless - * you have a very good reason. - */ - UnlabeledValueArg( const std::string& name, - const std::string& desc, - bool req, - T value, - const std::string& typeDesc, - bool ignoreable = false, - Visitor* v = NULL); - - /** - * UnlabeledValueArg constructor. - * \param name - A one word name for the argument. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param parser - A CmdLine parser object to add this Arg to - * \param ignoreable - Allows you to specify that this argument can be - * ignored if the '--' flag is set. This defaults to false (cannot - * be ignored) and should generally stay that way unless you have - * some special need for certain arguments to be ignored. - * \param v - Optional Vistor. You should leave this blank unless - * you have a very good reason. - */ - UnlabeledValueArg( const std::string& name, - const std::string& desc, - bool req, - T value, - const std::string& typeDesc, - CmdLineInterface& parser, - bool ignoreable = false, - Visitor* v = NULL ); - - /** - * UnlabeledValueArg constructor. - * \param name - A one word name for the argument. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param ignoreable - Allows you to specify that this argument can be - * ignored if the '--' flag is set. This defaults to false (cannot - * be ignored) and should generally stay that way unless you have - * some special need for certain arguments to be ignored. - * \param v - Optional Vistor. You should leave this blank unless - * you have a very good reason. - */ - UnlabeledValueArg( const std::string& name, - const std::string& desc, - bool req, - T value, - Constraint* constraint, - bool ignoreable = false, - Visitor* v = NULL ); - - - /** - * UnlabeledValueArg constructor. - * \param name - A one word name for the argument. Note that this is used for - * identification, not as a long flag. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param parser - A CmdLine parser object to add this Arg to - * \param ignoreable - Allows you to specify that this argument can be - * ignored if the '--' flag is set. This defaults to false (cannot - * be ignored) and should generally stay that way unless you have - * some special need for certain arguments to be ignored. - * \param v - Optional Vistor. You should leave this blank unless - * you have a very good reason. - */ - UnlabeledValueArg( const std::string& name, - const std::string& desc, - bool req, - T value, - Constraint* constraint, - CmdLineInterface& parser, - bool ignoreable = false, - Visitor* v = NULL); - - /** - * Handles the processing of the argument. - * This re-implements the Arg version of this method to set the - * _value of the argument appropriately. Handling specific to - * unlabled arguments. - * \param i - Pointer the the current argument in the list. - * \param args - Mutable list of strings. - */ - virtual bool processArg(int* i, std::vector& args); - - /** - * Overrides shortID for specific behavior. - */ - virtual std::string shortID(const std::string& val="val") const; - - /** - * Overrides longID for specific behavior. - */ - virtual std::string longID(const std::string& val="val") const; - - /** - * Overrides operator== for specific behavior. - */ - virtual bool operator==(const Arg& a ) const; - - /** - * Instead of pushing to the front of list, push to the back. - * \param argList - The list to add this to. - */ - virtual void addToList( std::list& argList ) const; - +template class UnlabeledValueArg : public ValueArg { + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using ValueArg::_ignoreable; + using ValueArg::_hasBlanks; + using ValueArg::_extractValue; + using ValueArg::_typeDesc; + using ValueArg::_name; + using ValueArg::_description; + using ValueArg::_alreadySet; + using ValueArg::toString; + +public: + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg(const std::string &name, const std::string &desc, bool req, + T value, const std::string &typeDesc, + bool ignoreable = false, Visitor *v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg(const std::string &name, const std::string &desc, bool req, + T value, const std::string &typeDesc, + CmdLineInterface &parser, bool ignoreable = false, + Visitor *v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg(const std::string &name, const std::string &desc, bool req, + T value, Constraint *constraint, bool ignoreable = false, + Visitor *v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg(const std::string &name, const std::string &desc, bool req, + T value, Constraint *constraint, + CmdLineInterface &parser, bool ignoreable = false, + Visitor *v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. Handling specific to + * unlabled arguments. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. + */ + virtual bool processArg(int *i, std::vector &args); + + /** + * Overrides shortID for specific behavior. + */ + virtual std::string shortID(const std::string &val = "val") const; + + /** + * Overrides longID for specific behavior. + */ + virtual std::string longID(const std::string &val = "val") const; + + /** + * Overrides operator== for specific behavior. + */ + virtual bool operator==(const Arg &a) const; + + /** + * Instead of pushing to the front of list, push to the back. + * \param argList - The list to add this to. + */ + virtual void addToList(std::list &argList) const; }; /** * Constructor implemenation. */ -template -UnlabeledValueArg::UnlabeledValueArg(const std::string& name, - const std::string& desc, - bool req, - T val, - const std::string& typeDesc, - bool ignoreable, - Visitor* v) -: ValueArg("", name, desc, req, val, typeDesc, v) -{ - _ignoreable = ignoreable; - - OptionalUnlabeledTracker::check(req, toString()); - +template +UnlabeledValueArg::UnlabeledValueArg(const std::string &name, + const std::string &desc, bool req, + T val, const std::string &typeDesc, + bool ignoreable, Visitor *v) + : ValueArg("", name, desc, req, val, typeDesc, v) { + _ignoreable = ignoreable; + + OptionalUnlabeledTracker::check(req, toString()); } -template -UnlabeledValueArg::UnlabeledValueArg(const std::string& name, - const std::string& desc, - bool req, - T val, - const std::string& typeDesc, - CmdLineInterface& parser, - bool ignoreable, - Visitor* v) -: ValueArg("", name, desc, req, val, typeDesc, v) -{ - _ignoreable = ignoreable; - OptionalUnlabeledTracker::check(req, toString()); - parser.add( this ); +template +UnlabeledValueArg::UnlabeledValueArg(const std::string &name, + const std::string &desc, bool req, + T val, const std::string &typeDesc, + CmdLineInterface &parser, + bool ignoreable, Visitor *v) + : ValueArg("", name, desc, req, val, typeDesc, v) { + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add(this); } /** * Constructor implemenation. */ -template -UnlabeledValueArg::UnlabeledValueArg(const std::string& name, - const std::string& desc, - bool req, - T val, - Constraint* constraint, - bool ignoreable, - Visitor* v) -: ValueArg("", name, desc, req, val, constraint, v) -{ - _ignoreable = ignoreable; - OptionalUnlabeledTracker::check(req, toString()); +template +UnlabeledValueArg::UnlabeledValueArg(const std::string &name, + const std::string &desc, bool req, + T val, Constraint *constraint, + bool ignoreable, Visitor *v) + : ValueArg("", name, desc, req, val, constraint, v) { + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); } -template -UnlabeledValueArg::UnlabeledValueArg(const std::string& name, - const std::string& desc, - bool req, - T val, - Constraint* constraint, - CmdLineInterface& parser, - bool ignoreable, - Visitor* v) -: ValueArg("", name, desc, req, val, constraint, v) -{ - _ignoreable = ignoreable; - OptionalUnlabeledTracker::check(req, toString()); - parser.add( this ); +template +UnlabeledValueArg::UnlabeledValueArg(const std::string &name, + const std::string &desc, bool req, + T val, Constraint *constraint, + CmdLineInterface &parser, + bool ignoreable, Visitor *v) + : ValueArg("", name, desc, req, val, constraint, v) { + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add(this); } /** * Implementation of processArg(). */ -template -bool UnlabeledValueArg::processArg(int *i, std::vector& args) -{ - - if ( _alreadySet ) - return false; - - if ( _hasBlanks( args[*i] ) ) - return false; - - // never ignore an unlabeled arg - - _extractValue( args[*i] ); - _alreadySet = true; - return true; +template +bool UnlabeledValueArg::processArg(int *i, std::vector &args) { + + if (_alreadySet) + return false; + + if (_hasBlanks(args[*i])) + return false; + + // never ignore an unlabeled arg + + _extractValue(args[*i]); + _alreadySet = true; + return true; } /** * Overriding shortID for specific output. */ -template -std::string UnlabeledValueArg::shortID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - return std::string("<") + _typeDesc + ">"; +template +std::string UnlabeledValueArg::shortID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + ">"; } /** * Overriding longID for specific output. */ -template -std::string UnlabeledValueArg::longID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - - // Ideally we would like to be able to use RTTI to return the name - // of the type required for this argument. However, g++ at least, - // doesn't appear to return terribly useful "names" of the types. - return std::string("<") + _typeDesc + ">"; +template +std::string UnlabeledValueArg::longID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + + // Ideally we would like to be able to use RTTI to return the name + // of the type required for this argument. However, g++ at least, + // doesn't appear to return terribly useful "names" of the types. + return std::string("<") + _typeDesc + ">"; } /** * Overriding operator== for specific behavior. */ -template -bool UnlabeledValueArg::operator==(const Arg& a ) const -{ - if ( _name == a.getName() || _description == a.getDescription() ) - return true; - else - return false; +template bool UnlabeledValueArg::operator==(const Arg &a) const { + if (_name == a.getName() || _description == a.getDescription()) + return true; + else + return false; } -template -void UnlabeledValueArg::addToList( std::list& argList ) const -{ - argList.push_back( const_cast(static_cast(this)) ); +template +void UnlabeledValueArg::addToList(std::list &argList) const { + argList.push_back(const_cast(static_cast(this))); } -} +} // namespace TCLAP #endif diff --git a/external/tclap/ValueArg.h b/external/tclap/ValueArg.h index 7ac2952..5d238a2 100644 --- a/external/tclap/ValueArg.h +++ b/external/tclap/ValueArg.h @@ -1,24 +1,23 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: ValueArg.h - * + * * Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_VALUE_ARGUMENT_H #define TCLAP_VALUE_ARGUMENT_H @@ -39,385 +38,314 @@ namespace TCLAP { * an unflagged ValueArg, it is unwise and would cause significant problems. * Instead use an UnlabeledValueArg. */ -template -class ValueArg : public Arg -{ - protected: - - /** - * The value parsed from the command line. - * Can be of any type, as long as the >> operator for the type - * is defined. - */ - T _value; - - /** - * Used to support the reset() method so that ValueArg can be - * reset to their constructed value. - */ - T _default; - - /** - * A human readable description of the type to be parsed. - * This is a hack, plain and simple. Ideally we would use RTTI to - * return the name of type T, but until there is some sort of - * consistent support for human readable names, we are left to our - * own devices. - */ - std::string _typeDesc; - - /** - * A Constraint this Arg must conform to. - */ - Constraint* _constraint; - - /** - * Extracts the value from the string. - * Attempts to parse string as type T, if this fails an exception - * is thrown. - * \param val - value to be parsed. - */ - void _extractValue( const std::string& val ); - - public: - - /** - * Labeled ValueArg constructor. - * You could conceivably call this constructor with a blank flag, - * but that would make you a bad person. It would also cause - * an exception to be thrown. If you want an unlabeled argument, - * use the other constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - ValueArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T value, - const std::string& typeDesc, - Visitor* v = NULL); - - - /** - * Labeled ValueArg constructor. - * You could conceivably call this constructor with a blank flag, - * but that would make you a bad person. It would also cause - * an exception to be thrown. If you want an unlabeled argument, - * use the other constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param typeDesc - A short, human readable description of the - * type that this object expects. This is used in the generation - * of the USAGE statement. The goal is to be helpful to the end user - * of the program. - * \param parser - A CmdLine parser object to add this Arg to - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - ValueArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T value, - const std::string& typeDesc, - CmdLineInterface& parser, - Visitor* v = NULL ); - - /** - * Labeled ValueArg constructor. - * You could conceivably call this constructor with a blank flag, - * but that would make you a bad person. It would also cause - * an exception to be thrown. If you want an unlabeled argument, - * use the other constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param parser - A CmdLine parser object to add this Arg to. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - ValueArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T value, - Constraint* constraint, - CmdLineInterface& parser, - Visitor* v = NULL ); - - /** - * Labeled ValueArg constructor. - * You could conceivably call this constructor with a blank flag, - * but that would make you a bad person. It would also cause - * an exception to be thrown. If you want an unlabeled argument, - * use the other constructor. - * \param flag - The one character flag that identifies this - * argument on the command line. - * \param name - A one word name for the argument. Can be - * used as a long flag on the command line. - * \param desc - A description of what the argument is for or - * does. - * \param req - Whether the argument is required on the command - * line. - * \param value - The default value assigned to this argument if it - * is not present on the command line. - * \param constraint - A pointer to a Constraint object used - * to constrain this Arg. - * \param v - An optional visitor. You probably should not - * use this unless you have a very good reason. - */ - ValueArg( const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T value, - Constraint* constraint, - Visitor* v = NULL ); - - /** - * Handles the processing of the argument. - * This re-implements the Arg version of this method to set the - * _value of the argument appropriately. It knows the difference - * between labeled and unlabeled. - * \param i - Pointer the the current argument in the list. - * \param args - Mutable list of strings. Passed - * in from main(). - */ - virtual bool processArg(int* i, std::vector& args); - - /** - * Returns the value of the argument. - */ - T& getValue() ; - - /** - * Specialization of shortID. - * \param val - value to be used. - */ - virtual std::string shortID(const std::string& val = "val") const; - - /** - * Specialization of longID. - * \param val - value to be used. - */ - virtual std::string longID(const std::string& val = "val") const; - - virtual void reset() ; +template class ValueArg : public Arg { +protected: + /** + * The value parsed from the command line. + * Can be of any type, as long as the >> operator for the type + * is defined. + */ + T _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + T _default; + + /** + * A human readable description of the type to be parsed. + * This is a hack, plain and simple. Ideally we would use RTTI to + * return the name of type T, but until there is some sort of + * consistent support for human readable names, we are left to our + * own devices. + */ + std::string _typeDesc; + + /** + * A Constraint this Arg must conform to. + */ + Constraint *_constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - value to be parsed. + */ + void _extractValue(const std::string &val); + +public: + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T value, + const std::string &typeDesc, Visitor *v = NULL); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T value, + const std::string &typeDesc, CmdLineInterface &parser, + Visitor *v = NULL); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T value, + Constraint *constraint, CmdLineInterface &parser, + Visitor *v = NULL); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T value, + Constraint *constraint, Visitor *v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int *i, std::vector &args); + + /** + * Returns the value of the argument. + */ + T &getValue(); + + /** + * Specialization of shortID. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string &val = "val") const; + + /** + * Specialization of longID. + * \param val - value to be used. + */ + virtual std::string longID(const std::string &val = "val") const; + + virtual void reset(); private: - /** - * Prevent accidental copying - */ - ValueArg(const ValueArg& rhs); - ValueArg& operator=(const ValueArg& rhs); + /** + * Prevent accidental copying + */ + ValueArg(const ValueArg &rhs); + ValueArg &operator=(const ValueArg &rhs); }; - /** * Constructor implementation. */ -template -ValueArg::ValueArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T val, - const std::string& typeDesc, - Visitor* v) -: Arg(flag, name, desc, req, true, v), - _value( val ), - _default( val ), - _typeDesc( typeDesc ), - _constraint( NULL ) -{ } - -template -ValueArg::ValueArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T val, - const std::string& typeDesc, - CmdLineInterface& parser, - Visitor* v) -: Arg(flag, name, desc, req, true, v), - _value( val ), - _default( val ), - _typeDesc( typeDesc ), - _constraint( NULL ) -{ - parser.add( this ); +template +ValueArg::ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T val, + const std::string &typeDesc, Visitor *v) + : Arg(flag, name, desc, req, true, v), _value(val), _default(val), + _typeDesc(typeDesc), _constraint(NULL) {} + +template +ValueArg::ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T val, + const std::string &typeDesc, CmdLineInterface &parser, + Visitor *v) + : Arg(flag, name, desc, req, true, v), _value(val), _default(val), + _typeDesc(typeDesc), _constraint(NULL) { + parser.add(this); } -template -ValueArg::ValueArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T val, - Constraint* constraint, - Visitor* v) -: Arg(flag, name, desc, req, true, v), - _value( val ), - _default( val ), - _typeDesc( constraint->shortID() ), - _constraint( constraint ) -{ } - -template -ValueArg::ValueArg(const std::string& flag, - const std::string& name, - const std::string& desc, - bool req, - T val, - Constraint* constraint, - CmdLineInterface& parser, - Visitor* v) -: Arg(flag, name, desc, req, true, v), - _value( val ), - _default( val ), - _typeDesc( constraint->shortID() ), - _constraint( constraint ) -{ - parser.add( this ); +template +ValueArg::ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T val, + Constraint *constraint, Visitor *v) + : Arg(flag, name, desc, req, true, v), _value(val), _default(val), + _typeDesc(constraint->shortID()), _constraint(constraint) {} + +template +ValueArg::ValueArg(const std::string &flag, const std::string &name, + const std::string &desc, bool req, T val, + Constraint *constraint, CmdLineInterface &parser, + Visitor *v) + : Arg(flag, name, desc, req, true, v), _value(val), _default(val), + _typeDesc(constraint->shortID()), _constraint(constraint) { + parser.add(this); } - /** * Implementation of getValue(). */ -template -T& ValueArg::getValue() { return _value; } +template T &ValueArg::getValue() { return _value; } /** * Implementation of processArg(). */ -template -bool ValueArg::processArg(int *i, std::vector& args) -{ - if ( _ignoreable && Arg::ignoreRest() ) - return false; - - if ( _hasBlanks( args[*i] ) ) - return false; - - std::string flag = args[*i]; - - std::string value = ""; - trimFlag( flag, value ); - - if ( argMatches( flag ) ) - { - if ( _alreadySet ) - { - if ( _xorSet ) - throw( CmdLineParseException( - "Mutually exclusive argument already set!", - toString()) ); - else - throw( CmdLineParseException("Argument already set!", - toString()) ); - } - - if ( Arg::delimiter() != ' ' && value == "" ) - throw( ArgParseException( - "Couldn't find delimiter for this argument!", - toString() ) ); - - if ( value == "" ) - { - (*i)++; - if ( static_cast(*i) < args.size() ) - _extractValue( args[*i] ); - else - throw( ArgParseException("Missing a value for this argument!", - toString() ) ); - } - else - _extractValue( value ); - - _alreadySet = true; - _checkWithVisitor(); - return true; - } - else - return false; +template +bool ValueArg::processArg(int *i, std::vector &args) { + if (_ignoreable && Arg::ignoreRest()) + return false; + + if (_hasBlanks(args[*i])) + return false; + + std::string flag = args[*i]; + + std::string value = ""; + trimFlag(flag, value); + + if (argMatches(flag)) { + if (_alreadySet) { + if (_xorSet) + throw(CmdLineParseException("Mutually exclusive argument already set!", + toString())); + else + throw(CmdLineParseException("Argument already set!", toString())); + } + + if (Arg::delimiter() != ' ' && value == "") + throw(ArgParseException("Couldn't find delimiter for this argument!", + toString())); + + if (value == "") { + (*i)++; + if (static_cast(*i) < args.size()) + _extractValue(args[*i]); + else + throw(ArgParseException("Missing a value for this argument!", + toString())); + } else + _extractValue(value); + + _alreadySet = true; + _checkWithVisitor(); + return true; + } else + return false; } /** * Implementation of shortID. */ -template -std::string ValueArg::shortID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - return Arg::shortID( _typeDesc ); +template +std::string ValueArg::shortID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + return Arg::shortID(_typeDesc); } /** * Implementation of longID. */ -template -std::string ValueArg::longID(const std::string& val) const -{ - static_cast(val); // Ignore input, don't warn - return Arg::longID( _typeDesc ); +template +std::string ValueArg::longID(const std::string &val) const { + static_cast(val); // Ignore input, don't warn + return Arg::longID(_typeDesc); } -template -void ValueArg::_extractValue( const std::string& val ) -{ - try { - ExtractValue(_value, val, typename ArgTraits::ValueCategory()); - } catch( ArgParseException &e) { - throw ArgParseException(e.error(), toString()); - } - - if ( _constraint != NULL ) - if ( ! _constraint->check( _value ) ) - throw( CmdLineParseException( "Value '" + val + - + "' does not meet constraint: " - + _constraint->description(), - toString() ) ); +template void ValueArg::_extractValue(const std::string &val) { + try { + ExtractValue(_value, val, typename ArgTraits::ValueCategory()); + } catch (ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if (_constraint != NULL) + if (!_constraint->check(_value)) + throw(CmdLineParseException( + "Value '" + val + + +"' does not meet constraint: " + _constraint->description(), + toString())); } -template -void ValueArg::reset() -{ - Arg::reset(); - _value = _default; +template void ValueArg::reset() { + Arg::reset(); + _value = _default; } } // namespace TCLAP diff --git a/external/tclap/ValuesConstraint.h b/external/tclap/ValuesConstraint.h index cb41f64..ad407eb 100644 --- a/external/tclap/ValuesConstraint.h +++ b/external/tclap/ValuesConstraint.h @@ -1,31 +1,31 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: ValuesConstraint.h - * + * * Copyright (c) 2005, Michael E. Smoot * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_VALUESCONSTRAINT_H #define TCLAP_VALUESCONSTRAINT_H #include -#include #include +#include #ifdef HAVE_CONFIG_H #include @@ -47,102 +47,86 @@ namespace TCLAP { * A Constraint that constrains the Arg to only those values specified * in the constraint. */ -template -class ValuesConstraint : public Constraint -{ - - public: - - /** - * Constructor. - * \param allowed - vector of allowed values. - */ - ValuesConstraint(std::vector& allowed); - - /** - * Virtual destructor. - */ - virtual ~ValuesConstraint() {} - - /** - * Returns a description of the Constraint. - */ - virtual std::string description() const; - - /** - * Returns the short ID for the Constraint. - */ - virtual std::string shortID() const; - - /** - * The method used to verify that the value parsed from the command - * line meets the constraint. - * \param value - The value that will be checked. - */ - virtual bool check(const T& value) const; - - protected: - - /** - * The list of valid values. - */ - std::vector _allowed; - - /** - * The string used to describe the allowed values of this constraint. - */ - std::string _typeDesc; - +template class ValuesConstraint : public Constraint { + +public: + /** + * Constructor. + * \param allowed - vector of allowed values. + */ + ValuesConstraint(std::vector &allowed); + + /** + * Virtual destructor. + */ + virtual ~ValuesConstraint() {} + + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T &value) const; + +protected: + /** + * The list of valid values. + */ + std::vector _allowed; + + /** + * The string used to describe the allowed values of this constraint. + */ + std::string _typeDesc; }; -template -ValuesConstraint::ValuesConstraint(std::vector& allowed) -: _allowed(allowed), - _typeDesc("") -{ - for ( unsigned int i = 0; i < _allowed.size(); i++ ) - { +template +ValuesConstraint::ValuesConstraint(std::vector &allowed) + : _allowed(allowed), _typeDesc("") { + for (unsigned int i = 0; i < _allowed.size(); i++) { #if defined(HAVE_SSTREAM) - std::ostringstream os; + std::ostringstream os; #elif defined(HAVE_STRSTREAM) - std::ostrstream os; + std::ostrstream os; #else #error "Need a stringstream (sstream or strstream) to compile!" #endif - os << _allowed[i]; + os << _allowed[i]; - std::string temp( os.str() ); + std::string temp(os.str()); - if ( i > 0 ) - _typeDesc += "|"; - _typeDesc += temp; - } + if (i > 0) + _typeDesc += "|"; + _typeDesc += temp; + } } -template -bool ValuesConstraint::check( const T& val ) const -{ - if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) - return false; - else - return true; +template bool ValuesConstraint::check(const T &val) const { + if (std::find(_allowed.begin(), _allowed.end(), val) == _allowed.end()) + return false; + else + return true; } -template -std::string ValuesConstraint::shortID() const -{ - return _typeDesc; +template std::string ValuesConstraint::shortID() const { + return _typeDesc; } -template -std::string ValuesConstraint::description() const -{ - return _typeDesc; +template std::string ValuesConstraint::description() const { + return _typeDesc; } - -} //namespace TCLAP -#endif - +} // namespace TCLAP +#endif diff --git a/external/tclap/VersionVisitor.h b/external/tclap/VersionVisitor.h index c110d4f..88fa71e 100644 --- a/external/tclap/VersionVisitor.h +++ b/external/tclap/VersionVisitor.h @@ -1,25 +1,24 @@ // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- -/****************************************************************************** - * +/****************************************************************************** + * * file: VersionVisitor.h - * + * * Copyright (c) 2003, Michael E. Smoot . * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_VERSION_VISITOR_H #define TCLAP_VERSION_VISITOR_H @@ -34,48 +33,44 @@ namespace TCLAP { * A Vistor that will call the version method of the given CmdLineOutput * for the specified CmdLine object and then exit. */ -class VersionVisitor: public Visitor -{ - private: - /** - * Prevent accidental copying - */ - VersionVisitor(const VersionVisitor& rhs); - VersionVisitor& operator=(const VersionVisitor& rhs); - - protected: - - /** - * The CmdLine of interest. - */ - CmdLineInterface* _cmd; - - /** - * The output object. - */ - CmdLineOutput** _out; +class VersionVisitor : public Visitor { +private: + /** + * Prevent accidental copying + */ + VersionVisitor(const VersionVisitor &rhs); + VersionVisitor &operator=(const VersionVisitor &rhs); - public: +protected: + /** + * The CmdLine of interest. + */ + CmdLineInterface *_cmd; - /** - * Constructor. - * \param cmd - The CmdLine the output is generated for. - * \param out - The type of output. - */ - VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) - : Visitor(), _cmd( cmd ), _out( out ) { } + /** + * The output object. + */ + CmdLineOutput **_out; - /** - * Calls the version method of the output object using the - * specified CmdLine. - */ - void visit() { - (*_out)->version(*_cmd); - throw ExitException(0); - } +public: + /** + * Constructor. + * \param cmd - The CmdLine the output is generated for. + * \param out - The type of output. + */ + VersionVisitor(CmdLineInterface *cmd, CmdLineOutput **out) + : Visitor(), _cmd(cmd), _out(out) {} + /** + * Calls the version method of the output object using the + * specified CmdLine. + */ + void visit() { + (*_out)->version(*_cmd); + throw ExitException(0); + } }; -} +} // namespace TCLAP #endif diff --git a/external/tclap/Visitor.h b/external/tclap/Visitor.h index 38ddcbd..4a53746 100644 --- a/external/tclap/Visitor.h +++ b/external/tclap/Visitor.h @@ -1,24 +1,23 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: Visitor.h - * + * * Copyright (c) 2003, Michael E. Smoot . * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ - + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_VISITOR_H #define TCLAP_VISITOR_H @@ -28,26 +27,24 @@ namespace TCLAP { /** * A base class that defines the interface for visitors. */ -class Visitor -{ - public: - - /** - * Constructor. Does nothing. - */ - Visitor() { } - - /** - * Destructor. Does nothing. - */ - virtual ~Visitor() { } - - /** - * Does nothing. Should be overridden by child. - */ - virtual void visit() { } +class Visitor { +public: + /** + * Constructor. Does nothing. + */ + Visitor() {} + + /** + * Destructor. Does nothing. + */ + virtual ~Visitor() {} + + /** + * Does nothing. Should be overridden by child. + */ + virtual void visit() {} }; -} +} // namespace TCLAP #endif diff --git a/external/tclap/XorHandler.h b/external/tclap/XorHandler.h index d9dfad3..f227ada 100644 --- a/external/tclap/XorHandler.h +++ b/external/tclap/XorHandler.h @@ -1,33 +1,33 @@ -/****************************************************************************** - * +/****************************************************************************** + * * file: XorHandler.h - * + * * Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ #ifndef TCLAP_XORHANDLER_H #define TCLAP_XORHANDLER_H -#include -#include -#include #include #include +#include +#include +#include namespace TCLAP { @@ -35,132 +35,112 @@ namespace TCLAP { * This class handles lists of Arg's that are to be XOR'd on the command * line. This is used by CmdLine and you shouldn't ever use it. */ -class XorHandler -{ - protected: - - /** - * The list of of lists of Arg's to be or'd together. - */ - std::vector< std::vector > _orList; - - public: - - /** - * Constructor. Does nothing. - */ - XorHandler( ) : _orList(std::vector< std::vector >()) {} - - /** - * Add a list of Arg*'s that will be orred together. - * \param ors - list of Arg* that will be xor'd. - */ - void add( std::vector& ors ); - - /** - * Checks whether the specified Arg is in one of the xor lists and - * if it does match one, returns the size of the xor list that the - * Arg matched. If the Arg matches, then it also sets the rest of - * the Arg's in the list. You shouldn't use this. - * \param a - The Arg to be checked. - */ - int check( const Arg* a ); - - /** - * Returns the XOR specific short usage. - */ - std::string shortUsage(); - - /** - * Prints the XOR specific long usage. - * \param os - Stream to print to. - */ - void printLongUsage(std::ostream& os); - - /** - * Simply checks whether the Arg is contained in one of the arg - * lists. - * \param a - The Arg to be checked. - */ - bool contains( const Arg* a ); - - std::vector< std::vector >& getXorList(); - +class XorHandler { +protected: + /** + * The list of of lists of Arg's to be or'd together. + */ + std::vector> _orList; + +public: + /** + * Constructor. Does nothing. + */ + XorHandler() : _orList(std::vector>()) {} + + /** + * Add a list of Arg*'s that will be orred together. + * \param ors - list of Arg* that will be xor'd. + */ + void add(std::vector &ors); + + /** + * Checks whether the specified Arg is in one of the xor lists and + * if it does match one, returns the size of the xor list that the + * Arg matched. If the Arg matches, then it also sets the rest of + * the Arg's in the list. You shouldn't use this. + * \param a - The Arg to be checked. + */ + int check(const Arg *a); + + /** + * Returns the XOR specific short usage. + */ + std::string shortUsage(); + + /** + * Prints the XOR specific long usage. + * \param os - Stream to print to. + */ + void printLongUsage(std::ostream &os); + + /** + * Simply checks whether the Arg is contained in one of the arg + * lists. + * \param a - The Arg to be checked. + */ + bool contains(const Arg *a); + + std::vector> &getXorList(); }; - ////////////////////////////////////////////////////////////////////// -//BEGIN XOR.cpp +// BEGIN XOR.cpp ////////////////////////////////////////////////////////////////////// -inline void XorHandler::add( std::vector& ors ) -{ - _orList.push_back( ors ); -} - -inline int XorHandler::check( const Arg* a ) -{ - // iterate over each XOR list - for ( int i = 0; static_cast(i) < _orList.size(); i++ ) - { - // if the XOR list contains the arg.. - ArgVectorIterator ait = std::find( _orList[i].begin(), - _orList[i].end(), a ); - if ( ait != _orList[i].end() ) - { - // first check to see if a mutually exclusive switch - // has not already been set - for ( ArgVectorIterator it = _orList[i].begin(); - it != _orList[i].end(); - it++ ) - if ( a != (*it) && (*it)->isSet() ) - throw(CmdLineParseException( - "Mutually exclusive argument already set!", - (*it)->toString())); - - // go through and set each arg that is not a - for ( ArgVectorIterator it = _orList[i].begin(); - it != _orList[i].end(); - it++ ) - if ( a != (*it) ) - (*it)->xorSet(); - - // return the number of required args that have now been set - if ( (*ait)->allowMore() ) - return 0; - else - return static_cast(_orList[i].size()); - } - } - - if ( a->isRequired() ) - return 1; - else - return 0; +inline void XorHandler::add(std::vector &ors) { _orList.push_back(ors); } + +inline int XorHandler::check(const Arg *a) { + // iterate over each XOR list + for (int i = 0; static_cast(i) < _orList.size(); i++) { + // if the XOR list contains the arg.. + ArgVectorIterator ait = std::find(_orList[i].begin(), _orList[i].end(), a); + if (ait != _orList[i].end()) { + // first check to see if a mutually exclusive switch + // has not already been set + for (ArgVectorIterator it = _orList[i].begin(); it != _orList[i].end(); + it++) + if (a != (*it) && (*it)->isSet()) + throw(CmdLineParseException( + "Mutually exclusive argument already set!", (*it)->toString())); + + // go through and set each arg that is not a + for (ArgVectorIterator it = _orList[i].begin(); it != _orList[i].end(); + it++) + if (a != (*it)) + (*it)->xorSet(); + + // return the number of required args that have now been set + if ((*ait)->allowMore()) + return 0; + else + return static_cast(_orList[i].size()); + } + } + + if (a->isRequired()) + return 1; + else + return 0; } -inline bool XorHandler::contains( const Arg* a ) -{ - for ( int i = 0; static_cast(i) < _orList.size(); i++ ) - for ( ArgVectorIterator it = _orList[i].begin(); - it != _orList[i].end(); - it++ ) - if ( a == (*it) ) - return true; +inline bool XorHandler::contains(const Arg *a) { + for (int i = 0; static_cast(i) < _orList.size(); i++) + for (ArgVectorIterator it = _orList[i].begin(); it != _orList[i].end(); + it++) + if (a == (*it)) + return true; - return false; + return false; } -inline std::vector< std::vector >& XorHandler::getXorList() -{ - return _orList; +inline std::vector> &XorHandler::getXorList() { + return _orList; } - - ////////////////////////////////////////////////////////////////////// -//END XOR.cpp +// END XOR.cpp ////////////////////////////////////////////////////////////////////// -} //namespace TCLAP +} // namespace TCLAP -#endif +#endif diff --git a/external/tclap/ZshCompletionOutput.h b/external/tclap/ZshCompletionOutput.h index 0b37fc7..6675c1b 100644 --- a/external/tclap/ZshCompletionOutput.h +++ b/external/tclap/ZshCompletionOutput.h @@ -1,38 +1,38 @@ // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- -/****************************************************************************** - * +/****************************************************************************** + * * file: ZshCompletionOutput.h - * + * * Copyright (c) 2006, Oliver Kiddle * All rights reverved. - * + * * See the file COPYING in the top directory of this distribution for * more information. - * - * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * - *****************************************************************************/ + * + *****************************************************************************/ #ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H #define TCLAP_ZSHCOMPLETIONOUTPUT_H -#include -#include -#include #include +#include #include +#include +#include +#include #include #include #include -#include namespace TCLAP { @@ -40,284 +40,244 @@ namespace TCLAP { * A class that generates a Zsh completion function as output from the usage() * method for the given CmdLine and its Args. */ -class ZshCompletionOutput : public CmdLineOutput -{ - - public: - - ZshCompletionOutput(); - - /** - * Prints the usage to stdout. Can be overridden to - * produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - */ - virtual void usage(CmdLineInterface& c); - - /** - * Prints the version to stdout. Can be overridden - * to produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - */ - virtual void version(CmdLineInterface& c); - - /** - * Prints (to stderr) an error message, short usage - * Can be overridden to produce alternative behavior. - * \param c - The CmdLine object the output is generated for. - * \param e - The ArgException that caused the failure. - */ - virtual void failure(CmdLineInterface& c, - ArgException& e ); - - protected: - - void basename( std::string& s ); - void quoteSpecialChars( std::string& s ); - - std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); - void printOption( Arg* it, std::string mutex ); - void printArg( Arg* it ); - - std::map common; - char theDelimiter; +class ZshCompletionOutput : public CmdLineOutput { + +public: + ZshCompletionOutput(); + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface &c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface &c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface &c, ArgException &e); + +protected: + void basename(std::string &s); + void quoteSpecialChars(std::string &s); + + std::string getMutexList(CmdLineInterface &_cmd, Arg *a); + void printOption(Arg *it, std::string mutex); + void printArg(Arg *it); + + std::map common; + char theDelimiter; }; ZshCompletionOutput::ZshCompletionOutput() -: common(std::map()), - theDelimiter('=') -{ - common["host"] = "_hosts"; - common["hostname"] = "_hosts"; - common["file"] = "_files"; - common["filename"] = "_files"; - common["user"] = "_users"; - common["username"] = "_users"; - common["directory"] = "_directories"; - common["path"] = "_directories"; - common["url"] = "_urls"; + : common(std::map()), theDelimiter('=') { + common["host"] = "_hosts"; + common["hostname"] = "_hosts"; + common["file"] = "_files"; + common["filename"] = "_files"; + common["user"] = "_users"; + common["username"] = "_users"; + common["directory"] = "_directories"; + common["path"] = "_directories"; + common["url"] = "_urls"; } -inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) -{ - std::cout << _cmd.getVersion() << std::endl; +inline void ZshCompletionOutput::version(CmdLineInterface &_cmd) { + std::cout << _cmd.getVersion() << std::endl; } -inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) -{ - std::list argList = _cmd.getArgList(); - std::string progName = _cmd.getProgramName(); - std::string xversion = _cmd.getVersion(); - theDelimiter = _cmd.getDelimiter(); - basename(progName); - - std::cout << "#compdef " << progName << std::endl << std::endl << - "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << - "_arguments -s -S"; - - for (ArgListIterator it = argList.begin(); it != argList.end(); it++) - { - if ( (*it)->shortID().at(0) == '<' ) - printArg((*it)); - else if ( (*it)->getFlag() != "-" ) - printOption((*it), getMutexList(_cmd, *it)); - } - - std::cout << std::endl; +inline void ZshCompletionOutput::usage(CmdLineInterface &_cmd) { + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + basename(progName); + + std::cout << "#compdef " << progName << std::endl + << std::endl + << "# " << progName << " version " << _cmd.getVersion() << std::endl + << std::endl + << "_arguments -s -S"; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) { + if ((*it)->shortID().at(0) == '<') + printArg((*it)); + else if ((*it)->getFlag() != "-") + printOption((*it), getMutexList(_cmd, *it)); + } + + std::cout << std::endl; } -inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, - ArgException& e ) -{ - static_cast(_cmd); // unused - std::cout << e.what() << std::endl; +inline void ZshCompletionOutput::failure(CmdLineInterface &_cmd, + ArgException &e) { + static_cast(_cmd); // unused + std::cout << e.what() << std::endl; } -inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) -{ - size_t idx = s.find_last_of(':'); - while ( idx != std::string::npos ) - { - s.insert(idx, 1, '\\'); - idx = s.find_last_of(':', idx); - } - idx = s.find_last_of('\''); - while ( idx != std::string::npos ) - { - s.insert(idx, "'\\'"); - if (idx == 0) - idx = std::string::npos; - else - idx = s.find_last_of('\'', --idx); - } +inline void ZshCompletionOutput::quoteSpecialChars(std::string &s) { + size_t idx = s.find_last_of(':'); + while (idx != std::string::npos) { + s.insert(idx, 1, '\\'); + idx = s.find_last_of(':', idx); + } + idx = s.find_last_of('\''); + while (idx != std::string::npos) { + s.insert(idx, "'\\'"); + if (idx == 0) + idx = std::string::npos; + else + idx = s.find_last_of('\'', --idx); + } } -inline void ZshCompletionOutput::basename( std::string& s ) -{ - size_t p = s.find_last_of('/'); - if ( p != std::string::npos ) - { - s.erase(0, p + 1); - } +inline void ZshCompletionOutput::basename(std::string &s) { + size_t p = s.find_last_of('/'); + if (p != std::string::npos) { + s.erase(0, p + 1); + } } -inline void ZshCompletionOutput::printArg(Arg* a) -{ - static int count = 1; - - std::cout << " \\" << std::endl << " '"; - if ( a->acceptsMultipleValues() ) - std::cout << '*'; - else - std::cout << count++; - std::cout << ':'; - if ( !a->isRequired() ) - std::cout << ':'; - - std::cout << a->getName() << ':'; - std::map::iterator compArg = common.find(a->getName()); - if ( compArg != common.end() ) - { - std::cout << compArg->second; - } - else - { - std::cout << "_guard \"^-*\" " << a->getName(); - } - std::cout << '\''; +inline void ZshCompletionOutput::printArg(Arg *a) { + static int count = 1; + + std::cout << " \\" << std::endl << " '"; + if (a->acceptsMultipleValues()) + std::cout << '*'; + else + std::cout << count++; + std::cout << ':'; + if (!a->isRequired()) + std::cout << ':'; + + std::cout << a->getName() << ':'; + std::map::iterator compArg = + common.find(a->getName()); + if (compArg != common.end()) { + std::cout << compArg->second; + } else { + std::cout << "_guard \"^-*\" " << a->getName(); + } + std::cout << '\''; } -inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) -{ - std::string flag = a->flagStartChar() + a->getFlag(); - std::string name = a->nameStartString() + a->getName(); - std::string desc = a->getDescription(); - - // remove full stop and capitalisation from description as - // this is the convention for zsh function - if (!desc.compare(0, 12, "(required) ")) - { - desc.erase(0, 12); - } - if (!desc.compare(0, 15, "(OR required) ")) - { - desc.erase(0, 15); - } - size_t len = desc.length(); - if (len && desc.at(--len) == '.') - { - desc.erase(len); - } - if (len) - { - desc.replace(0, 1, 1, tolower(desc.at(0))); - } - - std::cout << " \\" << std::endl << " '" << mutex; - - if ( a->getFlag().empty() ) - { - std::cout << name; - } - else - { - std::cout << "'{" << flag << ',' << name << "}'"; - } - if ( theDelimiter == '=' && a->isValueRequired() ) - std::cout << "=-"; - quoteSpecialChars(desc); - std::cout << '[' << desc << ']'; - - if ( a->isValueRequired() ) - { - std::string arg = a->shortID(); - arg.erase(0, arg.find_last_of(theDelimiter) + 1); - if ( arg.at(arg.length()-1) == ']' ) - arg.erase(arg.length()-1); - if ( arg.at(arg.length()-1) == ']' ) - { - arg.erase(arg.length()-1); - } - if ( arg.at(0) == '<' ) - { - arg.erase(arg.length()-1); - arg.erase(0, 1); - } - size_t p = arg.find('|'); - if ( p != std::string::npos ) - { - do - { - arg.replace(p, 1, 1, ' '); - } - while ( (p = arg.find_first_of('|', p)) != std::string::npos ); - quoteSpecialChars(arg); - std::cout << ": :(" << arg << ')'; - } - else - { - std::cout << ':' << arg; - std::map::iterator compArg = common.find(arg); - if ( compArg != common.end() ) - { - std::cout << ':' << compArg->second; - } - } - } - - std::cout << '\''; +inline void ZshCompletionOutput::printOption(Arg *a, std::string mutex) { + std::string flag = a->flagStartChar() + a->getFlag(); + std::string name = a->nameStartString() + a->getName(); + std::string desc = a->getDescription(); + + // remove full stop and capitalisation from description as + // this is the convention for zsh function + if (!desc.compare(0, 12, "(required) ")) { + desc.erase(0, 12); + } + if (!desc.compare(0, 15, "(OR required) ")) { + desc.erase(0, 15); + } + size_t len = desc.length(); + if (len && desc.at(--len) == '.') { + desc.erase(len); + } + if (len) { + desc.replace(0, 1, 1, tolower(desc.at(0))); + } + + std::cout << " \\" << std::endl << " '" << mutex; + + if (a->getFlag().empty()) { + std::cout << name; + } else { + std::cout << "'{" << flag << ',' << name << "}'"; + } + if (theDelimiter == '=' && a->isValueRequired()) + std::cout << "=-"; + quoteSpecialChars(desc); + std::cout << '[' << desc << ']'; + + if (a->isValueRequired()) { + std::string arg = a->shortID(); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + if (arg.at(arg.length() - 1) == ']') + arg.erase(arg.length() - 1); + if (arg.at(arg.length() - 1) == ']') { + arg.erase(arg.length() - 1); + } + if (arg.at(0) == '<') { + arg.erase(arg.length() - 1); + arg.erase(0, 1); + } + size_t p = arg.find('|'); + if (p != std::string::npos) { + do { + arg.replace(p, 1, 1, ' '); + } while ((p = arg.find_first_of('|', p)) != std::string::npos); + quoteSpecialChars(arg); + std::cout << ": :(" << arg << ')'; + } else { + std::cout << ':' << arg; + std::map::iterator compArg = common.find(arg); + if (compArg != common.end()) { + std::cout << ':' << compArg->second; + } + } + } + + std::cout << '\''; } -inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) -{ - XorHandler xorHandler = _cmd.getXorHandler(); - std::vector< std::vector > xorList = xorHandler.getXorList(); - - if (a->getName() == "help" || a->getName() == "version") - { - return "(-)"; - } - - std::ostringstream list; - if ( a->acceptsMultipleValues() ) - { - list << '*'; - } - - for ( int i = 0; static_cast(i) < xorList.size(); i++ ) - { - for ( ArgVectorIterator it = xorList[i].begin(); - it != xorList[i].end(); - it++) - if ( a == (*it) ) - { - list << '('; - for ( ArgVectorIterator iu = xorList[i].begin(); - iu != xorList[i].end(); - iu++ ) - { - bool notCur = (*iu) != a; - bool hasFlag = !(*iu)->getFlag().empty(); - if ( iu != xorList[i].begin() && (notCur || hasFlag) ) - list << ' '; - if (hasFlag) - list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; - if ( notCur || hasFlag ) - list << (*iu)->nameStartString() << (*iu)->getName(); - } - list << ')'; - return list.str(); - } - } - - // wasn't found in xor list - if (!a->getFlag().empty()) { - list << "(" << a->flagStartChar() << a->getFlag() << ' ' << - a->nameStartString() << a->getName() << ')'; - } - - return list.str(); +inline std::string ZshCompletionOutput::getMutexList(CmdLineInterface &_cmd, + Arg *a) { + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector> xorList = xorHandler.getXorList(); + + if (a->getName() == "help" || a->getName() == "version") { + return "(-)"; + } + + std::ostringstream list; + if (a->acceptsMultipleValues()) { + list << '*'; + } + + for (int i = 0; static_cast(i) < xorList.size(); i++) { + for (ArgVectorIterator it = xorList[i].begin(); it != xorList[i].end(); + it++) + if (a == (*it)) { + list << '('; + for (ArgVectorIterator iu = xorList[i].begin(); iu != xorList[i].end(); + iu++) { + bool notCur = (*iu) != a; + bool hasFlag = !(*iu)->getFlag().empty(); + if (iu != xorList[i].begin() && (notCur || hasFlag)) + list << ' '; + if (hasFlag) + list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; + if (notCur || hasFlag) + list << (*iu)->nameStartString() << (*iu)->getName(); + } + list << ')'; + return list.str(); + } + } + + // wasn't found in xor list + if (!a->getFlag().empty()) { + list << "(" << a->flagStartChar() << a->getFlag() << ' ' + << a->nameStartString() << a->getName() << ')'; + } + + return list.str(); } -} //namespace TCLAP +} // namespace TCLAP #endif diff --git a/external/tsl/ordered_hash.h b/external/tsl/ordered_hash.h new file mode 100644 index 0000000..93f5774 --- /dev/null +++ b/external/tsl/ordered_hash.h @@ -0,0 +1,1610 @@ +/** + * MIT License + * + * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef TSL_ORDERED_HASH_H +#define TSL_ORDERED_HASH_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Macros for compatibility with GCC 4.8 + */ +#if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 9)) +#define TSL_OH_NO_CONTAINER_ERASE_CONST_ITERATOR +#define TSL_OH_NO_CONTAINER_EMPLACE_CONST_ITERATOR +#endif + +/** + * Only activate tsl_oh_assert if TSL_DEBUG is defined. + * This way we avoid the performance hit when NDEBUG is not defined with assert + * as tsl_oh_assert is used a lot (people usually compile with "-O3" and not + * "-O3 -DNDEBUG"). + */ +#ifdef TSL_DEBUG +#define tsl_oh_assert(expr) assert(expr) +#else +#define tsl_oh_assert(expr) (static_cast(0)) +#endif + +/** + * If exceptions are enabled, throw the exception passed in parameter, otherwise + * call std::terminate. + */ +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \ + (defined(_MSC_VER) && defined(_CPPUNWIND))) && \ + !defined(TSL_NO_EXCEPTIONS) +#define TSL_OH_THROW_OR_TERMINATE(ex, msg) throw ex(msg) +#else +#define TSL_OH_NO_EXCEPTIONS +#ifdef NDEBUG +#define TSL_OH_THROW_OR_TERMINATE(ex, msg) std::terminate() +#else +#include +#define TSL_OH_THROW_OR_TERMINATE(ex, msg) \ + do { \ + std::cerr << msg << std::endl; \ + std::terminate(); \ + } while (0) +#endif +#endif + +namespace tsl { + +namespace detail_ordered_hash { + +template struct make_void { using type = void; }; + +template +struct has_is_transparent : std::false_type {}; + +template +struct has_is_transparent::type> + : std::true_type {}; + +template struct is_vector : std::false_type {}; + +template +struct is_vector>::value>::type> + : std::true_type {}; + +// Only available in C++17, we need to be compatible with C++11 +template const T &clamp(const T &v, const T &lo, const T &hi) { + return std::min(hi, std::max(lo, v)); +} + +template +static T numeric_cast(U value, + const char *error_message = "numeric_cast() failed.") { + T ret = static_cast(value); + if (static_cast(ret) != value) { + TSL_OH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } + + const bool is_same_signedness = + (std::is_unsigned::value && std::is_unsigned::value) || + (std::is_signed::value && std::is_signed::value); + if (!is_same_signedness && (ret < T{}) != (value < U{})) { + TSL_OH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } + + return ret; +} + +/** + * Fixed size type used to represent size_type values on serialization. Need to + * be big enough to represent a std::size_t on 32 and 64 bits platforms, and + * must be the same size on both platforms. + */ +using slz_size_type = std::uint64_t; +static_assert(std::numeric_limits::max() >= + std::numeric_limits::max(), + "slz_size_type must be >= std::size_t"); + +template +static T deserialize_value(Deserializer &deserializer) { + // MSVC < 2017 is not conformant, circumvent the problem by removing the + // template keyword +#if defined(_MSC_VER) && _MSC_VER < 1910 + return deserializer.Deserializer::operator()(); +#else + return deserializer.Deserializer::template operator()(); +#endif +} + +/** + * Each bucket entry stores an index which is the index in m_values + * corresponding to the bucket's value and a hash (which may be truncated to 32 + * bits depending on IndexType) corresponding to the hash of the value. + * + * The size of IndexType limits the size of the hash table to + * std::numeric_limits::max() - 1 elements (-1 due to a reserved + * value used to mark a bucket as empty). + */ +template class bucket_entry { + static_assert(std::is_unsigned::value, + "IndexType must be an unsigned value."); + static_assert(std::numeric_limits::max() <= + std::numeric_limits::max(), + "std::numeric_limits::max() must be <= " + "std::numeric_limits::max()."); + +public: + using index_type = IndexType; + using truncated_hash_type = typename std::conditional< + std::numeric_limits::max() <= + std::numeric_limits::max(), + std::uint_least32_t, std::size_t>::type; + + bucket_entry() noexcept : m_index(EMPTY_MARKER_INDEX), m_hash(0) {} + + bool empty() const noexcept { return m_index == EMPTY_MARKER_INDEX; } + + void clear() noexcept { m_index = EMPTY_MARKER_INDEX; } + + index_type index() const noexcept { + tsl_oh_assert(!empty()); + return m_index; + } + + index_type &index_ref() noexcept { + tsl_oh_assert(!empty()); + return m_index; + } + + void set_index(index_type index) noexcept { + tsl_oh_assert(index <= max_size()); + + m_index = index; + } + + truncated_hash_type truncated_hash() const noexcept { + tsl_oh_assert(!empty()); + return m_hash; + } + + truncated_hash_type &truncated_hash_ref() noexcept { + tsl_oh_assert(!empty()); + return m_hash; + } + + void set_hash(std::size_t hash) noexcept { m_hash = truncate_hash(hash); } + + template void serialize(Serializer &serializer) const { + const slz_size_type index = m_index; + serializer(index); + + const slz_size_type hash = m_hash; + serializer(hash); + } + + template + static bucket_entry deserialize(Deserializer &deserializer) { + const slz_size_type index = deserialize_value(deserializer); + const slz_size_type hash = deserialize_value(deserializer); + + bucket_entry bentry; + bentry.m_index = + numeric_cast(index, "Deserialized index is too big."); + bentry.m_hash = numeric_cast( + hash, "Deserialized hash is too big."); + + return bentry; + } + + static truncated_hash_type truncate_hash(std::size_t hash) noexcept { + return truncated_hash_type(hash); + } + + static std::size_t max_size() noexcept { + return static_cast(std::numeric_limits::max()) - + NB_RESERVED_INDEXES; + } + +private: + static const index_type EMPTY_MARKER_INDEX = + std::numeric_limits::max(); + static const std::size_t NB_RESERVED_INDEXES = 1; + + index_type m_index; + truncated_hash_type m_hash; +}; + +/** + * Internal common class used by ordered_map and ordered_set. + * + * ValueType is what will be stored by ordered_hash (usually std::pair + * for map and Key for set). + * + * KeySelect should be a FunctionObject which takes a ValueType in parameter and + * return a reference to the key. + * + * ValueSelect should be a FunctionObject which takes a ValueType in parameter + * and return a reference to the value. ValueSelect should be void if there is + * no value (in set for example). + * + * ValueTypeContainer is the container which will be used to store ValueType + * values. Usually a std::deque or std::vector. + * + * + * + * The orderd_hash structure is a hash table which preserves the order of + * insertion of the elements. To do so, it stores the values in the + * ValueTypeContainer (m_values) using emplace_back at each insertion of a new + * element. Another structure (m_buckets of type std::vector) will + * serve as buckets array for the hash table part. Each bucket stores an index + * which corresponds to the index in m_values where the bucket's value is and + * the (truncated) hash of this value. An index is used instead of a pointer to + * the value to reduce the size of each bucket entry. + * + * To resolve collisions in the buckets array, the structures use robin hood + * linear probing with backward shift deletion. + */ +template +class ordered_hash : private Hash, private KeyEqual { +private: + template + using has_mapped_type = + typename std::integral_constant::value>; + + static_assert( + std::is_same::value, + "ValueTypeContainer::value_type != ValueType. " + "Check that the ValueTypeContainer has 'Key' as type for a set or " + "'std::pair' as type for a map."); + + static_assert(std::is_same::value, + "ValueTypeContainer::allocator_type != Allocator. " + "Check that the allocator for ValueTypeContainer is the same " + "as Allocator."); + + static_assert(std::is_same::value, + "Allocator::value_type != ValueType. " + "Check that the allocator has 'Key' as type for a set or " + "'std::pair' as type for a map."); + +public: + template class ordered_iterator; + + using key_type = typename KeySelect::key_type; + using value_type = ValueType; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using hasher = Hash; + using key_equal = KeyEqual; + using allocator_type = Allocator; + using reference = value_type &; + using const_reference = const value_type &; + using pointer = value_type *; + using const_pointer = const value_type *; + using iterator = ordered_iterator; + using const_iterator = ordered_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + using values_container_type = ValueTypeContainer; + +public: + template class ordered_iterator { + friend class ordered_hash; + + private: + using iterator = typename std::conditional< + IsConst, typename values_container_type::const_iterator, + typename values_container_type::iterator>::type; + + ordered_iterator(iterator it) noexcept : m_iterator(it) {} + + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = const typename ordered_hash::value_type; + using difference_type = typename iterator::difference_type; + using reference = value_type &; + using pointer = value_type *; + + ordered_iterator() noexcept {} + + // Copy constructor from iterator to const_iterator. + template ::type * = nullptr> + ordered_iterator(const ordered_iterator &other) noexcept + : m_iterator(other.m_iterator) {} + + ordered_iterator(const ordered_iterator &other) = default; + ordered_iterator(ordered_iterator &&other) = default; + ordered_iterator &operator=(const ordered_iterator &other) = default; + ordered_iterator &operator=(ordered_iterator &&other) = default; + + const typename ordered_hash::key_type &key() const { + return KeySelect()(*m_iterator); + } + + template ::value && + IsConst>::type * = nullptr> + const typename U::value_type &value() const { + return U()(*m_iterator); + } + + template ::value && + !IsConst>::type * = nullptr> + typename U::value_type &value() { + return U()(*m_iterator); + } + + reference operator*() const { return *m_iterator; } + pointer operator->() const { return m_iterator.operator->(); } + + ordered_iterator &operator++() { + ++m_iterator; + return *this; + } + ordered_iterator &operator--() { + --m_iterator; + return *this; + } + + ordered_iterator operator++(int) { + ordered_iterator tmp(*this); + ++(*this); + return tmp; + } + ordered_iterator operator--(int) { + ordered_iterator tmp(*this); + --(*this); + return tmp; + } + + reference operator[](difference_type n) const { return m_iterator[n]; } + + ordered_iterator &operator+=(difference_type n) { + m_iterator += n; + return *this; + } + ordered_iterator &operator-=(difference_type n) { + m_iterator -= n; + return *this; + } + + ordered_iterator operator+(difference_type n) { + ordered_iterator tmp(*this); + tmp += n; + return tmp; + } + ordered_iterator operator-(difference_type n) { + ordered_iterator tmp(*this); + tmp -= n; + return tmp; + } + + friend bool operator==(const ordered_iterator &lhs, + const ordered_iterator &rhs) { + return lhs.m_iterator == rhs.m_iterator; + } + + friend bool operator!=(const ordered_iterator &lhs, + const ordered_iterator &rhs) { + return lhs.m_iterator != rhs.m_iterator; + } + + friend bool operator<(const ordered_iterator &lhs, + const ordered_iterator &rhs) { + return lhs.m_iterator < rhs.m_iterator; + } + + friend bool operator>(const ordered_iterator &lhs, + const ordered_iterator &rhs) { + return lhs.m_iterator > rhs.m_iterator; + } + + friend bool operator<=(const ordered_iterator &lhs, + const ordered_iterator &rhs) { + return lhs.m_iterator <= rhs.m_iterator; + } + + friend bool operator>=(const ordered_iterator &lhs, + const ordered_iterator &rhs) { + return lhs.m_iterator >= rhs.m_iterator; + } + + friend ordered_iterator operator+(difference_type n, + const ordered_iterator &it) { + return n + it.m_iterator; + } + + friend difference_type operator-(const ordered_iterator &lhs, + const ordered_iterator &rhs) { + return lhs.m_iterator - rhs.m_iterator; + } + + private: + iterator m_iterator; + }; + +private: + using bucket_entry = tsl::detail_ordered_hash::bucket_entry; + + using buckets_container_allocator = typename std::allocator_traits< + allocator_type>::template rebind_alloc; + + using buckets_container_type = + std::vector; + + using truncated_hash_type = typename bucket_entry::truncated_hash_type; + using index_type = typename bucket_entry::index_type; + +public: + ordered_hash(size_type bucket_count, const Hash &hash, const KeyEqual &equal, + const Allocator &alloc, float max_load_factor) + : Hash(hash), KeyEqual(equal), m_buckets_data(alloc), + m_buckets(static_empty_bucket_ptr()), m_hash_mask(0), m_values(alloc), + m_grow_on_next_insert(false) { + if (bucket_count > max_bucket_count()) { + TSL_OH_THROW_OR_TERMINATE(std::length_error, + "The map exceeds its maxmimum size."); + } + + if (bucket_count > 0) { + bucket_count = round_up_to_power_of_two(bucket_count); + + m_buckets_data.resize(bucket_count); + m_buckets = m_buckets_data.data(), m_hash_mask = bucket_count - 1; + } + + this->max_load_factor(max_load_factor); + } + + ordered_hash(const ordered_hash &other) + : Hash(other), KeyEqual(other), m_buckets_data(other.m_buckets_data), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() + : m_buckets_data.data()), + m_hash_mask(other.m_hash_mask), m_values(other.m_values), + m_load_threshold(other.m_load_threshold), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert) {} + + ordered_hash(ordered_hash &&other) noexcept( + std::is_nothrow_move_constructible< + Hash>::value &&std::is_nothrow_move_constructible::value + &&std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value) + : Hash(std::move(static_cast(other))), + KeyEqual(std::move(static_cast(other))), + m_buckets_data(std::move(other.m_buckets_data)), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() + : m_buckets_data.data()), + m_hash_mask(other.m_hash_mask), m_values(std::move(other.m_values)), + m_load_threshold(other.m_load_threshold), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert) { + other.m_buckets_data.clear(); + other.m_buckets = static_empty_bucket_ptr(); + other.m_hash_mask = 0; + other.m_values.clear(); + other.m_load_threshold = 0; + other.m_grow_on_next_insert = false; + } + + ordered_hash &operator=(const ordered_hash &other) { + if (&other != this) { + Hash::operator=(other); + KeyEqual::operator=(other); + + m_buckets_data = other.m_buckets_data; + m_buckets = m_buckets_data.empty() ? static_empty_bucket_ptr() + : m_buckets_data.data(); + + m_hash_mask = other.m_hash_mask; + m_values = other.m_values; + m_load_threshold = other.m_load_threshold; + m_max_load_factor = other.m_max_load_factor; + m_grow_on_next_insert = other.m_grow_on_next_insert; + } + + return *this; + } + + ordered_hash &operator=(ordered_hash &&other) { + other.swap(*this); + other.clear(); + + return *this; + } + + allocator_type get_allocator() const { return m_values.get_allocator(); } + + /* + * Iterators + */ + iterator begin() noexcept { return iterator(m_values.begin()); } + + const_iterator begin() const noexcept { return cbegin(); } + + const_iterator cbegin() const noexcept { + return const_iterator(m_values.cbegin()); + } + + iterator end() noexcept { return iterator(m_values.end()); } + + const_iterator end() const noexcept { return cend(); } + + const_iterator cend() const noexcept { + return const_iterator(m_values.cend()); + } + + reverse_iterator rbegin() noexcept { + return reverse_iterator(m_values.end()); + } + + const_reverse_iterator rbegin() const noexcept { return rcbegin(); } + + const_reverse_iterator rcbegin() const noexcept { + return const_reverse_iterator(m_values.cend()); + } + + reverse_iterator rend() noexcept { + return reverse_iterator(m_values.begin()); + } + + const_reverse_iterator rend() const noexcept { return rcend(); } + + const_reverse_iterator rcend() const noexcept { + return const_reverse_iterator(m_values.cbegin()); + } + + /* + * Capacity + */ + bool empty() const noexcept { return m_values.empty(); } + + size_type size() const noexcept { return m_values.size(); } + + size_type max_size() const noexcept { + return std::min(bucket_entry::max_size(), m_values.max_size()); + } + + /* + * Modifiers + */ + void clear() noexcept { + for (auto &bucket : m_buckets_data) { + bucket.clear(); + } + + m_values.clear(); + m_grow_on_next_insert = false; + } + + template std::pair insert(P &&value) { + return insert_impl(KeySelect()(value), std::forward

(value)); + } + + template iterator insert_hint(const_iterator hint, P &&value) { + if (hint != cend() && + compare_keys(KeySelect()(*hint), KeySelect()(value))) { + return mutable_iterator(hint); + } + + return insert(std::forward

(value)).first; + } + + template void insert(InputIt first, InputIt last) { + if (std::is_base_of< + std::forward_iterator_tag, + typename std::iterator_traits::iterator_category>::value) { + const auto nb_elements_insert = std::distance(first, last); + const size_type nb_free_buckets = m_load_threshold - size(); + tsl_oh_assert(m_load_threshold >= size()); + + if (nb_elements_insert > 0 && + nb_free_buckets < size_type(nb_elements_insert)) { + reserve(size() + size_type(nb_elements_insert)); + } + } + + for (; first != last; ++first) { + insert(*first); + } + } + + template + std::pair insert_or_assign(K &&key, M &&value) { + auto it = try_emplace(std::forward(key), std::forward(value)); + if (!it.second) { + it.first.value() = std::forward(value); + } + + return it; + } + + template + iterator insert_or_assign(const_iterator hint, K &&key, M &&obj) { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + auto it = mutable_iterator(hint); + it.value() = std::forward(obj); + + return it; + } + + return insert_or_assign(std::forward(key), std::forward(obj)).first; + } + + template std::pair emplace(Args &&... args) { + return insert(value_type(std::forward(args)...)); + } + + template + iterator emplace_hint(const_iterator hint, Args &&... args) { + return insert_hint(hint, value_type(std::forward(args)...)); + } + + template + std::pair try_emplace(K &&key, Args &&... value_args) { + return insert_impl( + key, std::piecewise_construct, + std::forward_as_tuple(std::forward(key)), + std::forward_as_tuple(std::forward(value_args)...)); + } + + template + iterator try_emplace_hint(const_iterator hint, K &&key, Args &&... args) { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + return mutable_iterator(hint); + } + + return try_emplace(std::forward(key), std::forward(args)...).first; + } + + /** + * Here to avoid `template size_type erase(const K& key)` being used + * when we use an `iterator` instead of a `const_iterator`. + */ + iterator erase(iterator pos) { return erase(const_iterator(pos)); } + + iterator erase(const_iterator pos) { + tsl_oh_assert(pos != cend()); + + const std::size_t index_erase = iterator_to_index(pos); + + auto it_bucket = find_key(pos.key(), hash_key(pos.key())); + tsl_oh_assert(it_bucket != m_buckets_data.end()); + + erase_value_from_bucket(it_bucket); + + /* + * One element was removed from m_values, due to the left shift the next + * element is now at the position of the previous element (or end if none). + */ + return begin() + index_erase; + } + + iterator erase(const_iterator first, const_iterator last) { + if (first == last) { + return mutable_iterator(first); + } + + tsl_oh_assert(std::distance(first, last) > 0); + const std::size_t start_index = iterator_to_index(first); + const std::size_t nb_values = std::size_t(std::distance(first, last)); + const std::size_t end_index = start_index + nb_values; + + // Delete all values +#ifdef TSL_OH_NO_CONTAINER_ERASE_CONST_ITERATOR + auto next_it = m_values.erase(mutable_iterator(first).m_iterator, + mutable_iterator(last).m_iterator); +#else + auto next_it = m_values.erase(first.m_iterator, last.m_iterator); +#endif + + /* + * Mark the buckets corresponding to the values as empty and do a backward + * shift. + * + * Also, the erase operation on m_values has shifted all the values on the + * right of last.m_iterator. Adapt the indexes for these values. + */ + std::size_t ibucket = 0; + while (ibucket < m_buckets_data.size()) { + if (m_buckets[ibucket].empty()) { + ibucket++; + } else if (m_buckets[ibucket].index() >= start_index && + m_buckets[ibucket].index() < end_index) { + m_buckets[ibucket].clear(); + backward_shift(ibucket); + // Don't increment ibucket, backward_shift may have replaced current + // bucket. + } else if (m_buckets[ibucket].index() >= end_index) { + m_buckets[ibucket].set_index( + index_type(m_buckets[ibucket].index() - nb_values)); + ibucket++; + } else { + ibucket++; + } + } + + return iterator(next_it); + } + + template size_type erase(const K &key) { + return erase(key, hash_key(key)); + } + + template size_type erase(const K &key, std::size_t hash) { + return erase_impl(key, hash); + } + + void swap(ordered_hash &other) { + using std::swap; + + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + swap(m_buckets_data, other.m_buckets_data); + swap(m_buckets, other.m_buckets); + swap(m_hash_mask, other.m_hash_mask); + swap(m_values, other.m_values); + swap(m_load_threshold, other.m_load_threshold); + swap(m_max_load_factor, other.m_max_load_factor); + swap(m_grow_on_next_insert, other.m_grow_on_next_insert); + } + + /* + * Lookup + */ + template < + class K, class U = ValueSelect, + typename std::enable_if::value>::type * = nullptr> + typename U::value_type &at(const K &key) { + return at(key, hash_key(key)); + } + + template < + class K, class U = ValueSelect, + typename std::enable_if::value>::type * = nullptr> + typename U::value_type &at(const K &key, std::size_t hash) { + return const_cast( + static_cast(this)->at(key, hash)); + } + + template < + class K, class U = ValueSelect, + typename std::enable_if::value>::type * = nullptr> + const typename U::value_type &at(const K &key) const { + return at(key, hash_key(key)); + } + + template < + class K, class U = ValueSelect, + typename std::enable_if::value>::type * = nullptr> + const typename U::value_type &at(const K &key, std::size_t hash) const { + auto it = find(key, hash); + if (it != end()) { + return it.value(); + } else { + TSL_OH_THROW_OR_TERMINATE(std::out_of_range, "Couldn't find the key."); + } + } + + template < + class K, class U = ValueSelect, + typename std::enable_if::value>::type * = nullptr> + typename U::value_type &operator[](K &&key) { + return try_emplace(std::forward(key)).first.value(); + } + + template size_type count(const K &key) const { + return count(key, hash_key(key)); + } + + template size_type count(const K &key, std::size_t hash) const { + if (find(key, hash) == cend()) { + return 0; + } else { + return 1; + } + } + + template iterator find(const K &key) { + return find(key, hash_key(key)); + } + + template iterator find(const K &key, std::size_t hash) { + auto it_bucket = find_key(key, hash); + return (it_bucket != m_buckets_data.end()) + ? iterator(m_values.begin() + it_bucket->index()) + : end(); + } + + template const_iterator find(const K &key) const { + return find(key, hash_key(key)); + } + + template const_iterator find(const K &key, std::size_t hash) const { + auto it_bucket = find_key(key, hash); + return (it_bucket != m_buckets_data.cend()) + ? const_iterator(m_values.begin() + it_bucket->index()) + : end(); + } + + template std::pair equal_range(const K &key) { + return equal_range(key, hash_key(key)); + } + + template + std::pair equal_range(const K &key, std::size_t hash) { + iterator it = find(key, hash); + return std::make_pair(it, (it == end()) ? it : std::next(it)); + } + + template + std::pair equal_range(const K &key) const { + return equal_range(key, hash_key(key)); + } + + template + std::pair + equal_range(const K &key, std::size_t hash) const { + const_iterator it = find(key, hash); + return std::make_pair(it, (it == cend()) ? it : std::next(it)); + } + + /* + * Bucket interface + */ + size_type bucket_count() const { return m_buckets_data.size(); } + + size_type max_bucket_count() const { return m_buckets_data.max_size(); } + + /* + * Hash policy + */ + float load_factor() const { + if (bucket_count() == 0) { + return 0; + } + + return float(size()) / float(bucket_count()); + } + + float max_load_factor() const { return m_max_load_factor; } + + void max_load_factor(float ml) { + m_max_load_factor = clamp(ml, float(MAX_LOAD_FACTOR__MINIMUM), + float(MAX_LOAD_FACTOR__MAXIMUM)); + + m_max_load_factor = ml; + m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor); + } + + void rehash(size_type count) { + count = std::max(count, + size_type(std::ceil(float(size()) / max_load_factor()))); + rehash_impl(count); + } + + void reserve(size_type count) { + reserve_space_for_values(count); + + count = size_type(std::ceil(float(count) / max_load_factor())); + rehash(count); + } + + /* + * Observers + */ + hasher hash_function() const { return static_cast(*this); } + + key_equal key_eq() const { return static_cast(*this); } + + /* + * Other + */ + iterator mutable_iterator(const_iterator pos) { + return iterator(m_values.begin() + iterator_to_index(pos)); + } + + iterator nth(size_type index) { + tsl_oh_assert(index <= size()); + return iterator(m_values.begin() + index); + } + + const_iterator nth(size_type index) const { + tsl_oh_assert(index <= size()); + return const_iterator(m_values.cbegin() + index); + } + + const_reference front() const { + tsl_oh_assert(!empty()); + return m_values.front(); + } + + const_reference back() const { + tsl_oh_assert(!empty()); + return m_values.back(); + } + + const values_container_type &values_container() const noexcept { + return m_values; + } + + template ::value>::type * = nullptr> + const typename values_container_type::value_type *data() const noexcept { + return m_values.data(); + } + + template ::value>::type * = nullptr> + size_type capacity() const noexcept { + return m_values.capacity(); + } + + void shrink_to_fit() { m_values.shrink_to_fit(); } + + template + std::pair insert_at_position(const_iterator pos, P &&value) { + return insert_at_position_impl(pos.m_iterator, KeySelect()(value), + std::forward

(value)); + } + + template + std::pair emplace_at_position(const_iterator pos, + Args &&... args) { + return insert_at_position(pos, value_type(std::forward(args)...)); + } + + template + std::pair try_emplace_at_position(const_iterator pos, K &&key, + Args &&... value_args) { + return insert_at_position_impl( + pos.m_iterator, key, std::piecewise_construct, + std::forward_as_tuple(std::forward(key)), + std::forward_as_tuple(std::forward(value_args)...)); + } + + void pop_back() { + tsl_oh_assert(!empty()); + erase(std::prev(end())); + } + + /** + * Here to avoid `template size_type unordered_erase(const K& key)` + * being used when we use a iterator instead of a const_iterator. + */ + iterator unordered_erase(iterator pos) { + return unordered_erase(const_iterator(pos)); + } + + iterator unordered_erase(const_iterator pos) { + const std::size_t index_erase = iterator_to_index(pos); + unordered_erase(pos.key()); + + /* + * One element was deleted, index_erase now points to the next element as + * the elements after the deleted value were shifted to the left in m_values + * (will be end() if we deleted the last element). + */ + return begin() + index_erase; + } + + template size_type unordered_erase(const K &key) { + return unordered_erase(key, hash_key(key)); + } + + template size_type unordered_erase(const K &key, std::size_t hash) { + auto it_bucket_key = find_key(key, hash); + if (it_bucket_key == m_buckets_data.end()) { + return 0; + } + + /** + * If we are not erasing the last element in m_values, we swap + * the element we are erasing with the last element. We then would + * just have to do a pop_back() in m_values. + */ + if (!compare_keys(key, KeySelect()(back()))) { + auto it_bucket_last_elem = + find_key(KeySelect()(back()), hash_key(KeySelect()(back()))); + tsl_oh_assert(it_bucket_last_elem != m_buckets_data.end()); + tsl_oh_assert(it_bucket_last_elem->index() == m_values.size() - 1); + + using std::swap; + swap(m_values[it_bucket_key->index()], + m_values[it_bucket_last_elem->index()]); + swap(it_bucket_key->index_ref(), it_bucket_last_elem->index_ref()); + } + + erase_value_from_bucket(it_bucket_key); + + return 1; + } + + template void serialize(Serializer &serializer) const { + serialize_impl(serializer); + } + + template + void deserialize(Deserializer &deserializer, bool hash_compatible) { + deserialize_impl(deserializer, hash_compatible); + } + + friend bool operator==(const ordered_hash &lhs, const ordered_hash &rhs) { + return lhs.m_values == rhs.m_values; + } + + friend bool operator!=(const ordered_hash &lhs, const ordered_hash &rhs) { + return lhs.m_values != rhs.m_values; + } + + friend bool operator<(const ordered_hash &lhs, const ordered_hash &rhs) { + return lhs.m_values < rhs.m_values; + } + + friend bool operator<=(const ordered_hash &lhs, const ordered_hash &rhs) { + return lhs.m_values <= rhs.m_values; + } + + friend bool operator>(const ordered_hash &lhs, const ordered_hash &rhs) { + return lhs.m_values > rhs.m_values; + } + + friend bool operator>=(const ordered_hash &lhs, const ordered_hash &rhs) { + return lhs.m_values >= rhs.m_values; + } + +private: + template std::size_t hash_key(const K &key) const { + return Hash::operator()(key); + } + + template + bool compare_keys(const K1 &key1, const K2 &key2) const { + return KeyEqual::operator()(key1, key2); + } + + template + typename buckets_container_type::iterator find_key(const K &key, + std::size_t hash) { + auto it = static_cast(this)->find_key(key, hash); + return m_buckets_data.begin() + std::distance(m_buckets_data.cbegin(), it); + } + + /** + * Return bucket which has the key 'key' or m_buckets_data.end() if none. + * + * From the bucket_for_hash, search for the value until we either find an + * empty bucket or a bucket which has a value with a distance from its ideal + * bucket longer than the probe length for the value we are looking for. + */ + template + typename buckets_container_type::const_iterator + find_key(const K &key, std::size_t hash) const { + for (std::size_t ibucket = bucket_for_hash(hash), + dist_from_ideal_bucket = 0; + ; ibucket = next_bucket(ibucket), dist_from_ideal_bucket++) { + if (m_buckets[ibucket].empty()) { + return m_buckets_data.end(); + } else if (m_buckets[ibucket].truncated_hash() == + bucket_entry::truncate_hash(hash) && + compare_keys( + key, KeySelect()(m_values[m_buckets[ibucket].index()]))) { + return m_buckets_data.begin() + ibucket; + } else if (dist_from_ideal_bucket > distance_from_ideal_bucket(ibucket)) { + return m_buckets_data.end(); + } + } + } + + void rehash_impl(size_type bucket_count) { + tsl_oh_assert(bucket_count >= + size_type(std::ceil(float(size()) / max_load_factor()))); + + if (bucket_count > max_bucket_count()) { + TSL_OH_THROW_OR_TERMINATE(std::length_error, + "The map exceeds its maxmimum size."); + } + + if (bucket_count > 0) { + bucket_count = round_up_to_power_of_two(bucket_count); + } + + if (bucket_count == this->bucket_count()) { + return; + } + + buckets_container_type old_buckets(bucket_count); + m_buckets_data.swap(old_buckets); + m_buckets = m_buckets_data.empty() ? static_empty_bucket_ptr() + : m_buckets_data.data(); + // Everything should be noexcept from here. + + m_hash_mask = (bucket_count > 0) ? (bucket_count - 1) : 0; + this->max_load_factor(m_max_load_factor); + m_grow_on_next_insert = false; + + for (const bucket_entry &old_bucket : old_buckets) { + if (old_bucket.empty()) { + continue; + } + + truncated_hash_type insert_hash = old_bucket.truncated_hash(); + index_type insert_index = old_bucket.index(); + + for (std::size_t ibucket = bucket_for_hash(insert_hash), + dist_from_ideal_bucket = 0; + ; ibucket = next_bucket(ibucket), dist_from_ideal_bucket++) { + if (m_buckets[ibucket].empty()) { + m_buckets[ibucket].set_index(insert_index); + m_buckets[ibucket].set_hash(insert_hash); + break; + } + + const std::size_t distance = distance_from_ideal_bucket(ibucket); + if (dist_from_ideal_bucket > distance) { + std::swap(insert_index, m_buckets[ibucket].index_ref()); + std::swap(insert_hash, m_buckets[ibucket].truncated_hash_ref()); + dist_from_ideal_bucket = distance; + } + } + } + } + + template ::value>::type * = nullptr> + void reserve_space_for_values(size_type count) { + m_values.reserve(count); + } + + template ::value>::type * = nullptr> + void reserve_space_for_values(size_type /*count*/) {} + + /** + * Swap the empty bucket with the values on its right until we cross another + * empty bucket or if the other bucket has a distance_from_ideal_bucket == 0. + */ + void backward_shift(std::size_t empty_ibucket) noexcept { + tsl_oh_assert(m_buckets[empty_ibucket].empty()); + + std::size_t previous_ibucket = empty_ibucket; + for (std::size_t current_ibucket = next_bucket(previous_ibucket); + !m_buckets[current_ibucket].empty() && + distance_from_ideal_bucket(current_ibucket) > 0; + previous_ibucket = current_ibucket, + current_ibucket = next_bucket(current_ibucket)) { + std::swap(m_buckets[current_ibucket], m_buckets[previous_ibucket]); + } + } + + void + erase_value_from_bucket(typename buckets_container_type::iterator it_bucket) { + tsl_oh_assert(it_bucket != m_buckets_data.end() && !it_bucket->empty()); + + m_values.erase(m_values.begin() + it_bucket->index()); + + /* + * m_values.erase shifted all the values on the right of the erased value, + * shift the indexes by -1 in the buckets array for these values. + */ + if (it_bucket->index() != m_values.size()) { + shift_indexes_in_buckets(it_bucket->index(), -1); + } + + // Mark the bucket as empty and do a backward shift of the values on the + // right + it_bucket->clear(); + backward_shift( + std::size_t(std::distance(m_buckets_data.begin(), it_bucket))); + } + + /** + * Go through each value from [from_ivalue, m_values.size()) in m_values and + * for each bucket corresponding to the value, shift the index by delta. + * + * delta must be equal to 1 or -1. + */ + void shift_indexes_in_buckets(index_type from_ivalue, int delta) noexcept { + tsl_oh_assert(delta == 1 || delta == -1); + + for (std::size_t ivalue = from_ivalue; ivalue < m_values.size(); ivalue++) { + // All the values in m_values have been shifted by delta. Find the bucket + // corresponding to the value m_values[ivalue] + const index_type old_index = static_cast(ivalue - delta); + + std::size_t ibucket = + bucket_for_hash(hash_key(KeySelect()(m_values[ivalue]))); + while (m_buckets[ibucket].index() != old_index) { + ibucket = next_bucket(ibucket); + } + + m_buckets[ibucket].set_index(index_type(ivalue)); + } + } + + template size_type erase_impl(const K &key, std::size_t hash) { + auto it_bucket = find_key(key, hash); + if (it_bucket != m_buckets_data.end()) { + erase_value_from_bucket(it_bucket); + + return 1; + } else { + return 0; + } + } + + /** + * Insert the element at the end. + */ + template + std::pair insert_impl(const K &key, + Args &&... value_type_args) { + const std::size_t hash = hash_key(key); + + std::size_t ibucket = bucket_for_hash(hash); + std::size_t dist_from_ideal_bucket = 0; + + while (!m_buckets[ibucket].empty() && + dist_from_ideal_bucket <= distance_from_ideal_bucket(ibucket)) { + if (m_buckets[ibucket].truncated_hash() == + bucket_entry::truncate_hash(hash) && + compare_keys(key, + KeySelect()(m_values[m_buckets[ibucket].index()]))) { + return std::make_pair(begin() + m_buckets[ibucket].index(), false); + } + + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } + + if (size() >= max_size()) { + TSL_OH_THROW_OR_TERMINATE( + std::length_error, "We reached the maximum size for the hash table."); + } + + if (grow_on_high_load()) { + ibucket = bucket_for_hash(hash); + dist_from_ideal_bucket = 0; + } + + m_values.emplace_back(std::forward(value_type_args)...); + insert_index(ibucket, dist_from_ideal_bucket, + index_type(m_values.size() - 1), + bucket_entry::truncate_hash(hash)); + + return std::make_pair(std::prev(end()), true); + } + + /** + * Insert the element before insert_position. + */ + template + std::pair insert_at_position_impl( + typename values_container_type::const_iterator insert_position, + const K &key, Args &&... value_type_args) { + const std::size_t hash = hash_key(key); + + std::size_t ibucket = bucket_for_hash(hash); + std::size_t dist_from_ideal_bucket = 0; + + while (!m_buckets[ibucket].empty() && + dist_from_ideal_bucket <= distance_from_ideal_bucket(ibucket)) { + if (m_buckets[ibucket].truncated_hash() == + bucket_entry::truncate_hash(hash) && + compare_keys(key, + KeySelect()(m_values[m_buckets[ibucket].index()]))) { + return std::make_pair(begin() + m_buckets[ibucket].index(), false); + } + + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } + + if (size() >= max_size()) { + TSL_OH_THROW_OR_TERMINATE( + std::length_error, "We reached the maximum size for the hash table."); + } + + if (grow_on_high_load()) { + ibucket = bucket_for_hash(hash); + dist_from_ideal_bucket = 0; + } + + const index_type index_insert_position = + index_type(std::distance(m_values.cbegin(), insert_position)); + +#ifdef TSL_OH_NO_CONTAINER_EMPLACE_CONST_ITERATOR + m_values.emplace(m_values.begin() + + std::distance(m_values.cbegin(), insert_position), + std::forward(value_type_args)...); +#else + m_values.emplace(insert_position, std::forward(value_type_args)...); +#endif + + insert_index(ibucket, dist_from_ideal_bucket, index_insert_position, + bucket_entry::truncate_hash(hash)); + + /* + * The insertion didn't happend at the end of the m_values container, + * we need to shift the indexes in m_buckets_data. + */ + if (index_insert_position != m_values.size() - 1) { + shift_indexes_in_buckets(index_insert_position + 1, 1); + } + + return std::make_pair(iterator(m_values.begin() + index_insert_position), + true); + } + + void insert_index(std::size_t ibucket, std::size_t dist_from_ideal_bucket, + index_type index_insert, + truncated_hash_type hash_insert) noexcept { + while (!m_buckets[ibucket].empty()) { + const std::size_t distance = distance_from_ideal_bucket(ibucket); + if (dist_from_ideal_bucket > distance) { + std::swap(index_insert, m_buckets[ibucket].index_ref()); + std::swap(hash_insert, m_buckets[ibucket].truncated_hash_ref()); + + dist_from_ideal_bucket = distance; + } + + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + + if (dist_from_ideal_bucket > REHASH_ON_HIGH_NB_PROBES__NPROBES && + !m_grow_on_next_insert && + load_factor() >= REHASH_ON_HIGH_NB_PROBES__MIN_LOAD_FACTOR) { + // We don't want to grow the map now as we need this method to be + // noexcept. Do it on next insert. + m_grow_on_next_insert = true; + } + } + + m_buckets[ibucket].set_index(index_insert); + m_buckets[ibucket].set_hash(hash_insert); + } + + std::size_t distance_from_ideal_bucket(std::size_t ibucket) const noexcept { + const std::size_t ideal_bucket = + bucket_for_hash(m_buckets[ibucket].truncated_hash()); + + if (ibucket >= ideal_bucket) { + return ibucket - ideal_bucket; + } + // If the bucket is smaller than the ideal bucket for the value, there was a + // wrapping at the end of the bucket array due to the modulo. + else { + return (bucket_count() + ibucket) - ideal_bucket; + } + } + + std::size_t next_bucket(std::size_t index) const noexcept { + tsl_oh_assert(index < m_buckets_data.size()); + + index++; + return (index < m_buckets_data.size()) ? index : 0; + } + + std::size_t bucket_for_hash(std::size_t hash) const noexcept { + return hash & m_hash_mask; + } + + std::size_t iterator_to_index(const_iterator it) const noexcept { + const auto dist = std::distance(cbegin(), it); + tsl_oh_assert(dist >= 0); + + return std::size_t(dist); + } + + /** + * Return true if the map has been rehashed. + */ + bool grow_on_high_load() { + if (m_grow_on_next_insert || size() >= m_load_threshold) { + rehash_impl(std::max(size_type(1), bucket_count() * 2)); + m_grow_on_next_insert = false; + + return true; + } else { + return false; + } + } + + template + void serialize_impl(Serializer &serializer) const { + const slz_size_type version = SERIALIZATION_PROTOCOL_VERSION; + serializer(version); + + const slz_size_type nb_elements = m_values.size(); + serializer(nb_elements); + + const slz_size_type bucket_count = m_buckets_data.size(); + serializer(bucket_count); + + const float max_load_factor = m_max_load_factor; + serializer(max_load_factor); + + for (const value_type &value : m_values) { + serializer(value); + } + + for (const bucket_entry &bucket : m_buckets_data) { + bucket.serialize(serializer); + } + } + + template + void deserialize_impl(Deserializer &deserializer, bool hash_compatible) { + tsl_oh_assert(m_buckets_data.empty()); // Current hash table must be empty + + const slz_size_type version = + deserialize_value(deserializer); + // For now we only have one version of the serialization protocol. + // If it doesn't match there is a problem with the file. + if (version != SERIALIZATION_PROTOCOL_VERSION) { + TSL_OH_THROW_OR_TERMINATE(std::runtime_error, + "Can't deserialize the ordered_map/set. " + "The protocol version header is invalid."); + } + + const slz_size_type nb_elements = + deserialize_value(deserializer); + const slz_size_type bucket_count_ds = + deserialize_value(deserializer); + const float max_load_factor = deserialize_value(deserializer); + + if (max_load_factor < MAX_LOAD_FACTOR__MINIMUM || + max_load_factor > MAX_LOAD_FACTOR__MAXIMUM) { + TSL_OH_THROW_OR_TERMINATE( + std::runtime_error, + "Invalid max_load_factor. Check that the serializer " + "and deserializer support floats correctly as they " + "can be converted implicitly to ints."); + } + + this->max_load_factor(max_load_factor); + + if (bucket_count_ds == 0) { + tsl_oh_assert(nb_elements == 0); + return; + } + + if (!hash_compatible) { + reserve(numeric_cast(nb_elements, + "Deserialized nb_elements is too big.")); + for (slz_size_type el = 0; el < nb_elements; el++) { + insert(deserialize_value(deserializer)); + } + } else { + m_buckets_data.reserve(numeric_cast( + bucket_count_ds, "Deserialized bucket_count is too big.")); + m_buckets = m_buckets_data.data(), + m_hash_mask = m_buckets_data.capacity() - 1; + + reserve_space_for_values(numeric_cast( + nb_elements, "Deserialized nb_elements is too big.")); + for (slz_size_type el = 0; el < nb_elements; el++) { + m_values.push_back(deserialize_value(deserializer)); + } + + for (slz_size_type b = 0; b < bucket_count_ds; b++) { + m_buckets_data.push_back(bucket_entry::deserialize(deserializer)); + } + } + } + + static std::size_t round_up_to_power_of_two(std::size_t value) { + if (is_power_of_two(value)) { + return value; + } + + if (value == 0) { + return 1; + } + + --value; + for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { + value |= value >> i; + } + + return value + 1; + } + + static constexpr bool is_power_of_two(std::size_t value) { + return value != 0 && (value & (value - 1)) == 0; + } + +public: + static const size_type DEFAULT_INIT_BUCKETS_SIZE = 0; + static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.75f; + +private: + static constexpr float MAX_LOAD_FACTOR__MINIMUM = 0.1f; + static constexpr float MAX_LOAD_FACTOR__MAXIMUM = 0.95f; + + static const size_type REHASH_ON_HIGH_NB_PROBES__NPROBES = 128; + static constexpr float REHASH_ON_HIGH_NB_PROBES__MIN_LOAD_FACTOR = 0.15f; + + /** + * Protocol version currenlty used for serialization. + */ + static const slz_size_type SERIALIZATION_PROTOCOL_VERSION = 1; + + /** + * Return an always valid pointer to an static empty bucket_entry with + * last_bucket() == true. + */ + bucket_entry *static_empty_bucket_ptr() { + static bucket_entry empty_bucket; + return &empty_bucket; + } + +private: + buckets_container_type m_buckets_data; + + /** + * Points to m_buckets_data.data() if !m_buckets_data.empty() otherwise points + * to static_empty_bucket_ptr. This variable is useful to avoid the cost of + * checking if m_buckets_data is empty when trying to find an element. + * + * TODO Remove m_buckets_data and only use a pointer+size instead of a + * pointer+vector to save some space in the ordered_hash object. + */ + bucket_entry *m_buckets; + + size_type m_hash_mask; + + values_container_type m_values; + + size_type m_load_threshold; + float m_max_load_factor; + + bool m_grow_on_next_insert; +}; + +} // end namespace detail_ordered_hash + +} // end namespace tsl + +#endif diff --git a/external/tsl/ordered_map.h b/external/tsl/ordered_map.h new file mode 100644 index 0000000..312125c --- /dev/null +++ b/external/tsl/ordered_map.h @@ -0,0 +1,934 @@ +/** + * MIT License + * + * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef TSL_ORDERED_MAP_H +#define TSL_ORDERED_MAP_H + +#include "ordered_hash.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace tsl { + +/** + * Implementation of an hash map using open adressing with robin hood with + * backshift delete to resolve collisions. + * + * The particularity of this hash map is that it remembers the order in which + * the elements were added and provide a way to access the structure which + * stores these values through the 'values_container()' method. The used + * container is defined by ValueTypeContainer, by default a std::deque is used + * (grows faster) but a std::vector may be used. In this case the map provides a + * 'data()' method which give a direct access to the memory used to store the + * values (which can be usefull to communicate with C API's). + * + * The Key and T must be copy constructible and/or move constructible. To use + * `unordered_erase` they both must be swappable. + * + * The behaviour of the hash map is undefinded if the destructor of Key or T + * throws an exception. + * + * By default the maximum size of a map is limited to 2^32 - 1 values, if needed + * this can be changed through the IndexType template parameter. Using an + * `uint64_t` will raise this limit to 2^64 - 1 values but each bucket will use + * 16 bytes instead of 8 bytes in addition to the space needed to store the + * values. + * + * Iterators invalidation: + * - clear, operator=, reserve, rehash: always invalidate the iterators (also + * invalidate end()). + * - insert, emplace, emplace_hint, operator[]: when a std::vector is used as + * ValueTypeContainer and if size() < capacity(), only end(). Otherwise all the + * iterators are invalidated if an insert occurs. + * - erase, unordered_erase: when a std::vector is used as ValueTypeContainer + * invalidate the iterator of the erased element and all the ones after the + * erased element (including end()). Otherwise all the iterators are invalidated + * if an erase occurs. + */ +template , + class KeyEqual = std::equal_to, + class Allocator = std::allocator>, + class ValueTypeContainer = std::deque, Allocator>, + class IndexType = std::uint_least32_t> +class ordered_map { +private: + template + using has_is_transparent = tsl::detail_ordered_hash::has_is_transparent; + + class KeySelect { + public: + using key_type = Key; + + const key_type &operator()(const std::pair &key_value) const + noexcept { + return key_value.first; + } + + key_type &operator()(std::pair &key_value) noexcept { + return key_value.first; + } + }; + + class ValueSelect { + public: + using value_type = T; + + const value_type &operator()(const std::pair &key_value) const + noexcept { + return key_value.second; + } + + value_type &operator()(std::pair &key_value) noexcept { + return key_value.second; + } + }; + + using ht = + detail_ordered_hash::ordered_hash, KeySelect, + ValueSelect, Hash, KeyEqual, Allocator, + ValueTypeContainer, IndexType>; + +public: + using key_type = typename ht::key_type; + using mapped_type = T; + using value_type = typename ht::value_type; + using size_type = typename ht::size_type; + using difference_type = typename ht::difference_type; + using hasher = typename ht::hasher; + using key_equal = typename ht::key_equal; + using allocator_type = typename ht::allocator_type; + using reference = typename ht::reference; + using const_reference = typename ht::const_reference; + using pointer = typename ht::pointer; + using const_pointer = typename ht::const_pointer; + using iterator = typename ht::iterator; + using const_iterator = typename ht::const_iterator; + using reverse_iterator = typename ht::reverse_iterator; + using const_reverse_iterator = typename ht::const_reverse_iterator; + + using values_container_type = typename ht::values_container_type; + + /* + * Constructors + */ + ordered_map() : ordered_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {} + + explicit ordered_map(size_type bucket_count, const Hash &hash = Hash(), + const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR) {} + + ordered_map(size_type bucket_count, const Allocator &alloc) + : ordered_map(bucket_count, Hash(), KeyEqual(), alloc) {} + + ordered_map(size_type bucket_count, const Hash &hash, const Allocator &alloc) + : ordered_map(bucket_count, hash, KeyEqual(), alloc) {} + + explicit ordered_map(const Allocator &alloc) + : ordered_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {} + + template + ordered_map(InputIt first, InputIt last, + size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, + const Hash &hash = Hash(), const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : ordered_map(bucket_count, hash, equal, alloc) { + insert(first, last); + } + + template + ordered_map(InputIt first, InputIt last, size_type bucket_count, + const Allocator &alloc) + : ordered_map(first, last, bucket_count, Hash(), KeyEqual(), alloc) {} + + template + ordered_map(InputIt first, InputIt last, size_type bucket_count, + const Hash &hash, const Allocator &alloc) + : ordered_map(first, last, bucket_count, hash, KeyEqual(), alloc) {} + + ordered_map(std::initializer_list init, + size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, + const Hash &hash = Hash(), const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : ordered_map(init.begin(), init.end(), bucket_count, hash, equal, + alloc) {} + + ordered_map(std::initializer_list init, size_type bucket_count, + const Allocator &alloc) + : ordered_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), + alloc) {} + + ordered_map(std::initializer_list init, size_type bucket_count, + const Hash &hash, const Allocator &alloc) + : ordered_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), + alloc) {} + + ordered_map &operator=(std::initializer_list ilist) { + m_ht.clear(); + + m_ht.reserve(ilist.size()); + m_ht.insert(ilist.begin(), ilist.end()); + + return *this; + } + + allocator_type get_allocator() const { return m_ht.get_allocator(); } + + /* + * Iterators + */ + iterator begin() noexcept { return m_ht.begin(); } + const_iterator begin() const noexcept { return m_ht.begin(); } + const_iterator cbegin() const noexcept { return m_ht.cbegin(); } + + iterator end() noexcept { return m_ht.end(); } + const_iterator end() const noexcept { return m_ht.end(); } + const_iterator cend() const noexcept { return m_ht.cend(); } + + reverse_iterator rbegin() noexcept { return m_ht.rbegin(); } + const_reverse_iterator rbegin() const noexcept { return m_ht.rbegin(); } + const_reverse_iterator rcbegin() const noexcept { return m_ht.rcbegin(); } + + reverse_iterator rend() noexcept { return m_ht.rend(); } + const_reverse_iterator rend() const noexcept { return m_ht.rend(); } + const_reverse_iterator rcend() const noexcept { return m_ht.rcend(); } + + /* + * Capacity + */ + bool empty() const noexcept { return m_ht.empty(); } + size_type size() const noexcept { return m_ht.size(); } + size_type max_size() const noexcept { return m_ht.max_size(); } + + /* + * Modifiers + */ + void clear() noexcept { m_ht.clear(); } + + std::pair insert(const value_type &value) { + return m_ht.insert(value); + } + + template ::value>::type * = nullptr> + std::pair insert(P &&value) { + return m_ht.emplace(std::forward

(value)); + } + + std::pair insert(value_type &&value) { + return m_ht.insert(std::move(value)); + } + + iterator insert(const_iterator hint, const value_type &value) { + return m_ht.insert_hint(hint, value); + } + + template ::value>::type * = nullptr> + iterator insert(const_iterator hint, P &&value) { + return m_ht.emplace_hint(hint, std::forward

(value)); + } + + iterator insert(const_iterator hint, value_type &&value) { + return m_ht.insert_hint(hint, std::move(value)); + } + + template void insert(InputIt first, InputIt last) { + m_ht.insert(first, last); + } + void insert(std::initializer_list ilist) { + m_ht.insert(ilist.begin(), ilist.end()); + } + + template + std::pair insert_or_assign(const key_type &k, M &&obj) { + return m_ht.insert_or_assign(k, std::forward(obj)); + } + + template + std::pair insert_or_assign(key_type &&k, M &&obj) { + return m_ht.insert_or_assign(std::move(k), std::forward(obj)); + } + + template + iterator insert_or_assign(const_iterator hint, const key_type &k, M &&obj) { + return m_ht.insert_or_assign(hint, k, std::forward(obj)); + } + + template + iterator insert_or_assign(const_iterator hint, key_type &&k, M &&obj) { + return m_ht.insert_or_assign(hint, std::move(k), std::forward(obj)); + } + + /** + * Due to the way elements are stored, emplace will need to move or copy the + * key-value once. The method is equivalent to + * insert(value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template std::pair emplace(Args &&... args) { + return m_ht.emplace(std::forward(args)...); + } + + /** + * Due to the way elements are stored, emplace_hint will need to move or copy + * the key-value once. The method is equivalent to insert(hint, + * value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template + iterator emplace_hint(const_iterator hint, Args &&... args) { + return m_ht.emplace_hint(hint, std::forward(args)...); + } + + template + std::pair try_emplace(const key_type &k, Args &&... args) { + return m_ht.try_emplace(k, std::forward(args)...); + } + + template + std::pair try_emplace(key_type &&k, Args &&... args) { + return m_ht.try_emplace(std::move(k), std::forward(args)...); + } + + template + iterator try_emplace(const_iterator hint, const key_type &k, + Args &&... args) { + return m_ht.try_emplace_hint(hint, k, std::forward(args)...); + } + + template + iterator try_emplace(const_iterator hint, key_type &&k, Args &&... args) { + return m_ht.try_emplace_hint(hint, std::move(k), + std::forward(args)...); + } + + /** + * When erasing an element, the insert order will be preserved and no holes + * will be present in the container returned by 'values_container()'. + * + * The method is in O(n), if the order is not important 'unordered_erase(...)' + * method is faster with an O(1) average complexity. + */ + iterator erase(iterator pos) { return m_ht.erase(pos); } + + /** + * @copydoc erase(iterator pos) + */ + iterator erase(const_iterator pos) { return m_ht.erase(pos); } + + /** + * @copydoc erase(iterator pos) + */ + iterator erase(const_iterator first, const_iterator last) { + return m_ht.erase(first, last); + } + + /** + * @copydoc erase(iterator pos) + */ + size_type erase(const key_type &key) { return m_ht.erase(key); } + + /** + * @copydoc erase(iterator pos) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup to the value if you already have the hash. + */ + size_type erase(const key_type &key, std::size_t precalculated_hash) { + return m_ht.erase(key, precalculated_hash); + } + + /** + * @copydoc erase(iterator pos) + * + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type erase(const K &key) { + return m_ht.erase(key); + } + + /** + * @copydoc erase(const key_type& key, std::size_t precalculated_hash) + * + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type erase(const K &key, std::size_t precalculated_hash) { + return m_ht.erase(key, precalculated_hash); + } + + void swap(ordered_map &other) { other.m_ht.swap(m_ht); } + + /* + * Lookup + */ + T &at(const Key &key) { return m_ht.at(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + T &at(const Key &key, std::size_t precalculated_hash) { + return m_ht.at(key, precalculated_hash); + } + + const T &at(const Key &key) const { return m_ht.at(key); } + + /** + * @copydoc at(const Key& key, std::size_t precalculated_hash) + */ + const T &at(const Key &key, std::size_t precalculated_hash) const { + return m_ht.at(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + T &at(const K &key) { + return m_ht.at(key); + } + + /** + * @copydoc at(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + T &at(const K &key, std::size_t precalculated_hash) { + return m_ht.at(key, precalculated_hash); + } + + /** + * @copydoc at(const K& key) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + const T &at(const K &key) const { + return m_ht.at(key); + } + + /** + * @copydoc at(const K& key, std::size_t precalculated_hash) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + const T &at(const K &key, std::size_t precalculated_hash) const { + return m_ht.at(key, precalculated_hash); + } + + T &operator[](const Key &key) { return m_ht[key]; } + T &operator[](Key &&key) { return m_ht[std::move(key)]; } + + size_type count(const Key &key) const { return m_ht.count(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + size_type count(const Key &key, std::size_t precalculated_hash) const { + return m_ht.count(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type count(const K &key) const { + return m_ht.count(key); + } + + /** + * @copydoc count(const K& key) const + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type count(const K &key, std::size_t precalculated_hash) const { + return m_ht.count(key, precalculated_hash); + } + + iterator find(const Key &key) { return m_ht.find(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + iterator find(const Key &key, std::size_t precalculated_hash) { + return m_ht.find(key, precalculated_hash); + } + + const_iterator find(const Key &key) const { return m_ht.find(key); } + + /** + * @copydoc find(const Key& key, std::size_t precalculated_hash) + */ + const_iterator find(const Key &key, std::size_t precalculated_hash) const { + return m_ht.find(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + iterator find(const K &key) { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + iterator find(const K &key, std::size_t precalculated_hash) { + return m_ht.find(key, precalculated_hash); + } + + /** + * @copydoc find(const K& key) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + const_iterator find(const K &key) const { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + const_iterator find(const K &key, std::size_t precalculated_hash) const { + return m_ht.find(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) { + return m_ht.equal_range(key); + } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + std::pair equal_range(const Key &key, + std::size_t precalculated_hash) { + return m_ht.equal_range(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) const { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const Key& key, std::size_t precalculated_hash) + */ + std::pair + equal_range(const Key &key, std::size_t precalculated_hash) const { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair equal_range(const K &key) { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair equal_range(const K &key, + std::size_t precalculated_hash) { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * @copydoc equal_range(const K& key) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair equal_range(const K &key) const { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key, std::size_t precalculated_hash) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair + equal_range(const K &key, std::size_t precalculated_hash) const { + return m_ht.equal_range(key, precalculated_hash); + } + + /* + * Bucket interface + */ + size_type bucket_count() const { return m_ht.bucket_count(); } + size_type max_bucket_count() const { return m_ht.max_bucket_count(); } + + /* + * Hash policy + */ + float load_factor() const { return m_ht.load_factor(); } + float max_load_factor() const { return m_ht.max_load_factor(); } + void max_load_factor(float ml) { m_ht.max_load_factor(ml); } + + void rehash(size_type count) { m_ht.rehash(count); } + void reserve(size_type count) { m_ht.reserve(count); } + + /* + * Observers + */ + hasher hash_function() const { return m_ht.hash_function(); } + key_equal key_eq() const { return m_ht.key_eq(); } + + /* + * Other + */ + + /** + * Convert a const_iterator to an iterator. + */ + iterator mutable_iterator(const_iterator pos) { + return m_ht.mutable_iterator(pos); + } + + /** + * Requires index <= size(). + * + * Return an iterator to the element at index. Return end() if index == + * size(). + */ + iterator nth(size_type index) { return m_ht.nth(index); } + + /** + * @copydoc nth(size_type index) + */ + const_iterator nth(size_type index) const { return m_ht.nth(index); } + + /** + * Return const_reference to the first element. Requires the container to not + * be empty. + */ + const_reference front() const { return m_ht.front(); } + + /** + * Return const_reference to the last element. Requires the container to not + * be empty. + */ + const_reference back() const { return m_ht.back(); } + + /** + * Only available if ValueTypeContainer is a std::vector. Same as calling + * 'values_container().data()'. + */ + template ::value>::type * = nullptr> + const typename values_container_type::value_type *data() const noexcept { + return m_ht.data(); + } + + /** + * Return the container in which the values are stored. The values are in the + * same order as the insertion order and are contiguous in the structure, no + * holes (size() == values_container().size()). + */ + const values_container_type &values_container() const noexcept { + return m_ht.values_container(); + } + + template ::value>::type * = nullptr> + size_type capacity() const noexcept { + return m_ht.capacity(); + } + + void shrink_to_fit() { m_ht.shrink_to_fit(); } + + /** + * Insert the value before pos shifting all the elements on the right of pos + * (including pos) one position to the right. + * + * Amortized linear time-complexity in the distance between pos and end(). + */ + std::pair insert_at_position(const_iterator pos, + const value_type &value) { + return m_ht.insert_at_position(pos, value); + } + + /** + * @copydoc insert_at_position(const_iterator pos, const value_type& value) + */ + std::pair insert_at_position(const_iterator pos, + value_type &&value) { + return m_ht.insert_at_position(pos, std::move(value)); + } + + /** + * @copydoc insert_at_position(const_iterator pos, const value_type& value) + * + * Same as insert_at_position(pos, value_type(std::forward(args)...), + * mainly here for coherence. + */ + template + std::pair emplace_at_position(const_iterator pos, + Args &&... args) { + return m_ht.emplace_at_position(pos, std::forward(args)...); + } + + /** + * @copydoc insert_at_position(const_iterator pos, const value_type& value) + */ + template + std::pair try_emplace_at_position(const_iterator pos, + const key_type &k, + Args &&... args) { + return m_ht.try_emplace_at_position(pos, k, std::forward(args)...); + } + + /** + * @copydoc insert_at_position(const_iterator pos, const value_type& value) + */ + template + std::pair + try_emplace_at_position(const_iterator pos, key_type &&k, Args &&... args) { + return m_ht.try_emplace_at_position(pos, std::move(k), + std::forward(args)...); + } + + void pop_back() { m_ht.pop_back(); } + + /** + * Faster erase operation with an O(1) average complexity but it doesn't + * preserve the insertion order. + * + * If an erasure occurs, the last element of the map will take the place of + * the erased element. + */ + iterator unordered_erase(iterator pos) { return m_ht.unordered_erase(pos); } + + /** + * @copydoc unordered_erase(iterator pos) + */ + iterator unordered_erase(const_iterator pos) { + return m_ht.unordered_erase(pos); + } + + /** + * @copydoc unordered_erase(iterator pos) + */ + size_type unordered_erase(const key_type &key) { + return m_ht.unordered_erase(key); + } + + /** + * @copydoc unordered_erase(iterator pos) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + size_type unordered_erase(const key_type &key, + std::size_t precalculated_hash) { + return m_ht.unordered_erase(key, precalculated_hash); + } + + /** + * @copydoc unordered_erase(iterator pos) + * + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type unordered_erase(const K &key) { + return m_ht.unordered_erase(key); + } + + /** + * @copydoc unordered_erase(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type unordered_erase(const K &key, std::size_t precalculated_hash) { + return m_ht.unordered_erase(key, precalculated_hash); + } + + /** + * Serialize the map through the `serializer` parameter. + * + * The `serializer` parameter must be a function object that supports the + * following call: + * - `template void operator()(const U& value);` where the types + * `std::uint64_t`, `float` and `std::pair` must be supported for U. + * + * The implementation leaves binary compatibilty (endianness, IEEE 754 for + * floats, ...) of the types it serializes in the hands of the `Serializer` + * function object if compatibilty is required. + */ + template void serialize(Serializer &serializer) const { + m_ht.serialize(serializer); + } + + /** + * Deserialize a previouly serialized map through the `deserializer` + * parameter. + * + * The `deserializer` parameter must be a function object that supports the + * following calls: + * - `template U operator()();` where the types `std::uint64_t`, + * `float` and `std::pair` must be supported for U. + * + * If the deserialized hash map type is hash compatible with the serialized + * map, the deserialization process can be sped up by setting + * `hash_compatible` to true. To be hash compatible, the Hash and KeyEqual + * must behave the same way than the ones used on the serialized map. The + * `std::size_t` must also be of the same size as the one on the platform used + * to serialize the map, the same apply for `IndexType`. If these criteria are + * not met, the behaviour is undefined with `hash_compatible` sets to true. + * + * The behaviour is undefined if the type `Key` and `T` of the `ordered_map` + * are not the same as the types used during serialization. + * + * The implementation leaves binary compatibilty (endianness, IEEE 754 for + * floats, size of int, ...) of the types it deserializes in the hands of the + * `Deserializer` function object if compatibilty is required. + */ + template + static ordered_map deserialize(Deserializer &deserializer, + bool hash_compatible = false) { + ordered_map map(0); + map.m_ht.deserialize(deserializer, hash_compatible); + + return map; + } + + friend bool operator==(const ordered_map &lhs, const ordered_map &rhs) { + return lhs.m_ht == rhs.m_ht; + } + friend bool operator!=(const ordered_map &lhs, const ordered_map &rhs) { + return lhs.m_ht != rhs.m_ht; + } + friend bool operator<(const ordered_map &lhs, const ordered_map &rhs) { + return lhs.m_ht < rhs.m_ht; + } + friend bool operator<=(const ordered_map &lhs, const ordered_map &rhs) { + return lhs.m_ht <= rhs.m_ht; + } + friend bool operator>(const ordered_map &lhs, const ordered_map &rhs) { + return lhs.m_ht > rhs.m_ht; + } + friend bool operator>=(const ordered_map &lhs, const ordered_map &rhs) { + return lhs.m_ht >= rhs.m_ht; + } + + friend void swap(ordered_map &lhs, ordered_map &rhs) { lhs.swap(rhs); } + +private: + ht m_ht; +}; + +} // end namespace tsl + +#endif diff --git a/external/tsl/ordered_set.h b/external/tsl/ordered_set.h new file mode 100644 index 0000000..9b2e7c8 --- /dev/null +++ b/external/tsl/ordered_set.h @@ -0,0 +1,769 @@ +/** + * MIT License + * + * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef TSL_ORDERED_SET_H +#define TSL_ORDERED_SET_H + +#include "ordered_hash.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace tsl { + +/** + * Implementation of an hash set using open adressing with robin hood with + * backshift delete to resolve collisions. + * + * The particularity of this hash set is that it remembers the order in which + * the elements were added and provide a way to access the structure which + * stores these values through the 'values_container()' method. The used + * container is defined by ValueTypeContainer, by default a std::deque is used + * (grows faster) but a std::vector may be used. In this case the set provides a + * 'data()' method which give a direct access to the memory used to store the + * values (which can be usefull to communicate with C API's). + * + * The Key must be copy constructible and/or move constructible. To use + * `unordered_erase` it also must be swappable. + * + * The behaviour of the hash set is undefinded if the destructor of Key throws + * an exception. + * + * By default the maximum size of a set is limited to 2^32 - 1 values, if needed + * this can be changed through the IndexType template parameter. Using an + * `uint64_t` will raise this limit to 2^64 - 1 values but each bucket will use + * 16 bytes instead of 8 bytes in addition to the space needed to store the + * values. + * + * Iterators invalidation: + * - clear, operator=, reserve, rehash: always invalidate the iterators (also + * invalidate end()). + * - insert, emplace, emplace_hint, operator[]: when a std::vector is used as + * ValueTypeContainer and if size() < capacity(), only end(). Otherwise all the + * iterators are invalidated if an insert occurs. + * - erase, unordered_erase: when a std::vector is used as ValueTypeContainer + * invalidate the iterator of the erased element and all the ones after the + * erased element (including end()). Otherwise all the iterators are invalidated + * if an erase occurs. + */ +template , + class KeyEqual = std::equal_to, + class Allocator = std::allocator, + class ValueTypeContainer = std::deque, + class IndexType = std::uint_least32_t> +class ordered_set { +private: + template + using has_is_transparent = tsl::detail_ordered_hash::has_is_transparent; + + class KeySelect { + public: + using key_type = Key; + + const key_type &operator()(const Key &key) const noexcept { return key; } + + key_type &operator()(Key &key) noexcept { return key; } + }; + + using ht = detail_ordered_hash::ordered_hash; + +public: + using key_type = typename ht::key_type; + using value_type = typename ht::value_type; + using size_type = typename ht::size_type; + using difference_type = typename ht::difference_type; + using hasher = typename ht::hasher; + using key_equal = typename ht::key_equal; + using allocator_type = typename ht::allocator_type; + using reference = typename ht::reference; + using const_reference = typename ht::const_reference; + using pointer = typename ht::pointer; + using const_pointer = typename ht::const_pointer; + using iterator = typename ht::iterator; + using const_iterator = typename ht::const_iterator; + using reverse_iterator = typename ht::reverse_iterator; + using const_reverse_iterator = typename ht::const_reverse_iterator; + + using values_container_type = typename ht::values_container_type; + + /* + * Constructors + */ + ordered_set() : ordered_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {} + + explicit ordered_set(size_type bucket_count, const Hash &hash = Hash(), + const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR) {} + + ordered_set(size_type bucket_count, const Allocator &alloc) + : ordered_set(bucket_count, Hash(), KeyEqual(), alloc) {} + + ordered_set(size_type bucket_count, const Hash &hash, const Allocator &alloc) + : ordered_set(bucket_count, hash, KeyEqual(), alloc) {} + + explicit ordered_set(const Allocator &alloc) + : ordered_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {} + + template + ordered_set(InputIt first, InputIt last, + size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, + const Hash &hash = Hash(), const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : ordered_set(bucket_count, hash, equal, alloc) { + insert(first, last); + } + + template + ordered_set(InputIt first, InputIt last, size_type bucket_count, + const Allocator &alloc) + : ordered_set(first, last, bucket_count, Hash(), KeyEqual(), alloc) {} + + template + ordered_set(InputIt first, InputIt last, size_type bucket_count, + const Hash &hash, const Allocator &alloc) + : ordered_set(first, last, bucket_count, hash, KeyEqual(), alloc) {} + + ordered_set(std::initializer_list init, + size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, + const Hash &hash = Hash(), const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : ordered_set(init.begin(), init.end(), bucket_count, hash, equal, + alloc) {} + + ordered_set(std::initializer_list init, size_type bucket_count, + const Allocator &alloc) + : ordered_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), + alloc) {} + + ordered_set(std::initializer_list init, size_type bucket_count, + const Hash &hash, const Allocator &alloc) + : ordered_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), + alloc) {} + + ordered_set &operator=(std::initializer_list ilist) { + m_ht.clear(); + + m_ht.reserve(ilist.size()); + m_ht.insert(ilist.begin(), ilist.end()); + + return *this; + } + + allocator_type get_allocator() const { return m_ht.get_allocator(); } + + /* + * Iterators + */ + iterator begin() noexcept { return m_ht.begin(); } + const_iterator begin() const noexcept { return m_ht.begin(); } + const_iterator cbegin() const noexcept { return m_ht.cbegin(); } + + iterator end() noexcept { return m_ht.end(); } + const_iterator end() const noexcept { return m_ht.end(); } + const_iterator cend() const noexcept { return m_ht.cend(); } + + reverse_iterator rbegin() noexcept { return m_ht.rbegin(); } + const_reverse_iterator rbegin() const noexcept { return m_ht.rbegin(); } + const_reverse_iterator rcbegin() const noexcept { return m_ht.rcbegin(); } + + reverse_iterator rend() noexcept { return m_ht.rend(); } + const_reverse_iterator rend() const noexcept { return m_ht.rend(); } + const_reverse_iterator rcend() const noexcept { return m_ht.rcend(); } + + /* + * Capacity + */ + bool empty() const noexcept { return m_ht.empty(); } + size_type size() const noexcept { return m_ht.size(); } + size_type max_size() const noexcept { return m_ht.max_size(); } + + /* + * Modifiers + */ + void clear() noexcept { m_ht.clear(); } + + std::pair insert(const value_type &value) { + return m_ht.insert(value); + } + std::pair insert(value_type &&value) { + return m_ht.insert(std::move(value)); + } + + iterator insert(const_iterator hint, const value_type &value) { + return m_ht.insert_hint(hint, value); + } + + iterator insert(const_iterator hint, value_type &&value) { + return m_ht.insert_hint(hint, std::move(value)); + } + + template void insert(InputIt first, InputIt last) { + m_ht.insert(first, last); + } + void insert(std::initializer_list ilist) { + m_ht.insert(ilist.begin(), ilist.end()); + } + + /** + * Due to the way elements are stored, emplace will need to move or copy the + * key-value once. The method is equivalent to + * insert(value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template std::pair emplace(Args &&... args) { + return m_ht.emplace(std::forward(args)...); + } + + /** + * Due to the way elements are stored, emplace_hint will need to move or copy + * the key-value once. The method is equivalent to insert(hint, + * value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template + iterator emplace_hint(const_iterator hint, Args &&... args) { + return m_ht.emplace_hint(hint, std::forward(args)...); + } + + /** + * When erasing an element, the insert order will be preserved and no holes + * will be present in the container returned by 'values_container()'. + * + * The method is in O(n), if the order is not important 'unordered_erase(...)' + * method is faster with an O(1) average complexity. + */ + iterator erase(iterator pos) { return m_ht.erase(pos); } + + /** + * @copydoc erase(iterator pos) + */ + iterator erase(const_iterator pos) { return m_ht.erase(pos); } + + /** + * @copydoc erase(iterator pos) + */ + iterator erase(const_iterator first, const_iterator last) { + return m_ht.erase(first, last); + } + + /** + * @copydoc erase(iterator pos) + */ + size_type erase(const key_type &key) { return m_ht.erase(key); } + + /** + * @copydoc erase(iterator pos) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup to the value if you already have the hash. + */ + size_type erase(const key_type &key, std::size_t precalculated_hash) { + return m_ht.erase(key, precalculated_hash); + } + + /** + * @copydoc erase(iterator pos) + * + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type erase(const K &key) { + return m_ht.erase(key); + } + + /** + * @copydoc erase(const key_type& key, std::size_t precalculated_hash) + * + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type erase(const K &key, std::size_t precalculated_hash) { + return m_ht.erase(key, precalculated_hash); + } + + void swap(ordered_set &other) { other.m_ht.swap(m_ht); } + + /* + * Lookup + */ + size_type count(const Key &key) const { return m_ht.count(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + size_type count(const Key &key, std::size_t precalculated_hash) const { + return m_ht.count(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type count(const K &key) const { + return m_ht.count(key); + } + + /** + * @copydoc count(const K& key) const + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type count(const K &key, std::size_t precalculated_hash) const { + return m_ht.count(key, precalculated_hash); + } + + iterator find(const Key &key) { return m_ht.find(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + iterator find(const Key &key, std::size_t precalculated_hash) { + return m_ht.find(key, precalculated_hash); + } + + const_iterator find(const Key &key) const { return m_ht.find(key); } + + /** + * @copydoc find(const Key& key, std::size_t precalculated_hash) + */ + const_iterator find(const Key &key, std::size_t precalculated_hash) const { + return m_ht.find(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + iterator find(const K &key) { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + iterator find(const K &key, std::size_t precalculated_hash) { + return m_ht.find(key, precalculated_hash); + } + + /** + * @copydoc find(const K& key) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + const_iterator find(const K &key) const { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + const_iterator find(const K &key, std::size_t precalculated_hash) const { + return m_ht.find(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) { + return m_ht.equal_range(key); + } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + std::pair equal_range(const Key &key, + std::size_t precalculated_hash) { + return m_ht.equal_range(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) const { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const Key& key, std::size_t precalculated_hash) + */ + std::pair + equal_range(const Key &key, std::size_t precalculated_hash) const { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair equal_range(const K &key) { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair equal_range(const K &key, + std::size_t precalculated_hash) { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * @copydoc equal_range(const K& key) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair equal_range(const K &key) const { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key, std::size_t precalculated_hash) + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + std::pair + equal_range(const K &key, std::size_t precalculated_hash) const { + return m_ht.equal_range(key, precalculated_hash); + } + + /* + * Bucket interface + */ + size_type bucket_count() const { return m_ht.bucket_count(); } + size_type max_bucket_count() const { return m_ht.max_bucket_count(); } + + /* + * Hash policy + */ + float load_factor() const { return m_ht.load_factor(); } + float max_load_factor() const { return m_ht.max_load_factor(); } + void max_load_factor(float ml) { m_ht.max_load_factor(ml); } + + void rehash(size_type count) { m_ht.rehash(count); } + void reserve(size_type count) { m_ht.reserve(count); } + + /* + * Observers + */ + hasher hash_function() const { return m_ht.hash_function(); } + key_equal key_eq() const { return m_ht.key_eq(); } + + /* + * Other + */ + + /** + * Convert a const_iterator to an iterator. + */ + iterator mutable_iterator(const_iterator pos) { + return m_ht.mutable_iterator(pos); + } + + /** + * Requires index <= size(). + * + * Return an iterator to the element at index. Return end() if index == + * size(). + */ + iterator nth(size_type index) { return m_ht.nth(index); } + + /** + * @copydoc nth(size_type index) + */ + const_iterator nth(size_type index) const { return m_ht.nth(index); } + + /** + * Return const_reference to the first element. Requires the container to not + * be empty. + */ + const_reference front() const { return m_ht.front(); } + + /** + * Return const_reference to the last element. Requires the container to not + * be empty. + */ + const_reference back() const { return m_ht.back(); } + + /** + * Only available if ValueTypeContainer is a std::vector. Same as calling + * 'values_container().data()'. + */ + template ::value>::type * = nullptr> + const typename values_container_type::value_type *data() const noexcept { + return m_ht.data(); + } + + /** + * Return the container in which the values are stored. The values are in the + * same order as the insertion order and are contiguous in the structure, no + * holes (size() == values_container().size()). + */ + const values_container_type &values_container() const noexcept { + return m_ht.values_container(); + } + + template ::value>::type * = nullptr> + size_type capacity() const noexcept { + return m_ht.capacity(); + } + + void shrink_to_fit() { m_ht.shrink_to_fit(); } + + /** + * Insert the value before pos shifting all the elements on the right of pos + * (including pos) one position to the right. + * + * Amortized linear time-complexity in the distance between pos and end(). + */ + std::pair insert_at_position(const_iterator pos, + const value_type &value) { + return m_ht.insert_at_position(pos, value); + } + + /** + * @copydoc insert_at_position(const_iterator pos, const value_type& value) + */ + std::pair insert_at_position(const_iterator pos, + value_type &&value) { + return m_ht.insert_at_position(pos, std::move(value)); + } + + /** + * @copydoc insert_at_position(const_iterator pos, const value_type& value) + * + * Same as insert_at_position(pos, value_type(std::forward(args)...), + * mainly here for coherence. + */ + template + std::pair emplace_at_position(const_iterator pos, + Args &&... args) { + return m_ht.emplace_at_position(pos, std::forward(args)...); + } + + void pop_back() { m_ht.pop_back(); } + + /** + * Faster erase operation with an O(1) average complexity but it doesn't + * preserve the insertion order. + * + * If an erasure occurs, the last element of the map will take the place of + * the erased element. + */ + iterator unordered_erase(iterator pos) { return m_ht.unordered_erase(pos); } + + /** + * @copydoc unordered_erase(iterator pos) + */ + iterator unordered_erase(const_iterator pos) { + return m_ht.unordered_erase(pos); + } + + /** + * @copydoc unordered_erase(iterator pos) + */ + size_type unordered_erase(const key_type &key) { + return m_ht.unordered_erase(key); + } + + /** + * @copydoc unordered_erase(iterator pos) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + size_type unordered_erase(const key_type &key, + std::size_t precalculated_hash) { + return m_ht.unordered_erase(key, precalculated_hash); + } + + /** + * @copydoc unordered_erase(iterator pos) + * + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type unordered_erase(const K &key) { + return m_ht.unordered_erase(key); + } + + /** + * @copydoc unordered_erase(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Usefull to speed-up + * the lookup if you already have the hash. + */ + template < + class K, class KE = KeyEqual, + typename std::enable_if::value>::type * = nullptr> + size_type unordered_erase(const K &key, std::size_t precalculated_hash) { + return m_ht.unordered_erase(key, precalculated_hash); + } + + /** + * Serialize the set through the `serializer` parameter. + * + * The `serializer` parameter must be a function object that supports the + * following call: + * - `void operator()(const U& value);` where the types `std::uint64_t`, + * `float` and `Key` must be supported for U. + * + * The implementation leaves binary compatibilty (endianness, IEEE 754 for + * floats, ...) of the types it serializes in the hands of the `Serializer` + * function object if compatibilty is required. + */ + template void serialize(Serializer &serializer) const { + m_ht.serialize(serializer); + } + + /** + * Deserialize a previouly serialized set through the `deserializer` + * parameter. + * + * The `deserializer` parameter must be a function object that supports the + * following calls: + * - `template U operator()();` where the types `std::uint64_t`, + * `float` and `Key` must be supported for U. + * + * If the deserialized hash set type is hash compatible with the serialized + * set, the deserialization process can be sped up by setting + * `hash_compatible` to true. To be hash compatible, the Hash and KeyEqual + * must behave the same way than the ones used on the serialized map. The + * `std::size_t` must also be of the same size as the one on the platform used + * to serialize the map, the same apply for `IndexType`. If these criteria are + * not met, the behaviour is undefined with `hash_compatible` sets to true. + * + * The behaviour is undefined if the type `Key` of the `ordered_set` is not + * the same as the type used during serialization. + * + * The implementation leaves binary compatibilty (endianness, IEEE 754 for + * floats, size of int, ...) of the types it deserializes in the hands of the + * `Deserializer` function object if compatibilty is required. + */ + template + static ordered_set deserialize(Deserializer &deserializer, + bool hash_compatible = false) { + ordered_set set(0); + set.m_ht.deserialize(deserializer, hash_compatible); + + return set; + } + + friend bool operator==(const ordered_set &lhs, const ordered_set &rhs) { + return lhs.m_ht == rhs.m_ht; + } + friend bool operator!=(const ordered_set &lhs, const ordered_set &rhs) { + return lhs.m_ht != rhs.m_ht; + } + friend bool operator<(const ordered_set &lhs, const ordered_set &rhs) { + return lhs.m_ht < rhs.m_ht; + } + friend bool operator<=(const ordered_set &lhs, const ordered_set &rhs) { + return lhs.m_ht <= rhs.m_ht; + } + friend bool operator>(const ordered_set &lhs, const ordered_set &rhs) { + return lhs.m_ht > rhs.m_ht; + } + friend bool operator>=(const ordered_set &lhs, const ordered_set &rhs) { + return lhs.m_ht >= rhs.m_ht; + } + + friend void swap(ordered_set &lhs, ordered_set &rhs) { lhs.swap(rhs); } + +private: + ht m_ht; +}; + +} // end namespace tsl + +#endif diff --git a/include/.clang-format b/include/.clang-format index 7605de0..cae777b 100644 --- a/include/.clang-format +++ b/include/.clang-format @@ -1,5 +1,5 @@ --- -# BasedOnStyle: CUED GeoMechanics +# BasedOnStyle: Cityscape AccessModifierOffset: -1 ConstructorInitializerIndentWidth: 4 AlignEscapedNewlinesLeft: true diff --git a/include/LU_solver.h b/include/LU_solver.h new file mode 100644 index 0000000..2ff7915 --- /dev/null +++ b/include/LU_solver.h @@ -0,0 +1,38 @@ +#ifndef PIPE_NETWORK_MKL_UNSYM_H +#define PIPE_NETWORK_MKL_UNSYM_H + +#include +#include +#include +#include +#include + +#include "mkl_pardiso.h" +#include "solver.h" + +namespace pipenetwork { +namespace linear_system { + +//! Pipe network LU Solver class +//! \brief Linear system solver using Eigen LU solver +class LUSolver : public Solver { + public: + //! default constructor + LUSolver() = default; + //! Call MKL Pardiso Unsymmetric solver + //! \retval status Return status of the solver + Eigen::VectorXd solve() override; + + protected: + //! Return the type of assembler for Factory + //! \retval assembler_type Eigen assembler + std::string assembler_type() const override { return "LU Solver"; } + + private: + Eigen::SparseLU, Eigen::COLAMDOrdering> + LU_solver_; +}; +} // namespace linear_system +} // namespace pipenetwork + +#endif // PIPE_NETWORK_MKL_UNSYM_H diff --git a/include/curves.h b/include/curves.h new file mode 100644 index 0000000..5f080c8 --- /dev/null +++ b/include/curves.h @@ -0,0 +1,131 @@ +#ifndef PIPE_NETWORK_CURVES_H +#define PIPE_NETWORK_CURVES_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "settings.h" + +namespace pipenetwork { +//! Pump_curve_prop struct +//! \brief Struct for pump curves that contains curve information for a given +//! head pump curve +struct Pump_curve_prop { + Pump_curve_prop() = default; + //! Constructor + //! \param[in] curve_name name of the curve + //! \param[in] curve_point vector (1 or 3) of curve points (flow, head) used + //! for pump curve construction + Pump_curve_prop(std::string& curve_name, + std::vector>& curve_point); + + //! Name of the pump curve + std::string name; + //! Number of points used for curve generation + unsigned num_points{0}; + //! Points used for curve generation + std::vector> points; + //! Head curve coefficients: H = head_curve_coefficients[0] - + //! head_curve_coefficients[1]*Q^head_curve_coefficients[2] + Eigen::Vector3d head_curve_coefficients{0, 0, 0}; + //! Pump polynomial approximation coefficients + Eigen::Vector4d poly_coefficients{0, 0, 0, 0}; + //! Pump line approximation coefficients + Eigen::Vector2d line_param{0, 0}; + + //! Method to compute pump polynomial approximation coefficients + Eigen::Vector4d get_pump_poly_coefficients(); + //! Method to compute pump line approximation coefficients + Eigen::Vector2d get_pump_line_params(); +}; + +//! Curves Class +//! \brief Class to hold all the curves information in hydraulic simulation +class Curves { + public: + //! Constructor + Curves() { + // default pdd(pressure demand driven) and hw(harzian williams) coefficients + poly_coefficients_["PDD_POLY_VEC1"] = compute_pdd1_poly_vec(); + poly_coefficients_["PDD_POLY_VEC2"] = compute_pdd2_poly_vec(); + poly_coefficients_["HW_POLY_VEC"] = compute_hw_poly_vec(); + }; + + //! Destructor + ~Curves() = default; + + // + //! Method to add head pump curve + //! \param[in] head_pump_curves a vector that contains information of each + //! pump curve + void add_pump_curves(const std::vector& head_pump_props); + + //! Method to add polynomial coefficients for leak equation + //! \param[in] node_name name of the leaky node + //! \param[in] leak_area area of the leak hole + void add_leak_poly_vec(std::string& node_name, double leak_area) { + poly_coefficients_[node_name] = compute_leak_poly_vec(leak_area); + }; + + //! get the head pump curves map + std::map pump_curves() const { + return head_pump_curves_; + } + + //! get the poly coefficient curves map + std::map poly_coeffs() const { + return poly_coefficients_; + } + + //! get pump string name to int code map + int pump_str_int(std::string k) const { return pump_str_int_.at(k); } + + //! get pump int code to string name map + std::string pump_int_str(int k) const { return pump_int_str_.at(k); } + + private: + //! map that stores all the polynomial approximation coefficients + std::map poly_coefficients_; + //! map that stores all the head pump curves information + std::map head_pump_curves_; + //! map that convert pump string key to int + std::map pump_str_int_; + std::map pump_int_str_; + //! Method to compute the polynomial coefficients for harzian williams + //! equation + //! \retval poly_coef polynomial approximation coefficient + Eigen::Vector4d compute_hw_poly_vec(); + //! Method to compute the polynomial coefficients for the first part of + //! pressure demand driven demand equation + //! \retval poly_coef polynomial approximation coefficient + Eigen::Vector4d compute_pdd1_poly_vec(); + //! Method to compute the polynomial coefficients for the second part of + //! pressure demand driven demand equation + //! \retval poly_coef polynomial approximation coefficient + Eigen::Vector4d compute_pdd2_poly_vec(); + //! Method to compute the polynomial coefficients for leak equations + //! \param[in] leak_area leak area of the leak hole + //! \retval leak_poly_coef polynomial approximation coefficient for leak + //! equation + Eigen::Vector4d compute_leak_poly_vec(double leak_area); +}; + +//! Method to compute the coefficients of a smoothing polynomial +//! \param[in] x points on the x-axis at which the smoothing polynomial begins +//! and ends +//! \param[in] f function evaluated at x1 and f2 \param[in] df +//! derivative evaluated at x1 and x2 +//! \retval A vector with the smoothing +//! polynomail coefficients starting with the cubic term. +Eigen::Vector4d compute_poly_coefficients(const std::array& x, + const std::array& f, + const std::array& df); +} // namespace pipenetwork + +#endif // PIPE_NETWORK_CURVES_H diff --git a/include/eigen_gmres.h b/include/eigen_gmres.h deleted file mode 100644 index 18e7d1b..0000000 --- a/include/eigen_gmres.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef PIPE_NETWORK_EIGEN_GMRES_H_ -#define PIPE_NETWORK_EIGEN_GMRES_H_ - -#include -#include - -#include -#include - -#include -#include - -#include "solver.h" - -namespace pipenetwork { - -//! Pipe network Eigen GMRES class -//! \brief Eigen GMRES solver class using Eigen -class EigenGMRES : public Solver { - public: - //! Constructor with tolerance, precision and iterations - //! \param[in] max_iter Maximum number of iterations - //! \param[in] tolerance Tolerance for solver to achieve convergence - EigenGMRES(unsigned max_iter, double tolerance) - : Solver(max_iter, tolerance) {} - - //! Call Conjugate Gradient solver - //! \retval status Return status of the solver - bool solve() override; - - protected: - //! Maximum number of iterations - using Solver::max_iter_; - //! Tolerance - using Solver::tolerance_; - //! Delta - using Solver::delta_; - //! Number of iterations - using Solver::niterations_; - //! Vector x - using Solver::vec_x_; - //! Vector b - using Solver::vec_b_; - //! Matrix A - using Solver::mat_a_; - //! Restraint vector - using Solver::vrestraints_; - - //! Return the type of assembler for Factory - //! \retval assembler_type Eigen assembler - std::string assembler_type() const override { return "Eigen_GMRES"; } -}; -} // namespace pipenetwork - -#endif // PIPE_NETWORK_EIGEN_GMRES_H_ diff --git a/include/factory.h b/include/factory.h new file mode 100644 index 0000000..ccf00cd --- /dev/null +++ b/include/factory.h @@ -0,0 +1,57 @@ +#ifndef _FACTORY_H_ +#define _FACTORY_H_ + +#include +#include +#include +#include + +//! Singleton factory implementation +template +class Factory { + public: + // Get the single instance of the factory + static Factory* instance() { + static Factory factory; + return &factory; + } + + // register a factory function to create an instance of className + void register_factory(Key key, + std::function class_factory_fn) { + // register the class factory function + registry[key] = class_factory_fn; + } + + // create an instance of a registered class + std::shared_ptr create(Key key) { + BaseClass* instance = nullptr; + // find name in the registry and call factory method. + auto it = registry.find(key); + if (it != registry.end()) { + instance = it->second(); + return std::shared_ptr(instance); + } else + return nullptr; + } + + private: + // Private constructor + Factory() {} + + // Register of factory functions + std::map> registry; +}; + +// A helper class to register a factory function +template +class Register { + public: + Register(Key key) { + // register the class factory function + Factory::instance()->register_factory( + key, [](void) -> BaseClass* { return new DerivedClass(); }); + } +}; + +#endif // _FACTORY_H_ \ No newline at end of file diff --git a/include/hydralic_sim.h b/include/hydralic_sim.h new file mode 100644 index 0000000..1a5d8ff --- /dev/null +++ b/include/hydralic_sim.h @@ -0,0 +1,69 @@ +#ifndef PIPE_NETWORK_HYDRALIC_SIM_H +#define PIPE_NETWORK_HYDRALIC_SIM_H +//#include +#include +#include +#include +#include + +#include "factory.h" +#include "io.h" +#include "matrix_assembler.h" +#include "settings.h" +#include "solver.h" + +namespace pipenetwork { +//! Hydraulic Simulation class +//! \brief Class for pipenetwork hydraulic simulation +class Hydralic_sim { + public: + //! Constructor with mesh input + //! \param[in] mesh the mesh pointer + //! \param[in] curves_info a pointer for curve information of the mesh + //! \param[in] pdd_mode if simulation type is pressure demand driven or demand + //! driven + //! \param[in] debug debug mode. if the mode is on, the initial variables, + //! residual, and jacobian matrix will be recorded, iteration process will be + //! printed + Hydralic_sim(const std::shared_ptr& mesh, + std::shared_ptr& curves_info, bool pdd_mode = false, + bool debug = false); + + //! run simulation + //! \param[in] NR_tolerance residual tolerance for newton ralphson process + //! \param[in] max_nr_steps max number of steps for newton ralphson process + bool run_simulation(double NR_tolerance = 1.e-8, int max_nr_steps = 20); + + //! get the norm of simulation residual + double sim_residual_norm() const { + return assembler_->residual_vector().norm(); + } + + //! update mesh using simulation results + void update_mesh(); + + private: + //! initial variable vector before linear system solving (for line search + //! comparison) + Eigen::VectorXd init_variable_; + //! the mesh ptr + std::shared_ptr mesh_; + //! the assember ptr + std::shared_ptr assembler_; + //! the solver ptr + std::shared_ptr solver_; + //! Network size Threshold for parallel solver + Index nthre_{10000}; + //! debug flag + bool debug_{false}; + //! backtracking (in line search) settings + int bt_max_iter_{20}; + double bt_roh_{0.5}; + + //! update system variable with line search + void line_search_update(const Eigen::VectorXd& x_diff); +}; + +} // namespace pipenetwork + +#endif // PIPE_NETWORK_HYDRALIC_SIM_H diff --git a/include/index_manager.h b/include/index_manager.h new file mode 100644 index 0000000..fd74ce4 --- /dev/null +++ b/include/index_manager.h @@ -0,0 +1,33 @@ +#ifndef PIPE_NETWORK_INDEX_MANAGER_H +#define PIPE_NETWORK_INDEX_MANAGER_H +#include +#include + +#include "settings.h" + +namespace pipenetwork { +//! Network index class +//! \brief Base class of a network index +class IndexManager { + public: + //! Constructor with an inital value for index + explicit IndexManager(Index idx = 0); + + //! Current index + Index current_index() const; + + //! Max value + Index max() const; + + //! Create index + Index create_index(); + + private: + //! index + Index index_{0}; + //! Next value + Index next_{0}; +}; +} // namespace pipenetwork + +#endif // PIPE_NETWORK_INDEX_MANAGER_H diff --git a/include/io.h b/include/io.h index 7d997aa..8303e49 100644 --- a/include/io.h +++ b/include/io.h @@ -1,91 +1,157 @@ -#ifndef PIPE_NETWORK_IO_H_ -#define PIPE_NETWORK_IO_H_ +#ifndef PIPE_NETWORK_IO_H +#define PIPE_NETWORK_IO_H -#include +#include +#include +#include +#include #include #include +#include +#include +#include #include #include -#include "csv.h" -#include - -#include "settings.h" +#include "curves.h" +#include "io_utils.h" +#include "valve_graph.h" namespace pipenetwork { //! Pipe network input output class -//! \brief Base class for input and output data +//! \brief Base class for parsing input data using .inp file class IO { public: - //! Read input CSV file and store the data - //! \param[in] node_filename the name of input CSV file with nodal information - //! \param[in] pipe_filename the name of input CSV file with pipe information - bool read_network(const std::string& node_filename, - const std::string& pipe_filename); - - //! Return input nodal coordinates - //! \retval nodal_coords_ input nodal coordinates - std::vector nodal_coordinates() const { - return nodal_coords_; - } + //! Default constructor + IO() = default; + //! Read and create mesh from the .inp file + //! \param[in] filename path of the .inp file + void read_inp(const std::string& filename); - //! Return input start and end nodes of pipes - //! \retval node_pairs input start and end nodes of pipes - std::vector> node_pairs() const { - return node_pairs_; - } + //! Create synthetic network + //! \param[in] n size of the network, number of nodes will be n^2 + void create_synthetic_net(Index n); - //! Return input pipe diameters - //! \retval diameters_ input pipe diameters - std::vector diameters() const { return diameters_; } + //! save mesh information to a .inp file + //! \param[in] mesh mesh ptr for save + //! \param[in] output_path save path + void save_mesh_inp(const std::shared_ptr& mesh, + const std::string& output_path); - //! Return input pipe roughnesses - //! \retval roughness_ input pipe diameters - std::vector roughness() const { return roughness_; } + //! save hydrualic simulation result of the mesh + //! \param[in] mesh mesh ptr for save + //! \param[in] output_path save path + void save_sim_result(const std::shared_ptr& mesh, + const std::string& output_path); - //! Return input pipe status - //! \retval pipe_status_ input pipe status - std::vector pipe_status() const { return pipe_status_; } - - //! Return input pipe discharge and corresponding index - //! \retval initial_pipe_discharge_ input pipe discharge and corresponding - //! index - std::vector> initial_pipe_discharge() const { - return initial_pipe_discharge_; + //! Return node information + std::vector junction_properties() const { + return junc_props_; } - - //! Return input nodal head and corresponding index - //! \retval initial_nodal_head_ input nodal head and corresponding index - std::vector> initial_nodal_head() const { - return initial_nodal_head_; + std::vector reservoir_properties() const { + return res_props_; } + //! Return pipe information + std::vector pipe_properties() const { + return pipe_props_; + } + //! Return pump information + std::vector pump_properties() const { return pump_props_; } + + //! Return valve information + std::vector valve_properties() const { return valve_props_; } - //! Return input nodal discharge and corresponding index - //! \retval initial_nodal_discharge_ input nodal discharge and corresponding - //! index - std::vector> initial_nodal_discharge() const { - return initial_nodal_discharge_; + //! Return isolation valve information + std::vector iso_valve_properties() const { + return iso_valve_props_; } + //! Return curve information + std::shared_ptr curve_info() const { return curves_info_; } + private: - //! Vector of nodal coordinates - std::vector nodal_coords_; - //! Vecotr of start and end nodes of pipes - std::vector> node_pairs_; - //! vector of pipe diameters - std::vector diameters_; - //! vector of pipe roughnesses - std::vector roughness_; - //! vector of pipe status - std::vector pipe_status_; - //! vector of pipe discharge and corresponding index - std::vector> initial_pipe_discharge_; - //! vector of nodal head and corresponding index - std::vector> initial_nodal_head_; - //! vector of nodal discharge and corresponding index - std::vector> initial_nodal_discharge_; + //! Filepath + std::string filename_; + //! the curves info ptr + std::shared_ptr curves_info_{std::make_shared()}; + //! Set of section key words + std::set section_keys_{ + "[JUNCTIONS]", "[RESERVOIRS]", "[TANKS]", "[PIPES]", "[COORDINATES]", + "[PUMPS]", "[CURVES]", "[VALVES]", "[LEAKS]", "[ISOVALVES]"}; + + //! Map of sections and its corresponding lines + std::map> sections_; + + //! Map of leaking nid to leak diameter + std::map nid2ldia_; + + //! Vector of parsed junction properties + std::vector junc_props_; + //! Vector of parsed reservoir properties + std::vector res_props_; + + //! Vector of parsed pipe properties + std::vector pipe_props_; + //! Vector of parsed pump properties + std::vector pump_props_; + //! Vector of parsed valve properties + std::vector valve_props_; + //! Vector of parsed isolation valves properties + std::vector iso_valve_props_; + + //! Parse information to each section from the input file + void parse_sections(); + //! Parse leak information (leak diameter) from the input file + void parse_leak_info(); + + //! Parse elevation, head or demand from a given node section + //! \param[in] an opened file + //!\retval a pair with vector of node ids their corresponding elevations, + //! heads or demand + std::pair, std::vector> parse_node_line( + const std::string& section_name, const std::string& mode) const; + + //! Construct node info that is used for pipeline-mesh + void construct_node_info(); + //! Construct pipe info that is used for pipeline-mesh + void construct_pipe_info(); + //! Construct curve info that is used for pipeline-mesh and matrix assembler + void construct_curve_info(); + //! Construct pump info that is used for pipeline-mesh + void construct_pump_info(); + //! Construct valve info that is used for pipeline-mesh + void construct_valve_info(); + //! Construct iso valve info that is used for segment usage + void construct_iso_valve_info(); + + //! Construct synthesis junctions + //! \param[in] n number of the mesh dimension (n*n) + std::vector> construct_synthesis_junctions(int n); + + //! Construct synthesis pipes + //! \param[in] junction_names names for junctions + void construct_synthesis_pipes( + const std::vector>& junction_names); + //! Construct pipes by linking junctions vertically + //! \param[in] junction_names names for junctions + //! \param[in] col_num current column number + //! \param[in] rand random connection or not + void create_vertical_pipes(const std::vector& junction_names, + int col_num, bool rand = false); + //! Construct pipes by linking junctions horizontally + //! \param[in] l_junc names for left sided junctions + //! \param[in] r_junc names for right sided junctions + //! \param[in] col_num current column number + //! \param[in] rand random connection or not + void create_horizontal_pipes(const std::vector& l_junc, + const std::vector& r_junc, + int col_num, bool rand = true); + //! Create sources for synthetic network + //! \param[in] n number of sources for the synthetic network + void create_sources(int n); }; + } // namespace pipenetwork -#endif // PIPE_NETWORK_IO_H_ +#endif // PIPE_NETWORK_IO_H diff --git a/include/io_utils.h b/include/io_utils.h new file mode 100644 index 0000000..8ea7673 --- /dev/null +++ b/include/io_utils.h @@ -0,0 +1,82 @@ +#ifndef PIPE_NETWORK_IO_UTILS_H +#define PIPE_NETWORK_IO_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mesh.h" + +namespace pipenetwork { +namespace IO_utils { +//! function to convert input value to standard unit for hydraulic simulation +//! \param[in] val the value need to be converted +//! \param[in] mode type of the input value (length, elevation, etc.) +double to_si(double val, const std::string&); + +//! function converts input value to GPM unit for hydraulic simulation +//! \param[in] val the value need to be converted +//! \param[in] mode type of the input value (length, elevation, etc.) +double from_si(double val, const std::string&); + +//! function to generate uniformly distributed random number +//! \param[in] l min value boundary for the random number domain +//! \param[in] r max value boundary for the random number domain +double rand_number(double l, double h); + +//! function check the existance of a file +//! \param[in] name path of the file +inline bool file_exists(const std::string& name) { + std::ifstream f(name.c_str()); + return f.good(); +} +//! function check the existance of a path +//! \param[in] pathname folder path +bool path_exist(const std::string& pathname); + +//! function to create a new folder if it does not exist +//! \param[in] pathname folder path +void create_new_folder(const std::string& pathname); + +//! Pipe network input output class +//! \brief Base class for writing mesh information into .inp file +class Output { + public: + //! constructor + //! \param[in] m mesh ptr + explicit Output(const std::shared_ptr& m) : mesh_{m} {} + + //! save mesh information to a .inp file + //! \param[in] output_path path for save + void save_mesh_inp(const std::string& output_path); + + //! save hydraulic simulation result + //! \param[in] output_path path for save + void save_sim_result(const std::string& output_path); + + private: + //! Filepath + std::string filepath_; + //! Mesh pointer + std::shared_ptr mesh_; + + //! Method for writing junctions + void write_junctions_inp(std::ofstream& outfile); + + //! Method for writing reservoirs + void write_reservoirs_inp(std::ofstream& outfile); + + //! Method for writing ouoes + void write_pipes_inp(std::ofstream& outfile); +}; +} // namespace IO_utils +} // namespace pipenetwork + +#endif // PIPE_NETWORK_IO_UTILS_H diff --git a/include/junction.h b/include/junction.h new file mode 100644 index 0000000..9d3eab3 --- /dev/null +++ b/include/junction.h @@ -0,0 +1,48 @@ +#ifndef PIPE_NETWORK_JUNCTION_H +#define PIPE_NETWORK_JUNCTION_H + +#include "node.h" +namespace pipenetwork { +//! Junction Property +//! name junction name +//! elevation elevation for the junction +//! demand base demand for the junction +//! leak_diameter diameter of the leak hole for the junction +struct JunctionProp { + std::string name{"junction"}; + double elevation{std::numeric_limits::min()}; + double demand{std::numeric_limits::min()}; + double leak_diameter{0}; +}; + +class Junction : public Node { + public: + //! Constructor with id, elevation, demand and leak diameter + //! \param[in] junc_prop junction properties + + Junction(const Index id, const JunctionProp& junc_prop) + : Node(id), property_{junc_prop} {}; + + //! Return nodal info + inline const JunctionProp property() const { return property_; } + + //! Return leak area + inline const double leak_area() const { + return std::pow((property_.leak_diameter / 2), 2) * PI; + } + + //! Junction demand, mutable + double demand{0}; + //! Junction head, mutable + double head{1e-3}; + //! Junction leak discharge, mutable + double leak_discharge{0}; + + private: + //! junction information + JunctionProp property_; +}; + +} // namespace pipenetwork + +#endif // PIPE_NETWORK_JUNCTION_H diff --git a/include/link.h b/include/link.h new file mode 100644 index 0000000..9605177 --- /dev/null +++ b/include/link.h @@ -0,0 +1,56 @@ +#ifndef PIPE_NETWORK_LINK_H +#define PIPE_NETWORK_LINK_H + +#include +#include +#include + +#include "node.h" + +namespace pipenetwork { +//! Link Property +//! name name of the link +//! node1_name name of one end node +//! node2_name ame of the other end node +struct LinkProp { + std::string name{"None"}; + std::string node1_name{"None"}; + std::string node2_name{"None"}; + LinkStatus status{LinkStatus::OPEN}; +}; + +//! Link class +//! \brief Base Class that stores the information about links +class Link { + public: + //! Constructor + //! \param[in] link_id link id + //! \param[in] node1 one end node + //! \param[in] node2 the other end node + Link(const Index link_id, const Node& node1, const Node& node2) + : id_{link_id} { + nodes_ = std::make_pair(std::make_shared(node1), + std::make_shared(node2)); + }; + + //! Destructor + virtual ~Link(){}; + + //! Return link id + Index id() const { return id_; } + + //! Return end nodes + const std::pair, std::shared_ptr>& nodes() const { + return nodes_; + } + + private: + //! link id + Index id_; + //! pair of node pointers which form the link + std::pair, std::shared_ptr> nodes_; +}; +} // namespace pipenetwork +; + +#endif // PIPE_NETWORK_LINK_H diff --git a/include/matrix_assembler.h b/include/matrix_assembler.h index 8d319bc..30af862 100644 --- a/include/matrix_assembler.h +++ b/include/matrix_assembler.h @@ -1,111 +1,63 @@ -#ifndef PIPE_NETWORK_MATRIX_ASSEMBLER_H_ -#define PIPE_NETWORK_MATRIX_ASSEMBLER_H_ +#ifndef PIPE_NETWORK_MATRIX_ASSEMBLER_H +#define PIPE_NETWORK_MATRIX_ASSEMBLER_H -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mesh.h" -#include "node.h" -#include "pipe.h" -#include "settings.h" +#include "matrix_assembler_components.h" namespace pipenetwork { - +namespace linear_system { //! Mtrix assembler class //! \brief Class for assembling matrix for solving class MatrixAssembler { public: //! Constructor - explicit MatrixAssembler(bool pdd_mode = false); + //! \param[in] mesh the mesh pointer + //! \param[in] curves_info the curve information pointer + //! \param[in] pdd_mode if simulation type is pressure demand driven or + //! demand driven + MatrixAssembler(const std::shared_ptr& mesh, + std::shared_ptr& curves_info, bool pdd_mode = false); //! Destructor ~MatrixAssembler() = default; - //! Obtain global nodal and pipe indices and pointers from meshes - //! \param[in] mesh meshes that form the pipe network - void global_nodal_pipe_indices(const std::shared_ptr& mesh); - - //! Return number of nodes in the network - //! \retval nnode_ number of nodes in the network - unsigned nnodes() { return nnode_; } - - //! Return number of pipes in the network - //! \retval nnode_ number of pipes in the network - unsigned npipes() { return npipe_; } - - //! Initialize variable vector - void assemble_variable_vector(); - - //! Assemble Jacobian matrix for nodal head, demand and pipe discharge as - //! variables - void assemble_jacobian(); - - //! Apply variables (head, demand and discharge) to nodes and pipes - void apply_variables(); - - //! Initialize variable vector (unknown variables only) - void assemble_residual_vector(); - - //! Return variable vector - //! \retval variable_vec_ pointer to variable vector - std::shared_ptr variable_vec() const { - return variable_vec_; + //! get the variable vector + Eigen::VectorXd& variable_vector() { return vars_->variables_vec(); } + //! Method to assemble residual from the variable vector + void assemble_residual(); + //! Method to get residual vector + const Eigen::VectorXd& residual_vector() const { + return res_->residual_vec(); } - - //! Return residual vector - //! \retval residual_vec_ pointer to residual vector - std::shared_ptr residual_vec() const { - return residual_vec_; + //! Method to update jacobian matrix from the variable vector + void update_jacobian(); + //! Method to get jacobian matrix + const Eigen::SparseMatrix& jac_matrix() const { + return jac_->jac_matrix(); } - //! Return Jacobian matrix - //! \retval jac_ pointer to Jacobian matrix - std::shared_ptr> jac() const { return jac_; } + //! Method for system update after variable changes + void system_update() { + assemble_residual(); + update_jacobian(); + } private: - //! global nodal id and corresponding nodal pointer - std::map> global_nodes_; - //! global pipe id and corresponding pipe pointer - std::map> global_pipes_; - //! number of nodes in the network - unsigned nnode_{0}; - //! number of pipes in the network - unsigned npipe_{0}; - //! pdd mode + //! the mesh ptr + std::shared_ptr mesh_; + //! the curves info ptr + std::shared_ptr curves_info_; + //! if it is pressure demand simulation mode bool pdd_{false}; - //! variable vector - std::shared_ptr variable_vec_; - //! residual vector - std::shared_ptr residual_vec_; - //! Jacobian matrix - std::shared_ptr> jac_; - - //! Assemble pressure demand part of the jacobian matrix - //! \param[in] n the corresponding node pointer - //! \param[in] index the position of the corresponding node in variable vector - //! jacobian matrix - std::vector> construct_demand_jac( - const std::shared_ptr& n, Index index); - - //! Method to get the corresponding value of jacobian for head-pressure - //! equations \param[in] node pointer for the desired node \retval The value - //! for the corresponding jacobian entry - double get_pressure_head_jacob( - const std::shared_ptr& node); - - //! Method to assemble residuals for demand equation in pressure-demand mode - //! \param[in] node pointer for the desired node - //! \param[in] ndex the position of the corresponding node in variable vector - void assemble_pdd_residual(const std::shared_ptr& node, - Index index); + //! Variable object + std::shared_ptr vars_; + //! Residual object + std::shared_ptr res_; + //! Jacobian object + std::shared_ptr jac_; + //! Update curves info + void update_curves_info_(); }; +} // namespace linear_system } // namespace pipenetwork - -#endif // PIPE_NETWORK_MATRIX_ASSEMBLER_H_ +#endif // PIPE_NETWORK_MATRIX_ASSEMBLER_H diff --git a/include/matrix_assembler_components.h b/include/matrix_assembler_components.h new file mode 100644 index 0000000..4cd0c16 --- /dev/null +++ b/include/matrix_assembler_components.h @@ -0,0 +1,305 @@ +#ifndef PIPE_NETWORK_MATRIX_ASSEMBLER_COMPONENTS_H +#define PIPE_NETWORK_MATRIX_ASSEMBLER_COMPONENTS_H + +#include "curves.h" +#include "mesh.h" +#include "settings.h" + +namespace pipenetwork { +namespace linear_system { + +//! Vairables class +//! \brief Class for linear system variables +class Variables { + public: + explicit Variables(const std::shared_ptr& mesh) : mesh_{mesh} { + assemble_iso_masks(); + init_variable_vectors(); + } + //! get the variable vector + Eigen::VectorXd& variables_vec() { return variable_vec_; } + + //! get the variable vector + const Eigen::VectorXd& demands_heads_vec() const { + return demands_heads_vec_; + } + + //! get the elevation vector + const Eigen::VectorXd& elevations() const { return elevations_; } + + //! get the resistance loss coefficient vector + const Eigen::VectorXd& link_resistance_coeff_vec() const { + return link_resistance_coeff_vec_; + } + + //! get the minor loss coefficient vector + const Eigen::VectorXd& link_minor_loss_coeff_vec() const { + return link_minor_loss_coeff_vec_; + } + //! get the leak areas for broken nodes + const Eigen::VectorXd& leak_areas() const { return leak_areas_; } + + //! Get the isolated junctions vector (boolean mask purpose) + const Eigen::VectorXd& iso_junctions_mask() const { + return iso_junctions_mask_; + } + + //! Get the connected junctions vector (boolean mask purpose) + const Eigen::VectorXd& connect_junctions_mask() const { + return connect_junctions_mask_; + } + + //! Get the isolated/closed links vector (boolean mask purpose) + const Eigen::VectorXd& iso_links_mask() const { return iso_links_mask_; } + + //! Get the connected links vector (boolean mask purpose) + const Eigen::VectorXd& connect_links_mask() const { + return connect_links_mask_; + } + + private: + //! the mesh ptr + std::shared_ptr mesh_; + //! variable vector + Eigen::VectorXd variable_vec_; + //! demand (for junction) and heads (for sources) of nodes + Eigen::VectorXd demands_heads_vec_; + //! junction elevations vector + Eigen::VectorXd elevations_; + //! resistence coefficients for links + Eigen::VectorXd link_resistance_coeff_vec_; + //! minor loss coefficients for links + Eigen::VectorXd link_minor_loss_coeff_vec_; + //! leak areas + Eigen::VectorXd leak_areas_; + //! isolated junctions vector (boolean mask purpose) + Eigen::VectorXd iso_junctions_mask_; + //! connected junctions vector (boolean mask purpose) + Eigen::VectorXd connect_junctions_mask_; + //! isolated/closed links vector (boolean mask purpose) + Eigen::VectorXd iso_links_mask_; + //! connected links vector (boolean mask purpose) + Eigen::VectorXd connect_links_mask_; + + //! assemble the masks for isolated nodes and links + void assemble_iso_masks(); + //! Initialize variable vector + void init_variable_vectors(); + //! resize variables + void resize_init_variables(Index nnodes, Index nlinks, Index nleaks); + //! initialize node related vectors (demand_head, elevations) + void init_nodes_vecs(const std::shared_ptr& nodes); + //! initialize link related vectors (link resistance coefficients, minor loss + //! coefficients) + void init_link_vecs(const std::shared_ptr& links, + Index link_start_idx); + //! initialize leak nodes information + void init_leak_nodes(const std::shared_ptr& nodes, + const std::vector& leak_ids, + Index leak_start_idx); + + //! helper function to create minor loss and flow energy loss + //! (harzan-williams) for links \param[in] linkmap map of link ptrs + template + void update_minor_resis_coeff(const LinkMap& linkmap); + + //! helper function to calcuate flow energy loss for links + //! \param[in] link link_ptr + double get_link_res_coeff(const std::shared_ptr& link) { return 0; } + + //! helper function to calcuate flow energy loss for pipes + //! \param[in] pipe pipe_ptr + double get_link_res_coeff(const std::shared_ptr& pipe); + + //! helper function to calcuate flow energy loss for valves + //! \param[in] valve valve_ptr + double get_link_res_coeff(const std::shared_ptr& valve); + + //! helper function to minor loss for links + //! \param[in] link link_ptr + double get_link_minor_coeff(const std::shared_ptr& link) { return 0; } +}; + +struct HW_vectors { + Eigen::ArrayXd sign_array; + Eigen::ArrayXd case1_bool; + Eigen::ArrayXd case2_bool; + Eigen::ArrayXd case3_bool; + Eigen::ArrayXd discharge_abs_array; + Eigen::ArrayXd head_diff_array; + Eigen::Vector4d hw_poly_vec; +}; +struct PDD_vectors { + Eigen::ArrayXd pressure; + Eigen::ArrayXd case1_bool; + Eigen::ArrayXd case2_bool; + Eigen::ArrayXd case3_bool; + Eigen::ArrayXd case4_bool; + Eigen::ArrayXd case5_bool; + Eigen::Vector4d pdd1_poly_vec; + Eigen::Vector4d pdd2_poly_vec; +}; + +//! Residuals class +//! \brief Class for linear system residuals +class Residuals { + public: + Residuals(const std::shared_ptr& mesh, + const std::shared_ptr& vars, + const std::shared_ptr& curves); + + //! assemble the residual vector for demand driven simulation + void assemble_residual(); + + //! assemble the residual vector for pressure demand driven simulation (PDD) + void assemble_residual_pdd(); + + //! get the residual vector + const Eigen::VectorXd& residual_vec() const { return residual_vec_; } + + //! get the harzan-williams vectors + const HW_vectors& hw_vectors() const { return hw_vec_; } + + //! get the pressure demand driven vectors + const PDD_vectors& pdd_vectors() const { return pdd_vec_; } + + private: + //! the mesh ptr + std::shared_ptr mesh_; + //! curves ptr + std::shared_ptr curves_info_; + //! the vriable ptr + std::shared_ptr vars_; + //! node balance matrix + Eigen::SparseMatrix node_balance_mat_; + //! link headloss matrix + Eigen::SparseMatrix headloss_mat_; + //! Residual vector + Eigen::VectorXd residual_vec_; + //! Variable vector ptr + Eigen::VectorXd& variable_vec_; + //! number of nodes + Index nnodes_; + //! number of links + Index nlinks_; + + //! information for Hazan-williams equation + HW_vectors hw_vec_; + //! information for pressure demand driven (PDD) demand head equation + PDD_vectors pdd_vec_; + //! assemble the balance headloss matrix for fast residual computation + void assemble_balance_headloss_matrix(); + + //! assemble node balance residual (0-nnodes) + void assemble_node_balance_residual(); + + //! assemble demand head residual (nnodes-2*nnodes) + void assemble_demand_head_residual(); + + //! assemble demand head residual for pressure demand driven mode + void assemble_demand_head_residual_pdd(); + + //! assemble necessary information for pressure demand equation (PDD) + void update_pdd_vectors(); + + //! assemble headloss residual for pipes (hazan-williams equation) + void assemble_headloss_residual_pipe(); + //! assemble necessary information for headloss (hazan-williams equation) + void update_hw_vectors(); + + //! assemble headloss residual for pumps + void assemble_headloss_residual_pump(); + + //! get pump head gain for head pumps + double get_pump_headgain(const std::shared_ptr& pump, double link_flow); + //! assemble headloss residual for valves + void assemble_headloss_residual_valve(); + + //! get residual for open valves + double get_open_valve_residual(const std::shared_ptr& valve, + double link_flow); + //! get residual for active valves based on different valve types + double get_active_valve_residual(const std::shared_ptr& valve, + double link_flow); + //! assemble leak residual + void assemble_leak_residual(); +}; + +//! Jacobian class +//! \brief Class for linear system jacobian +class Jacobian { + public: + Jacobian(const std::shared_ptr& mesh, + const std::shared_ptr& vars, + const std::shared_ptr& residuals, + const std::shared_ptr& curves); + + //! Method to update jacobian matrix from the variable vector (Demand driven + //! mode) + void update_jacobian(); + //! Method to update jacobian matrix from the variable vector (Pressure demand + //! driven mode) + void update_jacobian_pdd(); + + //! Method to get jacobian matrix + const Eigen::SparseMatrix& jac_matrix() const { + return jac_; + } + + private: + //! the mesh ptr + std::shared_ptr mesh_; + //! curves ptr + std::shared_ptr residuals_; + //! curves ptr + std::shared_ptr curves_info_; + //! the vriable ptr + std::shared_ptr vars_; + //! Variable vector ptr + Eigen::VectorXd& variable_vec_; + //! Jacobian matrix + Eigen::SparseMatrix jac_; + //! map of for sub-jacobian triplets (row, col, value) + std::map>> sub_jac_trip_; + //! number of nodes + Index nnodes_; + //! number of links + Index nlinks_; + //! Initialize the jacobian matrix, the Jacobian matrix is splitted into 9 + //! submatrices: sub jacobian A: node_bal equation with respect to demand sub + //! jacobian B: node_bal equation with respect to flow sub jacobian C: + //! node_bal equation with respect to leak flow sub jacobian D: demand/head + //! equation with respect to head sub jacobian E: demand/head equation with + //! respect to flow sub jacobian F: headloss equation with respect to head sub + //! jacobian G: headloss equation with respect to flow sub jacobian H: leak + //! flow to flow sub jacobian I: leak flow to leak flow + void initialize_jacobian(); + void initialize_subjacA(); + void initialize_subjacBnF(); + void initialize_subjacC(); + void initialize_subjacDnE(); + void initialize_subjacG(); + void initialize_subjacHnI(); + + //! set jacobian constant based on connectivity + void set_jac_const(); + void set_jacF_const(); + + // Jac_d: pressure-demand equation + void update_jac_d(); + // Jac_f: for power pump only + void update_jac_f(); + // jac_g: headloss equation (harzen-william) + void update_jac_g_pipe(); + void update_jac_g_pump(); + void update_jac_g_valve(); + // helper function to get pump jacobian + double get_pump_jac(const std::shared_ptr& pump, + double link_flow); + // jac_h: leak equation + void update_jac_h(); +}; +} // namespace linear_system +} // namespace pipenetwork + +#endif // PIPE_NETWORK_MATRIX_ASSEMBLER_COMPONENTS_H diff --git a/include/mesh.h b/include/mesh.h index a5c2377..5bb41d6 100644 --- a/include/mesh.h +++ b/include/mesh.h @@ -1,90 +1,91 @@ -#ifndef PIPE_NETWORK_MESH_H_ -#define PIPE_NETWORK_MESH_H_ - -#include - -#include -#include -#include -#include -#include -#include - -#include "node.h" -#include "pipe.h" -#include "settings.h" +#ifndef PIPE_NETWORK_MESH_H +#define PIPE_NETWORK_MESH_H +#include +#include +#include "mesh_components.h" namespace pipenetwork { -//! Mesh class -//! \brief Class for mesh that contains node and pipe pointers +////! Mesh class +////! \brief Class for mesh that contains node and pipe pointers class Mesh { - public: - // Constructor with id + //! Constructor with id //! \param[in] id mesh id - explicit Mesh(unsigned id) : id_{id} {}; - - //! Destructor - ~Mesh() = default; - - //! Return id - //! \retval id_ id of the mesh - unsigned id() const { return id_; } - - //! Create nodal pointers and assign indices based on coordinates - //! \param[in] coords vector of the coordinates of the nodes - void create_nodes(const std::vector& coords); - - //! Create a pipe pointers and assign indices based on the nodes at its ends - //! \param[in] nodeid1 and nodeid2 indices of the nodes at pipe ends - //! \retval status to check whether all input pipe created successfully - bool create_pipes(const std::vector>& nodeids, - const std::vector& diameter, - const std::vector& roughness, - const std::vector& pipe_status); - - //! Return the number of nodes in the mesh - //! \retval nodes_.size() number of nodes - unsigned nnodes() const { return nodes_.size(); } - - //! Return the number of pipes in the mesh - //! \retval pipes_.size() number of pipes - unsigned npipes() const { return pipes_.size(); } - - //! Remove unconnected nodes from the mesh - void remove_unconnected_nodes(); - - //! Initialize discharges in pipes - void initialize_pipe_discharge( - const std::vector>& init_discharge = - std::vector>()); - void initialize_pipe_discharge(double init_discharge); - - //! Assign initial heads/elevation for nodes - //! \param[in] node_head vector of pair of nodal index and initial nodal head - void assign_node_head(const std::vector>& node_head); - void assign_node_elevation( - const std::vector>& node_head); - - //! Assign initial demand for nodes that have known discharge - //! \param[in] node_discharge vector of pair of nodal index and initial - //! discharge - void assign_node_demand( - const std::vector>& node_discharge); - - //! Make MatrixAssembler a friend class of mesh - friend class MatrixAssembler; + explicit Mesh(std::string& name) : name_{name} {}; + + //! Return name + //! \retval name_ name of the mesh + std::string name() const { return name_; } + + // //! Create mesh from input object + // //! \param[in] IO pointer to the input object + // void create_mesh_from_io(const std::shared_ptr& IO); + + //! Create junction pointers + //! \param[in] junc_props vector of junction properties + void create_nodes(const std::vector& junc_props, + const std::vector& res_props) { + mesh_nodes_ = std::make_shared(junc_props, res_props); + find_leak_nids(); + }; + + //! Create Reservoir pointers + //! \param[in] res_props vector of reservoir properties + void create_links(const std::vector& pipe_props, + const std::vector& pump_props, + const std::vector& valve_props) { + mesh_links_ = std::make_shared(pipe_props, pump_props, + valve_props, *mesh_nodes_); + }; + + //! Create graph for mesh + void create_mesh_graph() { + mesh_graph_ = std::make_shared(mesh_nodes_, mesh_links_); + find_iso_components_(); + } + + //! get nodes + std::shared_ptr nodes() const { return mesh_nodes_; } + //! get links + std::shared_ptr links() const { return mesh_links_; } + //! get links + std::shared_ptr mesh_graph() const { return mesh_graph_; } + //! get isolated nodes + const std::vector& iso_nodes() const { return iso_nodes_; } + //! get isolated links + const std::vector& iso_links() const { return iso_links_; } + //! get leak nids + const std::vector& leak_nids() const { return leak_nids_; } + + //! Print summary for the mesh + void print_summary(); private: - //! mesh id - unsigned id_{std::numeric_limits::max()}; - //! nodal id and corresponding nodal pointer - std::map> nodes_; - //! pipe id and corresponding pipe pointer - std::map> pipes_; + //! mesh name + std::string name_; + //! mesh nodes + std::shared_ptr mesh_nodes_; + //! mesh links + std::shared_ptr mesh_links_; + //! graph + std::shared_ptr mesh_graph_; + //! isolated nodes ids + std::vector iso_nodes_; + //! isolated link ids + std::vector iso_links_; + //! leak nids + std::vector leak_nids_; + //! Find isolated junctions and links for the mesh + void find_iso_components_(); + //! find isolated nodes + void find_iso_nodes_(); + //! find isolated links + void find_iso_links_(); + //! find leak node lids + void find_leak_nids(); }; } // namespace pipenetwork -#endif // PIPE_NETWORK_MESH_H_ +#endif // PIPE_NETWORK_MESH_H diff --git a/include/mesh_components.h b/include/mesh_components.h new file mode 100644 index 0000000..9b6d5f8 --- /dev/null +++ b/include/mesh_components.h @@ -0,0 +1,219 @@ +#ifndef PIPE_NETWORK_MESH_COMPONENTS_H +#define PIPE_NETWORK_MESH_COMPONENTS_H +#include "index_manager.h" +#include "junction.h" +#include "pipe.h" +#include "pump.h" +#include "reservoir.h" +#include "valve.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pipenetwork { +//! MeshNodes class +//! \brief Nodes information for a mesh +class MeshNodes { + public: + MeshNodes() = default; + //! Constructor for different mesh nodes + //! \param[in] junc_props junction properties + //! \param[in] res_props reservoir properties + MeshNodes(const std::vector& junc_props, + const std::vector& res_props); + + //! Get node ptr with node name + //! \param[in] node_name node name + //! \return node node ptr + std::shared_ptr get_node(const std::string& node_name) const; + + //! Get junctions map + tsl::ordered_map>& junctions() { + return junctions_; + } + + //! Get reservoirs map + tsl::ordered_map>& reservoirs() { + return reservoirs_; + } + //! Get nodes map + const tsl::ordered_map>& nodes() { + return nodes_; + } + + //! number of junctions + Index njunctions() const { return junctions_.size(); } + + //! number of reservoirs + Index nreservoirs() const { return reservoirs_.size(); } + + //! number of nodes + Index nnodes() const { return nodes_.size(); } + + private: + //! Internal id manager + IndexManager nid_manager_; + //! node name to id map + tsl::ordered_map name2nid_; + //! Junction map with respect to internal index + tsl::ordered_map> junctions_; + //! Reservoir map with respect to internal index + tsl::ordered_map> reservoirs_; + //! Nodes map with respect to internal index + tsl::ordered_map> nodes_; + + //! Add list of nodes + //! \param[in] props vector of node properties + template + void add_nodes(const std::vector& props); + + //! Add a single node (junction) + //! \param[in] junc_prop junction property + void add_node(const JunctionProp& junc_prop); + + //! Add a single node (reservoir) + //! \param[in] res_prop reservoir property + void add_node(const ReservoirProp& res_prop); +}; + +//! Meshlink class +//! \brief links information for a mesh +class MeshLinks { + public: + MeshLinks() = default; + //! Constructor for different mesh links + //! \param[in] pipe_props pipe properties + //! \param[in] pump_props pump properties + //! \param[in] valve_props valve properties + //! \param[in] mesh_nodes information of nodes inside the mesh + MeshLinks(const std::vector& pipe_props, + const std::vector& pump_props, + const std::vector& valve_props, + const MeshNodes& mesh_nodes); + + //! Get link ptr with link name + //! \param[in] link_name link name + //! \return link link ptr + std::shared_ptr get_link(const std::string& link_name) const; + + //! Get pipes map + tsl::ordered_map>& pipes() { return pipes_; } + + //! Get pumps map + tsl::ordered_map>& pumps() { return pumps_; } + + //! Get valves map + tsl::ordered_map>& valves() { return valves_; } + + //! Get links map + const tsl::ordered_map>& links() { + return links_; + } + + //! number of pipes + Index npipes() const { return pipes_.size(); } + + //! number of pumps + Index npumps() const { return pumps_.size(); } + + //! number of valves + Index nvalves() const { return valves_.size(); } + + //! number of nodes + Index nlinks() const { return links_.size(); } + + private: + //! Internal id manager + IndexManager lid_manager_; + //! Pipes map with respect to internal index + tsl::ordered_map> pipes_; + //! Pumps map with respect to internal index + tsl::ordered_map> pumps_; + //! Valves map with respect to internal index + tsl::ordered_map> valves_; + //! Link map with respect to internal index + tsl::ordered_map> links_; + //! Link map from link names to lid + tsl::ordered_map name2lid_; + + //! Add list of links + //! \param[in] props vector of link properties + //! \param[in] mesh_nodes information of nodes inside the mesh + template + void add_links(const std::vector& props, const MeshNodes& mesh_nodes); + + //! Add a single link (pipe) + //! \param[in] pipe_prop pipe property + void add_link(const std::shared_ptr& node1, + const std::shared_ptr& node2, const PipeProp& pipe_prop); + + //! Add a single link (pump) + //! \param[in] pipe_prop pump property + void add_link(const std::shared_ptr& node1, + const std::shared_ptr& node2, const PumpProp& pump_prop); + + //! Add a single link (valve) + //! \param[in] valve_prop valve property + void add_link(const std::shared_ptr& node1, + const std::shared_ptr& node2, + const ValveProp& valve_prop); +}; + +//! Mesh graph class +//! \brief graph information for a mesh +class MeshGraph { + public: + MeshGraph(const std::shared_ptr& mesh_nodes, + const std::shared_ptr& mesh_links) + : mesh_nodes_{mesh_nodes}, mesh_links_{mesh_links} { + compute_graph_info_(); + }; + + //! Get adjacency matrix of the mesh + const Eigen::SparseMatrix& adjacency_matrix() const { return A_; } + //! Get node to link map + const std::map>& node2link_map() const { + return node2link_; + } + //! Get node degrees + std::vector ndegree() const { return ndegree_; } + //! BFS + Eigen::VectorXd bfs(Index nid); + //! link name to id + Index lname2id(const std::string& link_name) const { + return mesh_links_->get_link(link_name)->id(); + } + //! node name to id + Index nname2id(const std::string& node_name) const { + return mesh_nodes_->get_node(node_name)->id(); + } + + protected: + //! mesh nodes + std::shared_ptr mesh_nodes_; + //! mesh links + std::shared_ptr mesh_links_; + //! adjacency matrix + Eigen::SparseMatrix A_; + //! node id to link id + std::map> node2link_; + //! node degrees + std::vector ndegree_; + + //! compute adjacency matrix + void compute_graph_info_(); + + //! compute node connectivity degrees + void compute_node_degrees_(); +}; +} // namespace pipenetwork + +#endif // PIPE_NETWORK_MESH_COMPONENTS_H diff --git a/include/mkl_unsym.h b/include/mkl_unsym.h new file mode 100644 index 0000000..9add0a0 --- /dev/null +++ b/include/mkl_unsym.h @@ -0,0 +1,57 @@ +#ifndef PIPE_NETWORK_MKL_UNSYM_H +#define PIPE_NETWORK_MKL_UNSYM_H + +#include +#include +#include +#include +#include + +#include "mkl_pardiso.h" +#include "solver.h" + +namespace pipenetwork { +namespace linear_system { + +//! Pipe network mkl unsymmetirc matrix solver class +//! \brief unsymmetric solver class using Intel MKL +class Mkl_unsym : public Solver { + public: + //! default constructor + Mkl_unsym(); + //! Call MKL Pardiso Unsymmetric solver + //! \retval status Return status of the solver + Eigen::VectorXd solve() override; + + protected: + //! Row index for csr format matrix + using Solver::ia_; + //! Column index for csr format matrix + using Solver::ja_; + //! Matrix values for csr format matrix + using Solver::a_; + //! Return the type of assembler for Factory + //! \retval assembler_type Eigen assembler + std::string assembler_type() const override { return "MKL Pardiso"; } + + private: + int mtype_ = 11; /* Real unsymmetric matrix */ + /* RHS and solution vectors. */ + int nrhs_ = 1; /* Number of right hand sides. */ + + /* Internal solver memory pointer pt, */ + /* 32-bit: int pt[64]; 64-bit: long int pt[64] */ + /* or void *pt[64] should be OK on both architectures */ + void* pt_[64]; + /* Pardiso control parameters. */ + int iparm_[64]; + int maxfct_, mnum_, phase_, error_, msglvl_; + /* Number of processors. */ + int num_procs_; + double ddum_; /* Double dummy */ + int idum_; /* Integer dummy. */ +}; +} // namespace linear_system +} // namespace pipenetwork + +#endif // PIPE_NETWORK_MKL_UNSYM_H diff --git a/include/node.h b/include/node.h index ea3b8b6..76c6248 100644 --- a/include/node.h +++ b/include/node.h @@ -1,137 +1,27 @@ #ifndef PIPE_NETWORK_NODE_H_ #define PIPE_NETWORK_NODE_H_ -#include -#include -#include +#include +#include + +#include "settings.h" namespace pipenetwork { //! Node class -//! \brief Class that stores the information about nodes +//! \brief Base Class that stores the information about nodes class Node { - public: - // Constructor with id and coordinates - //! \param[in] id node id - //! \param[in] coordinates coordinates of the node - Node(unsigned id, const Eigen::Vector3d& coordinates) - : id_{id}, coordinates_{coordinates} {} + explicit Node(const Index node_id) : node_id_{node_id} {}; //! Destructor - ~Node() = default; - - //! Copy constructor - Node(const Node&) = delete; - - //! Assignment operator - Node& operator=(const Node&) = delete; - - //! Move constructor - Node(Node&&) = delete; - - //! Return id - //! \retval id_ id of the node - unsigned id() const { return id_; } - - //! Return coordinates - //! \retval coordinates_ coordinates of the node - Eigen::Vector3d coordinates() const { return coordinates_; } - - //! Return number of connection - //! \retval nconnections_ number of connection to the node - unsigned nconnections() const { return nconnections_; } - - //! Assign hydraulic head at the node - //! \param[in] head hydraulic head at the node - void elevation(double head) { - elevation_ = head; - head_ = head; - ishead_ = true; - } - void head(double iter_head) { head_ = iter_head; } + virtual ~Node(){}; - //! Return hydraulic head - //! \retval head_ hydraulic head at the node - double elevation() const { return elevation_; } - double head() const { return head_; } - - //! Return if node is a reservoir - //! \retval isres_ reservoir status - bool isres() const { return isres_; } - - //! Assign discharge at the node - //! \param[in] discharge discharge at the node - void demand(double discharge) { - demand_ = discharge; - iter_demand_ = discharge; - isdischarge_ = true; - // if demand is negative, it is a reservoir or tank - if (discharge < 0) { - isres_ = true; - } - } - double iter_demand() { return iter_demand_; } - - void iter_demand(double iter_discharge) { iter_demand_ = iter_discharge; } - //! Return discharge - //! \retval discharge_ discharge at the node - double demand() const { return demand_; } - - //! Return discharge assignment status - //! \retval isdischarge_ discharge assignment status at the node - bool isdischarge() const { return isdischarge_; } - - //! min pressure - double min_pressure() const { return minimum_pressure_; } - - //! norm pressure - double norm_pressure() const { return normal_pressure_; }; - - //! pdd delta - double pdd_smooth_delta() const { return pdd_smoothing_delta_; } - //! pdd slope - double pdd_slope() const { return pdd_slope_; } - - //! polynomial coefficients for pressure demand equations - Eigen::VectorXd get_pdd_poly_coef_1(); - Eigen::VectorXd get_pdd_poly_coef_2(); + //! Return nodal id + Index id() const { return node_id_; } private: - //! node id - unsigned id_{std::numeric_limits::max()}; - //! nodal coordinates - Eigen::Vector3d coordinates_; - //! number of connection to the node - unsigned nconnections_{std::numeric_limits::max()}; - //! hydraulic head - double elevation_{0}; - double head_{0}; - //! discharge - double demand_{10}; - double iter_demand_{10}; - //! whether head is assigned - bool ishead_{false}; - //! whether discharge is assigned - bool isdischarge_{false}; - //! whether node is reservoir - bool isres_{false}; - //! minimum_pressure - double minimum_pressure_{0}; - //! normal pressure - double normal_pressure_{20}; - //! pdd smoothing delta - double pdd_smoothing_delta_{0.2}; - double pdd_slope_{1e-12}; - - //! Method to compute the coefficients of a smoothing polynomial - //! \param[in] x points on the x-axis at which the smoothing polynomial begins - //! and ends \param[in] f function evaluated at x1 and f2 \param[in] df - //! derivative evaluated at x1 and x2 \retval A vector with the smoothing - //! polynomail coefficients starting with the cubic term. - Eigen::VectorXd compute_poly_coefficients(const std::array& x, - const std::array& f, - const std::array& df); + Index node_id_; }; } // namespace pipenetwork diff --git a/include/pipe.h b/include/pipe.h index 19b0c28..983595a 100644 --- a/include/pipe.h +++ b/include/pipe.h @@ -1,153 +1,47 @@ -#ifndef PIPE_NETWORK_PIPE_H_ -#define PIPE_NETWORK_PIPE_H_ -#include - -#include -#include -#include - -#include "node.h" -#include "settings.h" +#ifndef PIPE_NETWORK_PIPE_H +#define PIPE_NETWORK_PIPE_H +#include "link.h" namespace pipenetwork { +//! Pipe Property +//! length, length of the pipe +//! diameter, diameter of the pipe +//! roughness, roughness of the pipe +//! status, status of the pipe (open or close) +struct PipeProp : LinkProp { + double length{std::numeric_limits::max()}; + double diameter{std::numeric_limits::max()}; + double roughness{std::numeric_limits::max()}; + double minor_loss_coeff{MINOR_LOSS_COEFF}; +}; //! Pipe class //! \brief Class that stores the information about pipes -class Pipe { - +class Pipe : public Link { public: - //! Constructor with pipe id, node pointers, diameter, status and max - //! allowable velocity - //! \param[in] id pipe id - //! \param[in] nodes array of node pointers - //! \param[in] diameter of the pipe - //! \param[in] roughness pipe roughness for Hazen-Williams equation - //! \param[in] status of the pipe, true for open, flase for close - //! \param[in] maximum allowable velocity - Pipe(unsigned id, - const std::array, 2>& nodes, - double diameter, double roughness, bool status, - double max_velocity = std::numeric_limits::max()); - - //! Destructor - ~Pipe() { nodes_.fill(nullptr); } - - //! Copy constructor - Pipe(const Pipe&) = delete; - - //! Assignment operator - Pipe& operator=(const Pipe&) = delete; - - //! Move constructor - Pipe(Pipe&&) = delete; - - //! Return id - //! \retval id_ id of the pipe - unsigned id() const { return id_; } - - //! Return length of the pipe - //! \retval length_ pipe length - double length() { return length_; } - - //! Assign Dracy friction factor - //! \param[in] darcy_friction Darcy friction factor of the pipe - void darcy_friction(double darcy_friction) { - darcy_friction_ = darcy_friction; - } - - //! Assign discharge to the pipe - //! \param[in] iter_discharge dischargeof the pipe during iteration - void iter_discharge(double iter_discharge) { - iter_discharge_ = iter_discharge; - } + //! Constructor for a pipe + //! \param[in] link_id link id + //! \param[in] node1 one end node + //! \param[in] node2 the other end node + //! \param[in] pipe_prop struct with properties for the pipe + Pipe(Index link_id, const Node& node1, const Node& node2, + const PipeProp& pipe_prop) + : Link(link_id, node1, node2), property_{pipe_prop} {}; - //! Initialize discharge with input value - //! \param[in] discharge input discharge value of the pipe - void initialize_discharge(double discharge = 0.001) { - discharge_ = discharge; - iter_discharge_ = discharge_; - } + //! Virtual destructor + ~Pipe() override{}; - //! Calculate discharge using Darcy-Weisbach equation - //! Calculate discharge in m^3/s from head difference in m - //! SI unit meter and second are used in the whole equation - void compute_discharge_darcy_weisbach(); + //! Return pipe property + const PipeProp& property() const { return property_; } - //! Calculate discharge using Hazen-Williams equation - //! Calculate discharge in m^3/s from head difference in m - //! SI unit meter and second are used in the whole equation - void compute_discharge_hazen_williams(); - - //! Calculate and return derivative of Hazen-Williams equation with respect to - //! pipe discharge SI unit meter and second are used in the whole equation - //! \retval derivative of Hazen-Williams equation with respect to pipe - //! discharge - double deriv_hazen_williams_discharge(); - - //! Return calculated discharge in the pipe - //! \retval discharge_ discharge in the pipe - double discharge() const { return discharge_; } - - //! Calculate head loss over the pipe using Darcy-Weisbach equation: - //! Calculate head loss in m from discharge in m^3/s - //! SI unit meter and second are used in the whole equation - void compute_headloss_darcy_weisbach(); - - //! Calculate headloss over the pipe using Hazen-Williams equation: - //! Calculate head loss in m from discharge in m^3/s - //! SI unit meter and second are used in the whole equation - void compute_headloss_hazen_williams(); - - //! Return calculated headloss over the pipe - //! \retval headloss_ headloss over the pipe - double headloss() const { return headloss_; } - - //! Return assigned discharge during iteration of the pipe - //! \retval iter_discharge_ discharge of the pipe during iteration - double iter_discharge() const { return iter_discharge_; } - - //! calculate maximum allowable discharge based on ridius and maximum - //! allowable velocity \retval max_discharge maximun allowable discharge - double max_discharge() { return (max_velocity_ * M_PI * pow(radius_, 2)); } - - //! Return pipe open status - //! \retval isopen_ whether pipe open or close - bool isopen() const { return isopen_; } - - //! Return pipe broken status - //! \retval isbroken_ pipe broken status - bool isbroken() const { return isbroken_; } - - //! Return an array of pointers point to the nodes at pipe end - const std::array, 2> nodes(); + //! flowrate + double flowrate{INIT_FLOWRATE}; private: - //! pipe id - unsigned id_{std::numeric_limits::max()}; - //! array of node pointers which form the pipe - std::array, 2> nodes_; - //! discharge in the pipe - double discharge_{std::numeric_limits::max()}; - //! discharge assigned to the pipe during iteration - double iter_discharge_{std::numeric_limits::max()}; - //! headloss over the pipe - double headloss_{std::numeric_limits::max()}; - //! radius of the pipe - double radius_{std::numeric_limits::max()}; - //! length of the pipe - double length_; - //! Darcy friction factor of the pipe used in Darcy-Weisbach equation - double darcy_friction_{std::numeric_limits::max()}; - //! pipe roughness coefficient used in Hazen-Williams equation - double pipe_roughness_{std::numeric_limits::max()}; - //! maximum allowable velocity of flow in the pipe - double max_velocity_{std::numeric_limits::max()}; - //! whether the pipe is broken - bool isbroken_{false}; - //! whether the pipe is open - bool isopen_{true}; + //! pipe properties + PipeProp property_; }; -} // namespace pipenetwork -#endif // PIPE_NETWORK_PIPE_H_ +} // namespace pipenetwork +#endif // PIPE_NETWORK_PIPE_H diff --git a/include/pump.h b/include/pump.h new file mode 100644 index 0000000..19e76ac --- /dev/null +++ b/include/pump.h @@ -0,0 +1,42 @@ +#ifndef PIPE_NETWORK_PUMP_H +#define PIPE_NETWORK_PUMP_H + +#include "link.h" + +namespace pipenetwork { +//! Pump Property +//! type pump type +//! curve_name pump head curve id +//! speed speed for the pump +//! pattern pattern for speed setting +struct PumpProp : LinkProp { + PumpType type{PumpType::POWERPUMP}; + int curve_id{-1}; + double power{PUMP_POWER}; + double speed{PUMP_SPEED}; +}; + +//! Pump class +//! \brief Class that stores the information about pumps +class Pump : public Link { + public: + //! Constructor with pump property, which contains all the information for + //! the valve \param[in] pipe_prop struct with properties for the pipe + Pump(Index link_id, const Node& node1, const Node& node2, + const PumpProp& pump_prop) + : Link(link_id, node1, node2), property_{pump_prop} {}; + + //! Virtual destructor + ~Pump() override{}; + + //! Return pump property + const PumpProp& property() const { return property_; } + + private: + //! valve information + PumpProp property_; +}; + +} // namespace pipenetwork + +#endif // PIPE_NETWORK_PUMP_H diff --git a/include/reservoir.h b/include/reservoir.h new file mode 100644 index 0000000..b34fe4e --- /dev/null +++ b/include/reservoir.h @@ -0,0 +1,42 @@ +#ifndef PIPE_NETWORK_RESERVOIR_H +#define PIPE_NETWORK_RESERVOIR_H + +#include "node.h" + +namespace pipenetwork { +//! Reservoir Property +//! name junction name +//! head hydraulic head for the reservoir for the junction +struct ReservoirProp { + std::string name{"junction"}; + double head{std::numeric_limits::min()}; +}; + +class Reservoir : public Node { + public: + //! Constructor with id abd head + //! \param[in] id reservoir id + //! \param[in] head base head for the reservoir + Reservoir(const Index id, const ReservoirProp res_prop) + : Node(id), property_{res_prop} {}; + + //! Return nodal info + inline const ReservoirProp property() const { return property_; } + + //! Getter for head + inline const double head() const { return property_.head; } + + //! Setter for head + inline void head(const double head) { property_.head = head; } + + //! Discharge from the reservoir, mutable + double discharge = 0; + + private: + //! Reservoir information + ReservoirProp property_; +}; + +} // namespace pipenetwork + +#endif // PIPE_NETWORK_RESERVOIR_H diff --git a/include/settings.h b/include/settings.h index 7d3b96b..0d4570c 100644 --- a/include/settings.h +++ b/include/settings.h @@ -1,12 +1,41 @@ #ifndef PIPE_NETWORK_SETTING_H_ #define PIPE_NETWORK_SETTING_H_ - +#include +namespace pipenetwork { //! define alias of type for index -using Index = unsigned long long; +using Index = unsigned long; -namespace pipenetwork { -//! define gravitational acceleration in x, y, z direction -const Eigen::Vector3d Gravity(0.00, 0.00, 9.81); +//! node settings +const double PI{M_PI}; +const double G{9.81}; +const double HW_COEFF{10.666829500036352}; +const double LEAK_COEFF{0.75}; +const double INIT_FLOWRATE{1E-3}; + +//! pressure demand driven simulation (PDD) settings +const double MIN_PRESSURE{1e-4}; +const double NORMAL_PRESSURE{20}; +const double PDD_DELTA{0.2}; +const double PDD_SLOPE{1e-11}; + +//! link settings +enum class PumpType { POWERPUMP, HEADPUMP }; +enum class ValveType { PRVALVE, FCVALVE, TCVALVE, ISOVALVE }; +enum class LinkStatus { OPEN, CLOSED, ACTIVE }; +const double PUMP_POWER{50}; +const double PUMP_SPEED{1}; +const double MINOR_LOSS_COEFF{0}; +const double VALVE_DIAMETER{0.3048}; + +//! constant for modified hazen-williams formula +const double HW_Q1{0.0002}; +const double HW_Q2{0.0004}; +const double HW_M{0.001}; + +//! pump settings +const double PUMP_M = -0.00000000001; +const double PUMP_Q1 = 0.0; +const double PUMP_Q2 = 1.0e-8; } // namespace pipenetwork #endif // PIPE_NETWORK_SETTING_H_ diff --git a/include/solver.h b/include/solver.h index 250cab9..2c8c7f6 100644 --- a/include/solver.h +++ b/include/solver.h @@ -1,68 +1,64 @@ #ifndef PIPE_NETWORK_SOLVER_H_ #define PIPE_NETWORK_SOLVER_H_ -#include - #include "matrix_assembler.h" -#include "settings.h" +#include +#include namespace pipenetwork { +namespace linear_system { //! Pipe network solver base class //! \brief Base class for the pipe network solver class Solver { public: - //! Constructor with max iterations and tolerance - Solver(unsigned max_iter, double tolerance) - : max_iter_{max_iter}, tolerance_{tolerance} {} + //! Default constructor for noniterative solver + Solver() = default; - // using VectorX = typename Eigen::VectorXd; - // using SparseMatrix = typename Eigen::SparseMatrix; + //! Virtual Solver + virtual ~Solver(){}; //! Copy Matrix A, Vectors b and x //! \param[in] mat_a_ pointer to assembled A matrix //! \param[in] vec_x_ pointer to assembled x vector //! \param[in] vec_b_ pointer to assembled b vector - void assembled_matrices(std::shared_ptr> mat_a, - std::shared_ptr vec_x, - std::shared_ptr vec_b) { - mat_a_ = mat_a; - vec_x_ = vec_x; - vec_b_ = vec_b; - } - //! Restrain vector - void restrains(const Eigen::VectorXd& restraints) { - vrestraints_ = restraints; + void assembled_matrices( + const std::shared_ptr& matrix_assember) { + matrix_assembler_ = matrix_assember; + + // pointers for sparse matrix info + ia_ = const_cast(matrix_assembler_->jac_matrix().outerIndexPtr()); + ja_ = const_cast(matrix_assembler_->jac_matrix().innerIndexPtr()); + a_ = const_cast(matrix_assembler_->jac_matrix().valuePtr()); + + // matrix a basic information + rowsA_ = matrix_assembler_->jac_matrix().rows(); + colsA_ = matrix_assembler_->jac_matrix().cols(); + nnzA_ = matrix_assembler_->jac_matrix().nonZeros(); } //! Solve - virtual bool solve() = 0; + virtual Eigen::VectorXd solve() = 0; + virtual std::string assembler_type() const = 0; - //! number of iterations - unsigned niterations() const { return niterations_; } + protected: + std::shared_ptr matrix_assembler_; - //! Delta - double delta() const { return delta_; } + //! Row index for csr format matrix + int* ia_{nullptr}; + //! Column index for csr format matrix + int* ja_{nullptr}; - protected: - //! Maximum number of iterations - unsigned max_iter_; - //! Tolerance - double tolerance_; - //! Displacement restraint - Eigen::VectorXd vrestraints_; - //! Iterations - unsigned niterations_{0}; - //! Delta - double delta_{std::numeric_limits::quiet_NaN()}; - //! Displacement vector - std::shared_ptr vec_x_; - //! Force vector - std::shared_ptr vec_b_; - //! Sparse Stiffness Matrix - std::shared_ptr> mat_a_; + int rowsA_ = 0; /* number of rows of A */ + int colsA_ = 0; /* number of columns of A */ + int nnzA_ = 0; /* number of nonzeros of A */ + int baseA_ = 0; + + //! Matrix values for csr format matrix + double* a_{nullptr}; }; +} // namespace linear_system } // namespace pipenetwork #endif // PIPE_NETWORK_SOLVER_H_ diff --git a/include/valve.h b/include/valve.h new file mode 100644 index 0000000..68cbb53 --- /dev/null +++ b/include/valve.h @@ -0,0 +1,42 @@ +#ifndef PIPE_NETWORK_VALVE_H +#define PIPE_NETWORK_VALVE_H + +namespace pipenetwork { +//! Valve Property +//! type valve type +//! setting pressure setting for PRV, PSV, or PBV, flow setting for FCV, loss +//! coefficient for TCV, +struct ValveProp : LinkProp { + ValveType type{ValveType::PRVALVE}; + double setting{0}; + double diameter{VALVE_DIAMETER}; + double minor_loss_coeff{MINOR_LOSS_COEFF}; +}; + +//! Valve class +//! \brief Class that stores the information about pipes +class Valve : public Link { + public: + //! Constructor for a VALVE + //! \param[in] link_id link id + //! \param[in] node1 one end node + //! \param[in] node2 the other end node + //! \param[in] valve_prop struct with properties for the valve + Valve(Index link_id, const Node& node1, const Node& node2, + const ValveProp& valve_prop) + : Link(link_id, node1, node2), property_{valve_prop} {}; + + //! Virtual destructor + ~Valve() override{}; + + //! Return Valve property + const ValveProp& property() const { return property_; } + + private: + //! valve properties + ValveProp property_; +}; + +} // namespace pipenetwork + +#endif // PIPE_NETWORK_VALVE_H diff --git a/include/valve_graph.h b/include/valve_graph.h new file mode 100644 index 0000000..9f9352f --- /dev/null +++ b/include/valve_graph.h @@ -0,0 +1,66 @@ +#ifndef PIPE_NETWORK_VALVE_GRAPH_H +#define PIPE_NETWORK_VALVE_GRAPH_H + +#include "mesh_components.h" +#include "valve_graph_components.h" + +namespace pipenetwork { + +class ValveGraph : MeshGraph { + public: + ValveGraph(const std::shared_ptr& mesh_nodes, + const std::shared_ptr& mesh_links, + const std::vector& iso_valve_props); + + Eigen::SparseMatrix& node_pipe_mtx() { return node_pipe_mtx_; } + + Eigen::SparseMatrix& valve_loc_mtx() { return valve_loc_mtx_; } + + isolation::IsoSegments& segments() { return iso_segments_; } + + isolation::IsoSeg pname2segment(const std::string& p_name); + + void fail_valves(const std::vector& broken_valves); + + std::vector> segment_components( + const std::vector& pipes2iso); + + Index nsegs() { return iso_segments_.nsegs(); } + + //! construct isolation segments for the network + void initialize_iso_segs(); + + private: + //! Isolation valves in the valve graph + isolation::IsoValves iso_valves_; + //! Isolation segments in the valve graph + isolation::IsoSegments iso_segments_; + + //! node pipe matrix + Eigen::SparseMatrix node_pipe_mtx_; + //! valve location matrix + Eigen::SparseMatrix valve_loc_mtx_; + //! valve deficiency matrix + Eigen::SparseMatrix valve_def_mtx_; + //! lookup tables for the stored matrices + isolation::IsoMtxHelper mtx_helper; + + //! construct the node_pipe_mtx_ + void construct_node_pipe_mtx(); + + //! construct the valve location matrix + void construct_valve_loc_mtx(); + + //! construct the valve defeciency matrix + void construct_valve_def_mtx(); + + //! construct the col2row, row2col look up tables + void construct_vdef_idx_table(); + + // Eigen::SparseMatrix merge_segments( + // Index vid, Eigen::SparseMatrix seg_valve_mtx); +}; + +} // namespace pipenetwork + +#endif // PIPE_NETWORK_VALVE_GRAPH_H diff --git a/include/valve_graph_components.h b/include/valve_graph_components.h new file mode 100644 index 0000000..768bbff --- /dev/null +++ b/include/valve_graph_components.h @@ -0,0 +1,164 @@ +#ifndef PIPE_NETWORK_VALVE_GRAPH_COMPONENTS_H +#define PIPE_NETWORK_VALVE_GRAPH_COMPONENTS_H +#include "mesh_components.h" + +namespace pipenetwork { +namespace isolation { +//! Isolate Valve Property +//! name Valve name +//! on_node node name that the valve is closed to +//! on_pipe pipe name that the valve is on +struct ISOVProp { + std::string name{"junction"}; + std::string on_node{"Null"}; + std::string on_pipe{"Null"}; +}; +struct IsoSeg { + Index sid; + std::set pids; + std::set nids; + std::set vids; +}; +//! lookup tables for matrices used by the isolation finding algorithm +struct IsoMtxHelper { + //! Index lookup table for the valve deficieny matrix (col2row) + std::map> valve_def_col2row; + //! Index lookup table for the valve deficieny matrix (row2col) + std::map> valve_def_row2col; + //! Index lookup table for the valve location matrix (col2row) + std::map> valve_loc_col2row; + //! Index lookup table for the valve location matrix (row2col) + std::map> valve_loc_row2col; +}; + +struct IsoSegHelper { + static const unsigned EIGEN_THRE{100}; + static constexpr double NON_ZERO_THRE{1E-8}; + static Eigen::SparseMatrix shrink_mtx( + Eigen::SparseMatrix& matrix, + const std::vector& rowsToRemove, + const std::vector& colToRemove); + + static Eigen::SelfAdjointEigenSolver small_matrix_eigen_info( + Eigen::SparseMatrix& matrix); + + static Eigen::SparseMatrix create_graph_laplacian( + const Eigen::SparseMatrix& adj_mtx); + + static std::vector find_zero_eval_loc(const Eigen::VectorXd& evals); + + static std::vector find_non_zero_evac_loc(const Eigen::VectorXd& evec); +}; + +class IsoValves { + public: + IsoValves() = default; + + IsoValves(const std::vector& iso_valve_props); + + //! Get the iso valves map + const std::map& iso_valves() { return iso_valves_; } + + //! Query the vid from the position in the valve location matrix + Index loc2vid(const std::pair location) const { + return loc2vid_.at(location); + } + + //! Set location to vid map + void loc2vid(std::pair location, Index vid) { + loc2vid_[location] = vid; + } + + Index vname2vid(const std::string& vname) { + try { + return vname2vid_.at(vname); + } catch (...) { + throw std::runtime_error("Invalid valve name! "); + } + }; + + const Index nvalves() const { return iso_valves_.size(); } + + private: + //! Internal valve id manager + IndexManager vid_manager_; + //! Valve properties map + std::map iso_valves_; + //! valve id map with the position in the valve location matrix as the key + std::map, Index> loc2vid_; + //! valve id map with the valve name as the key + std::map vname2vid_; +}; + +class IsoSegments { + // TODO: Replace eigenvalue decomposition to simple BFS + public: + IsoSegments() = default; + + void construct_iso_segs(const IsoMtxHelper& mtx_helper, + pipenetwork::isolation::IsoValves& iso_valves, + std::set& pids); + + const isolation::IsoSeg pid2seg(Index pid); + + const tsl::ordered_map& iso_segment() { return iso_segments_; } + + const Index nsegs() { return iso_segments_.size(); } + + Eigen::SparseMatrix& seg_valve_mtx() { return seg_valve_mtx_; } + + Eigen::SparseMatrix& seg_valve_adj_mtx() { + return seg_valve_adj_mtx_; + } + + void merge_segments(Index broken_vid); + + std::vector> + get_segment_components(const std::set& segs2iso); + + private: + //! Internal segment id manager + IndexManager sid_manager_; + //! Segment map + tsl::ordered_map iso_segments_; + //! pid to sid + tsl::ordered_map pid2sid_; + //! segment valve matrix + Eigen::SparseMatrix seg_valve_mtx_; + //! Adjacency matrix for segments valve + Eigen::SparseMatrix seg_valve_adj_mtx_; + //! Removed vids + std::vector removed_vids_; + + void construct_seg_valve_mtx(pipenetwork::isolation::IsoValves& iso_valves); + + void construct_seg_valve_adj_mtx(); + + //! get the corresponding isolation segment from a pipe id + IsoSeg get_single_seg(const IsoMtxHelper& mtx_helper, Index pid); + + //! get the isolation valves that need to be closed from the corresponding + //! segment pids and segment nids + std::set get_seg_valves( + const pipenetwork::isolation::IsoMtxHelper& mtx_helper, + const pipenetwork::isolation::IsoValves& iso_valves, + const std::set& pids, const std::set& nids); + + void merge_two_segment(Index sid_from, Index sid_to, Index vid); + + void update_seg_valve_mtx(const std::vector& sids_remove); + + std::vector find_merging_sids(Index broken_vid); + + std::vector> einfo2components( + const Eigen::VectorXd& eigen_vals, const Eigen::MatrixXd& eigen_vecs); + + void reindex(); + + void update_pid2sid(); +}; + +} // namespace isolation +} // namespace pipenetwork + +#endif // PIPE_NETWORK_VALVE_GRAPH_COMPONENTS_H diff --git a/src/.clang-format b/src/.clang-format index 7605de0..cae777b 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -1,5 +1,5 @@ --- -# BasedOnStyle: CUED GeoMechanics +# BasedOnStyle: Cityscape AccessModifierOffset: -1 ConstructorInitializerIndentWidth: 4 AlignEscapedNewlinesLeft: true diff --git a/src/LU_solver.cc b/src/LU_solver.cc new file mode 100644 index 0000000..e49b0af --- /dev/null +++ b/src/LU_solver.cc @@ -0,0 +1,15 @@ +#include "LU_solver.h" +#include "factory.h" + +static Register + registry("LU"); + +Eigen::VectorXd pipenetwork::linear_system::LUSolver::solve() { + // std::cout << "residual in linear solver: " << *vec_b_ << std::endl; + LU_solver_.analyzePattern(matrix_assembler_->jac_matrix()); + // Compute the numerical factorization + LU_solver_.factorize(matrix_assembler_->jac_matrix()); + // Use the factors to solve the linear system + return LU_solver_.solve(matrix_assembler_->residual_vector()); +} \ No newline at end of file diff --git a/src/curves.cc b/src/curves.cc new file mode 100644 index 0000000..3986cd2 --- /dev/null +++ b/src/curves.cc @@ -0,0 +1,175 @@ +#include "curves.h" + +// Returns the A, B, C coefficients for a 1-point or a 3-point pump curve. +// Coefficient can only be calculated for pump curves. +// +// For a single point curve the coefficients are generated according to the +// following equation: +// +// A = 4/3 * H_1 +// B = 1/3 * H_1/Q_1^2 +// C = 2 +// +// For a three point curve the coefficients are generated according to the +// following equation: When the first point is a zero flow: (All INP files we +// have come across) +// +// A = H_1 +// C = ln((H_1 - H_2)/(H_1 - H_3))/ln(Q_2/Q_3) +// B = (H_1 - H_2)/Q_2^C +// +// When the first point is not zero, numpy fsolve is called to solve the +// following system of equation: +// +// H_1 = A - B*Q_1^C +// H_2 = A - B*Q_2^C +// H_3 = A - B*Q_3^C +// +// Multi point curves are currently not supported +pipenetwork::Pump_curve_prop::Pump_curve_prop( + std::string& curve_name, + std::vector>& curve_point) + : name{curve_name}, points{curve_point} { + num_points = points.size(); + double A = 0.; + double B = 0.; + double C = 0.; + if (num_points == 1) { + auto Q_1 = points[0].first; + auto H_1 = points[0].second; + + A = (4.0 / 3.0) * H_1; + B = (1.0 / 3.0) * (H_1 / (std::pow(Q_1, 2))); + C = 2; + } else if (num_points == 3) { + auto Q_1 = points[0].first; + auto H_1 = points[0].second; + auto Q_2 = points[1].first; + auto H_2 = points[1].second; + auto Q_3 = points[2].first; + auto H_3 = points[2].second; + + if (Q_1 == 0.0) { + A = H_1; + C = std::log((H_1 - H_2) / (H_1 - H_3)) / std::log(Q_2 / Q_3); + B = (H_1 - H_2) / (std::pow(Q_2, C)); + } + //! TODO: HEAD_CURVE_COEFFICIENTS FOR 3 POINTS WITH NONZERO STARTING POINT + } else { + throw std::runtime_error( + "Coefficient for Multipoint pump curves cannot be generated"); + } + if (A < 0 || B < 0 || C < 0) { + throw std::runtime_error( + "Value of pump head curve coefficient is negative, which is not " + "allowed"); + } + head_curve_coefficients = {A, B, C}; + if (C < 1) { + poly_coefficients = get_pump_poly_coefficients(); + } else { + line_param = get_pump_line_params(); + } +} + +Eigen::Vector4d pipenetwork::Pump_curve_prop::get_pump_poly_coefficients() { + + auto f1 = PUMP_M * PUMP_Q1 + head_curve_coefficients[0]; + auto f2 = head_curve_coefficients[0] - + head_curve_coefficients[1] * + std::pow(PUMP_Q2, head_curve_coefficients[2]); + auto df1 = PUMP_M; + auto df2 = -head_curve_coefficients[1] * head_curve_coefficients[2] * + std::pow(PUMP_Q2, (head_curve_coefficients[2] - 1.0)); + + return compute_poly_coefficients({PUMP_Q1, PUMP_Q2}, {f1, f2}, {df1, df2}); +} + +Eigen::Vector2d pipenetwork::Pump_curve_prop::get_pump_line_params() { + auto q_bar = std::pow( + (PUMP_M / (-head_curve_coefficients[1] * head_curve_coefficients[2])), + (1.0 / (head_curve_coefficients[2] - 1.0))); + auto h_bar = + head_curve_coefficients[0] - + head_curve_coefficients[1] * std::pow(q_bar, head_curve_coefficients[2]); + return {q_bar, h_bar}; +} + +Eigen::Vector4d pipenetwork::compute_poly_coefficients( + const std::array& x, const std::array& f, + const std::array& df) { + Eigen::Vector4d ret; + double a = + (2 * (f[0] - f[1]) - (x[0] - x[1]) * (df[1] + df[0])) / + (std::pow(x[1], 3) - std::pow(x[0], 3) + 3 * x[0] * x[1] * (x[0] - x[1])); + double b = + (df[0] - df[1] + 3 * ((std::pow(x[1], 2) - std::pow(x[0], 2)) * a)) / + (2 * (x[0] - x[1])); + double c = df[1] - 3 * std::pow(x[1], 2) * a - 2 * x[1] * b; + double d = f[1] - std::pow(x[1], 3) * a - std::pow(x[1], 2) * b - x[1] * c; + ret = {a, b, c, d}; + return ret; +} + +void pipenetwork::Curves::add_pump_curves( + const std::vector& head_pump_props) { + int count = 0; + for (const auto& pump_prop : head_pump_props) { + head_pump_curves_[pump_prop.name] = pump_prop; + pump_str_int_[pump_prop.name] = count; + pump_int_str_[count] = pump_prop.name; + ++count; + } +} + +Eigen::Vector4d pipenetwork::Curves::compute_hw_poly_vec() { + auto x1 = HW_Q1; + auto x2 = HW_Q2; + auto f1 = HW_M * HW_Q1; + auto f2 = std::pow(HW_Q2, 1.852); + auto df1 = HW_M; + auto df2 = 1.852 * std::pow(HW_Q2, 0.852); + return compute_poly_coefficients({x1, x2}, {f1, f2}, {df1, df2}); +} + +Eigen::Vector4d pipenetwork::Curves::compute_pdd1_poly_vec() { + double x1 = MIN_PRESSURE; + double f1 = 0.0; + double x2 = MIN_PRESSURE + PDD_DELTA; + double f2 = + std::pow(((x2 - MIN_PRESSURE) / (NORMAL_PRESSURE - MIN_PRESSURE)), 0.5); + double df1 = PDD_SLOPE; + double df2 = + 0.5 * + std::pow(((x2 - MIN_PRESSURE) / (NORMAL_PRESSURE - MIN_PRESSURE)), + (-0.5)) * + 1.0 / (NORMAL_PRESSURE - MIN_PRESSURE); + return compute_poly_coefficients({x1, x2}, {f1, f2}, {df1, df2}); +} + +Eigen::Vector4d pipenetwork::Curves::compute_pdd2_poly_vec() { + double x1 = NORMAL_PRESSURE - PDD_DELTA; + double f1 = + std::pow(((x1 - MIN_PRESSURE) / (NORMAL_PRESSURE - MIN_PRESSURE)), 0.5); + double x2 = NORMAL_PRESSURE; + double f2 = 1; + double df1 = + 0.5 * + std::pow(((x1 - MIN_PRESSURE) / (NORMAL_PRESSURE - MIN_PRESSURE)), + (-0.5)) * + 1.0 / (NORMAL_PRESSURE - MIN_PRESSURE); + double df2 = PDD_SLOPE; + return compute_poly_coefficients({x1, x2}, {f1, f2}, {df1, df2}); +} + +Eigen::Vector4d pipenetwork::Curves::compute_leak_poly_vec(double leak_area) { + double x1 = 0.0; + double f1 = 0.0; + double df1 = 1.0e-11; + double x2 = 1e-4; + double f2 = LEAK_COEFF * leak_area * std::pow((2 * G * x2), 0.5); + double df2 = 0.5 * LEAK_COEFF * leak_area * std::pow((2 * G), 0.5) * + std::pow(x2, -0.5); + + return compute_poly_coefficients({x1, x2}, {f1, f2}, {df1, df2}); +} diff --git a/src/eigen_gmres.cc b/src/eigen_gmres.cc deleted file mode 100644 index f34d91c..0000000 --- a/src/eigen_gmres.cc +++ /dev/null @@ -1,59 +0,0 @@ -#include "eigen_gmres.h" - -// Eigen GMRES Solver -bool pipenetwork::EigenGMRES::solve() { - bool convergence = false; - const size_t n = vec_b_->size(); - Eigen::VectorXd x_diff(n); - - // Apply restraints (only works when the known values are 0) - //(*vec_b_) = (*vec_b_).array() * vrestraints_.array(); - /* - // Apply Drichlet boundary condition (works for arbitrary known values) - Eigen::VectorXd x_fixed(n); - x_fixed = (*vec_x_).array() - (*vec_x_).array() * vrestraints_.array(); - (*vec_b_) -= (*mat_a_) * x_fixed; - for (int i = 0; i < n; i++) { - if (vrestraints_(i) == 0) { - vec_b_->coeffRef(i) = x_fixed(i); - for (int j = 0; j < n; j++) { - mat_a_->coeffRef(i, j) = 0; - mat_a_->coeffRef(j, i) = 0; - } - mat_a_->coeffRef(i, i) = 1; - } - } - */ - // Use GMRES solver in Eigen to solve - Eigen::GMRES> gmres(*mat_a_); - gmres.setMaxIterations(max_iter_); - gmres.setTolerance(tolerance_); - - x_diff = gmres.solve(*vec_b_); - x_diff = x_diff.array(); - // x_diff = x_diff.array() * vrestraints_.array(); - - if (gmres.info() == 0) { - convergence = true; - - // Update x (variables) in the system - (*vec_x_) += x_diff; - - // Update delta and iterations - this->delta_ = gmres.error(); - this->niterations_ = gmres.iterations(); - - std::cout << "Iteration: " << niterations_ << " of " << max_iter_ - << "; delta: " << delta_ << std::endl; - } else if (gmres.info() == 1) { - throw std::runtime_error( - "The provided data did not satisfy the prerequisites."); - } else if (gmres.info() == 2) { - throw std::runtime_error("Iterative procedure did not converge."); - } else { - throw std::runtime_error( - "The inputs are invalid, or the algorithm has been improperly called."); - } - - return convergence; -} diff --git a/src/hydralic_sim.cc b/src/hydralic_sim.cc new file mode 100644 index 0000000..ba23627 --- /dev/null +++ b/src/hydralic_sim.cc @@ -0,0 +1,121 @@ +#include "hydralic_sim.h" + +bool pipenetwork::Hydralic_sim::run_simulation(double NR_tolerance, + int max_nr_steps) { + + solver_->assembled_matrices(assembler_); + for (unsigned nr_iter = 0; nr_iter < max_nr_steps; ++nr_iter) { + + assembler_->system_update(); + init_variable_ = assembler_->variable_vector(); + + auto x_diff = solver_->solve(); + line_search_update(x_diff); + auto res_norm = assembler_->residual_vector().norm(); + + if (debug_) { + std::cout << "niter = " << nr_iter << std::endl; + std::cout << "residual norm = " << assembler_->residual_vector().norm() + << std::endl; + // std::cout << "variable " << assembler_->variable_vector() << + // std::endl; std::cout << "residual " << + // assembler_->residual_vector() << std::endl; + } + + if (res_norm < NR_tolerance) { + return true; + } + } + return false; +} + +void pipenetwork::Hydralic_sim::line_search_update( + const Eigen::VectorXd& x_diff) { + double alpha = 1.0; // start line search with the original x_diff + + auto old_res = assembler_->residual_vector().norm(); + Eigen::VectorXd& variables = assembler_->variable_vector(); + + for (int bt_iter = 0; bt_iter < bt_max_iter_; ++bt_iter) { + + variables = init_variable_.array() - alpha * x_diff.array(); + assembler_->assemble_residual(); // update residual from the new variable + // vector + auto new_res = assembler_->residual_vector().norm(); + if (new_res < (1.0 - 0.0001 * alpha) * old_res) { + break; // line search finished + } else { + alpha = alpha * bt_roh_; // continue line search + } + } +} + +pipenetwork::Hydralic_sim::Hydralic_sim( + const std::shared_ptr& mesh, + std::shared_ptr& curves_info, bool pdd_mode, + bool debug) { + mesh_ = mesh; + assembler_ = std::make_shared( + mesh, curves_info, pdd_mode); + // choose solver type based on network size + Index nnodes = mesh_->nodes()->nnodes(); + if (nnodes < nthre_) { + std::shared_ptr solve_ptr( + Factory::instance()->create("LU")); + std::cout << "small network, using the LU Solver " << std::endl; + solver_ = solve_ptr; + } else { + std::shared_ptr solve_ptr( + Factory::instance()->create("mkl_pardiso")); + std::cout << "large network, using the mkl_pardiso Solver " << std::endl; + solver_ = solve_ptr; + } + + debug_ = debug; +} + +void pipenetwork::Hydralic_sim::update_mesh() { + auto nodes = mesh_->nodes(); + auto links = mesh_->links(); + auto leak_nids = mesh_->leak_nids(); + + auto variables = assembler_->variable_vector(); + auto nnodes = nodes->nnodes(); + auto nlinks = links->nlinks(); + + // junctions + auto junction_map = nodes->junctions(); + Index leak_count = 0; + for (auto& index_junc : junction_map) { + auto nid = index_junc.first; + auto junction = index_junc.second; + auto sim_head = variables[nid]; + auto sim_demand = variables[nnodes + nid]; + junction->head = sim_head; + junction->demand = sim_demand; + bool leak_node = + std::find(leak_nids.begin(), leak_nids.end(), nid) != leak_nids.end(); + if (leak_node) { + junction->leak_discharge = variables[2 * nnodes + nlinks + leak_count]; + leak_count++; + } + } + + // srcs + auto res_map = nodes->reservoirs(); + for (auto& index_res : res_map) { + auto nid = index_res.first; + auto reservoir = index_res.second; + auto sim_discharge = variables[nnodes + nid]; + reservoir->discharge = sim_discharge; + } + + // pipes + auto pipe_map = links->pipes(); + for (auto& index_pipe : pipe_map) { + auto lid = index_pipe.first; + auto pipe = index_pipe.second; + auto sim_flowrate = variables[2 * nnodes + lid]; + pipe->flowrate = sim_flowrate; + } +} diff --git a/src/index_manager.cc b/src/index_manager.cc new file mode 100644 index 0000000..a30ab2d --- /dev/null +++ b/src/index_manager.cc @@ -0,0 +1,25 @@ +#include "index_manager.h" + +//! Constructor with an inital value for index +pipenetwork::IndexManager::IndexManager(Index idx) : index_{idx}, next_{idx} {}; + +//! Current index +pipenetwork::Index pipenetwork::IndexManager::current_index() const { + return index_; +} + +//! Maximum index value +pipenetwork::Index pipenetwork::IndexManager::max() const { + return std::numeric_limits::max(); +} + +//! Generate index +pipenetwork::Index pipenetwork::IndexManager::create_index() { + // Get the next value of index + // (at init both index and next will be the same) + index_ = next_; + // Increment next index by one + next_ += 1; + // Return current index + return index_; +} \ No newline at end of file diff --git a/src/io.cc b/src/io.cc index 2ef232e..777897b 100644 --- a/src/io.cc +++ b/src/io.cc @@ -1,70 +1,448 @@ #include "io.h" -// Read input CSV file and store the data -bool pipenetwork::IO::read_network(const std::string& node_filename, - const std::string& pipe_filename) { - bool status = true; +void pipenetwork::IO::read_inp(const std::string& filename) { + filename_ = filename; + if (!IO_utils::file_exists(filename)) { + throw std::runtime_error( + "Input file does not exist, please check the path!"); + } try { - io::CSVReader<6> in_node(node_filename); - io::CSVReader<7> in_pipe(pipe_filename); - in_node.read_header(io::ignore_extra_column, "Node_id", "Node_coord1", - "Node_coord2", "Node_coord3", "Node_head", - "Node_discharge"); - in_pipe.read_header(io::ignore_extra_column, "Pipe_id", "Pipe_node1", - "Pipe_node2", "Pipe_diameter", "Pipe_roughness", - "Pipe_status", "Pipe_discharge"); - Index node_id, pipe_id, pipe_node1, pipe_node2; - std::string node_head, node_discharge, pipe_discharge; - long double node_coord1, node_coord2, node_coord3, pipe_diameter, - pipe_roughness; - int pipe_status; - while (in_node.read_row(node_id, node_coord1, node_coord2, node_coord3, - node_head, node_discharge)) { - Eigen::Vector3d coords(node_coord1, node_coord2, node_coord3); - nodal_coords_.emplace_back(coords); - - if (node_head != "NA") { - long double head = std::stod(node_head); - initial_nodal_head_.emplace_back(std::make_pair(node_id, head)); + parse_sections(); + construct_node_info(); + construct_pipe_info(); + construct_curve_info(); + construct_pump_info(); + construct_valve_info(); + // get isolation valves information + bool iso = sections_.find("[ISOVALVES]") != sections_.end(); + if (iso) { + construct_iso_valve_info(); + } + + } catch (std::exception& e) { + std::cerr << "Failed to read input file, error message " << e.what() + << std::endl; + std::abort(); + } +} + +void pipenetwork::IO::create_synthetic_net(pipenetwork::Index n) { + auto junction_nodes = construct_synthesis_junctions(n); + construct_synthesis_pipes(junction_nodes); + create_sources(n); +} + +void pipenetwork::IO::parse_sections() { + std::string line; + std::string buf, current_key{"init"}; + std::vector info; + + std::ifstream infile(filename_); + //! parsing line one by one + bool parsing_flag = false; + while (std::getline(infile, line)) { + std::istringstream iss(line); + while (iss >> buf) { + if (buf[0] == '[') { + // check the condition + if ((current_key != "init") && (!info.empty())) { + // put parsed lines into map and clear the buffer vector + sections_[current_key] = info; + info.clear(); + parsing_flag = false; + } + // update the keys + bool is_in = section_keys_.find(buf) != section_keys_.end(); + if (is_in) { + current_key = buf; + parsing_flag = true; + } } - if (node_discharge != "NA") { - long double ndischarge = std::stod(node_discharge); - initial_nodal_discharge_.emplace_back( - std::make_pair(node_id, ndischarge)); + } + // parse the line + if (parsing_flag) { + info.emplace_back(line); + } + } +} + +std::pair, std::vector> + pipenetwork::IO::parse_node_line(const std::string& section_name, + const std::string& mode) const { + // check if the section name is right. + + if (!sections_.count(section_name)) { + throw std::invalid_argument("Parsing faild! Invalid section name"); + } + + double elevation_head, demand; + std::string id; + + std::vector node_ids; + std::vector node_info; + // get elevation for junctions + for (auto const& line : sections_.at(section_name)) { + // skip keys entries + if (line[0] == '[' || line[0] == ';') continue; + + std::istringstream iss(line); + // parsing lines for demand + if (mode == "demand") { + if (iss >> id >> elevation_head >> demand) { + node_info.emplace_back(IO_utils::to_si(demand, "demand")); + node_ids.emplace_back(id); } } + // parsing lines for elevation/head + else { + if (iss >> id >> elevation_head) { + node_info.emplace_back(IO_utils::to_si(elevation_head, "elevation")); + node_ids.emplace_back(id); + } + } + } + + return std::make_pair(node_ids, node_info); +} + +void pipenetwork::IO::parse_leak_info() { + std::string nid; + double diameter; + for (auto const& line : sections_.at("[LEAKS]")) { + // skip keys entries + if (line[0] == '[' || line[0] == ';') continue; + + std::istringstream iss(line); + if (iss >> nid >> diameter) { + nid2ldia_[nid] = diameter; + } + } +} - while (in_pipe.read_row(pipe_id, pipe_node1, pipe_node2, pipe_diameter, - pipe_roughness, pipe_status, pipe_discharge)) { - node_pairs_.emplace_back(std::make_pair(pipe_node1, pipe_node2)); - diameters_.emplace_back(pipe_diameter); - roughness_.emplace_back(pipe_roughness); - if (pipe_status == 0) - pipe_status_.emplace_back(false); - else - pipe_status_.emplace_back(true); - - if (pipe_discharge != "NA") { - long double pdischarge = std::stod(pipe_discharge); - initial_pipe_discharge_.emplace_back( - std::make_pair(pipe_id, pdischarge)); +void pipenetwork::IO::construct_node_info() { + // get elevation for junctions + auto junction_info = parse_node_line("[JUNCTIONS]", "elevation"); + auto junction_ids = junction_info.first; + auto junction_elevations = junction_info.second; + // get demand for junctions + auto junction_demand_info = + parse_node_line("[JUNCTIONS]", "demand"); // parse junction + auto junction_demands = junction_demand_info.second; + + // get head for reservoirs + auto reservoir_info = parse_node_line("[RESERVOIRS]", "head"); + auto reservoir_ids = reservoir_info.first; + auto reservoir_heads = reservoir_info.second; + + // get leak information + bool leak = sections_.find("[LEAKS]") != sections_.end(); + if (leak) { + parse_leak_info(); + } + + // construct property vectors + for (int i = 0; i < junction_elevations.size(); ++i) { + pipenetwork::JunctionProp junc_prop; + junc_prop.name = junction_ids[i]; + junc_prop.elevation = junction_elevations[i]; + junc_prop.demand = junction_demands[i]; + bool leak_node = nid2ldia_.find(junction_ids[i]) != nid2ldia_.end(); + if (leak_node) { + junc_prop.leak_diameter = + IO_utils::to_si(nid2ldia_.at(junction_ids[i]), "diameter"); + } + junc_props_.emplace_back(junc_prop); + } + + for (int i = 0; i < reservoir_ids.size(); ++i) { + pipenetwork::ReservoirProp res_prop; + res_prop.name = reservoir_ids[i]; + res_prop.head = reservoir_heads[i]; + res_props_.emplace_back(res_prop); + } +} + +void pipenetwork::IO::construct_pipe_info() { + double length, diameter, roughness, loss; + std::string pid, nid1, nid2, status; + + // get pipe information + for (auto const& line : sections_.at("[PIPES]")) { + // skip keys entries + if (line[0] == '[' || line[0] == ';') continue; + + std::istringstream iss(line); + // parsing lines for pipe + if (iss >> pid >> nid1 >> nid2 >> length >> diameter >> roughness >> loss >> + status) { + + pipenetwork::PipeProp pipe_prop; + std::transform(status.begin(), status.end(), status.begin(), ::toupper); + pipe_prop.name = pid; + pipe_prop.length = IO_utils::to_si(length, "length"); + pipe_prop.diameter = IO_utils::to_si(diameter, "diameter"); + pipe_prop.roughness = roughness; + pipe_prop.node1_name = nid1; + pipe_prop.node2_name = nid2; + + if (status == "OPEN") { + pipe_prop.status = LinkStatus::OPEN; + } else { + pipe_prop.status = LinkStatus::CLOSED; } + pipe_props_.emplace_back(pipe_prop); } + } +} + +void pipenetwork::IO::construct_pump_info() { + // get pump information + std::string pid, nid1, nid2, type, curve_name; + double power{50}; + for (auto const& line : sections_.at("[PUMPS]")) { + PumpProp pump_prop; + // skip keys entries + if (line[0] == '[' || line[0] == ';') continue; + + std::istringstream iss(line); + + if (iss >> pid >> nid1 >> nid2 >> type) { + std::transform(type.begin(), type.end(), type.begin(), ::toupper); + if (type == "HEAD") { + iss >> curve_name; + pump_prop.curve_id = curves_info_->pump_str_int(curve_name); + pump_prop.name = pid; + pump_prop.node1_name = nid1; + pump_prop.node2_name = nid2; + pump_prop.type = PumpType::HEADPUMP; + } + if (type == "POWER") { + iss >> power; + pump_prop.name = pid; + pump_prop.node1_name = nid1; + pump_prop.node2_name = nid2; + pump_prop.type = PumpType::POWERPUMP; + pump_prop.power = IO_utils::to_si(power, "power"); + } + pump_props_.emplace_back(pump_prop); + } + } +} + +void pipenetwork::IO::construct_valve_info() { + // get valve information + std::string pid, nid1, nid2, type; + double diameter, setting, minorloss{0}; + for (auto const& line : sections_.at("[VALVES]")) { + ValveProp valve_prop; + // skip keys entries + if (line[0] == '[' || line[0] == ';') continue; + std::istringstream iss(line); + if (iss >> pid >> nid1 >> nid2 >> diameter >> type >> setting) { + std::transform(type.begin(), type.end(), type.begin(), ::toupper); + valve_prop.name = pid; + valve_prop.node1_name = nid1; + valve_prop.node2_name = nid2; + valve_prop.diameter = IO_utils::to_si(diameter, "diameter"); + valve_prop.status = LinkStatus::ACTIVE; + + if (type == "PRV") { + valve_prop.type = ValveType::PRVALVE; + valve_prop.setting = IO_utils::to_si(setting, "pressure"); + } else if (type == "FCV") { + valve_prop.type = ValveType::FCVALVE; + valve_prop.setting = IO_utils::to_si(setting, "flow"); + } else if (type == "TCV") { + valve_prop.type = ValveType::TCVALVE; + valve_prop.setting = setting; + } + if (iss >> minorloss) { + valve_prop.minor_loss_coeff = minorloss; + } + valve_props_.emplace_back(valve_prop); + } + } +} + +void pipenetwork::IO::construct_iso_valve_info() { + // get valve information + std::string vid, nid, pid; + for (auto const& line : sections_.at("[ISOVALVES]")) { + isolation::ISOVProp iso_valve_prop; + // skip keys entries + if (line[0] == '[' || line[0] == ';') continue; + std::istringstream iss(line); + if (iss >> vid >> nid >> pid) { + iso_valve_prop.name = vid; + iso_valve_prop.on_node = nid; + iso_valve_prop.on_pipe = pid; + iso_valve_props_.emplace_back(iso_valve_prop); + } + } +} + +void pipenetwork::IO::construct_curve_info() { + // get curve information + std::string curve_id; + double x, y; + std::string id_buff; + std::vector> curve_point; + std::vector head_pump_props; + + for (auto const& line : sections_.at("[CURVES]")) { + // skip keys entries + if (line[0] == '[' || line[0] == ';') continue; + std::istringstream iss(line); + + if (iss >> curve_id >> x >> y) { + if (!curve_point.empty() && curve_id != id_buff) { + Pump_curve_prop pump_curve(id_buff, curve_point); + head_pump_props.emplace_back(pump_curve); + curve_point.clear(); + } + curve_point.emplace_back(std::make_pair(IO_utils::to_si(x, "flow"), + IO_utils::to_si(y, "head"))); + id_buff = curve_id; + } + } + if (!curve_point.empty()) { + Pump_curve_prop pump_curve(curve_id, curve_point); + head_pump_props.emplace_back(pump_curve); + // add pump info to curve object + curves_info_->add_pump_curves(head_pump_props); + } +} + +std::vector> + pipenetwork::IO::construct_synthesis_junctions(int n) { + // buffer vector + std::vector> junction_names(n); + std::vector buffer; + std::string junction_name; + pipenetwork::JunctionProp junc_prop; + double elevation, demand; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + // create junction name + junction_name = "J-" + std::to_string(i * n + j); + // elevation and demand + elevation = IO_utils::rand_number(400, 900); + demand = IO_utils::rand_number(0, 5); + // add to junction array + junc_prop.name = junction_name; + junc_prop.elevation = IO_utils::to_si(elevation, "elevation"); + junc_prop.demand = IO_utils::to_si(demand, "demand"); + junc_props_.emplace_back(junc_prop); + buffer.emplace_back(junction_name); + } + junction_names[i] = buffer; + buffer.clear(); + } + return junction_names; +} + +void pipenetwork::IO::construct_synthesis_pipes( + const std::vector>& junction_names) { + int n = junction_names.size(); + for (int i = 0; i < n; ++i) { + std::vector junction_name_col = junction_names.at(i); + create_vertical_pipes(junction_name_col, i); + } + for (int i = 1; i < n; ++i) { + std::vector left_junc = junction_names.at(i - 1); + std::vector right_junc = junction_names.at(i); + create_horizontal_pipes(left_junc, right_junc, i); + } +} + +void pipenetwork::IO::create_vertical_pipes( + const std::vector& junction_names, int col_num, bool rand) { + int n = junction_names.size(); + pipenetwork::PipeProp pipe_prop; + std::string upper_junc_id, lower_junc_id, pipe_name; + for (int i = 1; i < n; ++i) { + if (rand) { + if (IO_utils::rand_number(0, 1) < 0.5) { + continue; + } + } + + lower_junc_id = junction_names.at(i - 1); + upper_junc_id = junction_names.at(i); + pipe_name = "P-V-" + std::to_string(col_num * n + i); + pipe_prop.name = pipe_name; + pipe_prop.length = + IO_utils::to_si(IO_utils::rand_number(200, 800), "length"); + pipe_prop.diameter = + IO_utils::to_si(IO_utils::rand_number(3, 15), "diameter"); + pipe_prop.roughness = 155; + pipe_prop.node1_name = lower_junc_id; + pipe_prop.node2_name = upper_junc_id; + pipe_props_.emplace_back(pipe_prop); + } +} + +void pipenetwork::IO::create_horizontal_pipes( + const std::vector& l_junc, + const std::vector& r_junc, int col_num, bool rand) { + int n = l_junc.size(); + pipenetwork::PipeProp pipe_prop; + std::string left_junc_id, right_junc_id, pipe_name; + for (int i = 0; i < n; ++i) { + if (rand) { + if (IO_utils::rand_number(0, 1) < 0.5) { + continue; + } + } + left_junc_id = l_junc.at(i); + right_junc_id = r_junc.at(i); + pipe_name = "P-H-" + std::to_string(col_num * n + i); + pipe_prop.name = pipe_name; + pipe_prop.length = + IO_utils::to_si(IO_utils::rand_number(200, 800), "length"); + pipe_prop.diameter = + IO_utils::to_si(IO_utils::rand_number(3, 15), "diameter"); + pipe_prop.roughness = 155; + pipe_prop.node1_name = left_junc_id; + pipe_prop.node2_name = right_junc_id; + pipe_props_.emplace_back(pipe_prop); + } +} + +void pipenetwork::IO::create_sources(int n) { + pipenetwork::ReservoirProp src_prop; + pipenetwork::PipeProp pipe_prop; + std::string src_name, pipe_name; + + for (int i = 0; i < 5; ++i) { + src_name = "SRC-" + std::to_string(i); + src_prop.name = src_name; + src_prop.head = + IO_utils::to_si(IO_utils::rand_number(500, 1000), "elevation"); + + pipe_name = "P-S-" + std::to_string(i); + pipe_prop.name = pipe_name; + pipe_prop.length = IO_utils::to_si(30, "length"); + pipe_prop.diameter = IO_utils::to_si(30, "diameter"); + pipe_prop.roughness = 155; + pipe_prop.node1_name = src_name; + pipe_prop.node2_name = "J-" + std::to_string(i * n); + + res_props_.emplace_back(src_prop); + pipe_props_.emplace_back(pipe_prop); + } +} + +void pipenetwork::IO::save_mesh_inp( + const std::shared_ptr& mesh, + const std::string& output_path) { + auto out = IO_utils::Output(mesh); + out.save_mesh_inp(output_path); +} - std::cout << "Read from: " << node_filename << " and " << pipe_filename - << std::endl - << "The network contains " << nodal_coords_.size() - << " nodes and " << node_pairs_.size() << "pipes." << std::endl - << "With " << initial_nodal_head_.size() - << " known initial nodal heads, " - << initial_nodal_discharge_.size() - << " known initial nodal discharges and " - << initial_pipe_discharge_.size() - << " known initial pipe discharges." << std::endl; - } catch (std::exception& exception) { - std::cout << "Read pipe network file: " << exception.what() << std::endl; - status = false; - } - - return status; +void pipenetwork::IO::save_sim_result( + const std::shared_ptr& mesh, + const std::string& output_path) { + auto out = IO_utils::Output(mesh); + out.save_sim_result(output_path); } diff --git a/src/io_utils.cc b/src/io_utils.cc new file mode 100644 index 0000000..f3a4b41 --- /dev/null +++ b/src/io_utils.cc @@ -0,0 +1,198 @@ +#include "io_utils.h" + +double pipenetwork::IO_utils::rand_number(double l, double h) { + double r = l + static_cast(std::rand()) / + (static_cast(RAND_MAX / (h - l))); + return r; +} + +double pipenetwork::IO_utils::to_si(double val, const std::string& mode) { + if (mode == "elevation" || mode == "length" || mode == "head") { + return val * 0.3048; // ft to meter + } else if (mode == "demand" || mode == "flow") { + return val * 6.30901964e-05; // GPM to si + } else if (mode == "diameter") { + return val * 0.0254; // inch to meter + } else if (mode == "power") { + return val * 745.699872; // hp to W (Nm/s) + } else if (mode == "pressure") { + return val * (0.3048 / 0.4333); // psi * (m/ft / psi/ft) + } else { + throw std::runtime_error("Mode not recognized!"); + } +} + +double pipenetwork::IO_utils::from_si(double val, const std::string& mode) { + if (mode == "elevation" || mode == "length" || mode == "head") { + return val / 0.3048; // meter to ft + } else if (mode == "demand" || mode == "flow") { + return val / (6.30901964e-05); // si to GPM + } else if (mode == "diameter") { + return val / 0.0254; // meter to inch + } else if (mode == "power") { + return val / 745.699872; // W (Nm/s) to hp + } else if (mode == "pressure") { + return val / (0.3048 / 0.4333); // psi * (m/ft / psi/ft) + } else { + throw std::runtime_error("Mode not recognized!"); + } +} + +bool pipenetwork::IO_utils::path_exist(const std::string& pathname) { + struct stat info; + if (stat(pathname.c_str(), &info) != 0) { + return false; + } + return info.st_mode & S_IFDIR; +} + +void pipenetwork::IO_utils::create_new_folder(const std::string& pathname) { + if (!path_exist(pathname)) { + std::cout << "output folder does not exist, creating a new one" + << std::endl; + try { + mkdir(pathname.c_str(), 0777); + } catch (...) { + std::cerr << "Failed to create folder, abort"; + abort(); + } + } +} + +void pipenetwork::IO_utils::Output::save_mesh_inp( + const std::string& output_path) { + create_new_folder(output_path); + filepath_ = output_path + mesh_->name() + ".inp"; + std::ofstream outfile{filepath_}; + write_junctions_inp(outfile); + write_reservoirs_inp(outfile); + write_pipes_inp(outfile); +} + +void pipenetwork::IO_utils::Output::write_junctions_inp( + std::ofstream& outfile) { + // write row info + outfile << "[JUNCTIONS]" + << "\n"; + outfile << ";ID " + << "Elev " + << "Demand " + << "Pattern " + << "\n"; + auto junctions_map = mesh_->nodes()->junctions(); + for (const auto& node : junctions_map) { + auto junction = node.second; + auto junction_prop = junction->property(); + outfile << std::setprecision(12) << std::to_string(junction->id()) << " " + << from_si(junction_prop.elevation, "elevation") << " " + << from_si(junction_prop.demand, "demand") << " " + << " ;" + << "\n"; + } +} + +void pipenetwork::IO_utils::Output::write_reservoirs_inp( + std::ofstream& outfile) { + outfile << "\n"; + outfile << "[RESERVOIRS]" + << "\n"; + outfile << ";ID " + << "Head " + << "Pattern " + << "\n"; + auto res_map = mesh_->nodes()->reservoirs(); + for (const auto& node : res_map) { + // get node information, determine possible leak nodes and assemble demands + // heads vector + auto res = node.second; + auto res_property = res->property(); + + outfile << std::setprecision(12) << std::to_string(res->id()) << " " + << from_si(res_property.head, "head") << " " + << " ;" + << "\n"; + } +} + +void pipenetwork::IO_utils::Output::write_pipes_inp(std::ofstream& outfile) { + outfile << "\n"; + outfile << "[PIPES]" + << "\n"; + outfile << ";ID " + << "Node1 " + << "Node2 " + << "Length " + << "Diameter " + << "Roughness " + << "MinorLoss " + << "Status " + << "\n"; + + auto pipes_map = mesh_->links()->pipes(); + for (const auto& link : pipes_map) { + auto pipe = link.second; + auto node1 = pipe->nodes().first->id(); + auto node2 = pipe->nodes().second->id(); + auto pipe_prop = pipe->property(); + + outfile << std::setprecision(12) << pipe_prop.name << " " << node1 + << " " << node2 << " " << from_si(pipe_prop.length, "length") + << " " << from_si(pipe_prop.diameter, "diameter") << " " + << pipe_prop.roughness << " " << pipe_prop.minor_loss_coeff + << " " + << "Open" + << " " + << " ;" + << "\n"; + } +} + +void pipenetwork::IO_utils::Output::save_sim_result( + const std::string& output_path) { + create_new_folder(output_path); + std::ofstream outnode(output_path + mesh_->name() + "_nodes.csv"); + std::ofstream outlink(output_path + mesh_->name() + "_links.csv"); + outnode << "node_name" + << "," + << "head" + << "," + << "demand" + << "," + << "leak_discharge" + << "\n"; + outlink << "link_name" + << "," + << "flowrate" + << "\n"; + + // junctions + auto junction_map = mesh_->nodes()->junctions(); + for (auto& index_junc : junction_map) { + auto nid = index_junc.first; + auto junction = index_junc.second; + auto junc_prop = junction->property(); + outnode << std::setprecision(12) << junc_prop.name << "," << junction->head + << "," << junction->demand << "," << junction->leak_discharge + << "\n"; + } + // reservoirs + auto res_map = mesh_->nodes()->reservoirs(); + for (auto& index_res : res_map) { + auto nid = index_res.first; + auto res = index_res.second; + auto res_prop = res->property(); + outnode << std::setprecision(12) << res_prop.name << "," << res_prop.head + << "," << res->discharge << "," << 0 << "\n"; + } + + auto pipe_map = mesh_->links()->pipes(); + for (auto& index_pipe : pipe_map) { + auto nid = index_pipe.first; + auto pipe = index_pipe.second; + auto pipe_prop = pipe->property(); + outlink << std::setprecision(12) << pipe_prop.name << "," << pipe->flowrate + << "\n"; + } + + std::cout << "Simultation results saved to: " << output_path << std::endl; +} diff --git a/src/main.cc b/src/main.cc index 762cd76..2902ea1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,3 +1,67 @@ -#include +#include +#include +#include +#include -int main(int argc, char** argv) { std::cout << "Pipe network\n"; } +#include "hydralic_sim.h" + +int main(int argc, char** argv) { + using namespace std::chrono; + try { + TCLAP::CmdLine cmd( + "HydroSim: fast hydraulic simulation for potable water distribution " + "system", + ' ', "1.0"); + TCLAP::ValueArg fileArg( + "f", "file", ".inp file for WDN system", false, + "../test_files/test_net.inp", "filename", cmd); + TCLAP::ValueArg saveArg("t", "to", + "Folder to save the results", false, + "../results/", "save path", cmd); + TCLAP::ValueArg nameArg("n", "name", "Name for the WDN", false, + "test", "meshname", cmd); + TCLAP::SwitchArg pddSwitch( + "p", "pdd", "Run pressure demand driven (PDD) simulation", cmd, false); + TCLAP::SwitchArg debugSwitch( + "d", "debug", "Debug mode: output intermediate results", cmd, false); + + // Parse the argv array. + cmd.parse(argc, argv); + std::string filepath = fileArg.getValue(); + std::string mesh_name = nameArg.getValue(); + bool pdd_mode = pddSwitch.getValue(); + bool debug = debugSwitch.getValue(); + std::string save_path = saveArg.getValue(); + // IO + auto IO = std::make_shared(); + IO->read_inp(filepath); + auto start = high_resolution_clock::now(); + // Mesh + auto mesh = std::make_shared(mesh_name); + mesh->create_nodes(IO->junction_properties(), IO->reservoir_properties()); + mesh->create_links(IO->pipe_properties(), IO->pump_properties(), + IO->valve_properties()); + mesh->create_mesh_graph(); + mesh->print_summary(); + // hydraulic simulation + auto curves_info_io = IO->curve_info(); + auto sim = std::make_shared(mesh, curves_info_io, + pdd_mode, debug); + if (sim->run_simulation(1e-8, 100)) { + std::cout << "Simulation Completed!!!" << std::endl; + sim->update_mesh(); + IO->save_sim_result(mesh, save_path); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop - start); + std::cout << "hydraulic computation time (milliseconds)" + << duration.count() << std::endl; + } else { + std::cerr << "Simulation does not converge! " << std::endl; + } + } catch (std::exception& e) { + std::cerr << "Simulation failed: " << e.what() << std::endl; + std::abort(); + } + + return 0; +} diff --git a/src/matrix_assembler.cc b/src/matrix_assembler.cc index 463666b..53d79e8 100644 --- a/src/matrix_assembler.cc +++ b/src/matrix_assembler.cc @@ -1,347 +1,37 @@ #include "matrix_assembler.h" -// Constructor -pipenetwork::MatrixAssembler::MatrixAssembler(bool pdd_mode) { - pdd_ = pdd_mode; - jac_ = std::make_shared>(); - variable_vec_ = std::make_shared(); - residual_vec_ = std::make_shared(); -}; - -// Obtain global nodal and pipe indices and pointers from meshes -void pipenetwork::MatrixAssembler::global_nodal_pipe_indices( - const std::shared_ptr& mesh) { - global_nodes_.clear(); - global_pipes_.clear(); - for (const auto& node : mesh->nodes_) global_nodes_.emplace(node); - for (const auto& pipe : mesh->pipes_) global_pipes_.emplace(pipe); - nnode_ = global_nodes_.size(); - npipe_ = global_pipes_.size(); -} - -// Initialize variable vector -// 1 to nnode element: nodal head -// nnode+1 to 2*nnode element: nodal demand -// 2*nnode+1 to 2*nnode+npipe element: pipe discharge -void pipenetwork::MatrixAssembler::assemble_variable_vector() { - - variable_vec_->resize(2 * nnode_ + npipe_); - - for (const auto& node : global_nodes_) { - Index index_nh = node.first; - Index index_nd = node.first + nnode_; - - // nodal head vector - variable_vec_->coeffRef(index_nh) = node.second->head(); - - // nodal demand vector - variable_vec_->coeffRef(index_nd) = node.second->demand(); - } - - // pipe discharge vector - for (const auto& pipe : global_pipes_) { - Index index_pd = pipe.first + 2 * nnode_; - variable_vec_->coeffRef(index_pd) = pipe.second->discharge(); - } -} - -// assember the pressure demand part of jacobian matrix -std::vector> - pipenetwork::MatrixAssembler::construct_demand_jac( - const std::shared_ptr& node, Index index) { - std::vector> update; - if (!node->isres()) { - // construct jacH part - update.emplace_back(nnode_ + npipe_ + index, nnode_ + index, 1); - // construct jacG part - if (pdd_) { - update.emplace_back(nnode_ + npipe_ + index, index, - get_pressure_head_jacob(node)); - } +pipenetwork::linear_system::MatrixAssembler::MatrixAssembler( + const std::shared_ptr& mesh, + std::shared_ptr& curves_info, bool pdd_mode) + : mesh_{mesh}, curves_info_{curves_info}, pdd_{pdd_mode} { + vars_ = std::make_shared(mesh_); + update_curves_info_(); + res_ = std::make_shared(mesh_, vars_, curves_info_); + jac_ = std::make_shared(mesh_, vars_, res_, curves_info_); +} + +void pipenetwork::linear_system::MatrixAssembler::assemble_residual() { + if (pdd_) { + res_->assemble_residual_pdd(); } else { - // JacH will be 0, consturct jac G - update.emplace_back(nnode_ + npipe_ + index, index, 1); - } - return update; -} - -// Assemble Jacobian matrix -// nodal_head nodal_discharge(demand) pipe_discharge -// nodal_balance sub_jac_A sub_jac_B sub_jac_C -// headloss sub_jac_D sub_jac_E sub_jac_F -// demand_pressure sub_jac_G sub_jac_H sub_jac_I -// -// Nodal balance equation: -// Residual = flow = Inflow - Outflow - Demand -// -// Headloss equation (Hazen-Williams): -// Residual = (Start_node_head - end_node_head) - \frac{10.67 \times length -// \times pipe_discharge^1.852}{pipe_roughness^1.852 \times -// (2radius)^4.8704} -// -// demand_pressure equation : -// Residual = demand-demand (demand driven) -// Residual = pressure_demand_func-demand (demand driven) -// -// sub_jac_A: Derivative of nodal balance equation with respect to nodal head, -// 0. -// sub_jac_B: Derivative of nodal balance equation with respect to nodal -// discharge (demand), -1. -// sub_jac_C: Derivative of nodal balance equation with respect to pipe -// discharge, 1 for inlink, -1 for out link. -// sub_jac_D: Derivative of headloss equation with respect to nodal head, 1 for -// start node, -1 for end node. -// sub_jac_E: Derivative of headloss equation with respect to nodal discharge, -// 0. -// sub_jac_F: Derivative of headloss equation with respect to pipe discharge, -// for corresponding pipe, \frac{-1.852 \times 10.67 \times -// length}{pow(pipe_roughness,1.852) \times pow(2radius,4.8704)} -// \times pow(pipe_discharge,0.852). -// sub_jac_G: Derivative of demand_pressure equation with respect to nodal head, -// 0 for junctions, 1 for reservoir/tank of demand driven model, -// nonlinear for pressure_demand model. -// sub_jac_H: Derivative of demand_pressure equation with respect to nodal -// discharge (demand), -// 1 for junctions, 0 for reservoir/tank. -// sub_jac_I: Derivative of demand_pressure equation with respect to pipe -// discharge, -// 0. -// -// Each node has one nodal balance equation, each pipe has one headloss -// equation, Thus the Jacobian has (2*nnode+npipe) row and (2*nnode+npipe) -// column -// - -void pipenetwork::MatrixAssembler::assemble_jacobian() { - // Check network - if (nnode_ <= 0 || npipe_ <= 0) - throw std::runtime_error( - "No node or pipe index pairs created to assemble Jacobian matrix"); - - std::vector> update; - update.reserve(nnode_ + 5 * npipe_); - - // Iterate through all nodes - for (const auto& node : global_nodes_) { - Index index = node.first; - // construct jacB part - update.emplace_back(index, nnode_ + index, -1); - // construct jacH, jacG part - auto demand_update = construct_demand_jac(node.second, index); - update.insert(std::end(update), std::begin(demand_update), - std::end(demand_update)); + res_->assemble_residual(); } - - // Iterate through all pipes - for (const auto& pipe : global_pipes_) { - Index index_pipe = pipe.first; - - Index index_node1 = pipe.second->nodes().at(0)->id(); - Index index_node2 = pipe.second->nodes().at(1)->id(); - - // construct jacC part - if (pipe.second->iter_discharge() >= 0) { - update.emplace_back(index_node1, 2 * nnode_ + index_pipe, -1); - update.emplace_back(index_node2, 2 * nnode_ + index_pipe, 1); - } else { - update.emplace_back(index_node1, 2 * nnode_ + index_pipe, 1); - update.emplace_back(index_node2, 2 * nnode_ + index_pipe, -1); - } - // construct jacD part - update.emplace_back(nnode_ + index_pipe, index_node1, 1); - update.emplace_back(nnode_ + index_pipe, index_node2, -1); - // construct jacF part (Hazen-Williams) - double deriv_pipe_discharge = pipe.second->deriv_hazen_williams_discharge(); - update.emplace_back(nnode_ + index_pipe, 2 * nnode_ + index_pipe, - deriv_pipe_discharge); - } - - jac_->resize(2 * nnode_ + npipe_, 2 * nnode_ + npipe_); - jac_->setFromTriplets(update.begin(), update.end()); } -// Calculate and assemble residual vector -// Nodal balance equation: -// Residual = flow = Inflow - Outflow - Demand -// -// -// Headloss equation (Hazen-Williams): -// Residual = (Start_node_head - end_node_head) - \frac{10.67 \times length -// \times pipe_discharge^1.852}{pipe_roughness^1.852 \times -// (2radius)^4.8704} - -// demand_pressure equation : -// Residual = demand_var-demand_desired (demand driven mode) -// Residual = demand_var - pressure_demand_func(pressure demand driven mode) -// The network has nnode Nodal balance equation and npipe Headloss equation -// Thus the residual vector has (nnode+npipe) elements -void pipenetwork::MatrixAssembler::assemble_residual_vector() { - residual_vec_->resize(2 * nnode_ + npipe_); - residual_vec_->setZero(); - - // Iterate through all pipes - for (auto& pipe : global_pipes_) { - Index index_pipe = pipe.first; - Index index_node1 = pipe.second->nodes().at(0)->id(); - Index index_node2 = pipe.second->nodes().at(1)->id(); - // Calculate headloss residual - pipe.second->compute_headloss_hazen_williams(); - double head1 = 0; - double head2 = 0; - head1 = pipe.second->nodes().at(0)->head(); - head2 = pipe.second->nodes().at(1)->head(); - - auto head_res = (-1) * ((head1 - head2) - pipe.second->headloss()); - residual_vec_->coeffRef(nnode_ + index_pipe) = head_res; - - // Calculate the nodal balance residual (in and out flow part) - residual_vec_->coeffRef(index_node1) += - (-1) * (-1) * pipe.second->iter_discharge(); - residual_vec_->coeffRef(index_node2) += - (-1) * pipe.second->iter_discharge(); - } - - // Iterate through all nodes - for (const auto& node : global_nodes_) { - Index index = node.first; - // Calculate the nodal balance residual (demand part) - if (node.second->isdischarge()) - residual_vec_->coeffRef(index) -= (-1) * node.second->iter_demand(); - // Calculate the demand pressure residual - // Case 1 the node is Reservior/tank - if (node.second->isres()) { - residual_vec_->coeffRef(nnode_ + npipe_ + index) = - node.second->head() - node.second->elevation(); - } - // case 2 the node is a junction - else { - if (!pdd_) { - residual_vec_->coeffRef(nnode_ + npipe_ + index) = - node.second->iter_demand() - node.second->demand(); - } else { - assemble_pdd_residual(node.second, index); - } - } - } -} - -// Apply variables (head and discharge) back to nodes and pipes -void pipenetwork::MatrixAssembler::apply_variables() { - - // Iterate through nodes, assign nodal variables - for (auto& node : global_nodes_) { - // Get index of target variables - Index index_nh = node.first; - // Assign head - node.second->head(variable_vec_->coeff(index_nh)); - // Assign demand - node.second->iter_demand(variable_vec_->coeff(nnode_ + index_nh)); - } - - // Iterate through pipes, assign pipe discharge during iteration - for (auto& pipe : global_pipes_) { - // Get index of target variables - Index index_pd = pipe.first + 2 * nnode_; - // Assign discharge - pipe.second->iter_discharge(variable_vec_->coeff(index_pd)); - } -} - -void pipenetwork::MatrixAssembler::assemble_pdd_residual( - const std::shared_ptr& node, Index index) { - auto pressure = node->head() - node->elevation(); - double res; - double tolerance = 1e-10; - - // case 1: pressure below min pressure, no discharge - if (pressure < node->min_pressure()) { - res = -1 * (node->iter_demand() - node->demand() * node->pdd_slope() * - (pressure - node->min_pressure())); - } - // case 2: pressure just above min pressure, use polynomial to approximate - // nonlinear pressure-demand function for stabilization considerations - else if ((pressure > node->min_pressure()) && - ((pressure - (node->min_pressure() + node->pdd_smooth_delta()) < - tolerance))) { - auto pdd_coeff_1 = node->get_pdd_poly_coef_1(); - res = -1 * (node->iter_demand() - - node->demand() * - (pdd_coeff_1[0] * std::pow(pressure, 3) + - pdd_coeff_1[1] * std::pow(pressure, 2) + - pdd_coeff_1[2] * std::pow(pressure, 1) + pdd_coeff_1[3])); - } - // case 3: pressure-demand nonlinear function - else if ((pressure > (node->min_pressure() + node->pdd_smooth_delta())) && - ((pressure - (node->norm_pressure() - node->pdd_smooth_delta()) < - tolerance))) { - res = -1 * (node->iter_demand() - - node->demand() * - std::pow((pressure - node->min_pressure()) / - (node->norm_pressure() - node->min_pressure()), - 0.5)); - } - // case 4:pressure close to normal pressure, use polynomial to approximate - // nonlinear pressure-demand function for stabilization considerations - else if ((pressure > ((node->norm_pressure() - node->pdd_smooth_delta())) && - ((pressure - node->norm_pressure()) < tolerance))) { - auto pdd_coeff_2 = node->get_pdd_poly_coef_2(); - res = -1 * (node->iter_demand() - - node->demand() * - (pdd_coeff_2[0] * std::pow(pressure, 3) + - pdd_coeff_2[1] * std::pow(pressure, 2) + - pdd_coeff_2[2] * std::pow(pressure, 1) + pdd_coeff_2[3])); - } - // case 5: pressure above normal pressure, demand can be met - else { - res = -1 * (node->iter_demand() - node->demand()); +void pipenetwork::linear_system::MatrixAssembler::update_jacobian() { + if (pdd_) { + jac_->update_jacobian_pdd(); + } else { + jac_->update_jacobian(); } - // assign the residual - residual_vec_->coeffRef(nnode_ + npipe_ + index) = res; } -double pipenetwork::MatrixAssembler::get_pressure_head_jacob( - const std::shared_ptr& node) { - - auto pressure = node->head() - node->elevation(); - double res; - double tolerance = 1e-10; - - // case 1: pressure below min pressure, no discharge - if (pressure < node->min_pressure()) { - res = 0; - } - // case 2: pressure just above min pressure, use polynomial to approximate - // nonlinear pressure-demand function for stabilization considerations - else if ((pressure > node->min_pressure()) && - ((pressure - (node->min_pressure() + node->pdd_smooth_delta()) < - tolerance))) { - auto pdd_coeff_1 = node->get_pdd_poly_coef_1(); - res = -1 * node->demand() * - (3 * pdd_coeff_1[0] * std::pow(pressure, 2) + - 2 * pdd_coeff_1[1] * std::pow(pressure, 1) + pdd_coeff_1[2]); - } - // case 3: pressure-demand nonlinear function - else if ((pressure > (node->min_pressure() + node->pdd_smooth_delta())) && - ((pressure - (node->norm_pressure() - node->pdd_smooth_delta()) < - tolerance))) { - res = -1 * (0.5 * node->demand() * - std::pow((pressure - node->min_pressure()) / - (node->norm_pressure() - node->min_pressure()), - -0.5)); +void pipenetwork::linear_system::MatrixAssembler::update_curves_info_() { + auto leak_ids = mesh_->leak_nids(); + auto leak_areas = vars_->leak_areas(); + for (Index i = 0; i < leak_ids.size(); i++) { + std::string leak_id = std::to_string(leak_ids[i]); + auto leak_area = leak_areas[i]; + curves_info_->add_leak_poly_vec(leak_id, leak_area); } - // case 4:pressure close to normal pressure, use polynomial to approximate - // nonlinear pressure-demand function for stabilization considerations - else if ((pressure > ((node->norm_pressure() - node->pdd_smooth_delta())) && - ((pressure - node->norm_pressure()) < tolerance))) { - auto pdd_coeff_2 = node->get_pdd_poly_coef_2(); - res = -1 * node->demand() * - (3 * pdd_coeff_2[0] * std::pow(pressure, 2) + - 2 * pdd_coeff_2[1] * std::pow(pressure, 1) + pdd_coeff_2[2]); - } - // case 5: pressure above normal pressure, demand can be met - else { - res = 0; - } - - return res; } diff --git a/src/matrix_assembler_components.cc b/src/matrix_assembler_components.cc new file mode 100644 index 0000000..eee6657 --- /dev/null +++ b/src/matrix_assembler_components.cc @@ -0,0 +1,1071 @@ +#include "matrix_assembler_components.h" + +void pipenetwork::linear_system::Variables::assemble_iso_masks() { + auto nnodes = mesh_->nodes()->nnodes(); + auto nlinks = mesh_->links()->nlinks(); + + iso_junctions_mask_.setZero(nnodes); + for (auto& nid : mesh_->iso_nodes()) { + iso_junctions_mask_[nid] = 1; + } + + iso_links_mask_.setZero(nlinks); + for (auto& lid : mesh_->iso_links()) { + iso_links_mask_[lid] = 1; + } + + Eigen::VectorXd ones_link; + Eigen::VectorXd ones_nodes; + ones_link.setOnes(nlinks); + ones_nodes.setOnes(nnodes); + connect_junctions_mask_ = ones_nodes - iso_junctions_mask_; + connect_links_mask_ = ones_link - iso_links_mask_; +} + +// Initialize variable vector +// 0 to nnode-1 element: nodal head +// nnode to 2*nnode-1 element: nodal demand +// 2*nnode to 2*nnode+nlinks-1 element: pipe discharge +// 2*nnode+nlinks to 2*nnode+nlinks+nleaks element: leak discharge +void pipenetwork::linear_system::Variables::init_variable_vectors() { + auto nodes = mesh_->nodes(); + auto links = mesh_->links(); + auto leak_ids = mesh_->leak_nids(); + Index nnodes = nodes->nnodes(); + Index nlinks = links->nlinks(); + Index nleaks = leak_ids.size(); + + resize_init_variables(nnodes, nlinks, nleaks); + + init_nodes_vecs(nodes); + init_link_vecs(links, 2 * nnodes); + init_leak_nodes(nodes, leak_ids, 2 * nnodes + nlinks); +} + +void pipenetwork::linear_system::Variables::resize_init_variables( + Index nnodes, Index nlinks, Index nleaks) { + + variable_vec_.resize(2 * nnodes + nlinks + nleaks); + demands_heads_vec_.resize(nnodes); + elevations_.resize(nnodes); + link_resistance_coeff_vec_.resize(nlinks); + link_minor_loss_coeff_vec_.resize(nlinks); + leak_areas_.resize(nleaks); +} + +void pipenetwork::linear_system::Variables::init_nodes_vecs( + const std::shared_ptr& nodes) { + auto junctions_map = nodes->junctions(); + auto reservors_map = nodes->reservoirs(); + auto nnodes = nodes->nnodes(); + + for (const auto& index_junction : junctions_map) { + auto nid = index_junction.first; + auto junction = index_junction.second; + auto junc_prop = junction->property(); + demands_heads_vec_[nid] = junc_prop.demand; + variable_vec_[nnodes + nid] = junc_prop.demand; + + elevations_[nid] = junc_prop.elevation; + variable_vec_[nid] = junc_prop.elevation; + } + + for (const auto& index_res : reservors_map) { + auto nid = index_res.first; + auto res = index_res.second; + demands_heads_vec_[nid] = res->head(); + variable_vec_[nid] = res->head(); + elevations_[nid] = res->head(); + variable_vec_[nnodes + nid] = 0; + } +} + +void pipenetwork::linear_system::Variables::init_link_vecs( + const std::shared_ptr& links, + Index link_start_idx) { + auto pipes_map = links->pipes(); + auto pumps_map = links->pumps(); + auto valves_map = links->valves(); + auto links_map = links->links(); + + update_minor_resis_coeff(pipes_map); + update_minor_resis_coeff(pumps_map); + update_minor_resis_coeff(valves_map); + + for (const auto& index_link : links_map) { + auto lid = index_link.first; + variable_vec_[link_start_idx + lid] = INIT_FLOWRATE; + } +} + +template +void pipenetwork::linear_system::Variables::update_minor_resis_coeff( + const LinkMap& linkmap) { + + for (const auto& index_link : linkmap) { + auto lid = index_link.first; + auto link = index_link.second; + auto link_res_coeff = get_link_res_coeff(link); + auto minor_loss_coeff = get_link_minor_coeff(link); + + link_resistance_coeff_vec_[lid] = link_res_coeff; + link_minor_loss_coeff_vec_[lid] = minor_loss_coeff; + } +} + +double pipenetwork::linear_system::Variables::get_link_res_coeff( + const std::shared_ptr& pipe) { + auto pipe_property = pipe->property(); + auto link_res_coeff = HW_COEFF * std::pow(pipe_property.roughness, -1.852) * + std::pow(pipe_property.diameter, -4.871) * + pipe_property.length; + return link_res_coeff; +} + +double pipenetwork::linear_system::Variables::get_link_res_coeff( + const std::shared_ptr& valve) { + + auto valve_property = valve->property(); + double link_res_coeff = 0; + if (valve_property.type == ValveType::TCVALVE) { + link_res_coeff = + 8 * valve_property.setting / + (G * std::pow(PI, 2) * std::pow(valve_property.diameter, 4)); + } + return link_res_coeff; +} + +void pipenetwork::linear_system::Variables::init_leak_nodes( + const std::shared_ptr& nodes, + const std::vector& leak_ids, Index leak_start_idx) { + auto junction_map = nodes->junctions(); + Index i = 0; + for (const auto& leak_id : leak_ids) { + auto leak_junction = junction_map.at(leak_id); + leak_areas_[i] = leak_junction->leak_area(); + variable_vec_[leak_start_idx + i] = 0; + i++; + } +} + +pipenetwork::linear_system::Residuals::Residuals( + const std::shared_ptr& mesh, + const std::shared_ptr& vars, + const std::shared_ptr& curves) + : mesh_{mesh}, + vars_{vars}, + variable_vec_{vars_->variables_vec()}, + curves_info_{curves} { + + auto var_size = vars_->variables_vec().size(); + residual_vec_.resize(var_size); + + nnodes_ = mesh_->nodes()->nnodes(); + nlinks_ = mesh_->links()->nlinks(); + + assemble_balance_headloss_matrix(); + assemble_residual_pdd(); // initialize HW/PDD vectors for jacobian matrix +} + +// Assemble node balance and link headloss matrix, which contains relation +// between discharges and heads. These matrix are parts of big jacobian matrix +// and can be used for fast residual computation +void pipenetwork::linear_system::Residuals::assemble_balance_headloss_matrix() { + std::vector> update_balance, update_headloss; + auto links = mesh_->links(); + + update_balance.reserve(nnodes_ + nlinks_); + update_headloss.reserve(nnodes_ + nlinks_); + + for (const auto& index_link : links->links()) { + auto lid = index_link.first; + auto link = index_link.second; + auto out_node_id = link->nodes().first->id(); + auto in_node_id = link->nodes().second->id(); + + update_balance.emplace_back(out_node_id, lid, -1); + update_balance.emplace_back(in_node_id, lid, 1); + + update_headloss.emplace_back(lid, out_node_id, 1); + update_headloss.emplace_back(lid, in_node_id, -1); + } + + node_balance_mat_.resize(nnodes_, nlinks_); + node_balance_mat_.setFromTriplets(update_balance.begin(), + update_balance.end()); + + headloss_mat_.resize(nlinks_, nnodes_); + headloss_mat_.setFromTriplets(update_headloss.begin(), update_headloss.end()); +} + +void pipenetwork::linear_system::Residuals::assemble_residual() { + + assemble_node_balance_residual(); + assemble_demand_head_residual(); + + assemble_headloss_residual_pipe(); + assemble_headloss_residual_pump(); + assemble_headloss_residual_valve(); + + assemble_leak_residual(); +} + +void pipenetwork::linear_system::Residuals::assemble_residual_pdd() { + + assemble_residual(); + assemble_demand_head_residual_pdd(); +} + +void pipenetwork::linear_system::Residuals::assemble_node_balance_residual() { + residual_vec_.segment(0, nnodes_) = + node_balance_mat_ * (variable_vec_.segment(2 * nnodes_, nlinks_)) - + variable_vec_.segment(nnodes_, nnodes_); + + // correct on leaking nodes + auto leak_ids = mesh_->leak_nids(); + int leak_idx = 0; + for (const auto& leak_id : leak_ids) { + residual_vec_.coeffRef(leak_id) -= + variable_vec_.coeffRef(2 * nnodes_ + nlinks_ + leak_idx); + ++leak_idx; + } +} + +void pipenetwork::linear_system::Residuals::assemble_demand_head_residual() { + + auto demands_heads_vec = vars_->demands_heads_vec(); + auto iso_junction_mask = vars_->iso_junctions_mask(); + auto connect_junctions_mask = vars_->connect_junctions_mask(); + // demand for junctions + residual_vec_.segment(nnodes_, nnodes_) = + iso_junction_mask.array() * variable_vec_.segment(0, nnodes_).array() + + connect_junctions_mask.array() * + (variable_vec_.segment(nnodes_, nnodes_) - demands_heads_vec).array(); + + // correct residuals for sources (head for reservoir/tanks) + auto nsrcs = mesh_->nodes()->nreservoirs(); + auto njunctions = mesh_->nodes()->njunctions(); + residual_vec_.segment(nnodes_ + njunctions, nsrcs) = + variable_vec_.segment(njunctions, nsrcs) - + demands_heads_vec.segment(njunctions, nsrcs); +} + +void pipenetwork::linear_system::Residuals::update_pdd_vectors() { + auto pressure = (variable_vec_.segment(0, nnodes_) - vars_->elevations()); + pdd_vec_.pressure = pressure; + + // case 1, pressure smaller than min pressure, no water + pdd_vec_.case1_bool = pressure + .unaryExpr([](double x) { + if (x <= MIN_PRESSURE) return 1.0; + return 0.0; + }) + .array(); + // case 2, pressure larger than min pressure but in a small range, use + // polynomial approximation + pdd_vec_.case2_bool = + pressure + .unaryExpr([](double x) { + if ((x > MIN_PRESSURE) && (x < (MIN_PRESSURE + PDD_DELTA))) + return 1.0; + return 0.0; + }) + .array(); + // case 3, pressure close to normal pressure, use polynomial approximation + pdd_vec_.case3_bool = + pressure + .unaryExpr([](double x) { + if ((x > (NORMAL_PRESSURE - PDD_DELTA)) && (x < (NORMAL_PRESSURE))) + return 1.0; + return 0.0; + }) + .array(); + // case 4, pressure above normal pressure, demand can be met + pdd_vec_.case4_bool = pressure + .unaryExpr([](double x) { + if ((x > NORMAL_PRESSURE)) return 1.0; + return 0.0; + }) + .array(); + // case 5, pressure falls in between min pressure and normal pressure, use + // pressure-demand equation + pdd_vec_.case5_bool = pressure + .unaryExpr([](double x) { + if ((x > (MIN_PRESSURE + PDD_DELTA)) && + (x < (NORMAL_PRESSURE - PDD_DELTA))) + return 1.0; + return 0.0; + }) + .array(); + pdd_vec_.pdd1_poly_vec = curves_info_->poly_coeffs()["PDD_POLY_VEC1"]; + pdd_vec_.pdd2_poly_vec = curves_info_->poly_coeffs()["PDD_POLY_VEC2"]; +} + +void pipenetwork::linear_system::Residuals:: + assemble_demand_head_residual_pdd() { + + update_pdd_vectors(); + + auto iso_links_mask = vars_->iso_links_mask(); + auto connect_links_mask = vars_->connect_links_mask(); + auto demands_heads_vec = vars_->demands_heads_vec(); + + residual_vec_.segment(nnodes_, nnodes_) = + iso_links_mask.array() * variable_vec_.segment(0, nnodes_).array() + + connect_links_mask.array() * + (pdd_vec_.case1_bool * + (variable_vec_.segment(nnodes_, nnodes_).array() - + demands_heads_vec.array() * PDD_SLOPE * + (pdd_vec_.pressure.array() - MIN_PRESSURE)) + + pdd_vec_.case2_bool * + ((variable_vec_.segment(nnodes_, nnodes_).array()) - + demands_heads_vec.array() * + (pdd_vec_.pdd1_poly_vec[0] * + pdd_vec_.pressure.array().pow(3) + + pdd_vec_.pdd1_poly_vec[1] * + pdd_vec_.pressure.array().pow(2) + + pdd_vec_.pdd1_poly_vec[2] * pdd_vec_.pressure.array() + + pdd_vec_.pdd1_poly_vec[3])) + + pdd_vec_.case3_bool * + ((variable_vec_.segment(nnodes_, nnodes_).array()) - + demands_heads_vec.array() * + (pdd_vec_.pdd2_poly_vec[0] * + pdd_vec_.pressure.array().pow(3) + + pdd_vec_.pdd2_poly_vec[1] * + pdd_vec_.pressure.array().pow(2) + + pdd_vec_.pdd2_poly_vec[2] * pdd_vec_.pressure.array() + + pdd_vec_.pdd2_poly_vec[3])) + + pdd_vec_.case4_bool * + ((variable_vec_.segment(nnodes_, nnodes_).array()) - + demands_heads_vec.array() * + (PDD_SLOPE * (pdd_vec_.pressure.array() - NORMAL_PRESSURE) + + 1)) + + pdd_vec_.case5_bool * + ((variable_vec_.segment(nnodes_, nnodes_).array()) - + demands_heads_vec.array() * + ((pdd_vec_.pressure.array().abs() - MIN_PRESSURE) / + (NORMAL_PRESSURE - MIN_PRESSURE)) + .abs() + .pow(0.5))); + + // correct residuals for sources (head for reservoir/tanks) + auto nsrcs = mesh_->nodes()->nreservoirs(); + auto njunctions = mesh_->nodes()->njunctions(); + residual_vec_.segment(nnodes_ + njunctions, nsrcs) = + variable_vec_.segment(njunctions, nsrcs) - + demands_heads_vec.segment(njunctions, nsrcs); +} + +void pipenetwork::linear_system::Residuals::update_hw_vectors() { + auto npipes = mesh_->links()->npipes(); + hw_vec_.sign_array = (variable_vec_.segment(2 * nnodes_, npipes)) + .unaryExpr([](double x) { + // return (x < 0) ? -1 : + // 1; + if (x > 0) return 1.0; + return -1.0; + }) + .array(); // get the sign of discharges + // case 1, discharges that exceed the boundary of HW_Q2, use normal + // hazen-william equation + hw_vec_.case1_bool = (variable_vec_.segment(2 * nnodes_, npipes)) + .unaryExpr([](double x) { + if (std::abs(x) > HW_Q2) return 1.0; + return 0.0; + }) + .array(); + // case 2, discharges that fall in between HW_Q1 and HW_Q2, use polynomial + // approximation + hw_vec_.case2_bool = (variable_vec_.segment(2 * nnodes_, npipes)) + .unaryExpr([](double x) { + if ((std::abs(x) < HW_Q2) && (std::abs(x) > HW_Q1)) + return 1.0; + return 0.0; + }) + .array(); + // case 3, discharges that are smaller than HW_Q1 , approximate 0 headloss in + // this case + hw_vec_.case3_bool = (variable_vec_.segment(2 * nnodes_, npipes)) + .unaryExpr([](double x) { + if (std::abs(x) < HW_Q1) return 1.0; + return 0.0; + }) + .array(); + hw_vec_.discharge_abs_array = + ((variable_vec_.segment(2 * nnodes_, npipes)).array()).abs(); + hw_vec_.head_diff_array = + (headloss_mat_ * (variable_vec_.segment(0, nnodes_))) + .segment(0, npipes) + .array(); + hw_vec_.hw_poly_vec = curves_info_->poly_coeffs()["HW_POLY_VEC"]; +} +void pipenetwork::linear_system::Residuals::assemble_headloss_residual_pipe() { + + auto npipes = mesh_->links()->npipes(); + auto link_resistance_coeff_vec = vars_->link_resistance_coeff_vec(); + auto iso_links_mask = vars_->iso_links_mask(); + auto connect_links_mask = vars_->connect_links_mask(); + + update_hw_vectors(); + + residual_vec_.segment(2 * nnodes_, npipes) = + (iso_links_mask.segment(0, npipes).array() * + variable_vec_.segment(2 * nnodes_, npipes).array()) + + connect_links_mask.segment(0, npipes).array() * + (hw_vec_.case1_bool * + (hw_vec_.sign_array * + link_resistance_coeff_vec.segment(0, npipes).array() * + hw_vec_.discharge_abs_array.pow(1.852) - + hw_vec_.head_diff_array) + + + hw_vec_.case2_bool * + (hw_vec_.sign_array * + link_resistance_coeff_vec.segment(0, npipes).array() * + (hw_vec_.hw_poly_vec[0] * + hw_vec_.discharge_abs_array.pow(3) + + hw_vec_.hw_poly_vec[1] * + hw_vec_.discharge_abs_array.pow(2) + + hw_vec_.hw_poly_vec[2] * hw_vec_.discharge_abs_array + + hw_vec_.hw_poly_vec[3]) - + hw_vec_.head_diff_array) + + hw_vec_.case3_bool * + (hw_vec_.sign_array * + link_resistance_coeff_vec.segment(0, npipes).array() * + HW_M * hw_vec_.discharge_abs_array - + hw_vec_.head_diff_array)); +} + +void pipenetwork::linear_system::Residuals::assemble_headloss_residual_pump() { + auto pumps_map = mesh_->links()->pumps(); + for (const auto& index_pump : pumps_map) { + auto lid = index_pump.first; + auto pump = index_pump.second; + auto nodes = pump->nodes(); + auto pump_info = pump->property(); + auto link_flow = variable_vec_[2 * nnodes_ + lid]; + + double pump_residual = 0; + if (vars_->iso_links_mask()[lid] == 1) { + pump_residual = link_flow; + } else if (pump_info.type == PumpType::HEADPUMP) { + auto pump_headgain = get_pump_headgain(pump, link_flow); + pump_residual = pump_headgain - (variable_vec_[nodes.second->id()] - + variable_vec_[nodes.first->id()]); + + } else if (pump_info.type == PumpType::POWERPUMP) { + auto head_diff_array = + (headloss_mat_ * (variable_vec_.segment(0, nnodes_))).array(); + pump_residual = + pump_info.power + (head_diff_array[lid]) * link_flow * G * 1000.0; + } + residual_vec_[2 * nnodes_ + lid] = pump_residual; + } +} + +double pipenetwork::linear_system::Residuals::get_pump_headgain( + const std::shared_ptr& pump, double link_flow) { + auto pump_info = pump->property(); + + auto pump_curve = curves_info_->pump_curves().at( + curves_info_->pump_int_str(pump_info.curve_id)); + auto curve_coeff = pump_curve.head_curve_coefficients; + + double pump_headgain = 0; + + if (curve_coeff[2] > 1) { + auto line_coeff = pump_curve.line_param; + if (link_flow >= line_coeff[0]) { + pump_headgain = + curve_coeff[0] - curve_coeff[1] * std::pow(link_flow, curve_coeff[2]); + } else { + pump_headgain = PUMP_M * (link_flow - line_coeff[0]) + line_coeff[1]; + } + } else { + if (link_flow < PUMP_Q1) { + pump_headgain = PUMP_M * link_flow + curve_coeff[0]; + } else if (link_flow < PUMP_Q2) { + auto curve_poly_coeff = pump_curve.poly_coefficients; + pump_headgain = curve_poly_coeff[0] * std::pow(link_flow, 3) + + curve_poly_coeff[1] * std::pow(link_flow, 2) + + curve_poly_coeff[2] * link_flow + curve_poly_coeff[3]; + } else { + pump_headgain = + curve_coeff[0] - curve_coeff[1] * std::pow(link_flow, curve_coeff[2]); + } + } + return pump_headgain; +} + +void pipenetwork::linear_system::Residuals::assemble_headloss_residual_valve() { + + auto valve_map = mesh_->links()->valves(); + for (const auto& index_valve : valve_map) { + auto lid = index_valve.first; + auto valve = index_valve.second; + + auto valve_info = valve->property(); + auto link_flow = variable_vec_[2 * nnodes_ + lid]; + + double valve_residual = 0; + if (vars_->iso_links_mask()[lid] == 1 || + valve_info.status == LinkStatus::CLOSED) { + valve_residual = link_flow; + } else if (valve_info.status == LinkStatus::OPEN) { + valve_residual = get_open_valve_residual(valve, link_flow); + } + if (valve_info.status == LinkStatus::ACTIVE) { + valve_residual = get_active_valve_residual(valve, link_flow); + } + + residual_vec_[2 * nnodes_ + lid] = valve_residual; + } +} + +double pipenetwork::linear_system::Residuals::get_open_valve_residual( + const std::shared_ptr& valve, double link_flow) { + + auto lid = valve->id(); + auto link_minor_loss_coeff_vec = vars_->link_minor_loss_coeff_vec(); + auto pipe_headloss = link_minor_loss_coeff_vec[lid] * std::pow(link_flow, 2); + if (link_flow < 0) { + pipe_headloss = -1 * pipe_headloss; + } + auto head_diff_array = + (headloss_mat_ * (variable_vec_.segment(0, nnodes_))).array(); + + double valve_residual = pipe_headloss - head_diff_array[lid]; + return valve_residual; +} + +double pipenetwork::linear_system::Residuals::get_active_valve_residual( + const std::shared_ptr& valve, double link_flow) { + auto valve_info = valve->property(); + auto nodes = valve->nodes(); + + double valve_res = 0; + if (valve_info.type == ValveType::PRVALVE) { + auto end_node_idx = nodes.second->id(); + auto end_node_elevation = vars_->elevations()[end_node_idx]; + valve_res = + variable_vec_[end_node_idx] - (valve_info.setting + end_node_elevation); + } else if (valve_info.type == ValveType::FCVALVE) { + valve_res = link_flow - valve_info.setting; + } else if (valve_info.type == ValveType::TCVALVE) { + auto link_resistance_coeff_vec = vars_->link_resistance_coeff_vec(); + auto coeff = link_resistance_coeff_vec[valve->id()]; + auto pipe_headloss = coeff * std::pow(link_flow, 2); + if (link_flow < 0) { + pipe_headloss = -1 * pipe_headloss; + } + auto head_diff_array = + (headloss_mat_ * (variable_vec_.segment(0, nnodes_))).array(); + + valve_res = pipe_headloss - head_diff_array[valve->id()]; + } + return valve_res; +} + +// Residual for leak from holes. piece-wise function, use for loop... (number of +// leak nodes is usually small too) + +void pipenetwork::linear_system::Residuals::assemble_leak_residual() { + double m = 1e-4; + Index leak_idx = 2 * nnodes_ + nlinks_; + auto leak_ids = mesh_->leak_nids(); + auto elevations = vars_->elevations(); + auto leak_areas = vars_->leak_areas(); + + double leak_residual = 0; + for (const auto& leak_id : leak_ids) { + if (vars_->iso_junctions_mask()[leak_id] == 1) { + leak_residual = variable_vec_[leak_idx]; + } else { + auto p = variable_vec_[leak_id] - elevations[leak_id]; + // case 1, no pressure no leak + if (p < m) { + leak_residual = variable_vec_[leak_idx] - m * p; + } + // case 3, normal leak equation + else { + auto i = leak_idx - 2 * nnodes_ - nlinks_; + leak_residual = variable_vec_[leak_idx] - + LEAK_COEFF * leak_areas[i] * std::sqrt(2 * G * p); + } + residual_vec_[leak_idx] = leak_residual; + ++leak_idx; + } + } +} + +pipenetwork::linear_system::Jacobian::Jacobian( + const std::shared_ptr& mesh, + const std::shared_ptr& vars, + const std::shared_ptr& residuals, + const std::shared_ptr& curves) + : mesh_{mesh}, + vars_{vars}, + residuals_{residuals}, + curves_info_{curves}, + variable_vec_{vars_->variables_vec()} { + + nnodes_ = mesh_->nodes()->nnodes(); + nlinks_ = mesh_->links()->nlinks(); + + initialize_jacobian(); + update_jacobian(); +} + +void pipenetwork::linear_system::Jacobian::initialize_jacobian() { + initialize_subjacA(); + initialize_subjacBnF(); + initialize_subjacC(); + initialize_subjacDnE(); + initialize_subjacG(); + initialize_subjacHnI(); + + // loop through all the sub-matrix to form the initial jacobian matrix + auto leaks_id = mesh_->leak_nids(); + jac_.resize(2 * nnodes_ + nlinks_ + leaks_id.size(), + 2 * nnodes_ + nlinks_ + leaks_id.size()); + + std::vector> jac_triplet; + jac_triplet.reserve(10 * nnodes_); + for (auto const& trip_map : sub_jac_trip_) { + jac_triplet.insert(std::end(jac_triplet), std::begin(trip_map.second), + std::end(trip_map.second)); + } + jac_.setFromTriplets(jac_triplet.begin(), jac_triplet.end()); +} + +void pipenetwork::linear_system::Jacobian::initialize_subjacA() { + std::vector> update; + update.reserve(nnodes_); + for (int row_idx = 0; row_idx < nnodes_; row_idx++) { + auto col_idx = row_idx + nnodes_; + update.emplace_back(row_idx, col_idx, -1); + } + sub_jac_trip_["jac_a"] = update; +} + +void pipenetwork::linear_system::Jacobian::initialize_subjacBnF() { + std::vector> update_jacb, update_jacf; + update_jacb.reserve(2 * nlinks_); + update_jacf.reserve(2 * nlinks_); + + auto links = mesh_->links(); + auto pump_start_lid = links->npipes(); + auto pump_end_lid = pump_start_lid + links->npumps(); + for (const auto& index_link : links->links()) { + auto lid = index_link.first; + auto link = index_link.second; + auto out_node_id = link->nodes().first->id(); + auto in_node_id = link->nodes().second->id(); + + update_jacb.emplace_back(out_node_id, lid + 2 * nnodes_, -1); + update_jacb.emplace_back(in_node_id, lid + 2 * nnodes_, 1); + + double valout = -1, valin = 1; + // reverse on pumps + if (lid >= pump_start_lid && lid < pump_end_lid) { + valin *= -1; + valout *= -1; + } + update_jacf.emplace_back(lid + 2 * nnodes_, out_node_id, valout); + update_jacf.emplace_back(lid + 2 * nnodes_, in_node_id, valin); + } + + sub_jac_trip_["jac_b"] = update_jacb; + sub_jac_trip_["jac_f"] = update_jacf; +} + +void pipenetwork::linear_system::Jacobian::initialize_subjacC() { + auto leak_ids = mesh_->leak_nids(); + + std::vector> update; + update.reserve(leak_ids.size()); + + Index idx = 0; + for (const auto& leak_id : leak_ids) { + auto col_idx = 2 * nnodes_ + nlinks_ + idx; + update.emplace_back(leak_id, col_idx, -1); + ++idx; + } + sub_jac_trip_["jac_c"] = update; +} + +void pipenetwork::linear_system::Jacobian::initialize_subjacDnE() { + auto nodes = mesh_->nodes(); + auto src_start_nid = nodes->njunctions(); + auto src_end_nid = src_start_nid + nodes->nreservoirs(); + + std::vector> updateD, updateE; + updateD.reserve(nnodes_); + updateE.reserve(nnodes_); + + for (int row_idx = nnodes_; row_idx < nnodes_ + nnodes_; row_idx++) { + auto nid = row_idx - nnodes_; + if (nid >= src_start_nid && nid < src_end_nid) { + updateD.emplace_back(row_idx, row_idx - nnodes_, 1); // sources + updateE.emplace_back(row_idx, row_idx, 0); + } else { + updateD.emplace_back(row_idx, row_idx - nnodes_, 0); + updateE.emplace_back(row_idx, row_idx, 1); + } + } + sub_jac_trip_["jac_d"] = updateD; + sub_jac_trip_["jac_e"] = updateE; +} + +void pipenetwork::linear_system::Jacobian::initialize_subjacG() { + std::vector> update; + update.reserve(nlinks_); + + for (int row_idx = 0; row_idx < nlinks_; row_idx++) { + auto col_idx = row_idx; + update.emplace_back(row_idx + 2 * nnodes_, col_idx + 2 * nnodes_, 1); + } + sub_jac_trip_["jac_g"] = update; +} + +void pipenetwork::linear_system::Jacobian::initialize_subjacHnI() { + auto leak_ids = mesh_->leak_nids(); + + std::vector> updateH, updateI; + updateH.reserve(leak_ids.size()); + updateI.reserve(leak_ids.size()); + + unsigned idx = 0; + for (const auto& leak_id : leak_ids) { + auto col_idx = leak_id; + auto row_idx = 2 * nnodes_ + nlinks_ + idx; + updateH.emplace_back(row_idx, col_idx, 0); + updateI.emplace_back(row_idx, row_idx, 1); + ++idx; + } + sub_jac_trip_["jac_h"] = updateH; + sub_jac_trip_["jac_i"] = updateI; +} + +void pipenetwork::linear_system::Jacobian::update_jacobian() { + set_jac_const(); + // Jac_f: for power pump only + update_jac_f(); + // jac_g: headloss equation (harzen-william) + update_jac_g_pipe(); + update_jac_g_pump(); + update_jac_g_valve(); + // jac_h: leak equation + update_jac_h(); +} + +void pipenetwork::linear_system::Jacobian::update_jacobian_pdd() { + update_jacobian(); + // Jac_d: pressure-demand equation + update_jac_d(); +} + +void pipenetwork::linear_system::Jacobian::set_jac_const() { + // get trip f and isolated junctions+sources + + Eigen::VectorXd iso_junc_src = vars_->iso_junctions_mask(); + Eigen::VectorXd connect_junc_no_src = vars_->connect_junctions_mask(); + + auto reservoir_map = mesh_->nodes()->reservoirs(); + for (const auto& index_src : reservoir_map) { + auto nid = index_src.first; + iso_junc_src[nid] = 1; + connect_junc_no_src[nid] = 0; + } + + // change jacobian matrix entries based on connection status + int count = 0; + for (const auto& trip_d : sub_jac_trip_["jac_d"]) { + jac_.coeffRef(trip_d.row(), trip_d.col()) = iso_junc_src[count]; + ++count; + } + count = 0; + for (const auto& trip_e : sub_jac_trip_["jac_e"]) { + jac_.coeffRef(trip_e.row(), trip_e.col()) = connect_junc_no_src[count]; + ++count; + } + + set_jacF_const(); +} + +void pipenetwork::linear_system::Jacobian::set_jacF_const() { + auto trip_f = sub_jac_trip_["jac_f"]; + auto connect_links = vars_->connect_links_mask(); + for (int i = 0; i < nlinks_; ++i) { + jac_.coeffRef(trip_f[2 * i].row(), trip_f[2 * i].col()) = + connect_links[i] * trip_f[2 * i].value(); + jac_.coeffRef(trip_f[2 * i + 1].row(), trip_f[2 * i + 1].col()) = + connect_links[i] * trip_f[2 * i + 1].value(); + } + // iterate through all the valves for jac_f corrections + auto valves_map = mesh_->links()->valves(); + auto npipes = mesh_->links()->npipes(); + auto npumps = mesh_->links()->npumps(); + + for (const auto& index_valve : valves_map) { + Index valve_idx = index_valve.first; + auto valve = index_valve.second; + auto valve_info = valve->property(); + + if (valve_info.status == LinkStatus::ACTIVE) { + if (valve_info.type == ValveType::PRVALVE) { + jac_.coeffRef(trip_f[2 * valve_idx].row(), + trip_f[2 * valve_idx].col()) = 0; + } else if (valve_info.type == ValveType::FCVALVE) { + jac_.coeffRef(trip_f[2 * valve_idx].row(), + trip_f[2 * valve_idx].col()) = 0; + jac_.coeffRef(trip_f[2 * valve_idx + 1].row(), + trip_f[2 * valve_idx + 1].col()) = 0; + } + } + } +} +// +void pipenetwork::linear_system::Jacobian::update_jac_d() { + auto pdd_vec = residuals_->pdd_vectors(); + + auto iso_junctions = vars_->iso_junctions_mask(); + auto connect_junctions = vars_->connect_junctions_mask(); + auto demans_head_vec = vars_->demands_heads_vec(); + + auto vals = + iso_junctions.array() + + connect_junctions.array() * + (pdd_vec.case1_bool * (-PDD_SLOPE * demans_head_vec.array() * + variable_vec_.segment(0, nnodes_).array()) + + pdd_vec.case2_bool * (-demans_head_vec.array() * + (3 * pdd_vec.pdd1_poly_vec[0] * + pdd_vec.pressure.array().pow(2) + + 2 * pdd_vec.pdd1_poly_vec[1] * + pdd_vec.pressure.array().pow(1) + + pdd_vec.pdd1_poly_vec[2])) + + pdd_vec.case3_bool * (-demans_head_vec.array() * + (3 * pdd_vec.pdd2_poly_vec[0] * + pdd_vec.pressure.array().pow(2) + + 2 * pdd_vec.pdd2_poly_vec[1] * + pdd_vec.pressure.array().pow(1) + + pdd_vec.pdd2_poly_vec[2])) + + pdd_vec.case4_bool * (-PDD_SLOPE * demans_head_vec.array() * + variable_vec_.segment(0, nnodes_).array()) + + pdd_vec.case5_bool * + (-0.5 * demans_head_vec.array() / + (NORMAL_PRESSURE - MIN_PRESSURE) * + ((pdd_vec.pressure.array().abs() - MIN_PRESSURE) / + (NORMAL_PRESSURE - MIN_PRESSURE)) + .abs() + .pow(-0.5))); + + auto trip_d = sub_jac_trip_["jac_d"]; + auto njunctions = mesh_->nodes()->njunctions(); + for (Index i = 0; i < njunctions; ++i) { + jac_.coeffRef(trip_d[i].row(), trip_d[i].col()) = vals[i]; + } +} + +void pipenetwork::linear_system::Jacobian::update_jac_f() { + auto trip_f = sub_jac_trip_["jac_f"]; + auto pumps_map = mesh_->links()->pumps(); + auto iso_links = vars_->iso_links_mask(); + + for (const auto& index_pump : pumps_map) { + auto lid = index_pump.first; + auto pump = index_pump.second; + + if (iso_links[lid] == 0) { + auto pump_info = pump->property(); + + if (pump_info.type == PumpType::POWERPUMP) { + auto link_flow = variable_vec_[2 * nnodes_ + lid]; + + jac_.coeffRef(trip_f[2 * lid].row(), trip_f[2 * lid].col()) = + 1000.0 * G * link_flow; + jac_.coeffRef(trip_f[2 * lid + 1].row(), trip_f[2 * lid + 1].col()) = + -1000.0 * G * link_flow; + } + } + } +} + +void pipenetwork::linear_system::Jacobian::update_jac_g_pipe() { + auto npipes = mesh_->links()->npipes(); + auto link_resistance_coeff_vec = vars_->link_resistance_coeff_vec(); + auto iso_links_mask = vars_->iso_links_mask(); + auto connect_links_mask = vars_->connect_links_mask(); + auto hw_vectors = residuals_->hw_vectors(); + + auto vals = + (iso_links_mask.segment(0, npipes)).array() + + connect_links_mask.segment(0, npipes).array() * + (hw_vectors.case1_bool * 1.852 * + link_resistance_coeff_vec.segment(0, npipes).array() * + hw_vectors.discharge_abs_array.pow(.852) + + hw_vectors.case2_bool * + link_resistance_coeff_vec.segment(0, npipes).array() * + (3 * hw_vectors.hw_poly_vec[0] * + hw_vectors.discharge_abs_array.pow(2) + + 2 * hw_vectors.hw_poly_vec[1] * hw_vectors.discharge_abs_array + + 1 * hw_vectors.hw_poly_vec[2]) + + hw_vectors.case3_bool * + link_resistance_coeff_vec.segment(0, npipes).array() * HW_M); + auto trip_g = sub_jac_trip_["jac_g"]; + for (int i = 0; i < npipes; ++i) { + jac_.coeffRef(trip_g[i].row(), trip_g[i].col()) = vals[i]; + } +} + +void pipenetwork::linear_system::Jacobian::update_jac_g_pump() { + + auto trip_g = sub_jac_trip_["jac_g"]; + auto pumps_map = mesh_->links()->pumps(); + + for (const auto& index_pump : pumps_map) { + auto lid = index_pump.first; + auto pump = index_pump.second; + auto nodes = pump->nodes(); + auto pump_info = pump->property(); + auto link_flow = variable_vec_[2 * nnodes_ + lid]; + + double pump_jac = 0; + if (vars_->iso_links_mask()[lid] == 1) { + pump_jac = 1; + } else if (pump_info.type == PumpType::HEADPUMP) { + pump_jac = get_pump_jac(pump, link_flow); + + } else if (pump_info.type == PumpType::POWERPUMP) { + auto start_node_idx = nodes.first->id(); + auto end_node_idx = nodes.second->id(); + pump_jac = (1000.0 * G * variable_vec_[start_node_idx] - + 1000.0 * G * variable_vec_[end_node_idx]); + } + + jac_.coeffRef(trip_g[lid].row(), trip_g[lid].col()) = pump_jac; + } +} + +double pipenetwork::linear_system::Jacobian::get_pump_jac( + const std::shared_ptr& pump, double link_flow) { + auto pump_info = pump->property(); + + auto pump_curve = curves_info_->pump_curves().at( + curves_info_->pump_int_str(pump_info.curve_id)); + auto curve_coeff = pump_curve.head_curve_coefficients; + + double pump_jac = 0; + + if (curve_coeff[2] > 1) { + auto line_coeff = pump_curve.line_param; + if (link_flow >= line_coeff[0]) { + pump_jac = -curve_coeff[1] * curve_coeff[2] * + std::pow(link_flow, (curve_coeff[2] - 1)); + + } else { + pump_jac = PUMP_M; + } + } else { + if (link_flow < PUMP_Q1) { + pump_jac = PUMP_M; + } else if (link_flow < PUMP_Q2) { + auto curve_poly_coeff = pump_curve.poly_coefficients; + pump_jac = 3 * curve_poly_coeff[0] * std::pow(link_flow, 2) + + 2 * curve_poly_coeff[1] * link_flow + curve_poly_coeff[2]; + } else { + pump_jac = -curve_coeff[1] * curve_coeff[2] * + std::pow(link_flow, (curve_coeff[2] - 1)); + } + } + return pump_jac; +} + +void pipenetwork::linear_system::Jacobian::update_jac_g_valve() { + + auto hw_vectors = residuals_->hw_vectors(); + auto link_resistance_coeff_vec = vars_->link_resistance_coeff_vec(); + auto link_minor_loss_coeff_vec = vars_->link_minor_loss_coeff_vec(); + + auto head_diff_array = hw_vectors.head_diff_array; + auto trip_g = sub_jac_trip_["jac_g"]; + + // iterate through all the valves for jac_f corrections + auto valves_map = mesh_->links()->valves(); + auto npipes = mesh_->links()->npipes(); + auto npumps = mesh_->links()->npumps(); + auto iso_links = vars_->iso_links_mask(); + + for (const auto& index_valve : valves_map) { + Index lid = index_valve.first; + auto valve = index_valve.second; + + auto valve_info = valve->property(); + if (iso_links[lid] == 1) { + jac_.coeffRef(trip_g[lid].row(), trip_g[lid].col()) = 1; + } else { + double val = 0; + auto link_flow = variable_vec_[2 * nnodes_ + lid]; + + // PRV + if (valve_info.type == ValveType::PRVALVE) { + if (valve_info.status == LinkStatus::CLOSED) { + val = 1; + } else if (valve_info.status == LinkStatus::ACTIVE) { + val = 0; + } + } + + // FCV + else if (valve_info.type == ValveType::FCVALVE) { + if (valve_info.status == LinkStatus::CLOSED) { + val = 1; + } else if (valve_info.status == LinkStatus::ACTIVE) { + val = 1; + } + } + + // TCV + else if (valve_info.type == ValveType::TCVALVE) { + if (valve_info.status == LinkStatus::CLOSED) { + val = link_flow; + } else if (valve_info.status == LinkStatus::ACTIVE) { + auto coeff = link_resistance_coeff_vec[lid]; + val = 2 * coeff * std::abs(link_flow); + } + } + + if (valve_info.status == LinkStatus::OPEN) { + auto coeff = link_minor_loss_coeff_vec[lid]; + val = 2 * coeff * std::abs(link_flow); + } + jac_.coeffRef(trip_g[lid].row(), trip_g[lid].col()) = val; + } + } +} + +void pipenetwork::linear_system::Jacobian::update_jac_h() { + double m = 1e-4; + Index leak_idx = 2 * nnodes_ + nlinks_; + auto leak_ids = mesh_->leak_nids(); + auto elevations = vars_->elevations(); + auto leak_areas = vars_->leak_areas(); + auto trip_h = sub_jac_trip_["jac_h"]; + + double val = 0; + for (const auto& leak_id : leak_ids) { + auto p = variable_vec_[leak_id] - elevations[leak_id]; + // case 1, no pressure no leak + if (p < m) { + val = -m; + } + // case 3, normal leak equation + else { + auto i = leak_idx - 2 * nnodes_ - nlinks_; + val = -0.5 * LEAK_COEFF * leak_areas[i] * std::sqrt(2 * G) * + std::pow(p, -0.5); + } + jac_.coeffRef(trip_h[leak_idx - 2 * nnodes_ - nlinks_].row(), + trip_h[leak_idx - 2 * nnodes_ - nlinks_].col()) = val; + ++leak_idx; + } +} diff --git a/src/mesh.cc b/src/mesh.cc index 0ed7921..23005f2 100644 --- a/src/mesh.cc +++ b/src/mesh.cc @@ -1,96 +1,57 @@ - #include "mesh.h" +void pipenetwork::Mesh::find_iso_components_() { + find_iso_nodes_(); + find_iso_links_(); +} + +void pipenetwork::Mesh::find_iso_nodes_() { + Index nnodes = mesh_nodes_->nnodes(); + Eigen::VectorXd check_result(nnodes); + check_result.setZero(nnodes); -// Create nodal pointers and assign indices based on input coordinates -void pipenetwork::Mesh::create_nodes( - const std::vector& coords) { - Index index = 0; - for (const auto& coord : coords) { - nodes_.emplace(std::pair>( - index, std::make_shared(index, coord))); - ++index; + auto reservoirs = mesh_nodes_->reservoirs(); + for (const auto& index_res : reservoirs) { + auto res_id = index_res.first; + check_result += mesh_graph_->bfs(res_id); + } + for (Index i = 0; i < nnodes; ++i) { + if (check_result[i] == 0) { + iso_nodes_.emplace_back(i); + } } } -// Create pipe pointers and assign indices based on the nodes at its ends -bool pipenetwork::Mesh::create_pipes( - const std::vector>& nodeids, - const std::vector& diameter, const std::vector& roughness, - const std::vector& pipe_status) { - bool status = true; - Index index = 0; - try { - for (const auto& nodeid : nodeids) { - std::array, 2> nodes; - nodes.at(0) = nodes_.at(nodeid.first); - nodes.at(1) = nodes_.at(nodeid.second); - pipes_.emplace(std::pair>( - index, std::make_shared( - index, nodes, diameter.at(index), roughness.at(index), - pipe_status.at(index)))); - ++index; +void pipenetwork::Mesh::find_leak_nids() { + auto junctions = mesh_nodes_->junctions(); + for (const auto& index_junc : junctions) { + auto nid = index_junc.first; + auto junction = index_junc.second; + if (junction->leak_area() > 0) { + leak_nids_.emplace_back(nid); } - } catch (std::out_of_range& range_error) { - status = false; - std::cout << "Pipe(id: " << index - << ") is not created, as input node does not exist, nodal id: " - << nodeids.at(index).first << " or " << nodeids.at(index).second - << '\n' - << "Pipe creation is unfinished" << '\n'; } - return status; } -// Remove unconnected nodes from the mesh -void pipenetwork::Mesh::remove_unconnected_nodes() { - // Search for and record all unconnected nodes - std::vector unconnected_nodes; - for (const auto& node : nodes_) { - bool is_connected = false; - for (const auto& pipe : pipes_) { - if (pipe.second->nodes().at(0)->id() == node.second->id() || - pipe.second->nodes().at(1)->id() == node.second->id()) { - is_connected = true; - break; +void pipenetwork::Mesh::find_iso_links_() { + auto node2link_map = mesh_graph_->node2link_map(); + for (const auto& nid : iso_nodes_) { + if (node2link_map.find(nid) != node2link_map.end()) { + auto links = node2link_map.at(nid); + for (const auto& link : links) { + iso_links_.emplace_back(link); } } - if (!is_connected) unconnected_nodes.emplace_back(node.first); } - // Remove isolated nodes from list of nodal indices - for (const auto& unconnected_node : unconnected_nodes) - nodes_.erase(unconnected_node); -} - -// Initialize discharges in pipes -void pipenetwork::Mesh::initialize_pipe_discharge( - const std::vector>& init_discharge) { - for (auto& pipe : pipes_) pipe.second->initialize_discharge(); - for (const auto& discharge : init_discharge) - pipes_.at(discharge.first)->initialize_discharge(discharge.second); -} - -void pipenetwork::Mesh::initialize_pipe_discharge(double init_discharge) { - for (auto& pipe : pipes_) pipe.second->initialize_discharge(init_discharge); -} - -// Assign initial heads for nodes that have known head -void pipenetwork::Mesh::assign_node_head( - const std::vector>& node_head) { - for (const auto& head : node_head) nodes_.at(head.first)->head(head.second); -} - -// Assign initial elevation for nodes that have known head -void pipenetwork::Mesh::assign_node_elevation ( - const std::vector>& node_head) { - for (const auto& head : node_head) nodes_.at(head.first)->elevation(head.second); } - - - -// Assign initial discharges for nodes that have known discharge -void pipenetwork::Mesh::assign_node_demand( - const std::vector>& node_discharge) { - for (const auto& discharge : node_discharge) - nodes_.at(discharge.first)->demand (discharge.second); +void pipenetwork::Mesh::print_summary() { + std::cout << "Network Name: " << name_ << std::endl + << "number of pipes: " << mesh_links_->npipes() + << " ;number of pumps: " << mesh_links_->npumps() + << " ;number of valves: " << mesh_links_->nvalves() + << " ;number of junctions: " << mesh_nodes_->njunctions() + << " ;number of sources: " << mesh_nodes_->nreservoirs() + << " ;number of leaking junctions: " << leak_nids_.size() + << " ;number of isolated junctions: " << iso_nodes_.size() + << " ;number of isolated links: " << iso_links_.size() << std::endl; } diff --git a/src/mesh_components.cc b/src/mesh_components.cc new file mode 100644 index 0000000..d108bd6 --- /dev/null +++ b/src/mesh_components.cc @@ -0,0 +1,180 @@ +#include "mesh_components.h" + +pipenetwork::MeshNodes::MeshNodes( + const std::vector& junc_props, + const std::vector& res_props) { + + add_nodes(junc_props); + add_nodes(res_props); +} + +std::shared_ptr pipenetwork::MeshNodes::get_node( + const std::string& node_name) const { + try { + Index nid = name2nid_.at(node_name); + return nodes_.at(nid); + } catch (...) { + throw std::runtime_error("Node does not exist: " + node_name + "\n"); + } +} +template +void pipenetwork::MeshNodes::add_nodes(const std::vector& props) { + for (const auto& prop : props) { + Index nid = nid_manager_.create_index(); + name2nid_.emplace(prop.name, nid); + add_node(prop); + } +} + +void pipenetwork::MeshNodes::add_node( + const pipenetwork::JunctionProp& junc_prop) { + auto nid = nid_manager_.current_index(); + auto junc = std::make_shared(nid, junc_prop); + junctions_.emplace(nid, junc); + nodes_.emplace(nid, junc); +} + +void pipenetwork::MeshNodes::add_node( + const pipenetwork::ReservoirProp& res_prop) { + auto nid = nid_manager_.current_index(); + auto res = std::make_shared(nid, res_prop); + reservoirs_.emplace(nid, res); + nodes_.emplace(nid, res); +} + +// Meshlinks constructor +pipenetwork::MeshLinks::MeshLinks( + const std::vector& pipe_props, + const std::vector& pump_props, + const std::vector& valve_props, + const MeshNodes& mesh_nodes) { + + add_links(pipe_props, mesh_nodes); + add_links(pump_props, mesh_nodes); + add_links(valve_props, mesh_nodes); +} + +std::shared_ptr pipenetwork::MeshLinks::get_link( + const std::string& link_name) const { + { + try { + Index nid = name2lid_.at(link_name); + return links_.at(nid); + } catch (...) { + throw std::runtime_error("Link does not exist: " + link_name + "\n"); + } + } +} + +template +void pipenetwork::MeshLinks::add_links( + const std::vector& props, const pipenetwork::MeshNodes& mesh_nodes) { + for (const auto& prop : props) { + try { + auto node1 = mesh_nodes.get_node(prop.node1_name); + auto node2 = mesh_nodes.get_node(prop.node2_name); + auto lname = prop.name; + if (prop.status != LinkStatus::CLOSED) { + Index lid = lid_manager_.create_index(); + name2lid_[lname] = lid; + add_link(node1, node2, prop); + } + } catch (std::exception& e) { + std::cout << "Failed to create link: " << prop.name << "\n"; + std::cout << "Exception: " << e.what() << "\n"; + } + } +} + +void pipenetwork::MeshLinks::add_link( + const std::shared_ptr& node1, + const std::shared_ptr& node2, + const pipenetwork::PipeProp& pipe_prop) { + auto lid = lid_manager_.current_index(); + auto pipe = + std::make_shared(lid, *node1, *node2, pipe_prop); + pipes_.emplace(lid, pipe); + links_.emplace(lid, pipe); +} + +void pipenetwork::MeshLinks::add_link( + const std::shared_ptr& node1, + const std::shared_ptr& node2, + const pipenetwork::PumpProp& pump_prop) { + auto lid = lid_manager_.current_index(); + auto pump = + std::make_shared(lid, *node1, *node2, pump_prop); + pumps_.emplace(lid, pump); + links_.emplace(lid, pump); +} + +void pipenetwork::MeshLinks::add_link( + const std::shared_ptr& node1, + const std::shared_ptr& node2, + const pipenetwork::ValveProp& valve_prop) { + auto lid = lid_manager_.current_index(); + auto valve = + std::make_shared(lid, *node1, *node2, valve_prop); + valves_.emplace(lid, valve); + links_.emplace(lid, valve); +} + +void pipenetwork::MeshGraph::compute_graph_info_() { + std::vector> graph_triplet; + int connectivity_val = 1; + auto nnodes = mesh_nodes_->nnodes(); + for (const auto& index_link : mesh_links_->links()) { + auto lid = index_link.first; + auto link = index_link.second; + auto end_nodes = link->nodes(); + node2link_[end_nodes.first->id()].emplace_back(lid); + node2link_[end_nodes.second->id()].emplace_back(lid); + + graph_triplet.emplace_back(end_nodes.first->id(), end_nodes.second->id(), + connectivity_val); + graph_triplet.emplace_back(end_nodes.second->id(), end_nodes.first->id(), + connectivity_val); + } + A_.resize(nnodes, nnodes); + A_.setFromTriplets(graph_triplet.begin(), graph_triplet.end()); + + compute_node_degrees_(); +} + +void pipenetwork::MeshGraph::compute_node_degrees_() { + Index nnodes = mesh_nodes_->nnodes(); + ndegree_.resize(nnodes); + for (int i = 0; i < nnodes; ++i) { + ndegree_[i] = A_.outerIndexPtr()[i + 1] - A_.outerIndexPtr()[i]; + } +} + +Eigen::VectorXd pipenetwork::MeshGraph::bfs(pipenetwork::Index nid) { + Index nnodes = mesh_nodes_->nnodes(); + Eigen::VectorXd check_result(nnodes); + check_result.setZero(nnodes); + + std::set nodes_to_explore; + nodes_to_explore.emplace(nid); + check_result[nid] = 1; + auto indptr = A_.outerIndexPtr(); + auto indices = A_.innerIndexPtr(); + auto data = A_.valuePtr(); + + while (!nodes_to_explore.empty()) { + auto node_being_explored = *nodes_to_explore.begin(); + nodes_to_explore.erase(nodes_to_explore.begin()); + + int nconnections = ndegree_[node_being_explored]; + int ndx = indptr[node_being_explored]; + // for all the connected nodes, set result to 1 and place them into the + // searching queue + for (int i = 0; i < nconnections; ++i) { + if (data[ndx + i] != 0 && check_result[indices[ndx + i]] == 0) { + check_result[indices[ndx + i]] = 1; + nodes_to_explore.emplace(indices[ndx + i]); + } + } + } + return check_result; +} \ No newline at end of file diff --git a/src/mkl_unsym.cc b/src/mkl_unsym.cc new file mode 100644 index 0000000..406c6a7 --- /dev/null +++ b/src/mkl_unsym.cc @@ -0,0 +1,144 @@ +#include "mkl_unsym.h" +#include "factory.h" + +static Register + registry("mkl_pardiso"); + +pipenetwork::linear_system::Mkl_unsym::Mkl_unsym() : Solver() { + // configure pardiso + /* Auxiliary variables. */ + char* var; + /* -------------------------------------------------------------------- */ + /* .. Setup Pardiso control parameters and initialize the solvers */ + /* internal adress pointers. This is only necessary for the FIRST */ + /* call of the PARDISO solver. */ + /* ---------------------------------------------------------------------*/ + error_ = 0; + pardisoinit(pt_, &mtype_, iparm_); + + /* Numbers of processors, value of OMP_NUM_THREADS */ + var = getenv("OMP_NUM_THREADS"); + if (var != NULL) + sscanf(var, "%d", &num_procs_); + else { + num_procs_ = 2; + } + /* -------------------------------------------------------------------- */ + /* .. Setup Pardiso control parameters. */ + /* -------------------------------------------------------------------- */ + for (int i = 0; i < 64; i++) { + iparm_[i] = 0; + } + iparm_[0] = 1; /* No solver default */ + iparm_[1] = 3; /* Fill-in reordering from METIS */ + /* Numbers of processors, value of OMP_NUM_THREADS */ + iparm_[2] = num_procs_; + iparm_[3] = 0; /* No iterative-direct algorithm */ + iparm_[4] = 0; /* No user fill-in reducing permutation */ + iparm_[5] = 0; /* Write solution into x */ + iparm_[6] = 0; /* Not in use */ + iparm_[7] = 2; /* Max numbers of iterative refinement steps */ + iparm_[8] = 0; /* Not in use */ + iparm_[9] = 6; /* Perturb the pivot elements with 1E-6 */ + iparm_[10] = 1; /* Use nonsymmetric permutation and scaling MPS */ + iparm_[11] = 0; /* Not in use */ + iparm_[12] = 0; /* Not in use */ + iparm_[13] = 0; /* Output: Number of perturbed pivots */ + iparm_[14] = 0; /* Not in use */ + iparm_[15] = 0; /* Not in use */ + iparm_[16] = 0; /* Not in use */ + iparm_[17] = -1; /* Output: Number of nonzeros in the factor LU */ + iparm_[18] = -1; /* Output: Mflops for LU factorization */ + iparm_[19] = 0; /* Output: Numbers of CG Iterations */ + maxfct_ = 1; /* Maximum number of numerical factorizations. */ + mnum_ = 1; /* Which factorization to use. */ + msglvl_ = 0; /* Print statistical information in file */ + error_ = 0; /* Initialize error flag */ +} + +Eigen::VectorXd pipenetwork::linear_system::Mkl_unsym::solve() { + // configure matrix + int n = matrix_assembler_->residual_vector().size(); + double* vec_b = + const_cast(matrix_assembler_->residual_vector().data()); + double x_diff[n]; + int nnz = ia_[n]; + + /* -------------------------------------------------------------------- */ + /* .. Convert matrix from 0-based C-notation to Fortran 1-based */ + /* notation. */ + /* -------------------------------------------------------------------- */ + for (int i = 0; i < n + 1; i++) { + ia_[i] += 1; + } + for (int i = 0; i < nnz; i++) { + ja_[i] += 1; + } + + /* -------------------------------------------------------------------- */ + /* .. Reordering and Symbolic Factorization. This step also allocates */ + /* all memory that is necessary for the factorization. */ + /* -------------------------------------------------------------------- */ + phase_ = 11; + + pardiso(pt_, &maxfct_, &mnum_, &mtype_, &phase_, &n, a_, ia_, ja_, &idum_, + &nrhs_, iparm_, &msglvl_, &ddum_, &ddum_, &error_); + + if (error_ != 0) { + printf("\nERROR during symbolic factorization: %d", error_); + exit(1); + } + + /* -------------------------------------------------------------------- */ + /* .. Numerical factorization. */ + /* -------------------------------------------------------------------- */ + phase_ = 22; + + pardiso(pt_, &maxfct_, &mnum_, &mtype_, &phase_, &n, a_, ia_, ja_, &idum_, + &nrhs_, iparm_, &msglvl_, &ddum_, &ddum_, &error_); + + if (error_ != 0) { + printf("\nERROR during numerical factorization: %d", error_); + exit(2); + } + + /* -------------------------------------------------------------------- */ + /* .. Back substitution and iterative refinement. */ + /* -------------------------------------------------------------------- */ + phase_ = 33; + + pardiso(pt_, &maxfct_, &mnum_, &mtype_, &phase_, &n, a_, ia_, ja_, &idum_, + &nrhs_, iparm_, &msglvl_, vec_b, x_diff, &error_); + + if (error_ != 0) { + printf("\nERROR during solution: %d", error_); + exit(3); + } + + /* -------------------------------------------------------------------- */ + /* .. Convert matrix back to 0-based C-notation. */ + /* -------------------------------------------------------------------- */ + for (int i = 0; i < n + 1; i++) { + ia_[i] -= 1; + } + for (int i = 0; i < nnz; i++) { + ja_[i] -= 1; + } + + /* -------------------------------------------------------------------- */ + /* .. Termination and release of memory. */ + /* -------------------------------------------------------------------- */ + phase_ = -1; /* Release internal memory. */ + + pardiso(pt_, &maxfct_, &mnum_, &mtype_, &phase_, &n, &ddum_, ia_, ja_, &idum_, + &nrhs_, iparm_, &msglvl_, &ddum_, &ddum_, &error_); + + // return x_diff + Eigen::VectorXd x_diff_vec(n); + for (int i = 0; i < n; i++) { + x_diff_vec[i] = x_diff[i]; + } + + return x_diff_vec; +} \ No newline at end of file diff --git a/src/node.cc b/src/node.cc deleted file mode 100644 index 95238dc..0000000 --- a/src/node.cc +++ /dev/null @@ -1,51 +0,0 @@ -#include "node.h" - -// compute polynomial coefficients for polynomial approximation of a function in -// a given interval a : third order,x^3, coefficient b : second_order,x^2, -// coefficient c : first order,x, coefficient d: zero order, C, coefficient. -Eigen::VectorXd pipenetwork::Node::compute_poly_coefficients( - const std::array& x, const std::array& f, - const std::array& df) { - Eigen::VectorXd ret(4); - double a = - (2 * (f[0] - f[1]) - (x[0] - x[1]) * (df[1] + df[0])) / - (std::pow(x[1], 3) - std::pow(x[0], 3) + 3 * x[0] * x[1] * (x[0] - x[1])); - double b = - (df[0] - df[1] + 3 * ((std::pow(x[1], 2) - std::pow(x[0], 2)) * a)) / - (2 * (x[0] - x[1])); - double c = df[1] - 3 * std::pow(x[1], 2) * a - 2 * x[1] * b; - double d = f[1] - std::pow(x[1], 3) * a - std::pow(x[1], 2) * b - x[1] * c; - ret << a, b, c, d; - return ret; -} - -Eigen::VectorXd pipenetwork::Node::get_pdd_poly_coef_1() { - double x1 = minimum_pressure_; - double f1 = 0; - double x2 = minimum_pressure_ + pdd_smoothing_delta_; - double f2 = std::pow( - (x2 - minimum_pressure_) / (normal_pressure_ - minimum_pressure_), 0.5); - double df1 = pdd_slope_; - double df2 = 0.5 * - std::pow((x2 - minimum_pressure_) / - (normal_pressure_ - minimum_pressure_), - -0.5) * - (1 / (normal_pressure_ - minimum_pressure_)); - - return compute_poly_coefficients({x1, x2}, {f1, f2}, {df1, df2}); -} - -Eigen::VectorXd pipenetwork::Node::get_pdd_poly_coef_2() { - double x1 = normal_pressure_ - pdd_smoothing_delta_; - double f1 = std::pow( - (x1 - minimum_pressure_) / (normal_pressure_ - minimum_pressure_), 0.5); - double x2 = normal_pressure_; - double f2 = 1; - double df1 = 0.5 * - std::pow((x1 - minimum_pressure_) / - (normal_pressure_ - minimum_pressure_), - -0.5) * - (1 / (normal_pressure_ - minimum_pressure_)); - double df2 = pdd_slope_; - return compute_poly_coefficients({x1, x2}, {f1, f2}, {df1, df2}); -} diff --git a/src/pipe.cc b/src/pipe.cc deleted file mode 100644 index 8227066..0000000 --- a/src/pipe.cc +++ /dev/null @@ -1,86 +0,0 @@ -#include "pipe.h" - -// Constructor with id, node pointers, diameter, status and max allowable -// velocity -pipenetwork::Pipe::Pipe( - unsigned id, const std::array, 2>& nodes, - double diameter, double roughness, bool status, double max_velocity) - : id_{id}, - nodes_{nodes}, - radius_{diameter / 2.}, - pipe_roughness_{roughness}, - isopen_{status}, - max_velocity_{max_velocity} { - length_ = (nodes_.at(0)->coordinates() - nodes_.at(1)->coordinates()).norm(); -} - -// Calculate discharge using Darcy-Weisbach equation -// $discharge = (\frac{dhead \times \pi^2 \times g \times (2radius)^5}{8 \times -// length \times darcy_friction})^0.5$ -// SI unit meter and second are used in the whole equation -void pipenetwork::Pipe::compute_discharge_darcy_weisbach() { - const double dhead = nodes_.at(0)->head() - nodes_.at(1)->head(); - discharge_ = sqrt(std::abs(dhead) * pow(M_PI, 2) * pipenetwork::Gravity(2) * - pow(2 * radius_, 5) / (8. * length_ * darcy_friction_)); - // defined flow direction from nodes_.at(0) to nodes.at(1) as positive - if (dhead < 0) discharge_ *= -1.; -} - -// Calculate discharge using Hazen-Williams equation -// discharge = (\frac{dhead \times pipe_roughness^1.852 \times -// (2radius)^4.8704}{10.67 \times length})^(\frac{1}{1.852}) -// SI unit meter and second are used in the whole equation -void pipenetwork::Pipe::compute_discharge_hazen_williams() { - const double dhead = nodes_.at(0)->head() - nodes_.at(1)->head(); - discharge_ = pow((std::abs(dhead) * pow(pipe_roughness_, 1.852) * - pow(2 * radius_, 4.8704) / (10.67 * length_)), - 1 / 1.852); - // defined flow direction from nodes_.at(0) to nodes.at(1) as positive - if (dhead < 0) discharge_ *= -1.; -} - -// Calculate and return derivative of Hazen-Williams equation with respect to -// pipe discharge Headloss equation (Hazen-Williams): Residual = -// (Start_node_head - end_node_head) - \frac{10.67 \times length \times -// pipe_discharge^1.852}{pipe_roughness^1.852 \times -// (2radius)^4.8704} -// Take derivative with respect to pipe_discharge: -// \frac{-1.852 \times 10.67 \times length}{pow(pipe_roughness,1.852) -// \times pow(2radius,4.8704)} \times pow(pipe_discharge,0.852). -// SI unit meter and second are used in the whole equation -double pipenetwork::Pipe::deriv_hazen_williams_discharge() { - double coeff = 10.67 * length_ / - (pow(pipe_roughness_, 1.852) * pow(2 * radius_, 4.8704)); - double deriv = -1.852 * coeff * pow(std::abs(iter_discharge_), 0.852); - if (iter_discharge_ < 0) deriv *= -1.; - return deriv; -} - -// Calculate head loss over the pipe using Darcy-Weisbach equation: -// dhead = \frac{8 \times length \times darcy_factor \times discharge^2}{\pi^2 -// \times g \times (2radius)^5} -// SI unit meter and second are used in the whole equation -void pipenetwork::Pipe::compute_headloss_darcy_weisbach() { - headloss_ = 8. * length_ * darcy_friction_ * pow(iter_discharge_, 2) / - (pow(M_PI, 2) * pipenetwork::Gravity(2) * pow(2 * radius_, 5)); - if (iter_discharge_ < 0) headloss_ *= -1.; -} - -// Calculate headloss over the pipe using Hazen-Williams equation: -// dhead = \frac{10.67 \times length \times -// discharge^1.852}{pipe_roughness^1.852 \times (2radius)^4.8704} -// SI unit meter and second are used in the whole equation -void pipenetwork::Pipe::compute_headloss_hazen_williams() { - headloss_ = (10.67 * length_ * pow(std::abs(iter_discharge_), 1.852)) / - (pow(pipe_roughness_, 1.852) * pow(2 * radius_, 4.8704)); - if (iter_discharge_ < 0) headloss_ *= -1.; -} - -// Return an array of pointers point to the nodes at pipe end -const std::array, 2> - pipenetwork::Pipe::nodes() { - std::array, 2> nodes; - nodes.at(0) = nodes_.at(0); - nodes.at(1) = nodes_.at(1); - return nodes; -} diff --git a/src/valve_graph.cc b/src/valve_graph.cc new file mode 100644 index 0000000..38b2e72 --- /dev/null +++ b/src/valve_graph.cc @@ -0,0 +1,107 @@ + +#include "valve_graph.h" + +pipenetwork::ValveGraph::ValveGraph( + const std::shared_ptr& mesh_nodes, + const std::shared_ptr& mesh_links, + const std::vector& iso_valve_props) + : MeshGraph(mesh_nodes, mesh_links), iso_valves_(iso_valve_props) { + construct_node_pipe_mtx(); + construct_valve_loc_mtx(); + construct_valve_def_mtx(); + initialize_iso_segs(); +} + +void pipenetwork::ValveGraph::construct_node_pipe_mtx() { + std::vector> graph_triplet; + int connectivity_val = 1; + + for (const auto& index_link : mesh_links_->links()) { + auto lid = index_link.first; + auto link = index_link.second; + auto end_nodes = link->nodes(); + graph_triplet.emplace_back(end_nodes.first->id(), lid, connectivity_val); + graph_triplet.emplace_back(end_nodes.second->id(), lid, connectivity_val); + } + auto nnodes = mesh_nodes_->nnodes(); + auto nlinks = mesh_links_->nlinks(); + node_pipe_mtx_.resize(nnodes, nlinks); + node_pipe_mtx_.setFromTriplets(graph_triplet.begin(), graph_triplet.end()); +} + +void pipenetwork::ValveGraph::construct_valve_loc_mtx() { + auto iso_valve_props = iso_valves_.iso_valves(); + std::vector> graph_triplet; + int on_val = 1; + for (const auto& vid_vprop : iso_valve_props) { + auto vid = vid_vprop.first; + auto vprop = vid_vprop.second; + auto on_node = mesh_nodes_->get_node(vprop.on_node); + auto on_link = mesh_links_->get_link(vprop.on_pipe); + graph_triplet.emplace_back(on_node->id(), on_link->id(), on_val); + + iso_valves_.loc2vid( + std::make_pair(on_node->id(), on_link->id()), vid); + mtx_helper.valve_loc_row2col[on_node->id()].emplace_back(on_link->id()); + mtx_helper.valve_loc_col2row[on_link->id()].emplace_back(on_node->id()); + } + auto nnodes = mesh_nodes_->nnodes(); + auto nlinks = mesh_links_->nlinks(); + valve_loc_mtx_.resize(nnodes, nlinks); + valve_loc_mtx_.setFromTriplets(graph_triplet.begin(), graph_triplet.end()); +} + +void pipenetwork::ValveGraph::construct_valve_def_mtx() { + valve_def_mtx_ = node_pipe_mtx_ - valve_loc_mtx_; + construct_vdef_idx_table(); +} + +void pipenetwork::ValveGraph::construct_vdef_idx_table() { + valve_def_mtx_.makeCompressed(); + for (int k = 0; k < valve_def_mtx_.outerSize(); ++k) + for (Eigen::SparseMatrix::InnerIterator it(valve_def_mtx_, k); it; + ++it) { + auto row = it.row(); // row index + auto col = it.col(); // col index (here it is equal to k) + auto val = it.value(); + if (val != 0) { + mtx_helper.valve_def_row2col[row].emplace_back(col); + mtx_helper.valve_def_col2row[col].emplace_back(row); + } + } +} + +void pipenetwork::ValveGraph::initialize_iso_segs() { + std::set unexplored_pids; + for (const auto& index_link : mesh_links_->links()) { + auto lid = index_link.first; + unexplored_pids.insert(lid); + } + iso_segments_ = isolation::IsoSegments(); // reinitialize for clear state + iso_segments_.construct_iso_segs(mtx_helper, iso_valves_, unexplored_pids); +} + +pipenetwork::isolation::IsoSeg pipenetwork::ValveGraph::pname2segment( + const std::string& p_name) { + auto pid = lname2id(p_name); + return iso_segments_.pid2seg(pid); +} + +std::vector> + pipenetwork::ValveGraph::segment_components( + const std::vector& pipe2iso) { + std::set sids; + for (auto pname : pipe2iso) { + auto seg = pname2segment(pname); + sids.insert(seg.sid); + } + return iso_segments_.get_segment_components(sids); +} + +void pipenetwork::ValveGraph::fail_valves( + const std::vector& broken_valves) { + for (auto& vname : broken_valves) { + auto vid = iso_valves_.vname2vid(vname); + iso_segments_.merge_segments(vid); + } +} diff --git a/src/valve_graph_components.cc b/src/valve_graph_components.cc new file mode 100644 index 0000000..43169d5 --- /dev/null +++ b/src/valve_graph_components.cc @@ -0,0 +1,362 @@ +#include "valve_graph_components.h" + +pipenetwork::isolation::IsoValves::IsoValves( + const std::vector& iso_valve_props) { + for (const auto& vprop : iso_valve_props) { + Index vid = vid_manager_.create_index(); + iso_valves_[vid] = vprop; + vname2vid_[vprop.name] = vid; + } +} + +const pipenetwork::isolation::IsoSeg + pipenetwork::isolation::IsoSegments::pid2seg(pipenetwork::Index pid) { + auto sid = pid2sid_[pid]; + return iso_segments_[sid]; +} + +void pipenetwork::isolation::IsoSegments::construct_iso_segs( + const pipenetwork::isolation::IsoMtxHelper& mtx_helper, + pipenetwork::isolation::IsoValves& iso_valves, std::set& pids) { + while (!pids.empty()) { + auto searching_pid = *pids.begin(); + auto sid = sid_manager_.create_index(); + auto seg = get_single_seg(mtx_helper, searching_pid); + seg.vids = get_seg_valves(mtx_helper, iso_valves, seg.pids, + seg.nids); // update vids + for (auto isolated_pid : seg.pids) { + pids.erase(isolated_pid); + iso_segments_[sid] = seg; + } + } + construct_seg_valve_mtx(iso_valves); + construct_seg_valve_adj_mtx(); + update_pid2sid(); +} + +pipenetwork::isolation::IsoSeg + pipenetwork::isolation::IsoSegments::get_single_seg( + const pipenetwork::isolation::IsoMtxHelper& mtx_helper, + pipenetwork::Index pid) { + isolation::IsoSeg seg; + seg.sid = sid_manager_.current_index(); + + bool iso = mtx_helper.valve_def_col2row.find(pid) == + mtx_helper.valve_def_col2row.end(); + if (iso) { + seg.pids.insert(pid); + return seg; + } + std::set pids{pid}; + while (!pids.empty()) { + // col search (find isolated nodes) + auto searching_pid = *pids.begin(); + pids.erase(pids.begin()); + seg.pids.insert(searching_pid); + // adding new nids + auto new_nids = mtx_helper.valve_def_col2row.at(pid); + // row search (find new isolated pipes) + while (!new_nids.empty()) { + auto searching_nid = new_nids.back(); + new_nids.pop_back(); + seg.nids.insert(searching_nid); + // adding new pids + auto new_pids = mtx_helper.valve_def_row2col.at(searching_nid); + for (auto new_pid : new_pids) { + bool psearched = std::find(seg.pids.begin(), seg.pids.end(), new_pid) != + seg.pids.end(); + if (!psearched) { + pids.insert(new_pid); + } + } + } + } + return seg; +} + +std::set + pipenetwork::isolation::IsoSegments::get_seg_valves( + const pipenetwork::isolation::IsoMtxHelper& mtx_helper, + const pipenetwork::isolation::IsoValves& iso_valves, + const std::set& pids, const std::set& nids) { + std::set vids; + // pick by pipes + for (auto pid : pids) { + if (mtx_helper.valve_loc_col2row.find(pid) != + mtx_helper.valve_loc_col2row.end()) { // pipe may have no valve + auto nids = mtx_helper.valve_loc_col2row.at(pid); + for (auto nid : nids) { + auto vloc = std::make_pair(nid, pid); + auto vid = iso_valves.loc2vid(vloc); + vids.insert(vid); + } + } + } + // pick by nodes + for (Index nid : nids) { + if (mtx_helper.valve_loc_row2col.find(nid) != + mtx_helper.valve_loc_row2col.end()) { // node may have no valve + auto pids = mtx_helper.valve_loc_row2col.at(nid); + for (Index pid : pids) { + auto vloc = std::make_pair(nid, pid); + auto vid = iso_valves.loc2vid(vloc); + vids.insert(vid); + } + } + } + return vids; +} + +void pipenetwork::isolation::IsoSegments::construct_seg_valve_mtx( + pipenetwork::isolation::IsoValves& iso_valves) { + auto valves = iso_valves.iso_valves(); + std::vector> graph_triplet; + int on_val = 1; + for (const auto& sid_seg : iso_segments_) { + auto sid = sid_seg.first; + auto seg = sid_seg.second; + for (const auto& vid : seg.vids) { + graph_triplet.emplace_back(sid, vid, on_val); + } + } + seg_valve_mtx_.resize(iso_segments_.size(), iso_valves.nvalves()); + seg_valve_mtx_.setFromTriplets(graph_triplet.begin(), graph_triplet.end()); +} + +void pipenetwork::isolation::IsoSegments::construct_seg_valve_adj_mtx() { + std::vector> graph_triplet; + auto ncols = seg_valve_mtx_.cols(); + for (int k = 0; k < ncols; ++k) { + if (std::find(removed_vids_.begin(), removed_vids_.end(), k) == + removed_vids_.end()) { + Eigen::VectorXd v_seg = seg_valve_mtx_.col(k); + std::vector connected_segs; + if (v_seg.sum() == 2) { + for (Eigen::Index i = 0; i < v_seg.size(); ++i) { + if (v_seg[i]) connected_segs.push_back(i); + } + graph_triplet.emplace_back(connected_segs[0], connected_segs[1], 1); + graph_triplet.emplace_back(connected_segs[1], connected_segs[0], 1); + } + } + } + + seg_valve_adj_mtx_.resize(iso_segments_.size(), iso_segments_.size()); + seg_valve_adj_mtx_.setFromTriplets(graph_triplet.begin(), + graph_triplet.end()); +} + +void pipenetwork::isolation::IsoSegments::merge_segments(Index broken_vid) { + std::vector sids_to_remove; + auto sids = find_merging_sids(broken_vid); + if (sids.size() == 2) { + // one valve can only connect two segments + auto sid_from = sids[1]; + auto sid_to = sids[0]; + merge_two_segment(sid_from, sid_to, broken_vid); + sids_to_remove.emplace_back(sid_from); + } + update_seg_valve_mtx(sids_to_remove); + reindex(); // reindex for consistency (one segment is removed) + update_pid2sid(); +} + +std::vector + pipenetwork::isolation::IsoSegments::find_merging_sids(Index broken_vid) { + Eigen::VectorXd v_seg = seg_valve_mtx_.col(broken_vid); + std::vector segs_to_merge; + for (Eigen::Index i = 0; i < v_seg.size(); ++i) { + if (v_seg[i]) segs_to_merge.push_back(i); + } + return segs_to_merge; +} + +void pipenetwork::isolation::IsoSegments::merge_two_segment( + pipenetwork::Index sid_from, pipenetwork::Index sid_to, + pipenetwork::Index vid) { + auto& seg_from = iso_segments_[sid_from]; + auto& seg_to = iso_segments_[sid_to]; + + seg_to.vids.insert(seg_from.vids.begin(), seg_from.vids.end()); + seg_to.pids.insert(seg_from.pids.begin(), seg_from.pids.end()); + seg_to.nids.insert(seg_from.nids.begin(), seg_from.nids.end()); + for (int j = 0; j < seg_valve_mtx_.cols(); j++) { + seg_valve_mtx_.coeffRef(sid_to, j) += seg_valve_mtx_.coeffRef(sid_from, j); + } + + // update states + seg_to.vids.erase(vid); // remove the broken valve + removed_vids_.emplace_back(vid); + iso_segments_.erase(sid_from); +} + +void pipenetwork::isolation::IsoSegments::update_seg_valve_mtx( + const std::vector& sids_remove) { + + auto updated_seg_valve = pipenetwork::isolation::IsoSegHelper::shrink_mtx( + seg_valve_mtx_, sids_remove, {}); + seg_valve_mtx_ = updated_seg_valve; + // std::cout << "Seg Valve mtx after!" << std::endl; + // std::cout << seg_valve_mtx_ << std::endl; + construct_seg_valve_adj_mtx(); +} + +std::vector> + pipenetwork::isolation::IsoSegments::get_segment_components( + const std::set& segs2iso) { + + // isolate segments by setting corresponding connections to 0 + auto n = seg_valve_adj_mtx_.cols(); + for (int i = 0; i < n; i++) { + for (auto sid : segs2iso) { + seg_valve_adj_mtx_.coeffRef(sid, i) = 0; + seg_valve_adj_mtx_.coeffRef(i, sid) = 0; + } + } + + // construct graph laplacian + Eigen::SparseMatrix L = + isolation::IsoSegHelper::create_graph_laplacian(seg_valve_adj_mtx_); + // solve for eigen information + Eigen::VectorXd eigen_vals; + Eigen::MatrixXd eigen_vecs; + auto eigensolver = + pipenetwork::isolation::IsoSegHelper::small_matrix_eigen_info(L); + eigen_vals = eigensolver.eigenvalues(); + eigen_vecs = eigensolver.eigenvectors(); + + return einfo2components(eigen_vals, eigen_vecs); +} + +std::vector> + pipenetwork::isolation::IsoSegments::einfo2components( + const Eigen::VectorXd& eigen_vals, const Eigen::MatrixXd& eigen_vecs) { + auto valid_eids = isolation::IsoSegHelper::find_zero_eval_loc(eigen_vals); + std::vector> components; + for (auto valid_eid : valid_eids) { + Eigen::VectorXd evec = eigen_vecs.col(valid_eid); + std::vector component; + + auto sids = isolation::IsoSegHelper::find_non_zero_evac_loc(evec); + for (auto sid : sids) { + component.emplace_back(iso_segments_[sid]); + } + components.emplace_back(component); + } + return components; +} + +void pipenetwork::isolation::IsoSegments::reindex() { + sid_manager_ = IndexManager(); + tsl::ordered_map reindexed_segments; + for (auto& sid_seg : iso_segments_) { + auto seg = sid_seg.second; + auto new_sid = sid_manager_.create_index(); + seg.sid = new_sid; + reindexed_segments[new_sid] = seg; + } + iso_segments_ = reindexed_segments; +} + +void pipenetwork::isolation::IsoSegments::update_pid2sid() { + for (auto& sid_seg : iso_segments_) { + auto seg = sid_seg.second; + for (auto pid : seg.pids) { + pid2sid_[pid] = seg.sid; + } + } +} + +Eigen::SparseMatrix pipenetwork::isolation::IsoSegHelper::shrink_mtx( + Eigen::SparseMatrix& matrix, + const std::vector& rowsToRemove, + const std::vector& colsToRemove) { + + Eigen::SparseMatrix shrinked_mtx; + shrinked_mtx.resize(matrix.rows() - rowsToRemove.size(), + matrix.cols() - colsToRemove.size()); + + std::map row_idx_map; + for (int i = 0; i < matrix.innerSize(); ++i) { + int decrement = 0; + for (auto row2r : rowsToRemove) { + if (i > row2r) { + decrement -= 1; + } + } + auto new_row_idx = i + decrement; + row_idx_map[i] = new_row_idx; + } + + Index col_new = 0; + for (int k = 0; k < matrix.outerSize(); ++k) { + if (std::find(colsToRemove.begin(), colsToRemove.end(), k) == + colsToRemove.end()) { + for (Eigen::SparseMatrix::InnerIterator it(matrix, k); it; ++it) { + auto row_old = it.row(); // row index + auto val = it.value(); + if (std::find(rowsToRemove.begin(), rowsToRemove.end(), row_old) == + rowsToRemove.end() && + val != 0) { + auto row_new = row_idx_map[row_old]; + shrinked_mtx.insert(row_new, col_new) = 1; + } + } + col_new += 1; + } + } + return shrinked_mtx; +} + +Eigen::SelfAdjointEigenSolver + pipenetwork::isolation::IsoSegHelper::small_matrix_eigen_info( + Eigen::SparseMatrix& matrix) { + + auto dense_L = Eigen::MatrixXd(matrix); + Eigen::SelfAdjointEigenSolver eigensolver(dense_L); + if (eigensolver.info() != Eigen::Success) abort(); + return eigensolver; +} + +Eigen::SparseMatrix + pipenetwork::isolation::IsoSegHelper::create_graph_laplacian( + const Eigen::SparseMatrix& adj_mtx) { + std::vector> graph_triplet; + for (int i = 0; i < adj_mtx.innerSize(); i++) { + auto ki = adj_mtx.row(i).sum(); + graph_triplet.emplace_back(i, i, ki); + } + Eigen::SparseMatrix D; + D.resize(adj_mtx.outerSize(), adj_mtx.outerSize()); + D.setFromTriplets(graph_triplet.begin(), graph_triplet.end()); + + Eigen::SparseMatrix L = D - adj_mtx; + return L; +} + +std::vector + pipenetwork::isolation::IsoSegHelper::find_zero_eval_loc( + const Eigen::VectorXd& evals) { + std::vector valid_eids; + for (int i = 0; i < evals.size(); i++) { + auto val = evals[i]; + if (std::abs(val) < NON_ZERO_THRE) { + valid_eids.emplace_back(i); + } + } + return valid_eids; +} + +std::vector + pipenetwork::isolation::IsoSegHelper::find_non_zero_evac_loc( + const Eigen::VectorXd& evec) { + + std::vector non_zero_ids; + for (int i = 0; i < evec.size(); i++) { + auto val = evec[i]; + if (std::abs(val) > NON_ZERO_THRE) { + non_zero_ids.emplace_back(i); + } + } + return non_zero_ids; +} diff --git a/test_files/test_net.inp b/test_files/test_net.inp new file mode 100755 index 0000000..b894dfb --- /dev/null +++ b/test_files/test_net.inp @@ -0,0 +1,169 @@ +[TITLE] + EPANET Example Network 1 +A simple example of modeling chlorine decay. Both bulk and +wall reactions are included. + +[JUNCTIONS] +;ID Elev Demand Pattern + 10 710 0 ; + 11 710 150 ; + 12 700 150 ; + 13 695 100 ; + 21 700 150 ; + 22 695 200 ; + 23 690 150 ; + 31 700 100 ; + 32 710 100 ; + +[RESERVOIRS] +;ID Head Pattern + 41 800 ; + 42 900 ; + +[TANKS] +;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve + + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status + 100 10 11 10530 18 100 0 Open ; + 102 12 13 5280 10 100 0 Open ; + 105 31 32 5280 6 100 0 Open ; + 111 11 21 5280 10 100 0 Open ; + 112 12 22 5280 12 100 0 Open ; + 113 13 23 5280 8 100 0 Open ; + 121 21 31 5280 8 100 0 Open ; + 122 22 32 5280 6 100 0 Open ; + + +[PUMPS] +;ID Node1 Node2 Parameters + 123 41 10 HEAD 2 ; + 124 42 12 POWER 50 ; + + +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss +125 11 12 5280 PRV 40 0 ; +126 21 22 1000 TCV 50 0 ; + 127 22 23 5280 FCV 1 0 ; +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers +;Demand Pattern + + +[CURVES] +;ID X-Value Y-Value + 1 1500 250 + 2 0 104. + 2 2000. 92. + 2 4000. 63. + + +[CONTROLS] + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 1:00 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + 10 20.00 70.00 + 11 30.00 70.00 + 12 50.00 70.00 + 13 70.00 70.00 + 21 30.00 40.00 + 22 50.00 40.00 + 23 70.00 40.00 + 31 30.00 10.00 + 32 50.00 10.00 + 41 10.00 70.00 + 42 50.00 90.00 + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + 6.99 73.63 "Source" + 13.48 68.13 "Pump" + 43.85 91.21 "Tank" + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/test_files/test_net_broken.inp b/test_files/test_net_broken.inp new file mode 100755 index 0000000..da6cace --- /dev/null +++ b/test_files/test_net_broken.inp @@ -0,0 +1,172 @@ +[TITLE] + EPANET Example Network 1 +A simple example of modeling chlorine decay. Both bulk and +wall reactions are included. + +[JUNCTIONS] +;ID Elev Demand Pattern + 10 710 0 ; + 11 710 150 ; + 12 700 150 ; + 13 695 100 ; + 21 700 150 ; + 22 695 200 ; + 23 690 150 ; + 31 700 100 ; + 32 710 100 ; + 33 705 100 ; + +[RESERVOIRS] +;ID Head Pattern + 41 800 ; + 42 900 ; + +[TANKS] +;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve + + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status + 100 10 11 10530 18 100 0 Open ; + 102 12 13 5280 10 100 0 Open ; + 105 31 32 5280 6 100 0 Open ; + 111 11 21 5280 10 100 0 Open ; + 112 12 22 5280 12 100 0 Open ; + 113 13 23 5280 8 100 0 Open ; + 121 21 31 5280 8 100 0 Open ; + 122 22 32 5280 6 100 0 Open ; + 123 32 33 5280 6 100 0 Closed ; + + +[PUMPS] +;ID Node1 Node2 Parameters + 124 41 10 HEAD 1 ; + 125 42 12 POWER 50 ; + + +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss +126 11 12 5280 PRV 40 0 ; +127 21 22 1000 TCV 50 0 ; + 128 22 23 5280 FCV 1 0 ; +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers +;Demand Pattern + + +[CURVES] +;ID X-Value Y-Value + 1 1500 250 + 2 0 104. + 2 2000. 92. + 2 4000. 63. + + +[CONTROLS] + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 1:00 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + 10 20.00 70.00 + 11 30.00 70.00 + 12 50.00 70.00 + 13 70.00 70.00 + 21 30.00 40.00 + 22 50.00 40.00 + 23 70.00 40.00 + 31 30.00 10.00 + 32 50.00 10.00 + 33 70.00 10.00 + 41 10.00 70.00 + 42 50.00 90.00 + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + 6.99 73.63 "Source" + 13.48 68.13 "Pump" + 43.85 91.21 "Tank" + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/test_files/test_net_pdd.inp b/test_files/test_net_pdd.inp new file mode 100755 index 0000000..e8348b4 --- /dev/null +++ b/test_files/test_net_pdd.inp @@ -0,0 +1,166 @@ +[TITLE] + EPANET Example Network 1 +A simple example of modeling chlorine decay. Both bulk and +wall reactions are included. + +[JUNCTIONS] +;ID Elev Demand Pattern + 10 710 0 ; + 11 710 150 ; + 12 700 150 ; + 13 695 100 ; + 21 700 150 ; + 22 695 200 ; + 23 690 150 ; + 31 700 100 ; + 32 710 100 ; + +[RESERVOIRS] +;ID Head Pattern + 41 600 ; + 42 800 ; + +[TANKS] +;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve + + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status + 100 10 11 10530 18 100 0 Open ; + 102 12 13 5280 10 100 0 Open ; + 105 31 32 5280 6 100 0 Open ; + 110 42 12 200 18 100 0 Open ; + 111 11 21 5280 10 100 0 Open ; + 112 12 22 5280 12 100 0 Open ; + 113 13 23 5280 8 100 0 Open ; + 121 21 31 5280 8 100 0 Open ; + 122 22 32 5280 6 100 0 Open ; + 123 41 10 5280 6 100 0 Open ; +124 11 12 5280 6 100 0 Open ; +125 21 22 5280 6 100 0 Open ; + 126 22 23 5280 6 100 0 Open ; + + +[PUMPS] +;ID Node1 Node2 Parameters + +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers +;Demand Pattern + + +[CURVES] +;ID X-Value Y-Value + + +[CONTROLS] + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0:10 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 1:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + 10 20.00 70.00 + 11 30.00 70.00 + 12 50.00 70.00 + 13 70.00 70.00 + 21 30.00 40.00 + 22 50.00 40.00 + 23 70.00 40.00 + 31 30.00 10.00 + 32 50.00 10.00 + 41 10.00 70.00 + 42 50.00 90.00 + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + 6.99 73.63 "Source" + 13.48 68.13 "Pump" + 43.85 91.21 "Tank" + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/test_files/test_net_pump.inp b/test_files/test_net_pump.inp new file mode 100755 index 0000000..c1a5f36 --- /dev/null +++ b/test_files/test_net_pump.inp @@ -0,0 +1,182 @@ +[TITLE] + EPANET Example Network 1 +A simple example of modeling chlorine decay. Both bulk and +wall reactions are included. + +[JUNCTIONS] +;ID Elev Demand Pattern + 10 710 0 ; + 11 710 150 ; + 12 700 150 ; + 13 695 100 ; + 21 700 150 ; + 22 695 200 ; + 23 690 150 ; + 31 700 100 ; + 32 710 100 ; + +[RESERVOIRS] +;ID Head Pattern +41 800 ; +42 900 ; + +[TANKS] +;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status + 100 10 11 10530 18 100 0 Open ; + 101 11 12 5280 14 100 0 Open ; + 102 12 13 5280 10 100 0 Open ; + 103 21 22 5280 10 100 0 Open ; + 104 22 23 5280 12 100 0 Open ; + 105 31 32 5280 6 100 0 Open ; + 111 11 21 5280 10 100 0 Open ; + 112 12 22 5280 12 100 0 Open ; + 113 13 23 5280 8 100 0 Open ; + 121 21 31 5280 8 100 0 Open ; + 122 22 32 5280 6 100 0 Open ; + +[PUMPS] +;ID Node1 Node2 Parameters + 123 41 10 HEAD 2 ; + 124 42 12 POWER 50 ; + + +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers +;Demand Pattern + 1 1.0 1.2 1.4 1.6 1.4 1.2 + 1 1.0 0.8 0.6 0.4 0.6 0.8 + +[CURVES] +;ID X-Value Y-Value +;PUMP: PUMP: Pump Curve for Pump 9 + 1 1500 250 + 2 0 104. + 2 2000. 92. + 2 4000. 63. + +[CONTROLS] + + + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + 10 0.5 + 11 0.5 + 12 0.5 + 13 0.5 + 21 0.5 + 22 0.5 + 23 0.5 + 31 0.5 + 32 0.5 + 41 1.0 + 42 1.0 + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 1:00 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 0:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + 10 20.00 70.00 + 11 30.00 70.00 + 12 50.00 70.00 + 13 70.00 70.00 + 21 30.00 40.00 + 22 50.00 40.00 + 23 70.00 40.00 + 31 30.00 10.00 + 32 50.00 10.00 + 41 10.00 70.00 + 42 50.00 90.00 + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + 6.99 73.63 "Source" + 13.48 68.13 "Pump" + 43.85 91.21 "Tank" + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/test_files/test_net_valve.inp b/test_files/test_net_valve.inp new file mode 100755 index 0000000..9b06484 --- /dev/null +++ b/test_files/test_net_valve.inp @@ -0,0 +1,169 @@ +[TITLE] + EPANET Example Network 1 +A simple example of modeling chlorine decay. Both bulk and +wall reactions are included. + +[JUNCTIONS] +;ID Elev Demand Pattern + 10 710 0 ; + 11 710 150 ; + 12 700 150 ; + 13 695 100 ; + 21 700 150 ; + 22 695 200 ; + 23 690 150 ; + 31 700 100 ; + 32 710 100 ; + +[RESERVOIRS] +;ID Head Pattern + 41 800 ; + 42 900 ; + +[TANKS] +;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve + + +[PIPES] +;ID Node1 Node2 Length Diameter Roughness MinorLoss Status + 100 10 11 10530 18 100 0 Open ; + 102 12 13 5280 10 100 0 Open ; + 105 31 32 5280 6 100 0 Open ; + 110 42 12 200 18 100 0 Open ; + 111 11 21 5280 10 100 0 Open ; + 112 12 22 5280 12 100 0 Open ; + 113 13 23 5280 8 100 0 Open ; + 121 21 31 5280 8 100 0 Open ; + 122 22 32 5280 6 100 0 Open ; + +[PUMPS] +;ID Node1 Node2 Parameters + 124 41 10 POWER 50 ; + +[VALVES] +;ID Node1 Node2 Diameter Type Setting MinorLoss +124 11 12 5280 PRV 40 0 ; +125 21 22 1000 TCV 50 0 ; + 126 22 23 5280 FCV 1 0 ; + +[TAGS] + +[DEMANDS] +;Junction Demand Pattern Category + +[STATUS] +;ID Status/Setting + +[PATTERNS] +;ID Multipliers +;Demand Pattern + +[LEAKS] +;JID Diameter +11 2 + +[CURVES] +;ID X-Value Y-Value + + + + +[CONTROLS] + +[RULES] + + +[ENERGY] + Global Efficiency 75 + Global Price 0.0 + Demand Charge 0.0 + +[EMITTERS] +;Junction Coefficient + +[QUALITY] +;Node InitQual + +[SOURCES] +;Node Type Quality Pattern + +[REACTIONS] +;Type Pipe/Tank Coefficient + + +[REACTIONS] + Order Bulk 1 + Order Tank 1 + Order Wall 1 + Global Bulk -.5 + Global Wall -1 + Limiting Potential 0.0 + Roughness Correlation 0.0 + +[MIXING] +;Tank Model + +[TIMES] + Duration 0:10 + Hydraulic Timestep 1:00 + Quality Timestep 0:05 + Pattern Timestep 2:00 + Pattern Start 1:00 + Report Timestep 1:00 + Report Start 0:00 + Start ClockTime 12 am + Statistic NONE + +[REPORT] + Status Yes + Summary No + Page 0 + +[OPTIONS] + Units GPM + Headloss H-W + Specific Gravity 1.0 + Viscosity 1.0 + Trials 40 + Accuracy 0.001 + CHECKFREQ 2 + MAXCHECK 10 + DAMPLIMIT 0 + Unbalanced Continue 10 + Pattern 1 + Demand Multiplier 1.0 + Emitter Exponent 0.5 + Quality Chlorine mg/L + Diffusivity 1.0 + Tolerance 0.01 + +[COORDINATES] +;Node X-Coord Y-Coord + 10 20.00 70.00 + 11 30.00 70.00 + 12 50.00 70.00 + 13 70.00 70.00 + 21 30.00 40.00 + 22 50.00 40.00 + 23 70.00 40.00 + 31 30.00 10.00 + 32 50.00 10.00 + 41 10.00 70.00 + 42 50.00 90.00 + +[VERTICES] +;Link X-Coord Y-Coord + +[LABELS] +;X-Coord Y-Coord Label & Anchor Node + 6.99 73.63 "Source" + 13.48 68.13 "Pump" + 43.85 91.21 "Tank" + +[BACKDROP] + DIMENSIONS 7.00 6.00 73.00 94.00 + UNITS None + FILE + OFFSET 0.00 0.00 + +[END] diff --git a/tests/.clang-format b/tests/.clang-format index 7605de0..cae777b 100644 --- a/tests/.clang-format +++ b/tests/.clang-format @@ -1,5 +1,5 @@ --- -# BasedOnStyle: CUED GeoMechanics +# BasedOnStyle: Cityscape AccessModifierOffset: -1 ConstructorInitializerIndentWidth: 4 AlignEscapedNewlinesLeft: true diff --git a/tests/curve_test.cc b/tests/curve_test.cc new file mode 100644 index 0000000..4966061 --- /dev/null +++ b/tests/curve_test.cc @@ -0,0 +1,84 @@ +#include "catch.hpp" +#include +#include + +#include "curves.h" +// Check node class +TEST_CASE("Check Curves", "[Curve]") { + // Tolerance + const double tolerance = 1.e-8; + std::string head_pump_name1 = "1"; + std::string head_pump_name2 = "2"; + + std::vector> pump_curve_points1 = { + {0.0, 31.6992}, + {0.1261803928, 28.041600000000003}, + {0.2523607856, 19.2024}}; + std::vector> pump_curve_points2 = { + {0.1261803928, 30.48}}; + pipenetwork::Pump_curve_prop p_curve1(head_pump_name1, pump_curve_points1); + pipenetwork::Pump_curve_prop p_curve2(head_pump_name2, pump_curve_points2); + pipenetwork::Curves curve_list; + + SECTION("Check head pump curve property for three points input") { + + auto head_curve_coefficients = p_curve1.head_curve_coefficients; + + // check coefficients + REQUIRE(head_curve_coefficients[0] == Approx(31.6992).epsilon(tolerance)); + REQUIRE(head_curve_coefficients[1] == + Approx(143.47246994481017).epsilon(tolerance)); + REQUIRE(head_curve_coefficients[2] == + Approx(1.7725895038969284).epsilon(tolerance)); + } + + SECTION("Check head pump curve property for one point input") { + + auto head_curve_coefficients = p_curve2.head_curve_coefficients; + + // check coefficients + REQUIRE(head_curve_coefficients[0] == Approx(40.64).epsilon(tolerance)); + REQUIRE(head_curve_coefficients[1] == + Approx(638.1311689716313).epsilon(tolerance)); + REQUIRE(head_curve_coefficients[2] == Approx(2).epsilon(tolerance)); + } + + SECTION("Check linear approximation coefficients") { + auto line = p_curve1.line_param; + REQUIRE(line[0] == Approx(4.4542219126875336e-18).epsilon(tolerance)); + REQUIRE(line[1] == Approx(31.6992).epsilon(tolerance)); + } + SECTION("Check add pump properties") { + std::vector p_curve_vec = {p_curve1, + p_curve2}; + curve_list.add_pump_curves(p_curve_vec); + REQUIRE(curve_list.pump_curves()["1"].line_param[1] == + Approx(31.6992).epsilon(tolerance)); + REQUIRE(curve_list.poly_coeffs()["HW_POLY_VEC"][0] == + Approx(6619.952473405493).epsilon(tolerance)); + REQUIRE(curve_list.poly_coeffs()["HW_POLY_VEC"][1] == + Approx(-2.562247355522429).epsilon(tolerance)); + REQUIRE(curve_list.poly_coeffs()["HW_POLY_VEC"][2] == + Approx(0.0012305046454003125).epsilon(tolerance)); + REQUIRE(curve_list.poly_coeffs()["HW_POLY_VEC"][3] == + Approx(3.4293453535907055e-09).epsilon(tolerance)); + + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC1"][0] == + // Approx(-18.749999999749996).epsilon(tolerance)); + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC1"][1] == + // Approx(6.2456331391).epsilon(tolerance)); + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC1"][2] == + // Approx(1.000000082740371e-11).epsilon(tolerance)); + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC1"][3] == + // Approx(-4.440892098516782e-17).epsilon(tolerance)); + // + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC2"][0] == + // Approx(-0.6249920885505783).epsilon(tolerance)); + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC2"][1] == + // Approx(37.249212823040864).epsilon(tolerance)); + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC2"][2] == + // Approx(-739.9780066609305).epsilon(tolerance)); + // REQUIRE(curve_list.poly_coeffs()["PDD_POLY_VEC2"][3] == + // Approx(4900.811712406892).epsilon(tolerance)); + } +} \ No newline at end of file diff --git a/tests/eigen_gmres_test.cc b/tests/eigen_gmres_test.cc deleted file mode 100644 index 1da40b7..0000000 --- a/tests/eigen_gmres_test.cc +++ /dev/null @@ -1,105 +0,0 @@ -#include "catch.hpp" - -#include "eigen_gmres.h" -#include "matrix_assembler.h" -#include "settings.h" -#include "solver.h" - -// Check Eigen GMRES class (solve Ax=b) -TEST_CASE("Eigen GMRES solver is checked", "[EigenGMRES]") { - // Tolerance - const double tolerance = 1.e-10; - - // Max number of iteration - const unsigned max_iter = 5000; - - // Input vector b - auto b = std::make_shared(); - b->resize(8); - b->coeffRef(0) = 3.0; - b->coeffRef(1) = 5.1; - b->coeffRef(2) = 22.2; - b->coeffRef(3) = 13.0; - b->coeffRef(4) = 0.0; - b->coeffRef(5) = 140.4; - b->coeffRef(6) = 50.5; - b->coeffRef(7) = 27.0; - - // Input initial guess vector x - auto x = std::make_shared(); - x->resize(8); - x->setZero(); - - // Input matrix A - auto A = std::make_shared>(); - std::vector> update; - update.emplace_back(0, 0, 11.1); - update.emplace_back(0, 1, 12.2); - update.emplace_back(0, 3, 14.3); - update.emplace_back(1, 1, 22.4); - update.emplace_back(1, 2, 23.5); - update.emplace_back(1, 4, 25.6); - update.emplace_back(2, 0, 31.7); - update.emplace_back(2, 2, 33.8); - update.emplace_back(2, 3, 34.9); - update.emplace_back(3, 1, 42.0); - update.emplace_back(3, 4, 45.1); - update.emplace_back(3, 5, 46.2); - update.emplace_back(4, 4, 55.3); - update.emplace_back(5, 4, 65.4); - update.emplace_back(5, 5, 66.5); - update.emplace_back(5, 6, 67.6); - update.emplace_back(6, 4, 75.7); - update.emplace_back(6, 6, 77.8); - update.emplace_back(6, 7, 78.9); - update.emplace_back(7, 6, 87.0); - update.emplace_back(7, 7, 88.1); - A->resize(8, 8); - A->setFromTriplets(update.begin(), update.end()); - - // Creat a eigen gmres solver and solve - double gmres_tolerance = 1.e-25; - auto solver = - std::make_shared(max_iter, gmres_tolerance); - solver->assembled_matrices(A, x, b); - - // Check the case that there is no known values in x - SECTION("Check the case that there is no known values in x") { - - // Apply restraints and solve - Eigen::VectorXd restraints(8); - restraints << 1, 1, 1, 1, 1, 1, 1, 1; - solver->restrains(restraints); - bool issolved = solver->solve(); - - // Check results - REQUIRE(x->coeff(0) == Approx(-3470.91931206031813).epsilon(tolerance)); - REQUIRE(x->coeff(1) == Approx(-258.21997602699554).epsilon(tolerance)); - REQUIRE(x->coeff(2) == Approx(246.35010480871063).epsilon(tolerance)); - REQUIRE(x->coeff(3) == Approx(2914.71944555236860).epsilon(tolerance)); - REQUIRE(x->coeff(4) == Approx(0.0).epsilon(tolerance)); - REQUIRE(x->coeff(5) == Approx(235.02681803319942).epsilon(tolerance)); - REQUIRE(x->coeff(6) == Approx(-229.12549407112076).epsilon(tolerance)); - REQUIRE(x->coeff(7) == Approx(226.57114624503413).epsilon(tolerance)); - } - - // Check the case that there are known zeros in x - SECTION("Check the case that there are known zeros in x") { - - // Apply restraints and solve - Eigen::VectorXd restraints(8); - restraints << 1, 1, 1, 1, 0, 1, 1, 1; - solver->restrains(restraints); - bool issolved = solver->solve(); - - // Check results - REQUIRE(x->coeff(0) == Approx(-3470.91931206031813).epsilon(tolerance)); - REQUIRE(x->coeff(1) == Approx(-258.21997602699554).epsilon(tolerance)); - REQUIRE(x->coeff(2) == Approx(246.35010480871063).epsilon(tolerance)); - REQUIRE(x->coeff(3) == Approx(2914.71944555236860).epsilon(tolerance)); - REQUIRE(x->coeff(4) == Approx(0.0).epsilon(tolerance)); - REQUIRE(x->coeff(5) == Approx(235.02681803319942).epsilon(tolerance)); - REQUIRE(x->coeff(6) == Approx(-229.12549407112076).epsilon(tolerance)); - REQUIRE(x->coeff(7) == Approx(226.57114624503413).epsilon(tolerance)); - } -} diff --git a/tests/hydraulic_sim_test.cc b/tests/hydraulic_sim_test.cc new file mode 100644 index 0000000..c1dbf48 --- /dev/null +++ b/tests/hydraulic_sim_test.cc @@ -0,0 +1,171 @@ +#include "catch.hpp" + +#include "hydralic_sim.h" +#include + +using namespace std::chrono; +// Check matrix_assembler class +TEST_CASE("HydraulicSimulation is checked", "[hydralic_sim]") { + + // Tolerance + const double tolerance = 1.e-8; + + // Mesh index + std::string meshid = "Matrix test mesh"; + + // Creat a mesh + auto mesh = std::make_shared(meshid); + + // Create a curves info object + auto curves_info = std::make_shared(); + + std::vector junction_ids{"10", "11", "12"}; + std::vector elevations{216.408, 216.408, 213.36}; + std::vector demands{0, 9.464e-03, 9.464e-03}; + std::vector leak_diameters{0, 0.1, 0}; + + std::vector junc_props; + for (int i = 0; i < elevations.size(); ++i) { + pipenetwork::JunctionProp junc_prop; + junc_prop.name = junction_ids[i]; + junc_prop.elevation = elevations[i]; + junc_prop.demand = demands[i]; + junc_prop.leak_diameter = leak_diameters[i]; + + junc_props.emplace_back(junc_prop); + } + + std::vector res_ids{"13"}; + std::vector heads{3.048e+02}; + + std::vector res_props; + for (int i = 0; i < res_ids.size(); ++i) { + pipenetwork::ReservoirProp res_prop; + res_prop.name = res_ids[i]; + res_prop.head = heads[i]; + + res_props.emplace_back(res_prop); + } + + std::vector pipe_ids{"10", "11"}; + std::vector> nodeids{ + std::make_pair("13", "10"), std::make_pair("10", "11")}; + const std::vector length{3209.5440000000003, 3209.5440000000003, + 1609.344, 1609.344}; + const std::vector diameter{0.5588, 0.4572, 0.35559999999999997, + 0.254}; + const std::vector roughness{100, 100, 100, 100}; + + std::vector pipe_props; + for (int i = 0; i < pipe_ids.size(); ++i) { + pipenetwork::PipeProp pipe_prop; + pipe_prop.name = pipe_ids[i]; + pipe_prop.length = length[i]; + pipe_prop.diameter = diameter[i]; + pipe_prop.roughness = roughness[i]; + pipe_prop.node1_name = nodeids[i].first; + pipe_prop.node2_name = nodeids[i].second; + + pipe_props.emplace_back(pipe_prop); + } + + std::vector pump_ids{"12"}; + std::vector> pump_nodeids{ + std::make_pair("10", "12")}; + + std::vector pump_props; + + for (int i = 0; i < pump_ids.size(); ++i) { + pipenetwork::PumpProp pump_prop; + pump_prop.name = pump_ids[i]; + pump_prop.type = pipenetwork::PumpType::POWERPUMP; + pump_prop.node1_name = pump_nodeids[i].first; + pump_prop.node2_name = pump_nodeids[i].second; + pump_props.emplace_back(pump_prop); + } + + std::vector valve_ids{"13"}; + std::vector> valve_nodeids{ + std::make_pair("11", "12")}; + + std::vector valve_props; + + for (int i = 0; i < valve_ids.size(); ++i) { + pipenetwork::ValveProp valve_prop; + valve_prop.name = valve_ids[i]; + valve_prop.type = pipenetwork::ValveType::PRVALVE; + valve_prop.status = pipenetwork::LinkStatus ::ACTIVE; + valve_prop.setting = 10; + valve_prop.node1_name = valve_nodeids[i].first; + valve_prop.node2_name = valve_nodeids[i].second; + + valve_props.emplace_back(valve_prop); + } + + mesh->create_nodes(junc_props, res_props); + mesh->create_links(pipe_props, pump_props, valve_props); + mesh->create_mesh_graph(); + + SECTION("DD SIM TEST CASE 1: MESH INPUT ") { + bool pdd_mode = false; + bool debug = false; + auto sim = std::make_shared(mesh, curves_info, + pdd_mode, debug); + REQUIRE(sim->run_simulation()); + REQUIRE(sim->sim_residual_norm() < tolerance); + // pressure test for stability + auto start = high_resolution_clock::now(); + REQUIRE(!sim->run_simulation(1e-30, 100)); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop - start); + // std::cout << duration.count() << std::endl; + REQUIRE(sim->sim_residual_norm() < tolerance); + sim->update_mesh(); + } + + SECTION("DD SIM TEST CASE 2: .INP FILE INPUT") { + bool pdd_mode = false; + bool debug = false; + + auto IO = std::make_shared(); + IO->read_inp("../test_files/test_net.inp"); + std::string mesh_name = "test_mesh_inp"; + + auto mesh_inp = std::make_shared(mesh_name); + mesh_inp->create_nodes(IO->junction_properties(), + IO->reservoir_properties()); + mesh_inp->create_links(IO->pipe_properties(), IO->pump_properties(), + IO->valve_properties()); + mesh_inp->create_mesh_graph(); + mesh_inp->print_summary(); + + auto curves_info_io = IO->curve_info(); + auto sim = std::make_shared( + mesh_inp, curves_info_io, pdd_mode, debug); + sim->run_simulation(1e-8, 10); + REQUIRE(sim->sim_residual_norm() < tolerance); + } + + SECTION("PDD SIM TEST CASE: .INP FILE INPUT") { + bool pdd_mode = true; + bool debug = false; + + auto IO = std::make_shared(); + IO->read_inp("../test_files/test_net_pdd.inp"); + std::string mesh_name = "pdd_test"; + + auto mesh_inp = std::make_shared(mesh_name); + mesh_inp->create_nodes(IO->junction_properties(), + IO->reservoir_properties()); + mesh_inp->create_links(IO->pipe_properties(), IO->pump_properties(), + IO->valve_properties()); + mesh_inp->create_mesh_graph(); + mesh_inp->print_summary(); + + auto curves_info_io = IO->curve_info(); + auto sim = std::make_shared( + mesh_inp, curves_info_io, pdd_mode, debug); + sim->run_simulation(1e-8, 20); + REQUIRE(sim->sim_residual_norm() < tolerance); + } +} diff --git a/tests/input_test.cc b/tests/input_test.cc new file mode 100644 index 0000000..93cb69b --- /dev/null +++ b/tests/input_test.cc @@ -0,0 +1,118 @@ +#include "catch.hpp" + +#include "io.h" +#include "mesh.h" +// Check IO class +TEST_CASE("Input is checked", "[IO]") { + double tolerance = 1e-6; + + SECTION("Check Parsed valve info") { + + // Create a INPUT class object + auto IO = std::make_unique(); + IO->read_inp("../test_files/test_net_valve.inp"); + + // Mesh index + std::string meshid = "IO_test_mesh"; + // Creat a mesh + auto mesh = std::make_shared(meshid); + + auto valve_props = IO->valve_properties(); + REQUIRE(valve_props.size() == 3); + REQUIRE(valve_props[0].type == pipenetwork::ValveType::PRVALVE); + REQUIRE(valve_props[0].name == "124"); + REQUIRE(valve_props[0].setting == 28.137549042234017); + REQUIRE(valve_props[1].name == "125"); + REQUIRE(valve_props[1].type == pipenetwork::ValveType::TCVALVE); + REQUIRE(valve_props[1].setting == 50); + } + + SECTION("Check Parsed pump info") { + // Create a INPUT class object + auto IO = std::make_unique(); + IO->read_inp("../test_files/test_net_pump.inp"); + // Mesh index + std::string meshid = "IO_test_mesh"; + // Creat a mesh + auto mesh = std::make_shared(meshid); + + auto pump_props = IO->pump_properties(); + auto curve_info = IO->curve_info(); + REQUIRE(pump_props.size() == 2); + REQUIRE(curve_info->pump_int_str(pump_props[0].curve_id) == "2"); + REQUIRE(pump_props[0].type == pipenetwork::PumpType::HEADPUMP); + REQUIRE(pump_props[0].name == "123"); + REQUIRE(pump_props[1].name == "124"); + REQUIRE(pump_props[1].type == pipenetwork::PumpType::POWERPUMP); + REQUIRE(pump_props[1].curve_id == -1); + REQUIRE(pump_props[1].power == 37284.9936); + } + + SECTION("Check Parsed node info") { + auto IO = std::make_unique(); + IO->read_inp("../test_files/test_net_valve.inp"); + // Mesh index + std::string meshid = "IO_test_mesh"; + // Creat a mesh + auto mesh = std::make_unique(meshid); + + // junctions + auto junction_props = IO->junction_properties(); + + REQUIRE(junction_props.size() == 9); + REQUIRE(junction_props[0].name == "10"); + REQUIRE(junction_props[0].elevation == Approx(216.408).epsilon(tolerance)); + REQUIRE(junction_props[1].demand == + Approx(0.0094635295).epsilon(tolerance)); + REQUIRE(junction_props[8].name == "32"); + REQUIRE(junction_props[0].leak_diameter == 0); + + // leak junction + REQUIRE(junction_props[1].leak_diameter == 2 * 0.0254); + + // reservoirs + auto reservoir_props = IO->reservoir_properties(); + + REQUIRE(reservoir_props[0].head == Approx(243.84).epsilon(tolerance)); + REQUIRE(reservoir_props[0].name == "41"); + } + SECTION("Check Parsed Pipe info") { + auto IO = std::make_unique(); + IO->read_inp("../test_files/test_net.inp"); + // check end nodes + auto pipe_props = IO->pipe_properties(); + REQUIRE(pipe_props.size() == 8); + REQUIRE(pipe_props[0].node1_name == "10"); + REQUIRE(pipe_props[0].node2_name == "11"); + // check roughness + REQUIRE(pipe_props[0].roughness == 100); + // check diameter + REQUIRE(pipe_props[1].diameter == Approx(0.254).epsilon(tolerance)); + // check diameter + REQUIRE(pipe_props[0].status == pipenetwork::LinkStatus::OPEN); + // check length + REQUIRE(pipe_props[1].length == Approx(1609.344).epsilon(tolerance)); + // check id + REQUIRE(pipe_props[1].name == "102"); + } + + SECTION("Check Synthetic Net") { + // Create a INPUT class object + auto IO = std::make_shared(); + IO->create_synthetic_net(10); + auto junction_props = IO->junction_properties(); + REQUIRE(junction_props.size() == 100); + } + + SECTION("Check Parsed isolation valve info") { + auto IO = std::make_unique(); + IO->read_inp("../benchmarks/small/valves_test.inp"); + + // check iso valve + auto iso_valve_props = IO->iso_valve_properties(); + REQUIRE(iso_valve_props.size() == 17); + REQUIRE(iso_valve_props[1].name == "V2"); + REQUIRE(iso_valve_props[1].on_node == "4"); + REQUIRE(iso_valve_props[1].on_pipe == "P3"); + } +} \ No newline at end of file diff --git a/tests/io_test.cc b/tests/io_test.cc deleted file mode 100644 index 399716d..0000000 --- a/tests/io_test.cc +++ /dev/null @@ -1,138 +0,0 @@ -#include "catch.hpp" - -#include "io.h" - -// Check IO class -TEST_CASE("IO is checked", "[IO]") { - // Tolerance - const double tolerance = 1.e-12; - - // Create a IO class object - auto IO = std::make_unique(); - - // Read node and pipe information from CSV files - bool read_network = - IO->read_network("../benchmarks/todini_network_node_iotest.csv", - "../benchmarks/todini_network_pipe_iotest.csv"); - - // Check read nodal information - SECTION("Check read nodal information") { - std::vector nodal_coords = IO->nodal_coordinates(); - std::vector> init_nodal_head = - IO->initial_nodal_head(); - std::vector> init_nodal_discharge = - IO->initial_nodal_discharge(); - - // Check coordinates - REQUIRE(nodal_coords.at(0)(0) == Approx(1.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(0)(1) == Approx(3.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(0)(2) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(1)(0) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(1)(1) == Approx(2.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(1)(2) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(2)(0) == Approx(2.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(2)(1) == Approx(2.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(2)(2) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(3)(0) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(3)(1) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(3)(2) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(4)(0) == Approx(2.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(4)(1) == Approx(0.0).epsilon(tolerance)); - REQUIRE(nodal_coords.at(4)(2) == Approx(0.0).epsilon(tolerance)); - - // Check initial nodal head - REQUIRE(init_nodal_head.at(0).first == 0); - REQUIRE(init_nodal_head.at(0).second == Approx(100.0).epsilon(tolerance)); - REQUIRE(init_nodal_head.at(1).first == 1); - REQUIRE(init_nodal_head.at(1).second == Approx(99.0).epsilon(tolerance)); - REQUIRE(init_nodal_head.at(2).first == 2); - REQUIRE(init_nodal_head.at(2).second == Approx(98.0).epsilon(tolerance)); - REQUIRE(init_nodal_head.at(3).first == 3); - REQUIRE(init_nodal_head.at(3).second == Approx(97.0).epsilon(tolerance)); - - // Check initial nodal discharge - REQUIRE(init_nodal_discharge.at(0).first == 0); - REQUIRE(init_nodal_discharge.at(0).second == - Approx(-100.0).epsilon(tolerance)); - REQUIRE(init_nodal_discharge.at(1).first == 1); - REQUIRE(init_nodal_discharge.at(1).second == - Approx(10.0).epsilon(tolerance)); - REQUIRE(init_nodal_discharge.at(2).first == 2); - REQUIRE(init_nodal_discharge.at(2).second == - Approx(20.0).epsilon(tolerance)); - REQUIRE(init_nodal_discharge.at(3).first == 3); - REQUIRE(init_nodal_discharge.at(3).second == - Approx(30.0).epsilon(tolerance)); - REQUIRE(init_nodal_discharge.at(4).first == 4); - REQUIRE(init_nodal_discharge.at(4).second == - Approx(40.0).epsilon(tolerance)); - } - - // Check read pipe information - SECTION("Check read pipe information") { - std::vector> node_pairs = IO->node_pairs(); - std::vector diameters = IO->diameters(); - std::vector roughness = IO->roughness(); - std::vector pipe_status = IO->pipe_status(); - std::vector> init_pipe_discharge = - IO->initial_pipe_discharge(); - - // Check start and end nodes - REQUIRE(node_pairs.at(0).first == 0); - REQUIRE(node_pairs.at(0).second == 1); - REQUIRE(node_pairs.at(1).first == 0); - REQUIRE(node_pairs.at(1).second == 2); - REQUIRE(node_pairs.at(2).first == 1); - REQUIRE(node_pairs.at(2).second == 2); - REQUIRE(node_pairs.at(3).first == 1); - REQUIRE(node_pairs.at(3).second == 3); - REQUIRE(node_pairs.at(4).first == 1); - REQUIRE(node_pairs.at(4).second == 4); - REQUIRE(node_pairs.at(5).first == 2); - REQUIRE(node_pairs.at(5).second == 4); - REQUIRE(node_pairs.at(6).first == 3); - REQUIRE(node_pairs.at(6).second == 4); - - // Check pipe diameters - REQUIRE(diameters.at(0) == Approx(0.1).epsilon(tolerance)); - REQUIRE(diameters.at(1) == Approx(0.2).epsilon(tolerance)); - REQUIRE(diameters.at(2) == Approx(0.3).epsilon(tolerance)); - REQUIRE(diameters.at(3) == Approx(0.4).epsilon(tolerance)); - REQUIRE(diameters.at(4) == Approx(0.5).epsilon(tolerance)); - REQUIRE(diameters.at(5) == Approx(0.6).epsilon(tolerance)); - REQUIRE(diameters.at(6) == Approx(0.7).epsilon(tolerance)); - - // Check pipe roughness - REQUIRE(roughness.at(0) == Approx(147683.3637).epsilon(tolerance)); - REQUIRE(roughness.at(1) == Approx(4102.777965).epsilon(tolerance)); - REQUIRE(roughness.at(2) == Approx(1238.160737).epsilon(tolerance)); - REQUIRE(roughness.at(3) == Approx(1598.561076).epsilon(tolerance)); - REQUIRE(roughness.at(4) == Approx(430.5609768).epsilon(tolerance)); - REQUIRE(roughness.at(5) == Approx(137.5889198).epsilon(tolerance)); - REQUIRE(roughness.at(6) == Approx(133.3735196).epsilon(tolerance)); - - // Check pipe status - for (int i = 0; i < pipe_status.size(); i++) - REQUIRE(pipe_status.at(i) == true); - - // Check initial pipe discharge - REQUIRE(init_pipe_discharge.at(0).first == 0); - REQUIRE(init_pipe_discharge.at(0).second == - Approx(80.0).epsilon(tolerance)); - REQUIRE(init_pipe_discharge.at(1).first == 1); - REQUIRE(init_pipe_discharge.at(1).second == - Approx(20.0).epsilon(tolerance)); - REQUIRE(init_pipe_discharge.at(2).first == 2); - REQUIRE(init_pipe_discharge.at(2).second == - Approx(10.0).epsilon(tolerance)); - REQUIRE(init_pipe_discharge.at(3).first == 3); - REQUIRE(init_pipe_discharge.at(3).second == - Approx(40.0).epsilon(tolerance)); - REQUIRE(init_pipe_discharge.at(4).first == 4); - REQUIRE(init_pipe_discharge.at(4).second == - Approx(20.0).epsilon(tolerance)); - REQUIRE(init_pipe_discharge.at(5).first == 6); - REQUIRE(init_pipe_discharge.at(5).second == - Approx(10.0).epsilon(tolerance)); - } -} diff --git a/tests/link_test.cc b/tests/link_test.cc new file mode 100644 index 0000000..594b6ba --- /dev/null +++ b/tests/link_test.cc @@ -0,0 +1,98 @@ +#include "catch.hpp" +#include +#include + +#include "junction.h" +#include "pipe.h" +#include "pump.h" +#include "reservoir.h" +#include "valve.h" + +// Check node class +TEST_CASE("Link is checked", "[Link]") { + // Tolerance + const double tolerance = 1.e-6; + + pipenetwork::Index nid1 = 1; + pipenetwork::Index nid2 = 2; + + pipenetwork::ReservoirProp res1; + res1.name = "res1"; + res1.head = 10; + + pipenetwork::JunctionProp junc1; + junc1.name = "123"; + junc1.elevation = 10; + junc1.demand = 20; + junc1.leak_diameter = 5; + + // Create a junction + auto junction_node = pipenetwork::Junction(nid1, junc1); + // Create a reservoir + auto reservoir_node = pipenetwork::Reservoir(nid2, res1); + + SECTION("Check pipe") { + pipenetwork::PipeProp pipe1; + pipe1.name = "pipe1"; + pipe1.length = 10; + pipe1.diameter = 8; + pipe1.roughness = 0.5; + pipenetwork::Index pipe_id = 1; + + auto pipe = + pipenetwork::Pipe(pipe_id, junction_node, reservoir_node, pipe1); + // check id + REQUIRE(pipe.id() == pipe_id); + + // check two end points + REQUIRE(pipe.nodes().first->id() == nid1); + REQUIRE(pipe.nodes().second->id() == nid2); + + // check pipe property + auto property = pipe.property(); + REQUIRE(property.name == pipe1.name); + REQUIRE(property.length == pipe1.length); + } + + SECTION("Check pump") { + pipenetwork::PumpProp pump1; + pump1.name = "pump1"; + pump1.status = pipenetwork::LinkStatus::CLOSED; + pipenetwork::Index pump_id = 2; + + auto pump = + pipenetwork::Pump(pump_id, junction_node, reservoir_node, pump1); + // check id + REQUIRE(pump.id() == pump_id); + + // check two end points + REQUIRE(pump.nodes().first->id() == nid1); + REQUIRE(pump.nodes().second->id() == nid2); + + // check pipe property + auto property = pump.property(); + REQUIRE(property.name == pump1.name); + REQUIRE(property.status == pump1.status); + } + + SECTION("Check Valve") { + pipenetwork::ValveProp valve1; + valve1.name = "valve1"; + valve1.status = pipenetwork::LinkStatus::CLOSED; + pipenetwork::Index pump_id = 3; + + auto valve = + pipenetwork::Valve(pump_id, junction_node, reservoir_node, valve1); + // check id + REQUIRE(valve.id() == pump_id); + + // check two end points + REQUIRE(valve.nodes().first->id() == nid1); + REQUIRE(valve.nodes().second->id() == nid2); + + // check pipe property + auto property = valve.property(); + REQUIRE(property.name == valve1.name); + REQUIRE(property.status == valve1.status); + } +} diff --git a/tests/test.cc b/tests/main_test.cc similarity index 100% rename from tests/test.cc rename to tests/main_test.cc diff --git a/tests/matrix_assembler_test.cc b/tests/matrix_assembler_test.cc index f150526..70a8312 100644 --- a/tests/matrix_assembler_test.cc +++ b/tests/matrix_assembler_test.cc @@ -1,205 +1,416 @@ #include "catch.hpp" +#include +#include +#include "curves.h" +//#include "input.h" #include "matrix_assembler.h" -#include "mesh.h" -#include "node.h" -#include "pipe.h" -#include "settings.h" // Check matrix_assembler class TEST_CASE("MatrixAssembler is checked", "[MatrixAssembler]") { + // Tolerance - const double tolerance = 1.e-12; + const double tolerance = 1.e-8; // Mesh index - const unsigned meshid = 101; + std::string meshid = "Matrix test mesh"; // Creat a mesh auto mesh = std::make_shared(meshid); - // Nodal coordinates - // using example netwrok in Todini(2013) - const Eigen::Vector3d coords1(1.0, 3.0, 0.0); - const Eigen::Vector3d coords2(0.0, 2.0, 0.0); - const Eigen::Vector3d coords3(2.0, 2.0, 0.0); - const Eigen::Vector3d coords4(0.0, 0.0, 0.0); - const Eigen::Vector3d coords5(2.0, 0.0, 0.0); - std::vector coords = {coords1, coords2, coords3, coords4, - coords5}; - - // Create nodal pointers based on nodal coordinates in the mesh - mesh->create_nodes(coords); - - // Make pairs of nodes to create pipe - std::vector> node_pairs; - node_pairs.emplace_back(std::make_pair(0, 1)); - node_pairs.emplace_back(std::make_pair(0, 2)); - node_pairs.emplace_back(std::make_pair(1, 2)); - node_pairs.emplace_back(std::make_pair(1, 3)); - node_pairs.emplace_back(std::make_pair(1, 4)); - node_pairs.emplace_back(std::make_pair(2, 4)); - node_pairs.emplace_back(std::make_pair(3, 4)); - - // Input vector of pipe diameter, roughness and status - std::vector diameter{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7}; - std::vector roughness{ - 147683.36372579, 4102.7779645159, 1238.1607371737, 1598.5610759603, - 430.5609768094, 137.58891975265, 133.37351955511}; - std::vector status{true, true, true, true, true, true, true}; - - // Create pipes based on pipe indices and previous created node pointers in - // the mesh - bool all_pipe_created = - mesh->create_pipes(node_pairs, diameter, roughness, status); - - // Initialize pipe discharge - mesh->initialize_pipe_discharge(); - - // Assign initial nodal head and discharge - double default_init_node_head = 0.0; - double default_init_node_discharge = 0.0; - double init_pipe_discharge = 0.001; - double head1 = 100.0; - double head2 = 99.0; - double discharge1 = 100.0; - double discharge2 = -10.0; - std::vector> node_head; - node_head.emplace_back(std::make_pair(0, head1)); - node_head.emplace_back(std::make_pair(1, head2)); - std::vector> node_discharge; - node_discharge.emplace_back(std::make_pair(0, discharge1)); - node_discharge.emplace_back(std::make_pair(1, discharge2)); - mesh->initialize_pipe_discharge(init_pipe_discharge); - mesh->assign_node_head(node_head); - mesh->assign_node_discharge(node_discharge); - - // Initialize matrix assembler and obtain global index to nodes and pipes - auto assembler = std::make_shared(); - assembler->global_nodal_pipe_indices(mesh, 2); - - // Check the number of nodes and pipes in the network - unsigned nnodes = assembler->nnodes(); - unsigned npipes = assembler->npipes(); - // unsigned nnodes_known = assembler->nnodes_known(); - REQUIRE(nnodes == 5); - REQUIRE(npipes == 7); - // REQUIRE(nnodes_known == 2); - - // Check initialized variable (head and discharge) vector - SECTION("Check initialized variable vector") { - // Initialize variable vector - assembler->sim_assemble_variable_vector_v2(); - std::shared_ptr variable_vec = assembler->variable_vec(); - std::shared_ptr> id_map = assembler->id_map(); - - std::cout << (*variable_vec) << std::endl; - for (auto const& pair : *id_map) { - std::cout << " " << pair.first << ": " << pair.second << " \n"; - } - // Check id mapping - REQUIRE(id_map->at(2) == 0); - REQUIRE(id_map->at(3) == 1); - // for (int i = 2; i <= 4; i++) - // REQUIRE(variable_vec->coeff(i) == - // Approx(default_init_node_head).epsilon(tolerance)); - // // Check nodal discharge - // REQUIRE(variable_vec->coeff(5) == - // Approx(discharge1).epsilon(tolerance)); REQUIRE(variable_vec->coeff(6) - // == Approx(discharge2).epsilon(tolerance)); for (int i = 7; i <= 9; - // i++) - // REQUIRE(variable_vec->coeff(i) == - // Approx(default_init_node_discharge).epsilon(tolerance)); - // // Check pipe discharge - // for (int i = 10; i <= 16; i++) - // REQUIRE(variable_vec->coeff(i) == - // Approx(default_init_pipe_discharge).epsilon(tolerance)); + // Create a curves info object + auto curves_info = std::make_shared(); + + std::vector junction_ids{"10", "11", "12"}; + std::vector elevations{216.408, 216.408, 213.36}; + std::vector demands{0, 9.464e-03, 9.464e-03}; + std::vector leak_diameters{0, 0.1, 0}; + + std::vector junc_props; + for (int i = 0; i < elevations.size(); ++i) { + pipenetwork::JunctionProp junc_prop; + junc_prop.name = junction_ids[i]; + junc_prop.elevation = elevations[i]; + junc_prop.demand = demands[i]; + junc_prop.leak_diameter = leak_diameters[i]; + + junc_props.emplace_back(junc_prop); + } + + std::vector res_ids{"13"}; + std::vector heads{3.048e+02}; + + std::vector res_props; + for (int i = 0; i < res_ids.size(); ++i) { + pipenetwork::ReservoirProp res_prop; + res_prop.name = res_ids[i]; + res_prop.head = heads[i]; + + res_props.emplace_back(res_prop); + } + + std::vector pipe_ids{"10", "11"}; + std::vector> nodeids{ + std::make_pair("13", "10"), std::make_pair("10", "11")}; + const std::vector length{3209.5440000000003, 3209.5440000000003, + 1609.344, 1609.344}; + const std::vector diameter{0.5588, 0.4572, 0.35559999999999997, + 0.254}; + const std::vector roughness{100, 100, 100, 100}; + + std::vector pipe_props; + for (int i = 0; i < pipe_ids.size(); ++i) { + pipenetwork::PipeProp pipe_prop; + pipe_prop.name = pipe_ids[i]; + pipe_prop.length = length[i]; + pipe_prop.diameter = diameter[i]; + pipe_prop.roughness = roughness[i]; + pipe_prop.node1_name = nodeids[i].first; + pipe_prop.node2_name = nodeids[i].second; + + pipe_props.emplace_back(pipe_prop); + } + + std::vector pump_ids{"12"}; + std::vector> pump_nodeids{ + std::make_pair("10", "12")}; + + std::vector pump_props; + + for (int i = 0; i < pump_ids.size(); ++i) { + pipenetwork::PumpProp pump_prop; + pump_prop.name = pump_ids[i]; + pump_prop.type = pipenetwork::PumpType::POWERPUMP; + pump_prop.node1_name = pump_nodeids[i].first; + pump_prop.node2_name = pump_nodeids[i].second; + pump_props.emplace_back(pump_prop); + } + + std::vector valve_ids{"13"}; + std::vector> valve_nodeids{ + std::make_pair("11", "12")}; + + std::vector valve_props; + + for (int i = 0; i < valve_ids.size(); ++i) { + pipenetwork::ValveProp valve_prop; + valve_prop.name = valve_ids[i]; + valve_prop.type = pipenetwork::ValveType::PRVALVE; + valve_prop.status = pipenetwork::LinkStatus ::ACTIVE; + valve_prop.setting = 10; + valve_prop.node1_name = valve_nodeids[i].first; + valve_prop.node2_name = valve_nodeids[i].second; + + valve_props.emplace_back(valve_prop); + } + + mesh->create_nodes(junc_props, res_props); + mesh->create_links(pipe_props, pump_props, valve_props); + mesh->create_mesh_graph(); + + // mesh->print_summary(); + + SECTION("TEST VARIABLES") { + auto variables = pipenetwork::linear_system::Variables(mesh); + SECTION("variable vector") { + auto var_vec = variables.variables_vec(); + REQUIRE(var_vec.size() == 13); + REQUIRE(var_vec[0] == Approx(216.408).epsilon(tolerance)); + REQUIRE(var_vec[5] == Approx(9.464e-03).epsilon(tolerance)); + REQUIRE(var_vec[10] == + Approx(pipenetwork::INIT_FLOWRATE).epsilon(tolerance)); + REQUIRE(var_vec[12] == Approx(0).epsilon(tolerance)); + } + SECTION("variable vector") { + auto demands_heads_vec = variables.demands_heads_vec(); + REQUIRE(demands_heads_vec.size() == 4); + REQUIRE(demands_heads_vec[0] == Approx(0).epsilon(tolerance)); + REQUIRE(demands_heads_vec[1] == Approx(9.464e-03).epsilon(tolerance)); + REQUIRE(demands_heads_vec[2] == Approx(9.464e-03).epsilon(tolerance)); + REQUIRE(demands_heads_vec[3] == Approx(3.048e+02).epsilon(tolerance)); + } + SECTION("elevation vector") { + auto elevations_vec = variables.elevations(); + REQUIRE(elevations_vec.size() == 4); + REQUIRE(elevations_vec[0] == Approx(216.408).epsilon(tolerance)); + REQUIRE(elevations_vec[1] == Approx(216.408).epsilon(tolerance)); + REQUIRE(elevations_vec[2] == Approx(213.36).epsilon(tolerance)); + REQUIRE(elevations_vec[3] == Approx(3.048e+02).epsilon(tolerance)); + } + SECTION("resistance vector") { + auto link_resistance_coeff_vec = variables.link_resistance_coeff_vec(); + + double coeff1 = pipenetwork::HW_COEFF * std::pow(roughness[1], -1.852) * + std::pow(diameter[1], -4.871) * length[1]; + + REQUIRE(link_resistance_coeff_vec.size() == 4); + REQUIRE(link_resistance_coeff_vec[1] == + Approx(coeff1).epsilon(tolerance)); + } + + SECTION("minor vector") { + auto link_minor_loss_coeff_vec = variables.link_minor_loss_coeff_vec(); + REQUIRE(link_minor_loss_coeff_vec.size() == 4); + REQUIRE(link_minor_loss_coeff_vec[0] == Approx(0).epsilon(tolerance)); + REQUIRE(link_minor_loss_coeff_vec[1] == Approx(0).epsilon(tolerance)); + REQUIRE(link_minor_loss_coeff_vec[2] == Approx(0).epsilon(tolerance)); + REQUIRE(link_minor_loss_coeff_vec[3] == Approx(0).epsilon(tolerance)); + } + + SECTION("leak area vector") { + auto leak_areas = variables.leak_areas(); + double leak_area = pipenetwork::PI * std::pow((0.1 / 2), 2); + REQUIRE(leak_areas.size() == 1); + REQUIRE(leak_areas[0] == Approx(leak_area).epsilon(tolerance)); + } + } + + SECTION("TEST RESIDUALS") { + auto variables = + std::make_shared(mesh); + auto residuals = + pipenetwork::linear_system::Residuals(mesh, variables, curves_info); + residuals.assemble_residual(); + auto res_vec = residuals.residual_vec(); + + SECTION("node balance residual") { + REQUIRE(res_vec.coeff(0) == Approx(-0.001).epsilon(tolerance)); + REQUIRE(res_vec.coeff(1) == Approx(-9.464e-03).epsilon(tolerance)); + } + + SECTION("node demand head residual") { + REQUIRE(res_vec.coeff(5) == Approx(0).epsilon(tolerance)); + REQUIRE(res_vec.coeff(7) == Approx(0).epsilon(tolerance)); + } + + SECTION("pipe headloss residual") { + // pipe headloss + REQUIRE(res_vec.coeff(8) == Approx(-88.3916796736).epsilon(tolerance)); + // pump headloss + double pump_res = 50 + (elevations[0] - elevations[2]) * + pipenetwork::INIT_FLOWRATE * pipenetwork::G * + 1000.0; + REQUIRE(res_vec.coeff(10) == Approx(pump_res).epsilon(tolerance)); + + // valve headloss + REQUIRE(res_vec.coeff(11) == Approx(-10).epsilon(tolerance)); + } + + SECTION("pipe leak residual") { + REQUIRE(res_vec.coeff(12) == Approx(0).epsilon(tolerance)); + } + } + SECTION("TEST PDD RESIDUALS") { + auto variables = + std::make_shared(mesh); + auto residuals = + pipenetwork::linear_system::Residuals(mesh, variables, curves_info); + residuals.assemble_residual_pdd(); + auto res_vec = residuals.residual_vec(); + + SECTION("node demand head residual") { + REQUIRE(res_vec.coeff(5) == Approx(9.464e-03).epsilon(tolerance)); + REQUIRE(res_vec.coeff(7) == Approx(0).epsilon(tolerance)); + } } - // - // Check initialized residual vector - SECTION("Check initialized residual vector") { - // Initialize residual vector - - assembler->assemble_residual_vector_v2(); - std::shared_ptr residual_vec = assembler->residual_vec(); - std::cout << (*residual_vec) << std::endl; - // Check nodal balance residual - // REQUIRE(residual_vec->coeff(0) == Approx(100.002).epsilon(tolerance)); - // REQUIRE(residual_vec->coeff(1) == Approx(-9.998).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(0) == Approx(-0.00).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(1) == Approx(0.0).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(2) == Approx(-0.00).epsilon(tolerance)); - // Check headloss residual - REQUIRE(residual_vec->coeff(3) == - Approx(-0.99999999916924).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(4) == - Approx(-99.999999978347).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(5) == - Approx(-98.999999960916).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(6) == - Approx(-98.999999994002).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(7) == - Approx(-98.99999996752).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(8) == - Approx(0.000000078168179151258).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(9) == - Approx(0.000000039084089575629).epsilon(tolerance)); + + SECTION("TEST Jacobian") { + auto variables = + std::make_shared(mesh); + auto residuals = std::make_shared( + mesh, variables, curves_info); + residuals->assemble_residual(); + auto jacobian = pipenetwork::linear_system::Jacobian( + mesh, variables, residuals, curves_info); + + SECTION("jacobian test: DD mode") { + jacobian.update_jacobian(); + auto jac_matrix = jacobian.jac_matrix(); + // sub jacobian A: node_bal equation with respect to demand + REQUIRE(jac_matrix.coeff(0, 4) == -1); + REQUIRE(jac_matrix.coeff(1, 5) == -1); + REQUIRE(jac_matrix.coeff(2, 6) == -1); + REQUIRE(jac_matrix.coeff(3, 7) == -1); + // sub jacobian B: node_bal equation with respect to flow + REQUIRE(jac_matrix.coeff(3, 8) == -1); + REQUIRE(jac_matrix.coeff(0, 8) == 1); + REQUIRE(jac_matrix.coeff(0, 9) == -1); + REQUIRE(jac_matrix.coeff(1, 9) == 1); + REQUIRE(jac_matrix.coeff(0, 10) == -1); + REQUIRE(jac_matrix.coeff(2, 10) == 1); + REQUIRE(jac_matrix.coeff(1, 11) == -1); + REQUIRE(jac_matrix.coeff(2, 11) == 1); + // sub jacobian C: node_bal equation with respect to leak flow + REQUIRE(jac_matrix.coeff(0, 12) == 0); + REQUIRE(jac_matrix.coeff(1, 12) == -1); + REQUIRE(jac_matrix.coeff(2, 12) == 0); + REQUIRE(jac_matrix.coeff(3, 12) == 0); + // sub jacobian D: demand/head equation with respect to head + REQUIRE(jac_matrix.coeff(4, 0) == 0); + REQUIRE(jac_matrix.coeff(5, 1) == 0); + REQUIRE(jac_matrix.coeff(6, 2) == 0); + REQUIRE(jac_matrix.coeff(7, 3) == 1); + // sub jacobian E: demand/head equation with respect to flow + REQUIRE(jac_matrix.coeff(4, 4) == 1); + REQUIRE(jac_matrix.coeff(5, 5) == 1); + REQUIRE(jac_matrix.coeff(6, 6) == 1); + REQUIRE(jac_matrix.coeff(7, 7) == 0); + // sub jacobian F: headloss equation with respect to head + REQUIRE(jac_matrix.coeff(8, 3) == -1); + REQUIRE(jac_matrix.coeff(8, 0) == 1); + REQUIRE(jac_matrix.coeff(9, 0) == -1); + REQUIRE(jac_matrix.coeff(9, 1) == 1); + REQUIRE(jac_matrix.coeff(10, 0) == + 1000.0 * pipenetwork::G * pipenetwork::INIT_FLOWRATE); + REQUIRE(jac_matrix.coeff(10, 2) == + -1000.0 * pipenetwork::G * pipenetwork::INIT_FLOWRATE); + REQUIRE(jac_matrix.coeff(11, 1) == 0); + REQUIRE(jac_matrix.coeff(11, 2) == 1); + // sub jacobian G: headloss equation with respect to flow + REQUIRE(jac_matrix.coeff(8, 8) == + Approx(0.5932445506024201).epsilon(tolerance)); + REQUIRE(jac_matrix.coeff(9, 9) == + Approx(1.576675297968889).epsilon(tolerance)); + auto pump_jac = (elevations[0] - elevations[2]) * 1000 * pipenetwork::G; + REQUIRE(jac_matrix.coeff(10, 10) == Approx(pump_jac).epsilon(tolerance)); + REQUIRE(jac_matrix.coeff(11, 11) == 0); // PRV + // sub jacobian H: leak flow to flow + REQUIRE(jac_matrix.coeff(12, 0) == 0); + REQUIRE(jac_matrix.coeff(12, 1) == -1e-4); + // sub jacobian I: leak flow to leak flow + REQUIRE(jac_matrix.coeff(12, 12) == 1); + } + SECTION("jacobian test: PDD mode") { + jacobian.update_jacobian_pdd(); + auto jac_matrix = jacobian.jac_matrix(); + + // sub jacobian D: demand/head equation with respect to head + REQUIRE(jac_matrix.coeff(4, 0) == 0); + REQUIRE(jac_matrix.coeff(5, 1) == Approx(0).epsilon(tolerance)); + REQUIRE(jac_matrix.coeff(6, 2) == Approx(0).epsilon(tolerance)); + REQUIRE(jac_matrix.coeff(7, 3) == 1); + } } - // - // Check initialized Jacobian matrix - SECTION("Check initialized Jacobian matrix") { - - // Assemble Jacobian matrix - assembler->sim_assemble_variable_vector_v2(); - assembler->sim_assemble_jacobian_v2(); - - std::shared_ptr> jac = assembler->jac(); - - std::cout << (*jac) << std::endl; - - // // Check jacB (nodal discharge in nodal balance equation) - // for (int row = 0; row < nnodes; row++) { - // for (int col = nnodes; col < nnodes + nnodes; col++) { - // if ((col - nnodes) == row) { - // REQUIRE(jac->coeff(row, col) == -1); - // } else { - // REQUIRE(jac->coeff(row, col) == 0); - // } - // } - // } - // - // Check jacC (pipe discharge in nodal balance equation) - REQUIRE(jac->coeff(0, 4) == 1); - REQUIRE(jac->coeff(0, 5) == 1); - REQUIRE(jac->coeff(0, 8) == -1); - REQUIRE(jac->coeff(1, 6) == 1); - REQUIRE(jac->coeff(1, 9) == -1); - REQUIRE(jac->coeff(2, 7) == 1); - REQUIRE(jac->coeff(2, 8) == 1); - REQUIRE(jac->coeff(2, 9) == 1); - // - // Check jacD (nodal head in headloss equation) - REQUIRE(jac->coeff(4, 0) == -1); - REQUIRE(jac->coeff(5, 0) == -1); - REQUIRE(jac->coeff(6, 1) == -1); - REQUIRE(jac->coeff(7, 2) == -1); - REQUIRE(jac->coeff(8, 0) == 1); - REQUIRE(jac->coeff(8, 2) == -1); - REQUIRE(jac->coeff(9, 1) == 1); - REQUIRE(jac->coeff(9, 2) == -1); - // - // Check jacF (pipe discharge in headloss equation) - REQUIRE(jac->coeff(3, 3) == - Approx(-0.000001538573761089).epsilon(tolerance)); - REQUIRE(jac->coeff(4, 4) == - Approx(-0.00004010175932682).epsilon(tolerance)); - REQUIRE(jac->coeff(5, 5) == - Approx(-0.00007238373389406).epsilon(tolerance)); - REQUIRE(jac->coeff(6, 6) == - Approx(-0.00001110851163928).epsilon(tolerance)); - REQUIRE(jac->coeff(7, 7) == - Approx(-0.00006015263899023).epsilon(tolerance)); - REQUIRE(jac->coeff(8, 8) == Approx(-0.0001447674677881).epsilon(tolerance)); - REQUIRE(jac->coeff(9, 9) == - Approx(-0.00007238373389406).epsilon(tolerance)); + + SECTION("TEST Matrix Assembler") { + bool pdd_mode = false; + auto assembler = + std::make_shared( + mesh, curves_info, pdd_mode); + assembler->system_update(); + Eigen::VectorXd& var_vec = assembler->variable_vector(); + auto res_vec = assembler->residual_vector(); + auto jac_matrix = assembler->jac_matrix(); + SECTION("variable vector") { + REQUIRE(var_vec.size() == 13); + REQUIRE(var_vec[0] == Approx(216.408).epsilon(tolerance)); + REQUIRE(var_vec[5] == Approx(9.464e-03).epsilon(tolerance)); + REQUIRE(var_vec[10] == + Approx(pipenetwork::INIT_FLOWRATE).epsilon(tolerance)); + REQUIRE(var_vec[12] == Approx(0).epsilon(tolerance)); + } + SECTION("node balance residual") { + REQUIRE(res_vec.coeff(0) == Approx(-0.001).epsilon(tolerance)); + REQUIRE(res_vec.coeff(1) == Approx(-9.464e-03).epsilon(tolerance)); + REQUIRE(res_vec.coeff(5) == Approx(0).epsilon(tolerance)); + REQUIRE(res_vec.coeff(7) == Approx(0).epsilon(tolerance)); + REQUIRE(res_vec.coeff(8) == Approx(-88.3916796736).epsilon(tolerance)); + // pump headloss + double pump_res = 50 + (elevations[0] - elevations[2]) * + pipenetwork::INIT_FLOWRATE * pipenetwork::G * + 1000.0; + REQUIRE(res_vec.coeff(10) == Approx(pump_res).epsilon(tolerance)); + + // valve headloss + REQUIRE(res_vec.coeff(11) == Approx(-10).epsilon(tolerance)); + } + SECTION("jacobian test: DD mode") { + REQUIRE(jac_matrix.coeff(0, 4) == -1); + REQUIRE(jac_matrix.coeff(1, 5) == -1); + // sub jacobian A: node_bal equation with respect to demand + REQUIRE(jac_matrix.coeff(0, 4) == -1); + REQUIRE(jac_matrix.coeff(1, 5) == -1); + REQUIRE(jac_matrix.coeff(2, 6) == -1); + REQUIRE(jac_matrix.coeff(3, 7) == -1); + // sub jacobian B: node_bal equation with respect to flow + REQUIRE(jac_matrix.coeff(3, 8) == -1); + REQUIRE(jac_matrix.coeff(0, 8) == 1); + REQUIRE(jac_matrix.coeff(0, 9) == -1); + REQUIRE(jac_matrix.coeff(1, 9) == 1); + REQUIRE(jac_matrix.coeff(0, 10) == -1); + REQUIRE(jac_matrix.coeff(2, 10) == 1); + REQUIRE(jac_matrix.coeff(1, 11) == -1); + REQUIRE(jac_matrix.coeff(2, 11) == 1); + // sub jacobian C: node_bal equation with respect to leak flow + REQUIRE(jac_matrix.coeff(0, 12) == 0); + REQUIRE(jac_matrix.coeff(1, 12) == -1); + REQUIRE(jac_matrix.coeff(2, 12) == 0); + REQUIRE(jac_matrix.coeff(3, 12) == 0); + // sub jacobian D: demand/head equation with respect to head + REQUIRE(jac_matrix.coeff(4, 0) == 0); + REQUIRE(jac_matrix.coeff(5, 1) == 0); + REQUIRE(jac_matrix.coeff(6, 2) == 0); + REQUIRE(jac_matrix.coeff(7, 3) == 1); + // sub jacobian E: demand/head equation with respect to flow + REQUIRE(jac_matrix.coeff(4, 4) == 1); + REQUIRE(jac_matrix.coeff(5, 5) == 1); + REQUIRE(jac_matrix.coeff(6, 6) == 1); + REQUIRE(jac_matrix.coeff(7, 7) == 0); + // sub jacobian F: headloss equation with respect to head + REQUIRE(jac_matrix.coeff(8, 3) == -1); + REQUIRE(jac_matrix.coeff(8, 0) == 1); + REQUIRE(jac_matrix.coeff(9, 0) == -1); + REQUIRE(jac_matrix.coeff(9, 1) == 1); + REQUIRE(jac_matrix.coeff(10, 0) == + 1000.0 * pipenetwork::G * pipenetwork::INIT_FLOWRATE); + REQUIRE(jac_matrix.coeff(10, 2) == + -1000.0 * pipenetwork::G * pipenetwork::INIT_FLOWRATE); + REQUIRE(jac_matrix.coeff(11, 1) == 0); + REQUIRE(jac_matrix.coeff(11, 2) == 1); + // sub jacobian G: headloss equation with respect to flow + REQUIRE(jac_matrix.coeff(8, 8) == + Approx(0.5932445506024201).epsilon(tolerance)); + REQUIRE(jac_matrix.coeff(9, 9) == + Approx(1.576675297968889).epsilon(tolerance)); + auto pump_jac = (elevations[0] - elevations[2]) * 1000 * pipenetwork::G; + REQUIRE(jac_matrix.coeff(10, 10) == Approx(pump_jac).epsilon(tolerance)); + REQUIRE(jac_matrix.coeff(11, 11) == 0); // PRV + // sub jacobian H: leak flow to flow + REQUIRE(jac_matrix.coeff(12, 0) == 0); + REQUIRE(jac_matrix.coeff(12, 1) == -1e-4); + // sub jacobian I: leak flow to leak flow + REQUIRE(jac_matrix.coeff(12, 12) == 1); + } + SECTION("Test variable update") { + Eigen::VectorXd& var_vec_test = assembler->variable_vector(); + Eigen::VectorXd x_diff(var_vec_test.size()); + + x_diff.setOnes(); + var_vec_test -= x_diff; + auto updated_var_vec = assembler->variable_vector(); + REQUIRE(updated_var_vec[0] == Approx(216.408 - 1).epsilon(tolerance)); + REQUIRE(updated_var_vec[5] == Approx(9.464e-03 - 1).epsilon(tolerance)); + REQUIRE(updated_var_vec[10] == + Approx(pipenetwork::INIT_FLOWRATE - 1).epsilon(tolerance)); + REQUIRE(updated_var_vec[12] == Approx(0 - 1).epsilon(tolerance)); + + assembler->assemble_residual(); + auto updated_res_vec = assembler->residual_vector(); + REQUIRE(updated_res_vec.coeff(5) == Approx(-1).epsilon(tolerance)); + REQUIRE(updated_res_vec.coeff(7) == Approx(-1).epsilon(tolerance)); + + assembler->update_jacobian(); + auto updated_jac_matrix = assembler->jac_matrix(); + // sub jacobian G: headloss equation with respect to flow + REQUIRE(updated_jac_matrix.coeff(8, 8) == + Approx(213.2374859317).epsilon(tolerance)); + REQUIRE(updated_jac_matrix.coeff(11, 11) == 0); // PRV + // sub jacobian H: leak flow to flow + REQUIRE(updated_jac_matrix.coeff(12, 0) == 0); + REQUIRE(updated_jac_matrix.coeff(12, 1) == -1e-4); + + // REQUIRE(updated_res_vec.coeff(8) == + // Approx(-88.3916796736).epsilon(tolerance)); + } } -} +} \ No newline at end of file diff --git a/tests/matrix_assembler_test_full.cc b/tests/matrix_assembler_test_full.cc deleted file mode 100644 index ec1fc96..0000000 --- a/tests/matrix_assembler_test_full.cc +++ /dev/null @@ -1,252 +0,0 @@ -#include "catch.hpp" -#include - -#include "matrix_assembler.h" -#include "mesh.h" -#include "node.h" -#include "pipe.h" -#include "settings.h" - -// Check matrix_assembler class -TEST_CASE("MatrixAssembler is checked", "[MatrixAssembler]") { - // Tolerance - const double tolerance = 1.e-12; - - // Mesh index - const unsigned meshid = 102; - - // Creat a mesh - auto mesh = std::make_shared(meshid); - - // Nodal coordinates - // using example netwrok in Todini(2013) - const Eigen::Vector3d coords1(1.0, 3.0, 0.0); - const Eigen::Vector3d coords2(0.0, 2.0, 0.0); - const Eigen::Vector3d coords3(2.0, 2.0, 0.0); - const Eigen::Vector3d coords4(0.0, 0.0, 0.0); - const Eigen::Vector3d coords5(2.0, 0.0, 0.0); - std::vector coords = {coords1, coords2, coords3, coords4, - coords5}; - - // Create nodal pointers based on nodal coordinates in the mesh - mesh->create_nodes(coords); - - // Make pairs of nodes to create pipe - std::vector> node_pairs; - node_pairs.emplace_back(std::make_pair(0, 1)); - node_pairs.emplace_back(std::make_pair(0, 2)); - node_pairs.emplace_back(std::make_pair(1, 2)); - node_pairs.emplace_back(std::make_pair(1, 3)); - node_pairs.emplace_back(std::make_pair(1, 4)); - node_pairs.emplace_back(std::make_pair(2, 4)); - node_pairs.emplace_back(std::make_pair(3, 4)); - - // Input vector of pipe diameter, roughness and status - std::vector diameter{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7}; - std::vector roughness{ - 147683.36372579, 4102.7779645159, 1238.1607371737, 1598.5610759603, - 430.5609768094, 137.58891975265, 133.37351955511}; - std::vector status{true, true, true, true, true, true, true}; - - // Create pipes based on pipe indices and previous created node pointers in - // the mesh - bool all_pipe_created = - mesh->create_pipes(node_pairs, diameter, roughness, status); - - // Assign initial nodal head and discharge - double default_init_node_head = 0.0; - double default_init_node_discharge = 10; - double default_init_pipe_discharge = 0.001; - double head1 = 100.0; - double head2 = 99.0; - double discharge1 = 100.0; - double discharge2 = -10.0; - - // Initialize pipe discharge - mesh->initialize_pipe_discharge(default_init_pipe_discharge); - - std::vector> node_elevation; - node_elevation.emplace_back(std::make_pair(0, head1)); - node_elevation.emplace_back(std::make_pair(1, head2)); - std::vector> node_discharge; - node_discharge.emplace_back(std::make_pair(0, discharge1)); - node_discharge.emplace_back(std::make_pair(1, discharge2)); - mesh->assign_node_elevation(node_elevation); - mesh->assign_node_demand(node_discharge); - - SECTION("DD MODE") { - // Initialize matrix assembler and obtain global index to nodes and pipes - bool pdd_mode = false; - auto assembler = std::make_shared(pdd_mode); - assembler->global_nodal_pipe_indices(mesh); - - // Check the number of nodes and pipes in the network - unsigned nnodes = assembler->nnodes(); - unsigned npipes = assembler->npipes(); - REQUIRE(nnodes == 5); - REQUIRE(npipes == 7); - // Check initialized variable (head and discharge) vector - SECTION("Check initialized variable vector") { - // Initialize variable vector - assembler->assemble_variable_vector(); - std::shared_ptr variable_vec = assembler->variable_vec(); - // std::cout << (*variable_vec) << std::endl; - // Check nodal head - REQUIRE(variable_vec->coeff(0) == Approx(head1).epsilon(tolerance)); - REQUIRE(variable_vec->coeff(1) == Approx(head2).epsilon(tolerance)); - for (int i = 2; i <= 4; i++) - REQUIRE(variable_vec->coeff(i) == - Approx(default_init_node_head).epsilon(tolerance)); - // Check nodal discharge - REQUIRE(variable_vec->coeff(5) == Approx(discharge1).epsilon(tolerance)); - REQUIRE(variable_vec->coeff(6) == Approx(discharge2).epsilon(tolerance)); - for (int i = 7; i <= 9; i++) - REQUIRE(variable_vec->coeff(i) == - Approx(default_init_node_discharge).epsilon(tolerance)); - // Check pipe discharge - for (int i = 10; i <= 16; i++) - REQUIRE(variable_vec->coeff(i) == - Approx(default_init_pipe_discharge).epsilon(tolerance)); - } - - // Check initialized residual vector - SECTION("Check initialized residual vector") { - // Initialize residual vector - assembler->assemble_residual_vector(); - std::shared_ptr residual_vec = assembler->residual_vec(); - // std::cout << (*residual_vec) << std::endl; - // Check nodal balance residual - REQUIRE(residual_vec->coeff(0) == Approx(100.002).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(1) == Approx(-9.998).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(2) == Approx(-0.001).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(3) == Approx(0.0).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(4) == Approx(-0.003).epsilon(tolerance)); - // Check headloss residual - REQUIRE(residual_vec->coeff(5) == - Approx(-0.99999999916924).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(6) == - Approx(-99.999999978347).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(7) == - Approx(-98.999999960916).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(8) == - Approx(-98.999999994002).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(9) == - Approx(-98.99999996752).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(10) == - Approx(0.0000000781682).epsilon(tolerance)); - REQUIRE(residual_vec->coeff(11) == - Approx(0.0000000390841).epsilon(tolerance)); - } - // Check initialized Jacobian matrix - SECTION("Check initialized Jacobian matrix") { - - // Assemble Jacobian matrix - assembler->assemble_jacobian(); - std::shared_ptr> jac = assembler->jac(); - // std::cout << (*jac) << std::endl; - - // Check jacB (nodal discharge in nodal balance equation) - for (int row = 0; row < nnodes; row++) { - for (int col = nnodes; col < nnodes + nnodes; col++) { - if ((col - nnodes) == row) { - REQUIRE(jac->coeff(row, col) == -1); - } else { - REQUIRE(jac->coeff(row, col) == 0); - } - } - } - - // Check jacC (pipe discharge in nodal balance equation) - REQUIRE(jac->coeff(0, 10) == -1); - REQUIRE(jac->coeff(0, 11) == -1); - REQUIRE(jac->coeff(1, 10) == 1); - REQUIRE(jac->coeff(1, 12) == -1); - REQUIRE(jac->coeff(1, 13) == -1); - REQUIRE(jac->coeff(1, 14) == -1); - REQUIRE(jac->coeff(2, 11) == 1); - REQUIRE(jac->coeff(2, 12) == 1); - REQUIRE(jac->coeff(2, 15) == -1); - REQUIRE(jac->coeff(3, 13) == 1); - REQUIRE(jac->coeff(3, 16) == -1); - REQUIRE(jac->coeff(4, 14) == 1); - REQUIRE(jac->coeff(4, 15) == 1); - REQUIRE(jac->coeff(4, 16) == 1); - - // Check jacD (nodal head in headloss equation) - REQUIRE(jac->coeff(5, 0) == 1); - REQUIRE(jac->coeff(5, 1) == -1); - REQUIRE(jac->coeff(6, 0) == 1); - REQUIRE(jac->coeff(6, 2) == -1); - REQUIRE(jac->coeff(7, 1) == 1); - REQUIRE(jac->coeff(7, 2) == -1); - REQUIRE(jac->coeff(8, 1) == 1); - REQUIRE(jac->coeff(8, 3) == -1); - REQUIRE(jac->coeff(9, 1) == 1); - REQUIRE(jac->coeff(9, 4) == -1); - REQUIRE(jac->coeff(10, 2) == 1); - REQUIRE(jac->coeff(10, 4) == -1); - REQUIRE(jac->coeff(11, 3) == 1); - REQUIRE(jac->coeff(11, 4) == -1); - - // Check jacF (pipe discharge in headloss equation) - REQUIRE(jac->coeff(5, 10) == - Approx(-0.000001538573761089).epsilon(tolerance)); - REQUIRE(jac->coeff(6, 11) == - Approx(-0.00004010175932682).epsilon(tolerance)); - REQUIRE(jac->coeff(7, 12) == - Approx(-0.00007238373389406).epsilon(tolerance)); - REQUIRE(jac->coeff(8, 13) == - Approx(-0.00001110851163928).epsilon(tolerance)); - REQUIRE(jac->coeff(9, 14) == - Approx(-0.00006015263899023).epsilon(tolerance)); - REQUIRE(jac->coeff(10, 15) == - Approx(-0.0001447674677881).epsilon(tolerance)); - REQUIRE(jac->coeff(11, 16) == - Approx(-0.00007238373389406).epsilon(tolerance)); - REQUIRE(jac->coeff(13, 1) == Approx(1).epsilon(tolerance)); - } - } - - SECTION("PDD MODE") { - // Initialize matrix assembler and obtain global index to nodes and pipes - bool pdd_mode = true; - auto assembler = std::make_shared(pdd_mode); - - std::vector> node_head; - node_head.emplace_back(std::make_pair(0, 110)); - node_head.emplace_back(std::make_pair(1, 99)); - - mesh->assign_node_head(node_head); - assembler->global_nodal_pipe_indices(mesh); - - // Check the number of nodes and pipes in the network - unsigned nnodes = assembler->nnodes(); - unsigned npipes = assembler->npipes(); - assembler->assemble_variable_vector(); - std::shared_ptr variable_vec = assembler->variable_vec(); - std::cout << (*variable_vec) << std::endl; - // Check initialized residual vector - SECTION("Check initialized residual vector") { - // Initialize residual vector - assembler->assemble_residual_vector(); - std::shared_ptr residual_vec = assembler->residual_vec(); - std::cout << (*residual_vec) << std::endl; - // // Check pressure demand residual - double res = - -1 * (100 - 100 * std::pow((110.0 - 100 - 0) / (20 - 0), 0.5)); - REQUIRE(residual_vec->coeff(12) == Approx(res).epsilon(tolerance)); - } - // Check initialized Jacobian matrix - SECTION("Check initialized Jacobian matrix") { - - // Assemble Jacobian matrix - assembler->assemble_jacobian(); - std::shared_ptr> jac = assembler->jac(); - std::cout << (*jac) << std::endl; - - // Check jacG (demand equation) - double res = -1 * (0.5 * 100 * std::pow((10.0) / (20 - 0), -0.5)); - REQUIRE(jac->coeff(12, 0) == Approx(res).epsilon(tolerance)); - } - } -} \ No newline at end of file diff --git a/tests/mesh_test.cc b/tests/mesh_test.cc index 23d0971..3af17de 100644 --- a/tests/mesh_test.cc +++ b/tests/mesh_test.cc @@ -1,97 +1,190 @@ #include "catch.hpp" +#include "io.h" #include "mesh.h" -#include "node.h" -#include "pipe.h" -#include "settings.h" // Check mesh class TEST_CASE("Mesh is checked", "[Mesh]") { // Tolerance const double tolerance = 1.e-12; - // Mesh index - const unsigned meshid = 101; - - // Creat a mesh - auto mesh = std::make_unique(meshid); - - // Nodal coordinates - const Eigen::Vector3d coords1(0.0, 0.0, 0.0); - const Eigen::Vector3d coords2(2.0, 0.0, 0.0); - const Eigen::Vector3d coords3(1.0, 1.0, 0.0); - const Eigen::Vector3d coords4(0.0, 2.0, 0.0); - const Eigen::Vector3d coords5(2.0, 2.0, 0.0); - const Eigen::Vector3d coords6(3.0, 3.0, 0.0); - const Eigen::Vector3d coords7(3.0, 4.0, 0.0); - std::vector coords = {coords1, coords2, coords3, coords4, - coords5, coords6, coords7}; - - // Create nodal pointers based on nodal coordinates in the mesh - mesh->create_nodes(coords); - - // Make pairs of nodes to create pipe - std::vector> node_pairs; - node_pairs.emplace_back(std::make_pair(0, 2)); - node_pairs.emplace_back(std::make_pair(1, 2)); - node_pairs.emplace_back(std::make_pair(2, 3)); - node_pairs.emplace_back(std::make_pair(2, 4)); - - // Input vector of pipe diameter and status - std::vector diameter{1.1, 1.2, 1.3, 1.4}; - std::vector roughness{0.01, 0.01, 0.01, 0.01}; - std::vector status{true, true, true, true}; - - // Check mesh id - REQUIRE(mesh->id() == meshid); - - // Check the case in which exception is not thrown - SECTION("Check the case in which exception is not thrown") { - - // Create pipes based on pipe indices and previous created node pointers in - // the mesh - bool all_pipe_created = - mesh->create_pipes(node_pairs, diameter, roughness, status); - - // Check number of nodes before remove - REQUIRE(mesh->nnodes() == 7); - - // Remove isolated nodes from mesh - mesh->remove_unconnected_nodes(); - - // Check number of nodes after remove - REQUIRE(mesh->nnodes() == 5); - // Check number of pipes - REQUIRE(mesh->npipes() == 4); - // Check whether exception is thrown when creating pipe - REQUIRE(all_pipe_created == true); + // create junctions + std::vector junction_names{"1", "2", "3", "4", "5"}; + std::vector elevations{5, 4, 3, 2, 1}; + std::vector demands{1, 2, 3, 4, 5}; + std::vector leak_diameters{0, 0, 0, 0.2, 0.1}; + + std::vector junc_props; + for (int i = 0; i < elevations.size(); ++i) { + pipenetwork::JunctionProp junc_prop; + junc_prop.name = junction_names[i]; + junc_prop.elevation = elevations[i]; + junc_prop.demand = demands[i]; + junc_prop.leak_diameter = leak_diameters[i]; + junc_props.emplace_back(junc_prop); } - // Check the case in which exception is thrown - SECTION("Check the case in which exception is thrown") { - - // Make pairs of nodes which do not exist to create pipe - node_pairs.emplace_back(std::make_pair(2, 8)); - node_pairs.emplace_back(std::make_pair(8, 9)); - std::vector diameter{1.1, 1.2, 1.3, 1.4, 1.5, 1.6}; - std::vector roughness{0.01, 0.01, 0.01, 0.01, 0.01, 0.01}; - std::vector status{true, true, true, true, true, true}; - // Create pipes based on pipe indices and previous created node pointers in - // the mesh - bool all_pipe_created = - mesh->create_pipes(node_pairs, diameter, roughness, status); - - // Check number of nodes before remove - REQUIRE(mesh->nnodes() == 7); - - // Remove isolated nodes from mesh - mesh->remove_unconnected_nodes(); - - // Check number of nodes after remove - REQUIRE(mesh->nnodes() == 5); - // Check number of pipes - REQUIRE(mesh->npipes() == 4); - // Check whether exception is thrown when creating pipe - REQUIRE(all_pipe_created == false); + // Reservoirs + std::vector res_names{"6", "7"}; + std::vector heads{99, 100}; + + std::vector res_props; + for (int i = 0; i < res_names.size(); ++i) { + pipenetwork::ReservoirProp res_prop; + res_prop.name = res_names[i]; + res_prop.head = heads[i]; + res_props.emplace_back(res_prop); + } + + std::vector pipe_names{"1", "2", "3"}; + // 1<->2<->6; 4<->7 + + std::vector> node_names{ + std::make_pair("1", "2"), std::make_pair("2", "6"), + std::make_pair("4", "7")}; + const std::vector length{100, 200, 300}; + const std::vector diameter{3, 4, 5}; + const std::vector roughness{0.2, .6, .9}; + + std::vector pipe_props; + for (int i = 0; i < pipe_names.size(); ++i) { + pipenetwork::PipeProp pipe_prop; + pipe_prop.name = pipe_names[i]; + pipe_prop.length = length[i]; + pipe_prop.diameter = diameter[i]; + pipe_prop.roughness = roughness[i]; + pipe_prop.node1_name = node_names[i].first; + pipe_prop.node2_name = node_names[i].second; + pipe_props.emplace_back(pipe_prop); + } + + std::vector pump_props; + std::vector valve_props; + + for (int i = 0; i < 3; ++i) { + pipenetwork::PumpProp pump_prop; + pump_prop.name = "pump-" + std::to_string(i); + pump_props.emplace_back(pump_prop); + } + + SECTION("MeshNodes") { + auto mesh_nodes = pipenetwork::MeshNodes(junc_props, res_props); + // check junctions + REQUIRE(mesh_nodes.njunctions() == junc_props.size()); + // check reservoirs + REQUIRE(mesh_nodes.nreservoirs() == res_props.size()); + // check nodes + REQUIRE(mesh_nodes.nnodes() == (res_props.size() + junc_props.size())); + + // check get node + auto junc1 = mesh_nodes.get_node("1"); + REQUIRE(junc1->id() == 0); + + auto res1 = mesh_nodes.get_node("6"); + } + + SECTION("MeshLinks") { + auto mesh_nodes = pipenetwork::MeshNodes(junc_props, res_props); + auto mesh_links = + pipenetwork::MeshLinks(pipe_props, pump_props, valve_props, mesh_nodes); + + // check pipes + REQUIRE(mesh_links.npipes() == pipe_props.size()); + // check pumps + REQUIRE(mesh_links.npumps() == 0); + // check links + REQUIRE(mesh_links.nlinks() == pipe_props.size()); + } + + SECTION("Mesh") { + std::string mesh_name = "test_mesh"; + auto mesh = pipenetwork::Mesh(mesh_name); + mesh.create_nodes(junc_props, res_props); + mesh.create_links(pipe_props, pump_props, valve_props); + mesh.create_mesh_graph(); + // nodes + auto mesh_nodes = mesh.nodes(); + REQUIRE(mesh_nodes->njunctions() == junc_props.size()); + + // links + auto mesh_links = mesh.links(); + // check pipes + REQUIRE(mesh_links->npipes() == pipe_props.size()); + // check pumps + REQUIRE(mesh_links->npumps() == 0); + + // check leak node ids + auto leak_nids = mesh.leak_nids(); + REQUIRE(leak_nids.size() == 2); + REQUIRE(leak_nids[0] == 3); + REQUIRE(leak_nids[1] == 4); + + // graph + auto graph = mesh.mesh_graph(); + // Adjacency matrix + auto A = graph->adjacency_matrix(); + + REQUIRE(A.coeff(0, 1) == 1); + REQUIRE(A.coeff(1, 0) == 1); + REQUIRE(A.coeff(1, 5) == 1); + REQUIRE(A.coeff(5, 1) == 1); + REQUIRE(A.coeff(3, 6) == 1); + REQUIRE(A.coeff(6, 3) == 1); + REQUIRE(A.coeff(4, 4) == 0); + REQUIRE(A.coeff(2, 6) == 0); + + // Node to link map + auto n2l_map = graph->node2link_map(); + REQUIRE(n2l_map[0].size() == 1); + REQUIRE(n2l_map[1].size() == 2); + REQUIRE(n2l_map[2].size() == 0); + REQUIRE(n2l_map[3].size() == 1); + REQUIRE(n2l_map[4].size() == 0); + + // Node degrees + auto node_degrees = graph->ndegree(); + REQUIRE(node_degrees[0] == 1); + REQUIRE(node_degrees[1] == 2); + REQUIRE(node_degrees[2] == 0); + + // Bfs + auto connectivity_mask1 = graph->bfs(1); + REQUIRE(connectivity_mask1[0] == 1); + REQUIRE(connectivity_mask1[1] == 1); + REQUIRE(connectivity_mask1[5] == 1); + REQUIRE(connectivity_mask1[3] == 0); + REQUIRE(connectivity_mask1[6] == 0); + auto connectivity_mask3 = graph->bfs(3); + REQUIRE(connectivity_mask3[0] == 0); + REQUIRE(connectivity_mask3[1] == 0); + REQUIRE(connectivity_mask3[5] == 0); + REQUIRE(connectivity_mask3[3] == 1); + REQUIRE(connectivity_mask3[6] == 1); + + // isolated junctions + auto iso_juncs = mesh.iso_nodes(); + REQUIRE(iso_juncs.size() == 2); + REQUIRE(iso_juncs[0] == 2); + REQUIRE(iso_juncs[1] == 4); + + // isolated links + auto iso_links = mesh.iso_links(); + REQUIRE(iso_links.size() == 0); + } + + SECTION("Mesh from IO") { + auto IO = std::make_shared(); + IO->read_inp("../test_files/test_net.inp"); + std::string mesh_name = "test_mesh_inp"; + auto mesh = pipenetwork::Mesh(mesh_name); + mesh.create_nodes(IO->junction_properties(), IO->reservoir_properties()); + mesh.create_links(IO->pipe_properties(), IO->pump_properties(), + IO->valve_properties()); + mesh.create_mesh_graph(); + // mesh.print_summary(); + + REQUIRE(mesh.nodes()->njunctions() == 9); + REQUIRE(mesh.nodes()->nreservoirs() == 2); + REQUIRE(mesh.links()->npipes() == 8); } } diff --git a/tests/node_test.cc b/tests/node_test.cc index 614e5ac..a048728 100644 --- a/tests/node_test.cc +++ b/tests/node_test.cc @@ -1,65 +1,66 @@ #include "catch.hpp" #include +#include -#include "node.h" +#include "junction.h" +#include "reservoir.h" // Check node class TEST_CASE("Node is checked", "[Node]") { + using namespace pipenetwork; // Tolerance const double tolerance = 1.e-6; - // Index - unsigned id = 123; - // Coordinates - Eigen::Vector3d coords{11.2, 22.3, 33.4}; + SECTION("Check junction") { + // create junction + JunctionProp junction1; + junction1.name = "junc1"; + junction1.demand = 20; + junction1.leak_diameter = 5; - // Create a node - auto node = std::make_unique(id, coords); + Index id = 1; - // Check node id - REQUIRE(node->id() == id); + auto junction_node = std::make_shared(id, junction1); - // Check nodal coordinates - for (int i = 0; i < coords.size(); ++i) - REQUIRE(node->coordinates()(i) == Approx(coords(i)).epsilon(tolerance)); + // check id + REQUIRE(junction_node->id() == id); + // check leak hole area + REQUIRE(junction_node->leak_area() == + Approx(19.634954084936).epsilon(tolerance)); - // Check status of discharge before it is initialized - REQUIRE(node->isdischarge() == false); - - // Check hydraulic head at the node - SECTION("check hydraulic head at the node") { - // check PDD polynomial approximation - double elevation = 110.1; - node->elevation(elevation); - auto pdd_coeff1 = node->get_pdd_poly_coef_1(); - auto pdd_coeff2 = node->get_pdd_poly_coef_2(); + // check properties + auto prop = junction_node->property(); + // check name + REQUIRE(prop.name == junction1.name); + // check elevation + REQUIRE(prop.elevation == junction1.elevation); + // check demand + REQUIRE(prop.demand == junction1.demand); + } - REQUIRE(pdd_coeff1[0] == Approx(-18.75).epsilon(tolerance)); - REQUIRE(pdd_coeff1[1] == Approx(6.25).epsilon(tolerance)); - REQUIRE(pdd_coeff1[2] == Approx(1.00009e-12).epsilon(tolerance)); - REQUIRE(pdd_coeff1[3] == Approx(-3.88578e-17).epsilon(tolerance)); + SECTION("Check reservoir") { + // Index + Index res_id = 1; + // create reservoir + ReservoirProp res1; - REQUIRE(pdd_coeff2[0] == Approx(-0.624992).epsilon(tolerance)); - REQUIRE(pdd_coeff2[1] == Approx(37.2492).epsilon(tolerance)); - REQUIRE(pdd_coeff2[2] == Approx(-739.978).epsilon(tolerance)); - REQUIRE(pdd_coeff2[3] == Approx(4900.81).epsilon(tolerance)); + res1.name = "res1"; + res1.head = 10; - // Check nodal elevation - REQUIRE(node->elevation() == Approx(elevation).epsilon(tolerance)); - // Check if hydraulic head is assigned at the node - // REQUIRE(node->ishead() == true); - } + auto reservoir_node = + std::make_shared(res_id, res1); - // Check discharge at the node - SECTION("Check discharge at the node") { - double discharge = -23.4; - node->demand(discharge); + // check id + REQUIRE(reservoir_node->id() == res_id); + // check properties + auto prop = reservoir_node->property(); + // check name + REQUIRE(prop.name == res1.name); + // check elevation + REQUIRE(prop.head == res1.head); - // Check discharge at the node - REQUIRE(node->demand() == Approx(discharge).epsilon(tolerance)); - // Check if discharge is assigned at the node - REQUIRE(node->isdischarge() == true); + // reset head + reservoir_node->head(20); + REQUIRE(reservoir_node->head() == 20); } - - // TODO: test return nconnections } diff --git a/tests/pipe_test.cc b/tests/pipe_test.cc deleted file mode 100644 index 134e126..0000000 --- a/tests/pipe_test.cc +++ /dev/null @@ -1,144 +0,0 @@ -#include "catch.hpp" - -#include "node.h" -#include "pipe.h" -#include "settings.h" - -// Check pipe class -TEST_CASE("Pipe is checked", "[Pipe]") { - // Tolerance - const double tolerance = 1.e-12; - - // Node indices - const unsigned nodeid1 = 100; - const unsigned nodeid2 = 101; - - // Nodal coordinates - const Eigen::Vector3d coords1(10.0, 20.0, 30.0); - const Eigen::Vector3d coords2(11.1, 21.1, 31.1); - - // Creat an array of two node pointers with previous defined index and - // coordinates of the nodes - std::array, 2> nodes; - nodes.at(0) = std::make_shared(nodeid1, coords1); - nodes.at(1) = std::make_shared(nodeid2, coords2); - - // Pipe index - const unsigned pipeid = 201; - - // Dismeter of the pipe in m - const double diameter = 20.0; - - // Pipe roughness coefficient (for Hazen-Williams equation) - const double pipe_roughness = 100; - - // Pipe open status - bool status = true; - - // Creat pipes based on previous created node pointers - auto pipe1 = std::make_unique(pipeid, nodes, diameter, - pipe_roughness, status); - - // Pipe length - // To calculate length between two points in 3d space - // length = sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2)) - const double length = sqrt(3 * pow(1.1, 2)); - - // Check pipe id - REQUIRE(pipe1->id() == pipeid); - - // Check pipe length - REQUIRE(pipe1->length() == Approx(length).epsilon(tolerance)); - - // Check initialized discharge and return discharge - pipe1->initialize_discharge(); - REQUIRE(pipe1->discharge() == Approx(0.001).epsilon(tolerance)); - - // Check pipe open status - REQUIRE(pipe1->isopen() == true); - - // Check pipe broken status and initialized status - REQUIRE(pipe1->isbroken() == false); - - // Check radius, discharge, headloss, max flow velocity, pipe roughness and - // Darcy friction factor of the pipe - SECTION( - "Check radius, discharge, max flow velocity and Darcy friction factor of " - "the pipe") { - - // Maximum allowable flow velocity of the pipe in m/s - const double max_velocity = 100.0; - - // Creat pipes based on previous created node pointers - auto pipe2 = std::make_unique( - pipeid, nodes, diameter, pipe_roughness, status, max_velocity); - - // Initialize discharge in the pipe and check - const double init_discharge = 10.0; - pipe2->initialize_discharge(init_discharge); - REQUIRE(pipe2->discharge() == Approx(init_discharge).epsilon(tolerance)); - - // Maximum allowable discharge of the pipe in m3/s - // Calculated by max_discharge=M_PI*pow(radius,2)*max_velocity - const double max_discharge = M_PI * 1.e4; - - // Water head at two nodes in m - const double head1 = 110.0; - const double head2 = 100.0; - - // Pipe length - const double length = sqrt(3 * pow(1.1, 2)); - - // Gravity - const double gravity = 9.81; - - // Dimensionless Darcy friction factor (for Darcy-Weisbach equation) - const double darcy_friction = 0.1; - - // Assign defined variables to nodes and pipe - nodes.at(0)->head(head1); - nodes.at(1)->head(head2); - pipe2->darcy_friction(darcy_friction); - - // Check radius and max flow velocity of the pipe - REQUIRE(pipe2->max_discharge() == Approx(max_discharge).epsilon(tolerance)); - - // Check discharge and Darcy friction factor of the pipe using - // Darcy-Weisbach equation. Compared with hand calculation: - // discharge = sqrt{\frac{(110.0-100.0) \times \pi^2 \times 9.81 - // \times 20.0^5}{8.0 \times 0.1 \times squt{3 \times 1.1^2}}} - // = 45085.585688339 - pipe2->compute_discharge_darcy_weisbach(); - REQUIRE(pipe2->discharge() == Approx(45085.585688339).epsilon(tolerance)); - // Check headloss of the pipe using Darcy-Weisbach equation. - // Compared with hand calculation: - // headloss = \frac{8 \times sqrt{3 \times 1.1^2} \times 0.1 \times - // 45085.585688339^2}{pi^2 \times 9.81 \times 20.0^5} = 10.0 - pipe2->iter_discharge(45085.585688339); - pipe2->compute_headloss_darcy_weisbach(); - REQUIRE(pipe2->headloss() == Approx(10.0).epsilon(tolerance)); - - // Check discharge and pipe roughness coefficient of the pipe using - // Hazen-Williams equation. Compared with hand calculation: - // discharge = (\frac{(110.0-100) \times 100^1.852 \times 20.0^4.8704} - // {10.67 \times sqrt{3 \times 1.1^2}})^{\frac{1}{1.852}} - // = 179922.60192865 - pipe2->compute_discharge_hazen_williams(); - REQUIRE(pipe2->discharge() == Approx(179922.60192865).epsilon(tolerance)); - // Check headloss of the pipe using Hazen-Williams equation. - // Compared with hand calculation: - // Hand calculation: headloss = \frac{10.67 \times sqrt{3 \times 1.1^2} - // \times 179922.60192865^1.852}{100^1.852 \times 20.0^4.8704} = 10.0 - pipe2->iter_discharge(179922.60192865); - pipe2->compute_headloss_hazen_williams(); - REQUIRE(pipe2->headloss() == Approx(10.0).epsilon(tolerance)); - } - - // Check return pointer to const Node - SECTION("Check return pointer to const Node") { - - // Check return ids of the nodes - REQUIRE(pipe1->nodes().at(0)->id() == 100); - REQUIRE(pipe1->nodes().at(1)->id() == 101); - } -} diff --git a/tests/sim_pressure_test.cc b/tests/sim_pressure_test.cc new file mode 100644 index 0000000..5655803 --- /dev/null +++ b/tests/sim_pressure_test.cc @@ -0,0 +1,71 @@ +#include "catch.hpp" +#include "hydralic_sim.h" +#include + +using namespace std::chrono; +// Check matrix_assembler class +TEST_CASE("HydraulicSimulation pressure test", "[hydralic_sim]") { + + // Tolerance + const double tolerance = 1.e-6; + + SECTION("DD SIM TEST CASE 4: Large .INP FILE INPUT") { + bool pdd_mode = false; + bool debug = false; + std::string mesh_name = "ky7"; + std::string solver_name = "mkl_pardiso"; + auto sim = std::make_shared( + "../benchmarks/ky7.inp", mesh_name, pdd_mode, solver_name, debug); + auto start = high_resolution_clock::now(); + + sim->run_simulation(1e-8, 100); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop - start); + + // std::cout << duration.count() << std::endl; + REQUIRE(sim->sim_residual_norm() < tolerance); + } + SECTION("DD SIM TEST CASE 8: Broken .INP FILE INPUT (with pump and valves") { + bool pdd_mode = false; + bool debug = false; + std::string mesh_name = "broken_net"; + std::string solver_name = "mkl_pardiso"; + auto sim = std::make_shared( + "../test_files/test_net_broken.inp", mesh_name, pdd_mode, solver_name, + debug); + auto start = high_resolution_clock::now(); + + // REQUIRE(sim->run_simulation()); + sim->run_simulation(1e-8, 100); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop - start); + + // std::cout << duration.count() << std::endl; + REQUIRE(sim->sim_residual_norm() < tolerance); + } + SECTION("DD SIM TEST CASE 9: Large Synthetic Network") { + bool pdd_mode = false; + bool debug = false; + std::string solver_name = "mkl_pardiso"; + auto start = high_resolution_clock::now(); + auto sim = std::make_shared(100, pdd_mode, + solver_name, debug); + // REQUIRE(sim->run_simulation()); + sim->run_simulation(1e-8, 30); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop - start); + + // std::cout << duration.count() << std::endl; + REQUIRE(sim->sim_residual_norm() < tolerance); + } + + SECTION("PDD SIM TEST CASE 1: Large real case .INP FILE INPUT") { + bool pdd_mode = true; + bool debug = false; + std::string solver_name = "mkl_pardiso"; + auto sim = std::make_shared( + "../benchmarks/ky7.inp", "KY7_pdd", pdd_mode, solver_name, debug); + REQUIRE(sim->run_simulation(1e-8, 30)); + REQUIRE(sim->sim_residual_norm() < tolerance); + } +} diff --git a/tests/solver_test.cc b/tests/solver_test.cc new file mode 100644 index 0000000..158fd85 --- /dev/null +++ b/tests/solver_test.cc @@ -0,0 +1,147 @@ +#include "catch.hpp" + +#include "curves.h" +#include "factory.h" +//#include "input.h" +#include "matrix_assembler.h" +#include "solver.h" + +// Check solver class +TEST_CASE("Solver is checked", "[Solver]") { + + // Tolerance + const double tolerance = 1.e-8; + + // Mesh index + std::string meshid = "Matrix test mesh"; + + // Creat a mesh + auto mesh = std::make_shared(meshid); + + // Create a curves info object + auto curves_info = std::make_shared(); + + std::vector junction_ids{"10", "11", "12"}; + std::vector elevations{216.408, 216.408, 213.36}; + std::vector demands{0, 9.464e-03, 9.464e-03}; + std::vector leak_diameters{0, 0.1, 0}; + + std::vector junc_props; + for (int i = 0; i < elevations.size(); ++i) { + pipenetwork::JunctionProp junc_prop; + junc_prop.name = junction_ids[i]; + junc_prop.elevation = elevations[i]; + junc_prop.demand = demands[i]; + junc_prop.leak_diameter = leak_diameters[i]; + + junc_props.emplace_back(junc_prop); + } + + std::vector res_ids{"13"}; + std::vector heads{3.048e+02}; + + std::vector res_props; + for (int i = 0; i < res_ids.size(); ++i) { + pipenetwork::ReservoirProp res_prop; + res_prop.name = res_ids[i]; + res_prop.head = heads[i]; + + res_props.emplace_back(res_prop); + } + + std::vector pipe_ids{"10", "11"}; + std::vector> nodeids{ + std::make_pair("13", "10"), std::make_pair("10", "11")}; + const std::vector length{3209.5440000000003, 3209.5440000000003, + 1609.344, 1609.344}; + const std::vector diameter{0.5588, 0.4572, 0.35559999999999997, + 0.254}; + const std::vector roughness{100, 100, 100, 100}; + + std::vector pipe_props; + for (int i = 0; i < pipe_ids.size(); ++i) { + pipenetwork::PipeProp pipe_prop; + pipe_prop.name = pipe_ids[i]; + pipe_prop.length = length[i]; + pipe_prop.diameter = diameter[i]; + pipe_prop.roughness = roughness[i]; + pipe_prop.node1_name = nodeids[i].first; + pipe_prop.node2_name = nodeids[i].second; + + pipe_props.emplace_back(pipe_prop); + } + + std::vector pump_ids{"12"}; + std::vector> pump_nodeids{ + std::make_pair("10", "12")}; + + std::vector pump_props; + + for (int i = 0; i < pump_ids.size(); ++i) { + pipenetwork::PumpProp pump_prop; + pump_prop.name = pump_ids[i]; + pump_prop.type = pipenetwork::PumpType::POWERPUMP; + pump_prop.node1_name = pump_nodeids[i].first; + pump_prop.node2_name = pump_nodeids[i].second; + pump_props.emplace_back(pump_prop); + } + + std::vector valve_ids{"13"}; + std::vector> valve_nodeids{ + std::make_pair("11", "12")}; + + std::vector valve_props; + + for (int i = 0; i < valve_ids.size(); ++i) { + pipenetwork::ValveProp valve_prop; + valve_prop.name = valve_ids[i]; + valve_prop.type = pipenetwork::ValveType::PRVALVE; + valve_prop.status = pipenetwork::LinkStatus ::ACTIVE; + valve_prop.setting = 10; + valve_prop.node1_name = valve_nodeids[i].first; + valve_prop.node2_name = valve_nodeids[i].second; + + valve_props.emplace_back(valve_prop); + } + + mesh->create_nodes(junc_props, res_props); + mesh->create_links(pipe_props, pump_props, valve_props); + mesh->create_mesh_graph(); + + bool pdd_mode = false; + auto assembler = + std::make_shared( + mesh, curves_info, pdd_mode); + assembler->assemble_residual(); + assembler->update_jacobian(); + Eigen::VectorXd& var_vec = assembler->variable_vector(); + const Eigen::VectorXd& res_vec = assembler->residual_vector(); + const Eigen::SparseMatrix& jac_matrix = + assembler->jac_matrix(); + + SECTION("mkl pardiso solver") { + std::string solver_name = "mkl_pardiso"; + std::shared_ptr solve_ptr( + Factory::instance()->create( + solver_name)); + + solve_ptr->assembled_matrices(assembler); + auto x_diff = solve_ptr->solve(); + auto linear_sys_res = (jac_matrix * x_diff - res_vec).norm(); + + REQUIRE(linear_sys_res < tolerance); + } + + SECTION("Eigen LU solver") { + std::string solver_name = "LU"; + std::shared_ptr solve_ptr( + Factory::instance()->create( + solver_name)); + + solve_ptr->assembled_matrices(assembler); + auto x_diff = solve_ptr->solve(); + auto linear_sys_res = (jac_matrix * x_diff - res_vec).norm(); + + REQUIRE(linear_sys_res < tolerance); + } +} diff --git a/tests/todini_example_test.cc b/tests/todini_example_test.cc deleted file mode 100644 index 30d8f47..0000000 --- a/tests/todini_example_test.cc +++ /dev/null @@ -1,149 +0,0 @@ -#include "catch.hpp" - -#include "eigen_gmres.h" -#include "io.h" -#include "matrix_assembler.h" -#include "mesh.h" -#include "node.h" -#include "pipe.h" -#include "settings.h" - -// Test to solve example network in Todini(2013) -TEST_CASE("Example network is tested", "[NR method]") { - // Tolerance - const double tolerance = 1.e-6; - - // Mesh index - const unsigned meshid = 101; - - // Creat a mesh - auto mesh = std::make_shared(meshid); - - // Create a IO class object - auto IO = std::make_unique(); - - // Read node and pipe information from CSV files - bool read_network = IO->read_network("../benchmarks/todini_network_node.csv", - "../benchmarks/todini_network_pipe.csv"); - std::vector coords = IO->nodal_coordinates(); - std::vector> init_nodal_head = - IO->initial_nodal_head(); - std::vector> init_nodal_discharge = - IO->initial_nodal_discharge(); - std::vector> node_pairs = IO->node_pairs(); - std::vector diameter = IO->diameters(); - std::vector roughness = IO->roughness(); - std::vector status = IO->pipe_status(); - std::vector> init_pipe_discharge = - IO->initial_pipe_discharge(); - - double pipe_discharge_unknown = 10; - // Create nodal pointers based on nodal coordinates in the mesh - mesh->create_nodes(coords); - - // Create pipes based on pipe indices and previous created node pointers in - // the mesh - bool all_pipe_created = - mesh->create_pipes(node_pairs, diameter, roughness, status); - - // Initialize pipe discharge - mesh->initialize_pipe_discharge(pipe_discharge_unknown); - - // Assign initial nodal head and discharge - mesh->assign_node_elevation(init_nodal_head); - mesh->assign_node_demand(init_nodal_discharge); - - SECTION("DD mode test") { - // Initialize matrix assembler and obtain global index to nodes and pipes - bool pdd_mode = false; - auto assembler = std::make_shared(pdd_mode); - assembler->global_nodal_pipe_indices(mesh); - - // Assemble variable vector, residual vector and Jacobian - assembler->assemble_variable_vector(); - std::shared_ptr variable_vec = assembler->variable_vec(); - assembler->assemble_residual_vector(); - std::shared_ptr residual_vec = assembler->residual_vec(); - assembler->assemble_jacobian(); - std::shared_ptr> jac = assembler->jac(); - - // Creat a eigen gmres solver and solve - double gmres_tolerance = 1.e-12; - const unsigned max_iter = 5000; - auto solver = - std::make_shared(max_iter, gmres_tolerance); - solver->assembled_matrices(jac, variable_vec, residual_vec); - - unsigned niter = 30; - for (unsigned nr_iter = 0; nr_iter < niter; ++nr_iter) { - - bool issolved = solver->solve(); - assembler->apply_variables(); - assembler->assemble_residual_vector(); - assembler->assemble_jacobian(); - if (residual_vec->norm() < tolerance) { - std::cout << "niter = " << nr_iter << std::endl; - std::cout << "Jac = " << std::endl - << (*jac) << std::endl - << std::endl - << "residual = " << std::endl - << (*residual_vec) << std::endl - << std::endl - << "variable = " << std::endl - << (*variable_vec) << std::endl - << std::endl; - break; - } - } - REQUIRE(residual_vec->norm() == Approx(0.0).epsilon(tolerance)); - } - - SECTION("PD mode test") { - // Initialize matrix assembler and obtain global index to nodes and pipes - bool pdd_mode = true; - auto assembler = std::make_shared(pdd_mode); - assembler->global_nodal_pipe_indices(mesh); - - // Assemble variable vector, residual vector and Jacobian - assembler->assemble_variable_vector(); - std::shared_ptr variable_vec = assembler->variable_vec(); - assembler->assemble_residual_vector(); - std::shared_ptr residual_vec = assembler->residual_vec(); - assembler->assemble_jacobian(); - std::shared_ptr> jac = assembler->jac(); - - // Creat a eigen gmres solver and solve - double gmres_tolerance = 1.e-12; - const unsigned max_iter = 5000; - auto solver = - std::make_shared(max_iter, gmres_tolerance); - solver->assembled_matrices(jac, variable_vec, residual_vec); - - bool issolved = solver->solve(); - assembler->apply_variables(); - assembler->assemble_residual_vector(); - - unsigned niter = 30; - for (unsigned nr_iter = 0; nr_iter < niter; ++nr_iter) { - - bool issolved = solver->solve(); - assembler->apply_variables(); - assembler->assemble_residual_vector(); - assembler->assemble_jacobian(); - if (residual_vec->norm() < tolerance) { - std::cout << "niter = " << nr_iter << std::endl; - std::cout << "Jac = " << std::endl - << (*jac) << std::endl - << std::endl - << "residual = " << std::endl - << (*residual_vec) << std::endl - << std::endl - << "variable = " << std::endl - << (*variable_vec) << std::endl - << std::endl; - break; - } - } - REQUIRE(residual_vec->norm() == Approx(0.0).epsilon(tolerance)); - } -} diff --git a/tests/valve_graph_test.cc b/tests/valve_graph_test.cc new file mode 100644 index 0000000..a6fc3e6 --- /dev/null +++ b/tests/valve_graph_test.cc @@ -0,0 +1,260 @@ +#include "catch.hpp" + +#include "io.h" +#include "valve_graph.h" +#include + +// Check mesh class +TEST_CASE("Valve Graph is checked", "[Valve Graph]") { + // Tolerance + const double tolerance = 1.e-12; + + // create junctions + std::vector junction_names{"1", "2", "3", "4"}; + std::vector elevations{5, 4, 3, 2}; + std::vector demands{1, 2, 3, 4}; + std::vector leak_diameters{0, 0, 0, 0.2}; + + std::vector junc_props; + for (int i = 0; i < elevations.size(); ++i) { + pipenetwork::JunctionProp junc_prop; + junc_prop.name = junction_names[i]; + junc_prop.elevation = elevations[i]; + junc_prop.demand = demands[i]; + junc_prop.leak_diameter = leak_diameters[i]; + junc_props.emplace_back(junc_prop); + } + + std::vector res_props; + std::vector pipe_names{"p1", "p2", "p3", "p4"}; + + std::vector> node_names{ + std::make_pair("1", "2"), std::make_pair("2", "4"), + std::make_pair("2", "3"), std::make_pair("3", "4")}; + const std::vector length{100, 200, 300, 400}; + const std::vector diameter{3, 4, 5, 6}; + const std::vector roughness{0.2, .6, .9, 2}; + + std::vector pipe_props; + for (int i = 0; i < pipe_names.size(); ++i) { + pipenetwork::PipeProp pipe_prop; + pipe_prop.name = pipe_names[i]; + pipe_prop.length = length[i]; + pipe_prop.diameter = diameter[i]; + pipe_prop.roughness = roughness[i]; + pipe_prop.node1_name = node_names[i].first; + pipe_prop.node2_name = node_names[i].second; + pipe_props.emplace_back(pipe_prop); + } + + std::vector pump_props; + std::vector valve_props; + + std::vector iso_valve_props; + pipenetwork::isolation::ISOVProp v1_prop; + v1_prop.on_node = "1"; + v1_prop.on_pipe = "p1"; + v1_prop.name = "v1"; + iso_valve_props.emplace_back(v1_prop); + + pipenetwork::isolation::ISOVProp v2_prop; + v2_prop.on_node = "2"; + v2_prop.on_pipe = "p1"; + v2_prop.name = "v2"; + iso_valve_props.emplace_back(v2_prop); + // assume broken + + pipenetwork::isolation::ISOVProp v3_prop; + v3_prop.on_node = "2"; + v3_prop.on_pipe = "p3"; + v3_prop.name = "v3"; + iso_valve_props.emplace_back(v3_prop); + + pipenetwork::isolation::ISOVProp v4_prop; + v4_prop.on_node = "3"; + v4_prop.on_pipe = "p3"; + v4_prop.name = "v4"; + iso_valve_props.emplace_back(v4_prop); + + pipenetwork::isolation::ISOVProp v5_prop; + v5_prop.on_node = "4"; + v5_prop.on_pipe = "p4"; + v5_prop.name = "v5"; + iso_valve_props.emplace_back(v5_prop); + + auto mesh_nodes = + std::make_shared(junc_props, res_props); + auto mesh_links = std::make_shared( + pipe_props, pump_props, valve_props, *mesh_nodes); + auto valve_graph = + pipenetwork::ValveGraph(mesh_nodes, mesh_links, iso_valve_props); + + SECTION("CHECK The NODE PIPE MATRIX") { + auto node_pipe_matrix = valve_graph.node_pipe_mtx(); + REQUIRE(node_pipe_matrix.coeff(0, 0) == 1); + REQUIRE(node_pipe_matrix.coeff(1, 0) == 1); + REQUIRE(node_pipe_matrix.coeff(1, 1) == 1); + REQUIRE(node_pipe_matrix.coeff(3, 1) == 1); + REQUIRE(node_pipe_matrix.coeff(1, 2) == 1); + REQUIRE(node_pipe_matrix.coeff(2, 2) == 1); + REQUIRE(node_pipe_matrix.coeff(5, 2) == 0); + } + SECTION("CHECK The Valve Location Matrix") { + auto valve_loc_matrix = valve_graph.valve_loc_mtx(); + // std::cout << valve_loc_matrix << std::endl; + REQUIRE(valve_loc_matrix.coeff(0, 0) == 1); + REQUIRE(valve_loc_matrix.coeff(1, 0) == 1); + REQUIRE(valve_loc_matrix.coeff(1, 1) == 0); + REQUIRE(valve_loc_matrix.coeff(3, 1) == 0); + REQUIRE(valve_loc_matrix.coeff(1, 2) == 1); + REQUIRE(valve_loc_matrix.coeff(2, 2) == 1); + REQUIRE(valve_loc_matrix.coeff(3, 2) == 0); + REQUIRE(valve_loc_matrix.coeff(3, 3) == 1); + } + SECTION("CHECK isolation segment search algorithm") { + auto& initial_segments = valve_graph.segments(); + + auto nsegs = initial_segments.nsegs(); + REQUIRE(nsegs == 4); + + pipenetwork::Index pid = 0; + auto seg0 = initial_segments.pid2seg(pid); + + REQUIRE(seg0.pids.size() == 1); + REQUIRE(seg0.nids.size() == 0); + REQUIRE(seg0.vids.size() == 2); + + auto seg3 = initial_segments.pid2seg(3); + REQUIRE(seg3.pids.size() == 1); + REQUIRE(seg3.nids.size() == 1); + REQUIRE(seg3.vids.size() == 2); + } + SECTION("Check the Segment Valves Matrix") { + auto& initial_segments = valve_graph.segments(); + auto seg_valve_mtx = initial_segments.seg_valve_mtx(); + std::cout << seg_valve_mtx << std::endl; + REQUIRE(seg_valve_mtx.innerSize() == 4); + REQUIRE(seg_valve_mtx.outerSize() == 5); + + REQUIRE(seg_valve_mtx.coeff(0, 0) == 1); + REQUIRE(seg_valve_mtx.coeff(0, 1) == 1); + REQUIRE(seg_valve_mtx.coeff(0, 2) == 0); + REQUIRE(seg_valve_mtx.coeff(1, 0) == 0); + REQUIRE(seg_valve_mtx.coeff(1, 1) == 1); + REQUIRE(seg_valve_mtx.coeff(1, 2) == 1); + REQUIRE(seg_valve_mtx.coeff(1, 4) == 1); + REQUIRE(seg_valve_mtx.coeff(2, 0) == 0); + REQUIRE(seg_valve_mtx.coeff(2, 2) == 1); + REQUIRE(seg_valve_mtx.coeff(2, 3) == 1); + REQUIRE(seg_valve_mtx.coeff(3, 1) == 0); + REQUIRE(seg_valve_mtx.coeff(3, 3) == 1); + REQUIRE(seg_valve_mtx.coeff(3, 4) == 1); + + SECTION("Check the shrink matrix tool") { + std::vector rows_to_remove{0, 2}; + std::vector cols_to_remove{1, 3}; + auto shrinked_mtx = pipenetwork::isolation::IsoSegHelper::shrink_mtx( + seg_valve_mtx, rows_to_remove, cols_to_remove); + REQUIRE(shrinked_mtx.innerSize() == 2); + REQUIRE(shrinked_mtx.outerSize() == 3); + REQUIRE(shrinked_mtx.coeff(0, 0) == 0); + REQUIRE(shrinked_mtx.coeff(0, 1) == 1); + REQUIRE(shrinked_mtx.coeff(0, 2) == 1); + REQUIRE(shrinked_mtx.coeff(1, 0) == 0); + REQUIRE(shrinked_mtx.coeff(1, 1) == 0); + REQUIRE(shrinked_mtx.coeff(1, 2) == 1); + } + } + SECTION("Check the Segment Valves ADJ Matrix") { + auto& initial_segments = valve_graph.segments(); + auto seg_valve_adj_mtx = initial_segments.seg_valve_adj_mtx(); + // std::cout << seg_valve_adj_mtx << std::endl; + REQUIRE(seg_valve_adj_mtx.coeff(0, 0) == 0); + REQUIRE(seg_valve_adj_mtx.coeff(0, 1) == 1); + REQUIRE(seg_valve_adj_mtx.coeff(1, 0) == 1); + REQUIRE(seg_valve_adj_mtx.coeff(1, 1) == 0); + } + SECTION("Check components finding algorithm") { + auto& segments = valve_graph.segments(); + std::set iso_sid{1}; + auto components = segments.get_segment_components(iso_sid); + REQUIRE(components.size() == 3); + REQUIRE(components[0].size() == 1); + REQUIRE(components[1].size() == 1); + REQUIRE(components[2].size() == 2); + } + SECTION("Check merge segments by remove valves") { + auto& segments = valve_graph.segments(); + segments.merge_segments(1); + auto seg_valve_mtx = segments.seg_valve_mtx(); + std::cout << seg_valve_mtx << std::endl; + REQUIRE(seg_valve_mtx.innerSize() == 3); + REQUIRE(seg_valve_mtx.coeff(0, 0) == 1); + REQUIRE(seg_valve_mtx.coeff(0, 1) == 1); + REQUIRE(seg_valve_mtx.coeff(0, 2) == 1); + REQUIRE(seg_valve_mtx.coeff(0, 4) == 1); + REQUIRE(seg_valve_mtx.coeff(1, 0) == 0); + REQUIRE(seg_valve_mtx.coeff(1, 1) == 0); + REQUIRE(seg_valve_mtx.coeff(1, 2) == 1); + REQUIRE(seg_valve_mtx.coeff(1, 4) == 0); + REQUIRE(seg_valve_mtx.coeff(2, 0) == 0); + REQUIRE(seg_valve_mtx.coeff(2, 1) == 0); + REQUIRE(seg_valve_mtx.coeff(2, 2) == 0); + REQUIRE(seg_valve_mtx.coeff(2, 4) == 1); + + auto segment = segments.pid2seg(1); + REQUIRE(segment.sid == 0); + REQUIRE(segment.pids.size() == 2); + + SECTION("Check components finding algorithm after merging") { + std::set iso_sid{2}; + auto components = segments.get_segment_components(iso_sid); + REQUIRE(components.size() == 2); + REQUIRE(components[0].size() == 2); + REQUIRE(components[1].size() == 1); + } + SECTION("Continous failure case") { + segments.merge_segments(4); + auto seg_valve_mtx = segments.seg_valve_mtx(); + std::cout << seg_valve_mtx << std::endl; + REQUIRE(seg_valve_mtx.innerSize() == 2); + + auto seg_valve_adj_mtx = segments.seg_valve_adj_mtx(); + std::cout << seg_valve_adj_mtx << std::endl; + + auto components = segments.get_segment_components({1}); + REQUIRE(components.size() == 2); + REQUIRE(components[0].size() == 1); + REQUIRE(components[1].size() == 1); + } + } + + SECTION("Check wrappers in the valve graph class") { + valve_graph.initialize_iso_segs(); // reinitialize + REQUIRE(valve_graph.nsegs() == 4); + + auto seg0 = valve_graph.pname2segment("p1"); + REQUIRE(seg0.pids.size() == 1); + REQUIRE(seg0.nids.size() == 0); + REQUIRE(seg0.vids.size() == 2); + + auto seg_components_init = valve_graph.segment_components({"p1", "p2"}); + REQUIRE(seg_components_init.size() == 3); + + valve_graph.fail_valves({"v2", "v5"}); + REQUIRE(valve_graph.nsegs() == 2); + + auto seg_components_after = valve_graph.segment_components({"p1", "p2"}); + REQUIRE(seg_components_after.size() == 2); + + auto seg3 = valve_graph.pname2segment("p3"); + REQUIRE(seg3.pids.size() == 1); + REQUIRE(seg3.nids.size() == 0); + REQUIRE(seg3.vids.size() == 2); + + auto seg_union = valve_graph.pname2segment("p4"); + REQUIRE(seg_union.pids.size() == 3); + REQUIRE(seg_union.nids.size() == 3); + REQUIRE(seg_union.vids.size() == 3); + } +} \ No newline at end of file