pax_global_header00006660000000000000000000000064151736067250014526gustar00rootroot0000000000000052 comment=c764b404bb0c2430819092490fbe55787d63016d Sigmyne-SuperNOVAS-c764b40/000077500000000000000000000000001517360672500153775ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/.cproject000066400000000000000000000163261517360672500172210ustar00rootroot00000000000000 Sigmyne-SuperNOVAS-c764b40/.github/000077500000000000000000000000001517360672500167375ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/.github/FUNDING.yml000066400000000000000000000015241517360672500205560ustar00rootroot00000000000000# These are supported funding model platforms github: attipaci patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry polar: # Replace with a single Polar username buy_me_a_coffee: # Replace with a single Buy Me a Coffee username thanks_dev: # Replace with a single thanks.dev username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] Sigmyne-SuperNOVAS-c764b40/.github/dependabot.yml000066400000000000000000000007201517360672500215660ustar00rootroot00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" Sigmyne-SuperNOVAS-c764b40/.github/workflows/000077500000000000000000000000001517360672500207745ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/.github/workflows/analyze.yml000066400000000000000000000013751517360672500231700ustar00rootroot00000000000000name: Static Analysis permissions: contents: read pull-requests: write on: push: branches: - main paths: - 'src/**' - 'include/**' - 'Makefile' - '*.mk' - '.github/workflows/analyze.yml' pull_request: paths: - 'src/**' - 'include/**' - 'Makefile' - '*.mk' - '.github/workflows/analyze.yml' jobs: cppcheck: name: Check source code runs-on: ubuntu-latest env: CC: gcc steps: - uses: actions/checkout@v6 - name: install dependencies run: sudo apt-get install -y cppcheck - name: Run cppcheck on the C sources run: make -C src/c99 analyze - name: Run cppcheck on the C++ sources run: make -C src/cpp analyze Sigmyne-SuperNOVAS-c764b40/.github/workflows/build-cmake.yml000066400000000000000000000052731517360672500237030ustar00rootroot00000000000000name: CMake permissions: contents: read on: push: branches: - main paths: - "src/**" - "include/**" - "CMakeLists.txt" - "cmake/**" - ".github/workflows/build-cmake.yml" pull_request: paths: - "src/**" - "include/**" - "CMakeLists.txt" - "cmake/**" - ".github/workflows/build-cmake.yml" jobs: build: name: Build on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v6 - name: Configure CMake (Unix) run: cmake -B build -DENABLE_CPP=ON -DBUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=ON -DBUILD_BENCHMARK=ON - name: Build (Unix) if: runner.os != 'Windows' run: cmake --build build - name: Build (Windows) if: runner.os == 'Windows' run: cmake --build build --config Release - name: Install run: cmake --install build --prefix install - name: Check Installation (Unix) if: runner.os != 'Windows' run: | echo Installation contents: ls -la install/ - name: Check Installation (Windows) if: runner.os == 'Windows' run: | echo Installation contents: dir install build-freebsd: runs-on: ubuntu-latest name: Build on FreeBSD steps: - uses: actions/checkout@v6 - name: Build on FreeBSD uses: vmactions/freebsd-vm@v1 with: release: "14.0" usesh: true prepare: | pkg install -y cmake run: | echo Building on FreeBSD $(uname -m) cmake -B build cmake --build build cmake --install build --prefix install ls -la install/ build-doc: runs-on: ubuntu-latest name: Build Documentation (Ubuntu) steps: - uses: actions/checkout@v6 - name: Install doxygen run: sudo apt-get install doxygen - name: Build HTML documentation run: | cmake -B build -DENABLE_CPP=ON -DBUILD_DOC=ON cmake --build build - name: Install docs run: | cmake --install build --prefix install ls -la install/ # build-calceph: # runs-on: ubuntu-latest # name: Build with CALCEPH support (Ubuntu) # steps: # - uses: actions/checkout@v6 # # - name: Install libcalceph-dev # run: | # sudo apt-get update -q -y # sudo apt-get install -y libcalceph-dev # # - name: Build with CALCEPH support enabled # run: | # cmake -B build -DENABLE_CALCEPH=ON # cmake --build build Sigmyne-SuperNOVAS-c764b40/.github/workflows/build.yml000066400000000000000000000052051517360672500226200ustar00rootroot00000000000000name: Build permissions: contents: read pull-requests: write on: push: branches: - main paths: - 'src/**' - 'include/**' - 'tools/src/**' - 'Makefile' - '*.mk' - '.github/workflows/build.yml' pull_request: paths: - 'src/**' - 'include/**' - 'tools/src/**' - 'Makefile' - '*.mk' - '.github/workflows/build.yml' jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] include: - os: ubuntu-latest cc: gcc - os: macos-latest cc: clang env: CC: ${{ matrix.cc }} CFLAGS: -Os -Wall -Werror CSTANDARD: c99 WEXTRA: 1 FORTIFY: 3 steps: - uses: actions/checkout@v6 - name: Build static library run: make static - name: Build shared library run: make shared - name: Compile solsys plugins run: make solsys - name: Build examples run: make examples - name: Build benchmarks run: make -C benchmark build build-cpp: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] include: - os: ubuntu-latest cxx: g++ - os: macos-latest cxx: clang++ env: CXX: ${{ matrix.cxx }} CXXFLAGS: -Os -Wall -Werror WEXTRA: 1 FORTIFY: 3 steps: - uses: actions/checkout@v6 - name: Build static C++ library run: make static-cpp - name: Build shared C++ library run: make shared-cpp - name: Build C++ examples run: make -C examples/cpp # Reverse build not yet supported in ubuntu-latest # # reverse-build: # runs-on: ubuntu-latest # steps: # - uses: actions/checkout@v6 # - name: Reverse order build # run: make --shuffle=reverse # test-calceph: # name: Build with CALCEPH support # runs-on: ubuntu-latest # steps: # - uses: actions/checkout@v6 # # - name: Install dependencies # run: | # sudo apt-get update -q -y # sudo apt-get install -y libcalceph-dev # # - name: Build # env: # CALCEPH_SUPPORT: 1 # run: make solsys build-freebsd: runs-on: ubuntu-latest name: FreeBSD steps: - uses: actions/checkout@v6 - name: Build on FreeBSD uses: vmactions/freebsd-vm@v1 with: release: "14.0" prepare: | pkg install -y gmake run: | echo Building on FreeBSD $(uname -m) gmake static gmake shared Sigmyne-SuperNOVAS-c764b40/.github/workflows/dox.yml000066400000000000000000000070711517360672500223160ustar00rootroot00000000000000name: Documentation permissions: contents: write pull-requests: write on: release: types: [published] push: branches: - main paths: - 'doc/**' - 'resources/**' - 'src/**' - 'include/**' - 'Makefile' - '*.md' - '.github/workflows/dox.yml' pull_request: paths: - 'doc/**' - 'resources/**' - 'src/**' - 'include/**' - 'Makefile' - '*.md' - '.github/workflows/dox.yml' jobs: apidocs: name: Generate API documentation runs-on: ubuntu-latest env: CC: gcc steps: - name: install doxygen run: sudo apt-get install doxygen - uses: actions/checkout@v6 - name: Generate docs run: make dox site-update: name: Update github pages needs: apidocs if: github.repository_owner == 'Sigmyne' && (github.event_name == 'release' || github.event.pull_request.merged || contains(github.event.head_commit.message, 'site update')) runs-on: ubuntu-latest steps: - name: Checkout source uses: actions/checkout@v6 - name: Generate headless README run: make -C doc README.md - uses: mattnotmitt/doxygen-action@edge with: working-directory: 'doc/c99' additional-packages: font-roboto - uses: mattnotmitt/doxygen-action@edge with: working-directory: 'doc/cpp' additional-packages: font-roboto - name: Insert Google analytics tracker run: for file in doc/c*/html/*.html ; do sudo sed -i "/<\/head>/e cat resources/analytics.html" $file ; done - name: Checkout gh-pages uses: actions/checkout@v6 with: ref: 'gh-pages' path: site - name: Assert site/doc/ run: mkdir -p site/doc - name: Copy doc/ markdowns run: | rm doc/README.md mv doc/README-undecorated.md doc/README.md cp doc/*.md site/doc/ cp doc/cpp/*.md site/doc/ cp doc/c99/*.md site/doc/ - name: Copy CHANGELOG run: cp -a CHANGELOG.md site/doc/ - name: Copy Usage Guides run: cp -a USAGE-*.md site/doc/ - name: Copy API documentation run: | rm -rf site/doc/html cp -a doc/c99/html site/doc/ mkdir site/doc/html/cpp cp -a doc/cpp/html/* site/doc/html/cpp/ - name: Assert site/resources/ run: mkdir -p site/resources - name: Copy Figures run: cp -a resources/*.png resources/*.svg site/resources/ - name: Push to pages run: | cd site git config --global user.email "$GITHUB_JOB+github-actions[bot]@users.noreply.github.com" git config --global user.name "github-actions" git add -A git commit -m "[automated site update]" && git push || true changelog-update: name: Update CHANGELOG on github pages if: github.repository_owner == 'Sigmyne' && (github.event.pull_request.merged || contains(github.event.head_commit.message, 'changelog update')) runs-on: ubuntu-latest steps: - name: Checkout source uses: actions/checkout@v6 - name: Checkout gh-pages uses: actions/checkout@v6 with: ref: 'gh-pages' path: site - name: Assert site/doc/ run: mkdir -p site/doc - name: Copy CHANGELOG run: cp CHANGELOG.md site/doc/ - name: Push to pages run: | cd site git config --global user.email "$GITHUB_JOB+github-actions[bot]@users.noreply.github.com" git config --global user.name "github-actions" git add -A git commit -m "[automated site update]" && git push || true Sigmyne-SuperNOVAS-c764b40/.github/workflows/example.yml000066400000000000000000000013721517360672500231550ustar00rootroot00000000000000name: Example permissions: contents: read pull-requests: write on: push: branches: - main paths: - 'examples/**' - '.github/workflows/example.yml' pull_request: paths: - 'examples/**' - '.github/workflows/example.yml' jobs: build: name: Check examples runs-on: ubuntu-latest strategy: matrix: prog: [star, high-z, orbital, time, rise-set, moon] steps: - uses: actions/checkout@v6 - name: Compile example-${{ matrix.prog }}.c run: | gcc -c -Wall -Werror -Iinclude examples/c99/example-${{matrix.prog }}.c - name: Compile example-${{ matrix.prog }}.cpp run: | g++ -c -Wall -Werror -Iinclude examples/cpp/example-${{ matrix.prog }}.cpp Sigmyne-SuperNOVAS-c764b40/.github/workflows/indexnow.yml000066400000000000000000000005661517360672500233610ustar00rootroot00000000000000name: IndexNow permissions: contents: read pull-requests: write on: page_build jobs: indexnow: runs-on: ubuntu-latest steps: - name: IndexNow uses: bojieyang/indexnow-action@v2 with: sitemap-location: 'https://sigmyne.github.io/SuperNOVAS/sitemap.xml' key: ${{ secrets.INDEXNOW_KEY }} limit: 1000 Sigmyne-SuperNOVAS-c764b40/.github/workflows/install.yml000066400000000000000000000022441517360672500231670ustar00rootroot00000000000000name: Test install permissions: contents: read pull-requests: write on: push: branches: - main paths: - 'src/**' - 'include/**' - 'tools/src/**' - 'Makefile' - '*.mk' - '.github/workflows/install.yml' pull_request: paths: - 'src/**' - 'include/**' - 'tools/src/**' - 'Makefile' - '*.mk' - '.github/workflows/install.yml' jobs: install: name: Install on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: include: - os: ubuntu-latest cc: g++ - os: macos-latest cc: clang env: CC: ${{ matrix.cc }} ENABLE_CPP: 1 steps: - uses: actions/checkout@v6 - name: Install dependencies run: | if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then sudo apt-get update sudo apt-get install -y doxygen else brew upgrade brew install doxygen fi - name: Build distro run: make distro - name: Install to local prefix run: | make DESTDIR=$HOME/test-install install Sigmyne-SuperNOVAS-c764b40/.github/workflows/test.yml000066400000000000000000000053241517360672500225020ustar00rootroot00000000000000name: Test permissions: contents: read pull-requests: write on: push: branches: - main paths: - 'src/**' - 'include/**' - 'test/src/**' - 'test/reference/**' - 'Makefile' - '*.mk' - 'test/Makefile' - '.github/workflows/test.yml' pull_request: paths: - 'src/**' - 'include/**' - 'test/src/**' - 'test/reference/**' - 'Makefile' - '*.mk' - 'test/Makefile' - '.github/workflows/test.yml' jobs: test: name: Test and coverage runs-on: ubuntu-latest env: CC: gcc CXX: g++ CFLAGS: -O0 ENABLE_CPP: 1 steps: - uses: actions/checkout@v6 - name: install dependencies run: | sudo apt-get update -q -y sudo apt-get install -y lcov - name: Run regression tests run: make test - name: Generate test coverage run: make coverage - name: Upload coverage to Codecov.io uses: codecov/codecov-action@v6 continue-on-error: true with: fail_ci_if_error: false flags: unittests name: codecov token: ${{ secrets.CODECOV_TOKEN }} verbose: true - name: Upload coverage to Coveralls.io continue-on-error: true uses: coverallsapp/github-action@v2 test-linux: name: Linux ${{ matrix.arch }} runs-on: ubuntu-latest strategy: matrix: include: - arch: armv7 distro: ubuntu_latest - arch: aarch64 distro: ubuntu_latest - arch: riscv64 distro: ubuntu_latest - arch: s390x distro: ubuntu_latest - arch: ppc64le distro: ubuntu_latest steps: - uses: actions/checkout@v6 - uses: uraimo/run-on-arch-action@v3 name: Run regression tests with: arch: ${{ matrix.arch }} distro: ${{ matrix.distro }} install: | apt-get update -q -y apt-get install -q -y make gcc gfortran run: make test test-macos: name: Test on MacOS runs-on: macos-latest steps: - uses: actions/checkout@v6 - name: Build and test on macOS run: make test test-cmake: name: Test with CMake (Ubuntu) runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 # - name: Install libcalceph-dev # run: | # sudo apt-get update -q -y # sudo apt-get install -y libcalceph-dev - name: Build run: | cmake -B build -DENABLE_CPP=ON -DBUILD_TESTING=ON -DBUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=ON cmake --build build - name: Test run: ctest --test-dir build Sigmyne-SuperNOVAS-c764b40/.gitignore000066400000000000000000000004471517360672500173740ustar00rootroot00000000000000**/*.o **/*.a **/*.so **/*.d **/*.bin **/dep/** **/build/** **/obj/** **/bin/** **/sobj/** **/lib/** **/apidoc/** **/test/data/** **/*~ **/gmon.out site/** *.swp .pydevproject README-headless.md README-orig.md UsersGuide.md Doxyfile.local TODO VERSION RELEASE-HOWTO.md infer-out build/ Testing/ Sigmyne-SuperNOVAS-c764b40/.project000066400000000000000000000016731517360672500170550ustar00rootroot00000000000000 SuperNOVAS org.python.pydev.PyDevBuilder org.eclipse.cdt.managedbuilder.core.genmakebuilder clean, org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder full,incremental, org.eclipse.cdt.core.cnature org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature org.python.pydev.pythonNature org.eclipse.cdt.core.ccnature Sigmyne-SuperNOVAS-c764b40/.settings/000077500000000000000000000000001517360672500173155ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/.settings/language.settings.xml000066400000000000000000000022311517360672500234570ustar00rootroot00000000000000 Sigmyne-SuperNOVAS-c764b40/.settings/org.eclipse.cdt.core.prefs000066400000000000000000000404531517360672500242760ustar00rootroot00000000000000doxygen/doxygen_new_line_after_brief=true doxygen/doxygen_use_brief_tag=false doxygen/doxygen_use_javadoc_tags=true doxygen/doxygen_use_pre_tag=false doxygen/doxygen_use_structural_commands=false eclipse.preferences.version=1 environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/CALCEPH_SUPPORT/delimiter=\: environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/CALCEPH_SUPPORT/operation=append environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/CALCEPH_SUPPORT/value=1 environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/CSPICE_SUPPORT/delimiter=\: environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/CSPICE_SUPPORT/operation=append environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/CSPICE_SUPPORT/value=1 environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/append=true environment/project/cdt.managedbuild.toolchain.gnu.base.2126916097/appendContributed=true org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.cdt.core.formatter.alignment_for_assignment=16 org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80 org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16 org.eclipse.cdt.core.formatter.alignment_for_compact_if=16 org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=34 org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18 org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0 org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16 org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48 org.eclipse.cdt.core.formatter.alignment_for_expression_list=0 org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.cdt.core.formatter.alignment_for_lambda_expression=20 org.eclipse.cdt.core.formatter.alignment_for_member_access=0 org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16 org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16 org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_linkage_declaration=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.cdt.core.formatter.comment.line_up_line_comment_in_blocks_on_first_column=false org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1 org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true org.eclipse.cdt.core.formatter.comment_formatter_off_tag=@formatter\:off org.eclipse.cdt.core.formatter.comment_formatter_on_tag=@formatter\:on org.eclipse.cdt.core.formatter.compact_else_if=true org.eclipse.cdt.core.formatter.continuation_indentation=4 org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=4 org.eclipse.cdt.core.formatter.format_block_comment=true org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.cdt.core.formatter.format_header_comment=true org.eclipse.cdt.core.formatter.format_line_comment=true org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0 org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_linkage=false org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false org.eclipse.cdt.core.formatter.indent_empty_lines=false org.eclipse.cdt.core.formatter.indent_label_compare_to_statements=true org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=true org.eclipse.cdt.core.formatter.indentation.size=2 org.eclipse.cdt.core.formatter.insert_new_line_after_colon_in_constructor_initializer_list=insert org.eclipse.cdt.core.formatter.insert_new_line_after_label=do not insert org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=insert org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_structured_binding_name_list=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_lambda_return=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_structured_binding_name_list=do not insert org.eclipse.cdt.core.formatter.insert_space_after_pointer_in_declarator_list=do not insert org.eclipse.cdt.core.formatter.insert_space_after_pointer_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_structured_binding_name_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_structured_binding_name_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_lambda_return=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_linkage_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_structured_binding_name_list=insert org.eclipse.cdt.core.formatter.insert_space_before_pointer_in_declarator_list=insert org.eclipse.cdt.core.formatter.insert_space_before_pointer_in_method_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_before_ref_qualifier_in_structured_binding=do not insert org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.join_wrapped_lines=true org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.cdt.core.formatter.lineSplit=140 org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=false org.eclipse.cdt.core.formatter.tabulation.char=space org.eclipse.cdt.core.formatter.tabulation.size=2 org.eclipse.cdt.core.formatter.use_comment_formatter_tag=true org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false Sigmyne-SuperNOVAS-c764b40/.settings/org.eclipse.cdt.ui.prefs000066400000000000000000000001501517360672500237510ustar00rootroot00000000000000eclipse.preferences.version=1 formatter_profile=_K&R [small indent spaces] formatter_settings_version=1 Sigmyne-SuperNOVAS-c764b40/.settings/org.eclipse.core.resources.prefs000066400000000000000000000000671517360672500255330ustar00rootroot00000000000000eclipse.preferences.version=1 encoding/=UTF-8 Sigmyne-SuperNOVAS-c764b40/CHANGELOG.md000066400000000000000000002357361517360672500172300ustar00rootroot00000000000000# Changelog All notable changes to the [SuperNOVAS](https://github.com/Sigmyne/SuperNOVAS) library will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [1.6.0] - 2026-04-27 Feature release, introducing a proper C++ API for the first time, adding the self-contained semi-analytic ELP2000 / MPP02 model of the Moon, and bringing various other improvements. ### Fixed - #293: `geo_posvel()` applied TOD to ICRS conversions twice for airborne observers, resulting in imprecise observer coordinates relative to the geocenter. - #296: Possible buffer overflow in `novas_print_dms()`. (thanks to aleberti) - #305: `novas_geom_posvel()` returned velocities referenced to SSB, not to the observer. ### Added - #256: New C++11 API to wrap the C99 functions into a higher-level, easier to use, and object-oriented interface. (thanks to aleberti for helping with testing and debugging). - #256: New `novas_time_leap()` to simplify back calculating the leap seconds from a `novas_timespec` structure. - #281: Added a truncated version of semi-analytic ELP/MPP02 model of the Moon's position relative to the geocenter by Chapront & Francou (2003), using up to about 3400 terms, and reaching accuracies to the 1 arcsec / 1km level (or better for the present era). - #298: Added `cspice_clear_kernels()` to CSPICE plugin to close all kernels and free up the resources they use (thanks to aleberti) - #306: Added `novas_site_gcrs_posvel()` as a more precise alternative to `geo_posvel()` for Earth-bound observers, when polar wobble offsets are known. - Added `novas_enu_to_itrs()` and `novas_itrs_to_enu()` functions to help convert between local East-North-Up (ENU) coordinates and ITRS. ENU is a natural local Cartesian coordinate system of an observer at or near the Earth's surface. - Added `novas_diff_time_scale()` for obtaining time difference between two astrometric times in the specified timescale of choice. - Added `novas_timescale_offset()` for returning the time offset in two different timescale representations of a time instance. - Added `novas_icrs_to_sys()` and `novas_sys_to_icrs()` for more flexible conversion of equatorial vectors between ICRS/GCRS and other coordinate reference systems. ### Changed - #256: Changes to repo layout to accommodate C++ API _in addition to_ the base C99 API. - #306: `novas_make_frame()` now uses the new `novas_site_gcrs_posvel()` when calculating SSB-based observer location and velocity, in the GCRS, for Earth-based observers. - #306: `geo_posvel()` changed to return an error (-1) if used for a geodetic observer and debug mode is set to `NOVAS_DEBUG_EXTRA`, to warn that polar offsets are not included in the calculation. - #310: Change how CMake detects the need for linking against `libm`. - Use more precise matrix from Liu et al. (2011) for equatorial / galactic conversions. - Consolidated equatorial vector transformations, eliminating duplicated code. - CMake config updated to link libraries against dependent libraries with `PUBLIC` scope, and other configuration tweaks. - Improved and updated documentation. ## [1.5.1] - 2026-01-02 Bug fix release. ### Fixed - #270: `novas_print_dms()` gave incorrect representations of negative angles, whereby the negative sign was repeated in the minutes and seconds components also. - #272: `CMakeLists.txt` exported the `core` target by another name of `supernovas`, which messed up the CMake package dependencies and also __vcpkg__. Fixed by not renaming `core` target. - #275: Error in `novas_sep()` formula. (thanks to prookyon) - #276: Wrong eccentricity value in `novas_make_moon_orbit()`, resulting in errors up to a few degrees in the Moon's orbital modeling. (thanks to prookyon) ### Changed - #273: Removed `CLEAN_DIRECT_OUTPUT` from `CMakeLists.txt`. It's an option that is no longer needed or used (since 2009). - #273: Removed unnecessary `POSITION_INDEPENDENT_CODE` from `CMakeLists.txt`. (It's automatic for shared libraries.) - #273: Updated `README.md` CMake snippet for building against the `supernovas` package. - #276, #280: Improved Lunar orbital modeling in `novas_make_moon_orbit()`, by using the leading terms from the ELP/MPP02 model, for a typical accuracy at the 10 arcmin level for a day or so around the reference epoch of the orbital parameters. - #284: Changed `strcpy()` calls to the safer `strncpy()`. (thanks to ChooseAfferoGPL) - `novas_sep()` now uses the Vincenty formula for calculating distances on a sphere, which is accurate for all locations, unlike the law of cosines or the haversine formula used previously. - CMake: `cmake_minimum_required()` now includes current version upper bound of 4.2, in preparation to CMake 4.0 (see https://fedoraproject.org/wiki/Changes/CMake4.0 for more explanation). - Fix unclosed code blocks in Doxygen markup (causes errors in latest Doxygen). - CMake libraries (targets) built with transitive dependencies. ## [1.5.0] - 2025-10-29 Feature release. Some new functions, enhanced precision, improved portability (including Windows and Android), C++ compatibility, and documentation. ### Fixed - #259: Fix `novas_track_pos()` tracking across / near the poles. - `NOVAS_JD_B1900` definition was MJD date instead of JD date. - Fix the length of a Besselian year (used for parsing Besselian epochs). - `gcrs2equ()`: propagate error if converting to TOD and the `accuracy` is invalid. - `NOVAS_VERSION_STRING` definition in `novas.h`. - Pedantic `enum` type casting for function parameters and enums, to improve C++ compatibility. - Small fixes to error tracing in `frames.c`. ### Added - #209: Added `novas_gmst()` and `novas_gast()` functions to calculate Greenwich Mean and Apparent (respectively) Sidereal Times for a given UT1 date. The new functions are meant to provide a cleaner, simpler alternative the old NOVAS C `sidereal_time()`. - #215: New functions `novas_diurnal_eop()`, `novas_diurnal_ocean_tides()` and `novas_diurnal_libration()` to calculate corrections to the Earth orientation parameters published by IERS, to include the effect of libration and ocean tides. Such corrections are necessary if needing or using ITRS / TIRS coordinates with accuracy below the milli-arcsecond (mas) level. - #217: New functions `novas_itrf_transform()` and `novas_itrf_transform_eop()` to enable transforming gecocentric _xyz_ station coordinates, or Earth orientation parameters (EOP), between different ITRF realizations (e.g. ITRF2000 to ITRF2014). The implementation is based on Chapter 4 of the IERS Conventions 2010. - #217: New functions `novas_geodetic_to_cartesian()` and `novas_cartesian_to_geodetic()` to convert between geocentric _xyz_ station coordinates and geodetic (longitude, latitude, altitude) coordinates on the reference ellipsoid of choice, and vice versa. The latter function is adapted from the IERS `GCONV2.F` routine. - #221: Now supporting Mac OS X builds, which are different from the standard UNIX build, via GNU `make` also (in collaboration with kiranshila). - #222: CMake build support, e.g for Mac OS X or Windows builds also, with further tweaks in #228, #229, #230, #234, #235... (in collaboration with kiranshila). - #223: New functions `novas_clock_skew()` / `novas_mean_clock_skew()` to calculate the instantaneous or averaged (for Earth-bound observers) incremental rate, respectively, at which an observer's clock ticks faster than an astronomical timescale. All reference timescales, except UT1, are supported (see also #232 and #233). - #239: New step-by-step approach to populate astrometric data for catalog sources, complementing the one-step `make_cat_entry()`. Start with `novas_init_cat_entry()` specifying the name and the R.A. / Dec coordinates, and then add more information as needed: set radial velocities with `novas_set_ssb_vel()` / `novas_set_lsr_vel()` / `novas_set_redshift()`; set parallax or distance (if any) with `novas_set_parallax()` or `novas_set_distance()`; set proper motion (if any) with `novas_set_proper_motion()`; or add catalog information with `novas_set_catalog()`. - #243: Added `novas_set_current_time()` to set astrometric time based on the current system clock UNIX time. The new function makes a common use case more accessible, but you should make sure the system clock is well synchronized to a time reference (preferably a local one) for accuracy. - #244: Added `novas_set_str_time()` for convenience. It is the same as using `novas_parse_date()` followed by `novas_set_time()` with error propagation in-between. - #245: New `make_itrf_site()`, `make_gps_site()`, `make_xyz_site()`, `make_itrf_observer()`, `make_gps_observer()`, `make_observer_at_site()` to facilitate the creation of sites / observers with GPS, ITRF or geocentric Cartesian (_xyz_) site coordinates. All of the above will also initialize default weather parameters for the location, based on simple global models of pressure scale height, annualized mean temperatures, and typical humidity values for the altitude. - #245: New `novas_set_default_weather()` to initialize default weather parameters for the location, based on simple global models of pressure scale height, annualized mean temperatures, and typical humidity values for the altitude. - #246: New `novas_geodetic_transform_site()` and `novas_itrf_transform_site()` convenience functions to make it simpler to change the reference ellipsoid or the ITRF realization of an `on_surface` data structure, respectively. ### Removed - #250: No longer including `CIO_RA.TXT` (now unused) in the distribution. - #252: Some build configuration options have been removed, such as the GNU make `BUILTIN_SOLSYS1`, `BUILTIN_SOLSYS2`, `BUILTIN_SOLSYS3`, `BUILTIN_SOLSYS_EPHEM`, `DEFAULT_SOLSYS`, and `DEFAULT_READEPH` configuration options, or the CMake `BUILD_SOLSYS1` / `BUILD_SOLSYS2` options. ### Changed - #208: `cio_location()` now always returns the CIO's right ascension relative to the true equinox of date (on the same true equator of date). - #209: `novas_make_frame()` calculates `gst` and `gcrs_to_cirs` fields faster, using the already available frame quantities and thus eliminating duplicate calculations. - #210: Speed up `iau2000a()` and `iau2000b()` nutations by restricting the range of multiples that are iterated over. - #212: Speed up `ee_ct()` by restricting the range of multiples that are iterated over. Also reduced accuracy now uses the same series, only with fewer terms. - #213: Rename a couple of source modules (`system.c` to `transform.c`, and `coords.c` to `system.c`). - #214: Reworked GCRS-CIRS transforms without `cio_basis()` (IERS method 2). - #217: Changed `terra()` to use GRS80 reference ellipsoid insread of the IERS 2003 ellipsoid. ITRF uses the GRS80 ellipsoid. The change restores the original NOVAS C behaviour. - #221: GitHub Actions CI now includes `Makefile` builds and tests for Mac OS X. (by kiranshila) - #222: GitHub Actions CI now checks CMake build, for Linux, Mac OS X, FreeBSD, and Windows. (by kiranshila) - #225: GNU `Makefile` fixes for non-Linux builds, and FreeBSD build check in GitHub Actions CI. - #231: The source code (including tests and examples) now uses platform-dependent file separator for improved portability to Windows. - #231: Changed documentation build to wean off the likes of `sed` or `tail`, thus allowing to build documentation in a more platform-independent way. - #237: Both CMake and GNU make now install more developer docs into `$(docdir)/supernovas`, such as `examples/`, `legacy/`, source code, and markdown files. - #241: Overhauled document generation. Non-GitHub markdown files are now in `doc/`, which has its own `Makefile` and CMake sub-configuration. - #242: README edits and collapsible sections, as well as Github style highlighting of notes, warnings etc. - #249: Option to exclude deprecated API from `novas.h` definitions for your application. Simply compile your application with `-D_EXCLUDE_DEPRECATED` or else define `_EXCLUDE_DEPRECATED` in your source _before_ including `novas.h`. - #250: `cio_array()` is changed to calculate CIO locations vs GCRS on the fly. With the change SuperNOVAS does not use a CIO locator data file any more, for any purpose. The change also ensures complete internal consistency with the implemented standards, such as the precession-nutation model. - #251: Added further CI checks via Github Actions. - #252: Overhauled how legacy `solarsystem()` / `solarsystem_hp()` and `readeph()` functions can be added to the build if needed, e.g. via externally provided sources at build time. If a `solarsystem()` / `solarsystem_hp()` module is not explicitly defined for the build, `solsys3.c` will provide a default implementation for these. (No more undefined symbols that need to be resolved at runtime.) - #255: More platform-independent code, by eliminating some UNIX specific calls. Windows builds with the Microsoft Visual C compiler are now possible also (with CMake). - #263: Use pthread mutexes instead of POSIX semaphores to provide thread-safe access to CALCEPH / CSPICE ephemeris data. POSIX semaphores are not supported on Windows and MacOS, whereas pthread is available on all (via wrapper library on Windows -- something that CMake is aware of). - #264: The likes of `novas_set_time()` and full accuracy `novas_make_frame()` will automatically apply diurnal corrections for libration and ocean tides to the input EOP values. As such, users should supply mean (interpolated) UT1-UTC time differences and _x_p, _y_p pole offsets, e.g. directly from the IERS Bulletins. - #264: `novas_timespec` now stores the TT-TDB conversion to the full (100 ns) precision. It's slightly slower than the less precise original NOVAS `tdb2tt()`, but it's worth it not having to worry about the precision. - #265: CALCEPH and CSPICE plugins to use portable mutex code. - #266: Add caching to `tt2tdb_hp()` and `novas_moon_phase()` functions. - Both CMake and GNU make now install only the headers for the components that were built. E.g. `novas-calceph.h` is installed only if the library is built with the CALCEPH support option enabled. - Renamed `equinox.c` to `equator.c`, since the functions therein concern the equator of date more than the equinox of date specifically. - Moved a few functions around among the source modules to make the organization more consistent. It also helps when browsing the HTML documentation topically by source modules. - `solarsystem.h` is moved to `legacy` with non-legacy definitions and prototypes migrated to `novas.h`. This has no downstream effect as all content of `solarsystem.h` was already included in `novas.h`, and it relied on definitions in `novas.h`, s.t. it could not be included prior to `novas.h` anyway. Effectively it has always been an integral part of `novas.h` even if it was a separate file before. - Fully revised API and user documentation. The HTML API docs now have automatic brief descriptions when listed (except for the deprecated entitites, which do not). ### Deprecated - #208: Deprecated `cio_array()` and `cio_location()`. Going forward, SuperNOVAS no longer uses the CIO locator data files (`CIO_RA.TXT` or `cio_ra.bin`) internally, and so `cio_location()` becomes redundant with `cio_ra()` and also with `ira_equinox()` (which returns the negative of the same value). - #209: Deprecated `sidereal_time()`. It is messy and one of its arguments (`erot`) is now unused. Instead, you should use `novas_gmst()` or `novas_gast()` to get the same results simpler. - #214: Deprecated `cio_basis()`. It is no longer used internally by the library, and users are recommended against using it themselves, since SuperNOVAS provides cleaner ways to convert between GCRS and CIRS using frames and transforms, or else via the `gcrs_to_cirs()` / `cirs_to_gcrs()` functions. - #245: Deprecated `make_on_surface()`, `make_observer_on_surface()`, and `make_observer()` functions. The first two did not disambiguate between GPS and ITRF locations, and also required to set some weather parameters, while did not set humidity. There are a new set of functions (see further above) which provide more flexibility. And, `make_observer()` no longer supports all SuperNOVAS observer types, hence it's less relevant now than the targeted set of SuperNOVAS functions available for every type of observer. - #250: Deprecated `set_cio_locator_file()`. It has no function any more, and does exactly nothing beyond providing API compatibility. - Deprecated the functions in `solsys2.c`. This NOVAS C module is half-baked at best, requiring a custom Fortran interface to the PLEPH library. You probably should stay away from it for your own good, and use instead the provided CALCEPH or CSPICE plugins for a more up-to-date and modern JPL ephemeris support. - Deprecated the internal variables and functions of `eph_manager.c`. They should never have been exposed to users in the first place. The definitions can also be hidden from `eph_manager.h` by setting `-D_EXCLUDE_DEPRECATED` compiler flag, or adding `#define _EXCLUDE_DEPRECATED` in your application source code _before_ including `eph_manager.h`. - Deprecated the functions of `solsys1.c` and `eph_manager.c`. These provide built-in support for older JPL planetary ephemerides DE200 -- DE405 only. Given its lack of support for more recent ephemeris data, users should probably stay away from this NOVAS C legacy module, and instead opt for one the built-in CALCEPH and/or CSPICE plugins to allow accessing a wider variety, and more up-to-date, ephemeris data -- with a lot more flexibility also. - Moved `nutation.h` to `legacy/`. Its functions are now integral to `novas.h` instead. It is unlikely that any one would use it as a separate header, and not via `novas.h`. But, in case someone does want it, they can find it it the installation folder of the `supernovas` documentation, under the `legacy/` folder. ## [1.4.2] - 2025-08-25 Bug fix release with updated nutation models. ### Fixed - #201: By default expect to find the CIO locator file (`CIO_RA.TXT` or `cio_ra.bin`) in its install location, e.g. in `/usr/share/supernovas` or as set via the `datadir` or `prefix` install locations. - #202: The P03 recommended rescaling of the original IAU2000A nutation model to IAU2006 (see Coppola, Seago, and Vallado 2009) was not correctly implemented in the prior 1.4 releases. The resulting errors are around or below 40 μas for the present era, and slightly larger than the model discrepancies (~10 μas) that the rescaling was meant to address. ### Changed - #206: Updated nutation models: `iau2000a()` now uses IAU2000A R06 model coefficients (see https://hpiers.obspm.fr/eop-pc/models/nutations/nut.html), making it dynamically consistent with the IAU2006 (P03) precession model, which was already implemented by NOVAS and SuperNOVAS. `iau2000b()` is now a truncated version of the above, keeping terms with amplitude <100 μas, resulting in similar number of terms and precision as the original IAU2000B model. And, `nu2000k()` has been rescaled according to Coppola, Seago, & Vallado (2009) to also bring it in line with the IAU2006 (P03) precession model. - `make benchmark` now uses any user-defined `CPPFLAGS`, automatically adding the `include/` directory to it. ## [1.4.1] - 2025-07-21 Bug fix release. ### Fixed - #197: Fix reverse target order builds via `make --shuffle=reverse`, which could also fail parallel builds in some cases. See also Debian Bug Tracker [#1105702](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1105702). ### Changed - #199: Fixed typos in `README.md.` (by Asininite) - Various improvements to documentation. ## [1.4.0] - 2025-06-02 Feature release, with critical bug fixes. ### Fixed - #188: Critical bug in `novas_make_transform()` since inception in v1.1. Compound transforms were calculated using matrix products in the wrong commutation order (successive transforms were multiplied from the right instead of from the left). Very embarrasing indeed, and somehow it went unnoticed with the testing suite also (even more embarrassing...). - #183: IERS Earth orientation corrections set via `cel_pole()` were not taken into account for true obliquity and the equation of equinoxes in `e_tilt()`. This was a bug since v1.0. The bug only affected the old (pre IAU 2006) ways of incorporating polar offsets into TOD coordinates, at the sub-arcsec level. Note, than even with the old method, it is now preferrable to apply such offsets with `wobble()` for the PEF / TIRS to ITRS (and reverse) conversions instead. - #184: The frame based approach introduced in v1.1 has ommitted applying polar wobble corrections for transforming between the TIRS) / PEF and ITRS, and vice versa. This resulted in an error at the sub-arcsec level for celestial to ITRS / horizontal (or reverse) calculations, when IERS Earth orientation parameters were explicitly set. - #187: The NOVAS C 3.1 implementation of `cel2ter()` / `ter2cel()` was such that if both `xp` and `yp` parameters were zero, then no wobble correction was applied, not even for the TIO location (s') when converting between CIRS and ITRS. The error from this omission is very small, at just a few μas (micro-acrseconds) within a couple of centuries of J2000. - #190: Reverse `wobble()` (ITRS to TIRS/PEF) had wrong 2nd order corrections, resulting in negligible errors below 0.1 μas (micro-arcseconds) typically. - #193: C++ namespace conflict in `novas_frame` declaration. Fixed by declaring and using named structure types instead of the conflicting `typedef` aliases. ### Added - #172: Added `novas_time_gst()` and `novas_time_lst()` convenience functions to calculate the Greenwich (apparent) Sidereal Time (GST / GaST) and Local (apparent) Sidereal Time (LST / LaST) for a given astrometric time (and observer location) more easily. - #173: Added our own implementation of the wavelength-dependent IAU refraction model as `novas_wave_refraction()`, which is based on the SOFA `iauRefco()` function. The wavelength for which the refraction is calculated can be set by `novas_refract_wavelength()`. By default 550 nm (0.55 μm) is assumed. - #176: `novas_make_planet_orbit()` to generate Keplerian orbital elements for the major planets (sans Earth), and the Earth-Moon Barycenter (EMB), based on Standish & Williams 1992. In most cases such orbitals can provide arcmin-level precisions, especially for current dates. - #176:`novas_make_moon_orbit()` to generate geocentric Keplerian orbital elements for the Moon using the Chapront et al. 2002 model. - #176: `novas_approx_heliocentric()` and `novas_approx_sky_pos()` to calculate approximate heliocentric ICRS and observable apparent positions, respectively, for the major planets (including Earth), and Moon and the Earth-Moon Barycenter, using the orbital models mentioned above. - #176: `novas_moon_phase()` and `novas_next_moon_phase()` to calculate the Moon's apparent phase or the date/time when it reaches a specific phase, respectively, using the Keplerian orbitals for the E-M Barycenter by Standish & Williams 1992, and the geocentric orbitals of the Moon by Chapront et al. 2002. - #176: `novas_orbital_native_posvel()` to calculate orbital positions in the native system, in which the orbital is defined (e.g. ecliptic coordinates for planetary orbits). - #177: Added `novas_day_of_week()` and `novas_day_of_year()` functions to convert JD dates to a 1-based day of week index, or to a day of the year in the calendar of choice. - #185: Added `NOVAS_TIRS` and `NOVAS_ITRS` to `enum novas_reference_systems`. All frame-based functions now support these. Legacy `place()` and its variants support TIRS but not ITRS (because of the lack of information available to the legacy calls), while Keplerian orbitals may not be be defined in either TIRS or ITRS since these Earth co-rotating systems are not inertial systems. - #186: Added `NOVAS_RADIO_REFRACTION` and `NOVAS_WAVE_REFRACTION` to `enum novas_refraction_model`, for referencing the Berman & Rockwell 1976 radio-wave model, or the IAU / SOFA wavelength-dependent model, respectively. - #191: Added `tt2tdb_hp()` (high-precision) and `tt2tdb_fp()` (flexible-precision) functions for calculating the TDB-TT time difference (in seconds), with up to 0.1 μs accuracy based on Fairhead & Bretagnon 1990. - #194: Added documentation under `resources/` for a side-by-side example comparison with __astropy__. ### Changed - #173: Added parameter range checking to `refract()` function and `novas_radio_refraction()` model. If called with weather parameters or an elevation angle outside of reasonable values, `NaN` will be returned and `errno` will be set to `EINVAL`. - #181: Changed `nutation_angles()` to apply P03 model rescaling to IAU2000 nutation angles to provide 'IAU2006' values (see Capitaine et al. 2005). The same rescaling has been adopted by SOFA also. - #186: Tweaked error handling in atmospheric refraction functions (in `refract.c`). - `NOVAS_RMASS_INIT` (in `novas.h`) and LG (in `timescale.c`) values updated with DE440 data (Park et al. 2021). - Moved some functions around between source files. ### Deprecated - Deprecated `cel_pole()` function and `EPS_COR` / `PSI_COR` global variables, which provided support for the old (now disfavored) way of incorporating Earth orientation parameters as corrections into the true equator and equinox of date. The preferred way to incorpotate Earth orientation corrections is to use _dx,dy_ offsets relative to the IAU2006 precession-nutation model only when transforming between the Terrestrial Intermediate Reference System (TIRS) or Pseudo Earth-Fixed (PEF) system and the International Terrestrial Reference System (ITRS), and vice versa. ## [1.3.1] - 2025-05-07 Bug fix release with minor enhancements. ### Fixed - #167: Fixes for Debian i386 cross builds. - #174: `accum_prec()` had linear and quadratic time evolution coefficients swapped since v1.0. The bug affected the IAU2000 precession-nutation calculations, and the calculation of the complementary terms in the equation of equinoxes in `ee_ct()` / `e_tilt()`. The effect however is small, typically just a few micro-arcseconds (μas), for dates within a century of J2000. ### Changed - #166: Improved detection of invalid seconds in `parse_degrees()`. - #169: `novas_parse_degrees()` to support parsing values in exponential notation also, e.g. `1.23E2`, `1.23E2W` etc. - #170: `make_on_surface()` to validate temperature and pressure values, and return -1 (with `errno` set to `EINVAL`) if the supplied values are outside of the sensible range. - #171: Cache `nutation_angles()` instead of `e_tilt()` to improve performance in more usage scenarios. (See updated benchmarks). - #171: Moved `precession()`, `nutation()`, and `nutation_angles()` to `equinox.c`. - #178: `novas_jd_to_date()` to check if input calendar is valid and return -1 with `errno` set to `EINVAL` if it is not. - #179: `novas_jd_from_date()` to check if input calendar is valid and return NaN with `errno` set to `EINVAL` if it is not. - Corrected benchmarks for individual frames. - Corrections and edits to API documentation. ### Deprecated - Deprecated `ee_ct()` and `ira_equinox()` functions. Both are meant for internal use only, and need not be exposed to users in general. - Deprecated `solarsystem()`, `solarsystem_hp()`, and `readeph()` functions. These were prototypes for user-defined implementations that had to be linked together with NOVAS. In SuperNOVAS, the same functionality can be (should be) set dynamically, during runtime. Thus, these functions are provided to support building legacy NOVAS applications only, and should be avoided in new application code going forward. ## [1.3.0] - 2025-04-15 Feature release with many new convenience functions, such as for handling times and angles as strings; calculating rise, set, transit times; and other common astrometric calculations. In addition, the release brings various changes to improve performance. ### Fixed - #116: `transform_cat()` to update parallax to the recalculated value when precessing or changing epochs. This was a SuperNOVAS bug since v1.0. - #128: `transform_cat()` had insufficient string length checking of `out_id` parameter. Prior to the fix it checked for the longer object name size instead of the catalog name size. However, even if longer than expected input names were left uncaught, only the appropriatre number of characters were used -- hence it broke nothing, only failed to remind the caller (with an error) when the supplied name was too long. - #139: Legacy linking of external `solarsystem()` / `solarsystem_hp()` provider modules was blocked by `solsys-ephem.c` inadvertently definining these functions when `BUILTIN_SOLSYS_EPHEM` was set to 1 (default) during the build, even though it was not supposed to. - #156: `obs_posvel()` called `geo_posvel()` with TDB instead of TT. It less than a 2 ms difference, so not typically signifficant, unless <10-m level poitioning is required for Earth-orbiting satellites. ### Added - #113: New `novas_frame_lst()` convenience function to readily return the Local (apparent) Sidereal Time for a given Earth-based observing frame. - #113: New `novas_hms_hours()` and `novas_dms_degrees()` convenience functions to make it easier to parse HMS or DMS based time or angle values, returning the result in units of hours or degrees, appropriately for use in SuperNOVAS. - #113: New `novas_rises_above()` and `novas_sets_below()` functions to return the date/time a source rises above or sets below a specific elevation on a given date, and `novas_transit_time()` to calculate the time a source transits over the local meridian. (For Earth-based observers only). #140, #146: Further fixes to these calculations after the v1.3.0-rc5 release candidate [thanks to valeriy-sokoloff]. - #113: New `novas_helio_dist()` function to calculate the heliocentric distance of a Solar-system body on a given date. The `novas_solar_power()` function can be used to estimate the incident Solar power on a Solar-system body, while `novas_solar_illum()` can be used to calculate the fraction of a spherical body that is illuminated by the Sun seen from the observer location. - #113: New `novas_hpa()` and `novas_epa()` functions to calculate the parallactic angle (a.k.a. vertical position angle) for a given location on sky, using the local horizontal coordinates, or else the equatorial position, respectively. The parallactic angle (PA) can be useful to convert local Cartesian offsets (e.g. from a flat image or detector array) between the local horizontal and equatorial orientations, e.g. via the newly added `novas_h2e_offset()` or `novas_e2h_offset()` functions. The conversion between offsets and absolute coordinates usually requires a WCS projections, such as described in Calabretta & Greisen 2002. - #113: New `novas_sep()`, `novas_equ_sep()`, and `novas_object_sep()` functions can be used to calculate the precise apparent distance between to spherical or equatorial locations, or between two sources, respectively. `novas_sun_angle()` and `novas_moon_angle()` can be used to calculate the apparent angular distance of sources from the Sun and Moon, respectively. - #113: New `novas_observable` and `novas_track` data structures to provide second order Taylor series expansion of the apparent horizontal or equatorial positions, distances, and redshifts for sources. They can be calculated with the newly added `novas_hor_track()` or `novas_equ_track()` functions. Such tracking values, including rates and accelerations, can be directly useful for controlling telescope drives in horizontal or equatorial mounts to track sources (hence the name). You can also obtain instantaneous projected (extrapolated) positions from the tracking parameters via `novas_track_pos()` at low computational cost. - #113: New `novas_los_to_xyz()` and `novas_xyz_to_los()` functions to convert between line-of-sight (δφ, δθ, δr) vectors and rectangular equatorial (δx, δy, δz) vectors. - #113: New `novas_xyz_to_uvw()` and `novas_uvw_to_xzy()` functions to convert between ITRS Earth locations (absolute or differential) to equatorial projections along a line of sight in the direction of a source. Such projections are oft used in interferometry. - #114: New `novas_lsr_to_ssb_vel()` can be used to convert velocity vectors referenced to the LSR to Solar-System Barycentric velocities. And, `novas_ssb_to_lsr_vel()` to provide the inverse conversion. - #117: Added benchmarks under the `benchmark/` folder, for SuperNOVAS as well as equivalent benchmarks for __astropy__. To run the SuperNOVAS benchmarks, simply `make benchmark` in the distribution directory. - #118: New `novas_parse_date()` / `novas_parse_date_format()` to parse date/time specifications, `novas_parse_dms()` and `novas_parse_hms()` to return hours and degrees for HMS and DMS specifications, as well as the updated parse position. - #118: New `novas_timescale_for_string()` to match timescale constants to string representations, such as "UTC", or "TAI", and `novas_print_timescale()` to convert to string representation. - #118: New `novas_iso_timestamp()` to print UTC timestamps in ISO date format with millisecond precision, and `novas_timestamp()` to print timestamps in specific timescales. #151: Various fixes to new timestamping after `rc7`. [thanks to valeriy-sokoloff] - #122: New `novas_jd_to_date()`, and `novas_jd_from_date()` which convert between JD day and calendar dates using the specific type of calendar: Gregorian, Roman/Julian, or the conventional calendar of date. - #131: New `novas_date()` and `novas_date_scale()` for the simplest conversion of string times to Julian days, and in case of the latter also to a corresponding timescale (without returning a parse position). - #133: New `novas_parse_timescale()` to parse a timescale from a string specification, and return the updated parse position after also. - #134: New `novas_parse_hours()` and `novas_parse_degrees()` to convert strings in decimal or HMS/DMS formats to floating point values for SuperNOVAS, and return the parse position after the time/angle specification. - #135: New `novas_str_hours()` and `novas_str_degrees()` for the simplest conversion of strings in decimal or HMS/DMS formats to floating point values for SuperNOVAS (without retruning a parse position). - #137: New `novas_epoch()` to convert string coordinate system specifications to the Julian date of the corresponding epoch, and new `make_cat_object_sys()` and `make_redshifted_object_sys()` to make it simpler to define ICRS catalog sources in the coordinate system of choice. - #143: Added `FORTIFY` build configuration setting to enable gcc source code fortification checking by setting the `_FORTIFY_SOURCE` macro to the specified value. It is now used with a value of 3 in the build and test CIs. - #150: Further initializers for SuperNOVAS structures that can be used to empty initialize data. - #154: Added `novas_print_hms()` and `novas_print_dms()` functions to convert time / angles to their HMS/DMS string representations, with the chosen separators, and the desired decimal places on the seconds. - #155: Added `novas_parse_iso_date()` for pasing ISO 8601 timestamps, including those expressed in the proleptic Gregorian calendar prior to the Gregorian calendar reform of 1582, for which the ISO 8601 timestamp differs from the astronomical calendar date assumed by `novas_parse_timestamp()`. - Added `example-time.c` and `example-rise-set.c` under `examples/`, for demonstrating date/time handling functions and rise, set, and transit time calculations. ### Changed - #130 Use C99 `restrict` keyword to prevent pointer argument aliasing. Modern compilers will warn if restricted pointer arguments are aliased. At the least, it is a hint to users that pointer arguments marked as such should be distinct from (not overlapping with) the other pointer arguments. - #139 Reorganized code into more manageably sized modules. It also makes the API documentation by source file more logically organized. - #139: Legacy source code moved to `legacy/` folder. - #150: Use standard C initializers instead of the non-standard empty backets `{}`. While the empty brackets have been OK with `gcc` for quite a while, they only became standard in C23. Other compilers might barf at their use. - #152: For C++ compatibility do not use `class` as a parameter name. [thanks to valeriy-sokoloff] - #156: Omit TDB-TT time difference, a maximum of 2 ms, in Earth tilt calculations, where it really does not make any difference. As a result some calculations are now faster than before. - #156: Higher precision time match requirement for re-using cached ephemeris calculations. - #156: `tt2tdb()` now caches last calculation also. - #156: Eliminate redundant caching of calculations. (Also in #158). - #156: Tighten `precession()` time checking. - #157: Switch to `iau2000b()` as the low-precision nutation series. It is good to about 1 arcsec, which is the promised precision in reduced accuracy, but a lot faster than the `nu2000k()` series, which in turn is barely faster than the full `iau2000a()` nutation series. - #157: `fund_args()` to always calculate full polynomial expansion. There is little performance to gain from the truncation we used in the vicinity of J2000. No real change in the results. - #159: Add caching to `ee_ct()`. Just in case someone wants to call it repeatedly with the same parameters, it will be much much faster now. - In reduced accuracy mode apply gravitational deflection for the Sun only. In prior versions, deflection corrections were applied for Earth too. However, these are below the mas-level accuracy promised in reduced accuracy mode, and without it, the calculations for `place()` and `novas_sky_pos()` are significantly faster. - Modified `julian_date()` to add range checking for month and day arguments, and return `NAN` (with `errno` set to `EINVAL`) if the input values are invalid. - `julian_date()` and `cal_date()` now use astronomical calendar dates instead of the fixed Gregorian dates of before. Astronomical dates are Julian/Roman calendar dates prior to the Gregorian calendar reform of 1582. - `precession()` to cache matrices to/from J2000 separately. - Use `SIZE_OF_OBJ_NAME` and `SIZE_OF_CAT_NAME` instead of `sizeof(obj->starname)` and `sizeof(obj->catalog)` internally for improved portability. - Various arithmetic simplifications to give a minor performance boost. - Updated `README.md` for v1.3 and benchmarks, including comparisons to __astropy__. - Default `THREAD_LOCAL` definition extended to C23 `thread_local` keyword also. ## [1.2.0] - 2025-01-15 Feature release. New easy to use adapter modules for CALCEPH or the NAIF CSPICE Toolkit to provide precise positions for Solar-system sources. Also, added support for Keplerian orbitals, such as the ones published by the IAU Minor Planet Center (MPC) for asteroids, comets, and Near-Earth-Objects (NEOs). And, many more fixes and improvements. ### Fixed - Fixes to GCC version checking for macros. - Fixed dummy `readeph()` implementation in `readeph0.c`, and the use of `DEFAULT_READEPH` in `config.mk`. `readeph0.c` is not linked by default, and was not linked in prior releases either. - Cure LLVM `clang` compiler warnings, in tests and examples also. ### Added - #57: New generic redshift-handling functions `novas_v2z()`, `novas_z2v()`. - #57, #102: New `make_redshifted_cat_entry()` and `make_redshifted_object()` to simplify the creation of distant catalog sources that are characterized with a redshift measure rather than a radial velocity value. - #58: New functions to calculate and apply additional gravitational redshift corrections for light that originates near massive gravitating bodies (other than major planets, or Sun or Moon), or for observers located near massive gravitating bodies (other than the Sun and Earth). The added functions are `grav_redshift()`, `redhift_vrad()`, `unredshift_vrad()`, `novas_z_add()`, and `novas_z_inv()`. - #83: CALCEPH integration: `novas_use_calceph()` and/or `novas_use_calceph_planets()` to specify and use ephemeris data via CALCEPH for Solar-system sources in general, and for major planets specifically; and `novas_calceph_use_ids()` to specify whether `object.number` in `NOVAS_EPHEM_OBJECT` type objects is a NAIF ID (default) or else a CALCEPH ID number of the Solar-system body. These functions are provided by the `libsolsys-calceph.so[.1]` and/or `.a` plugin libraries, which are built contingent on the `CALCEPH_SUPPORT` variable being set to 1 prior to the build. The build of the plugin module requires an accessible installation of the CALCEPH development files (C headers and unversioned static or shared libraries depending on the needs of the build). - #86: NAIF CSPICE integration: `novas_use_cspice()`, `novas_use_cspice_planets()`, `novas_use_cspice_ephem()` to use the NAIF CSPICE library for all Solar-system sources, major planets only, or for other bodies only. `NOVAS_EPHEM_OBJECTS` should use NAIF IDs with CSPICE (or else -1 for name-based lookup). Also provides `cspice_add_kernel()` and `cspice_remove_kernel()` functions for convenience to manage the set of active kernels (#89). These functions are provided by the `libsolsys-cspice.so[.1]` and/or `.a` plugin libraries, which are built contingent on the `CSPICE_SUPPORT` variable being set to 1 prior to the build. The build of the plugin module requires an accessible installation of the CSPICE development files (C headers and unversioned static or shared libraries depending on the needs of the build). - #87: Added `novas_planet_for_name()` function to return the NOVAS planet ID for a given (case insensitive) name. - NOVAS-NAIF conversions for major planets (and Sun, Moon, SSB): `novas_to_naif_planet()` (planet centers), `novas_to_dexxx_planet()` (mixed planet center/barycenter for DExxx ephemeris files), and the inverse `naif_to_novas_planet()`. - Added `get_planet_provider()` and `get_planet_provider_hp()` functions for convenience to return the `solarsystem()` / `solarsystem_hp()` type custom planet ephemeris provider functions currently configured, so they may be used directly, outside of `ephemeris()` calls. - #93: Now supporting `make install` with `prefix` and `DESTDIR` support (e.g. `make prefix="/opt" install` to install under `/opt`, and/or `make DESTDIR="/tmp/stage" install` to stage install under `/tmp/stage`). You can also set other standard directory variables, as prescribed by the [GNU standard](https://www.gnu.org/prep/standards/html_node/Directory-Variables.html) to further customize the install locations. - #95, #98: Added support for using orbital elements. `object.type` can now be set to `NOVAS_ORBITAL_OBJECT`, whose orbit can be defined by the set of `novas_orbital`, relative to a `novas_orbital_system`. You can initialize an `object` with a set of orbital elements using `make_orbital_object()`, and for planetary satellite orbits you might use `novas_set_orbsys_pole()`. For orbital objects, `ephemeris()` will call on the new `novas_orbit_posvel()` to calculate positions. While orbital elements do not always yield precise positions, they can for shorter periods, provided that the orbital elements are up-to-date. For example, the Minor Planer Center (MPC) publishes accurate orbital elements for all known asteroids and comets regularly. For newly discovered objects, this may be the only and/or most accurate information available anywhere. - #97: Added `NOVAS_EMB` (Earth-Moon Barycenter) and `NOVAS_PLUTO_BARYCENTER` to `enum novas_planets` to distinguish from the planet center in calculations. - #98: Added `gcrs_to_tod()` / `tod_to_gcrs()` and `gcrs_to_mod()` / `mod_to_gcrs()` vector conversion functions for convenience. - #106: New example files under `examples/` demonstrating the recommended approach for using SuperNOVAS to calculate positions for various types of object. - Added various `object` initializer macros in `novas.h` for the major planets, Sun, Moon, and barycenters, e.g. `NOVAS_EARTH_INIT` or `NOVAS_SSB_INIT`. These wrap the parametric `NOVAS_PLANET_INIT(num, name)` macro, and can be used to simplify the initialization of NOVAS `object`s. - Added more physical unit constants to `novas.h` and a corresponding section in the README on how these may be used to convert to/from NOVAS conventional quantities. - SuperNOVAS headers now include each other as system-headers, not local headers. This is unlikely to affect anything really but it is more proper for an installation of the library, and works with our own `Makefile` too. - Added 'Coordinate Systems and Conversions' flowchart to `README`. - Added a GNU standard documentation targets to `Makefile`. - Added `infer` make target for running Facebook's `infer` static analysis tool. - Added missing error tracing in `nutation()`. - Added `README.md` Figure 1, to clarify relation of coordinate systems and (Super)NOVAS function to convert vectors among them. ### Changed - #96: Changed `object` structure to include `novas_orbital` for `NOVAS_ORBITAL_OBJECT` types. To keep ABI compatibility to earlier SuperNOVAS releases, `make_object()` will not initialize the new `.orbit` field _unless_ `type` is set to `NOVAS_ORBITAL_OBJECT` (which was not available before). - #97: Updated `NOVAS_PLANETS`, `NOVAS_PLANET_NAMES_INIT`, and `NOVAS_RMASS_INIT` macros to include the added planet constants. - #106: The old (legacy) NOVAS C example has been removed. Instead a new set of examples are provided, which are better suited for SuperNOVAS. - `make check` now runs both static analysis by cppcheck (new `analysis` target) and regression tests (`test` target), in closer conformance to GNU Makefile standards. - Added `-g` to default `CFLAGS` as a matter of GNU best practice. - Static library is now named `ibsupernovas.a`, which is symlinked to `libnovas.a` for back compatibility. - `readeph0.c` moved to `examples/`. It's a dummy legacy NOVAS C implementation that is not really needed in SuperNOVAS. - Various small tweaks to Makefiles. - Updated `README.md` and API documentation. ## [1.1.1] - 2024-10-28 Bug fix release. Nothing too scary, mainly just a collection of smaller fixes and improvements. ### Fixed - #55: Relativistic corrections to radial velocity were still not applied correctly. The revised calculation now uses the actual relativistic velocity differential between the source and observer to apply the appropriate time dilation factor, and applies gravitational corrections for Sun and Earth consistently at source and observer alike. - #64: `NOVAS_TAI_TO_TT` definition had wrong decimal in last place, thus was 3 ms off from what it should have been. (thanks to kiranshila) - #68: `readeph_dummy()` dummy implementation in `readeph0.c` called non existing error handler function. ### Changed - #59: For observing major planets (and Sun and Moon) `rad_vel()`, `rad_vel2()`, `place()`, and `novas_sky_pos()` will include gravitational corrections to radial velocity for light originating at the surface, and observed near Earth or else at a large distance away. These corrections, along with those for the Solar potential at the source, may be skipped for `rad_vel()` / `rad_vel2()` by setting `d_src_sun` negative. - #55: Use relativistic formulae to add/difference velocities (i.e. change velocity reference frame). - #60: Moved SuperNOVAS-only functions to a separate `super.c` module to alleviate the bloating of `novas.c`, which can still be used as a self-contained, standalone, NOVAS C replacement for legacy applications if need be. - #62: Improve debug mode error tracing when NAN values are returned, so the trace indicates NAN rather than a bogus integer return value before. - #66: Various tweaks for C/C++ best practices (by kiranshila) - #67: Use accuracy argument in `tod_to_cirs()`. (thanks to kiranshila) - #68: Various improvements to debug error tracing. - #73: Initializer macros (primarily for internal use), forced 'use' of unused variables after declarations, and no order-only-dependencies in Makefiles -- in order to cure warnings and to conform with older compilers and make. - Slight tweaks to `Makefile`, and `.mk` snippets, with added `make` configurability. ## [1.1.0] - 2024-08-04 Feature release. Introducing a more efficient and elegant approach to position and velocity calculations using observer frames; versatile handling of astronomical timescales; and support for further observer locations, coordinate reference systems, and atmospheric refraction models. The release also fixes a number of bugs, of varying severity, which affected prior SuperNOVAS releases. ### Fixed - #29: Fix portability to non-Intel platforms. Previously, SuperNOVAS used `char` for storing small integer coefficients, assuming `char` was signed. However, on some platforms like ARM and PowerPC `char` is unsigned, which broke calculations badly. As of now, we use the explicit platform independent signed `int8_t` storage type for these coefficients. - #38: `gcrs_to_j2000()` transformed in the wrong direction in v1.0. - #39: `tod_to_itrs()` used wrong Earth rotation measure (`NOVAS_ERA` instead of `NOVAS_GST`) in v1.0. - #45: `cel2ter()` invalid output in v1.0 with CIRS input coordinates (`erot` = `EROT_ERA` and `class` = `NOVAS_DYNAMICAL_CLASS`) if output vector was distinct from input vector. Affects `cirs_to_itrs()` also. - #36: `tt2tdb()` Had a wrong scaling in sinusoidal period in v1.0, resulting in an error of up to +/- 1.7 ms. - #37: `gcrs_to_cirs()` did not handle well if input and output vectors were the same in v1.0. - #28: Division by zero bug in `d_light()` (since NOVAS C 3.1) if the first position argument is the ephemeris reference position (e.g. the Sun for `solsys3.c`). The bug affects for example `grav_def()`, where it effectively results in the gravitational deflection due to the Sun being skipped. See Issue #28. - #41: `grav_def()` gravitating body position antedated somewhat incorrectly (in v1.0) when observed source is a Solar-system object between the observer and the gravitating body. The resulting positional error is typically small at below 10 uas. - #50: The NOVAS C 3.1 implementation of `rad_vel()` applied relativistic corrections for a moving observer conditional on applying relativistic gravitational corrections (for Sun and/or Earth potential) for the observer. However, it seems more reasonable that the corrections for a moving observer should be applied always and independently of the (optional) gravitational corrections. - #34: `place()` radial velocities were not quite correct in prior SuperNOVAS releases. The radial velocity calculation now precedes aberration, since the radial velocity that is observed is in the geometric direction towards the source (unaffected by aberration). As for gravitational deflection, the geometric direction is the correct direction in which light was emitted from the source for sidereal objects. For Solar system sources we now reverse trace the deflected light to calculate the direction in which it was emitted from the source. As such, the radial velocities calculated should now be precise under all conditions. The typical errors of the old calculations were up to tens of m/s because of aberration, and a few m/s due to the wrong gravitational deflection calculation. - #24: Bungled definition of `SUPERNOVAS_VERSION_STRING` in `novas.h` in v1.0. - Bungled definition of `NOVAS_OBSERVER_PLACES` in `novas.h` in v1.0. ### Added - #33: New observing-frame based approach for calculations (`frames.c`). A `novas_frame` object uniquely defines both the place and time of observation, with a set of pre-calculated transformations and constants. Once the frame is defined it can be used very efficiently to calculate positions for multiple celestial objects with minimum additional computational cost. The frames API is also more elegant and more versatile than the low-level NOVAS C approach for performing the same kind of calculations. And, frames are inherently thread-safe since post-creation their internal state is never modified during the calculations. The following new functions were added: `novas_make_frame()`, `novas_change_observer()`, `novas_geom_posvel()`, `novas_geom_to_app()`, `novas_sky_pos()`, `novas_app_to_hor()`, `novas_app_to_geom()`, `novas_hor_to_app()`. - #33: New coordinate system transformations via the `novas_transform` structure. You may use these transforms to express position / velocity vectors, calculated for a given observer and time, in the coordinate reference system of choice.The following new functions were added: `novas_make_transform()`, `novas_invert_transform()`, `novas_transform_vector()`, and `novas_transform_sky_pos()`. - #33: New `novas_timespec` structure for the self-contained definition of precise astronomical time (`timescale.c`). You can set the time via `novas_set_time()` or `novas_set_split_time()` to a JD date in the timescale of choice (UTC, UT1, GPS, TAI, TT, TCG, TDB, or TCB), or to a UNIX time with `novas_set_unix_time()`. Once set, you can obtain an expression of that time in any timescale of choice via `novas_get_time()`, `novas_get_split_time()` or `novas_get_unix_time()`. And, you can create a new time specification by incrementing an existing one, using `novas_increment_time()`, or measure time differences via `novas_diff_time()`, `novas_diff_tcg()`, or `novas_diff_tcb()`. - Added `novas_planet_bundle` structure to handle planet positions and velocities more elegantly (e.g. for gravitational deflection calculations). - #32: Added `grav_undef()` to undo gravitational bending of the observed light to obtain geometric positions from observed ones. - Added `obs_posvel()` to calculate the observer position and velocity relative to the Solar System Barycenter (SSB). - Added `obs_planets()` to calculate apparent planet positions (relative to observer) and velocities (w.r.t. SSB). - Added new observer locations `NOVAS_AIRBORNE_OBSERVER` for an observer moving relative to the surface of Earth e.g. in an aircraft or balloon based telescope platform, and `NOVAS_SOLAR_SYSTEM_OBSERVER` for spacecraft orbiting the Sun. Both of these use the `observer.near_earth` strcture to define (positions and) velocities as appropriate. Hence the `'near_earth` name is a bit misleading, but remains for back compatibility. - Added coordinate reference systems `NOVAS_MOD` (Mean of Date) which includes precession by not nutation and `NOVAS_J2000` for the J2000 dynamical reference system. - New observer locations `NOVAS_AIRBORNE_OBSERVER` and `NOVAS_SOLAR_SYSTEM_OBSERVER`, and corresponding `make_airborne_observer()` and `make_solar_system_observer()` functions. Airborne observers have an Earth-fixed momentary location, defined by longitude, latitude, and altitude, the same way as for a stationary observer on Earth, but are moving relative to the surface, such as in an aircraft or balloon based observatory. Solar-system observers are similar to observers in Earth-orbit but their momentary position and velocity is defined relative to the Solar System Barycenter (SSB), instead of the geocenter. - Added humidity field to `on_surface` structure, e.g. for refraction calculations at radio wavelengths. The `make_on_surface()` function will set humidity to 0.0, but the user can set the field appropriately afterwards. - New set of built-in refraction models to use with the frame-based `novas_app_to_hor()` / `novas_hor_to_app()` functions. The models `novas_standard_refraction()` and `novas_optical_refraction()` implement the same refraction model as `refract()` in NOVAS C 3.1, with `NOVAS_STANDARD_ATMOSPHERE` and `NOVAS_WEATHER_AT_LOCATION` respectively, including the reversed direction provided by `refract_astro()`. The user may supply their own custom refraction also, and may make use of the generic reversal function `novas_inv_refract()` to calculate refraction in the reverse direction (observer vs astrometric elevations) as needed. - Added radio refraction model `novas_radio_refraction()` based on the formulae by Berman & Rockwell 1976. - Added `cirs_to_tod()` and `tod_to_cirs()` functions for efficient tranformation between True of Date (TOD) and Celestial Intermediate Reference System (CIRS), and vice versa. - Added `make_cat_object()` function to create a NOVAS celestial `object` structure from existing `cat_entry` data. - Added `rad_vel2()` to calculate radial velocities precisely in the presense of gravitational deflection i.e., when the direction in which light was emitted is different from the direction it is detected by the observer. This new function is now used by both `place()` and `novas_sky_pos()`. - `make help` to provide a brief list and explanation of the available build targets. (Thanks to `@teuben` for suggesting this.) - Added GitHub CI regression testing for non-x86 platforms: `armv7`, `aarch64`, `riscv64`, `ppc64le`. Thus, we should avoid misphaps, like the platform specific bug Issue #29, in the future. ### Changed - #42: `cio_array()` can now parse the original ASCII CIO locator data file (`data/CIO_RA.TXT`) efficiently also, thus no longer requiring a platform-specific binary translation via the `cio_file` tool. - #51: The NOVAS C implementation of `rad_vel()` has ignored this redshifting when the Sun was being observed. From now on, we shall gravitationally reference radial velocities when observing the Sun to its photosphere. - `cio_file` tool parses interval from header rather than the less precise differencing of the first two record timestamps. This leads to `cio_array()` being more accurately centered on matching date entries, e.g. J2000. - `grav_def()` estimation of light time to where light passes nearest to gravitating body is improved by starting with the body position already antedated for light-time for the gravitating mass. The change typically improves the grativational deflection calculations at the few uas level. - `grav_def()` is simplified. It no longer uses the location type argument. Instead it will skip deflections due to any body, if the observer is within ~1500 km of its center. - `place()` now returns an error 3 if and only if the observer is at (or very close, to within ~1.5m) of the observed Solar-system object. - Improved precision of some calculations, like `era()`, `fund_args()`, and `planet_lon()` by being more careful about the order in which terms are accumulated and combined, resulting in a small improvement on the few uas (micro-arcsecond) level. - `vector2radec()`: `ra` or `dec` arguments may now be NULL if not required. - `tt2tdb()` Now uses the same, slightly more precise series as the original NOVAS C `tdb2tt()`. - `rad_vel()` You can use negative values for the distances to skip particular gravitational corrections to the radial velocity measure. The value 0.0 also continues to have the same effect as before, except if the observed source is the Sun. Then `d_src_sun` being 0.0 takes on a different meaning than before: rather than skipping gravitational redshift corrections for the Solar potential (as before) we will apply gravitational corrections for light originating at the Sun's photosphere. - `PSI_COR` and `EPS_COR` made globally visible again, thus improving NOVAS C 3.1 compatibility. - Convergent inverse calculations now use the `novas_inv_max_iter` variable declared in `novas.c` to specify the maximum number of iterations before inverse functions return with an error (with errno set to `ECANCELED`). Users may adjust this limit, if they prefer some other maximum value. - Adjusted regression testing to treat `nan` and `-nan` effectively the same. They both represent an equally invalid result regardless of the sign. - The default make target is now `distro`. It's similar to the deprecated `api` target from before except that it skips building `static` libraries and `cio_ra.bin`. - `make` now generates `.so` shared libraries with `SONAME` set to `lib.so.1` where the `.1` indicates that it is major version 1 of the `ABI`. All 1.x.x releases are expected to be ABI compatible with earlier releases. - `lib/*.so` files are now just symlinks to the actual versioned libraries `lib/*.so.1`. This conforms more closely to what Linux distros expect. - Default `make` skips `local-dox` target unless `doxygen` is available (either in the default `PATH` or else specified via the `DOXYGEN` variable, e.g. in `config.mk`). This way the default build does not have unexpected dependencies. (see Issue #22, thanks to `@teuben`). - `make` can be configured without editing `config.mk` simply by setting the appropriate shell variables (the same ones as in `config.mk`) prior to invoking `make`. Standard `CC`, `CPPFLAGS`, `CFLAGS` and `LDFLAGS` will also be used if defined externally. - `make shared` now also builds `lib/libsolsys1.so.1` and `lib/libsolsys2.so.1` shared libraries that can be used by programs that need solsys1 (via `eph_manager`) or solsys2 (via `jplint`) functionality. - `make solsys` now generates only the `solarsystem()` implementation objects that are external (not built in). - Eliminate unchecked return value compiler warnings from `cio_file` (used typically at build time only to generate `cio_ra.bin`). - `jplint.f` is moved to `examples/` since it provides only a default implementation that typically needs to be tweaked for the particualr JPL PLEPH library one intends to use. - Doxygen tag file renamed to `supernovas.tag` for consistency. - Initialize test variables for reproducibility ## [1.0.1] - 2024-05-13 Bug fix release with minor changes. ### Fixed - `cirs_to_itrs()`, `itrs_to_cirs()`, `tod_to_itrs()`, and `itrs_to_tod()` all had a unit conversion bug in using the `ut1_to_tt` argument [s] when converting TT-based Julian date to UT1-based JD [day] internally. (thanks to hannorein) - Fixed errors in `example.c` [by hannorein]. ### Added - Added `cirs_to_app_ra()` and `app_to_cirs_ra()` for convenience to convert between right ascensions measured from the CIO (for CIRS) vs measured from the true equinox of date, on the same true equator of date. ### Changed - Changed definition of `NOVAS_AU` to the IAU definition of exactly 1.495978707e+11 m. The old definition is also available as `DE405_AU`. (thanks to hannorein) - Various corrections and changes to documentation. ## [1.0.0] - 2024-03-01 This is the initial release of the SuperNOVAS library. Changes are indicated w.r.t. the upstream NOVAS C 3.1 library from which SuperNOVAS is forked from. ### Fixed - Fixes the NOVAS C 3.1 [sidereal_time bug](https://aa.usno.navy.mil/software/novas_faq), whereby the `sidereal_time()` function had an incorrect unit cast. - Fixes antedating velocities and distances for light travel time in NOVAS C 3.1 `ephemeris()`. When getting positions and velocities for Solar-system sources, it is important to use the values from the time light originated from the observed body rather than at the time that light arrives to the observer. This correction was done properly for positions, but not for velocities or distances, resulting in incorrect observed radial velocities or apparent distances being reported for spectroscopic observations or for angular-physical size conversions. - Fixes NOVAS C 3.1 bug in `ira_equinox()` which may return the result for the wrong type of equinox (mean vs. true) if the `equinox` argument was changing from 1 to 0, and back to 1 again with the date being held the same. This affected NOVAS C 3.1 routines downstream also, such as `sidereal_time()`. - Fixes NOVAS C 3.1 accuracy switching bug in `cio_basis()`, `cio_location()`, `ecl2equ()`, `equ2ecl_vec()`, `ecl2equ_vec()`, `geo_posvel()`, `place()`, and `sidereal_time()`. All these functions returned a cached value for the other accuracy if the other input parameters are the same as a prior call, except the accuracy. - Fixes multiple NOVAS C 3.1 bugs related to using cached values in `cio_basis()` with alternating CIO location reference systems. This affected many CIRS-based position calculations downstream. - Fixes NOVAS C 3.1 bug in `equ2ecl_vec()` and `ecl2equ_vec()` whereby a query with `coord_sys = 2` (GCRS) has overwritten the cached mean obliquity value for `coord_sys = 0` (mean equinox of date). As a result, a subsequent call with `coord_sys = 0` and the same date as before would return the results GCRS coordinates instead of the requested mean equinox of date coordinates. - Some remainder calculations in NOVAS C 3.1 used the result from `fmod()` unchecked, which resulted in angles outside of the expected [0:2π] range and was also the reason why `cal_date()` did not work for negative JD values. - Fixes NOVAS C 3.1 `aberration()` returning NaN vectors if the `ve` argument is 0. It now returns the unmodified input vector appropriately instead. - Fixes unpopulated `az` output value in `equ2hor()` at zenith in NOVAS C 3.1. While any azimuth is acceptable really, it results in unpredictable behavior. Hence, we set `az` to 0.0 for zenith to be consistent. - Fixes potential NOVAS C 3.1 string overflows and eliminates associated compiler warnings. - Fixes the NOVAS C 3.1 [ephem_close bug](https://aa.usno.navy.mil/software/novas_faq), whereby `ephem_close()` in `eph_manager.c` did not reset the `EPHFILE` pointer to NULL. - Supports calculations in parallel threads by making cached results thread-local. ### Added - New debug mode and error traces. Simply call `novas_debug(NOVAS_DEBUG_ON)` or `novas_debug(NOVAS_DEBUG_EXTRA)` to enable. When enabled, any error conditions (such as NULL pointer arguments, or invalid input values etc.) will be reported to the standard error, complete with call tracing within the SuperNOVAS library, s.t. users can have a better idea of what exactly did not go to plan (and where). The debug messages can be disabled by passing `NOVAS_DEBUF_OFF` (0) as the argument to the same call. - Added Doxygen markup of source code and header. - Added Makefile for GNU make. - Added continuous integration on GitHub, including regression testing, static analysis, and doxygen validation. - Added an number of precompiler constants and enums in `novas.h` to promote consistent usage and easier to read code. - New runtime configurability: * The planet position calculator function used by `ephemeris()` can be set at runtime via `set_planet_provider()`, and `set_planet_provider_hp()` (for high precision calculations). Similarly, if `planet_ephem_provider()` or `planet_ephem_provider_hp()` (defined in `solsys-ephem.c`) are set as the planet calculator functions, then `set_ephem_provider()` can set the user-specified function to use with these to actually read ephemeris data (e.g. from a JPL ephemeris file). * If CIO locations vs GCRS are important to the user, the user may call `set_cio_locator_file()` at runtime to specify the location of the binary CIO interpolation table (e.g. `cio_ra.bin`) to use, even if the library was compiled with the different default CIO locator path. * The default low-precision nutation calculator `nu2000k()` can be replaced by another suitable IAU 2006 nutation approximation via `set_nutation_lp_provider()`. For example, the user may want to use the `iau2000b()` model instead or some custom algorithm instead. - New intutitive XYZ coordinate conversion functions: * for GCRS - CIRS - ITRS (IAU 2000 standard): `gcrs_to_cirs()`, `cirs_to_itrs()`, and `itrs_to_cirs()`, `cirs_to_gcrs()`. * for GCRS - J2000 - TOD - ITRS (old methodology): `gcrs_to_j2000()`, `j2000_to_tod()`, `tod_to_itrs()`, and `itrs_to_tod()`, `tod_to_j2000()`, `j2000_to_gcrs()`. - New `itrs_to_hor()` and `hor_to_itrs()` functions to convert Earth-fixed ITRS coordinates to astrometric azimuth and elevation or back. Whereas `tod_to_itrs()` followed by `itrs_to_hor()` is effectively a just a more explicit 2-step version of the existing `equ2hor()` for converting from TOD to to local horizontal (old methodology), the `cirs_to_itrs()` followed by `itrs_to_hor()` does the same from CIRS (new IAU standard methodology), and had no prior equivalent in NOVAS C 3.1. - New `ecl2equ()` for converting ecliptic coordinates to equatorial, complementing existing `equ2ecl()`. - New `gal2equ()` for converting galactic coordinates to ICRS equatorial, complementing existing `equ2gal()`. - New `refract_astro()` complements the existing `refract()` but takes an unrefracted (astrometric) zenith angle as its argument. - New convenience functions to wrap `place()` for simpler specific use: `place_star()`, `place_icrs()`, `place_gcrs()`, `place_cirs()`, and `place_tod()`. - New `radec_star()` and `radec_planet()` as the common point for existing functions such as `astro_star()` `local_star()`, `virtual_planet()`, `topo_planet()` etc. - New time conversion utilities `tt2tdb()`, `get_utc_to_tt()`, and `get_ut1_to_tt()` make it simpler to convert between UTC, UT1, TT, and TDB time scales, and to supply `ut1_to_tt` arguments to `place()` or topocentric calculations. - Co-existing `solarsystem()` variants. It is possible to use the different `solarsystem()` implementations provided by `solsys1.c`, `solsys2.c`, `solsys3.c` and/or `solsys-ephem.c` side-by-side, as they define their functionalities with distinct, non-conflicting names, e.g. `earth_sun_calc()` vs `planet_jplint()` vs `planet_eph_manager()` vs `planet_ephem_provider()`. - New `novas_case_sensitive(int)` to enable (or disable) case-sensitive processing of object names. (By default NOVAS `object` names are converted to upper-case, making them effectively case-insensitive.) - New `make_planet()` and `make_ephem_object()` to make it simpler to configure Solar-system objects. ### Changed - Changed to support for calculations in parallel threads by making cached results thread-local (as opposed to the globally cached values in NOVAS C 3.1). This works using the C11 standard `_Thread_local` or else the earlier GNU C >= 3.3 standard `__thread` modifier. You can also set the preferred thread-local keyword for your compiler by passing it via `-DTHREAD_LOCAL=...` in `config.mk` to ensure that your build is thread-safe. And, if your compiler has no support whatsoever for thread_local variables, then SuperNOVAS will not be thread-safe, just as NOVAS C isn't. - SuperNOVAS functions take `enum`s as their option arguments instead of the raw integers in NOVAS C 3.1. These enums are defined in `novas.h`. The same header also defines a number of useful constants. The enums allow for some compiler checking, and make for more readable code that is easier to debug. They also make it easy to see what choices are available for each function argument, without having to consult the documentation each and every time. - All SuperNOVAS functions check for the basic validity of the supplied arguments (Such as NULL pointers or illegal duplicate arguments) and will return -1 (with `errno` set, usually to `EINVAL`) if the arguments supplied are invalid (unless the NOVAS C API already defined a different return value for specific cases. If so, the NOVAS C error code is returned for compatibility). There were no such checks performed in NOVAS C 3.1. - All erroneous returns now set `errno` so that users can track the source of the error in the standard C way and use functions such as `perror()` and `strerror()` to print human-readable error messages. (NOVAS C 3.1 did not set `errno`). - Many output values supplied via pointers are set to clearly invalid values in case of erroneous returns, such as `NAN` so that even if the caller forgets to check the error code, it becomes obvious that the values returned should not be used as if they were valid. (No more sneaky silent errors, which were common in NOVAS C 3.1.) - Many SuperNOVAS functions allow `NULL` arguments (unlike NOVAS C 3.1), both for optional input values as well as outputs that are not required (see the [API Documentation](https://smithsonian.github.io/SuperNOVAS/apidoc/html/) for specifics). This eliminates the need to declare dummy variables in your application code for quantities you do not require. - All SuperNOVAS functions that take an input vector to produce an output vector allow the output vector argument be the same as the input vector argument (unlike in NOVAS C 3.1 where this was not consistently implented). For example, `frame_tie(pos, J2000_TO_ICRS, pos)` using the same `pos` vector both as the input and the output. In this case the `pos` vector is modified in place by the call. This can greatly simplify usage, and can eliminate extraneous declarations, when intermediates are not required. - SuperNOVAS declares function pointer arguments as `const` whenever the function does not modify the data content being referenced. This supports better programming practices that generally aim to avoid unintended data modifications. (The passing of `const` arguments to NOVAS C 3.1 calls would result in compiler warnings.) - Catalog names can be up to 6 bytes (including termination), up from 4 in NOVAS C 3.1, while keeping `struct` layouts the same as NOVAS C thanks to alignment, thus allowing cross-compatible binary exchange of `cat_entry` records with NOVAS C 3.1. - Object ID numbers are `long` instead of `short` (in NOVAS C 3.1) to accommodate NAIF IDs, which require minimum 32-bit integers. - `precession()` can now take arbitrary input and output epochs. Unlike NOVAS C 3.1, it is not required that either of those epochs be J2000. - `cel2ter()` and `ter2cel()` can now process 'option'/'class' = 1 (`NOVAS_REFERENCE_CLASS`) regardless of the methodology (`EROT_ERA` or `EROT_GST`) used to input or output coordinates in GCRS (unlike in NOVAS C 3.1). - Changed `make_object()` to retain the specified number argument (which can be different from the `starnumber` value in the supplied `cat_entry` structure), in contrast to NOVAS C 3.1, which set `object->number` to 0 for `cat_entry` arguments. - `cio_location()` will always return a valid value as long as neither output pointer argument is NULL. (NOVAS C 3.1 would return an error if a CIO locator file was previously opened but cannot provide the data for whatever reason). - `sun_eph()` in `solsysl3.c` evaluates the series in reverse order compared to NOVAS C 3.1, accumulating the least significant terms first, and thus resulting in higher precision result in the end. - Changed `vector2radec()` to return NAN values if the input is a null-vector (i.e. all components are zero), as opposed to NOVAS C 3.1, which left the input vector argument unchanged. - IAU 2000A nutation model uses higher-order Delaunay arguments provided by `fund_args()`, instead of the linear model in NOVAS C 3.1. - IAU 2000 nutation made a bit faster vs NOVAS C 3.1, via reducing the the number of floating-point multiplications necessary by skipping terms that do not contribute. Its coefficients are also packed more frugally in memory, resulting in a smaller footprint than in NOVAS C 3.1. - More efficient paging (cache management) for `cio_array()` vs NOVAS C 3.1, including I/O error checking. - Changed the standard atmospheric model for (optical) refraction calculation to include a simple model for the annual average temperature at the site (based on latitude and elevation). This results is a slightly more educated guess of the actual refraction than the global fixed temperature of 10 °C assumed by NOVAC C 3.1 regardless of observing location. ### Deprecated - `novascon.h` / `novascon.c`: These definitions of constants in NOVAS C 3.1 was troublesome for two reasons: (1) They were primarily meant for use internally within the library itself. As the library clearly defines in what units input and output quantities are expressed, the user code can apply its own appropriate conversions that need not match the internal system used by the library. Hence exposing these constants to users was half baked. (2) The naming of constants was too simplistic (with names such as `C` or `F`) that it was rather prone to naming conflicts in user code. As a result, the constants have been moved to `novas.h` with more unique names (such as `NOVAS_C` and `NOVAS_EARTH_FLATTENING`. New code should rely on these definitions instead of the troubled constants of `novascon.c` / `.h` if at all necessary. - `equ2hor()`: It's name does not make it clear that this function is suitable only for converting TOD (old methodology) to horizontal but not CIRS to horizontal (IAU 2000 standard). You should use the equivalent but more specific `tod_to_itrs()` or the newly added `cirs_to_itrs()`, followed by `itrs_to_hor()` instead. - `cel2ter()` / `ter2cel()`: These NOVAS C 3.1 function can be somewhat confusing to use. You are likely better off with `tod_to_itrs()` and `cirs_to_itrs()` instead, and possibly followed by further conversions if desired. - `app_star()`, `app_planet()`, `topo_star()` and `topo_planet()`: These NOVAS C 3.1 function use the old (pre IAU 2000) methodology, which isn't clear from their naming. Use `place()` or `place_star()` with `NOVAS_TOD` or `NOVAS_CIRS` as the system instead, as appropriate. - `readeph()`: This NOVAS C 3.1 function is prone to memory leaks, and not flexible with its origin (necessarily at the barycenter). Instead, use a similar `novas_ephem_provider` implementation and `set_ephem_provider()` for a more flexible and less troublesome equivalent, which also does not need to be baked into the library and can be configured at runtime. - `tdb2tt()`. Use `tt2tdb()` instead. It's both more intuitive to use (returning the time difference as a double) and faster to calculate than the NOVAS C function, not to mention that it implements the more standard approach. Sigmyne-SuperNOVAS-c764b40/CMakeLists.txt000066400000000000000000000222141517360672500201400ustar00rootroot00000000000000# CMake configuration file for the SuperNOVAS library # # Authors: Kiran Shila, Attila Kovacs # # Usage: # # To build under a 'build/' directory: # # $ cmake -B build [OPTIONS] # $ cmake --build build # # And then to install, e.g. under '/usr/local': # $ [sudo ] cmake --install --prefix=/usr/local # # You may install just a specific component via the --component option, such # as 'Runtime' or 'Development'. # cmake_minimum_required(VERSION 3.24...4.3) # Project definition project(supernovas VERSION 1.6.0 DESCRIPTION "SuperNOVAS C/C++ astrometry library" HOMEPAGE_URL "https://sigmyne.github.io/SuperNOVAS/" LANGUAGES C ) # Include required modules include(CheckLibraryExists) include(GNUInstallDirs) include(CMakePackageConfigHelpers) include(FeatureSummary) # Build options option(BUILD_SHARED_LIBS "Build as shared libraries instead of static" OFF) option(BUILD_DOC "Build HTML documetation" OFF) option(BUILD_TESTING "Build regression test suite" ON) option(BUILD_EXAMPLES "Build example programs" OFF) option(BUILD_BENCHMARK "Build benchmark programs" OFF) option(ENABLE_CPP "Enable C++ library build (supernovas++ library)" OFF) option(ENABLE_CALCEPH "Enable CALCEPH support (solsys-calceph plugin)" OFF) option(ENABLE_CSPICE "Enable CSPICE support (solsys-cspice plugin)" OFF) # Set feature descriptions for summary add_feature_info(SharedLibs BUILD_SHARED_LIBS "Build as shared libraries") add_feature_info(Documentation BUILD_DOC "Developer documentation (HTML)") add_feature_info(Testing BUILD_TESTING "Run regression testing") add_feature_info(Examples BUILD_EXAMPLES "Build and test example programs") add_feature_info(Benchmarks BUILD_BENCHMARK "Build benchmarking programs") add_feature_info(C++-Libs ENABLE_CPP "Build C++ library also (supernovas++)") add_feature_info(Calceph-Plugin ENABLE_CALCEPH "Optional ephemeris support via CALCEPH (solsys-calceph)") add_feature_info(CSPICE-Plugin ENABLE_CSPICE "Optional ephemeris support via CSPICE (solsys-cspice)") # ---------------------------------------------------------------------------- # pkg-config variables # [.pc] Libs -- linker flags for apps set(PC_LIBS "-lsupernovas ") # [.pc] Libs.private -- linker flags for supernovas itself set(PC_LIBS_PRIVATE "") # ---------------------------------------------------------------------------- # Global build configuration # Set output directories set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) # Debug postfix for libraries set(CMAKE_DEBUG_POSTFIX d) # Build time locations for sub-configs link_directories(${CMAKE_BINARY_DIR}/lib) set(supernovas_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include) if(WIN32) # Windows-specific settings message("Configuring for Windows...") set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() check_library_exists(m exp "" HAS_MATHLIB) if(HAS_MATHLIB) set(MATHLIB m) # [.pc] Link applications against math lib... string(APPEND PC_LIBS_PRIVATE -l${MATHLIB} " ") endif() if(ENABLE_CALCEPH OR ENABLE_CSPICE) find_package(Threads) if(CMAKE_THREAD_LIBS_INIT) # [.pc] apps should be linked against threads libs also... string(APPEND PC_LIBS_PRIVATE ${CMAKE_THREAD_LIBS_INIT} " ") endif() endif() # ---------------------------------------------------------------------------- # Extenal plugin configuration # CALCEPH plugin if(ENABLE_CALCEPH) find_package(calceph COMPONENTS Development REQUIRED CONFIG) set_package_properties(calceph PROPERTIES URL "https://calceph.imcce.fr" DESCRIPTION "is designed to access the binary planetary ephemeris files" TYPE REQUIRED PURPOSE "Provides ephemeris support for supernovas" ) string(APPEND PC_LIBS "-lsolsys-calceph ") string(APPEND PC_LIBS_PRIVATE "-lcalceph ") endif() # CSPICE plugin if(ENABLE_CSPICE) find_library(cspice cspice REGISTRY_VIEW TARGET REQUIRED) string(APPEND PC_LIBS "-lsolsys-cspice ") string(APPEND PC_LIBS_PRIVATE "-lcspice ") endif() # ---------------------------------------------------------------------------- # Link applications against the C++ library also, if enabled if(ENABLE_CPP) enable_language(CXX) string(APPEND PC_LIBS "-lsupernovas++ ") endif() # ---------------------------------------------------------------------------- # Build libraries from source add_subdirectory(src) # ---------------------------------------------------------------------------- # Testing, examples, and benchmarks... # Run tests for the enabled options below... enable_testing() # Examples if(BUILD_EXAMPLES) add_subdirectory(examples) endif() # Testing if(BUILD_TESTING) add_subdirectory(test) endif() # Benchmarking if(BUILD_BENCHMARK) add_subdirectory(benchmark) endif() # Documentation if(BUILD_DOC) add_subdirectory(doc) endif() # ---------------------------------------------------------------------------- # Install Runtime component set(INSTALL_TARGETS core) set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Runtime) if(ENABLE_CALCEPH) list(APPEND INSTALL_TARGETS solsys-calceph) endif() if(ENABLE_CSPICE) list(APPEND INSTALL_TARGETS solsys-cspice) endif() if(ENABLE_CPP) list(APPEND INSTALL_TARGETS cpp) endif() install(TARGETS ${INSTALL_TARGETS} EXPORT supernovasTargets) # ------------------------------------------------------------------------ # Install Development component install(FILES include/novas.h TYPE INCLUDE COMPONENT Development ) if(ENABLE_CALCEPH) install(FILES include/novas-calceph.h TYPE INCLUDE COMPONENT Development ) endif() if(ENABLE_CSPICE) install(FILES include/novas-cspice.h TYPE INCLUDE COMPONENT Development ) endif() if(ENABLE_CPP) install(FILES include/supernovas.h TYPE INCLUDE COMPONENT Development ) endif() # Install markdown files install(FILES CHANGELOG.md CONTRIBUTING.md TYPE DOC COMPONENT Development ) # For examples/ dir, list just the directory, not the individual files installed. install(CODE "message(STATUS \"Installing: /${CMAKE_INSTALL_DOCDIR}/examples/\")") install(DIRECTORY ${PROJECT_SOURCE_DIR}/examples TYPE DOC MESSAGE_NEVER COMPONENT Development ) # For legacy/ dir, list just the directory, not the individual files installed. install(CODE "message(STATUS \"Installing: /${CMAKE_INSTALL_DOCDIR}/legacy/*\")") install(DIRECTORY ${PROJECT_SOURCE_DIR}/legacy TYPE DOC MESSAGE_NEVER COMPONENT Development ) install(EXPORT supernovasTargets COMPONENT Development FILE supernovasTargets.cmake NAMESPACE supernovas:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/supernovas ) # ------------------------------------------------------------------------ # Package config configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/supernovasConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/supernovasConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/supernovas ) write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/supernovasConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/supernovasConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/supernovasConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/supernovas COMPONENT Development ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/supernovas.pc.in ${CMAKE_CURRENT_BINARY_DIR}/supernovas.pc @ONLY ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/supernovas.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT Development ) # ---------------------------------------------------------------------------- # Uninstall target if(NOT TARGET uninstall) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY ) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake ) endif() # ---------------------------------------------------------------------------- # Export the package for use from the build-tree # (this registers the build-tree with a global CMake-registry) export(PACKAGE supernovas) # ---------------------------------------------------------------------------- # Summary feature_summary(WHAT ALL) message(" - Compile flags added with CMAKE_BUILD_TYPE:") message(" Debug: ${CMAKE_C_FLAGS_DEBUG}") message(" Release: ${CMAKE_C_FLAGS_RELEASE}") message(" RelWithDebInfo: ${CMAKE_C_FLAGS_RELWITHDEBINFO}") message(" MinSizeRel: ${CMAKE_C_FLAGS_MINSIZEREL}") message("") message(" - supernovas Configuration Summary:") message(" Version: ${PROJECT_VERSION}") if(CMAKE_BUILD_TYPE) message(" Build type: ${CMAKE_BUILD_TYPE}") else() message(" Build type: (default) -- external CFLAGS only") endif() message(" Install prefix: ${CMAKE_INSTALL_PREFIX}") message(" Compiler: ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}") message("") Sigmyne-SuperNOVAS-c764b40/CODE_OF_CONDUCT.md000066400000000000000000000121301517360672500201730ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at GitHub. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. Sigmyne-SuperNOVAS-c764b40/CONTRIBUTING.md000066400000000000000000000076011517360672500176340ustar00rootroot00000000000000# Contributing to SuperNOVAS The _SuperNOVAS_ library is for everyone. And, it is developers like you who can make it better. Whether there is a nagging issue you would like to fix, or a new feature you'd like to see, you can make a difference yourself. Make this project a little bit your own, by submitting pull requests with fixes and enhancement. When you are ready, here are the typical steps for contributing to the project: 1. Old or new __Issue__? Whether you just found a bug, or you are missing a much needed feature, start by checking open (and closed) [Issues](https://github.com/Sigmyne/SuperNOVAS/issues). If an existing issue seems like a good match to yours, feel free to speak up, comment, or to offer help in resolving it. If you find no issues that match, go ahead and create a new one. 2. __Fork__. Is it something you'd like to help resolve? Great! You should start by creating your own fork of the repository so you can work freely on your solution. I recommend that you place your work on a branch of your fork, which is named either after the issue number, e.g. `issue-192`, or some other descriptive name, such as `fast-nutations`. 3. __Develop__. Experiment on your fork/branch freely. If you run into a dead-end, you can always abandon it (which is why branches are great) and start anew. You can run your own tests locally using `make test` before committing your changes. If the tests pass, you should also try running `make all` and to ensure that all components of the package and its API documentation are also in order. Remember to synchronize your `main` branch by fetching changes from upstream every once in a while, and merging them into your development branch. Don't forget to: - Add __doxygen__ markup your new code. You can keep it sweet and simple, but make sure it properly explains your globally exposed functions, their arguments and return values. You should also cross-reference other functions / constants that are similar, related, or relevant to what you just added. - Add __Unit Tests__. Make sure your new code has as close to full unit test coverage as possible. You can add tests to `test/src/test.c` as appropriate, and if you add new source files, you may need to adjust `test/Makefile` so that `gcov` coverage is generated for your new source files. You should aim for 100% diff coverage. When pushing changes to your fork, you can get a coverage report by checking the Github Actions result of your commit (click the Coveralls link), and you can analyze what line(s) of code need to have tests added. Try to create tests that are simple but meaningful (i.e. check for valid results, rather than just confirm existing behavior), and try to cover as many realistic scenarios as appropriate. Write lots of tests if you need to. 4. __Pull Request__. Once you feel your work can be integrated, create a pull request from your fork/branch. You can do that easily from the github page of your fork/branch directly. In the pull request, provide a concise description of what you added or changed. Your pull request will be reviewed. You may get some feedback at this point, and maybe there will be discussions about possible improvements or regressions etc. It's a good thing too, and your changes will likely end up with added polish as a result. You can be all the more proud of it in the end! 5. If all goes well, your pull-request will get merged, and will be included in the upcoming release of _SuperNOVAS_. Congratulations for your excellent work, and many thanks for dedicating some of your time for making this library a little bit better. There will be many who will appreciate it. :-) If at any point you have questions, or need feedback, don't be afraid to ask. You can put your questions into the issue you found or created, or your pull-request, or as a Q&A in [Discussions](https://github.com/Sigmyne/SuperNOVAS/discussions). Sigmyne-SuperNOVAS-c764b40/LICENSE000066400000000000000000000022731517360672500164100ustar00rootroot00000000000000This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 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 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. For more information, please refer to Sigmyne-SuperNOVAS-c764b40/Makefile000066400000000000000000000175201517360672500170440ustar00rootroot00000000000000 # =============================================================================== # WARNING! You should leave this Makefile alone probably # To configure the build, you can edit config.mk, or else you export the # equivalent shell variables prior to invoking 'make' to adjust the # build configuration. # =============================================================================== include config.mk # =============================================================================== # Specific build targets and recipes below... # =============================================================================== # Default target for packaging with Linux distributions .PHONY: distro distro: shared $(DOC_TARGETS) # Shared or static libraries (versioned and unversioned) .PHONY: shared static analyze shared static: summary $(MAKE) -C src $@ .PHONY: shared-c99 shared-c99: summary $(MAKE) -C src/c99 shared .PHONY: shared-cpp shared-cpp: summary $(MAKE) -C src/cpp shared .PHONY: static-c99 static-c99: summary $(MAKE) -C src/c99 static .PHONY: static-cpp static-cpp: summary $(MAKE) -C src/cpp static .PHONY: solsys solsys: $(MAKE) -C src/c99 solsys # Static analysis .PHONY: analyze analyze: $(MAKE) -C src $@ # All of the above .PHONY: all all: distro static test coverage analyze # Run regression tests .PHONY: test test: $(MAKE) -C test run .PHONY: benchmark benchmark: shared-c99 $(MAKE) -C benchmark .PHONY: examples examples: shared $(MAKE) -C examples # Perform checks (test + analyze) .PHONY: check check: test analyze # Measure test coverage (on test set of files only) .PHONY: coverage coverage: $(MAKE) -C test coverage # Remove intermediates .PHONY: clean clean: @rm -f $(OBJECTS) Doxyfile.local gmon.out @$(MAKE) -s -C src clean @$(MAKE) -s -C test clean @$(MAKE) -s -C benchmark clean @$(MAKE) -s -C examples clean @$(MAKE) -s -C doc clean # Remove all generated files .PHONY: distclean distclean: clean @rm -f $(LIB)/libsupernovas.$(SOEXT)* $(LIB)/libsupernovas.a $(LIB)/libnovas.a \ $(LIB)/libnovas.$(SOEXT)* $(LIB)/libsolsys*.$(SOEXT)* @rm -f doc/Doxyfile.local doc/README.md @rm -rf build */build @$(MAKE) -s -C src distclean @$(MAKE) -s -C test distclean @$(MAKE) -s -C benchmark distclean @$(MAKE) -s -C examples distclean @$(MAKE) -s -C doc distclean .PHONY: dox local-dox dox local-dox: $(MAKE) -C doc # ---------------------------------------------------------------------------- # Install targets and recipes # ---------------------------------------------------------------------------- LIB ?= lib # Standard install commands INSTALL_PROGRAM ?= install INSTALL_DATA ?= install -m 644 .PHONY: install install: install-libs install-headers install-docs install-legacy .PHONY: install-libs install-libs: ifneq ($(wildcard $(LIB)/*),) @echo "installing libraries to $(DESTDIR)$(libdir)" install -d $(DESTDIR)$(libdir) cp -a $(LIB)/* $(DESTDIR)$(libdir)/ else @echo "WARNING! Skipping libs install: needs 'shared' and/or 'static'" endif .PHONY: install-calceph-headers install-calceph-headers: ifeq ($(CALCEPH_SUPPORT),1) $(INSTALL_DATA) include/novas-calceph.h $(DESTDIR)$(includedir)/ endif .PHONY: install-cspice-headers install-cspice-headers: ifeq ($(CSPICE_SUPPORT),1) $(INSTALL_DATA) include/novas-cspice.h $(DESTDIR)$(includedir)/ endif .PHONY: install-headers install-headers: @echo "installing headers to $(DESTDIR)$(includedir)" install -d $(DESTDIR)$(includedir) $(INSTALL_DATA) include/novas.h $(DESTDIR)$(includedir)/ ifeq ($(ENABLE_CPP),1) $(INSTALL_DATA) include/supernovas.h $(DESTDIR)$(includedir)/ endif @$(MAKE) install-calceph-headers @$(MAKE) install-cspice-headers .PHONY: install-docs install-docs: install-markdown install-html install-examples install-legacy .PHONY: install-markdown install-markdown: @echo "installing Markdown documentation to $(DESTDIR)$(docdir)" install -d $(DESTDIR)$(docdir) $(INSTALL_DATA) CHANGELOG.md $(DESTDIR)$(docdir)/ $(INSTALL_DATA) CONTRIBUTING.md $(DESTDIR)$(docdir)/ .PHONY: install-html install-html: ifneq ($(wildcard doc/c99/html/search/*),) @echo "installing C99 API documentation to $(DESTDIR)$(htmldir)/c99" install -d $(DESTDIR)$(htmldir)/c99/search $(INSTALL_DATA) doc/c99/html/search/* $(DESTDIR)$(htmldir)/c99/search/ $(INSTALL_DATA) doc/c99/html/*.* $(DESTDIR)$(htmldir)/c99/ @echo "installing C99 Doxygen tag file to $(DESTDIR)$(docdir)" install -d $(DESTDIR)$(docdir) $(INSTALL_DATA) doc/supernovas.tag $(DESTDIR)$(docdir)/ else @echo "WARNING! Skipping C99 HTML docs install: needs doxygen and 'local-dox'" endif ifneq ($(wildcard doc/cpp/html/search/*),) @echo "installing C++ API documentation to $(DESTDIR)$(htmldir)/cpp" install -d $(DESTDIR)$(htmldir)/cpp/search $(INSTALL_DATA) doc/cpp/html/search/* $(DESTDIR)$(htmldir)/cpp/search/ $(INSTALL_DATA) doc/cpp/html/*.* $(DESTDIR)$(htmldir)/cpp/ @echo "installing C++ Doxygen tag file to $(DESTDIR)$(docdir)" install -d $(DESTDIR)$(docdir) $(INSTALL_DATA) doc/cpp/supernovas++.tag $(DESTDIR)$(docdir)/ else @echo "WARNING! Skipping C++ HTML docs install: needs doxygen and 'local-dox'" endif .PHONY: install-examples install-examples: @echo "installing C99 examples to $(DESTDIR)$(docdir)/examples/c99" install -d $(DESTDIR)$(docdir)/examples/c99 $(INSTALL_DATA) examples/c99/* $(DESTDIR)$(docdir)/examples/c99/ ifeq ($(ENABLE_CPP),1) @echo "installing C++ examples to $(DESTDIR)$(docdir)/examples/cpp" install -d $(DESTDIR)$(docdir)/examples/cpp $(INSTALL_DATA) examples/cpp/* $(DESTDIR)$(docdir)/examples/cpp/ endif .PHONY: install-legacy install-legacy: @echo "installing legacy files to $(DESTDIR)$(docdir)/legacy" install -d $(DESTDIR)$(docdir)/legacy $(INSTALL_DATA) legacy/* $(DESTDIR)$(docdir)/legacy/ # Some standard GNU targets, that should always exist... .PHONY: html html: local-dox .PHONY: dvi dvi: .PHONY: ps ps: .PHONY: pdf pdf: # ---------------------------------------------------------------------------- # Help and info targets # ---------------------------------------------------------------------------- # Build configuration summary .PHONY: summary summary: @echo @echo "SuperNOVAS build configuration:" @echo @echo " CALCEPH_SUPPORT = $(CALCEPH_SUPPORT)" @echo " CSPICE_SUPPORT = $(CSPICE_SUPPORT)" @echo " ENABLE_CPP = $(ENABLE_CPP)" @echo " SOLSYS_SOURCES = $(SOLSYS_SOURCES)" @echo " READEPH_SOURCES = $(READEPH_SOURCES)" @echo @echo " CC = $(CC)" @echo " CFLAGS = $(CFLAGS)" @echo " LDFLAGS = $(LDFLAGS)" @echo # Built-in help screen for `make help` .PHONY: help help: @echo @echo "Syntax: make [target]" @echo @echo "The following tairgets are available:" @echo @echo " distro (default) 'shared' targets and also 'local-dox' provided 'doxygen'" @echo " is available, or was specified via the DOXYGEN variable (e.g. in" @echo " 'config.mk')" @echo " static Builds the static 'lib/libsupernovas[++].a' libraries." @echo " shared Builds the shared 'libsupernovas[++].so', 'libsolsys1.so', and" @echo " 'libsolsys2.so' libraries (linked to versioned ones)." @echo " dox Compiles HTML API documentation using 'doxygen'." @echo " test Runs regression tests." @echo " benchmark Runs benchmarks." @echo " analyze Performs static code analysis with 'cppcheck'." @echo " check Same as 'test' and then 'analyze'." @echo " coverage Runs 'gcov' to analyze regression test coverage." @echo " summary Provides a summary of the current build configuration." @echo " all All of the above." @echo " install Install components (e.g. 'make prefix= install')" @echo " clean Removes intermediate products." @echo " distclean Deletes all generated files." @echo # This Makefile depends on the config and build snipplets. Makefile: config.mk build.mk Sigmyne-SuperNOVAS-c764b40/README.md000066400000000000000000002175371517360672500166750ustar00rootroot00000000000000![Build Status](https://github.com/Sigmyne/SuperNOVAS/actions/workflows/build.yml/badge.svg) ![Test](https://github.com/Sigmyne/SuperNOVAS/actions/workflows/test.yml/badge.svg) ![API documentation](https://github.com/Sigmyne/SuperNOVAS/actions/workflows/dox.yml/badge.svg) ![Coverage Status](https://codecov.io/gh/Sigmyne/SuperNOVAS/graph/badge.svg?token=E11OFOISMW)
SuperNOVAS logo
# SuperNOVAS [![DOI: 10.5281/zenodo.14584983](https://zenodo.org/badge/DOI/10.5281/zenodo.14584983.svg)](https://doi.org/10.5281/zenodo.14584983) The NOVAS C astrometry library, made better. - [C99 API documentation](https://sigmyne.github.io/SuperNOVAS/doc/html/topics.html) - [C++ API documentation](https://sigmyne.github.io/SuperNOVAS/doc/html/cpp/topics.html) - [SuperNOVAS pages](https://sigmyne.github.io/SuperNOVAS) on github.io [SuperNOVAS](https://github.com/Sigmyne/SuperNOVAS/) is a C/C++ astronomy software library, providing high-precision astrometry such as one might need for running an observatory, a precise planetarium program, or for analyzing astronomical datasets. It started as a fork of the Naval Observatory Vector Astrometry Software ([NOVAS](https://aa.usno.navy.mil/software/novas_info)) C version 3.1, but since then it has grown into its own, providing bug fixes, tons of new features, and a much improved API compared to the original NOVAS. __SuperNOVAS__ is easy to use and it is very fast, with 3--5 orders of magnitude faster position calculations than [astropy](https://www.astropy.org/) 7.0.0 in a single thread (see the [benchmarks](#benchmarks)), and its performance will scale further with the number of CPUs when calculations are performed in parallel threads. __SuperNOVAS__ is and it is available through the [Sigmyne/SuperNOVAS](https://github.com/Sigmyne/SuperNOVAS) repository on GitHub, without licensing restrictions. Its source code is compatible with the C99 and C++11 standards, and hence should be suitable for old and new platforms alike. And, despite it being a light-weight library, it fully supports the IAU 2000/2006 conventions for microarcsecond-level position calculations. This document has been updated for the `v1.6` and later releases. ## Table of Contents - [Introduction](#introduction) - [Fixed NOVAS C 3.1 issues](#fixed-issues) - [Compatibility with NOVAS C 3.1](#compatibility) - [Building and installation](#installation) - [Celestial coordinate systems (old vs. new)](#methodologies) - [Example use cases](#examples) - [Incorporating Solar-system ephemeris data or services](#solarsystem) - [Notes on precision](#precision) - [Runtime debug support](#debug-support) - [Representative benchmarks](#benchmarks) - [SuperNOVAS added features](#supernovas-features) - [Release schedule](#release-schedule) ----------------------------------------------------------------------------- ## Introduction __SuperNOVAS__ is a supercharged fork of the The Naval Observatory Vector Astrometry Software ([NOVAS](https://aa.usno.navy.mil/software/novas_info)). (It is not related to the separate NOVA / libnova library.) The primary goal of __SuperNOVAS__ is to improve on the original NOVAS C library via: - Fixing [outstanding issues](#fixed-issues). - Adding a high-level [C++11 API](USAGE-CPP.md). - Improved [C99 API documentation](https://sigmyne.github.io/SuperNOVAS/doc/html/files.html). - [Faster calculations](#benchmarks). - [New features](#added-functionality). - [Refined C99 API](#api-changes) to promote best programming practices. - [Thread-safe calculations](https://github.com/Sigmyne/SuperNOVAS/blob/main/doc/USAGE-C99.md#multi-threading-c99). - [Debug mode](#debug-support) with informative error tracing. - [Regression testing](https://codecov.io/gh/Sigmyne/SuperNOVAS) and continuous integration on GitHub. At the same time, __SuperNOVAS__ aims to be fully backward compatible with the intended functionality of the upstream NOVAS C library, such that it can be used as a _build-time_ replacement for NOVAS in your application without having to change existing (functional) code you may have written for NOVAS C. __SuperNOVAS__ is really quite easy to use. Its new API is just as simple and intuitive as that of __astropy__ (or so we strive for it to be), and it is similarly well documented also (see the documentation for the [C99](https://sigmyne.github.io/SuperNOVAS/doc/html/files.html)) and/or [C++](https://sigmyne.github.io/SuperNOVAS/doc/html/cpp/files.html) APIs. You can typically achieve the same results with similar lines of code on [C](https://github.com/Sigmyne/SuperNOVAS/blob/main/doc/SuperNOVAS_vs_astropy.md) or [C++](https://github.com/Sigmyne/SuperNOVAS/blob/main/doc/cpp/SuperNOVAS++_vs_astropy.md) with __SuperNOVAS__ as with __astropy__, notwithstanding a little more involved error handling (due to the lack of `try / except` style constructs in C/C++). __SuperNOVAS__ is currently based on NOVAS C version 3.1. We plan to rebase __SuperNOVAS__ to the latest upstream release of the NOVAS C library, if possible when new releases become available. __SuperNOVAS__ is maintained by [Attila Kovács](https://www.sigmyne.com/attipaci). Outside contributions are very welcome. See [how you can contribute](https://sigmyne.github.io/SuperNOVAS/doc/CONTRIBUTING.html) on how you can make __SuperNOVAS__ even better. ### Related links - [NOVAS](https://aa.usno.navy.mil/software/novas_info) home page at the US Naval Observatory. - [CALCEPH C library](https://calceph.imcce.fr) for integrating Solar-system ephemerides from JPL and/or in INPOP 2.0/3.0 format. - [NAIF SPICE toolkit](https://naif.jpl.nasa.gov/naif/toolkit.html) for integrating Solar-system ephemerides from JPL. - [Sigmyne/cspice-sharedlib](https://github.com/Sigmyne/cspice-sharedlib) for building CSPICE as a shared library for dynamic linking. - [IAU Minor Planet Center](https://www.minorplanetcenter.net/iau/mpc.html) provides up-to-date orbital elements for asteroids, comets, and near-Earth objects (NEOs), including newly discovered objects. - [IERS Earth Rotation and Reference Systems Service](https://www.iers.org/IERS/EN/DataProducts/EarthOrientationData/eop) provides Earth Orientation Parameter (EOP) data for many high accuracy calculations. ----------------------------------------------------------------------------- ## Fixed NOVAS C 3.1 issues __SuperNOVAS__ fixes a number of outstanding issues with NOVAS C 3.1:
- Fixes the [sidereal_time bug](https://aa.usno.navy.mil/software/novas_faq), whereby the `sidereal_time()` function had an incorrect unit cast. This was a documented issue of NOVAS C 3.1. - Fixes the [ephem_close bug](https://aa.usno.navy.mil/software/novas_faq), whereby `ephem_close()` in `eph_manager.c` did not reset the `EPHFILE` pointer to NULL. This was a documented issue of NOVAS C 3.1. - Fixes antedating velocities and distances for light travel time in `ephemeris()`. When getting positions and velocities for Solar-system sources, it is important to use the values from the time light originated from the observed body rather than at the time that light arrives to the observer. This correction was done properly for positions, but not for velocities or distances, resulting in incorrect observed radial velocities or apparent distances being reported for spectroscopic observations or for angular-physical size conversions. - Fixes bug in `ira_equinox()` which may return the result for the wrong type of equinox (mean vs. true) if the `equinox` argument was changing from 1 to 0, and back to 1 again with the date being held the same. This affected routines downstream also, such as `sidereal_time()`. - Fixes accuracy switching bug in `cio_basis()`, `cio_location()`, `ecl2equ()`, `equ2ecl_vec()`, `ecl2equ_vec()`, `geo_posvel()`, `place()`, and `sidereal_time()`. All these functions returned a cached value for the other accuracy if the other input parameters are the same as a prior call, except the accuracy. - Fixes multiple bugs related to using cached values in `cio_basis()` with alternating CIO location reference systems. This affected many CIRS-based position calculations downstream. - Fixes bug in `equ2ecl_vec()` and `ecl2equ_vec()` whereby a query with `coord_sys = 2` (GCRS) has overwritten the cached mean obliquity value for `coord_sys = 0` (mean equinox of date). As a result, a subsequent call with `coord_sys = 0` and the same date as before would return the results in GCRS coordinates instead of the requested mean equinox of date coordinates. - Some remainder calculations in NOVAS C 3.1 used the result from `fmod()` unchecked, which resulted in angles outside of the expected [0:2π] range and was also the reason why `cal_date()` did not work for negative JD values. - Fixes `aberration()` returning NaN vectors if the `ve` argument is 0. It now returns the unmodified input vector appropriately instead. - Fixes unpopulated `az` output value in `equ2hor()` at zenith. While any azimuth is acceptable really, it results in unpredictable behavior. Hence, we set `az` to 0.0 for zenith to be consistent. - Fixes potential string overflows and eliminates associated compiler warnings. - Nutation series used truncated expressions for the fundamental arguments, resulting in μas-level errors in when dozens or more years away from the reference epoch of J2000. - [__v1.1__] Fixes division by zero bug in `d_light()` if the first position argument is the ephemeris reference position (e.g. the Sun for `solsys3.c`). The bug affects for example `grav_def()`, where it effectively results in the gravitational deflection due to the Sun being skipped. - [__v1.1__] The NOVAS C 3.1 implementation of `rad_vel()` has a number of issues that produce inaccurate results. The errors are typically at or below the tens of m/s level for objects not moving at relativistic speeds. - [__v1.4__] The NOVAS C 3.1 implementation of `cel2ter()` / `ter2cel()` was such that if both `xp` and `yp` parameters were zero, then no wobble correction was applied, not even for the TIO longitude (s'). The error from this omission is very small, at just a few μas (microarcseconds) within a couple of centuries of J2000. - [__v1.6__] The NOVAS C `geo_posvel()` function is imprecise for geodetic observer locations on Earth, since it does not account for polar offsets _x_p, _y_p. As such the geocentric GCRS observer position and velocity vectors are accurate at the tens of meters level only. For Earth-based observers, __SuperNOVAS__ adds `novas_site_gcrs_posvel()` as a more precise alternative.
----------------------------------------------------------------------------- ## Compatibility with NOVAS C 3.1 __SuperNOVAS__ strives to maintain API compatibility with the upstream NOVAS C 3.1 library, but not binary (ABI) compatibility. If you have code that was written for NOVAS C 3.1, it should work with __SuperNOVAS__ as is, without modifications. Simply (re)build your application against __SuperNOVAS__, and you are good to go. The lack of binary compatibility just means that you cannot drop-in replace the libraries (e.g. the static `libnovas.a`, or the shared `libnovas.so`), from NOVAS C 3.1 with those from __SuperNOVAS__. Instead, you will have to build (compile) your application referencing the __SuperNOVAS__ headers and/or libraries from the start. This is because some function signatures have changed, e.g. to use an `enum` argument instead of the nondescript `short int` option arguments used in NOVAS C 3.1, or because we added a return value to a function that was declared `void` in NOVAS C 3.1. We also changed the `object` structure to contain a `long` ID number instead of `short` to accommodate JPL NAIF codes, for which 16-bit storage is insufficient. ----------------------------------------------------------------------------- ## Building and installation - [Build SuperNOVAS using GNU make](#gnu-build) - [Build SuperNOVAS using CMake](#cmake-build) - [Install SuperNOVAS via `vcpkg`](#vcpkg-port) - [Linux packages](#linux-packages) - [Homebrew package](#homebrew) - [Nix package](#nix) ### Build SuperNOVAS using GNU make The __SuperNOVAS__ distribution contains a GNU `Makefile`, which is suitable for compiling the library (as well as local documentation, and tests, etc.) on POSIX systems such as Linux, Mac OS X, BSD, Cygwin or WSL -- using [GNU `make`](https://www.gnu.org/software/make/).
Before compiling the library take a look a `config.mk` and edit it as necessary for your needs, or else define the necessary variables in the shell prior to invoking `make`. For example: - `ENABLE_CPP`: As of v1.6, __SuperNOVAS__ offers a C++11 API and library also, but it is not enabled by default. To build C++ library (`libsupernovas++`), and install the C++ header (`supernovas.h`) and documentation you should set this option to 1, either in your environment or else in `config.mk`. - [CALCEPH](https://www.imcce.fr/recherche/equipes/asd/calceph/) C library integration is automatic on Linux if `ldconfig` can locate the `libcalceph` shared library. You can also control CALCEPH integration manually, e.g. by setting `CALCEPH_SUPPORT = 1` in `config.mk` or in the shell prior to the build. CALCEPH integration will require an accessible installation of the CALCEPH development files (C headers and unversioned static or shared libraries depending on the needs of the build). - [NAIF CSPICE Toolkit](https://naif.jpl.nasa.gov/naif/toolkit.html) integration is automatic on Linux if `ldconfig` can locate the `libcspice` shared library. You can also control CSPICE integration manually, e.g. by setting `CSPICE_SUPPORT = 1` in `config.mk` or in the shell prior to the build. CSPICE integration will require an accessible installation of the CSPICE development files (C headers, under a `cspice/` subfolder in the header search path, and unversioned static or shared libraries depending on the needs of the build). You might want to check out the [Sigmyne/cspice-sharedlib](https://github.com/Sigmyne/cspice-sharedlib) repository for building CSPICE as a shared library. - If your compiler does not support the C11 standard and it is not GCC >=3.3, but provides some nonstandard support for declaring thread-local variables, you may want to pass the keyword to use to declare variables as thread local via `-DTHREAD_LOCAL=...` added to `CFLAGS`. (Don't forget to enclose the string value in escaped quotes in `config.mk`, or unescaped if defining the `THREAD_LOCAL` shell variable prior to invoking `make`.) Additionally, you may set number of environment variables to futher customize the build, such as: - `CC`: The C compiler to use (default: `gcc`). - `CPPFLAGS`: C preprocessor flags, such as externally defined compiler constants. - `CFLAGS`: Flags to pass onto the C compiler (default: `-g -Os -Wall`). Note, `-Iinclude` will be added automatically. - `LDFLAGS`: Extra linker flags (default is _not set_). Note, `-lm` will be added automatically. - `CSTANDARD`: Optionally, specify the C standard to compile for, e.g. `c99` to compile for the C99 standard. If defined then `-std=$(CSTANDARD)` is added to `CFLAGS` automatically. - `WEXTRA`: If set to 1, `-Wextra` is added to `CFLAGS` automatically. - `FORTIFY`: If set it will set the `_FORTIFY_SOURCE` macro to the specified value (`gcc` supports values 1 through 3). It affords varying levels of extra compile time / runtime checks. - `CHECKEXTRA`: Extra options to pass to `cppcheck` for the `make check` target - `DOXYGEN`: Specify the `doxygen` executable to use for generating documentation. If not set (default), `make` will use `doxygen` in your `PATH` (if any). You can also set it to `none` to disable document generation and the checking for a usable `doxygen` version entirely. Now you are ready to build the library: ```bash $ make ``` will compile the shared (e.g. `lib/libsupernovas.so`) libraries, and compile the API documentation (into `doc/`) using `doxygen` (if available). Alternatively, you can build select components of the above with the `make` targets `shared`, and `local-dox` respectively. And, if unsure, you can always call `make help` to see what build targets are available. To build __SuperNOVAS__ as static libraries, use `make static`. After building the library you can install the above components to the desired locations on your system. For a system-wide install you may simply run: ```bash $ sudo make install ``` Or, to install in some other locations, you may set a prefix and/or `DESTDIR`. For example, to install under `/opt` instead, you can: ```bash $ sudo make prefix="/opt" install ``` Or, to stage the installation (to `/usr`) under a 'build root': ```bash $ make DESTDIR="/tmp/stage" install ```
> [!TIP] > On BSD, you will need to use `gmake` instead of `make`. > [!NOTE] > if you want to build __SuperNOVAS__ for with your old NOVAS C applications you might want to further customize the > build. See section on > [legacy application](https://github.com/Sigmyne/SuperNOVAS/blob/main/doc/USAGE-C99.md#legacy-application-c99) in the > [C99 User's guide](USAGE-C99.md). ### Build SuperNOVAS using CMake As of v1.5, __SuperNOVAS__ can be built using [CMake](https://cmake.org/) (many thanks to Kiran Shila). CMake allows for greater portability than the regular GNU `Makefile`. Note, however, that the CMake configuration does not support all of the build options of the GNU `Makefile`, such as automatic CALCEPH and CSPICE integration on Linux, supporting legacy NOVAS C style builds, and code coverage tracking.
The basic build recipe for CMake is: ```bash $ cmake -B build $ cmake --build build ``` The __SuperNOVAS__ CMake build supports the following options (in addition to the standard CMake options): - `BUILD_SHARED_LIBS=ON|OFF` (default: OFF) - Build shared libraries instead of static - `BUILD_DOC=ON|OFF` (default: OFF) - Compile HTML documentation. Requires `doxygen`. - `BUILD_EXAMPLES=ON|OFF` (default: OFF) - Build the included examples - `BUILD_TESTING=ON|OFF` (default: ON - Build regression tests - `BUILD_BENCHMARK=ON|OFF` (default: OFF - Build benchmarking programs - `ENABLE_CPP=ON|OFF` (default: OFF - Build C++11 library (`supernovas++`) also. - `ENABLE_CALCEPH=ON|OFF` (default: OFF) - Optional CALCEPH ephemeris plugin support. Requires `calceph` package. - `ENABLE_CSPICE=ON|OFF` (default: OFF) - Optional CSPICE ephemeris plugin support. Requires `cspice` library installed. For example, to configure the build of __SuperNOVAS__ with shared libraries and with [CALCEPH](https://calceph.imcce.fr) integration for ephemeris support: ```bash $ cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DENABLE_CALCEPH=ON ``` and then perform the build: ```bash $ cmake --build build ``` Or, on Windows (Microsoft Visual C) you will want: ```bash $ cmake --build build --config Release ``` If a `CMAKE_BUILD_TYPE` is not set, the build will only use the `CFLAGS` (if any) that were set in the environment. This is ideal for those who want to have full control of the compiler flags used in the build. Specifying `Release` or `Debug` will append a particular set of appropriate compiler options which are suited for the given build type. (If you want to use the MinGW compiler on Windows, you'll want to set `-DCMAKE_C_COMPILER=gcc -G "MinGW Makefiles"` options also.) After a successful build, you can install the `Runtime` (libraries), and `Development` (headers, CMake config, and `pkg-config`) components, e.g. under `/usr/local`, as: ```bash $ cmake --install build --prefix /usr/local ``` Or, you can use the `--component` option to install just the selected components. For example to install just the `Runtime` component: ```bash $ cmake --install build --component Runtime --prefix /usr/local ```
### Install SuperNOVAS via `vcpkg` As of version 1.5, __SuperNOVAS__ is available through the [vcpkg](https://vcpkg.io/en/) registry. The `vcpkg` port supports a wide range of platforms, including Linux, Windows, MacOS, and Android -- for both `arm64` and `x64` architectures (and in case of Windows also `x86`). It is effectively the same as the CMake build (above), only with more simplicity, convenience, and dependency resolution.
The `vcpkg` port has optional add-on components, which may be installed along with the `core` library as needed. The following components are available: - `core` -- The core C99 library (this is installed by default if no components are specified). - `cpp` -- The C++11 extension runtime and development files. - `solsys-calceph` -- CALCEPH plugin runtime and development files. (It also installs the `calceph` dependency as needed). You can install just the core C99 library of SuperNOVAS (without the C++ API and CALCEPH support) with `vcpkg` as: ```bash $ vcpkg install supernovas ``` Or, a set of selected components library as, such as all the complete installation as: ```bash $ vcpkg install supernovas[core,cpp,solsys-calceph] ```
### Linux packages __SuperNOVAS__ is packaged for Debian, Fedora / EPEL, and NixOS Linux distributions, and derivatives based on these (Ubuntu, Mint, RHEL, CentOS Stream, Alma Linux, Rocky Linux, Oracle Linux etc.).
On Debian-based platforms you might install all components via: ```bash $ sudo apt-get install libsupernovas1 libsupernovas++1 libsolsys-calceph1 libsupernovas-doc libsupernovas-dev ``` And or Fedora / EPEL based distributions as: ```bash $ sudo dnf install supernovas supernovas-c++ supernovas-solsys-calceph supernovas-doc supernovas-devel ``` In both cases the first package is the runtime library, the second is the C++11 runtime library, the third is the runtime for the `solsys-calceph` plugin, the fourth is documentation, and the last one is the files needed for application development.
> [!NOTE] > The turnaround time for Debian packages is quite slow, and typically follows the 6-month Debian release cycle, > whereas the Fedora / EPEL packages are usually fully up-to-date (i.e. in `stable`) within a week of a new SuperNOVAS > release. Somewhat newer Debian versions may be found in `testing`, but even that tends to lag behind the `stable` > Fedora / EPEL updates. ### Homebrew package As of version 1.5, there is also a [Homebrew](https://brew.sh/) package through the maintainer's own Tap.
To install SuperNOVAS via Homebrew, in the recommended default configuration: ```bash $ brew tap attipaci/pub $ brew install supernovas ``` The above will build and install SuperNOVAS with the C++ API extension and the CALCEPH plugin support (including the `calceph` dependency, as needed). However, you may add further options to customize your build: - `--with-cspice` -- Install with NAIF CSPICE support (and dependency). - `--with-doxygen` -- Install with local HTML documentation. - `--without-c++` -- Install without the C++ API extension and runtime. - `--without-calceph` -- Install without CALCEPH support (and dependency).
### Nix package As of version 1.5, there is also a [Nix](https://nixos.org/) [package](https://search.nixos.org/packages?channel=unstable&show=supernovas&query=supernovas). This declarative and determinstic package manager can be used on every Linux distribution as well as MacOS. The default package includes the `solsys-calceph` plugin, but can be overriden by changing `withCalceph`.
Install to your profile with ```bash $ nix profile add nixpkgs#supernovas ``` Or include in your Nix build of other software with ```nix nativeBuildInputs = with pkgs; [supernovas]; ```
----------------------------------------------------------------------------- ## Celestial coordinate systems (old vs. new) | ![SuperNOVAS coordinate systems and conversions](resources/SuperNOVAS-systems.png) | |:--:| | __Figure 1.__ SuperNOVAS Coordinate Systems and Conversions. Functions indicated in bold face are available in NOVAS C also. All other functions are available in SuperNOVAS only. SuperNOVAS also adds efficient [matrix transformations](https://github.com/Sigmyne/SuperNOVAS/blob/main/doc/USAGE-C99.md#transforms-c99) between the equatorial systems. | The IAU 2000 and 2006 resolutions have completely overhauled the system of astronomical coordinate transformations to enable higher precision astrometry. (Super)NOVAS supports coordinate calculations both in the old (pre IAU 2000) ways, and in the new IAU standard method. The table below provides an overview of how the old and new methods define some of the terms differently: | Concept | Old standard | New IAU standard | |:-------------------------- | ----------------------------- | ------------------------------------------------- | | Catalog coordinate system | MOD (e.g. FK4, FK5, HIP...) | International Celestial Reference System (ICRS) | | Dynamical system | True of Date (TOD) | Celestial Intermediate Reference System (CIRS) | | Dynamical R.A. origin | equinox of date | Celestial Intermediate Origin (CIO) | | Precession, nutation, bias | no tidal terms | IAU 2000/2006 precession/nutation model | | Celestial Pole offsets | dψ, dε (for TOD) | _x_p, _y_p (for ITRS) | | Earth rotation measure | Greenwich Sidereal Time (GST) | Earth Rotation Angle (ERA) | | Pseudo Earth-fixed system | PEF | Terrestrial Intermediate Reference System (TIRS) | | Earth rotation origin | Greenwich Meridian | Terrestrial Intermediate Origin (TIO) | | Earth-fixed System | WGS84 | International Terrestrial Reference System (ITRS) | See the various enums and constants defined in `novas.h`, as well as the descriptions on the various NOVAS routines on how they are appropriate for the old and new methodologies respectively. Figure 1 also shows the relation of the various old and new coordinate systems and the (Super)NOVAS functions for converting position / velocity vectors among them. > [!NOTE] > In NOVAS, the barycentric BCRS and the geocentric GCRS systems are effectively synonymous to ICRS, since the origin > for positions and for velocities, in any reference system, is determined by the `observer` location. Aberration and > gravitational deflection correction included for apparent places only (as seen from the observer location, > regardless of where that is), but not for geometric places. > [!TIP] > Older catalogs, such as J2000 (FK5), HIP, B1950 (FK4) or B1900 are just special cases of MOD (mean-of-date) > coordinates for the J2000, J1991.25, B1950, and B1900 epochs, respectively. > [!CAUTION] > Applying residual polar offsets (Δdψ, Δdε or _x_p, _y_p) to the > TOD equator (via `cel_pole()`) is discouraged. Instead, the sub-arcsecond level corrections to Earth orientation > (_x_p, _y_p) should be used only for converting between the pseudo Earth-fixed (PEF or TIRS) > and ITRS, and vice-versa (e.g. with `novas_make_frame()` or `wobble()`). > [!NOTE] > WGS84 has been superseded by ITRS for higher accuracy definitions of Earth-based locations. WGS84 matches ITRS to > the 10m level globally, but it does not account for continental drifts and crustal motion. In (Super)NOVAS all > Earth-base locations are presumed ITRS. ITRS longitude, latitude, and altitude coordinates are referenced to the > GRS80 ellipsoid, whereas GPS locations are referenced to the WGS84 ellipsoid. __SuperNOVAS__ offers ways to convert > between the two if needed. ----------------------------------------------------------------------------- ## Example use cases - [Recommendation: set up an ephemeris provider](#recommendation) - [Pick you flavor (C or C++)](#usage-flavors) ### Recommendation: set up an ephemeris provider __SuperNOVAS__ can do a lot of things on its own. What it cannot do alone is provide precise positions for Solar-system bodies. For that, you need ephemeris data and a helping hand from an external tool to access them. Even if you don't particularly care to obtain precise planet positions per se, they are needed for a range of high-precision calculations (such as for positional calculations for Earth-based observers, and gravitational deflections in full-precision observing frames). Therefore, it is strongly recommended that you download [planetary ephemeris files from NASA / JPL](https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/) (such as the DE440, or the smaller DE440s, or the long-term DE441), and install [CALCEPH](https://calceph.imcce.fr/) or the [CSPICE Toolkit](https://naif.jpl.nasa.gov/naif/toolkit.html) for accessing these. I recommend CALCEPH, because it is more widely available (also in packaged form), and it is also more modern, and actively maintained. Provided you installed CALCEPH, you usage of __SuperNOVAS__ should always start with something like this (regardless of whether you will use the C99 or the C++ API afterwards): ```c #include // Use DE440, DE440s, or DE441 as your planet provider... t_calcephbin *pleph = calceph_open("/path/to/de440.bsp"); status = novas_use_calceph_planets(pleph); if(status < 0) { // Oops something went wrong... } ``` Don't forget to link with `-lsolsys-calceph` and `-lcalceph` flags added you yor build. With that, you have now unlocked a lot of the high-precision capabilities of __SuperNOVAS__. Have fun with it! For more details on using CALCEPH or integrating other ways for providing ephemeris data to __SuperNOVAS__ look at the [section below](#solarsystem). ### Pick your flavor (C or C++) As of v1.6 __SuperNOVAS__ comes in two flavors, the original C99 API, and a higher-level C++11 API. Depending on which one you intend to use, choose the appropriate link to an external document below for further information: - [Using the C99 API](USAGE-C99.md) - [Using the C++11 API](USAGE-CPP.md) ----------------------------------------------------------------------------- ## Incorporating Solar-system ephemeris data or services If you want to use __SuperNOVAS__ to calculate positions for a range of Solar-system objects, and/or to do it with precision, you will have to interface it to a suitable provider of ephemeris data. The preferred ways to do that in __SuperNOVAS__ enumerated below. (The legacy NOVAS C ways are not covered here, since they require specialized builds of __SuperNOVAS__, which are covered [separately](https://github.com/Sigmyne/SuperNOVAS/blob/main/doc/USAGE-C99.md#legacy-application).) NASA/JPL provides [generic ephemerides](https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/) for the major planets, satellites thereof, the 300 largest asteroids, the Lagrange points, and some Earth orbiting stations. For example, [DE440](https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de440.bsp) covers the major planets, and the Sun, Moon, and barycenters for times between 1550 AD and 2650 AD. Or, you can use the [JPL HORIZONS](https://ssd.jpl.nasa.gov/horizons/) system (via the command-line / telnet or API interfaces) to generate custom ephemerides (SPK/BSP) for just about all known solar systems bodies, down to the tiniest rocks. - [CALCEPH integration](#calceph-integration) - [NAIF CSPICE toolkit integration](#cspice-integration) - [Universal ephemeris data / service integration](#universal-ephemerides) ### CALCEPH integration The [CALCEPH](https://www.imcce.fr/recherche/equipes/asd/calceph/) library provides easy-to-use access to JPL and INPOP ephemeris files from C/C++. As of version 1.2, we provide optional support for interfacing __SuperNOVAS__ with the the CALCEPH C library for handling Solar-system objects.
Prior to building __SuperNOVAS__ simply set `CALCEPH_SUPPORT` to 1 in `config.mk` or in your environment (or for CMake configure with the `-DENABLE_CALCEPH=ON`). Depending on the build target (or type), it will build `libsolsys-calceph.so[.1]` (target `shared` or CMake option `-DBUILD_SHARED_LIBS=ON1`) or `libsolsys-calceph.a` (target `static` or default CMake build) libraries or `solsys-calceph.o` (target `solsys`, no CMake equivalent), which provide the `novas_use_calceph()` and `novas_use_calceph_planets()`, and `novas_calceph_use_ids()` functions. Of course, you will need access to the CALCEPH C development files (C headers and unversioned `libcalceph.so` or `.a` library) for the build to succeed. Here is an example on how you'd use CALCEPH with __SuperNOVAS__ in your application code: First and foremost, you should use CALCEPH to provide planet positions via the DE440 or DE440s (smaller file size) or DE441 (long term) ephemeris data: ```c #include // Use DE440, DE440s, or DE441 as your planet provider... t_calcephbin *pleph = calceph_open("/path/to/de440.bsp"); status = novas_use_calceph_planets(pleph); if(status < 0) { // Oops something went wrong... } ``` Even if you don't care for the planets, you'll still need the planetary ephemeris for a lot of the high-precision calculations, so don't skip on this step if you can help it. Beyond just the planets, you might want to download and use further ephemeris data, such as for the many moons orbiting planets, the major asteroids, various minor bodies of interest (e.g. comets, NEOs), or man-made spacecrafts. You can activate an additional set (or sets) of ephemeris files separately from the planetary ephemeris above. For example: ```c // Open all files that you will use concurrently t_calcephbin *eph = calceph_open_array(...); // Tell SperNOVAS to use CALCEPH with these files for obtaining // positions for objects contained within them int status = novas_use_calceph(eph); if(status < 0) { // Oops something went wrong... } ``` All modern JPL (SPK) ephemeris files should work with the `solsys-calceph` plugin. When linking your application, add `-lsolsys-calceph` to your link flags (or else link with `solsys-calceph.o`), and link against the CALCEPH library also (`-lcalceph`). That's all there is to it. When using CALCEPH, ephemeris objects are referenced by their ID numbers (`object.number`), unless it is set to -1, in which case name-based lookup will be used instead. ID numbers are assumed to be NAIF by default, but `novas_calceph_use_ids()` can select between NAIF or CALCEPH numbering systems, if necessary.
### NAIF CSPICE toolkit integration The [NAIF CSPICE Toolkit](https://naif.jpl.nasa.gov/naif/toolkit.html) is the canonical standard library for JPL ephemeris files from C/C++. As of version 1.2, we provide optional support for interfacing __SuperNOVAS__ with CSPICE for handling Solar-system objects.
Prior to building __SuperNOVAS__ simply set `CSPICE_SUPPORT` to 1 in `config.mk` or in your environment (or for CMake configure with `-DENABLE_CSPICE=ON`). Depending on the build target, it will build `libsolsys-cspice.so[.1]` (target `shared` or CMake option `-DBUILD_SHARED_LIBS=ON`) or `libsolsys-cspice.a` (target `static` or default CMake build) libraries or `solsys-cspice.o` (target `solsys`, no CMake equivalent), which provide the `novas_use_cspice()`, `novas_use_cspice_planets()`, and `novas_use_cspice_ephem()` functions to enable CSPICE for providing data for all Solar-system sources, or for major planets only, or for other bodies only, respectively. You can also manage the active kernels with the `cspice_add_kernel()` and `cspice_remove_kernel()` functions. Of course, you will need access to the CSPICE development files (C headers, installed under a `cspice/` directory of a header search location, and the unversioned `libcspice.so` or `.a` library) for the build to succeed. You may want to check out the [Sigmyne/cspice-sharedlib](https://github.com/Sigmyne/cspice-sharedlib) GitHub repository to help you build CSPICE with shared libraries and dynamically linked tools. Here is an example on how you might use CSPICE with __SuperNOVAS__ in your application code: ```c #include // You can load the desired kernels for CSPICE // E.g. load DE440s and the Mars satellites: int status; status = cspice_add_kernel("/path/to/de440s.bsp"); if(status < 0) { // oops, the kernels must not have loaded... ... } // Load additional kernels as needed... status = cspice_add_kernel("/path/to/mar097.bsp"); ... // Then use CSPICE as your SuperNOVAS ephemeris provider novas_use_cspice(); ``` All JPL ephemeris data will work with the `solsys-cspice` plugin. When linking your application, add `-lsolsys-cspice` to your link flags (or else link with `solsys-cspice.o`), and of course the CSPICE library also. That's all there is to it. When using CSPICE, ephemeris objects are referenced by their NAIF ID numbers (`object.number`), unless that number is set to -1, in which case name-based lookup will be used instead.
### Universal ephemeris data / service integration Possibly the most universal way to integrate ephemeris data with __SuperNOVAS__ is to write your own `novas_ephem_provider` function.
```c int my_ephem_reader(const char *name, long id, double jd_tdb_high, double jd_tdb_low, enum novas_origin *restrict origin, double *restric pos, double *restrict vel) { // Your custom ephemeris reader implementation here ... } ``` which takes an object ID number (such as a NAIF), an object name, and a split TDB date (for precision) as it inputs, and returns the type of origin with corresponding ICRS position and velocity vectors in the supplied pointer locations. The function can use either the ID number or the name to identify the object or file (whatever is the most appropriate for the implementation and for the supplied parameters). The positions and velocities may be returned either relative to the SSB or relative to the heliocenter, and accordingly, your function should set the value pointed at by origin to `NOVAS_BARYCENTER` or `NOVAS_HELIOCENTER` accordingly. Positions and velocities are rectangular ICRS _x,y,z_ vectors in units of AU and AU/day respectively. This way you can easily integrate current ephemeris data, e.g. for the Minor Planet Center (MPC), or whatever other ephemeris service you prefer.
Once you have your adapter function, you can set it as your ephemeris service via `set_ephem_provider()`: ```c set_ephem_provider(my_ephem_reader); ``` By default, your custom `my_ephem_reader` function will be used for `NOVAS_EPHEM_OBJECT` type objects only (i.e. anything other than the major planets, the Sun, Moon, Solar-system Barycenter...). But, you can use the same function for the major planets (`NOVAS_PLANET` type objects) also via: ```c set_planet_provider(planet_ephem_provider); set_planet_provider_hp(planet_ephem_provider_hp); ``` The above simply instructs __SuperNOVAS__ to use the same ephemeris provider function for planets as what was set for `NOVAS_EPHEM_OBJECT` type objects, provided you compiled __SuperNOVAS__ with `BUILTIN_SOLSYS_EPHEM = 1` (in `config.mk`), or else you link your code against `solsys-ephem.c` explicitly. Easy-peasy. ## Notes on precision - [Prerequisites to precise results](#accuracy-prerequisites) - [Reduced accuracy shortcuts](#reduced-accuracy) Many of the (Super)NOVAS functions take an accuracy argument, which determines to what level of precision quantities are calculated. The argument can have one of two values, which correspond to typical precisions around: | `enum novas_accuracy` value | Typical precision | | ---------------------------- |:-------------------------------- | | `NOVAS_REDUCED_ACCURACY` | ~ 1 milli-arcsecond (mas) | | `NOVAS_FULL_ACCURACY` | ~ 1 micro-arcsecond (μas) | Note, that some functions will not support full accuracy calculations, unless you have provided a high-precision ephemeris provider for the major planets (and any Solar-system bodies of interest), which does not come with __SuperNOVAS__ out of the box. In the absence of a suitable high-precision ephemeris provider, some functions might return an error if called with `NOVAS_FULL_ACCURACY`. (Click on the wedges next to each component to expand the details...) ### Prerequisites to precise results The __SuperNOVAS__ library is in principle capable of calculating positions to microarcsecond, and velocities to mm/s, precision for all types of celestial sources. However, there are certain prerequisites and practical considerations before that level of accuracy is reached. (Click on the wedge next to each heading below to expand the details.)
The IAU 2000/2006 conventions and methods High precision calculations will generally require that you use __SuperNOVAS__ with the new IAU standard quantities and methods. The old ways were simply not suited for precision much below the milliarcsecond level. In particular, Earth orientation parameters (EOP) should be applied only for converting between TIRS and ITRS systems, and defined either with `novas_make_frame()` or else with `wobble()`. The old ways of incorporating (global) offsets in TOD coordinates via `cel_pole()` should be avoided.
Gravitational effects Calculations much below the milliarcsecond level will require accounting for gravitational bending around massive Solar-system bodies, and hence will require you to provide a high-precision ephemeris provider for the major planets. Without it, there is no guarantee of achieving precision below the milli-arcsecond level in general, especially when observing near the Sun or massive planets (e.g. observing Jupiter's or Saturn's moons, near conjunction with their host planet). Therefore, some functions will return with an error, if used with `NOVAS_FULL_ACCURACY` in the absence of a suitable high-precision planetary ephemeris provider.
Solar-system ephemeris Precise calculations for Solar-system sources requires precise ephemeris data for both the target object as well as for Earth, and the Sun. For the highest precision calculations you also need positions for all major planets to calculate gravitational deflection precisely. By default, __SuperNOVAS__ can only provide approximate positions for the Earth and Sun (see `earth_sun_calc()`) at the tens of arcsecond level. You will need to provide a way to interface __SuperNOVAS__ with a suitable ephemeris source (such as CALCEPH, or the CSPICE toolkit from JPL) to obtain precise positions for Solar-system bodies. See the [section further above](#solarsystem) for more information how you can do that.
Earth orientation parameters (EOP) Calculating precise positions for any Earth-based observations requires precise knowledge of Earth orientation parameters (EOP) at the time of observation. Earth's pole is subject to predictable precession and nutation, but also small irregular and diurnal variations in the orientation of the rotational axis and the rotation period (a.k.a. polar wobble). You can apply the EOP values in `novas_set_time()` (for UT1-UTC), and `novas_make_frame()` (_x_p and _y_p) to improve the astrometric precision of Earth based coordinate calculations. Without the EOP values, positions for Earth-based calculations will be accurate at the tenths of arcsecond level only. The [IERS Bulletins](https://www.iers.org/IERS/EN/Publications/Bulletins/bulletins.html) provide up-to-date measurements, historical data, and near-term projections for the polar offsets, the UT1-UTC time difference, and leap-seconds (UTC-TAI). For sub-milliarcsecond accuracy the values published by IERS should be interpolated before passing to the likes of `novas_set_time()` or `novas_make_frame()`. At the micro-arcsecond (μas) level, you will need to ensure also that the EOP values are provided for the same ITRF realization as the observer's location, e.g. via `novas_itrf_transform_eop()`.
Atmospheric refraction model Ground based observations are subject to atmospheric refraction. __SuperNOVAS__ offers the option to include refraction corrections with a set of atmospheric models, or using models you provide. Estimating refraction accurately requires local weather parameters (pressure, temperature, and humidity), which may be be specified within the `on_surface` data structure alongside the observer location. A standard radio refraction model is included as of version __1.1__, as well as our implementation of the wavelength-dependent IAU refraction model (`novas_wave_refraction()` since version 1.4) based on the SOFA `iauRefco()` function. If none of the built-in options satisfies your needs, you may also implement your own refraction correction to use.
### Reduced accuracy shortcuts When one does not need positions at the microarcsecond level, some shortcuts can be made to the recipe above: - You may forgo reconciling the ITRF realizations of EOP vs. an Earth-based observing site, if precision at the microarcsecond level is not required. - You may skip the interpolation of published EOP values, if accuracy below the milliarcsecond level is not required. - You can use `NOVAS_REDUCED_ACCURACY` instead of `NOVAS_FULL_ACCURACY` for the calculations. This typically has an effect at or below the milliarcsecond level only, but may be much faster to calculate. - You might skip the pole offsets _x_p, _y_p. These are tenths of arcsec, typically. - You may not need to interface to an ephemeris provider if you don't need positions for Solar-system objects, and you are willing to ignore gravitational redhifts / deflections around Solar-system bodies. ----------------------------------------------------------------------------- ## Runtime debug support You can enable or disable debugging output to `stderr` with `novas_debug(enum novas_debug_mode)`, where the argument is one of the defined constants from `novas.h`: | `novas_debug_mode` value | Description | | -------------------------- |:-------------------------------------------------- | | `NOVAS_DEBUG_OFF` | No debugging output (_default_) | | `NOVAS_DEBUG_ON` | Prints error messages and traces to `stderr` | | `NOVAS_DEBUG_EXTRA` | Same as above but with stricter error checking | The main difference between `NOVAS_DEBUG_ON` and `NOVAS_DEBUG_EXTRA` is that the latter will treat minor issues as errors also, while the former may ignore them. For example, `place()` will return normally by default if it cannot calculate gravitational bending around massive planets in full accuracy mode. It is unlikely that this omission would significantly alter the result in most cases, except for some very specific ones when observing in a direction close to a major planet. Thus, with `NOVAS_DEBUG_ON`, `place()` go about as usual even if the Jupiter's position is not known. However, `NOVAS_DEBUG_EXTRA` will not give it a free pass, and will make `place()` return an error (and print the trace) if it cannot properly account for gravitational bending around the major planets as it is expected to. When debug mode is enabled, any error condition (such as NULL pointer arguments, or invalid input values etc.) will be reported to the standard error, complete with call tracing within the __SuperNOVAS__ library, s.t. users can have a better idea of what exactly did not go to plan (and where). The debug messages can be disabled by passing `NOVAS_DEBUG_OFF` (0) as the argument to the same call. Here is an example error trace when your application calls `grav_def()` with `NOVAS_FULL_ACCURACY` while `solsys3` provides Earth and Sun positions only and when debug mode is `NOVAS_DEBUG_EXTRA` (otherwise we'll ignore that we skipped the almost always negligible deflection due to planets): ``` ERROR! earth_sun_calc: invalid or unsupported planet number: 6 [=> 2] @ earth_sun_calc_hp [=> 2] @ ephemeris:planet [=> 12] @ light_time2 [=> 22] @ obs_planets [=> 12] @ grav_def [=> 12] ``` You can use the built-in error tracing to identify where things go awry in your code. You can turn on error tracing for your entire code, or for a relevant section, in which a __SuperNOVAS__ function returns an error (such as -1 or NaN), e.g.: ```c novas_debug(NOVAS_DEBUG_ON); // The part of your code that might have to do with the error return... ... novas_debug(NOVAS_DEBUG_OFF); ``` ----------------------------------------------------------------------------- ## Representative benchmarks To get an idea of the speed of __SuperNOVAS__, you can use `make benchmark` on your machine. Figure 2 below summarizes the single-threaded results obtained with v1.5.0 on an AMD Ryzen 5 PRO 6650U laptop. While this is clearly not the state of the art for today's server class machines, it nevertheless gives you a ballpark idea for how a typical, not so new, run-of-the-mill PC might perform. | ![SuperNOVAS benchmarks](resources/SuperNOVAS-benchmark.png) | |:--:| | __Figure 2.__ SuperNOVAS apparent position calculation benchmarks, including proper motion, the IAU 2000 precession-nutation model, polar wobble, aberration, and gravitational deflection corrections, and precise spectroscopic redhift calculations. | The tests calculate apparent positions (in CIRS) for a set of sidereal sources with random parameters, using either the __SuperNOVAS__ `novas_sky_pos()` or the legacy NOVAS C `place()`, both in full accuracy and reduced accuracy modes. The two methods are equivalent, and both include calculating a precise geometric position, as well as aberration and gravitational deflection corrections from the observer's point of view.
| Description | accuracy | positions / sec | |:----------------------------------- |:---------:| ---------------:| | `novas_sky_pos()`, same frame | reduced | 3130414 | | | full | 3149028 | | `place()`, same time, same observer | reduced | 831101 | | | full | 831015 | | `novas_sky_pos()`, individual | reduced | 168212 | | | full | 25943 | | `place()`, individual | reduced | 167475 | | | full | 25537 | For reference, we also provide the reduced accuracy benchmarks from NOVAS C 3.1. | Description | accuracy | positions / sec | |:------------------------------------|:---------:|----------------:| | NOVAS C 3.1 `place()`, same frame | reduced | 371164 | | NOVAS C 3.1 `place()`, individual | reduced | 55484 | For comparison, a very similar benchmark with [astropy](https://www.astropy.org/) (v7.0.0 on Python v3.13.1) on the same machine, provides ~70 positions / second both for a fixed frame and for individual frames. As such, __SuperNOVAS__ is a whopping ~40000 times faster than __astropy__ for calculations in the same observing frame, and 400--2000 times faster than __astropy__ for individual frames. (The __astropy__ benchmarking code is also provided under the `benchmark/` folder in the __SuperNOVAS__ GitHub repository). | Description | positions / sec | |:------------------------------------------------|----------------:| | __astropy__ 7.0.0 (python 3.13.1), same frame | 71 | | __astropy__ 7.0.0 (python 3.13.1), individual | 70 |
As one may observe, the __SuperNOVAS__ `novas_sky_pos()` significantly outperforms the legacy `place()` function, when repeatedly calculating positions for sources for the same instant of time and same observer location, providing 3--4 times faster performance than `place()` with the same observer and time. The same performance is maintained even when cycling through different frames, a usage scenario in which the performance advantage over `place()` may be up to 2 orders of magnitude. When observing frames are reused, the performance is essentially independent of the accuracy. By contrast, calculations for individual observing times or observer locations are generally around twice a fast if reduced accuracy is sufficient. The above benchmarks are all for single-threaded performance. Since __SuperNOVAS__ is generally thread-safe, you can expect that performance shall scale with the number of concurrent CPUs used. So, on a 16-core PC, with similar single core performance, you could calculate up to 32 million precise positions per second, if you wanted to. To put that into perspective, you could calculate precise apparent positions for the entire Gaia dataset (1.7 billion stars) in under one minute. ----------------------------------------------------------------------------- ## SuperNOVAS added features - [Newly functionality highlights](#added-functionality) - [Refinements to the NOVAS C API](#api-changes) ### New functionality highlights Below is a non-exhaustive overview new features added by __SuperNOVAS__ on top of the existing NOVAS C API. See [`CHANGELOG.md`](https://github.com/Sigmyne/SuperNOVAS/blob/main/CHANGELOG.md) for more details.
New in v1.0 - New runtime configuration: * The planet position, and generic Solar-system position calculator functions can be set at runtime, and users can provide their own custom implementations, e.g. to read ephemeris data, such as from a JPL `.bsp` file. * If CIO locations vs GCRS are important to the user, the user may call `set_cio_locator_file()` at runtime to specify the location of the binary CIO interpolation table (e.g. `CIO_RA.TXT` or `cio_ra.bin`) to use, even if the library was compiled with the different default CIO locator path. * The default low-precision nutation calculator `nu2000k()` can be replaced by another suitable IAU 2006 nutation approximation. For example, the user may want to use the `iau2000b()` model or some custom algorithm instead. - New constants, and enums -- adding more specificity and transparency to option switches and physical units. - Many new functions to provide more coordinate transformations, inverse calculations, and more intuitive usage.
New in v1.1 - New observing-frame based approach for calculations (`frames.c`). A `novas_frame` object uniquely defines both the place and time of observation, with a set of precalculated transformations and constants. Once the frame is defined it can be used very efficiently to calculate positions for multiple celestial objects with minimum additional computational cost. The frames API is also more elegant and more versatile than the low-level NOVAS C approach for performing the same kind of calculations. And, frames are inherently thread-safe since post-creation their internal state is never modified during the calculations. - New `novas_timespec` structure for the self-contained definition of precise astronomical time (`timescale.c`). You can set the time to a JD date in the timescale of choice (UTC, UT1, GPS, TAI, TT, TCG, TDB, or TCB), or to a UNIX time. Once set, you can obtain an expression of that time in any timescale of choice. And, you can create a new time specification by incrementing an existing one, or measure precise time differences. - New coordinate reference systems `NOVAS_MOD` (Mean of Date) which includes precession but not nutation and `NOVAS_J2000` for the J2000 dynamical reference system. - New observer locations `NOVAS_AIRBORNE_OBSERVER` and `NOVAS_SOLAR_SYSTEM_OBSERVER`, and corresponding `make_airborne_observer()` and `make_solar_system_observer()` functions. Airborne observers have an Earth-fixed momentary location, defined by longitude, latitude, and altitude, the same way as for a stationary observer on Earth, but are moving relative to the surface, such as in an aircraft or balloon based observatory. Solar-system observers are similar to observers in Earth-orbit but their momentary position and velocity is defined relative to the Solar System Barycenter (SSB), instead of the geocenter. - New set of built-in refraction models to use with the frame-based functions, including a radio refraction model based on the formulae by Berman & Rockwell 1976. Users may supply their own custom refraction model also, and may make use of the generic reversal function `novas_inv_refract()` to calculate refraction in the reverse direction (observed vs astrometric elevations as the input) as needed.
New in v1.2 - New functions to calculate and apply additional gravitational redshift corrections for light that originates near massive gravitating bodies (other than major planets, or Sun or Moon), or for observers located near massive gravitating bodies (other than the Sun and Earth). - [CALCEPH integration](#calceph-integration) to specify and use ephemeris data via the CALCEPH library for Solar-system sources in general, and for major planets specifically. - [NAIF CSPICE integration](#cspice-integration) to use the NAIF CSPICE library for all Solar-system sources, or for major planets or other bodies only. - Added support for using orbital elements. `object.type` can now be set to `NOVAS_ORBITAL_OBJECT`, whose orbit can be defined by `novas_orbital`, relative to a `novas_orbital_system`. While orbital elements do not always yield precise positions, they can for shorter periods, provided that the orbital elements are up-to-date. For example, the [Minor Planet Center](https://www.minorplanetcenter.net/iau/mpc.html) (MPC) publishes accurate orbital elements for all known asteroids and comets regularly. For newly discovered objects, this may be the only and/or most accurate information available anywhere. - Added `NOVAS_EMB` (Earth-Moon Barycenter) and `NOVAS_PLUTO_BARYCENTER` to `enum novas_planets` to distinguish from the corresponding planet centers in calculations. - Added more physical unit constants to `novas.h`.
New in v1.3 - New functions to aid the conversion of LSR velocities to SSB-based velocities, and vice-versa. (Super)NOVAS always defines catalog sources with SSB-based radial velocities, but some catalogs provide LSR velocities. - New functions to convert dates/times and angles to/from their string representations. - New functions to convert between Julian Days and calendar dates in the calendar of choice (astronomical, Gregorian, or Roman/Julian). - New convenience functions for oft-used astronomical calculations, such as rise/set times, LST, parallactic angle (a.k.a. Vertical Position Angle), heliocentric distance, illumination fraction, or incident solar power, Sun and Moon angles, and much more. - New functions and data structures provide second order Taylor series expansion of the apparent horizontal or equatorial positions, distances, and redshifts for sources. These values, including rates and accelerations, can be directly useful for controlling telescope drives in horizontal or equatorial mounts to track sources. You can also use them to obtain instantaneous projected (extrapolated) positions at low computational cost.
New in v1.4 - Updated nutation model from IAU2000 to IAU2006 (P03) model, by applying scaling factors (Capitaine et al. 2005) to match the IAU2006 precession model that was already implemented in NOVAS. - Approximate Keplerian orbital models for the major planets (Standish & Williams, 1992), EMB, and the Moon (Chapront et al. 2002), for when arcmin-scale accuracy is sufficient (e.g. rise or set times, approximate sky positions). - Moon phase calculator functions, based on above orbital modeling. - Improved support for expressing and using coordinates in TIRS (Terrestrial Intermediate Reference System) and ITRS (International Terrestrial Reference System). - Improvements to atmospheric refraction modeling.
New in v1.5 - Simpler functions to calculate Greenwich Mean and Apparent Sidereal Time (GMST / GAST). - Functions to calculate corrections to the Earth orientation parameters published by IERS, to include the effect of libration and ocean tides. Such corrections are necessary to include if needing or using ITRS / TIRS coordinates with accuracy below the milliarcsecond (mas) level. - New functions to simplify the handling ground-based observing locations (GPS vs ITRF vs Cartesian locations), including setting default weather values, at least until actual values are specified if needed, and conversion between geodetic (longitude, latitude, altitude) and geocentric Cartesian (x, y, z) site coordinates using the reference ellipsoid of choice (e.g. GRS80 or WGS84). - Transformations of site coordinates and Earth orientation parameters between different ITRF realizations (e.g. ITRF2000 and ITRF2014). - Functions to calculate the rate at which an observer's clock ticks differently from a standard astronomical timescale, due to the gravitational potential around the observer and the observer's movement. - No longer using a CIO vs GCRS locator data file in any way, thus eliminating an annoying external soft dependency. This change has absolutely zero effect on backward compatibility and functionality. - GNU `make` build support for Mac OS X and FreeBSD (co-authored with Kiran Shila). - CMake build support (co-authored with Kiran Shila).
New in v1.6 - Introducing a new, high-level, C++11 API (`libsupernovas++`) on top of the standard C99 one. - Added a truncated version of the ELP2000 / MPP02 semi-analytical model of the Moon (Chapront & Francou 2003), allowing arcsec (km) level position calculations for the Moon even without ephemeris data.
### Refinements to the NOVAS C API Many __SuperNOVAS__ changes are focused on improving the usability and promote best coding practices so that both the library and your application will be safer, and less prone to nagging errors. Below is a detailed listing of the principal ways __SuperNOVAS__ has improved on the original NOVAS C library in these respects.
- Changed to support for calculations in parallel threads by making cached results thread-local. This works using the C11 standard `_Thread_local`, or the C23 `thread_local`, or else the earlier GNU C >= 3.3 standard `__thread` modifier. You can also set the preferred thread-local keyword for your compiler by passing it via `-DTHREAD_LOCAL=...` in `config.mk` to ensure that your build is thread-safe. And, if your compiler has no support whatsoever for thread_local variables, then __SuperNOVAS__ will not be thread-safe, just as NOVAS C isn't. - __SuperNOVAS__ functions take `enum`s as their option arguments instead of raw integers. The enums allow for some compiler checking (e.g. using the wrong enum), and make for more readable code that is easier to debug. They also make it easy to see what choices are available for each function argument, without having to consult the documentation each and every time. - All __SuperNOVAS__ functions check for the basic validity of the supplied arguments (Such as NULL pointers, or empty strings) and will return -1 (with `errno` set, usually to `EINVAL`) if the arguments supplied are invalid (unless the NOVAS C API already defined a different return value for specific cases. If so, the NOVAS C error code is returned for compatibility). - All erroneous returns now set `errno` so that users can track the source of the error in the standard C way and use functions such as `perror()` and `strerror()` to print human-readable error messages. - __SuperNOVAS__ prototypes declare function pointer arguments as `const` whenever the function does not modify the data content being pointed at. This supports better programming practices that generally aim to avoid unintended data modifications. - Many __SuperNOVAS__ functions allow `NULL` arguments, both for optional input values as well as outputs that are not required (see the [C99 API Documentation](https://sigmyne.github.io/SuperNOVAS/doc/html/) for specifics). This eliminates the need to declare dummy variables in your application code. - Many output values supplied via pointers are set to clearly invalid values in case of erroneous returns, such as `NAN` so that even if the caller forgets to check the error code, it becomes obvious that the values returned should not be used as if they were valid. (No more sneaky silent failures.) - All __SuperNOVAS__ functions that take an input vector to produce an output vector allow the output vector argument be the same as the input vector argument. For example, `frame_tie(pos, J2000_TO_ICRS, pos)` using the same `pos` vector both as the input and the output. In this case the `pos` vector is modified in place by the call. This can greatly simplify usage, and eliminate extraneous declarations, when intermediates are not required. - Catalog names can be up to 6 bytes (including termination), up from 4 in NOVAS C, while keeping `struct` layouts the same as NOVAS C thanks to alignment, thus allowing cross-compatible binary exchange of `cat_entry` records with NOVAS C 3.1. - Changed `make_object()` to retain the specified number argument (which can be different from the `starnumber` value in the supplied `cat_entry` structure). - `cio_location()` will always return a valid value as long as neither output pointer argument is NULL. (NOVAS C 3.1 would return an error if a CIO locator file was previously opened but cannot provide the data for whatever reason). - `cel2ter()` and `ter2cel()` can now process 'option'/'class' = 1 (`NOVAS_REFERENCE_CLASS`) regardless of the methodology (`EROT_ERA` or `EROT_GST`) used to input or output coordinates in GCRS. - More efficient paging (cache management) for `cio_array()`, including I/O error checking. - IAU 2000A nutation model uses higher-order Delaunay arguments provided by `fund_args()`, instead of the linear model in NOVAS C 3.1. - IAU 2000 nutation made a bit faster, reducing the the number of floating-point multiplications necessary by skipping terms that do not contribute. Its coefficients are also packed more frugally in memory, resulting in a smaller footprint. - Changed the standard atmospheric model for (optical) refraction calculation to include a simple model for the annual average temperature at the site (based on latitude and elevation). This results is a slightly more educated guess of the actual refraction than the global fixed temperature of 10 °C assumed by NOVAS C 3.1 regardless of observing location. - [__v1.1__] Improved the precision of some calculations, like `era()`, `fund_args()`, and `planet_lon()` by being more careful about the order in which terms are accumulated and combined, resulting in a small improvement on the few uas (micro-arcsecond) level. - [__v1.1__] `place()` now returns an error 3 if and only if the observer is at (or very close, within ~1.5m) of the observed Solar-system object. - [__v1.1__] `grav_def()` is simplified. It no longer uses the location type argument. Instead it will skip deflections due to a body if the observer is within ~1500 km of its center (which is below the surface for all major Solar system bodies). - [__v1.1.1__] For major planets (and Sun and Moon) `rad_vel()` and `place()` will include gravitational corrections to radial velocity for light originating at the surface, and observed near Earth or at a large distance away from the source. - [__v1.3__] In reduced accuracy mode apply gravitational deflection for the Sun only. In prior versions, deflection corrections were applied for Earth too. However, these are below the mas-level accuracy promised in reduced accuracy mode, and without it, the calculations for `place()` and `novas_sky_pos()` are significantly faster. - [__v1.3__] `julian_date()` and `cal_date()` now use astronomical calendar dates instead of the fixed Gregorian dates of before. Astronomical dates are Julian/Roman calendar dates prior to the Gregorian calendar reform of 1582. - [__v1.3__] Use C99 `restrict` keyword to prevent pointer argument aliasing as appropriate. - [__v1.4.2__] Nutation models have been upgraded from the original IAU2000 model to IAU2006 (i.e. IAU2000A R06), making them dynamically consistent with the implemented IAU2006 (P03) precession model. - [__v1.5__] Faster IAU2000A (R06) nutation series and `ee_ct()` calculations, with a ~2x speedup. - [__v1.5__] Weaned off using CIO locator file internally (but still allowing users to access them if they want to).
----------------------------------------------------------------------------- ## Release schedule A predictable release schedule and process can help manage expectations and reduce stress on adopters and developers alike. __SuperNOVAS__ will try to follow a quarterly release schedule. You may expect upcoming releases to be published around __February 1__, __May 1__, __August 1__, and/or __November 1__ each year, on an as-needed basis. That means that if there are outstanding bugs, or new pull requests (PRs), you may expect a release that addresses these in the upcoming quarter. The dates are placeholders only, with no guarantee that a new release will actually be available every quarter. If nothing of note comes up, a potential release date may pass without a release being published. New features are generally reserved for the feature releases (e.g. __1.x.0__ version bumps), although they may also be rolled out in bug-fix releases as long as they do not affect the existing API -- in line with the desire to keep bug-fix releases fully backwards compatible with their parent versions. In the weeks and month(s) preceding releases one or more _release candidates_ (e.g. `1.0.1-rc3`) will be published temporarily on GitHub, under [Releases](https://github.com/Sigmyne/SuperNOVAS/releases), so that changes can be tested by adopters before the releases are finalized. Please use due diligence to test such release candidates with your code when they become available to avoid unexpected surprises when the finalized release is published. Release candidates are typically available for one week only before they are superseded either by another, or by the finalized release. ----------------------------------------------------------------------------- Copyright (C) 2026 Attila Kovács Sigmyne-SuperNOVAS-c764b40/USAGE-C99.md000066400000000000000000001167231517360672500171410ustar00rootroot00000000000000# C99 Usage This guide is specifically for using __SuperNOVAS__ as a C99 library. There is a separate guide for [using the C++11 API](USAGE-CPP.md). The links below let you jump to the relevant sections: - [Building your application with SuperNOVAS (C99)](#integration-c99) - [Example C99 usage](#examples-c99) - [Tips & Tricks (C99)](#tips-c99) __SuperNOVAS__ is a C99 library at its core. If you are looking for maximum speed, or want to use __SuperNOVAS__ on older platforms, the C99 API is there for you. The following links provide further useful documentation resources for you: - [C99 API documentation](https://sigmyne.github.io/SuperNOVAS/doc/html/topics.html) - [SuperNOVAS pages](https://sigmyne.github.io/SuperNOVAS) on github.io ----------------------------------------------------------------------------- ## Building your application with SuperNOVAS (C99) There are a number of ways you can build your application with __SuperNOVAS__. See which of the options suits your needs best: - [Using a GNU `Makefile`](#makefile-application-c99) - [Using CMake](#cmake-application-c99) - [Deprecated API](#deprecations-c99) - [Legacy linking `solarsystem()` and `readeph()` modules](#legacy-application-c99) - [Legacy modules: a better way](#preferred-legacy-application-c99) ### Using a GNU `Makefile`
Provided you have installed the __SuperNOVAS__ headers and (static or shared) libraries into a standard location, you can build your application against it easily. For example, to build `myastroapp.c` against __SuperNOVAS__, you might have a `Makefile` with contents like: ```make myastroapp: myastroapp.c $(CC) -o $@ $(CFLAGS) $^ -lm -lsupernovas ``` If you have a legacy NOVAS C 3.1 application, it is possible that the compilation will give you errors due to missing includes for `stdio.h`, `stdlib.h`, `ctype.h` or `string.h`, because these headers were implicitly included with `novas.h` in NOVAS C 3.1, but not in __SuperNOVAS__ (at least not by default), as a matter of best practice. If this is a problem for you can 'fix' it in one of two ways: (1) Add the missing `#include` directives to your application source explicitly, or if that's not an option for you, then (2) set the `-DCOMPAT` compiler flag when compiling your application: ```make myastroapp: myastroapp.c $(CC) -o $@ $(CFLAGS) -DCOMPAT $^ -lm -lsupernovas ``` If your application uses optional planet or ephemeris calculator modules, you may need to specify the additional shared libraries also: ```make myastroapp: myastroapp.c $(CC) -o $@ $(CFLAGS) $^ -lm -lsupernovas -lsolsys-calceph -lcalceph ```
### Using CMake
Add the appropriate bits from below to the `CMakeLists.txt` file of your application (`my-application`): ```cmake find_package(supernovas REQUIRED) target_include_directories(my-application PRIVATE ${supernovas_INCLUDE_DIRS}) target_link_libraries(my-application PRIVATE ${supernovas_LIBRARIES}) ```
### Deprecated API __SuperNOVAS__ began deprecating some NOVAS C functions, either because they are no longer needed; or are not easy to use and have better alternatives around; or are internals that should never have been exposed to end-users. The deprecations are marked in the inline and HTML API documentations, suggesting also alternatives. That said, the deprecated parts of the API are NOT removed, nor we plan on removing them for the foreseeable future. Instead, they serve as a gentle reminder to users that perhaps they should stay away from these features for their own good. However, you have the option to force yourself to avoid using the deprecated API if you choose to do so, by compiling your application with `-D_EXCLUDE_DEPRECATED`, or equivalently, by defining `_EXCLUDE_DEPRECATED` in your source code _before_ including `novas.h`. E.g.: ```c // Include novas.h without the deprecated definitions #define _EXCLUDE_DEPRECATED #include ``` After that, your compiler will complain if your source code references any of the deprecated entities, so you may change that part of your code to use the recommended alternatives instead. ### Legacy linking `solarsystem()` / `solarsystem_hp()` and `readeph()` modules The NOVAS C way to handle planet or other ephemeris functions was to link particular modules to provide the `solarsystem()` / `solarsystem_hp()` and `readeph()` functions. This approach is discouraged in __SuperNOVAS__, with preference for selecting implementations at runtime. The old, deprecated way, of incorporating Solar-system data is supported, nevertheless, for legacy applications with some caveats.
To use your own existing default `solarsystem()` implementation in the NOVAS C way, you will have to build __SuperNOVAS__ with `SOLSYS_SOURCE` set to the source file(s) of the implementation (`config.mk` or the environment). The same principle applies to using your specific legacy `readeph()` implementation, except that you must set `READEPH_SOURCE` to the source file(s) of the chosen implementation when building __SuperNOVAS__). (You might have to also add additional include directories to `CPPFLAGS`, e.g. `-I/my-path/include` for you custom sources for their associated headers).
### Legacy modules: a better way A better way to recycle your old planet and ephemeris calculator modules may be to rename `solarsystem()` / `solarsystem_hp()` functions therein to e.g. `my_planet_calculator()` / `my_planet_calculator_hp()` and then in your application can specify these functions as the provider at runtime.
E.g.: ```c set_planet_calculator(my_planet_calculator); set_planet_calculator(my_planet_calculator_hp); ``` (You might also change the `short` type parameters to the SuperNOVAS enum types while at it, to conform to the SuperNOVAS `novas_planet_provider` / `novas_planet_provider_hp` types.) For `readeph()` implementations, it is recommended that you change both the name and the footprint to e.g.: ```c int my_ephem_provider(const char *name, long id, double jd_tdb_high, double jd_tdb_low, enum novas_origin *origin, double *pos, double *vel); ``` and then then apply it in your application as: ```c set_ephem_provider(my_ephem_provider); ``` While all of that requires some minimal changes to your old code, the advantage of this preferred approach is that you do not need to re-build the library with `USER_SOLSYS` and/or `USER_READEPH` defined.
----------------------------------------------------------------------------- ## Example C99 usage - [Calculating positions for a sidereal source](#sidereal-example-c99) - [Calculating positions for a Solar-system source](#solsys-example-c99) - [Going in reverse...](#reverse-place-c99) - [Calculate rise, set, and transit times](#rise-set-transit-c99) - [Coordinate and velocity transforms (change of coordinate system)](#transforms-c99) __SuperNOVAS v1.1__ has introduced a new, more intuitive, more elegant, and more efficient approach for calculating astrometric positions of celestial objects. The guide below is geared towards this new method. However, the original NOVAS C approach remains viable also (albeit often less efficient). > [!NOTE] > You may find an equivalent legacy example showcasing the original NOVAS method in > [`NOVAS-legacy.md`](https://github.com/Sigmyne/SuperNOVAS/blob/main/doc/NOVAS-legacy.md). ### Calculating positions for a sidereal source A sidereal source may be anything beyond the Solar system with 'fixed' catalog coordinates. It may be a star, or a galactic molecular cloud, or a distant quasar. - [Specify the object of interest](#specify-object-c99) - [Specify the observer location](#specify-observer-c99) - [Specify the time of observation](#specify-time-c99) - [Set up the observing frame](#observing-frame-c99) - [Calculate an apparent place on sky](#apparent-place-c99) - [Calculate azimuth and elevation angles at the observing location](#horizontal-place-c99) #### Specify the object of interest First, you must provide the astrometric parameters (coordinates, and optionally radial velocity or redshift, proper motion, and/or parallax or distance also). Let's assume we pick a star for which we have B1950 (i.e. FK4) coordinates. We begin with the assigned name and the R.A. / Dec coordinates. ```c cat_entry star; // Structure to contain information on sidereal source // Let's assume we have B1950 (FK4) coordinates of // 16h26m20.1918s, -26d19m23.138s novas_init_cat_entry(&star, "Antares", 16.43894213, -26.323094); ``` If you have coordinates as strings in decimal or HMS / DMS format, you might use `novas_str_hours()` and/or `novas_str_degrees()` to convert them to hours/degrees for `novas_init_cat_entry()`, with a fair bit of flexibility on the particulars of the representation, e.g.: ```c novas_init_entry(&star, "Antares", novas_str_hours("16h 26m 20.1918s"), // e.g. using h,m,s and spaces as separators novas_str_degrees("-26:19:23.138")); // e.g. using colons to separate components ``` Next, if it's a star or some other source within our own Galaxy, you'll want to specify its proper motion (in the same reference system as the above coordinates), so we can calculate its position for the epoch of observation. ```c // Now, let's add proper motion of 12.11, -23.30 mas/year. novas_set_proper_motion(&star, -12.11, -23.30); ``` For Galactic sources you will also want to set the parallax using `novas_set_parallax()` or equivalently the distance (in parsecs) using `novas_set_distance()`, e.g.: ```c // Add parallax of 5.89 mas novas_set_parallax(&star, 5.89); ``` Finally, for spectroscopic applications you will also want to set the radial velocity. You can use `novas_set_ssb_vel()` if you have standard radial velocities defined with respect to the Solar System Barycenter; or `novas_set_lsr_vel()` if the velocity is relative to the Local Standard of Rest (LSR); or else `novas_set_redshift()` if you have a redshift measure (as is typical for distant galaxies and quasars). E.g.: ```c // Add a radial velocity of -3.4 km/s (relative to SSB) novas_set_ssb_vel(&star, -3.4); ``` Alternatively, if you prefer, you may use the original NOVAS C `make_cat_entry()` to set the astrometric parameters above all at once.
E.g.: ```c make_cat_entry("Antares", "FK4", 1, novas_str_hours("16h 26m 20.1918s"), novas_str_degrees("-26:19:23.138"), -12.11, -23.30, 5.89, -3.4, &star); ```
Next, we wrap that catalog source into a generic celestial `object` structure. (An `object` handles various Solar-system sources also, as you'll see further below). Whereas the catalog source may have been defined in any epoch / catalog system, the `object` structure shall define ICRS coordinates always (no exceptions): ```c object source; // Encapsulates a sidereal or a Solar-system source // Use the B1950 astrometric parameters to set up the observables in ICRS... make_cat_object_sys(&star, "B1950", &source); ``` Alternatively, for high-_z_ sources you might simply use the 1-step `make_redshifted_object_sys()` e.g.: ```c object quasar; // 12h29m6.6997s +2d3m8.598s (ICRS) z=0.158339 make_redshifted_object_sys("3c273", 12.4851944, 2.0523883, "ICRS", 0.158339, &quasar); ``` #### Specify the observer location Next, we define the location where we observe from. Let's assume we have a GPS location: ```c observer obs; // Structure to contain observer location // Specify the location we are observing from, e.g. a GPS / WGS84 location // 50.7374 deg N, 7.0982 deg E, 60m elevation make_gps_observer(50.7374, 7.0982, 60.0, &obs); ``` > [!TIP] > You might use `make_itrf_observer()` instead if the location is defined on the GRS80 reference ellipsoid, used e.g. > for ITRF locations. Or, if you have geocentric Cartesian coordinates, you could use `make_xyz_site()` and then > `make_observer_at_site()`. Again you might use `novas_str_degrees()` for typical string representations of the longitude and latitude coordinates here, such as: ```c make_gps_observer( novas_str_degrees("50.7374N"), novas_str_degrees("7.0982 deg E"), 60.0, &obs); ``` Alternatively, you can also specify airborne observers, or observers in Earth orbit, in heliocentric orbit, at the geocenter, or at the Solar-system barycenter. The above also sets default, mean annual weather parameters based on the location and a global model based on Feulner et al. (2013). You can, of course, set actual weather values _after_, as appropriate, if you need them for the refraction models, e.g.: ```c obs.on_surf.temperature = 12.4; // [C] Ambient temperature obs.on_surf.pressure = 973.47; // [mbar] Atmospheric pressure obs.on_surf.humidity = 48.3; // [%] relative humidity to use for refraction. ``` #### Specify the time of observation Next, we set the time of observation. For a ground-based observer, you will need to provide __SuperNOVAS__ with the UT1 - UTC time difference (a.k.a. DUT1), and the current leap seconds. You can obtain suitable values for DUT1 from IERS, and for the highest precision, interpolate for the time of observations. For the example, let's assume 37 leap seconds, and DUT1 = 0.042, ```c int leap_seconds = 37; // [s] UTC - TAI time difference double dut1 = 0.042; // [s] UT1 - UTC time difference ``` Then we can set the time of observation, for example, using the current UNIX time: ```c novas_timespec obs_time; // Structure that will define astrometric time // Set the time of observation to the precise UTC-based UNIX time novas_set_current_time(leap_seconds, dut1, &obs_time); ``` Alternatively, you may set the time as a Julian date in the time measure of choice (UTC, UT1, TT, TDB, GPS, TAI, TCG, or TCB): ```c double jd_tai = ... // TAI-based Julian Date novas_set_time(NOVAS_TAI, jd_tai, leap_seconds, dut1, &obs_time); ``` or, for the best precision we may do the same with an integer / fractional split: ```c long ijd_tai = ... // Integer part of the TAI-based Julian Date double fjd_tai = ... // Fractional part of the TAI-based Julian Date novas_set_split_time(NOVAS_TAI, ijd_tai, fjd_tai, leap_seconds, dut1, &obs_time); ``` Or, you might use string dates, such as an ISO timestamp: ```c novas_set_str_time(NOVAS_UTC, "2025-01-26T22:05:14.234+0200", leap_seconds, dut1, &obs_time); ``` Note, that the likes of `novas_set_time()` will automatically apply diurnal corrections to the supplied UT1-UTC time difference for libration and ocean tides. Thus, the supplied values should not include these. Rather you should pass `dut1` directly (or interpolated) from the IERS Bulletin values for the time of observation. #### Set up the observing frame Next, we set up an observing frame, which is defined for a unique combination of the observer location and the time of observation: ```c novas_frame obs_frame; // Structure that will define the observing frame double xp = ... // [mas] Earth polar offset x, e.g. from IERS Bulletin A. double yp = ... // [mas] Earth polar offset y, from same source as above. // Initialize the observing frame with the given observing parameters novas_make_frame(NOVAS_REDUCED_ACCURACY, &obs, &obs_time, xp, yp, &obs_frame); ``` Here `xp` and `yp` are small (sub-arcsec level) corrections to Earth orientation. Values for these are are published in the [IERS Bulletins](https://www.iers.org/IERS/EN/Publications/Bulletins/bulletins.html). These values should be interpolated for the time of observation, but should NOT be corrected for libration and ocean tides (`novas_make_frame()` will apply such corrections as appropriate for full accuracy frames). The Earth orientation parameters (EOP) are needed only when converting positions from the celestial CIRS (or TOD) frame to the Earth-fixed ITRS (or PEF) frames. You may ignore these and set zeroes if not interested in Earth-fixed calculations or if sub-arcsecond precision is not required. The advantage of using the observing frame, is that it enables very fast position calculations for multiple objects in that frame (see the [benchmarks](#benchmarks)), since all sources in a frame have well-defined, fixed, topological positions on the celestial sphere. It is only a matter of expressing these positions as coordinates (and velocities) in a particular coordinate system. So, if you need to calculate positions for thousands of sources for the same observer and time, it will be significantly faster than using the low-level NOVAS C routines instead. You can create derivative frames for different observer locations, if need be, via `novas_change_observer()`. > [!IMPORTANT] > Without a proper ephemeris provider for the major planets, you are invariably restricted to working with > `NOVAS_REDUCED_ACCURACY` frames, providing milliarcsecond precision at most. Attempting to construct high-accuracy > frames without an appropriate high-precision ephemeris provider will result in an error from the requisite > `ephemeris()` calls. > [!TIP] > `NOVAS_FULL_ACCURACY` frames require a high-precision ephemeris provider for the major planets, e.g. to account > for the gravitational deflections. Without it, μas accuracy cannot be ensured, in general. See section on > [Incorporating Solar-system ephemeris data or services](#solarsystem) further below. #### Calculate an apparent place on sky Now we can calculate the apparent R.A. and declination for our source, which includes proper motion (for sidereal sources) or light-time correction (for Solar-system bodies), and also aberration corrections for the moving observer and gravitational deflection around the major Solar System bodies (in full accuracy mode). You can calculate an apparent location in the coordinate system of choice (ICRS/GCRS, CIRS, J2000, MOD, TOD, TIRS, or ITRS) using `novas_sky_pos()`. E.g.: ```c sky_pos apparent; // Structure containing the precise observed position novas_sky_pos(&source, &obs_frame, NOVAS_CIRS, &apparent); ``` Apart from providing precise apparent R.A. and declination coordinates, the `sky_pos` structure also provides the _x,y,z_ unit vector pointing in the observed direction of the source (in the designated coordinate system). We also get radial velocity (for spectroscopy), and apparent distance for Solar-system bodies (e.g. for apparent-to-physical size conversion). > [!NOTE] > If you want geometric positions (and/or velocities) instead, without aberration and gravitational deflection, you > might use `novas_geom_posvel()`. > [!TIP] > Regardless, which reference system you have used in the calculations above, you can always easily and efficiently > change the coordinate reference system in which your results are expressed, by creating an appropriate transform > via `novas_make_transform()` and then using `novas_transform_vector()` or `novas_transform_skypos()`. More on > [coordinate transforms](#transforms-c99) further below. #### Calculate azimuth and elevation angles at the observing location If your ultimate goal is to calculate the azimuth and elevation angles of the source at the specified observing location, you can proceed from the `sky_pos` data you obtained above (in whichever coordinate system!): ```c double az, el; // [deg] local azimuth and elevation angles to populate // Convert the apparent position in CIRS on sky to horizontal coordinates novas_app_to_hor(&obs_frame, NOVAS_CIRS, apparent.ra, apparent.dec, novas_standard_refraction, &az, &el); ``` Above we converted the apparent coordinates, that were calculated in CIRS, to refracted azimuth and elevation coordinates at the observing location, using the `novas_standard_refraction()` function to provide a suitable refraction correction. We could have used `novas_optical_refraction()` instead to use the weather data embedded in the frame's `observer` structure, or some user-defined refraction model, or else `NULL` to calculate unrefracted elevation angles. ### Calculating positions for a Solar-system source - [Planets and/or ephemeris type objects](#ephemeris-sources-c99) - [Solar-system objects with Keplerian orbital parameters](#orbital-sources-c99) - [Approximate planet orbitals](#planet-orbitals-c99) - [Moon's position and phase](#moon-c99) Solar-system sources work similarly to the above with a few important differences at the start. #### Planets and/or ephemeris type objects Historically, NOVAS divided Solar-system objects into two categories: (1) major planets (including also the Sun, the Moon, and the Solar-system Barycenter); and (2) 'ephemeris' type objects, which are all other Solar-system objects. The main difference is the numbering convention. NOVAS major planets have definitive ID numbers (see `enum novas_planet`), whereas 'ephemeris' objects have user-defined IDs. They are also handled by two separate adapter functions (although __SuperNOVAS__ has the option of using the same ephemeris provider for both types of objects also). Thus, instead of `make_cat_object()` you define your source as a planet or ephemeris type `object` with a name or ID number that is used by the ephemeris service you provided. For major planets you might want to use `make_planet()`, if they use a `novas_planet_provider` function to access ephemeris data with their NOVAS IDs, or else `make_ephem_object()` for more generic ephemeris handling via a user-provided `novas_ephem_provider`. E.g.: ```c object mars, ceres; // Hold data on solar-system bodies. // Mars will be handled by the planet provider function make_planet(NOVAS_MARS, &mars); without background checks // Ceres will be handled by the generic ephemeris provider function, which let's say // uses the NAIF ID of 2000001 _or_ the name 'Ceres' (depending on the implementation) make_ephem_object("Ceres", 2000001, &ceres); ``` > [!IMPORTANT] > Before you can handle all major planets and other ephemeris objects this way, you will have to provide one or more > functions to obtain the barycentric ICRS positions for your Solar-system source(s) of interest for the specific > Barycentric Dynamical Time (TDB) of observation. See section on > [Incorporating Solar-system ephemeris data or services](https://github.com/Sigmyne/SuperNOVAS/blob/main/README.md#solarsystem). And then, it's the same spiel as before, e.g.: ```c int status = novas_sky_pos(&mars, &obs_frame, NOVAS_TOD, &apparent); if(status) { // Oops, something went wrong... ... } ``` #### Solar-system objects with Keplerian orbital parameters As of version __1.2__ you can also define solar system sources with Keplerian orbital elements (such as the most up-to-date ones provided by the [Minor Planet Center](https://minorplanetcenter.net/data) for asteroids, comets, etc.): ```c object NEA; // e.g. a Near-Earth Asteroid // Fill in the orbital parameters (pay attention to units!) novas_orbital orbit = NOVAS_ORBIT_INIT; orbit.a = ...; // Major axis in AU... ... // ... and the rest of the orbital elements // Create an object for that orbit make_orbital_object("NEAxxx", -1, &orbit, &NEA); ``` > [!NOTE] > Even with orbital elements, you will, in general, still require an ephemeris provider also, to obtain precise > positions for the Sun, an Earth-based observer, or the planet, around which the orbit is defined. #### Approximate planet orbitals Finally, as of version __1.4__, you might generate approximate (arcmin-level) orbitals for the major planets (but not Earth!), the Moon, and the Earth-Moon Barycenter (EMB) also. E.g.: ```c double jd_tdb = ... // Time (epoch) for which to calculate orbital parameters // Planet orbitals, e.g. for Mars novas_orbital mars_orbit = NOVAS_ORBIT_INIT; novas_make_planet_orbit(NOVAS_MARS, jd_tdb, &mars_orbit); // Moon's (very approcimate) orbital around Earth novas_orbital moon_orbit = NOVAS_ORBIT_INIT; novas_make_moon_orbit(jd_tdb, &moon_orbit); ``` While the planet and Moon orbitals are not suitable for precision applications, they can be useful for determining approximate positions (e.g. via the `novas_approx_heliocentric()` and `novas_approx_sky_pos()` functions), and for rise/set time calculations. #### Moon's position and phase __SuperNOVAS__ can calculate positions and velocities for the Moon to arcsecond (or km) level, or better, accuracy using the ELP2000 / MPP02 semi-analytical model by Chapront & Francou (2003). This means that you can calculate astrometric quantities for the Moon with reasonable accuracy even without an ephemeris provider configured. For example, you can calculate the apparent place of the Moon in an observing frame as: ```c novas_frame frame = ...; // observer location and time of observation sky_pos apparent = {}; // apparent data structure to populate... // Calculate apparent position, say in true-of-date (TOD) system if(novas_moon_elp_sky_pos(&frame, NOVAS_TOD, &apparent) != 0) { // Oops something went wrong... return -1; } ``` Alternatively, you can obtain geometric positions and velocities of the Moon, relative to the observer using `novas_moon_elp_posvel()` instead. You can also obtain the current phase of the Moon, for the time of observation: ```c double jd_tdb = ...; // TDB-based Julian Date of observation // [deg] Moon's phase at the specified time (0 is new moon). double phase = novas_moon_phase(jd_tdb); ``` or, calculate when the Moon will reach a particular phase next: ```c // TDB-based Julian Date of the next full moon (phase = 180 deg), after TDB-based date double jd_tdb_full = novas_next_moon_phase(180.0, jd_tdb); ``` ### Going in reverse... Of course, __SuperNOVAS__ allows you to go in reverse, for example from an observed Az/El position all the way to proper ICRS R.A./Dec coordinates. E.g.: ```c double az = ..., el = ...; // [deg] measured azimuth and elevation angles double pos[3]; // [arb. u.] xyz position vector double ra, dec; // [h, deg] R.A. and declination to populate // Calculate the observer's apparent coordinates from the observed Az/El values, // lets say in CIRS (but it could also be ICRS, for all that matters). novas_hor_to_app(&obs_frame, az, el, novas_standard_refraction, NOVAS_CIRS, &ra, &dec); // Convert apparent to ICRS geometric positions (no parallax) novas_app_to_geom(&obs_frame, NOVAS_CIRS, ra, dec, 0.0, pos); // Convert ICRS rectangular equatorial to R.A. and Dec vector2radec(pos, &ra, &dec); ``` Voila! And, of course you might want the coordinates in some other reference systems, such as B1950. For that you can simply add a transformation before `vector2radec()` above, e.g. as: ```c ... // Transform position from ICRS to B1950 gcrs_to_mod(NOVAS_JD_B1950, pos, pos); // Convert B1950 xyz position to R.A. and Dec vector2radec(pos, &ra, &dec); ``` ### Calculate rise, set, and transit times You may be interested to know when sources rise above or set below some specific elevation angle, or at what time they appear to transit at the observer location. __SuperNOVAS__ has routines to help you with that too. Given that rise, set, or transit times are dependent on the day of observation, and observer location, they are effectively tied to an observer frame. ```c novas_frame frame = ...; // Earth-based observer location and lower-bound time of interest. object source = ...; // Source of interest // UTC-based Julian day *after* observer frame, when source rises above 30 degrees of elevation // next, given a standard optical refraction model. double jd_rise = novas_rises_above(30.0, &source, &frame, novas_standard_refraction); // UTC-based Julian day *after* observer frame, of next source transit double jd_transit = novas_transit_time(&source, &frame); // UTC-based Julian day *after* observer frame, when source sets below 30 degrees of elevation // next, not accounting for refraction. double jd_set = novas_sets_below(30.0, &source, &frame, NULL); ``` Note, that in the current implementation these calls are not well suited sources that are at or within the geostationary orbit, such as such as Low Earth Orbit satellites (LEOs), geostationary satellites (which never really rise, set, or transit), or some Near Earth Objects (NEOs), which will rise set multiple times per day. For the latter, the above calls may still return a valid time, only without the guarantee that it is the time of the first such event after the specified frame instant. A future implementation may address near-Earth orbits better, so stay tuned for updates. ### Coordinate and velocity transforms (change of coordinate system) __SuperNOVAS__ introduces matrix transforms (correctly since version __1.4__), which can take a position or velocity vector (geometric or apparent), obtained for an observer frame, from one coordinate system to another efficiently. E.g.: ```c novas_frame frame = ... // The observer frame (time and location) double j2000_vec[3] = ...; // IN: original position vector, say in J2000. double tirs_vec[3] = {0.0}; // OUT: equivalent vector in TIRS we want to obtain novas_transform T; // Coordinate transformation data // Calculate the transformation matrix from J2000 to TIRS in the given observer frame. novas_make_transform(&frame, NOVAS_J2000, NOVAS_TIRS, &T); // Transform the J2000 position or velocity vector to TIRS... novas_transform_vector(j2000_vec, &T, tirs_vec); ``` Transformations support all __SupeNOVAS__ reference systems, that is ICRS/GCRS, J2000, TOD, MOD, CIRS, TIRS, and ITRS. The same transform can also be used to convert apparent positions in a `sky_pos` structure also, e.g.: ```c ... sky_pos j2000_pos = ... // IN: in J2000, e.g. via novas_sky_pos()... sky_pos tirs_pos; // OUT: equivalent TIRS position to calculate... // Transform the J2000 apparent positions to TIRS.... novas_transform_sky_pos(&j2000_pos, &T, &tirs_pos); ``` ----------------------------------------------------------------------------- ## Tips and tricks (C99) - [Multi-threaded calculations](#multi-threading-c99) - [Physical units](#physical-units-c99) - [String times and angles](#string-times-and-angles-c99) - [String dates](#string-dates-c99) ### Multi-threaded calculations Some of the calculations involved can be expensive from a computational perspective. For the most typical use case however, NOVAS (and __SuperNOVAS__) has a trick up its sleeve: it caches the last result of intensive calculations so they may be re-used if the call is made with the same environmental parameters again (such as JD time and accuracy). A direct consequence of the caching of results is that calculations are generally not thread-safe as implemented by the original NOVAS C 3.1 library. One thread may be in the process of returning cached values for one set of input parameters while, at the same time, another thread is saving cached values for a different set of parameters. Thus, when running calculations in more than one thread, the NOVAS C results returned may at times be incorrect, or more precisely they may not correspond to the requested input parameters. While you should never call the original NOVAS C library from multiple threads simultaneously, __SuperNOVAS__ caches the results in thread local variables (provided your compiler supports it), and is therefore generally safe to use in multi-threaded applications. Just make sure that you: - use a compiler which supports the C11 language standard; - or, compile with GCC >= 3.3; - or else, set the appropriate non-standard keyword to use for declaring thread-local variables for your compiler in `config.mk` or in your equivalent build setup. ### Physical units The NOVAS API has been using conventional units (e.g. AU, km, day, deg, h) typically for its parameters and return values alike. Hence, __SuperNOVAS__ follows the same conventions for its added functions and data structures also. However, when interfacing __SuperNOVAS__ with other programs, libraries, or data files, it is often necessary to use quantities that are expressed in different units, such as SI or CGS. To facilitate such conversions, `novas.h` provides a set of unit constants, which can be used for converting to/from SI units (and radians). For example, `novas.h` contains the following definitions: ```c /// [s] The length of a synodic day, that is 24 hours exactly. @since 1.2 #define NOVAS_DAY 86400.0 /// [rad] A degree expressed in radians. @since 1.2 #define NOVAS_DEGREE (M_PI / 180.0) /// [rad] An hour of angle expressed in radians. @since 1.2 #define NOVAS_HOURANGLE (M_PI / 12.0) ``` You can use these, for example, to convert quantities expressed in conventional units for NOVAS to standard (SI) values, by multiplying NOVAS quantities with the corresponding unit definition. E.g.: ```c // A difference in Julian Dates [day] in seconds. double delta_t = (tjd - tjd0) * NOVAS_DAY; // R.A. [h] / declination [deg] converted radians (e.g. for trigonometric functions). double ra_rad = ra_h * NOVAS_HOURANGLE; double dec_rad = dec_d * NOVAS_DEGREE; ``` And vice-versa: to convert values expressed in standard (SI) units, you can divide by the appropriate constant to 'cast' an SI value into the particular physical unit, e.g.: ```c // Increment a Julian Date [day] with some time differential [s]. double tjd = tjd0 + delta_t / NOVAS_DAY; // convert R.A. / declination in radians to hours and degrees double ra_h = ra_rad / NOVAS_HOURANGLE; double dec_d = dec_rad / NOVAS_DEGREE; ``` Finally, you can combine them to convert between two different conventional units, e.g.: ```c // Convert angle from [h] -> [rad] -> [deg] double lst_d = lst_h * NOVAS_HOURANGLE / NOVAS_DEGREE; // Convert [AU/day] -> [m/s] (SI) -> [km/s] double v_kms = v_auday * (NOVAS_AU / NOVAS_DAY) / NOVAS_KMS ``` ### String times and angles __SuperNOVAS__ functions typically input and output times and angles as decimal values (hours and degrees, but also as days and hour-angles), but that is not how these are represented in many cases. Time and right-ascention are often given as string values indicating hours, minutes, and seconds (e.g. "11:32:31.595", or "11h 32m 31.595s"). Similarly angles, are commonly represented as degrees, arc-minutes, and arc-seconds (e.g. "+53 60 19.9"). For that reason, __SuperNOVAS__ provides a set of functions to convert string values expressed in decimal or broken-down format to floating point representation. E.g., ```c // Right ascention from string double ra_h = novas_str_hours("9 18 49.068"); // Declination from string double dec_d = novas_str_degrees("-53 10 07.33"); ``` The conversions have a lot of flexibility. Components can be separated by spaces (as above), by colons, commas, or underscores, by the letters 'h'/'d', 'm', and 's', by single (minutes) and double quotes (seconds), or any combination thereof. Decimal values may be followed by 'h' or 'd' unit markers. Additionally, angles can end with a compass direction, such as 'N', 'E', 'S' or 'W'. So the above could also have been: ```c double ra_h = novas_str_hours("9h_18:49.068\""); double dec_d = novas_str_degrees("53d 10'_07.33S"); ``` or as decimals: ```c double ra_h = novas_str_hours("9.31363"); double dec_d = novas_str_degrees("53.16870278d South"); ``` ### String dates Dates are typically represented broken down into year, month, and day (e.g. "2025-02-16", or "16.02.2025", or "2/16/2025"), with or without a time marker, which itself may or may not include a time zone specification. In astronomy, the most commonly used string representation of dates is with ISO 8601 timestamps. The following are all valid ISO date specifications: ``` 2025-02-16 # Date only (0 UTC) 2025-02-16T19:35:21Z # UTC date/time 2025-02-16T19:35:21.832Z # UTC date/time with decimals 2025-02-16T14:35:21+0500 # date in time zone (e.g. EST) 2025-02-16T14:35:21.832+05:00 # alternative time zone specification ``` __SuperNOVAS__ provides functions to convert between ISO dates/times and their string representation for convenience. E.g., ```c novas_timespec time; // Astronomical time specification char timestamp[40]; // A string to contain an ISO representation // Parse an ISO timestamp into a Julian day (w/o returning the tail). double jd = novas_parse_iso_date("2025-02-16T19:35:21Z", NULL); if(isnan(jd)) { // Oops could not parse date. ... } // Use the parsed JD date (in UTC) with the appropriate leap seconds // and UT1-UTC time difference novas_set_time(NOVAS_UTC, jd, leap_seconds, dut1, &time); // Print an ISO timestamp, with millisecond precision, into the // designated string buffer. novas_iso_timestamp(&time, timestamp, sizeof(timestamp)); ``` > [!NOTE] > ISO 8601 timestamps are always UTC-based and expressed in the Gregorian calendar, as per specification, even for > dates that preceded the Gregorian calendar reform of 1582 (i.e. 'proleptic Gregorian' dates). Other __SuperNOVAS__ string date functions will process dates in the astronomical calendar of date by default, that is in the Gregorian calendar after the Gregorian calendar reform of 1582, or the Julian/Roman calendar for dates prior, and support timescales other than UTC also. E.g.: ```c // Print a TDB timestamp in the astronomical calendar of date instead novas_timestamp(&time, NOVAS_TDB, timestamp, sizeof(timestamp)); ``` Or, parse an astronomical date: ```c // Parse astronomical dates into a Julian day... double jd = novas_date("2025-02-16T19:35:21"); if(isnan(jd)) { // Oops could not parse date. ... } ``` Or, parse an astronomical date, including the timescale specification: ```c // Parse a TAI-based timestamp into a Julian day and corresponding timescale double jd = novas_date_scale("2025-02-16T19:35:21+0200 TAI", &scale); if(isnan(jd)) { // Oops could not parse date. ... } ``` Sometimes your input dates are represented in various other formats. You can have additional flexibility for parsing dates using the `novas_parse_date_format()` and `novas_timescale_for_string()` functions.
E.g., ```c char *pos = NULL; // We'll keep track of the string parse position here enum novas_timescale scale; // We'll parse the timescale here (if we can) // Parse the M/D/Y date up to the 'TAI' timescale specification... double jd = novas_parse_date_format(NOVAS_GREGORIAN_CALENDAR, NOVAS_MDY, "2/16/2025 20:08:49.082 TAI", &pos); // Then parse the 'TAI' timescale marker, after the date/time specification scale = novas_timescale_for_string(pos); if(scale < 0) { // Oops, not a valid timescale marker. Perhaps assume UTC... scale = NOVAS_UTC; } // Now set the time for the given calendar, date format, and timescale of the // string representation. novas_set_time(scale, jd, leap_seconds, dut1, &time); ```
----------------------------------------------------------------------------- Copyright (C) 2026 Attila Kovács Sigmyne-SuperNOVAS-c764b40/USAGE-CPP.md000066400000000000000000001032141517360672500172060ustar00rootroot00000000000000# C++ Usage This guide is specifically for using __SuperNOVAS__ primarily as a C++11 library. There is a separate guide for [using the C99 API](USAGE-C99.md). The links below let you jump to the relevant sections: - [Building your application with SuperNOVAS (C++)](#integration-cpp) - [C++ Fundametals](#fundamentals-cpp) - [Example C++ usage](#examples-cpp) __SuperNOVAS__ is a C99 library at its core. If you are looking for maximum speed, or want to use __SuperNOVAS__ on older platforms, the C99 API is there for you. However, if you want a more modern, more intuitive, higher-level, and more elegant way of using __SuperNOVAS__ then the C++ API gives you that comfort. The following links provide further useful documentation resources for you: - [C++ API documentation](https://sigmyne.github.io/SuperNOVAS/doc/html/cpp/topics.html) - [SuperNOVAS pages](https://sigmyne.github.io/SuperNOVAS) on github.io ----------------------------------------------------------------------------- ## Building your application with SuperNOVAS (C++) There are a number of ways you can build your application with __SuperNOVAS__. See which of the options suits your needs best: - [Using a GNU `Makefile`](#makefile-application-cpp) - [Using CMake](#cmake-application-cpp) ### Using a GNU `Makefile`
Provided you have installed the __SuperNOVAS__ headers and (static or shared) libraries into a standard location, you can build your application against it easily. For example, to build `myastroapp.cpp` against __SuperNOVAS__, you might have a `Makefile` with contents like: ```make myastroapp: myastroapp.cpp $(CC) -o $@ $(CFLAGS) $^ -lm -lsupernovas -lsupernovas++ ``` I.e., you will need to link your program against *both* the C99 `supernovas` library *and* the C++ `supernovas++` library on top of that. If your application uses optional planet or ephemeris calculator modules, you may need to specify the additional shared libraries also: ```make myastroapp: myastroapp.cpp $(CC) -o $@ $(CFLAGS) $^ -lm -lsupernovas -lsupernovas++ -lsolsys-calceph -lcalceph ```
### Using CMake
Add the appropriate bits from below to the `CMakeLists.txt` file of your application (`my-application`): ```cmake find_package(supernovas REQUIRED) target_include_directories(my-application PRIVATE ${supernovas_INCLUDE_DIRS}) target_link_libraries(my-application PRIVATE ${supernovas_LIBRARIES}) ```
----------------------------------------------------------------------------- ## C++ Fundamentals - [Namespace](#namespace-cpp) - [Validation](#validation-cpp) - [Thread safety](#thread-safety-cpp) - [Operator overloading](#operators-cpp) Before we dive into specific examples for using the __SuperNOVAS__ C++ API, you should know of the generic features and design principles that underly the C++ implementation. ### Namespace To allow using simple class names, while being cognizant of potential namespace conflicts, the __SuperNOVAS__ classes all live under the `supernovas` namespace. Thus, the class `Angle`, for example, has a full name `supernovas::Angle` that can be used in any context. But, when convenient you can make one of more namespaces default in your source code, e.g.: ```cpp #include using namespace supernovas; void my_func() { Angle a(...); ... } ``` is equivalent to: ```cpp #include void my_func() { supernovas::Angle a(...); ... } ``` ### Validation C++ does not have runtime exceptions the same way as Python or Java, which can be caught. While C++17 introduced `std::optional` types that can be used to return with or without valid data, __SuperNOVAS__ does not use these, because _(a)_ the optionals are not supported on Apple and Windows (in 2026), and _(b)_ they don't do anything for constructors. Instead all __SuperNOVAS__ classes are based on a `supernovas::Validating` base class, providing an `is_valid()` method. All subclasses (that is all __SuperNOVAS__ classes) sanity check their data as part of their constructor. And, mutable classes sanity check every time they are modified as well. The checks typically include flagging NaNs and infinite values (unless they are explicitly allowed), enum values outside of their normal range (yes the compiler checks for these, but those checks can be easily bypassed), and whatever else is necessary to ensure that the objects contain fully usable data. It is generally a good idea to check for validity whenever getting sane numerical data (i.e., not NaNs) is critical, or if you are not entirely sure. For example: ```cpp Observer obs = ...; // Define an observer location if(!obs.is_valid()) { // Oops, something isn't right... return; } ``` or, equivalently the objects themselves can be evaluated as boolean types, the same as calling `is_valid()`, i.e.: ```cpp Observer obs = ...; // Define an observer location if(!obs) { // Oops, something isn't right... return; } ``` And if in doubt as to why your object is invalid, you can always turn on debugging with `novas_debug(NOVAS_DEBUG_ON)`, at least in the relevant section of your code. __SuperNOVAS__ will provide error descriptions and call traces every time an invalid class instance is created, and when methods create invalid objects themselves. ### Thread safety It is easy to use the C++ API safely in a multi-threaded environment, even without explicit mutexing. The best practice is to always declare your shared (among threads) class variables as `const` so they will never get accidentally modified by one thread while another thread accesses them concurrently. While most __SuperNOVAS__ classes do not have explicitly declared methods that can modify them, their contents can nevertheless get overwritten easily with the implicit copy-assignment operator -- but not when the variable was declared as `const`. For example: ```c++ // Declaring 'frame' as const will make it safe to use in threads. const Frame frame = ...; ``` To further support thread safety, the __SuperNOVAS__ classes are designed never to store references to external objects internally. Instead, they always store copies of the parameters that were supplied by their constructors or update methods. While the copying may result in a small overhead, it guarantess that the internal data cannot vanish or change unexpectedly. ### Operator overloading Several __SuperNOVAS__ classes override arithmetic operators (often `+` and `-`, and sometimes `*` and `/`), but only when this is physically meaningful. For example, you can add and difference position or velocity vectors: for `supernovas::Position`, __a__ and __b__, __a__ + __b__ is the two positions superimposed, __a__ - __b__ is the difference vector of the same type. For `supernovas::Velocity`, the addition and subtraction follows the relativistic formulae, e.g. for velocity vectors `v1` and `v2`: ```cpp Velocity dv = v2 - v1; // Relativistic difference of two velocity vectors. ``` You can also add or subtract intervals around `supernovas::Time` instances, such as: ```cpp Time t = ...; // An astrometric time instance Time t1 = t + 1.1 * Unit::min; // offset time (in a terrestrial timescale) ``` This works for small intervals so long as the Earth Orientation Parameters (leap seconds and UT1 - UTC time difference) remain the same, _and_ the offset is in a terrestrial timescale (UTC, TT, TAI, or GPS). The above is the same as `t + Interval(1.1 * Unit::min)` or `t.shifted(1.1 * Unit::min)` or `t.shifted(Interval(1.1 * Unit::min))`. You can also multiply a `supernovas::Velocity` or `supernovas::ScalarVelocity` (`rv`) with a time interval on either side to get distance travelled, e.g.: ```cpp Coordinate dr = rv * Interval(5.0 * Unit::s); // distance travelled ``` is the same as `Interval(5.0 * Unit::s) * rv`, and is the same as `v.travel(5.0 * Unit::s)` or `v.travel(Interval(5.0 * Unit::s))`. Conversely, you can define (scalar and vector) velocities by dividing the traveled coordinate or position vector with a time interval: ```cpp ScalarVelocity v = Coordinate(120.0 * Unit::km) / Interval(14.3 * Unit::s); ``` Or, using a bunch of the arithmetic operators already discussed, you can calculate a velocity from two positions measured at two different time instances: ```cpp Position p0, p1; // Postions measured at two different times Time t0, t1; // the times of the measurements // Calculate an average velocity from the above... Velocity v = (p1 - p0) / (t1 - t0); ``` Celestial coordinates, which can be expressed in different reference systems, can be transformed to another system with the `>>` operator, which is just a shorthand for the `.to_system()` method. E.g., if you have `supernovas::Equatorial` coordinates `eq` in some reference system, and want it to be converted to ICRS, you might write: ```cpp Equatorial icrs = eq >> Equinox::icrs(); // ICRS coordinates ``` which is the same as `eq.to_system(Equinox::icrs())` or `eq.to_icrs()`. Many classes also define `==` and `!=` to check for equality. This is the same as calling their `.equals()` method with the default precision, or it's negated form, respectively. `supernovas::Time` and `supernovas::CalendarDate` also have comparison operators defined: `<`, `>`, `<=`, and `>=`. The `<` and `>` always evaluate at the full precision, whereas `<=` and `>=` follow the default precision of `==`. This makes `<=` fully consistent with `<` _or_ `==`, and `>=` with `>` _or_ `==`. So for two `Time` instances `t1` and `t2`, you could check, e.g.: ```cpp if(t1 >= t2) std::cout << "t1 is approximately the same or after t2.\n"; else if(t1 < t2) std::cout << "t1 is before t2.\n"; else std::cout << "either t1 or t2 is undefined / invalid.\n"; ``` Last, but not least, all __SuperNOVAS__ classes can be evaluated as boolean types, to check validity (same as the `.is_valid()` method), as described a little further above. It is up to you whether your coding style prefers using the overloaded operators or the equivalent methods. Do what works best for you. ----------------------------------------------------------------------------- ## Example C++ usage - [Calculating positions for a sidereal source](#sidereal-example-cpp) - [Calculating positions for a Solar-system source](#solsys-example-cpp) - [Going in reverse...](#reverse-place-cpp) - [Calculate rise, set, and transit times](#rise-set-transit-cpp) - [Coordinate and velocity transforms (change of coordinate system)](#transforms-cpp) ### Calculating positions for a sidereal source A sidereal source may be anything beyond the Solar system with 'fixed' catalog coordinates. It may be a star, or a galactic molecular cloud, or a distant quasar. - [Specify the object of interest](#specify-object-cpp) - [Specify the observer location](#specify-observer-cpp) - [Specify the time of observation](#specify-time-cpp) - [Set up the observing frame](#observing-frame-cpp) - [Calculate an apparent place on sky](#apparent-place-cpp) - [Calculate azimuth and elevation angles at the observing location](#horizontal-place-cpp) #### Specify the object of interest First, you must provide the astrometric parameters (coordinates, and optionally radial velocity or redshift, proper motion, and/or parallax or distance also). Let's assume we pick a star for which we have B1950 (i.e. FK4) coordinates. We begin with the assigned name and the R.A. / Dec coordinates, and then populate any other astrometric parameters we may have: ```cpp // Let's assume we have B1950 (FK4) coordinates CatalogEntry entry = CatalogEntry("Antares", "16h26m20.1918s", "-26d19m23.138s", Equinox::b1950()) .proper_motion(-12.11 * Unit::mas / Unit::yr, -23.30 * Unit::mas / Unit:yr) .parallax(5.89 * Unit::mas) .radial_velocity(5.89 * Unit::km / Unit::s); ``` Above, the coordinates were specified as strings. but they could have been floating-point values (e.g. `16.43894213 * Unit::hour_angle`, `-26.323094 * Unit::deg`), or `supernovas::Angle` / `supernovas::TimeAngle` objects instead. We also specified an equinox (B1950), but you can skip that if you use ICRS coordinates. After that, we used a builder pattern to add additional detail, such as proper motion, parallax, and an (SSB-based) radial velocity. We could have also set `distance()` instead of `parallax()`, or `v_lsr()` or `redshift()` instead of `radial_velocity()`. Use what fits your needs best. Note the use of physical units along with the numerical data. Next, we we create a `Source` type object from this catalog entry: ```cpp auto source = entry.to_source(); ``` The `supernovas::Source` class can represent different astronomical objects, and accordingly has different subclasses. Specifically, `entry.to_source()` above returns a `supernovas::CatalogSource`, but thanks to the `auto` keyword, we don't really need to know what subclass of `Source` is actually being created here. #### Specify the observer location ##### A. Earth-based observer location Next, we define the location where we observe from. Let's assume we have a GPS location, such as 50.7374 deg N, 7.0982 deg E, 60m elevation: ```cpp // Specify the location we are observing from, e.g. a GPS / WGS84 location Site site = Site::from_GPS(7.0982 * Unit::deg, 50.7374 * Unit::deg, 60.0 * Unit::m); ``` > [!TIP] > You might use one of the `supernovas::Site()` constructors directly if the location is defined on the GRS80 > reference ellipsoid, or if you have geocentric Cartesian coordinates. Again you could have specified the coordinates as DMS strings, or as `supernovas::Angle` objects also, e.g.: ```cpp Site site = Site::from_GPS("7.0982 deg E", "50.7374N", Coordinate(60.0 * Unit::m)); ``` Next, you will want to create an `supernovas::Observer` instance for that location with the appropriate Earth Orientation Parameters (EOP), such as obtained from the [IERS Bulletins](https://www.iers.org/IERS/EN/Publications/Bulletins/bulletins.html) or data service. These are leap seconds, the UT1-UTC time difference capturing variations in Earth's rotation, and the _xp_, _yp_ polar offsets, which measure small wanders of Earth's rotational pole w.r.t. the crust: ```cpp // Let's assume 37 leap seconds, 0.6447s UT1-UTC difference, and some polar offsets: EOP eop(37, 0.6447 * Unit::s, 103.2 * Unit::mas, 211.3 * Unit::mas); // Now create an observer for that site auto obs = site::to_observer(eop); ``` Again, `supernovas::Observer` has many subclasses of specific flavors, so here we use the `auto` keyword again if we are lazy (otherwise we could have specified `supernovas::GeodeticObserver`, which is what `site.to_observer()` returns). ##### B. other observer locations Alternatively, you can also specify airborne observers, or observers in Earth orbit, in heliocentric orbit, or a virtual observer at the geocenter, or at the Solar-system barycenter. See the static methods of the `supernovas::Observer` class. E.g.: ```cpp auto obs = Observer::at_geocenter(); ``` #### Specify the time of observation Then we can set the time of observation, for example, using the current UNIX time: ```cpp // Set the time of observation to the precise UTC-based UNIX time Time obs_time = Time::now(eop); ``` Once again, EOP is needed for the leap seconds and UT1-UTC time difference. Alternatively, you may set the time as a Julian date in the time measure of choice (UTC, UT1, TT, TDB, GPS, TAI, TCG, or TCB): ```cpp double jd_tai = ... // TAI-based Julian Date Time obs_time(jd_tai, eop, NOVAS_TAI) ``` or, for the best precision we may do the same with an integer / fractional split: ```cpp long ijd_tai = ... // Integer part of the TAI-based Julian Date double fjd_tai = ... // Fractional part of the TAI-based Julian Date Time obs_time(ijd_tai, fjd_tai, eop, NOVAS_TAI); ``` Or, you might use string dates, such as an ISO timestamp: ```cpp Time obs_time = Time("2025-01-26T22:05:14.234+0200", eop); ``` #### Set up the observing frame Next, we set up an observing frame, which is defined for a unique combination of the observer location and the time of observation: ```cpp // Initialize the observing frame for the observer at the time of observation. Frame frame = obs.frame_at(obs_time); // It's a good idea to confirm that the frame is actually valid if(!frame) { // Oops, not a valid frame, perhaps because we don't have an ephemeris provider configured. ... } ``` Or, you can use `obs.reduced_accuracy_frame_at(time)` to construct a frame with mas-level accuracy only. > [!IMPORTANT] > Without a proper ephemeris provider for the major planets, you are invariably restricted to working with reduced > accuracy frames, providing milliarcsecond precision at most. Attempting to construct high-accuracy frames without an > appropriate high-precision ephemeris provider will result in an error from the requisite `ephemeris()` calls. > [!TIP] > Full accuracy (μas-level) frames require a high-precision ephemeris provider for the major planets, e.g. to account > for the gravitational deflections. Without it, μas accuracy cannot be ensured, in general. See section on > [Incorporating Solar-system ephemeris data or services](#solarsystem) further below. #### Calculate an apparent place on sky Now we can calculate the apparent R.A. and declination for our source, which includes proper motion (for sidereal sources) or light-time correction (for Solar-system bodies), and also aberration corrections for the moving observer and gravitational deflection around the major Solar System bodies (in full accuracy mode). You can calculate an apparent location in the: ```cpp // Precise apparent positions and spectroscopic velocities (in TOD). Apparent app = source.apparent_in(frame); ``` You cat get true-of-date (TOD) equatorial coordinates (`.equatorial()`), or in CIRS (`.cirs()`). And you can convert these to any other coordinate system of choice (ICRS/GCRS, J2000, or MOD), e.g.: ```cpp // true-of-date apparent coordinates Equatorial tod = app.equatorial(); // the same converted to ICRS Equatorial icrs = tod.to_icrs(); ``` You can also obtain ecliptic (TOD) and galactic coordinates the same way, and convert ecliptic coordinates to other equinoxes just like we did for the equatorial: ```cpp // apparent ecliptic coordinates in J2000 Ecliptic ecl = app.ecliptic() >> NOVAS_J2000; // apparent Galactic coordinates Galactic gal = app.galactic(); ``` Above the `>>` operator is used as a shorthand for the `.to_system()` method. It's the same as writing `.to_system(NOVAS_J2000)` or `.to_j2000()`. For spectroscopic applications, you can get a spectroscopic radial velocity or redshift (including gravitational effects) as: ```cpp ScalarVelocity rv = app.radial_velocity(); double z = app.redshift(); ``` And, you can also get a distance: ```cpp Coordinate d = app.distance(); ``` > [!NOTE] > If you want geometric positions and/or velocities instead, without aberration and gravitational deflection, you > might use `supernovas::Source::geometric_in(Frame&)` instead of `supernovas::Source::apparent_in(Frame&)`. #### Calculate azimuth and elevation angles at the observing location If your ultimate goal is to calculate the azimuth and elevation angles of the source at the specified observing location, you can proceed from the `Apparent` positions you obtained above, provided they are calculated for an Earth based observer (otherwise, you'll get an invalid result): ```cpp // Convert the apparent position to unrefracted horizontal coordinates Horizontal hor = app.to_horizontal() // ...and you might further apply atmospheric refraction with the refraction model and // weather parameters of choice... // Lets define the weather parameters explicitly as 12.0C, 895 mbar, and 47% humidity: Weather weather = Weather(Temperature::celsius(12.0), Pressure::mbar(895.0), 47.0 * Unit::percent); // Obtain refraction cofrrected horizontal coordinates hor = hor.to_refracted(novas_optical_refraction, weather); ``` ### Calculating positions for a Solar-system source - [Planets and/or ephemeris type objects](#ephemeris-sources-cpp) - [Solar-system objects with Keplerian orbital parameters](#orbital-sources-cpp) - [Approximate planet orbitals](#planet-orbitals-cpp) - [Moon's position and phase](#moon-c99) Solar-system sources work similarly to the above with a few important differences at the start. #### Planets and/or ephemeris type objects Historically, NOVAS divided Solar-system objects into two categories: (1) major planets (including also the Sun, the Moon, and the Solar-system Barycenter); and (2) 'ephemeris' type objects, which are all other Solar-system objects. The main difference is the numbering convention. NOVAS major planets have definitive ID numbers (see `enum novas_planet`), whereas 'ephemeris' objects have user-defined IDs. They are also handled by two separate adapter functions (although __SuperNOVAS__ has the option of using the same ephemeris provider for both types of objects also). Thus, you define your `Source` as a `supernovas::Planet` or `supernovas::EphemerisSource` type object with the name or ID number that is used by the ephemeris service you provided. For major planets you might want to use `Planet`, if they use a `novas_planet_provider` function to access ephemeris data with their NOVAS IDs, or else `supernovas::EphemerisSource` for more generic ephemeris handling via a user-provided `novas_ephem_provider`. E.g.: ```cpp // Planet types are handled by the planet provider function. auto mars = Planet::mars(); // Ceres will be handled by the generic ephemeris provider function, which let's say // uses the NAIF ID of 2000001 _or_ the name 'Ceres' (depending on the implementation) auto ceres = EphemerisSource("Ceres", 2000001); ``` > [!IMPORTANT] > Before you can handle all major planets and other ephemeris objects this way, you will have to provide one or more > functions to obtain the barycentric ICRS positions for your Solar-system source(s) of interest for the specific > Barycentric Dynamical Time (TDB) of observation. See section on > [Incorporating Solar-system ephemeris data or services](https://github.com/Sigmyne/SuperNOVAS/blob/main/README.md#solarsystem). And then, it's the same spiel as before, e.g.: ```cpp Apparent app = mars.apparent_in(frame); ``` or to get geometric (unaberrated, undeflected) positions and velocities of when the light left the Solar-system body: ```cpp // Obtain geometric positions / velocities for when light Geometric geom = ceres.geometric_in(frame); // The 3D geometric position of Ceres at the time the observed light originated Position pos = geom.position(); // 3D geometric velocity of Ceres, antedated for when observed light originated Velocity vel = geom.velocity(); ``` #### Solar-system objects with Keplerian orbital parameters You can also define solar system sources with Keplerian orbital elements (such as the most up-to-date ones provided by the [Minor Planet Center](https://minorplanetcenter.net/data) for asteroids, comets, etc.): ```cpp // e.g. a Near-Earth Asteroid in Time ref_time = ... // reference time for which orbital parameters are defined // Define the orbital parameters in the given orbital system: Orbital orb = OrbitalSystem::equatorial(Planet::earth()) .orbit(ref_time, 3452.0 * Unit::km, 192.3 * Unit::deg 3.55 * Unit::h) // t0, M0, T .eccentricity(0.049, 44.1 * Unit::deg) // e, omega .inclination(11.3 * Unit::deg, -112.1 * Unit::deg) // i, Omega .apsis_period(14.5 * Unit::yr) .node_period(29.0 * Unit::yr); // Make an OrbitalSource with the designated name auto nea = orb.to_source("name-this-NEA"); ``` > [!NOTE] > Even with orbital elements, you will, in general, still require an ephemeris provider also, to obtain precise > positions for the Sun, an Earth-based observer, or the planet, around which the orbit is defined. You don't have to fill all the parameters, and instead of setting inclination and the argument of the rising node, you could also set the location of the orbital pole (via `pole()`). And, instead of orbital period, you might use a mean motion parameter to instantiate the orbit with `supernovas::Orbital::from_mean_motion()`. And then, it's once again the same spiel as before, e.g.: ```cpp Apparent app = nea.apparent_in(frame); ``` or ```cpp Geometric geom = nea.geometric_in(frame); ``` #### Approximate planet orbitals Finally, you might generate approximate (arcmin-level) orbitals for the major planets (but not Earth!), the Moon, and the Earth-Moon Barycenter (EMB) also. E.g.: ```cpp // The current Keplerian orbital of Venus... Orbital orb = Planet::venus().orbit(Time::now()); ``` Or, you can use such orbitals (implicitly) to calculate approximate positions and velocities for the planets, e.g.: ```cpp // Approximate, orbital model based, apparent positions for Mars... Apparent app = Planet::mars().approx_apparent_in(frame); // Approximate, orbital model based, geometric positions and velocities for Neptune... Geometric geom = Planet::neptune().approx_geometric_in(frame); ``` Keep in mind that the planet and Moon orbitals are not suitable for precision applications. #### Moon's position and phase __SuperNOVAS__ can calculate positions and velocities for the Moon to arcsecond (or km) level, or better, accuracy using the ELP2000 / MPP02 semi-analytical model by Chapront & Francou (2003). This means that you can calculate astrometric quantities for the Moon with reasonable accuracy even without an ephemeris provider configured. For example, you can calculate the apparent place of the Moon in an observing frame as: ```cpp Frame frame = ...; // Observer location and time of observation // Apparent position of the Moon on observer's sky. Apparent app = frame.apparent_moon_elp2000(); ``` Alternatively, you can obtain geometric positions and velocities of the Moon, relative to the observer using `supernovas::Frame::geometric_moon_elp2000()` instead. You can also obtain the current phase of the Moon, for the time of observation: ```cpp Time t_obs = ...; // Astrometric time of observation // Moon's phase at the specified time (0 is new moon). Angle phase = t_obs.moon_phase(); ``` or, calculate when the Moon will reach a particular phase next: ```cpp Time t_obs = ...; // Astrometric time of observation // Astrometric time of next full moon (phase = 180 deg). Time t_full = t_obs.next_moon_phase(Angle(180.0 * Unit::deg)); ``` ### Going in reverse... Of course, __SuperNOVAS__ allows you to go in reverse, for example from an observed Az/El position all the way to proper ICRS R.A./Dec coordinates, or a geometric place. E.g., let's assume you start with horizontal coorinates that measured at your observing location: ```cpp Horizontal hor = ...; // observer azimuth and elevation angles ``` If needed correct for atmospheric refraction. ```cpp Weather weather(...); // define local weather parameters for the refraction (if needed) hor = hor.to_unrefracted(novas_optical_refraction, weather); ``` Noew you can calculate an apparent place on the celestial sphere given your observing frame (precise location and time of observation). ```cpp Apparent app = hor.to_apparent(frame); ``` or, ```cpp Apparent app = hor.to_apparent(frame, ScalarVelocity(-14.2 * Unit::km / Unit::s), Distance(43.6 * Unit::pc); ``` Note, that when radial velocity and/or distance is not explicitly defined, they are assumed as 0 (km/s) and 1 Gpc, respectively. Next, you can convert the apparent place to a geometric position, referenced to the time when the observed light originated from the source (at the distance defined or assumed): ```cpp AstrometricPosition pos = app.astrometric_position(); ``` Or, calculate the geometric position relative to the SSB instead... ```cpp AstrometricPosition ssb_pos = app.astrometric_position().referenced_to_ssb(); ``` And finally, you can calculate nominal SSB-based ICRS coordinates as: ```cpp Equatorial icrs = ssb_pos.as_equatorial().to_icrs(); ``` ### Calculate rise, set, and transit times You may be interested to know when sources rise above or set below some specific elevation angle, or at what time they appear to transit at the observer location. __SuperNOVAS__ has routines to help you with that too. Given that rise, set, or transit times are dependent on the day of observation, and observer location, they are effectively tied to an observer frame. Let's assume you have defined a source and an observing frame: ```cpp Frame frame = ...; // Earth-based observer location and lower-bound time of interest. Source source = ...; // Source of interest ``` Let's calculate the time when source rises above 30 degrees of elevation next *after* the observing time of the frame, given the NOVAS optical refraction model. ```cpp Weather weather = ...; // Define local weather parameters... Time t_rise = source.rises_above(30.0 * Unit::deg, frame, novas_optical_refraction, weather); ``` Or, calculate the time the source transits after the frame's time of observation: ```cpp Time t_transit = source.transits_in(frame); ``` Or, calculate the next time when source sets below 30 degrees of elevation, not accounting for refraction. ```cpp Time t_set = source.sets_below(30.0 * Unit::deg, frame); ``` Note, that in the current implementation these calls are not well suited sources that are at or within the geostationary orbit, such as such as Low Earth Orbit satellites (LEOs), geostationary satellites (which never really rise, set, or transit), or some Near Earth Objects (NEOs), which will rise set multiple times per day. For the latter, the above calls may still return a valid time, only without the guarantee that it is the time of the first such event after the specified frame instant. A future implementation may address near-Earth orbits better, so stay tuned for updates. ### Coordinate and velocity transforms (change of coordinate system) Equatorial coordinates are inherently linked to a choice of equator orientation (w.r.t. distant quasars), and the location of the equinox, the intersection of the equator of choice with the and ecliptic of date. The choice of equator is commonly referred as the _coordinate reference system_ (e.g. ICRS, CIRS, TOD, J200, B1950). A such, equatorial coordinates (`supernovas::Equatorial` class) and ecliptic coordinates (`supernovas::Ecliptic` class) are always defined w.r.t. an equator and equinox, a.k.a. a reference system, of choice (`supernovas::Equinox` class). However, after such coordinates are instantiated for one choice of reference system, you can easily convert them to another, even if the other system is defined for a different date: ```cpp // Suppose you have ICRS equatorial coordinates Equatorial eq = ...; // convert them to say CIRS coordinates now... Equatorial cirs_now = eq >> Equinox::cirs(Time::now(eop)); // or convert to B1950 coordinates Equatorial b1950 = icrs.to_b1950(); ``` The astrometric time definition for 'now' needs Earth Orientation Parameters (EOP), which are defined by the `supernovas::EOP` class. The operator `>>` is a shorthand for `.to_system()`, and we could have used `.to_cirs(Time&)` as well. Similarly, the `.to_b1950()` is a shorthand for `.to_system(Equinox::b1950())`. These methods and operators can be used interchangeably. The same goes for ecliptic coordinates: ```cpp // define ecliptic coordinates in some reference system Ecliptic ec = ...; // convert to ICRS Ecliptic ec_icrs = ec.to_icrs(); // convert to J2000 Ecliptic ec_j2000 = ec >> Equinox::j2000(); ``` You can also easily convert between equatorial, ecliptic, and galactic coordinates (`supernovas::Galactic` class), e.g.: ```cpp // say you start with equatorial Equatorial eq = ...; // convert to J2000 Ecliptic coordinates Ecliptic ec2000 = eq.to_ecliptic().to_j2000(); // convert to Galactic coordinates Galactic gal = eq.to_galactic(); // Let's convert back and check if (eq != gal.equatorial()) std::cerr << "Oops, that was unexpected.\n"; ``` Similarly, geometric (equatorial) positions and velocities (`supernovas::Geometric` class), defined for an observing frame, are also defined w.r.t. an equator and equinox. They can be converted to another reference system type for the same date, or else ICRS or J2000: ```cpp // Define some geometric positions and velocities in an observing frame Geometric geom = ...; // convert to ICRS positions / velocities Geometric geom_icrs = geom.to_icrs(); // convert to J2000 position / velocities Geometric geom_j2000 = geom.to_system(NOVAS_J2000); // convert to pseudo Earth rotating TIRS positions / velocities Geometric geom_tirs = geom >> NOVAS_TIRS; ``` Once again, the `>>` operator is just a shorthand for the `.to_system()` method, and there are system-specific convenience methods (like `.to_icrs()`, or `to_mod()`) defined also. Note, that geometric coordinates can be defined not only for celestial equatorial systems, but also for the Earth-rotating reference systems TIRS and ITRS. ----------------------------------------------------------------------------- Copyright (C) 2026 Attila Kovács Sigmyne-SuperNOVAS-c764b40/benchmark/000077500000000000000000000000001517360672500173315ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/benchmark/.gitignore000066400000000000000000000000261517360672500213170ustar00rootroot00000000000000benchmark* !*.c !*.py Sigmyne-SuperNOVAS-c764b40/benchmark/CMakeLists.txt000066400000000000000000000015511517360672500220730ustar00rootroot00000000000000# Additional CMake configuration file for building the benchmarking programs # of the SuperNOVAS library. # # To invoke simply configure the cmake build in the supernovas directory with # the -DBUILD_BENCHMARK=ON option. # # Author: Attila Kovacs # List of benchmarking programs to build set(BENCHMARK_PROGRAMS benchmark-nutation benchmark-place ) include_directories(${supernovas_INCLUDE_DIRS}) # Build each example foreach(BENCHMARK ${BENCHMARK_PROGRAMS}) set(BENCHMARK_SOURCE ${BENCHMARK}.c) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${BENCHMARK_SOURCE}) add_executable(${BENCHMARK} ${BENCHMARK_SOURCE}) # Link against the supernovas library target_link_libraries(${BENCHMARK} PRIVATE core) else() message(WARNING "Source file ${BENCHMARK_SOURCE} not found - ${BENCHMARK} will not be built") endif() endforeach() Sigmyne-SuperNOVAS-c764b40/benchmark/Makefile000066400000000000000000000020121517360672500207640ustar00rootroot00000000000000# Part of SuperNOVAS # # Generates headless README.md and HTML documentation # # Author: Attila Kovacs # Use the definitions project definitions include ../config.mk BENCHMARKS = benchmark-nutation benchmark-place LIB ?= ../lib CPPFLAGS += -I../include LDFLAGS += -L$(LIB) -lsupernovas .PHONY: all all: build run .PHONY: build build: $(BENCHMARKS) .PHONY: run run: build @for prog in $(BENCHMARKS) ; do $(LIB_PATH_VAR)=$(LIB) ./$${prog} ; done .PHONY: clean clean: .PHONY: distclean distclean: clean @rm -f $(BENCHMARKS) benchmark-%: benchmark-%.c $(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $< $(LDFLAGS) # Built-in help screen for `make help` .PHONY: help help: @echo @echo "Syntax: make [target]" @echo @echo "The following targets are available:" @echo @echo " all (default) builds and runs benchmarks." @echo " build Builds benchmarks." @echo " run Runs benchmarks." @echo " clean Removes intermediate products." @echo " distclean Deletes all generated files." @echo Sigmyne-SuperNOVAS-c764b40/benchmark/benchmark-astropy.py000066400000000000000000000050541517360672500233400ustar00rootroot00000000000000# astropy benchmark for position calculations, matching the SuperNOVAS # benchmarks in `benchmark-place.c` # # It calculates CIRS positions for an Earth based observer for a number of # random sidereal sources. The first benchmark calculates positions for a # fixed observing frame (time and observer location), while the second test # calculates positions for individual observing frames. # # Author: Attila Kovacs # Date: 2025-01-25 # ---------------------------------------------------------------------------- import astropy import random import time import astropy.units as u from astropy.coordinates import SkyCoord, EarthLocation, Longitude, Latitude, CIRS # ---------------------------------------------------------------------------- # main program entry point # Number of sources / iterations to test with N = 300 # ---------------------------------------------------------------------------- # Set up a source 'catalog' with the desired number of sources and random # properties sources = [] for i in range(0, N): # Generate random source properties ra = Longitude(360.0 * (random.random() - 0.5) * u.degree) dec = Latitude(180.0 * (random.random() - 0.5) * u.degree) d = (1.0 + 1000.0 * random.random()) * u.pc pmra = 100.0 * (random.random() - 0.5) * u.mas / u.yr pmdec = 100.0 * (random.random() - 0.5) * u.mas / u.yr rv = 1000.0 * (random.random() - 0.5) * u.km / u.s sc = SkyCoord(ra, dec, d, pm_ra_cosdec=pmra, pm_dec=pmdec, radial_velocity=rv) sources.append(sc) # ---------------------------------------------------------------------------- # Benchmark 1: calculating positions in the same frame # Set up a fixed observing frame... tim = astropy.time.Time("2025-01-25T15:32:00") loc = EarthLocation.from_geodetic(lon=Longitude(6.16 * u.degree), lat=Latitude(42.7 * u.degree), height=2500.0) frame = CIRS(obstime=tim, location=loc) start = time.time() for source in sources : source.transform_to(frame) end = time.time() print("same frame " + str(N / (end - start))) # ---------------------------------------------------------------------------- # Benchmark 2: calculating positions in individual frames start = time.time() for source in sources : tim = astropy.time.Time("2025-01-25T15:32:00") - 365.0 * random.random() * u.day lon = Longitude(360.0 * random.random() * u.degree) lat = Latitude(180.0 * (random.random() - 0.5) * u.degree) loc = EarthLocation.from_geodetic(lon, lat, height=2500.0) frame = CIRS(obstime=tim, location=loc) source.transform_to(frame) end = time.time() print("individual frame " + str(N / (end - start))) Sigmyne-SuperNOVAS-c764b40/benchmark/benchmark-nutation.c000066400000000000000000000041041517360672500232650ustar00rootroot00000000000000/** * @file * * @date Created on Jan 26, 2025 * @author Attila Kovacs */ /** * @file * * @date Created on Jan 24, 2025 * @author Attila Kovacs */ #define _POSIX_C_SOURCE 199309L ///< for clock_gettime() #include #include #include #include #include #include ///< SuperNOVAS functions and definitions #define LEAP_SECONDS 37 ///< [s] current leap seconds from IERS Bulletin C #define DUT1 0.114 ///< [s] current UT1 - UTC time difference from IERS Bulletin A static void timestamp(novas_timespec *t) { novas_set_current_time(LEAP_SECONDS, DUT1, t); } int main() { // observer location // Other variables we need -----------------------------------------------> int i, N = 100000, N2 = N / 10; double tjd = 2460683.132905, dx, dy; novas_timespec start, end; // ------------------------------------------------------------------------- // Start benchmarks... fprintf(stderr, "Starting single-thread benchmarks...\n"); // ------------------------------------------------------------------------- // Benchmark reduced accuracy, place(), same time timestamp(&start); for(i = 0; i < N2; i++) iau2000a(tjd + i * 0.01, 0.0, &dx, &dy); timestamp(&end); printf(" - iau2000a: %12.1f nutations/sec\n", N2 / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark reduced accuracy, place(), different times() timestamp(&start); for(i = 0; i < N; i++) for(i = 0; i < N; i++) iau2000b(tjd + i * 0.01, 0.0, &dx, &dy); timestamp(&end); printf(" - iau2000b: %12.1f positions/sec\n", N / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark reduced accuracy, place(), different times() timestamp(&start); for(i = 0; i < N; i++) for(i = 0; i < N; i++) nu2000k(tjd + i * 0.01, 0.0, &dx, &dy); timestamp(&end); printf(" - nu2000k: %12.1f positions/sec\n", N / novas_diff_time(&end, &start)); return 0; } Sigmyne-SuperNOVAS-c764b40/benchmark/benchmark-place.c000066400000000000000000000210231517360672500225070ustar00rootroot00000000000000/** * @file * * @date Created on Jan 24, 2025 * @author Attila Kovacs */ #if __STDC_VERSION__ < 201112L # define _POSIX_C_SOURCE 199309 ///< struct timespec #endif #include #include #include #include #include #include ///< SuperNOVAS functions and definitions #define LEAP_SECONDS 37 ///< [s] current leap seconds from IERS Bulletin C #define DUT1 0.114 ///< [s] current UT1 - UTC time difference from IERS Bulletin A #define POLAR_DX 230.0 ///< [mas] Earth polar offset x, e.g. from IERS Bulletin A. #define POLAR_DY -62.0 ///< [mas] Earth polar offset y, e.g. from IERS Bulletin A. static void timestamp(novas_timespec *t) { novas_set_current_time(LEAP_SECONDS, DUT1, t); } static void calc_pos(const cat_entry *star, const novas_frame *frame) { object source = NOVAS_OBJECT_INIT; sky_pos apparent = SKY_POS_INIT; make_cat_object(star, &source); if(novas_sky_pos(&source, frame, NOVAS_CIRS, &apparent) != 0) { fprintf(stderr, "ERROR! failed to calculate apparent position.\n"); exit(1); } } static void calc_place(const cat_entry *star, const novas_frame *frame) { const novas_timespec *time = &frame->time; sky_pos apparent = SKY_POS_INIT; if(place_star(time->ijd_tt + time->fjd_tt, star, &frame->observer, time->ut1_to_tt, NOVAS_CIRS, frame->accuracy, &apparent) != 0) { fprintf(stderr, "ERROR! failed to calculate apparent position.\n"); exit(1); } } int main(int argc, const char *argv[]) { // SuperNOVAS variables used for the calculations -------------------------> cat_entry *stars; // Array of sidereal source entries. observer obs; // observer location novas_timespec obs_time; // astrometric time of observation novas_frame obs_frame; // observing frame defined for observing time and location // Intermediate variables we'll use --------------------------------------> novas_timespec start, end; // timestamps for execution time // Other variables we need -----------------------------------------------> int i, N = 300000, N2 = N / 10, N3 = N / 30; novas_debug(1); if(argc > 1) N = (int) strtol(argv[1], NULL, 10); if(N < 1) { fprintf(stderr, "ERROR! invalid source count: %d\n", N); return 1; } stars = (cat_entry *) calloc(N, sizeof(cat_entry)); if(!stars) { fprintf(stderr, "ERROR! alloc %d stars: %s\n", N, strerror(errno)); return 1; } // ------------------------------------------------------------------------- // Define observer somewhere on Earth (we can also define observers in Earth // or Sun orbit, at the geocenter or at the Solary-system barycenter...) // Specify the location we are observing from // 50.7374 deg N, 7.0982 deg E, 60m elevation // (We'll ignore the local weather parameters here, but you can set those too.) if(make_observer_on_surface(50.7374, 7.0982, 60.0, 0.0, 0.0, &obs) != 0) { fprintf(stderr, "ERROR! defining Earth-based observer location.\n"); return 1; } // ------------------------------------------------------------------------- // Set the astrometric time of observation... // Set the time of observation to the current UTC-based UNIX time if(novas_set_current_time(LEAP_SECONDS, DUT1, &obs_time) != 0) { fprintf(stderr, "ERROR! failed to set time of observation.\n"); return 1; } // ------------------------------------------------------------------------- // Initialize the observing frame with the given observing and Earth // orientation patameters. // if(novas_make_frame(NOVAS_REDUCED_ACCURACY, &obs, &obs_time, POLAR_DX, POLAR_DY, &obs_frame) != 0) { fprintf(stderr, "ERROR! failed to define observing frame.\n"); return 1; } // ------------------------------------------------------------------------- // Allow faking high-accuracy calculations enable_earth_sun_hp(1); // ------------------------------------------------------------------------- // Configure sources with random data. fprintf(stderr, "Configuring %d sources...\n", N); for(i = 0; i < N; i++) { cat_entry *star = &stars[i]; sprintf(star->catalog, "TST"); sprintf(star->starname, "test-%d", i); star->starnumber = i; star->ra = (23.0 * rand()) / RAND_MAX; star->dec = (180.0 * rand()) / RAND_MAX - 90.0; star->radialvelocity = (1000.0 * rand()) / RAND_MAX - 500.0; star->parallax = (20.0 * rand()) / RAND_MAX; star->promora = (200.0 * rand()) / RAND_MAX - 100.0; star->promodec = (200.0 * rand()) / RAND_MAX - 100.0; } // ------------------------------------------------------------------------- // Start benchmarks... fprintf(stderr, "Starting single-thread benchmarks...\n"); // ------------------------------------------------------------------------- // Benchmark reduced accuracy, same frame timestamp(&start); for(i = 0; i < N; i++) calc_pos(&stars[i], &obs_frame); timestamp(&end); printf(" - novas_sky_pos(), same frame, red. acc.: %12.1f positions/sec\n", N / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark full accuracy, same frame obs_frame.accuracy = NOVAS_FULL_ACCURACY; timestamp(&start); for(i = 0; i < N; i++) calc_pos(&stars[i], &obs_frame); timestamp(&end); printf(" - novas_sky_pos(), same frame, full acc.: %12.1f positions/sec\n", N / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark place() reduced accuracy, same frame timestamp(&start); for(i = 0; i < N; i++) calc_place(&stars[i], &obs_frame); timestamp(&end); printf(" - place(), same frame, red. acc.: %12.1f positions/sec\n", N / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark place() full accuracy, same frame obs_frame.accuracy = NOVAS_FULL_ACCURACY; timestamp(&start); for(i = 0; i < N; i++) calc_place(&stars[i], &obs_frame); timestamp(&end); printf(" - place(), same frame, full acc.: %12.1f positions/sec\n", N / novas_diff_time(&end, &start)); // individual frames are expected to be significantly slower, so // benchmark over fewer iterations N /= 10; // ------------------------------------------------------------------------- // Benchmark reduced accuracy, individual fames timestamp(&start); for(i = 0; i < N2; i++) { novas_set_time(NOVAS_TT, novas_get_time(&start, NOVAS_TT) + i, LEAP_SECONDS, DUT1, &obs_time); novas_make_frame(NOVAS_REDUCED_ACCURACY, &obs, &obs_time, POLAR_DX, POLAR_DY, &obs_frame); calc_pos(&stars[i], &obs_frame); } timestamp(&end); printf(" - novas_sky_pos, individual, red. acc.: %12.1f positions/sec\n", N2 / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark full accuracy, individual frames timestamp(&start); for(i = 0; i < N3; i++) { novas_set_time(NOVAS_TT, novas_get_time(&start, NOVAS_TT) + i, LEAP_SECONDS, DUT1, &obs_time); novas_make_frame(NOVAS_FULL_ACCURACY, &obs, &obs_time, POLAR_DX, POLAR_DY, &obs_frame); calc_pos(&stars[i], &obs_frame); } timestamp(&end); printf(" - novas_sky_pos, individual, full acc.: %12.1f positions/sec\n", N3 / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark place() reduced accuracy, individual frames obs_frame.accuracy = NOVAS_REDUCED_ACCURACY; timestamp(&start); for(i = 0; i < N2; i++) { novas_set_time(NOVAS_TT, novas_get_time(&start, NOVAS_TT) + ((i % 2) ? 1 : -1), LEAP_SECONDS, DUT1, &obs_frame.time); calc_place(&stars[i], &obs_frame); } timestamp(&end); printf(" - place(), individual, red. acc.: %12.1f positions/sec\n", N2 / novas_diff_time(&end, &start)); // ------------------------------------------------------------------------- // Benchmark place full accuracy, individual frames obs_frame.accuracy = NOVAS_FULL_ACCURACY; timestamp(&start); for(i = 0; i < N3; i++) { novas_set_time(NOVAS_TT, novas_get_time(&start, NOVAS_TT) + ((i % 2) ? 1 : -1), LEAP_SECONDS, DUT1, &obs_frame.time); calc_place(&stars[i], &obs_frame); } timestamp(&end); printf(" - place(), individual, full acc.: %12.1f positions/sec\n", N3 / novas_diff_time(&end, &start)); return 0; } Sigmyne-SuperNOVAS-c764b40/build.mk000066400000000000000000000027241517360672500170340ustar00rootroot00000000000000 # ============================================================================ # Generic build targets and recipes for SuperNOVAS. # # You can include this in your Makefile also. # ============================================================================ # Regular object files $(OBJ)/%.o: %.c $(OBJ) Makefile $(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $< # Shared library recipe $(LIB)/%.$(SOEXT).$(SO_VERSION): | $(LIB) $(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $^ $(SHARED_FLAGS) $(SONAME_FLAG)$(notdir $@) $(LDFLAGS) # Unversioned shared libs (for linking against) $(LIB)/lib%.$(SOEXT): @rm -f $@ ( cd $(dir $@); ln -s $(notdir $<) $(notdir $@) ) # Static library recipe $(LIB)/%.a: @$(MAKE) $(LIB) ar -rc $@ $^ ranlib $@ # Create sub-directories for build targets $(OBJ) $(LIB) $(BIN): mkdir -p $@ # Remove intermediate files locally .PHONY: clean-local clean-local: @rm -rf obj # Remove all locally built files, effectively restoring the repo to its # pristine state .PHONY: distclean-local distclean-local: clean-local @rm -rf bin lib infer-out # Remove intermediate files (general) .PHONY: clean clean: clean-local # Remove intermediate files (general) .PHONY: distclean distclean: distclean-local CHECK_DIR ?= . # Static code analysis using 'cppcheck' .PHONY: analyze analyze: @echo " [analyze]" @cppcheck $(CPPFLAGS) -DCPPCHECK=1 $(CHECKOPTS) $(CHECK_DIR) # Static code analysis viacat Facebook's infer .PHONY: infer infer: clean infer run -- $(MAKE) shared Sigmyne-SuperNOVAS-c764b40/cmake/000077500000000000000000000000001517360672500164575ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/cmake/cmake_uninstall.cmake.in000066400000000000000000000016261517360672500232440ustar00rootroot00000000000000# cmake_uninstall.cmake.in # # Uninstall target template for CMake projects # if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") endif() file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif() else() message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif() endforeach() Sigmyne-SuperNOVAS-c764b40/cmake/supernovas.pc.in000066400000000000000000000005721517360672500216210ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=@CMAKE_INSTALL_FULL_LIBDIR@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: supernovas Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ URL: @PROJECT_HOMEPAGE_URL@ Copyright: (C) 2026 Attila Kovacs License: Unlicense Cflags: -I${includedir} Libs: -L${libdir} @PC_LIBS@ Libs.private: @PC_LIBS_PRIVATE@ Sigmyne-SuperNOVAS-c764b40/cmake/supernovasConfig.cmake.in000066400000000000000000000021271517360672500234230ustar00rootroot00000000000000@PACKAGE_INIT@ # supernovas CMake configuration file include(CMakeFindDependencyMacro) # Find math library if needed if(NOT WIN32) find_library(MATH_LIBRARY m) if(NOT MATH_LIBRARY) message(FATAL_ERROR "Math library not found") endif() endif() # Include targets include("${CMAKE_CURRENT_LIST_DIR}/supernovasTargets.cmake") # Get include directories from target properties get_target_property(supernovas_INCLUDE_DIRS supernovas::core INTERFACE_INCLUDE_DIRECTORIES) # Check if optional components are available if(TARGET supernovas::cpp) set(supernovas_cpp_FOUND TRUE) else() set(supernovas_cpp_FOUND FALSE) endif() if(TARGET supernovas::solsys-calceph) find_library(CALCEPH_LIB calceph) find_dependency(Threads) set(supernovas_solsys-calceph_FOUND TRUE) else() set(supernovas_solsys-calceph_FOUND FALSE) endif() if(TARGET supernovas::solsys-cspice) find_library(CSPICE_LIB cspice) find_dependency(Threads) set(supernovas_solsys-cspice_FOUND TRUE) else() set(supernovas_solsys-cspice_FOUND FALSE) endif() check_required_components(supernovas) Sigmyne-SuperNOVAS-c764b40/codecov.yml000066400000000000000000000006461517360672500175520ustar00rootroot00000000000000codecov: require_ci_to_pass: no coverage: precision: 2 round: down status: patch: off project: default: target: auto threshold: 0.3% removed_code_behavior: adjust_base parsers: gcov: branch_detection: conditional: yes loop: yes method: no macro: no comment: layout: "reach,diff,flags,files,footer" behavior: default require_changes: no Sigmyne-SuperNOVAS-c764b40/config.mk000066400000000000000000000140561517360672500172030ustar00rootroot00000000000000# =========================================================================== # Generic configuration options for building the SuperNOVAS libraries (both # static and shared). # # You can include this snipplet in your Makefile also. # ============================================================================ # Folders for compiled objects, libraries, and binaries, respectively OBJ ?= obj BIN ?= bin # Default compiler to use (if not defined externally) CC ?= gcc # Default compiler options (if not defined externally) CFLAGS ?= -g -Os -Wall # Specific Doxygen to use if not the default one #DOXYGEN ?= /opt/bin/doxygen # To make SuperNOVAS thread-safe, we use thread-local storage modifier # keywords. These were not standardized prior to C11. So while we automatically # recognize C11 or GCC >= 3.3 to use the correct thread-local modifier keyword, # for other compilers (e.g. Intel C, LLVM) you may need to specify it # explicitly here by passing the keyword via the THREAD_LOCAL definition # # E.g. #THREAD_LOCAL ?= __thread #or #THREAD_LOCAL ?= __declspec( thread ) # To build / install the C++ library (libsupernovas++)... #ENABLE_CPP=1 # To compile library with an external or legacy `solarsystem()` / # `solarsystem_hp()` implementation as the default planet provider, specify # the source(s), which provide the implementation. (E.g. `legacy/solsys1.c # legacy/eph_manager.c` or 'src/solsys-calceph.c`). If not set, then # `solarsystem()` / `solatsystem_hp()` will be provided by the currently # defined `novas_planet_provider` call, such as `src/solsys3.c`. #SOLSYS_SOURCE = legacy/solsys1.c legacy/eph_manager.c # To compile to use some user-supplied legacy `readeph()` implementation as # the default ephemeris data provider, specify the source that will provide # the implementation. If not set, SuperNOVAS will not provide a legacy # `readeph()` implementation. #READEPH_SOURCE = legacy/readeph0.c # Whether or not to build solsys-calceph libraries. You need the calceph # development libraries (libcalceph.so and/or libcaclceph.a) installed in # LD_LIBRARY_PATH, and calceph.h in /usr/include or some other accessible # location (you may also set an appropriate -I option to CPPFLAGS # prior to calling make). #CALCEPH_SUPPORT = 1 # Whether or not to build solsys-cspice libraries. You need the CSPICE # development libraries (libcspice.so and/or libcspice.a) installed in # LD_LIBRARY_PATH, and CSPICE header files in /usr/include/cspice or some # other accessible location (you may also set an appropriate -I # option to CPPFLAGS prior to calling make). #CSPICE_SUPPORT = 1 # cppcheck options for 'check' target. You can add additional options by # setting the CHECKEXTRA variable (e.g. in shell) prior to invoking 'make'. LANGUAGE ?= c CHECKOPTS ?= --enable=performance,warning,portability,style --language=$(LANGUAGE) \ --error-exitcode=1 --std=c99 # Add-on ccpcheck options CHECKOPTS += --inline-suppr $(CHECKEXTRA) # Exhaustive checking for newer cppcheck... #CHECKOPTS += --check-level=exhaustive # ============================================================================ # END of user config section. # # Below are some generated constants based on the one that were set above # ============================================================================ SUPERNOVAS_BUILD := 1 export SUPERNOVAS_BUILD # The version of the shared .so libraries SO_VERSION := 1 # If the THREAD_LOCAL variable was defined externally, use that definition to # specify the thread local keyword to use. ifdef THREAD_LOCAL CPPFLAGS += -DTHREAD_LOCAL=\"$(THREAD_LOCAL)\" endif # Whether to use user-provided legacy `solarsystem()` / `solarsystem_hp()` # functions as the default planetary ephemeris provider. ifdef SOLSYS_SOURCE SOURCES += $(SOLSYS_SOURCE) CPPFLAGS += -DUSER_SOLSYS=1 endif # Whether to use a legacy `readeph()` function as the default non-planetary # ephemeris provider. ifdef READEPH_SOURCE SOURCES += $(READEPH_SOURCE) CPPFLAGS += -DUSER_READEPH=1 endif # Compile for specific C standard ifdef CSTANDARD CFLAGS += -std=$(CSTANDARD) endif # Extra warnings (not supported on all compilers) ifeq ($(WEXTRA), 1) CFLAGS += -Wextra endif # Add source code fortification checks ifdef FORTIFY CFLAGS += -D_FORTIFY_SOURCE=$(FORTIFY) endif # By default determine the build platform (OS type) PLATFORM ?= $(shell uname -s) # Platform-specific configurations ifeq ($(PLATFORM),Darwin) # macOS specific SOEXT := dylib SHARED_FLAGS := -dynamiclib -fPIC SONAME_FLAG := -Wl,-install_name,@rpath/ LIB_PATH_VAR := DYLD_LIBRARY_PATH else # Linux/Unix specific SOEXT := so SHARED_FLAGS := -shared -fPIC SONAME_FLAG := -Wl,-soname, LIB_PATH_VAR := LD_LIBRARY_PATH endif # On Linux autodetect calceph / cspice libraties with ldconfig ifeq ($(PLATFORM),Linux) AUTO_DETECT_LIBS := 1 else AUTO_DETECT_LIBS := 0 endif ifeq ($(AUTO_DETECT_LIBS),1) # Use ldconfig (if available) to detect CALCEPH / CSPICE shared libs # automatically ifndef CALCEPH_SUPPORT ifneq ($(shell ldconfig -p | grep libcalceph), ) CALCEPH_SUPPORT = 1 endif endif ifndef CSPICE_SUPPORT ifneq ($(shell ldconfig -p | grep libcspice), ) CSPICE_SUPPORT = 1 endif endif endif SOURCES = target.c observer.c earth.c equator.c system.c transform.c cio.c \ orbital.c spectral.c grav.c nutation.c timescale.c frames.c place.c \ calendar.c refract.c naif.c parse.c util.c planets.c itrf.c \ ephemeris.c solsys3.c solsys-ephem.c moon.c # Generate a list of object (obj/*.o) files from the input sources OBJECTS := $(addprefix $(OBJ)/,$(subst .c,.o,$(SOURCES))) # Default values for install locations # See https://www.gnu.org/prep/standards/html_node/Directory-Variables.html prefix ?= /usr exec_prefix ?= $(prefix) libdir ?= $(exec_prefix)/lib includedir ?= $(prefix)/include datarootdir ?= $(prefix)/share datadir ?= $(datarootdir) mydatadir ?= $(datadir)/supernovas docdir ?= $(datarootdir)/doc/supernovas htmldir ?= $(docdir)/html # Search for files in the designated locations vpath %.h $(INC) vpath %.o $(OBJ) vpath %.d dep Sigmyne-SuperNOVAS-c764b40/doc/000077500000000000000000000000001517360672500161445ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/doc/.gitignore000066400000000000000000000000261517360672500201320ustar00rootroot00000000000000README*.md html *.tag Sigmyne-SuperNOVAS-c764b40/doc/CMakeLists.txt000066400000000000000000000020211517360672500206770ustar00rootroot00000000000000# Additional CMake configuration file for building the documentation of the # SuperNOVAS library. # # To invoke simply configure the cmake build in the supernovas directory with # the -DBUILD_DOC=ON option. # # Author: Attila Kovacs # ---------------------------------------------------------------------------- # Generate derivative documentation # Generate headless README add_executable(docedit EXCLUDE_FROM_ALL src/docedit.c) add_custom_target(headless_readme ALL COMMAND docedit ${CMAKE_CURRENT_SOURCE_DIR} ) # Install Markdown documentation (Development) file(GLOB MD_FILES doc/*.md) install(FILES ${MD_FILES} COMPONENT Development DESTINATION ${CMAKE_INSTALL_DOCDIR} ) find_package(Doxygen) set_package_properties(Doxygen PROPERTIES URL "https://doxygen.nl/" DESCRIPTION "is a widely-used documentation generator tool in software development" TYPE OPTIONAL PURPOSE "Enables HTML documentation for supernovas" ) add_subdirectory(c99) if(ENABLE_CPP) add_subdirectory(cpp) endif() Sigmyne-SuperNOVAS-c764b40/doc/Makefile000066400000000000000000000016621517360672500176110ustar00rootroot00000000000000# Part of SuperNOVAS # # Generates headless README.md and HTML documentation # # Author: Attila Kovacs CC ?= gcc # Doxygen documentation (HTML and man pages) .PHONY: all all: README.md @$(MAKE) -C c99 all @$(MAKE) -C cpp all .INTERMEDIATE: docedit docedit: src/docedit.o $(CC) -o $@ $^ # Generate headless and undecorated README variants README.md README-undecorated.md: ../README.md docedit @echo " [README variants]" @./docedit .PHONY: clean clean: @rm -f docedit src/docedit.o @$(MAKE) -C c99 clean @$(MAKE) -C cpp clean .PHONY: distclean distclean: clean @rm -rf README*.md @$(MAKE) -C c99 distclean @$(MAKE) -C cpp distclean .PHONY: help help: @echo @echo "Syntax: make [target]" @echo @echo "The following targets are available:" @echo @echo " all (default) Build HTML documentation." @echo " clean Removes intermediate products." @echo " distclean Deletes all generated files." @echo Sigmyne-SuperNOVAS-c764b40/doc/USAGE-C99.md000077700000000000000000000000001517360672500216322../USAGE-C99.mdustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/doc/USAGE-CPP.md000077700000000000000000000000001517360672500217662../USAGE-CPP.mdustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/doc/c99/000077500000000000000000000000001517360672500165505ustar00rootroot00000000000000Sigmyne-SuperNOVAS-c764b40/doc/c99/CMakeLists.txt000066400000000000000000000023541517360672500213140ustar00rootroot00000000000000# Additional CMake configuration file for building the documentation of the # SuperNOVAS library. The examples are also added to the test suite so they # may be checked for functionality. # # To invoke simply configure the cmake build in the supernovas directory with # the -DBUILD_DOC=ON option. # # Author: Attila Kovacs # ---------------------------------------------------------------------------- # Generate derivative documentation if(Doxygen_FOUND) # Generate headless docs and run Doxygen on them. doxygen_add_docs(project_docs ALL CONFIG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile) add_dependencies(project_docs headless_readme) # For html/ dir, list just the directory, not the individual files installed. install(CODE "message(STATUS \"Installing: /${CMAKE_INSTALL_DOCDIR}/html/c99/*\")") install(DIRECTORY html/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/html/c99 MESSAGE_NEVER COMPONENT Development ) # Install Doxygen tag, which downstream docs can link to. install(FILES supernovas.tag DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT Development ) else() message(WARNING "Doxygen not found -- Will skip generating C99 HTML documentation") endif() Sigmyne-SuperNOVAS-c764b40/doc/c99/Doxyfile000066400000000000000000004113251517360672500202640ustar00rootroot00000000000000# Doxyfile 1.14.0 # This file describes the settings to be used by the documentation system # Doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). # # Note: # # Use Doxygen to compare the used configuration file with the template # configuration file: # doxygen -x [configFile] # Use Doxygen to compare the used configuration file with the template # configuration file without replacing the environment variables or CMake type # replacement variables: # doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the configuration # file that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "SuperNOVAS C API" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = v1.6 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewers a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "High-precision C/C++ astrometry library" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = resources/SuperNOVAS-logo-55x55.png # With the PROJECT_ICON tag one can specify an icon that is included in the tabs # when the HTML document is shown. Doxygen will copy the logo to the output # directory. PROJECT_ICON = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where Doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format # and will distribute the generated files over these directories. Enabling this # option can be useful when feeding Doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise cause # performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to # control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO # Controls the number of sub-directories that will be created when # CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every # level increment doubles the number of directories, resulting in 4096 # directories at level 8 which is the default and also the maximum value. The # sub-directories are organized in 2 levels, the first level always has a fixed # number of 16 directories. # Minimum value: 0, maximum value: 8, default value: 8. # This tag requires that the tag CREATE_SUBDIRS is set to YES. CREATE_SUBDIRS_LEVEL = 8 # If the ALLOW_UNICODE_NAMES tag is set to YES, Doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by Doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, # Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English # (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, # Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with # English messages), Korean, Korean-en (Korean with English messages), Latvian, # Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, # Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, # Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, Doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, Doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, Doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, Doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = NO # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which Doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where Doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, Doxygen will generate much shorter (but # less readable) file names. This can be useful if your file system doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen will interpret the # first line (until the first dot, question mark or exclamation mark) of a # Javadoc-style comment as the brief description. If set to NO, the Javadoc- # style will behave just like regular Qt-style comments (thus requiring an # explicit @brief command for a brief description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the JAVADOC_BANNER tag is set to YES then Doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be # interpreted by Doxygen. # The default value is: NO. JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will interpret the first # line (until the first dot, question mark or exclamation mark) of a Qt-style # comment as the brief description. If set to NO, the Qt-style will behave just # like regular Qt-style comments (thus requiring an explicit \brief command for # a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # By default Python docstrings are displayed as preformatted text and Doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the # Doxygen's special commands can be used and the contents of the docstring # documentation blocks is shown as Doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then Doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". Note that you cannot put \n's in the value part of an alias # to insert newlines (in the resulting output). You can put ^^ in the value part # of an alias to insert a newline as if a physical newline was in the original # file. When you need a literal { or } or , in the value part of an alias you # have to escape them by means of a backslash (\), this can lead to conflicts # with the commands \{ and \} for these it is advised to use the version @{ and # @} or use a double escape (\\{ and \\}) ALIASES = "c_source=@ingroup source" \ "c_observer=@ingroup observer" \ "c_time=@ingroup time" \ "c_frame=@ingroup frame" \ "c_apparent=@ingroup apparent" \ "c_geometric=@ingroup geometric" \ "c_equatorial=@ingroup equatorial" \ "c_nonequatorial=@ingroup nonequatorial" \ "c_refract=@ingroup refract" \ "c_spectral=@ingroup spectral" \ "c_solar-system=@ingroup solar-system" \ "c_earth=@ingroup earth" \ "c_util=@ingroup util" \ "c_tracking=@ingroup tracking" \ "c_interferometry=@ingroup interferometry" # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice # sources only. Doxygen will then generate output that is more tailored for that # language. For instance, namespaces will be presented as modules, types will be # separated into more groups, etc. # The default value is: NO. OPTIMIZE_OUTPUT_SLICE = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by Doxygen: IDL, Java, JavaScript, # Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, # VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make Doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by Doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by Doxygen, so you can # mix Doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 6. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 # The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to # generate identifiers for the Markdown headings. Note: Every identifier is # unique. # Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a # sequence number starting at 0 and GITHUB use the lower case version of title # with any whitespace replaced by '-' and punctuation characters removed. # The default value is: DOXYGEN. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. MARKDOWN_ID_STYLE = DOXYGEN # When enabled Doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. Words listed in the # AUTOLINK_IGNORE_WORDS tag are excluded from automatic linking. # The default value is: YES. AUTOLINK_SUPPORT = YES # This tag specifies a list of words that, when matching the start of a word in # the documentation, will suppress auto links generation, if it is enabled via # AUTOLINK_SUPPORT. This list does not affect links explicitly created using \# # or the \link or commands. # This tag requires that the tag AUTOLINK_SUPPORT is set to YES. AUTOLINK_IGNORE_WORDS = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let Doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also makes the inheritance and # collaboration diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software) sources only. Doxygen will parse # them like normal C++ but will assume all classes use public instead of private # inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # Doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then Doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, Doxygen keeps a cache of pre-resolved symbols. If the cache is too small # Doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run Doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 # The NUM_PROC_THREADS specifies the number of threads Doxygen is allowed to use # during processing. When set to 0 Doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, # which effectively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 0 # If the TIMESTAMP tag is set different from NO then each generated page will # contain the date or date and time when the page was generated. Setting this to # NO can help when comparing the output of multiple runs. # Possible values are: YES, NO, DATETIME and DATE. # The default value is: NO. TIMESTAMP = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, Doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # methods of a class will be included in the documentation. # The default value is: NO. EXTRACT_PRIV_VIRTUAL = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = YES # If this flag is set to YES, the name of an unnamed parameter in a declaration # will be determined by the corresponding definition. By default unnamed # parameters remain unnamed in the output. # The default value is: YES. RESOLVE_UNNAMED_PARAMS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # will also hide undocumented C++ concepts if enabled. This option has no effect # if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_UNDOC_NAMESPACES tag is set to YES, Doxygen will hide all # undocumented namespaces that are normally visible in the namespace hierarchy. # If set to NO, these namespaces will be included in the various overviews. This # option has no effect if EXTRACT_ALL is enabled. # The default value is: YES. HIDE_UNDOC_NAMESPACES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # With the correct setting of option CASE_SENSE_NAMES Doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that # are not case sensitive the option should be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and macOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. # Possible values are: SYSTEM, NO and YES. # The default value is: SYSTEM. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then Doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then Doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_HEADERFILE tag is set to YES then the documentation for a class # will show which file needs to be included to use the class. # The default value is: YES. SHOW_HEADERFILE = YES # If the SHOW_INCLUDE_FILES tag is set to YES then Doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = NO # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then Doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then Doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then Doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = YES # If the SORT_GROUP_NAMES tag is set to YES then Doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and Doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING Doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = C_API # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # Doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by Doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by Doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents Doxygen's defaults, run Doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. See also section "Changing the # layout of pages" for information. # # Note that if you run Doxygen from a directory containing a file called # DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = # The EXTERNAL_TOOL_PATH tag can be used to extend the search path (PATH # environment variable) so that external tools such as latex and gs can be # found. # Note: Directories specified with EXTERNAL_TOOL_PATH are added in front of the # path already specified by the PATH variable, and are added in the order # specified. # Note: This option is particularly useful for macOS version 14 (Sonoma) and # higher, when running Doxygen from Doxywizard, because in this case any user- # defined changes to the PATH are ignored. A typical example on macOS is to set # EXTERNAL_TOOL_PATH = /Library/TeX/texbin /usr/local/bin # together with the standard path, the full search path used by doxygen when # launching external tools will then become # PATH=/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin EXTERNAL_TOOL_PATH = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by Doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by Doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then Doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, Doxygen will generate warnings for # potential errors in the documentation, such as documenting some parameters in # a documented function twice, or documenting parameters that don't exist or # using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # If WARN_IF_INCOMPLETE_DOC is set to YES, Doxygen will warn about incomplete # function parameter documentation. If set to NO, Doxygen will accept that some # parameters have no documentation without warning. # The default value is: YES. WARN_IF_INCOMPLETE_DOC = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, Doxygen will only warn about wrong parameter # documentation, but not about the absence of documentation. If EXTRACT_ALL is # set to YES then this flag will automatically be disabled. See also # WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = NO # If WARN_IF_UNDOC_ENUM_VAL option is set to YES, Doxygen will warn about # undocumented enumeration values. If set to NO, Doxygen will accept # undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: NO. WARN_IF_UNDOC_ENUM_VAL = NO # If WARN_LAYOUT_FILE option is set to YES, Doxygen will warn about issues found # while parsing the user defined layout file, such as missing or wrong elements. # See also LAYOUT_FILE for details. If set to NO, problems with the layout file # will be suppressed. # The default value is: YES. WARN_LAYOUT_FILE = YES # If the WARN_AS_ERROR tag is set to YES then Doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then Doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the Doxygen process Doxygen will return with a non-zero status. # If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then Doxygen behaves # like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined Doxygen will not # write the warning messages in between other messages but write them at the end # of a run, in case a WARN_LOGFILE is defined the warning messages will be # besides being in the defined file also be shown at the end of a run, unless # the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case # the behavior will remain as with the setting FAIL_ON_WARNINGS. # Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. WARN_AS_ERROR = FAIL_ON_WARNINGS # The WARN_FORMAT tag determines the format of the warning messages that Doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # In the $text part of the WARN_FORMAT command it is possible that a reference # to a more specific place is given. To make it easier to jump to this place # (outside of Doxygen) the user can define a custom "cut" / "paste" string. # Example: # WARN_LINE_FORMAT = "'vi $file +$line'" # See also: WARN_FORMAT # The default value is: at line $line of file $file. WARN_LINE_FORMAT = "at line $line of file $file" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). In case the file specified cannot be opened for writing the # warning and error messages are written to standard error. When as file - is # specified the warning and error messages are written to standard output # (stdout). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = ../../src/c99 \ ../../include \ .. \ . # This tag can be used to specify the character encoding of the source files # that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. # See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # This tag can be used to specify the character encoding of the source files # that Doxygen parses. The INPUT_FILE_ENCODING tag can be used to specify # character encoding on a per file pattern basis. Doxygen will compare the file # name with each pattern and apply the encoding instead of the default # INPUT_ENCODING if there is a match. The character encodings are a list of the # form: pattern=encoding (like *.php=ISO-8859-1). # See also: INPUT_ENCODING for further information on supported encodings. INPUT_FILE_ENCODING = # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by Doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, # *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, # *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, # *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be # provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.idl \ *.ddl \ *.odl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.cs \ *.d \ *.php \ *.php4 \ *.php5 \ *.phtml \ *.inc \ *.m \ *.markdown \ *.mm \ *.dox \ *.doc \ *.txt \ *.py \ *.pyw \ *.f90 \ *.f95 \ *.f03 \ *.f08 \ *.f \ *.for \ *.tcl \ *.vhd \ *.vhdl \ *.ucf \ *.qsf \ *.ice \ *.mm \ *.mm \ *.md # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which Doxygen is # run. EXCLUDE = ../../RELEASE-HOWTO.md \ ../../README.md \ ../../CODE_OF_CONDUCT.md \ ../README-undecorated.md \ ../../include/supernovas.h \ NOVAS-legacy.md \ ../src/docedit.c # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = */test/* \ */tests/* \ */rpc/* \ */unused/* \ */old/* \ */obsolete/* \ */examples/* \ */tools/* \ */ephem/* \ */benchmark/* \ */CMakeLists.txt \ */cpp/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # ANamespace::AClass, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = resources # The INPUT_FILTER tag can be used to specify a program that Doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that Doxygen will use the data processed and written to standard output # for further processing, therefore nothing else, like debug statements or used # commands (so in case of a Windows batch file always use @echo OFF), should be # written to standard output. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by Doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by Doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the Doxygen output. USE_MDFILE_AS_MAINPAGE = ../README.md # If the IMPLICIT_DIR_DOCS tag is set to YES, any README.md file found in sub- # directories of the project's root, is used as the documentation for that sub- # directory, except when the README.md starts with a \dir, \page or \mainpage # command. If set to NO, the README.md file needs to start with an explicit \dir # command in order to be used as directory documentation. # The default value is: YES. IMPLICIT_DIR_DOCS = YES # The Fortran standard specifies that for fixed formatted Fortran code all # characters from position 72 are to be considered as comment. A common # extension is to allow longer lines before the automatic comment starts. The # setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can # be processed before the automatic comment starts. # Minimum value: 7, maximum value: 10000, default value: 72. FORTRAN_COMMENT_AFTER = 72 #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # multi-line macros, enums or list initialized variables directly into the # documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct Doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = NO # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of Doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by Doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then Doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = NO # If the CLANG_ASSISTED_PARSING tag is set to YES then Doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for # which Doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not Doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS # tag is set to YES then Doxygen will add the directory of each input to the # include path. # The default value is: YES. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by Doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the # path to the directory containing a file called compile_commands.json. This # file is the compilation database (see: # http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the # options used when the source files were built. This is equivalent to # specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. # Note: The availability of this option depends on whether or not Doxygen was # generated with the -Duse_libclang=ON option for CMake. CLANG_DATABASE_PATH = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) # that should be ignored while generating the index headers. The IGNORE_PREFIX # tag works for classes, function and member names. The entity will be placed in # the alphabetical list under the first letter of the entity name that remains # after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, Doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank Doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that Doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that Doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of Doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank Doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that Doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank Doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that Doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by Doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). # Note: Since the styling of scrollbars can currently not be overruled in # Webkit/Chromium, the styling will be left out of the default doxygen.css if # one or more extra stylesheets have been specified. So if scrollbar # customization is desired it has to be added explicitly. For an example see the # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = resources/doxygen_extra.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. # Possible values are: LIGHT always generates light mode output, DARK always # generates dark mode output, AUTO_LIGHT automatically sets the mode according # to the user preference, uses light mode if no preference is set (the default), # AUTO_DARK automatically sets the mode according to the user preference, uses # dark mode if no preference is set and TOGGLE allows a user to switch between # light and dark mode via a button. # The default value is: AUTO_LIGHT. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE = TOGGLE # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 0 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 0 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 100 # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = YES # If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be # dynamically folded and expanded in the generated HTML source code. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_CODE_FOLDING = YES # If the HTML_COPY_CLIPBOARD tag is set to YES then Doxygen will show an icon in # the top right corner of code and text fragments that allows the user to copy # its content to the clipboard. Note this only works if supported by the browser # and the web page is served via a secure context (see: # https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: # protocol. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COPY_CLIPBOARD = YES # Doxygen stores a couple of settings persistently in the browser (via e.g. # cookies). By default these settings apply to all HTML pages generated by # Doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store # the settings under a project specific key, such that the user preferences will # be stored separately. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_PROJECT_COOKIE = # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To # create a documentation set, Doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag determines the URL of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDURL = # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then Doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # on Windows. In the beginning of 2021 Microsoft took the original page, with # a.o. the download links, offline (the HTML help workshop was already many # years in maintenance mode). You can download the HTML help workshop from the # web archives at Installation executable (see: # http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo # ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by Doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # Doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # The SITEMAP_URL tag is used to specify the full URL of the place where the # generated documentation will be placed on the server by the user during the # deployment of the documentation. The generated sitemap is called sitemap.xml # and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL # is specified no sitemap is generated. For information about the sitemap # protocol see https://www.sitemaps.org # This tag requires that the tag GENERATE_HTML is set to YES. SITEMAP_URL = # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path # including file name) of Qt's qhelpgenerator. If non-empty Doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = YES # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = edu.harvard.cfa.supernovas # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine tune the look of the index (see "Fine-tuning the output"). As an # example, the default style sheet generated by Doxygen has an example that # shows how to put an image at the root of the tree instead of the PROJECT_NAME. # Since the tree basically has more details information than the tab index, you # could consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES # When GENERATE_TREEVIEW is set to YES, the PAGE_OUTLINE_PANEL option determines # if an additional navigation panel is shown at the right hand side of the # screen, displaying an outline of the contents of the main page, similar to # e.g. https://developer.android.com/reference If GENERATE_TREEVIEW is set to # NO, this option has no effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. PAGE_OUTLINE_PANEL = YES # When GENERATE_TREEVIEW is set to YES, the FULL_SIDEBAR option determines if # the side bar is limited to only the treeview area (value NO) or if it should # extend to the full height of the window (value YES). Setting this to YES gives # a layout similar to e.g. https://docs.readthedocs.io with more room for # contents, but less room for the project logo, title, and description. If # GENERATE_TREEVIEW is set to NO, this option has no effect. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. FULL_SIDEBAR = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # Doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # When the SHOW_ENUM_VALUES tag is set doxygen will show the specified # enumeration values besides the enumeration mnemonics. # The default value is: NO. SHOW_ENUM_VALUES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, Doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # If the OBFUSCATE_EMAILS tag is set to YES, Doxygen will obfuscate email # addresses. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. OBFUSCATE_EMAILS = YES # If the HTML_FORMULA_FORMAT option is set to svg, Doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. # Possible values are: png (the default) and svg (looks nicer but requires the # pdf2svg or inkscape tool). # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # Doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # With MATHJAX_VERSION it is possible to specify the MathJax version to be used. # Note that the different versions of MathJax have different requirements with # regards to the different settings, so it is possible that also other MathJax # settings have to be changed when switching between the different MathJax # versions. # Possible values are: MathJax_2 and MathJax_3. # The default value is: MathJax_2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_VERSION = MathJax_2 # When MathJax is enabled you can set the default output format to be used for # the MathJax output. For more details about the output format see MathJax # version 2 (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 # (see: # http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best # compatibility. This is the name for Mathjax version 2, for MathJax version 3 # this will be translated into chtml), NativeMML (i.e. MathML. Only supported # for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This # is the name for Mathjax version 3, for MathJax version 2 this will be # translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. The default value is: # - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 # - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # for MathJax version 2 (see # https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # For example for MathJax version 3 (see # http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): # MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled Doxygen will generate a search box for # the HTML output. The underlying search engine uses JavaScript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the JavaScript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /