pax_global_header00006660000000000000000000000064146547270150014525gustar00rootroot0000000000000052 comment=da0d756e7f3c58db92a2697cd0f44ea7a66a4320 glvis-4.3/000077500000000000000000000000001465472701500125175ustar00rootroot00000000000000glvis-4.3/.github/000077500000000000000000000000001465472701500140575ustar00rootroot00000000000000glvis-4.3/.github/workflows/000077500000000000000000000000001465472701500161145ustar00rootroot00000000000000glvis-4.3/.github/workflows/builds.yml000066400000000000000000000212601465472701500201220ustar00rootroot00000000000000# Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced # at the Lawrence Livermore National Laboratory. All Rights reserved. See files # LICENSE and NOTICE for details. LLNL-CODE-443271. # # This file is part of the GLVis visualization tool and library. For more # information and source code availability see https://glvis.org. # # GLVis is free software; you can redistribute it and/or modify it under the # terms of the BSD-3 license. We welcome feedback and contributions, see file # CONTRIBUTING.md for details. # GLVis - an OpenGL visualization server based on the MFEM library name: builds on: push: branches: - master pull_request: workflow_dispatch: env: HYPRE_ARCHIVE: v2.19.0.tar.gz HYPRE_TOP_DIR: hypre-2.19.0 METIS_ARCHIVE: metis-4.0.3.tar.gz METIS_TOP_DIR: metis-4.0.3 MFEM_TOP_DIR: mfem MFEM_BRANCH: master jobs: builds-and-tests: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] target: [dbg, opt] mpi: [seq] build-system: [cmake] include: - os: ubuntu-latest target: opt mpi: seq build-system: make - os: ubuntu-latest target: dbg mpi: par build-system: make - os: macos-latest target: opt mpi: seq build-system: make - os: macos-latest target: dbg mpi: par build-system: make name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }} runs-on: ${{ matrix.os }} steps: - name: get MPI (Linux) if: matrix.os == 'ubuntu-latest' && matrix.mpi == 'par' run: | sudo apt-get update sudo apt-get install mpich libmpich-dev export MAKE_CXX_FLAG="MPICXX=mpic++" # Keep the following section in case we need it again in the future, # see: https://github.com/mfem/mfem/pull/3385#discussion_r1058013032 # - name: Set up Homebrew # if: matrix.os == 'macos-latest' && matrix.mpi == 'par' # uses: Homebrew/actions/setup-homebrew@master - name: get MPI (MacOS) if: matrix.os == 'macos-latest' && matrix.mpi == 'par' run: | export HOMEBREW_NO_INSTALL_CLEANUP=1 brew install openmpi export MAKE_CXX_FLAG="MPICXX=mpic++" # Get Hypre through cache, or build it. # Install will only run on cache miss. - name: cache hypre if: matrix.mpi == 'par' id: hypre-cache uses: actions/cache@v4 with: path: ${{ env.HYPRE_TOP_DIR }} key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-v2.2 - name: build hypre if: steps.hypre-cache.outputs.cache-hit != 'true' && matrix.mpi == 'par' uses: mfem/github-actions/build-hypre@v2.4 with: archive: ${{ env.HYPRE_ARCHIVE }} dir: ${{ env.HYPRE_TOP_DIR }} build-system: make # Get Metis through cache, or build it. # Install will only run on cache miss. - name: cache metis if: matrix.mpi == 'par' id: metis-cache uses: actions/cache@v4 with: path: ${{ env.METIS_TOP_DIR }} key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2 - name: build metis if: steps.metis-cache.outputs.cache-hit != 'true' && matrix.mpi == 'par' uses: mfem/github-actions/build-metis@v2.4 with: archive: ${{ env.METIS_ARCHIVE }} dir: ${{ env.METIS_TOP_DIR }} # make generic links to libraries for MFEM install # Those links are already created by build-mfem action, but not when the cache is used... - name: configure links if: matrix.mpi == 'par' run: | echo "Hypre symlink:" ln -s $HYPRE_TOP_DIR hypre; echo "Metis symlink:" ln -s $METIS_TOP_DIR metis-4.0; - name: MFEM ${{ env.MFEM_BRANCH }} commit run: | echo "MFEM_COMMIT=$(git ls-remote --heads https://github.com/mfem/mfem.git ${MFEM_BRANCH} | awk '{print $1;}')" >> $GITHUB_ENV # Get MFEM through cache, or build it. # Install will only run on cache miss. - name: cache mfem id: cache-mfem uses: actions/cache@v4 with: path: ${{ env.MFEM_TOP_DIR }} key: ${{ runner.os }}-build-${{ env.MFEM_TOP_DIR }}-${{ env.MFEM_COMMIT }}-${{ matrix.target }}-${{ matrix.build-system}}-v2.4 # We are using the defaults of the MFEM action here, which is to use master # branch. There is an implicit assumption here that mfem master hasn't # changed since the 'MFEM master commit' step. # Also, if we apply to MFEM build the same target as GLVis. This may be # superfluous. - name: build mfem if: steps.cache-mfem.outputs.cache-hit != 'true' uses: mfem/github-actions/build-mfem@v2.4 with: os: ${{ matrix.os }} target: ${{ matrix.target }} hypre-dir: ${{ env.HYPRE_TOP_DIR }} metis-dir: ${{ env.METIS_TOP_DIR }} mfem-dir: ${{ env.MFEM_TOP_DIR }} mfem-branch: ${{ env.MFEM_BRANCH }} build-system: ${{ matrix.build-system }} mpi: ${{ matrix.mpi }} library-only: true # Install GLVis dependencies with package manager - name: get deps (Linux) if: matrix.os == 'ubuntu-latest' run: | # We need to add a PPA for SDL 2.0.14 - fixes some initialization # errors for X11 sudo add-apt-repository -y ppa:savoury1/multimedia sudo apt-get update sudo apt-get install libfontconfig1-dev libfreetype6-dev libsdl2-dev libglew-dev libglm-dev libpng-dev # - name: Set up Homebrew # if: matrix.os == 'macos-latest' # uses: Homebrew/actions/setup-homebrew@master - name: get deps (MacOS) if: matrix.os == 'macos-latest' run: | export HOMEBREW_NO_INSTALL_CLEANUP=1 brew install fontconfig freetype sdl2 glew glm libpng - name: cache deps (Windows) id: cache-deps uses: actions/cache@v4 with: path: vcpkg_cache key: ${{ runner.os }}-vcpkg-v1 - name: prepare binary cache location if: steps.cache-deps.outputs.cache-hit != 'true' run: | mkdir -p vcpkg_cache - name: checkout GLVis uses: actions/checkout@v4 with: path: glvis submodules: recursive - name: build GLVis (make) if: matrix.build-system == 'make' run: | glvis_target="opt" [[ ${{ matrix.target }} == "dbg" ]] && glvis_target="debug"; cd glvis && make ${glvis_target} -j3 - name: build GLVis (cmake) if: matrix.build-system == 'cmake' env: VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache run: | build_type="Release" [[ ${{ matrix.target }} == "dbg" ]] && build_type="Debug"; [[ ${{ matrix.os }} == "windows-latest" ]] \ && toolchain_file="${VCPKG_INSTALLATION_ROOT}\\scripts\\buildsystems\\vcpkg.cmake" cd glvis && mkdir build && cd build cmake \ -D CMAKE_TOOLCHAIN_FILE:STRING=${toolchain_file} \ -D CMAKE_BUILD_TYPE:STRING=${build_type} \ -D ENABLE_TESTS:BOOL=TRUE \ -D mfem_DIR:PATH=${GITHUB_WORKSPACE}/${MFEM_TOP_DIR}/build \ -D GLVIS_BASELINE_SYS=${{ matrix.os }} \ .. cmake --build . --parallel 3 --config "${build_type}" shell: bash - name: setup Python if: matrix.build-system == 'cmake' uses: actions/setup-python@v5 with: python-version: 3.9 - name: setup Python packages for testing if: matrix.build-system == 'cmake' run: | python -m pip install --upgrade pip pip install scikit-image - name: setup Linux testing dependencies if: matrix.build-system == 'cmake' && matrix.os == 'ubuntu-latest' run: | sudo apt-get install xvfb - name: test GLVis (cmake/linux) if: matrix.build-system == 'cmake' && matrix.os == 'ubuntu-latest' run: | cd glvis && cd build xvfb-run -a ctest --verbose tar czvf test_screenshots.tar.gz tests/test.*.png - name: test GLVis (cmake/mac) if: matrix.build-system == 'cmake' && matrix.os == 'macos-latest' run: | cd glvis && cd build ctest --verbose - name: create screenshot tarball if: always() && matrix.build-system == 'cmake' && matrix.os != 'windows-latest' run: | cd glvis && cd build tar czvf test_screenshots.tar.gz tests/test.*.png - name: upload test screenshots if: always() && matrix.build-system == 'cmake' && matrix.os != 'windows-latest' uses: actions/upload-artifact@v4 with: name: test-screenshots-${{ matrix.os }}-${{ matrix.target }}-${{ matrix.mpi }} path: glvis/build/test_screenshots.tar.gz glvis-4.3/.github/workflows/release.yml000066400000000000000000000177241465472701500202720ustar00rootroot00000000000000# Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced # at the Lawrence Livermore National Laboratory. All Rights reserved. See files # LICENSE and NOTICE for details. LLNL-CODE-443271. # # This file is part of the GLVis visualization tool and library. For more # information and source code availability see https://glvis.org. # # GLVis is free software; you can redistribute it and/or modify it under the # terms of the BSD-3 license. We welcome feedback and contributions, see file # CONTRIBUTING.md for details. # GLVis - an OpenGL visualization server based on the MFEM library name: release on: push: tags: - v* branches: - master workflow_dispatch: env: HYPRE_ARCHIVE: v2.19.0.tar.gz HYPRE_TOP_DIR: hypre-2.19.0 METIS_ARCHIVE: metis-4.0.3.tar.gz METIS_TOP_DIR: metis-4.0.3 MFEM_TOP_DIR: mfem MFEM_BRANCH: master jobs: release-builds: strategy: matrix: os: [macos-latest, windows-latest] target: [opt] mpi: [seq] build-system: [cmake] name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }} runs-on: ${{ matrix.os }} steps: - name: get MPI (Linux) if: matrix.os == 'ubuntu-latest' && matrix.mpi == 'par' run: | sudo apt-get update sudo apt-get install mpich libmpich-dev export MAKE_CXX_FLAG="MPICXX=mpic++" # Keep the following section in case we need it again in the future, # see: https://github.com/mfem/mfem/pull/3385#discussion_r1058013032 # - name: Set up Homebrew # if: matrix.os == 'macos-latest' && matrix.mpi == 'par' # uses: Homebrew/actions/setup-homebrew@master - name: get MPI (MacOS) if: matrix.os == 'macos-latest' && matrix.mpi == 'par' run: | export HOMEBREW_NO_INSTALL_CLEANUP=1 brew install openmpi export MAKE_CXX_FLAG="MPICXX=mpic++" # Get Hypre through cache, or build it. # Install will only run on cache miss. - name: cache hypre if: matrix.mpi == 'par' id: hypre-cache uses: actions/cache@v4 with: path: ${{ env.HYPRE_TOP_DIR }} key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-v2.2 - name: build hypre if: steps.hypre-cache.outputs.cache-hit != 'true' && matrix.mpi == 'par' uses: mfem/github-actions/build-hypre@v2.4 with: archive: ${{ env.HYPRE_ARCHIVE }} dir: ${{ env.HYPRE_TOP_DIR }} build-system: make # Get Metis through cache, or build it. # Install will only run on cache miss. - name: cache metis if: matrix.mpi == 'par' id: metis-cache uses: actions/cache@v4 with: path: ${{ env.METIS_TOP_DIR }} key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2 - name: build metis if: steps.metis-cache.outputs.cache-hit != 'true' && matrix.mpi == 'par' uses: mfem/github-actions/build-metis@v2.4 with: archive: ${{ env.METIS_ARCHIVE }} dir: ${{ env.METIS_TOP_DIR }} # make generic links to libraries for MFEM install # Those links are already created by build-mfem action, but not when the cache is used... - name: configure links if: matrix.mpi == 'par' run: | echo "Hypre symlink:" ln -s $HYPRE_TOP_DIR hypre; echo "Metis symlink:" ln -s $METIS_TOP_DIR metis-4.0; - name: MFEM ${{ env.MFEM_BRANCH }} commit run: | echo "MFEM_COMMIT=$(git ls-remote --heads https://github.com/mfem/mfem.git ${MFEM_BRANCH} | awk '{print $1;}')" >> $GITHUB_ENV # Get MFEM through cache, or build it. # Install will only run on cache miss. - name: cache mfem id: cache-mfem uses: actions/cache@v4 with: path: ${{ env.MFEM_TOP_DIR }} key: ${{ runner.os }}-build-${{ env.MFEM_TOP_DIR }}-${{ env.MFEM_COMMIT }}-${{ matrix.target }}-${{ matrix.build-system}}-v2.2 # We are using the defaults of the MFEM action here, which is to use master # branch. There is an implicit assumption here that mfem master hasn't # changed since the 'MFEM master commit' step. # Also, if we apply to MFEM build the same target as GLVis. This may be # superfluous. - name: build mfem if: steps.cache-mfem.outputs.cache-hit != 'true' uses: mfem/github-actions/build-mfem@v2.4 with: os: ${{ matrix.os }} target: ${{ matrix.target }} hypre-dir: ${{ env.HYPRE_TOP_DIR }} metis-dir: ${{ env.METIS_TOP_DIR }} mfem-dir: ${{ env.MFEM_TOP_DIR }} mfem-branch: ${{ env.MFEM_BRANCH }} build-system: ${{ matrix.build-system }} mpi: ${{ matrix.mpi }} # Install GLVis dependencies with package manager - name: get deps (Linux) if: matrix.os == 'ubuntu-latest' run: | # We need to add a PPA for SDL 2.0.14 - fixes some initialization # errors for X11 sudo add-apt-repository -y ppa:savoury1/multimedia sudo apt-get update sudo apt-get install libfontconfig1-dev libfreetype6-dev libsdl2-dev libglew-dev libglm-dev libpng-dev # - name: Set up Homebrew # if: matrix.os == 'macos-latest' # uses: Homebrew/actions/setup-homebrew@master - name: get deps (MacOS) if: matrix.os == 'macos-latest' run: | export HOMEBREW_NO_INSTALL_CLEANUP=1 brew install fontconfig freetype sdl2 glew glm libpng - name: cache deps (Windows) id: cache-deps uses: actions/cache@v4 with: path: vcpkg_cache key: ${{ runner.os }}-vcpkg-v1 - name: prepare binary cache location if: steps.cache-deps.outputs.cache-hit != 'true' run: | mkdir -p vcpkg_cache - name: checkout GLVis uses: actions/checkout@v4 with: path: glvis submodules: recursive - name: build GLVis (cmake) if: matrix.build-system == 'cmake' env: VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache run: | build_type="Release" [[ ${{ matrix.os }} == "windows-latest" ]] \ && toolchain_file="${VCPKG_INSTALLATION_ROOT}\\scripts\\buildsystems\\vcpkg.cmake" cd glvis && mkdir build && cd build cmake \ -D CMAKE_TOOLCHAIN_FILE:STRING=${toolchain_file} \ -D CMAKE_BUILD_TYPE:STRING=${build_type} \ -D ENABLE_TESTS:BOOL=TRUE \ -D mfem_DIR:PATH=${GITHUB_WORKSPACE}/${MFEM_TOP_DIR}/build \ -D GLVIS_BASELINE_SYS=${{ matrix.os }} \ -D CMAKE_INSTALL_PREFIX=../install-${{ matrix.os }} \ .. cmake --build . --parallel 3 --config "${build_type}" shell: bash - name: package binary (Windows) if: matrix.os == 'windows-latest' env: GLVIS_EXPORT_NAME: glvis-${{ github.ref_name }}-${{ runner.os }}-amd64 run: | cd glvis/build Copy-Item -Path "Release" -Destination "${Env:GLVIS_EXPORT_NAME}" -Recurse - name: package binary (Mac) if: matrix.os == 'macos-latest' env: GLVIS_EXPORT_NAME: glvis-${{ github.ref_name }}-${{ runner.os }}-amd64 run: | cd glvis/build make app # Creates the actual relocatable bundle (copying system libraries) sudo make install # Fix permissions from running `make install` as root cd ../install-${{ matrix.os }} sudo chown -R ${USER} GLVis.app # Go back to build directory cd ../build # Copy executable to a temporary directory mkdir dmg_tmp cp -a ../install-${{ matrix.os }}/GLVis.app dmg_tmp/GLVis.app # Create DMG since actions/upload-artifact will clobber Unix permissions hdiutil create -volname "GLVis macOS x86_64" -srcfolder dmg_tmp -ov -format UDZO GLVis.dmg mkdir ${GLVIS_EXPORT_NAME} cp GLVis.dmg ${GLVIS_EXPORT_NAME} - name: upload binary uses: actions/upload-artifact@v4 with: name: glvis-${{ github.ref_name }}-${{ runner.os }}-amd64 path: glvis/build/glvis-${{ github.ref_name }}-${{ runner.os }}-amd64 glvis-4.3/.gitignore000066400000000000000000000005521465472701500145110ustar00rootroot00000000000000# Build artifacts *.o *.bc lib/libglvis.js lib/libglvis.a share/logo.rgba.bin.cpp glvis GLVis.app # Output from running glvis GLVis.pdf GLVis_s*.png GLVis_m*.png glvis-saved.* # CMake-specific exclusions CMakeCache.txt CMakeFiles CMakeScripts Testing Makefile cmake_install.cmake install_manifest.txt compile_commands.json # OS-specific: Mac *.dSYM .DS_Store glvis-4.3/.gitmodules000066400000000000000000000001251465472701500146720ustar00rootroot00000000000000[submodule "tests/data"] path = tests/data url = https://github.com/GLVis/data.git glvis-4.3/CHANGELOG000066400000000000000000000441331465472701500137360ustar00rootroot00000000000000 GLVis visualization tool _/_/_/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/_/ _/ _/_/ _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/_/ _/_/_/ _/_/_/_/ _/ _/ _/_/_/ https://glvis.org Version 4.3 released on Aug 7, 2024 =================================== - Added visualization of quadrature data (QuadratureFunction in MFEM). Both loading from file, with the new command line argument '-q', or from a socket stream, with the keyword 'quadrature', are supported. Three visualization options are provided: piece-wise constants on a refined mesh (LOR), L2 field with DOFs collocated (interpolation), or projection to discontinuous elements (L2 projection). Use 'Q' to switch between them. High-order quadrature data is supported only for tensor finite elements with the first two options. With the first option, only the mesh lines of the original mesh are visualized. This feature is also supported for the element-wise cutting plane in 3D (cplane=2). - The GLVis auto refinement algorithm now takes into account the order of the data (mesh and grid function). The new refinement is chosen to be sufficient for resolving the curvature of the data, but only if we can do that with less than 2M vertices and 16 refinements. Otherwise, we print a warning and the user may still need to press 'o' to fully resolve the data. For more details, see the section Auto-refinement in README.md. - Added option to specify the floating point number formatting in GLVis axes and colorbar. Use 'Alt+a' for the axes and 'Alt+c' for the colorbar. Formatting can also be specified in socket stream or glvis script with axis_numberformat or colorbar_numberformat, followed by a C-like formatting string, for example "colorbar_numberformat '%+06.1f'". - Added a building option for setting the default font size. - Added support for scalar integral finite elements, where calculation of the surface normals was not implemented and was crashing GLVis. The normals are approximately calculated from the point-wise projected value-based elements. - Added two new modes for visualization of vector fields in 2D, placing the arrows above the plotted surface and using a single color. - Added support to visualize solutions on 1D elements embedded in 2D and 3D. - Significantly improved memory usage. - Various other bugfixes and improvements. Version 4.2 released on May 23, 2022 ==================================== - Added 3D scene export to glTF format (https://www.khronos.org/gltf) which is bound to the key 'G'. This can be used to import GLVis scenes for rendering in Blender, as well as for augmented reality, see https://modelviewer.dev/editor. - Added the option to cut a portion of the interiors of 3D faces to expose more of the mesh. Useful as an alternative to transparency. See keys Ctrl+F3/F4. - Added a third mode to keys 'b'/'B' in 2D to display the mesh boundary colored by boundary element attribute. - Support for visualization of pyramid-shaped elements. - An edge numbering option is now available in 2D. - In 2D, save and restore solution's value range when using keys 'e' and 'b'. - Mac and Windows binaries are now automatically built with GitHub actions CI. - The command-line option -mac was renamed to -save. - Various other bugfixes and improvements. Version 4.1, released on Aug 31, 2021 ===================================== - Use threads in server mode for window creation and session management instead of fork(). This resolves issues with the GLVis server mode on macOS. It also allows for closing all open GLVis server windows by Ctrl-C in the terminal. - Preliminary support for interactive inline GLVis plots in Python Jupyter Notebooks with https://github.com/glvis/pyglvis and C++ Jupyter Notebooks with https://github.com/glvis/xeus-glvis. - Added support for native builds on Windows with CMake. - Added support for native Mac application bundle with "make app". The resulting app can be double-clicked, added to the Dock, etc. - Added screenshots support to the JavaScript/web version (key 'S'). - Enabled support for WebGL 2, when available. This enables, among other features, support for controllable multisampling via framebuffers. - Refactored rendering components, including palette and shader handling. - Replaced pthreads and POSIX-specific code with C++11 standard thread library. - Added a new regression test suite based on generated screenshots of stream files. See the README in the tests/ directory for more details. Note that this requires a git submodule for the baseline images, which are located in the separate https://github.com/glvis/data repository. - Various bugfixes and improvements related to the JavaScript version, vertex numbering, script handling, screenshots, HiDPI support, and more. Version 4.0, released on Dec 11, 2020 ===================================== Starting with this version, the GLVis open source license is changed to BSD-3. Unlike previous GLVis releases, this version requires a C++11 compiler. - Major overhaul and modernization of the GLVis rendering and window management, replacing X Windows with SDL for platform-native window and event handling. This enables OpenGL 3+ support and HiDPI support on Mac OS X. - Two rendering backends are included: one for legacy OpenGL contexts without support for shaders, and one with full support for modern OpenGL 3 features. The modern OpenGL context is preferred by default; a new command-line argument "-oldgl" can be used to request the legacy backend. - Preliminary support for building GLVis to JavaScript/WebAssembly using Emscripten, see https://github.com/GLVis/glvis-js. - Documented project workflow and provided contribution guidelines in the new top-level file, CONTRIBUTING.md. - Added several perceptually uniform colormaps "turbo", "viridis", "plasma", "fusion", "iceburn", "viola", "pride" and "ocean" from * Google AI: https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html * Matplotlib: https://bids.github.io/colormap/ * CMasher: https://github.com/1313e/CMasher - Added support for visualization of the element ordering curve with 'Ctrl+o'. - Keystroke changes: cutting plane in 2D is now toggled with 'i' instead of 'w', and 2D element subdivision is controlled with 'o/O' instead of 'i/I'. These are the same as the corresponding keystrokes in 3D. - Improved the 3D cutting plane algorithm for curved elements. The key 'I' can be used to switch to the previous (faster) algorithm which is suitable for meshes with planar faces. - Updated to support the display and slicing of meshes with wedge elements. - Improved the opening of parallel meshes/solutions. - Transparency and printing in textured coloring modes is now supported, and no-texture coloring has been removed as a result. - FreeType is now a required dependency and text on screen is rendered using a texture atlas. - Replaced the "deep sea" palette with "ocean". Added new palette: gray. - Added the ability to discretize a palette, i.e. to use just a prescribed number of its colors, see the new "number of colors" input of the F6 key. - Added new script and socket command: "palette_repeat" which can be used to repeat and reverse/flip the palette - controls the same parameter as the first prompt after pressing the F6 key in the GLVis window. - Added a key for setting the bounding box from the terminal (Shift+F7). Version 3.4, released on May 29, 2018 ===================================== - When enabled, secure sockets (based on GnuTLS) now use authentication based on X.509 certificates. A new set of X.509 client/server keys can be generated with the updated version of the script 'glvis-keygen.sh'. - Added capability to show element and vertex numbering in 2D (key 'n'). - Added support for reading mesh and solution from the same file. - Added a CMake build system. - Added 10 new color palettes which can now be switched both forwards and backwards with the 'p' and 'P' keys respectively. - Allow multi-screen window managers to redraw on current screen. - Printing to PDF is now done with 'Ctrl+p' (replacing 'P'). - Default multisampling linewidth for Macs is now 0.01 (seems to work better). On other platforms the default remains 1.4. Version 3.3, released on Jan 28, 2017 ===================================== - Added the ability to change the axis labels displayed with the coordinate cross in the lower left corner. They can be set with the new 'axis_labels' socket command, for example: sol_sock << "axis_labels 'u' 'v' 'w'\n"; - With the corresponding version of MFEM, GLVis now supports gz-compressed files and socket streams. Version 3.2, released on Jun 30, 2016 ===================================== - Added support for secure socket connections based on the GnuTLS library through MFEM. This option may be useful in multi-user environment to prevent users from sending/receiving visualization data to/from other users. See INSTALL for setup instructions. - Added an optional caption at the top of the GLVis window. This can be set in several different ways: through a command-line parameter (-c|--plot-caption), a socket command (plot_caption), a GLVis script command (plot_caption) or the 'C' keystroke. The caption is displayed as one of the states of the colorbar (key 'c') which now has 3 modes: no colorbar & no caption; colorbar & caption; colorbar & no caption. With empty caption, 'c' works the same as before. For vector fields, the current vector-to-scalar function is added to the caption in parenthesis. Similarly, for 2D scalar fields, the "surface elements mode" (attached to the 'e' key) is added to the caption. - Improved the handling of the "keys" command in GLVis scripts and socket connections. - Added "scale" and "translate" script commands. Version 3.1, released on Feb 5, 2016 ==================================== - Moved GLVis from Google Code to GitHub. New website: http://glvis.org. - Formatted the code with Artistic Style, see the "make style" target. - Added 'help', 'distclean', 'install' and 'status'/'info' targets to the GLVis makefile. The default install directory is ./bin. That can be overwritten with "make install PREFIX=". - With the corresponding version of MFEM, GLVis now supports the visualization of non-conforming meshes and grid functions. - Added support for visualizing vector fields on surface meshes, and for element shrinking (F3/F4) of surface meshes. - The 'P' key now prints in PDF instead of EPS format. The output still has some deficiencies, so 'P' is recommended only if vector format is necessary. For quick screenshots (e.g. for a talk), the 'S' key is preferable. - Added a command-line option (-d | --pad-digits), to set the number of digits used for processor ranks in file names. - Added a command-line option (-grt | -geom_ref_type) to refine the geometry using the Gauss-Lobatto instead of uniform points. - In 2D, added keys that in addition to 'b', can cycle through the boundary attributes: shift+f9 (forward) and shift-f10 (backward); added visualization of element attributes as another state of the 'e' key. - New socket command, window_geometry, can be used to arrange the visualization window on the screen - Various other small fixes and styling updates. Version 3.0, released on Jan 26, 2015 ===================================== - Updated the makefile to use the new build system in MFEM, so GLVis can now be built from any (serial or parallel) MFEM build. - Support for saving screenshots directly in png format using libpng. Enabled by default with "USE_LIBPNG = YES" in the makefile. - Support for antialiased fonts using the freetype library. Enabled by default with "USE_FREETYPE = YES" in the makefile (the options "FT_OPTS_YES" and "FT_LIBS_YES" may need to be adjusted). The font is determined at runtime from a list of fontconfig patterns: fc_font_patterns in lib/aux_vis.cpp. It can also be specified on the command line, e.g. "-fn Ubuntu-15". - Improved level surfaces to support hexahedral elements and to better represent high-order grid-functions and curved meshes using element subdivision. - Added support for 1D meshes + solutions, visualized in 2D via extrusion in y-direction. The z-axis is scaled relative to the x-axis. - Added support for surface meshes (2D meshes in 3 space dimensions). - Added new (input stream) command, "autopause " that will stop (when turned on) the interpretation of the input stream after every mesh + solution update. Autopause can also be toggled using the "Control+Space" key. - When visualizing a GridFunction from a socket, script, or the command line GLVis will now enable the subdivision mode ("f" key) and select subdivision factor (using the new AutoRefine method) depending on the number of elements (2D) or number of boundary elements (3D) in the mesh. - Additional stream command support. Most of the script commands are supported including taking screenshots. - New camera manipulation using Ctrl, the middle mouse button, and optionally Shift and Alt. - Significantly improved logarithmic scaling mode (key "L"). - Improved visualization of smoothed (antialiased) lines without multisampling. - Switched to MFEM's OptionParser class for command line arguments parsing. - Various small fixes and styling updates. Version 2.0, released on Nov 18, 2011 ===================================== - Extended GLVis to allow visualization of parallel meshes and grid functions. For data saved in separate files, the format is: glvis -np <#proc> -m [-g ] The file names are obtained from the prefix by appending '.' followed by a 6-digit processor/subdomain number padded with 0's. The related (obsolete) option -par3d was removed. For results send by separate socket connections from each processor, the format just adds the prefix: "parallel <#proc> " (see the parallel MFEM examples). The corresponding GLVis script command is "psolution ", where controls if the boundary attributes should be replaced with the processor number or if they should be kept unchanged (this option is also available from the command line as '-a'). In all cases, GLVis will stitch the parallel results to show the global mesh and solution, but the subdomain data can still be examined through the F3/F4, F8, F9/F10 and F11/F12 keystrokes. - Added the ability to directly visualize 3D VectorFiniteElement-based grid functions (e.g. from a Nedelec or a Raviart-Thomas space), by an internal projection onto the discontinuous piece-wise polynomial space of the appropriate order. - Added new bounding box visualization mode (fourth state for the 'a' key) using red, green, blue colored main axes and dashed box. - Added support for dynamic mesh and solution (grid function) update over sockets based on MFEM's new socket communication classes socketserver and socketstream. Both serial and parallel codes can use this capability. - Switched to GLX 1.3 compatible mode selection and window creation. The old GLX calls are still available when GLVis is compiled with -DGLVIS_GLX10. The new functions allow for multisampling on Macs with ATI cards, though the X11 server on OS X Snow Leopard gives a warning that "GLX 1.3 is not supported", but works fine in practice. - Added functionality allowing GLVis to handle modifier+key input. As a first application, control + arrow keys can be used now to translate the view. - Improved the handling of the boundary in 2D ('b' key) for curved meshes. - The palettes can now be flipped by specifying a negative value for the number of times the palette is repeated (F6 key). - Provided workaround for a bug in the NVIDIA driver on some 64 bit systems, where glX calls after a fork() close file descriptor 0. - Various small fixes and styling updates. Version 1.2, released on Apr 8, 2011 ==================================== - If build with mfem version 1.2 (or later), glvis now supports unstructured meshes in VTK format, including quadratic curvilinear meshes. - When viewing 3D vector field, 'F' will cycle the displayed scalar function between magnitude, x-component, y-component and z-component. - Added a new command line option: '-gc' allowing visualization of a single component of a GridFunction, e.g: glvis -m mesh -g sol -gc 0. This is useful for grid functions describing tensors. - Ensured that the shrinking of elements (F3/F4) and material subdomains (F11/F12) work in 2D/3D, with scalar/vector plots and on curved meshes. The latter are useful, in particular, to visualize the subdomains corresponding to different processors in a mfem parallel run. - The palette update (key 'p') when using texture is now instantaneous. - Added a new script command: toggle_attributes. - Added a new palette: calewhite, from VisIt. - Various small fixes and styling updates. Version 1.1, released on Sep 13, 2010 ===================================== - Anti-aliasing (key 'A') now uses the OpenGL ARB_multisample extension (when available). By default, 4x multisampling is used. See file lib/tk.cpp. This value can be changed by setting GLVIS_MULTISAMPLE during compilation. - When drawing subdivided elements, the real normals are now used (at least in some cases) to smooth the appearance inside the element, i.e. the surface in 2D and the (curved) boundary in 3D. - Enabled the shrinking of elements (F3/F4) and material subdomains (F11/F12) for 3D meshes saved using Mesh::PrintWithPartitioning(). This allows for better visualization of the interior of the mesh. - Improved the hex-cutting algorithm to handle all cases of non-flat faces. - Scripts now work with scalar 3D mesh/solution. - Changed the makefile to recompile only files that have been changed and to allow 'make -j'. - Various small fixes and styling updates. Version 1.0, released on Jul 21, 2010 ===================================== - Uploaded to http://glvis.googlecode.com. - Initial release. glvis-4.3/CMakeLists.txt000066400000000000000000000265311465472701500152660ustar00rootroot00000000000000# Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced # at the Lawrence Livermore National Laboratory. All Rights reserved. See files # LICENSE and NOTICE for details. LLNL-CODE-443271. # # This file is part of the GLVis visualization tool and library. For more # information and source code availability see https://glvis.org. # # GLVis is free software; you can redistribute it and/or modify it under the # terms of the BSD-3 license. We welcome feedback and contributions, see file # CONTRIBUTING.md for details. # CMake v3.10 is where "Imported Targets" like "Freetype::Freetype" are # introduced. cmake_minimum_required(VERSION 3.10) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # Prohibit in-source builds if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR "In-source builds are prohibited.") endif ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") project(glvis NONE) # Import MFEM. The following variables can be used to help CMake find MFEM: # * MFEM_DIR - absolute path to the MFEM build or install prefix. # * mfem_DIR - absolute path to where MFEMConfig.cmake is. message(STATUS "Looking for mfem ...") set(MFEM_DIR "" CACHE PATH "Path to the MFEM build or install prefix.") if (MFEM_DIR) find_package(mfem REQUIRED NAMES MFEM HINTS "${MFEM_DIR}" "${MFEM_DIR}/lib/cmake/mfem" NO_DEFAULT_PATH) else() find_package(mfem REQUIRED NAMES MFEM) endif() message(STATUS "Found mfem config in: ${mfem_DIR} (version ${MFEM_VERSION})") # Use the same C++ compiler as MFEM. This is needed when MFEM was built using # an MPI wrapper and we do not have explicitly the MPI compile and link flags. if (NOT CMAKE_CXX_COMPILER AND MFEM_CXX_COMPILER) set(CMAKE_CXX_COMPILER "${MFEM_CXX_COMPILER}") endif() enable_language(C) enable_language(CXX) # Default options match the Makefile if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() option(GLVIS_USE_LIBTIFF "Use libtiff for taking screenshots internally" OFF) option(GLVIS_USE_LIBPNG "Use libpng for taking screenshots internally" ON) # # Handle a few other definitions # # Default multisampling mode if (NOT GLVIS_MULTISAMPLE) set(GLVIS_MULTISAMPLE 4) endif (NOT GLVIS_MULTISAMPLE) # Default multisampling line-width if (NOT GLVIS_MS_LINEWIDTH) if (NOT APPLE) set(GLVIS_MS_LINEWIDTH 1.4) else() # This value seems to work better on Macs set(GLVIS_MS_LINEWIDTH 1.0) endif() endif (NOT GLVIS_MS_LINEWIDTH) # Default font size if (NOT GLVIS_FONT_SIZE) set(GLVIS_FONT_SIZE 12) endif (NOT GLVIS_FONT_SIZE) # # Start finding everything # set(_glvis_compile_defs) set(_glvis_compile_opts) set(_glvis_include_dirs) set(_glvis_libraries) list(APPEND _glvis_compile_defs "GLVIS_MULTISAMPLE=${GLVIS_MULTISAMPLE}") list(APPEND _glvis_compile_defs "GLVIS_MS_LINEWIDTH=${GLVIS_MS_LINEWIDTH}") list(APPEND _glvis_compile_defs "GLVIS_FONT_SIZE=${GLVIS_FONT_SIZE}") if (NOT WIN32) list(APPEND _glvis_compile_defs "GLVIS_USE_LOGO") else() list(APPEND _glvis_compile_defs "_USE_MATH_DEFINES") endif() if(NOT WIN32) find_program(XXD_FOUND xxd) if(NOT XXD_FOUND) message(FATAL_ERROR "Required tool not found: xxd.") endif() endif() if (CMAKE_BUILD_TYPE MATCHES "Debug|debug|DEBUG") list(APPEND _glvis_compile_defs "GLVIS_DEBUG") list(APPEND _glvis_compile_opts "-Wall") endif() # Include paths and libraries needed by MFEM set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MFEM_CXX_FLAGS}") list(APPEND _glvis_include_dirs "${MFEM_INCLUDE_DIRS}") list(APPEND _glvis_libraries "${MFEM_LIBRARIES}") if (NOT EMSCRIPTEN) # Find OpenGL find_package(OpenGL REQUIRED) list(APPEND _glvis_libraries OpenGL::GL) # Find 'SDL2' which is not part of the CMake standard modules list(APPEND SDL2_DIR "../SDL2") set(SDL2_DIR_SAVE ${SDL2_DIR}) find_package(SDL2 QUIET HINTS ${SDL2_DIR}) # The SDL2 target 'SDL2::SDL2' is not always defined, so instead we use # directly 'SDL2_INCLUDE_DIRS' and 'SDL2_LIBRARIES'. if (TARGET SDL2::SDL2) list(APPEND _glvis_libraries SDL2::SDL2) elseif (SDL2_INCLUDE_DIRS AND SDL2_LIBRARIES) # SDL2_INCLUDE_DIRS is defined with 'SDL2' at the end of the path we need to # strip that. set(new_list_) foreach (path IN LISTS SDL2_INCLUDE_DIRS) string(REGEX REPLACE "/include/SDL2$" "/include" new_path_ "${path}") list(APPEND new_list_ "${new_path_}") endforeach() set(SDL2_INCLUDE_DIRS ${new_list_}) list(APPEND _glvis_include_dirs "${SDL2_INCLUDE_DIRS}") list(APPEND _glvis_libraries "${SDL2_LIBRARIES}") else() # find_package() did not work; try more direct approach. set(SDL2_DIR ${SDL2_DIR_SAVE}) find_path(SDL2_INCLUDE_DIRS "SDL2/SDL.h" HINTS ${SDL2_DIR} ENV SDL2_DIR PATH_SUFFIXES "include" DOC "SDL2 include path.") find_library(SDL2_LIBRARIES "SDL2" HINTS ${SDL2_DIR} ENV SDL2_DIR PATH_SUFFIXES "lib" DOC "SDL2 library.") if (NOT (SDL2_INCLUDE_DIRS AND SDL2_LIBRARIES)) message(FATAL_ERROR "SDL2 library not found. Please set SDL2_DIR.") endif() list(APPEND _glvis_include_dirs "${SDL2_INCLUDE_DIRS}") list(APPEND _glvis_libraries "${SDL2_LIBRARIES}") endif() message(STATUS "SDL2 found: ${SDL2_LIBRARIES}") message(STATUS "SDL2_INCLUDE_DIRS = ${SDL2_INCLUDE_DIRS}") # Find GLEW # GLEW search path can be set using CMAKE_PREFIX_PATH list(APPEND CMAKE_PREFIX_PATH "../glew") find_package(GLEW REQUIRED) list(APPEND _glvis_libraries GLEW::GLEW) # Find 'glm' which is not part of the CMake standard modules list(APPEND GLM_DIR "../glm") find_package(glm QUIET HINTS ${GLM_DIR}) if (NOT GLM_INCLUDE_DIRS) find_path(GLM_INCLUDE_DIRS "glm/glm.hpp" HINTS ${GLM_DIR} ENV GLM_DIR PATH_SUFFIXES "include" DOC "GLM include path.") if (NOT GLM_INCLUDE_DIRS) message(FATAL_ERROR "GLM headers not found. Please set GLM_DIR.") endif() endif() message(STATUS "GLM headers found: ${GLM_INCLUDE_DIRS}") list(APPEND _glvis_include_dirs "${GLM_INCLUDE_DIRS}") # Find TIFF if (GLVIS_USE_LIBTIFF) find_package(TIFF) if (TIFF_FOUND) list(APPEND _glvis_compile_defs "GLVIS_USE_LIBTIFF") list(APPEND _glvis_libraries TIFF::TIFF) else() message(WARNING "TIFF library not found. TIFF disabled.") set(GLVIS_USE_LIBTIFF OFF) endif (TIFF_FOUND) endif (GLVIS_USE_LIBTIFF) # Find PNG if (GLVIS_USE_LIBPNG) find_package(PNG) if (PNG_FOUND) list(APPEND _glvis_compile_defs "GLVIS_USE_LIBPNG") list(APPEND _glvis_libraries PNG::PNG) else() message(WARNING "PNG library not found. PNG disabled.") set(GLVIS_USE_LIBPNG OFF) endif (PNG_FOUND) endif (GLVIS_USE_LIBPNG) # Find FreeType. find_package(Freetype REQUIRED) # Find FontConfig (FindFontconfig.cmake was added in CMake 3.14) find_library(FONTCONFIG_LIBRARY fontconfig HINTS ${FONTCONFIG_DIR} $ENV{FONTCONFIG_DIR} DOC "The fontconfig library for use with FreeType." NO_DEFAULT_PATH) find_library(FONTCONFIG_LIBRARY fontconfig) if (FONTCONFIG_LIBRARY) list(APPEND _glvis_libraries Freetype::Freetype) # Need FONTCONFIG_INCLUDE_DIRS? list(APPEND _glvis_libraries "${FONTCONFIG_LIBRARY}") message(STATUS "Found Fontconfig: ${FONTCONFIG_LIBRARY}") else() message(STATUS "Fontconfig not found. Please set FONTCONFIG_DIR.") message(FATAL_ERROR "Fontconfig not found.") endif (FONTCONFIG_LIBRARY) # Find threading library find_package(Threads REQUIRED) list(APPEND _glvis_libraries "${CMAKE_THREAD_LIBS_INIT}") if (CMAKE_USE_PTHREADS_INIT) message(STATUS "System threading library: pthreads") elseif (CMAKE_USE_WIN32_THREADS_INIT) message(STATUS "System threading library: Win32 threads") elseif (Threads_FOUND) message(STATUS "System threading library: other") endif() else(NOT EMSCRIPTEN) find_package(glm REQUIRED) list(APPEND _glvis_include_dirs "${GLM_INCLUDE_DIRS}") set(_emscripten_opts) # Enable embind list(APPEND _emscripten_opts "--bind") # OpenGL, SDL2, and GLEW are provided by the Emscripten runtime # Enable SDL2 list(APPEND _emscripten_opts "-s USE_SDL=2") list(APPEND _emscripten_opts "-s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0") # Set WebGL options list(APPEND _emscripten_opts "-s GL_ASSERTIONS=1 -s GL_DEBUG=1 -s MAX_WEBGL_VERSION=2") # Enable Freetype port list(APPEND _emscripten_opts "-s USE_FREETYPE=1") # Module export options list(APPEND _emscripten_opts "-s ENVIRONMENT=web") list(APPEND _emscripten_opts "-s MODULARIZE=1") list(APPEND _emscripten_opts "-s EXPORT_NAME=glvis") # Other emscripten options list(APPEND _emscripten_opts "-s ALLOW_MEMORY_GROWTH=1") list(APPEND _emscripten_opts "-s SINGLE_FILE=1") list(APPEND _emscripten_opts "--no-heap-copy") # Since we don't have access to fontconfig, embed a font if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/OpenSans.ttf") message(FATAL_ERROR "Preload font file \"OpenSans.ttf\" not found.") endif() list(APPEND _emscripten_opts "--embed-file ${CMAKE_CURRENT_SOURCE_DIR}/OpenSans.ttf@OpenSans.ttf") endif(NOT EMSCRIPTEN) message(STATUS "GLVis build type: CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") message(STATUS "GLVis defines: ${_glvis_compile_defs}") # message(STATUS "GLVis opts: ${_glvis_compile_opts}") # message(STATUS "GLVis include dirs: ${_glvis_include_dirs}") # message(STATUS "GLVis libraries: ${_glvis_libraries}") message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") # # Setup the GLVis library target # add_subdirectory(lib) add_subdirectory(share) if(NOT EMSCRIPTEN) # Setup the GLVis executable set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON CACHE BOOL "") set(CMAKE_INSTALL_RPATH "${MFEM_LIBRARY_DIR}" CACHE PATH "") add_executable(glvis-exe glvis.cpp) set_target_properties(glvis-exe PROPERTIES OUTPUT_NAME glvis) target_link_libraries(glvis-exe PRIVATE glvis) if (WIN32) target_sources(glvis-exe PRIVATE "share/windows.manifest" "${CMAKE_CURRENT_BINARY_DIR}/share/resource.rc") else() target_link_libraries(glvis-exe PRIVATE glvis_logo) endif (WIN32) # Install the executable install(TARGETS glvis-exe RUNTIME DESTINATION bin) # Install the gnutls helper script if (MFEM_USE_GNUTLS) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/glvis-keygen.sh DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif (MFEM_USE_GNUTLS) if (APPLE) set(GLVIS_APP_ICON ${CMAKE_CURRENT_SOURCE_DIR}/share/GLVis.icns) set(GLVIS_APP_CREDITS ${CMAKE_CURRENT_SOURCE_DIR}/share/Credits.rtf) set_source_files_properties( ${GLVIS_APP_ICON} ${GLVIS_APP_CREDITS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") add_executable(app MACOSX_BUNDLE glvis.cpp ${GLVIS_APP_ICON} ${GLVIS_APP_CREDITS}) set_target_properties(app PROPERTIES EXCLUDE_FROM_ALL TRUE OUTPUT_NAME GLVis MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/share/Info.cmake.plist.in) target_link_libraries(app PRIVATE glvis glvis_logo) install(TARGETS app RUNTIME DESTINATION . BUNDLE DESTINATION .) install(CODE [[ include (BundleUtilities) fixup_bundle("${CMAKE_INSTALL_PREFIX}/GLVis.app" "" "") ]] COMPONENT RUNTIME) endif(APPLE) endif(NOT EMSCRIPTEN) if(ENABLE_TESTS) enable_testing() add_subdirectory(tests) endif(ENABLE_TESTS) glvis-4.3/CONTRIBUTING.md000066400000000000000000000414271465472701500147600ustar00rootroot00000000000000

glvis

Release Build License Doxygen License License

# How to Contribute The GLVis team welcomes contributions at all levels: bugfixes; code improvements; simplifications; new visualization capabilities; improved documentation; etc. GLVis is distributed under the terms of the BSD-3 license. All new contributions must be made under this license. If you plan on contributing to GLVis, consider reviewing the [issue tracker](https://github.com/glvis/glvis/issues) first to check if a thread already exists for your desired feature or the bug you ran into. Use a pull request (PR) toward the `glvis:master` branch to propose your contribution. If you are planning significant code changes or have questions, you may want to open an [issue](https://github.com/glvis/glvis/issues) before issuing a PR. In addition to technical contributions, we are also interested in your results and [simulation images](https://glvis.org/gallery/), which you can share via a pull request in the [glvis/web](https://github.com/glvis/web) repo. See the [Quick Summary](#quick-summary) section for the main highlights of our GitHub workflow. For more details, consult the following sections and refer back to them before issuing pull requests: - [Quick Summary](#quick-summary) - [Code Overview](#code-overview) - [GitHub Workflow](#github-workflow) - [GLVis Organization](#glvis-organization) - [New Feature Development](#new-feature-development) - [Developer Guidelines](#developer-guidelines) - [Pull Requests](#pull-requests) - [Pull Request Checklist](#pull-request-checklist) - [Releases](#releases) - [Release Checklist](#release-checklist) - [LLNL Workflow](#llnl-workflow) - [Automated Testing](#automated-testing) - [Contact Information](#contact-information) Contributing to GLVis requires knowledge of Git and, likely, OpenGL and/or finite elements. If you are new to Git, see the [GitHub learning resources](https://help.github.com/articles/git-and-github-learning-resources/). To learn more about the finite element method, see this [MFEM page](https://mfem.org/fem). *By submitting a pull request, you are affirming the [Developer's Certificate of Origin](#developers-certificate-of-origin-11) at the end of this file.* ## Quick Summary - We encourage you to [join the GLVis organization](#glvis-organization) and create development branches off `glvis:master`. - Please follow the [developer guidelines](#developer-guidelines), in particular with regards to documentation and code styling. - Pull requests should be issued toward `glvis:master`. Make sure to check the items off the [Pull Request Checklist](#pull-request-checklist). - When your contribution is fully working and ready to be reviewed, add the `ready-for-review` label. - PRs are treated similarly to journal submission with an "editor" assigning two reviewers to evaluate the changes. - The reviewers have 3 weeks to evaluate the PR and work with the author to fix issues and implement improvements. - We use [milestones](https://github.com/glvis/glvis/milestones) to coordinate the work on different PRs toward a release. - Don't hesitate to [contact us](#contact-information) if you have any questions. ### Code Overview #### Source code structure: The GLVis library uses object-oriented design principles which reflect, in code, the independent mathematical concepts of meshing, linear algebra and finite element spaces and operators. The GLVis source code has the following structure: ``` . ├── lib │ └── gl │ └── shaders ├── share └── tests ``` ## GitHub Workflow The GLVis GitHub organization: https://github.com/glvis, is the main developer hub for the GLVis project. If you plan to make contributions or would like to stay up-to-date with changes in the code, *we strongly encourage you to [join the GLVis organization](#glvis-organization)*. This will simplify the workflow (by providing you additional permissions), and will allow us to reach you directly with project announcements. ### GLVis Organization #### Getting started (GitHub) Before you can start, you need a GitHub account, here are a few suggestions: + Create the account at: [github.com/join](https://github.com/join). + For easy identification, please add your full name and maybe a picture of you at: https://github.com/settings/profile. + To receive notification, set a primary email at: https://github.com/settings/emails. + For password-less pull/push over SSH, add your SSH keys at: https://github.com/settings/keys. #### Joining - [Contact us](#contact-information) for an invitation to join the GLVis GitHub organization. You will receive an invitation email, which you can directly accept. Alternatively, *after logging into GitHub*, you can accept the invitation at the top of https://github.com/glvis. - Consider making your membership public by going to https://github.com/orgs/glvis/people and clicking on the organization visibility drop box next to your name. - Project discussions and announcements will be posted at https://github.com/orgs/glvis/teams/everyone. #### Structure - The GLVis source code is in the [glvis](https://github.com/glvis/glvis) repository. - The website and corresponding documentation are in the [web](https://github.com/glvis/web) repository. ### New Feature Development - A new feature should be important enough that at least one person, the author, is willing to work on it and be its champion. - The author creates a branch for the new feature (with suffix `-dev`), off the `master` branch, or another existing feature branch, for example: ``` # Clone assuming you have setup your ssh keys on GitHub: git clone git@github.com:glvis/glvis.git # Alternatively, clone using the "https" protocol: git clone https://github.com/glvis/glvis.git # Create a new feature branch starting from "master": git checkout master git pull git checkout -b feature-dev # Work on "feature-dev", add local commits # ... # (One time only) push the branch to github and setup your local # branch to track the github branch (for "git pull"): git push -u origin feature-dev ``` - **We prefer that you create the new feature branch inside the GLVis organization as opposed to in a fork.** This allows everyone in the community to collaborate in one central place. - If you prefer to work in your fork, please [enable upstream edits](https://help.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/). - Never use the `next` branch to start a new feature branch! - The typical feature branch name is `new-feature-dev`, e.g. `pumi-dev`. While not frequent in GLVis, other suffixes are possible, e.g. `-fix`, `-doc`, etc. ### Developer Guidelines - *Keep the code lean and as simple as possible* - Well-designed simple code is frequently more general and powerful. - Lean code base is easier to understand by new collaborators. - New features should be added only if they are necessary or generally useful. - Introduction of language constructions not currently used in GLVis should be justified and generally avoided (to maintain portability to various systems and compilers, including early access hardware). - We prefer basic C++ and the C++03 standard, to keep the code readable by a large audience and to make sure it compiles anywhere. - *Keep the code general and reasonably efficient* - The main goal is fast prototyping for research and application development. - When in doubt, generality wins over efficiency. - Respect the needs of different users (current and/or future). - *Keep things separate and logically organized* - General usage features go in GLVis (implemented in as much generality as possible), non-general features go into external apps. - Inside GLVis, compartmentalize between linalg, fem, mesh, GLVis, etc. - Contributions that are project-specific or have external dependencies are allowed (if they are of broader interest), but should be `#ifdef`-ed and not change the code by default. - Code specifics - All significant new classes, methods and functions have Doxygen-style documentation in source comments. - Consistent code styling is enforced with `make style` in the top-level directory. This requires [Artistic Style](http://astyle.sourceforge.net) version 3.1 and MFEM's style configuration file, typically located in `../mfem/config/mfem.astylerc`. - When manually resolving conflicts during a merge, make sure to mention the conflicted files in the commit message. ### Pull Requests - When your branch is ready for other developers to review / comment on the code, create a pull request towards `glvis:master`. - Pull request typically have titles like: `Description [new-feature-dev]` for example: `Parallel Unstructured Mesh Infrastructure (PUMI) integration [pumi-dev]` Note the branch name suffix (in square brackets). - Titles may contain a prefix in square brackets to emphasize the type of PR. Common choices are: `[DON'T MERGE]`, `[WIP]` and `[DISCUSS]`, for example: `[DISCUSS] Hybridized DG [hdg-dev]` - If the PR is still a work in progress, add the `WIP` label to it and optionally the `[WIP]` prefix in the title. - Add a description, appropriate labels and assign yourself to the PR. The GLVis team will add reviewers as appropriate. - List outstanding TODO items in the description, see PR #222 for an example. - When your contribution is fully working and ready to be reviewed, add the `ready-for-review` label. - PRs are treated similarly to journal submission with an "editor" assigning two reviewers to evaluate the changes. The reviewers have 3 weeks to evaluate the PR and work with the author to implement improvements and fix issues. ### Pull Request Checklist Before a PR can be merged, it should satisfy the following: - [ ] Code builds. - [ ] Code passes `make style`. - [ ] Update `CHANGELOG`: - [ ] Is this a new feature users need to be aware of? - [ ] Does it make sense to create a new section in the `CHANGELOG` to group with other related features? - [ ] Update `INSTALL`: - [ ] Had a new optional library been added? If so, what range of versions of this library are required? (*Make sure the external library is compatible with our BSD license, e.g. it is not licensed under GPL!*) - [ ] Have the version ranges for any required or optional libraries changed? - [ ] Does `make` or `cmake` have a new target? - [ ] Did the requirements or the installation process change? *(rare)* - [ ] Update `.gitignore`: - [ ] Check if `make distclean; git status` shows any files that were generated from the source by the project (not an IDE) but we don't want to track in the repository. - [ ] Add new patterns (just for the new files above) and re-run the above test. - [ ] New capability: - [ ] All significant new classes, methods and functions have Doxygen-style documentation in source comments. - [ ] Consider saving cool simulation pictures with the new capability in the Confluence gallery (LLNL only) or submitting them, via pull request, to the gallery section of the `glvis/web` repo. - [ ] If this is a major new feature, consider mentioning it in the short summary inside `README` *(rare)*. - [ ] List major new classes in `doc/CodeDocumentation.dox` *(rare)*. - [ ] Update this checklist, if the new pull request affects it. ### Releases - Releases are just tags in the `master` branch, e.g. https://github.com/glvis/glvis/releases/tag/v3.4, and have a version that ends in an even "patch" number, e.g. `v3.4.2` or `v3.4` (by convention `v3.4` is the same as `v3.4.0`.) Between releases, the version ends in an odd "patch" number, e.g. `v3.4.1`. - We use [milestones](https://github.com/glvis/glvis/milestones) to coordinate the work on different PRs toward a release, see for example the [v3.4 release](https://github.com/glvis/glvis/milestone/1?closed=1). - After a release is complete, the `next` branch is recreated, e.g. as follows (replace `3.4` with current release): - Rename the current `next` branch to `next-pre-v3.4`. - Create a new `next` branch starting from the `v3.4` release. - Local copies of `next` can then be updated with `git fetch origin next && git checkout -B next origin/next`. ### Release Checklist - [ ] Update the GLVis version in the following files: - [ ] `CHANGELOG` - [ ] `README.md` - [ ] `vcpkg.json` - [ ] `share/Info.plist` - [ ] `share/Info.cmake.plist.in` - [ ] Check that version requirements for each of GLVis's dependencies are documented in `INSTALL` and up-to-date - [ ] Update the `CHANGELOG` to organize all release contributions - [ ] Review the whole source code once over - [ ] Ask GLVis-based applications to test the pre-release branch - [ ] Test on additional platforms and compilers - [ ] Tag the repository: ``` git tag -a v3.1 -m "Official release v3.1" git push origin v3.1 ``` - [ ] Create the release tarball and push to `glvis/releases`. - [ ] Recreate the `next` branch as described in previous section. - [ ] Update and push documentation to `glvis/doxygen`. - [ ] Update URL shortlinks: - [ ] Create a shortlink at [http://bit.ly/](http://bit.ly/) for the release tarball, e.g. https://glvis.github.io/releases/glvis-3.1.tgz. - [ ] (LLNL only) Add and commit the new shortlink in the `links` and `links-glvis` files of the internal `glvis/downloads` repo. - [ ] Add the new shortlinks to the GLVis packages in `spack`, `homebrew/science`, `VisIt`, etc. - [ ] Update website in `glvis/web` repo: - Update version and shortlinks in `src/index.md` and `src/download.md`. - Use [cloc-1.62.pl](http://cloc.sourceforge.net/) and `ls -lh` to estimate the SLOC and the tarball size in `src/download.md`. ## LLNL Workflow ### Mirroring on Bitbucket - The GitHub `master` and `next` branches are mirrored to the LLNL institutional Bitbucket repository as `gh-master` and `gh-next`. - `gh-master` is merged into LLNL's internal `master` through pull requests; write permissions to `master` are restricted to ensure this is the only way in which it gets updated. - We never push directly from LLNL to GitHub. - Versions of the code on LLNL's internal server, from most to least stable: - GLVis official release on glvis.org -- Most stable, tested in many apps. - `glvis:master` -- Recent development version, guaranteed to work. - `glvis:gh-master` -- Stable development version, passed testing, you can use it to build your code between releases. - `glvis:gh-next` -- Bleeding-edge development version, may be broken, use at your own risk. ## Contact Information - Contact the GLVis team by posting to the [GitHub issue tracker](https://github.com/glvis/glvis). Please perform a search to make sure your question has not been answered already. ## [Developer's Certificate of Origin 1.1](https://developercertificate.org/) By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. glvis-4.3/INSTALL000066400000000000000000000216141465472701500135540ustar00rootroot00000000000000 GLVis visualization tool _/_/_/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/_/ _/ _/_/ _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/_/ _/_/_/ _/_/_/_/ _/ _/ _/_/_/ https://glvis.org GLVis is a multiplatform OpenGL application and can be built on Linux/Unix systems, including Mac OS X, and under Windows. Besides a C++ compiler, GLVis depends on the following external packages: - the MFEM library (use the latest release) plus any libraries that MFEM was built to depend on https://mfem.org - the OpenGL library https://www.opengl.org - the GLEW library; used for setting up OpenGL functions and extensions http://glew.sourceforge.net - the GLM library; used for computing OpenGL-related mathematics https://glm.g-truc.net - the SDL2 library; used for platform-native window and event management https://www.libsdl.org - the FreeType 2 and Fontconfig libraries; used for font rendering https://www.freetype.org, https://www.fontconfig.org - the libpng or libtiff library; used for taking screenshots (optional) http://www.libpng.org, http://www.libtiff.org - the XQuartz app (on Mac OS X, if running GLVis remotely through ssh) https://www.xquartz.org There are two build systems, one based on GNU make and one based on CMake, as described below. Choose the one that matches the build system you used to build MFEM. In addition to the native build systems, a GLVis package is also available in the Spack package manager, https://github.com/spack/spack. Building with GNU make ====================== GLVis comes with a standard makefile, which can be adjusted to specify the paths to the external libraries, the compiler flags, etc. Some of the available 'make' targets are: make -> Builds the glvis binary, using the MFEM compiler and options make opt -> Builds an optimized version make debug -> Builds a debug version make app -> Builds a Mac OS application bundle make clean -> Cleans the build make style -> Format the code with Artistic Style. make help -> Prints a short help message Information about the current build configuration can be viewed using make status make info An optional installation of the glvis executable can be performed with make install [PREFIX=] Building with CMake =================== GLVis may also be configured using CMake to find dependencies. This is the only supported build method for native Windows builds with Visual Studio. NOTE: You must have built MFEM using CMake to build GLVis using CMake. An example invocation of CMake may be: cmake \ -G Ninja \ -D CMAKE_BUILD_TYPE:STRING=Release \ -D CMAKE_INSTALL_PREFIX:STRING=/path/to/glvis/install \ \ -D GLVIS_USE_LIBTIFF=OFF \ -D GLVIS_USE_LIBPNG=ON \ \ -D MFEM_DIR=/path/to/directory/with/MFEMConfig.cmake \ \ /path/to/glvis/source Some important variables for CMake are: - MFEM_DIR: This is the MFEM build or install prefix. Can be used if the MFEM location is not auto-detected correctly. - mfem_DIR: (alternative to MFEM_DIR) This is the location of the configuration file MFEMConfig.cmake that is created during the build and/or install of MFEM. You may use either the build directory's config file or the install directory's config file. - CMAKE_BUILD_TYPE: Most common options are "Debug" and "Release" [default]. - CMAKE_INSTALL_PREFIX: Top-level directory for the install. GLVis will be installed to ${CMAKE_INSTALL_PREFIX}/bin. Default is "/usr/local". - GLVIS_USE_LIBPNG: Use libpng for creating screenshots. Default is "ON". - GLVIS_USE_LIBTIFF: Use libtiff for creating screenshots. Default is "OFF". - GLVIS_MULTISAMPLE and GLVIS_MS_LINEWIDTH: See building considerations below for more information on these variables. - GLVIS_FONT_SIZE: Default font size for text. Default is "12". Some building considerations ============================ - On most Linux distributions, the required dependencies (except MFEM) can be installed via a package manager. On Ubuntu/Debian, the required dependencies can be installed by running: apt-get install libfontconfig1-dev libfreetype-dev libsdl2-dev \ libglew-dev libglm-dev libpng-dev On Fedora/RHEL, the required dependencies can be installed by running: dnf install fontconfig-devel freetype-devel SDL2-devel glew-devel \ glm-devel libpng-devel On Mac OS X, the required dependencies can be installed with Homebrew: brew install fontconfig freetype sdl2 glew glm libpng Package names in other distributions may vary. - On Windows, GLVis can be built in two ways: 1) Via a Linux-compatible environment, such as Cygwin or Windows Subsystem for Linux (WSL). Install the required dependencies, following the directions above for your WSL environment's Linux distribution, then continue with the build method of your choice. For WSL, you may also need to install an X server to run GLVis, such as VcXsrv (https://sourceforge.net/projects/vcxsrv/). 2) As a native Windows executable. This enables support for platform-native visualization windows, as well as the modern OpenGL backend. Visual Studio or another Windows-compatible compiler is required. It is recommended to install dependencies via vcpkg: vcpkg install fontconfig freetype sdl2 glew glm libpng \ --triplet=x64-windows After installing, proceed with the CMake configuration process, making sure to point the CMake variable CMAKE_TOOLCHAIN_FILE to the correct path, based on the directory where you installed vcpkg. More directions can be found in the link below: https://vcpkg.readthedocs.io/en/latest/examples/installing-and-using-packages/#cmake You may then open the generated Visual Studio project files to build GLVis, or call the following command from the GLVis project root directory: cmake --build [build directory] --parallel - In case packaged versions of the needed libraries are not available, download and build instructions are included below for GLM, GLEW, and SDL2. - To adjust the anti-aliasing settings for your hardware: 1) Modify the value of the GLVIS_MULTISAMPLE variable (multisample mode) in the makefile or CMake invocation. Supported values can be obtained from the 'glxinfo' command ('ms' columns) or a from a tool like 'nvidia-settings'. 2) Modify the value of the GLVIS_MS_LINEWIDTH variable (anti-aliased line width) in the makefile or CMake invocation. Note that the same value can produce different results depending on the OpenGL implementation. 3) The above options and some other built-in defaults can be overwritten with command line options, see glvis -h for short help. - GLVis can be built without libpng/libtiff by setting the makefile variables GLVIS_USE_LIBPNG/GLVIS_USE_LIBTIFF to NO or setting the same variables to OFF during cmake configuration. In this case, GLVis uses SDL to take screenshots in .bmp format, which are then converted to .png using `convert`. - Support for secure sockets using the GnuTLS library through MFEM can be enabled by configuring and compiling MFEM with the option MFEM_USE_GNUTLS=YES, see MFEM's INSTALL for more details. In addition, in order for this to work, one needs to generate GLVis server/client key pairs (in ~/.config/glvis), similar to ssh keys. The script 'glvis-keygen.sh' can be used to do that: bash glvis-keygen.sh ["Your Name"] ["Your Email"] - On Mac OS X, GLVis can be built as a native application bundle using the 'make app' target (with both the makefile and CMake build systems). Dependency building instructions ================================ Note that using the build locations given below will let the GLVis build systems (GNU make and CMake) find these libraries automatically. ----- GLM ----- From the directory containing the 'glvis' directory run the command: git clone https://github.com/g-truc/glm.git or the sequence of commands: wget "https://github.com/g-truc/glm/archive/0.9.9.8.tar.gz" mv 0.9.9.8.tar.gz glm-0.9.9.8.tar.gz tar zxf glm-0.9.9.8.tar.gz ln -s glm-0.9.9.8 glm GLM is a header-only library, no building is necessary. ------ GLEW ------ From the directory containing the 'glvis' directory run the commands: wget "https://github.com/nigels-com/glew/releases/download/glew-2.1.0/glew-2.1.0.tgz" tar zxf glew-2.1.0.tgz ln -s glew-2.1.0 glew To build the library run the commands (see also glew/README.md): cd glew make -j 4 cd .. ------ SDL2 ------ From the directory containing the 'glvis' directory run the commands: wget "https://www.libsdl.org/release/SDL2-2.0.12.tar.gz" tar zxf SDL2-2.0.12.tar.gz To build the library run the commands (see also SDL2-2.0.12/INSTALL.txt): cd SDL2-2.0.12 ./configure --prefix=`dirname $PWD`/SDL2 make -j 4 make install cd .. glvis-4.3/LICENSE000066400000000000000000000030121465472701500135200ustar00rootroot00000000000000BSD 3-Clause License Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. glvis-4.3/NOTICE000066400000000000000000000027201465472701500134240ustar00rootroot00000000000000This work was produced under the auspices of the U.S. Department of Energy by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. This work was prepared as an account of work sponsored by an agency of the United States Government. Neither the United States Government nor Lawrence Livermore National Security, LLC, nor any of their employees makes any warranty, expressed or implied, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights. Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or otherwise does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or Lawrence Livermore National Security, LLC. The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government or Lawrence Livermore National Security, LLC, and shall not be used for advertising or product endorsement purposes. Inclusion of external software: This project distributes the sources of several external software products with their own respective licenses which can be found in their code and attached license files. These software products and their licenses are as follows: * GL2PS (linalg/gl2ps.{h,c}) -- Custom 1-clause license glvis-4.3/README.md000066400000000000000000000445671465472701500140160ustar00rootroot00000000000000 GLVis visualization tool _/_/_/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/_/ _/ _/_/ _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/_/ _/_/_/ _/_/_/_/ _/ _/ _/_/_/ https://glvis.org Release Build License Doxygen License License [GLVis](https://glvis.org) is an OpenGL tool for visualization of finite element meshes and functions. It is a multiplatform application that can be built on Linux/Unix systems, including macOS, and under Windows. It can also be used in a Jupyter notebook, or in a web browser, see https://glvis.org/live. - For building instructions, see [INSTALL](INSTALL). - The GLVis [key commands](#key-commands) and [mouse functions](#mouse-functions) are documented below. - GLVis is distributed under the terms of the BSD-3 license. All new contributions must be made under this license. See [LICENSE](LICENSE) and [NOTICE](NOTICE) for details. We welcome contributions and feedback from the community. Please see the file [CONTRIBUTING.md](CONTRIBUTING.md) for additional details about our development process. When started without any options, glvis starts a server which waits for a socket connections (on port `19916` by default) and visualizes any received data. This way the results of simulations on a remote (parallel) machine can be visualized on the local user desktop. GLVis can also be used to visualize a mesh with or without a finite element function (solution), as in ``` glvis -m cube.mesh3d ``` For parallel computations, GLVis supports input from several parallel socket connections as well as the visualization of parallel meshes and grid functions saved in separate files from the command line as in ``` glvis -np 4 -m mesh -g solution ``` When given parallel input, GLVis will stitch the results to show the global mesh and solution. GLVis can also run a batch sequence of commands (GLVis scripts), or display previously saved socket streams. For a complete list of command line options, type ``` glvis -h ``` Depending on the data type, variety of manipulations can be performed by using the mouse and by typing (case sensitive) keystrokes in the GLVis window. Below is a partial list of the available functionality. Some of these keys can also be provided as input, using the `-k` command-line option and the `keys` script command. For high-order meshes and/or solution data, GLVis performs element subdivision to try to represent the data more accurately. However, for highly-varying data or large meshes, the auto-selected subdivision factor (see the [Auto-refinement](#auto-refinement) section below) may not be sufficient -- use the keys o / O, described below, to manually adjust the subdivision factor. SPDX-License-Identifier: BSD-3-Clause
LLNL Release Number: LLNL-CODE-443271
DOI: 10.11578/dc.20171025.1249 Mouse functions =============== ## Basic - Left – Rotate the viewpoint - Right – Zoom in (up) / Zoom out (down) - Middle – Translate the viewpoint - Left + Shift – Start spinning the viewpoint (according to the dragging vector) ## Advanced - Left + Alt – Tilt - Left + Ctrl – Spherical rotation - Left + Ctrl + Shift – `z`-spinning - Right + Ctrl – Object scaling (see also [ and ]) - Right + Shift – Change light source position (see \\) - Middle + Ctrl – Object translation (moves the camera left/right/up/down) - Middle + Ctrl + Alt – Moves the camera forward/backward (vertical mouse motion) and tilts the camera left/right (horizontal mouse motion) - Middle + Ctrl + Shift – Object translation (turns the camera left/right/up/down) Key commands ============ ## Basic - h – Print a short help message in the terminal - r – Reset the plot to 3D view - R – Cycle through the six 2D projections (camera looking above/below in `x`/`y`/`z` directions) - j – Turn on/off perspective - s – Turn on/off unit cube scaling - A – Turn on/off the use of anti-aliasing/multi-sampling - L – Turn on/off logarithmic scale - c – Toggle the colorbar and caption display state - C – Change the main plot caption - p / P – Cycle forward/backwards through color palettes (lots of options, use F6 for a menu) - t – Cycle materials and lights (5 states) - i – Toggle cutting plane (different options in 2D and 3D, see below) - o / O – Control element subdivisions (different options in 2D and 3D, see below) - l – Turn on/off the light - g – Toggle background color (white/black) - a – Toggle the bounding box *axes*. The options are: - none - bounding box with coordinates of the corners - bounding box without coordinates - red, green, blue colored main `x`, `y`, `z` axes + dashed axes - m – Toggle the *mesh* state. The options are: - no mesh or level lines - draw the element edges (i.e. the mesh) - draw the level lines (use F5 to modify the level lines) - e – Toggle the *elements* state (see below for vector functions). The options are: - show surface elements (corresponding to the function) - show no surface elements - (2D only) show element attributes - (2D only) show element `det(J)` - (2D only) show element `1/det(J)` - (2D only) show element `\kappa` - (2D only) show element `\kappa + 1/\kappa` - S – Take an image snapshot or record a movie (in spinning mode). By default, the screenshots are taken in `png` format, using libpng. When GLVis is compiled with `libtiff` support (see [INSTALL](INSTALL)) then the screenshots are taken internally and saved in TIFF format (`.tif` extension). If both of these options are disabled during the build process, GLVis will use `SDL` to take screenshots in `bmp` format, which it will then convert to `png` if ImageMagick's `convert` tool is available. - G – 3D scene export to [glTF format](https://www.khronos.org/gltf) - Ctrl + p – Print to a PDF file using `gl2ps`. Other vector formats (SVG, EPS) are also possible, but keep in mind that the printing takes a while and the generated files are big. - Q – Cycle between representations of the visualized *quadrature data*. The options are: - piece-wise constant refined (LOR) - L2 element dof collocation (interpolation) - L2 element projection (L2 projection) - q – Exit ## Advanced - f – Change the shading type (the way the elements and mesh are drawn). The options are: - one triangle / quad per element with a constant normal - one triangle / quad per element with normals averaged at the vertices - multiple triangles / quads per element, also allowing for the visualization of discontinuous functions and curvilinear elements (use o / O to control subdivisions) - \\ – Set light source position (see Right + Shift) - * / / – Zoom in/out - + / - – Stretch/compress in `z`-direction - [ / ] – Shrink/enlarge the bounding box (relative to the colorbar) - ( / ) – Shrink/enlarge the visualization window - . – Start/stop `z`-spinning (speed/direction can be controlled with 0 / Enter) - , , , – Manual rotation - 1, 2, 3, 4, 5, 6, 7, 8, 9 – Manual rotation along coordinate axes - Alt + a – Set axes number format - Alt + c – Set colorbar number format - Ctrl + , , , – Translate the viewpoint - Ctrl + o – Toggle an element ordering curve - n / N – Cycle through numberings. The options are: - none - show element numbering - show edge numbering - show vertex numbering - ` – Toggle a ruler, with initial origin at the center of the bounding box. The origin can be later moved with ~. The options are: - none - coordinate axes lines - coordinate axes planes - ~ - Enter new ruler origin - k / K - Adjust the transparency level. The balance of transparency can be further adjusted with , and <. - ! - Toggle the use of (1D) texture (smooth interpolation of colors). The options are: - use discrete texture, the number of colors used depends on the current palette - use smooth texture (interpolated from current palette) - F5 – Change the range and number of the level lines - F6 – Palette menu (negative repeat number flips the palette) - F7 – Change the minimum and maximum values - Shift + F7 – Set the bounding box from the terminal ## 2D scalar data - i – Toggle cutting (clipping) plane in 2D - y / Y – Rotate cutting plane (`\theta`) in 2D - z / Z – Translate cutting plane in 2D - o / O – Control element subdivisions in 2D - there are two subdivision factors in this case: element (`s1`) and boundary (`s2`). - O cycles through the following "subdivision functions", (prints a message in the terminal when changed): - Increase element subdivision factor: `s1 += s2` - Decrease element subdivision factor: `s1 -= s2` - Increase boundary subdivision factor: `s2++` - Decrease boundary subdivision factor: `s2--` - o – performs the currently selected function - b – Toggle the boundary in 2D scalar mode. The options are: - no boundary - black boundary - boundary colored with the boundary attribute - Use Shift + F9 / F10 to cycle through the boundary attributes. - F3 / F4 – Shrink/Zoom each element towards its center, in order to better visualize the different element shapes - F8 – List of material subdomains to show - F9 / F10 – Walk through material subdomains - F11 / F12 – Shrink/Zoom material subdomains (to the centers of the attributes) ## 3D scalar data - i – Toggle cutting (clipping) plane in 3D. The options are: - none - cut through the elements - show only elements behind the cutting plane - I – Toggle the cutting plane algorithm used when the option *cut through the elements* is selected. The two algorithms are: - slower, more accurate algorithm for curved meshes (default) - faster algorithm suitable for meshes with planar faces - x / X – Rotate cutting plane (`\phi`) in 3D - y / Y – Rotate cutting plane (`\theta`) in 3D - z / Z – Translate cutting plane in 3D - E – Display/Hide the elements in the cutting plane - M – Display/Hide the mesh in the cutting plane - o / O – Refine/de-refine elements in 3D - u / U – Move level surface value up/down - v / V – Add/Delete a level surface value - w / W – Move boundary elements up/down in direction of the normal (i.e. "plot" the boundary values in normal direction) - F3 / F4 – Shrink/Zoom boundary elements (to the centers of the attributes) - F8 – List of boundary subdomains to show - F9 / F10 – Walk through boundary subdomains - F11 / F12 – Shrink/Zoom material subdomains (to the centers of the attributes) ## 2D vector data - v – Toggle the *vector* state (uses vector subdivision factor, accept u / U). The options are: - do not show vectors - show vectors as displacement - show vector field; vectors are uniformly scaled; the color varies with the magnitude (or the current *vector-to-scalar function*, see keys u / U) - show vector field as above, but the vectors are scaled proportionally to their magnitude - show vector field; vectors are uniformly scaled; the color is gray; arrows are above the surface - show vector field as above, but the vectors are scaled proportionally to their magnitude - V – Change the scaling of the vectors relative to the default - d – Toggle the *displaced mesh* state: (see also keys n / b). The options are: - do not show displaced mesh - show displaced mesh - assuming displacement field show deformation using Cartesian lines - assuming displacement field show deformation using polar lines - n – Increase the displacement amount in 10% steps, wraps around from 100% to 0% - b – Decrease the displacement amount in 10% steps, wraps around from 0% to 100% - B – Toggle the boundary in 2D vector mode - e – Toggle the *elements* state (vector data version). The options are: - show surface elements corresponding to the current *vector-to-scalar function* - do not show surface elements - assuming a displacement field show `det(J)/det(J_d)` - assuming a displacement field show `det(J_d)/det(J)` - u / U – Change the *vector-to-scalar function* and the vector subdivision factor - U – Toggle the functionality of u (prints a message in the terminal when changed). The options are: - Increase the vector subdivision factor - Decrease the vector subdivision factor - Cycle through *vector-to-scalar functions* choices: - magnitude: `\sqrt{v_x^2+v_y^2}` - direction from `-\pi` to `\pi`: `atan2(v_y,v_x)` - `x`-component: `v_x` - `y`-component: `v_y` - divergence: `div(v)` - curl: `curl(v)` [skipped for H(div) elements] - anisotropy in `grad(v)` [skipped for H(div) elements] ## 3D vector data - v – Toggle the *vector* state. The options are: - do not show vectors - show vectors as displacement - show vector field; vectors are uniformly scaled; the color varies with the magnitude (or the current *vector-to-scalar function*, see key F) - show vector field as above, but the vectors are scaled proportionally to their magnitude - show the subset of the vector field with scalar function around a given value (adjusted with keys u / U and w / W) - show the vector field restricted to the boundary of the domain - V – Cycle the *vector* state in the opposite direction of v - u / U – Move the level field vectors (in the appropriate *vector* state) - w / W – Add/Delete level field vector (in the appropriate *vector* state) - d – Toggle the *displaced mesh* state (see also keys n / b). The options are: - do not show displaced mesh - show displaced mesh - n – Increase the displacement amount in 10% steps, wraps around from 100% to 0% - b – Decrease the displacement amount in 10% steps, wraps around from 0% to 100% - F – Change the *vector-to-scalar function*. The options are: - magnitude: `\sqrt{v_x^2+v_y^2+v_z^2}` - `x`-component: `v_x` - `y`-component: `v_y` - `z`-component: `v_z` ## Auto-refinement The GLVis auto-refinement algorithm selects a subdivision factor trying to achieve an accurate representation of high-order meshes and solution data while keeping the initial time to visualize the data reasonable. The algorithm can be summarized as follows: - GLVis draws surface elements; the number of drawn elements, `ne`, is either: - the number of elements in the mesh for 2D meshes (including surface meshes, i.e. 2D meshes embedded in 3D space), or - the number of boundary mesh elements described by the mesh in 3D. - A tentative upper limit on the number of vertices to be drawn is defined based on the maximum order of the mesh and the solution, `max_order`: ``` max_vert = ne * (max_order + 1) * (max_order + 1) ``` - To allow more accurate representation for small meshes, this number is potentially increased: ``` max_vert = max(max_vert, 100 000) ``` - To keep the time to initially visualize the data reasonable, this number is potentially reduced: ``` max_vert = min(max_vert, 2 000 000) ``` - Finally, the subdivision factor `ref` is chosen to be the largest number such that: - the number of vertices needed to draw the `ne` surface elements with `ref` subdivisions does not exceed `max_vert`: ``` ne * (ref + 1) * (ref + 1) <= max_vert ``` - for large meshes where the above limit cannot be satisfied, set `ref = 1` - for small meshes, avoid excessive refinements: ``` ref <= 16 ``` Note that, for highly-varying data or large meshes, this auto-selected subdivision factor may not be sufficient for accurate representation. In such cases the subdivision can be manually adjusted using the keys o / O, described above. glvis-4.3/glvis-keygen.sh000077500000000000000000000257651465472701500155010ustar00rootroot00000000000000#!/bin/bash # Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced # at the Lawrence Livermore National Laboratory. All Rights reserved. See files # LICENSE and NOTICE for details. LLNL-CODE-443271. # # This file is part of the GLVis visualization tool and library. For more # information and source code availability see https://glvis.org. # # GLVis is free software; you can redistribute it and/or modify it under the # terms of the BSD-3 license. We welcome feedback and contributions, see file # CONTRIBUTING.md for details. GLVIS_KEYS_DIR="${HOME}"/.config/glvis NAME_COMMENT_SERVER="GLVis server key" NAME_COMMENT_CLIENT="GLVis client key" function have_command() { command -v $1 > /dev/null 2>&1 } function check_gpg2() { if ! have_command ${GPG2}; then printf "\nThe required command \"${GPG2}\" was not found. Stop.\n\n" exit 1 fi } function check_certtool() { if ! have_command ${CERTTOOL}; then printf "\nThe required command \"${CERTTOOL}\" was not found. Stop.\n\n" exit 1 fi if { ${CERTTOOL} --help | head -1 | grep -q GnuTLS; }; then # newer versions of GnuTLS certtool return 0 elif { ${CERTTOOL} --version | head -1 | grep -q GnuTLS; }; then # older versions of GnuTLS certtool return 0 else printf "\nThe required command \"${CERTTOOL}\" is not GnuTLS certtool." printf " Stop.\n\n" exit 1 fi } function gen_keys_gpg2() { local IN="" IN="${IN}Key-Type: RSA\n" IN="${IN}Key-Length: 2048\n" IN="${IN}Subkey-Type: RSA\n" IN="${IN}Subkey-Length: 2048\n" IN="${IN}Name-Real: "'${NAME_REAL}'"\n" IN="${IN}Name-Comment: "'${NAME_COMMENT}'"\n" IN="${IN}Name-Email: "'${NAME_EMAIL}'"\n" IN="${IN}Expire-Date: 0\n" IN="${IN}%%no-protection\n" # for gpg2 version >= 2.1 IN="${IN}%%commit" IN=$(printf "${IN}") eval "IN=\"${IN}\"" # printf "%s\n" "${IN}" local GPG2_ARGS=("--homedir" "${KEY_DIR}" "--batch" "--gen-key" "-") printf "%s\n" "${IN}" | ${GPG2} "${GPG2_ARGS[@]}" } function gen_keys_certtool() { local CT="${CERTTOOL}" ROLE="$1" IN="" cd "${KEY_DIR}" || return 1 # Generate user CA key $CT --generate-privkey --outfile ca-key.pem || return 1 # Generate self-signed user CA certificate IN="cn = \"${NAME_REAL}'s GLVis ${ROLE} CA Certificate\"\n" IN="${IN}email = \"${NAME_EMAIL}\"\n" IN="${IN}expiration_days = 3651\n" IN="${IN}ca\n" IN="${IN}cert_signing_key\n" printf "$IN" > ca-cert.cfg $CT --generate-self-signed --load-privkey ca-key.pem \ --outfile ca-cert.pem --template ca-cert.cfg \ > ca-cert.txt 2>&1 || return 1 rm -f ca-cert.cfg ca-cert.txt # Generate user key $CT --generate-privkey --outfile key.pem || return 1 # Generate user certificate signed with the CA key & certificate IN="cn = \"${NAME_REAL}'s GLVis ${ROLE} Certificate\"\n" IN="${IN}email = \"${NAME_EMAIL}\"\n" IN="${IN}expiration_days = 3650\n" IN="${IN}signing_key\n" IN="${IN}encryption_key\n" if [ "${ROLE}" == "Client" ]; then IN="${IN}tls_www_client\n" else IN="${IN}tls_www_server\n" fi printf "$IN" > cert.cfg $CT --generate-certificate --load-privkey key.pem \ --outfile cert.pem --load-ca-certificate ca-cert.pem \ --load-ca-privkey ca-key.pem --template cert.cfg \ > cert.txt 2>&1 || return 1 rm -f cert.cfg cert.txt } function check_keys_gpg2() { if [ -s "${GLVIS_KEYS_DIR}"/server/pubring.gpg ] && \ [ -s "${GLVIS_KEYS_DIR}"/server/secring.gpg ]; then GEN_SERVER_KEY="NO" fi if [ -s "${GLVIS_KEYS_DIR}"/client/pubring.gpg ] && \ [ -s "${GLVIS_KEYS_DIR}"/client/secring.gpg ]; then GEN_CLIENT_KEY="NO" fi if [ -s "${GLVIS_KEYS_DIR}"/client/trusted-servers.gpg ]; then ADD_SERVER_KEY="NO" fi if [ -s "${GLVIS_KEYS_DIR}"/server/trusted-clients.gpg ]; then ADD_CLIENT_KEY="NO" fi } function check_keys_certtool() { if [ -s "${GLVIS_KEYS_DIR}"/server/cert.pem ] && \ [ -s "${GLVIS_KEYS_DIR}"/server/key.pem ]; then GEN_SERVER_KEY="NO" fi if [ -s "${GLVIS_KEYS_DIR}"/client/cert.pem ] && \ [ -s "${GLVIS_KEYS_DIR}"/client/key.pem ]; then GEN_CLIENT_KEY="NO" fi if [ -s "${GLVIS_KEYS_DIR}"/client/trusted-servers.pem ]; then ADD_SERVER_KEY="NO" fi if [ -s "${GLVIS_KEYS_DIR}"/server/trusted-clients.pem ]; then ADD_CLIENT_KEY="NO" fi } # $1 - scr dir, $2 - dest dir function add_keys_gpg2() { cd "${GLVIS_KEYS_DIR}" && \ ${GPG2} --homedir "${GLVIS_KEYS_DIR}"/$1 --export --armor \ --output "$1.asc" && \ ${GPG2} --homedir "${GLVIS_KEYS_DIR}"/$2 --no-default-keyring \ --keyring "trusted-${1}s.gpg" --import "$1.asc" } # $1 - scr dir, $2 - dest dir add_keys_certtool() { cd "${GLVIS_KEYS_DIR}" && \ cp -fp $1/ca-cert.pem $2/trusted-${1}s.pem } function list_keys_gpg2() { # ${GPG2} --homedir "${GLVIS_KEYS_DIR}"/server --list-secret-keys if [ -s "${GLVIS_KEYS_DIR}"/server/trusted-clients.gpg ]; then ${GPG2} --homedir "${GLVIS_KEYS_DIR}"/server \ --keyring "trusted-clients.gpg" --list-public-keys else printf "Server/trusted-client keys not found.\n" fi # ${GPG2} --homedir "${GLVIS_KEYS_DIR}"/client --list-secret-keys if [ -s "${GLVIS_KEYS_DIR}"/client/trusted-servers.gpg ]; then ${GPG2} --homedir "${GLVIS_KEYS_DIR}"/client \ --keyring "trusted-servers.gpg" --list-public-keys else printf "Client/trusted-server keys not found.\n" fi } function list_keys_certtool() { local CT="${CERTTOOL}" local sc="${GLVIS_KEYS_DIR}"/server/cert.pem sn="Server certificate" local cc="${GLVIS_KEYS_DIR}"/client/cert.pem cn="Client certificate" if [ -s "$sc" ]; then echo "$sn:" echo "-------------------" $CT --certificate-info --infile "$sc" else printf "$sn not found.\n" fi echo if [ -s "$cc" ]; then echo "$cn:" echo "-------------------" $CT --certificate-info --infile "$cc" else printf "$cn not found.\n" fi } function read_name_email() { NAME_REAL="$1" NAME_EMAIL="$2" if [ "${NAME_REAL}" == "" ]; then if [ -t 0 ]; then if [ -s "${HOME}"/.gitconfig ] && have_command git; then FULL_NAME=$(git config user.name) elif [ $(uname -s) == "Darwin" ]; then FULL_NAME=$(id -P ${USER} | awk -F: '{print $8}') elif have_command getent; then FULL_NAME=$(getent passwd ${USER} | awk -F: '{print $5}') else FULL_NAME=${USER} fi read -p "Enter your name [${FULL_NAME}]: " NAME_REAL if [ "${NAME_REAL}" == "" ]; then NAME_REAL="${FULL_NAME}" fi else return 1 fi fi if [ "${NAME_EMAIL}" == "" ]; then if [ -t 0 ]; then if [ -s "${HOME}"/.gitconfig ] && have_command git; then FULL_EMAIL=$(git config user.email) else FULL_EMAIL="${USER}@${HOST}" fi read -p "Enter your email [${FULL_EMAIL}]: " NAME_EMAIL if [ "${NAME_EMAIL}" == "" ]; then NAME_EMAIL="${FULL_EMAIL}" fi else return 1 fi fi } function print_usage() { printf "Usage:\n" printf " $0 {-h|--help}\n" printf " $0 [=]... {-l|--list}\n" printf " $0 [=]... [\"Your Name\"] [\"Your Email\"]\n" printf "Valid variables:\n" printf " keytype={x509|gpg} (current value: ${KEYTYPE})\n" printf " certtool= (current value: ${CERTTOOL}" printf ", keytype: x509)\n" printf " gpg2= (current value: ${GPG2}" printf ", keytype: gpg)\n" } function select_params() { # Key generation programs: gpg2, certtool GPG2=${gpg2:-gpg2} case "$OSTYPE" in darwin*) CERTTOOL=${certtool:-gnutls-certtool} ;; *) CERTTOOL=${certtool:-certtool} ;; esac # Key type to generate: gpg or x509 KEYTYPE=${keytype:-x509} case "$KEYTYPE" in gpg) keytype_prog=gpg2 ;; x509) keytype_prog=certtool ;; *) printf "\nInvalid keytype: '${KEYTYPE}'. Stop.\n\n" exit 1 ;; esac } while [ $# -gt 0 ]; do case "$1" in -h|--help) select_params print_usage exit 0 ;; -l|--list) select_params check_$keytype_prog echo list_keys_$keytype_prog exit 0 ;; -*) printf "Unknown option: '$1'. Stop.\n\n" exit 1 ;; *=*) eval $1 shift ;; *) break ;; esac done select_params GEN_SERVER_KEY="YES" GEN_CLIENT_KEY="YES" ADD_SERVER_KEY="YES" ADD_CLIENT_KEY="YES" check_keys_$keytype_prog if [ "${GEN_SERVER_KEY}" == "YES" ] || [ "${GEN_CLIENT_KEY}" == "YES" ]; then check_$keytype_prog if ! read_name_email "$@"; then print_usage exit 1 fi elif [ "${ADD_SERVER_KEY}" == "YES" ] || [ "${ADD_CLIENT_KEY}" == "YES" ]; then check_$keytype_prog fi echo if [ "${GEN_SERVER_KEY}" == "NO" ]; then printf "Server key exists.\n\n" else printf "\r---------------------------\n" printf " Generating server key\n" printf "\r---------------------------\n" NAME_COMMENT="${NAME_COMMENT_SERVER}" KEY_DIR="${GLVIS_KEYS_DIR}"/server echo mkdir -p "${KEY_DIR}" mkdir -p "${KEY_DIR}" if ! gen_keys_$keytype_prog "Server"; then printf "\nGeneration failed. Stop.\n\n" exit 1 fi printf "\r---------------------------\n\n" fi if [ "${GEN_CLIENT_KEY}" == "NO" ]; then printf "Client key exists.\n\n" else printf "\r---------------------------\n" printf " Generating client key\n" printf "\r---------------------------\n" NAME_COMMENT="${NAME_COMMENT_CLIENT}" KEY_DIR="${GLVIS_KEYS_DIR}"/client echo mkdir -p "${KEY_DIR}" mkdir -p "${KEY_DIR}" if ! gen_keys_$keytype_prog "Client"; then printf "\nGeneration failed. Stop.\n\n" exit 1 fi printf "\r---------------------------\n\n" fi if [ "${ADD_SERVER_KEY}" == "NO" ]; then printf "Client's trusted-servers keyring exists.\n\n" else printf "\r-------------------------------------------------------\n" printf " Adding the server key to the client's trusted-servers\n" printf "\r-------------------------------------------------------\n" if ! add_keys_$keytype_prog "server" "client"; then printf "\nOperation failed. Stop.\n\n" exit 1 fi printf "\r-------------------------------------------------------\n\n" fi if [ "${ADD_CLIENT_KEY}" == "NO" ]; then printf "Server's trusted-clients keyring exists.\n\n" else printf "\r-------------------------------------------------------\n" printf " Adding the client key to the server's trusted-clients\n" printf "\r-------------------------------------------------------\n" if ! add_keys_$keytype_prog "client" "server"; then printf "\nOperation failed. Stop.\n\n" exit 1 fi printf "\r-------------------------------------------------------\n\n" fi glvis-4.3/glvis.cpp000066400000000000000000001560721465472701500143620ustar00rootroot00000000000000// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-443271. // // This file is part of the GLVis visualization tool and library. For more // information and source code availability see https://glvis.org. // // GLVis is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. // GLVis - an OpenGL visualization server based on the MFEM library #include #include #include #include #include #include #include // SDL may redefine main() as SDL_main() ostensibly to ease portability. // (WinMain() instead of main() is used as the entry point in a non-console // Windows program.) // // We must instead define SDL_MAIN_HANDLED so that SDL doesn't do this // substitution, since we need a console to accept certain user input from // stdin. #ifdef _WIN32 #define SDL_MAIN_HANDLED #endif #include "mfem.hpp" #include "lib/palettes.hpp" #include "lib/visual.hpp" #include "lib/stream_reader.hpp" using namespace std; using namespace mfem; const char *string_none = "(none)"; const char *string_default = "(default)"; // Global variables for command line arguments const char *mesh_file = string_none; const char *sol_file = string_none; const char *vec_sol_file = string_none; const char *gfunc_file = string_none; const char *qfunc_file = string_none; const char *arg_keys = string_none; int pad_digits = 6; int gf_component = -1; int qf_component = -1; int window_x = 0; // not a command line option int window_y = 0; // not a command line option int window_w = 400; int window_h = 350; const char *window_title = string_default; const char *c_plot_caption = string_none; thread_local string plot_caption; thread_local string extra_caption; bool secure = socketstream::secure_default; // Global variables enum InputOptions { INPUT_SERVER_MODE = 1, INPUT_MESH = 2, INPUT_SCALAR_SOL = 4, INPUT_VECTOR_SOL = 8, //... INPUT_PARALLEL = 256, }; int input = INPUT_SERVER_MODE; thread_local StreamState stream_state; thread_local VisualizationSceneScalarData *vs = NULL; extern thread_local GLVisCommand* glvis_command; thread_local communication_thread *comm_thread = NULL; thread_local GeometryRefiner GLVisGeometryRefiner; const char *window_titles[] = { "GLVis [scalar data]", "GLVis [vector data]", "GLVis [mesh]" }; istream *script = NULL; int scr_running = 0; int scr_level = 0; Vector *init_nodes = NULL; double scr_min_val, scr_max_val; extern char **environ; void PrintSampleUsage(ostream &out); // read the mesh and the solution from a file void ReadSerial(StreamState& state); // choose grid function component and set the input flag void SetGridFunction(StreamState& state); // choose quadrature function component and set the input flag void SetQuadFunction(StreamState& state); // read the mesh and the solution from multiple files void ReadParallel(int np, StreamState& state); int ReadParMeshAndGridFunction(int np, const char *mesh_prefix, const char *sol_prefix, StreamState& state); int ReadParMeshAndQuadFunction(int np, const char *mesh_prefix, const char *sol_prefix, StreamState& state); // switch representation of the quadrature function void SwitchQuadSolution(); // Visualize the data in the global variables mesh, sol/grid_f, etc bool GLVisInitVis(StreamState::FieldType field_type, StreamCollection input_streams) { if (field_type <= StreamState::FieldType::MIN || field_type >= StreamState::FieldType::MAX) { return false; } const char *win_title = (window_title == string_default) ? window_titles[(int)field_type] : window_title; if (InitVisualization(win_title, window_x, window_y, window_w, window_h)) { cerr << "Initializing the visualization failed." << endl; return false; } if (input_streams.size() > 0) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); glvis_command = new GLVisCommand(&vs, stream_state, &stream_state.keep_attr); comm_thread = new communication_thread(std::move(input_streams), glvis_command); } if (stream_state.quad_f) { GetAppWindow()->setOnKeyDown('Q', SwitchQuadSolution); } double mesh_range = -1.0; if (field_type == StreamState::FieldType::SCALAR || field_type == StreamState::FieldType::MESH) { if (stream_state.grid_f) { stream_state.grid_f->GetNodalValues(stream_state.sol); } if (stream_state.mesh->SpaceDimension() == 2) { VisualizationSceneSolution * vss; if (stream_state.normals.Size() > 0) { vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol, stream_state.mesh_quad.get(), &stream_state.normals); } else { vs = vss = new VisualizationSceneSolution(*stream_state.mesh, stream_state.sol, stream_state.mesh_quad.get()); } if (stream_state.grid_f) { vss->SetGridFunction(*stream_state.grid_f); } if (field_type == StreamState::FieldType::MESH) { vs->OrthogonalProjection = 1; vs->SetLight(false); vs->Zoom(1.8); // Use the 'bone' palette when visualizing a 2D mesh only (otherwise // the 'jet-like' palette is used in 2D, see vssolution.cpp). vs->palette.SetIndex(4); } } else if (stream_state.mesh->SpaceDimension() == 3) { VisualizationSceneSolution3d * vss; vs = vss = new VisualizationSceneSolution3d(*stream_state.mesh, stream_state.sol, stream_state.mesh_quad.get()); if (stream_state.grid_f) { vss->SetGridFunction(stream_state.grid_f.get()); } if (field_type == StreamState::FieldType::MESH) { if (stream_state.mesh->Dimension() == 3) { // Use the 'white' palette when visualizing a 3D volume mesh only vss->palette.SetIndex(11); vss->SetLightMatIdx(4); } else { // Use the 'bone' palette when visualizing a surface mesh only vss->palette.SetIndex(4); } // Otherwise, the 'vivid' palette is used in 3D see vssolution3d.cpp vss->ToggleDrawAxes(); vss->ToggleDrawMesh(); } } if (field_type == StreamState::FieldType::MESH) { if (stream_state.grid_f) { mesh_range = stream_state.grid_f->Max() + 1.0; } else { mesh_range = stream_state.sol.Max() + 1.0; } } } else if (field_type == StreamState::FieldType::VECTOR) { if (stream_state.mesh->SpaceDimension() == 2) { if (stream_state.grid_f) { vs = new VisualizationSceneVector(*stream_state.grid_f); } else { vs = new VisualizationSceneVector(*stream_state.mesh, stream_state.solu, stream_state.solv, stream_state.mesh_quad.get()); } } else if (stream_state.mesh->SpaceDimension() == 3) { if (stream_state.grid_f) { stream_state.ProjectVectorFEGridFunction(); vs = new VisualizationSceneVector3d(*stream_state.grid_f, stream_state.mesh_quad.get()); } else { vs = new VisualizationSceneVector3d(*stream_state.mesh, stream_state.solu, stream_state.solv, stream_state.solw, stream_state.mesh_quad.get()); } } } if (vs) { // increase the refinement factors if visualizing a GridFunction if (stream_state.grid_f) { vs->AutoRefine(); vs->SetShading(VisualizationSceneScalarData::Shading::Noncomforming, true); } if (mesh_range > 0.0) { vs->SetValueRange(-mesh_range, mesh_range); vs->SetAutoscale(0); } if (stream_state.mesh->SpaceDimension() == 2 && field_type == StreamState::FieldType::MESH) { SetVisualizationScene(vs, 2, stream_state.keys.c_str()); } else { SetVisualizationScene(vs, 3, stream_state.keys.c_str()); } } return true; } void GLVisStartVis() { RunVisualization(); // deletes vs vs = NULL; if (glvis_command) { glvis_command->Terminate(); delete comm_thread; delete glvis_command; glvis_command = NULL; } cout << "GLVis window closed." << endl; } int ScriptReadSolution(istream &scr, StreamState& state) { string mword,sword; cout << "Script: solution: " << flush; // read the mesh scr >> ws >> mword; // mesh filename (can't contain spaces) cout << "mesh: " << mword << "; " << flush; named_ifgzstream imesh(mword.c_str()); if (!imesh) { cout << "Can not open mesh file: " << mword << endl; return 1; } state.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); // read the solution (GridFunction) scr >> ws >> sword; if (sword == mword) // mesh and solution in the same file { cout << "solution: " << mword << endl; state.SetGridFunction(new GridFunction(state.mesh.get(), imesh)); } else { cout << "solution: " << sword << endl; ifgzstream isol(sword.c_str()); if (!isol) { cout << "Can not open solution file: " << sword << endl; return 2; } state.SetGridFunction(new GridFunction(state.mesh.get(), isol)); } state.Extrude1DMeshAndSolution(); return 0; } int ScriptReadQuadrature(istream &scr, StreamState& state) { string mword,sword; cout << "Script: quadrature: " << flush; // read the mesh scr >> ws >> mword; // mesh filename (can't contain spaces) cout << "mesh: " << mword << "; " << flush; named_ifgzstream imesh(mword.c_str()); if (!imesh) { cout << "Can not open mesh file: " << mword << endl; return 1; } state.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); // read the quadrature (QuadratureFunction) scr >> ws >> sword; if (sword == mword) // mesh and quadrature in the same file { cout << "quadrature: " << mword << endl; state.SetQuadFunction(new QuadratureFunction(state.mesh.get(), imesh)); } else { cout << "quadrature: " << sword << endl; ifgzstream isol(sword.c_str()); if (!isol) { cout << "Can not open quadrature file: " << sword << endl; return 2; } state.SetQuadFunction(new QuadratureFunction(state.mesh.get(), isol)); } state.SetQuadSolution(); state.Extrude1DMeshAndSolution(); return 0; } int ScriptReadParSolution(istream &scr, StreamState& state) { int np, scr_keep_attr, err_read; string mesh_prefix, sol_prefix; cout << "Script: psolution: " << flush; // read number of processors scr >> np; cout << "# processors: " << np << "; " << flush; // read the mesh prefix scr >> ws >> mesh_prefix; // mesh prefix (can't contain spaces) cout << "mesh prefix: " << mesh_prefix << "; " << flush; scr >> ws >> scr_keep_attr; if (scr_keep_attr) { cout << "(real attributes); " << flush; } else { cout << "(processor attributes); " << flush; } // read the solution prefix scr >> ws >> sol_prefix; cout << "solution prefix: " << sol_prefix << endl; err_read = ReadParMeshAndGridFunction(np, mesh_prefix.c_str(), sol_prefix.c_str(), state); if (!err_read) { state.Extrude1DMeshAndSolution(); } return err_read; } int ScriptReadParQuadrature(istream &scr, StreamState& state) { int np, scr_keep_attr, err_read; string mesh_prefix, quad_prefix; cout << "Script: pquadrature: " << flush; // read number of processors scr >> np; cout << "# processors: " << np << "; " << flush; // read the mesh prefix scr >> ws >> mesh_prefix; // mesh prefix (can't contain spaces) cout << "mesh prefix: " << mesh_prefix << "; " << flush; scr >> ws >> scr_keep_attr; if (scr_keep_attr) { cout << "(real attributes); " << flush; } else { cout << "(processor attributes); " << flush; } // read the quadrature prefix scr >> ws >> quad_prefix; cout << "quadrature prefix: " << quad_prefix << endl; err_read = ReadParMeshAndQuadFunction(np, mesh_prefix.c_str(), quad_prefix.c_str(), state); if (!err_read) { state.SetQuadSolution(); state.Extrude1DMeshAndSolution(); } return err_read; } int ScriptReadDisplMesh(istream &scr, StreamState& state) { StreamState meshstate; string word; cout << "Script: mesh: " << flush; scr >> ws >> word; { named_ifgzstream imesh(word.c_str()); if (!imesh) { cout << "Can not open mesh file: " << word << endl; return 1; } cout << word << endl; meshstate.SetMesh(new Mesh(imesh, 1, 0, state.fix_elem_orient)); } meshstate.Extrude1DMeshAndSolution(); Mesh* const m = meshstate.mesh.get(); if (init_nodes == NULL) { init_nodes = new Vector; meshstate.mesh->GetNodes(*init_nodes); state.SetMesh(NULL); state.SetGridFunction(NULL); } else { FiniteElementCollection *vfec = NULL; FiniteElementSpace *vfes; vfes = (FiniteElementSpace *)m->GetNodalFESpace(); if (vfes == NULL) { vfec = new LinearFECollection; vfes = new FiniteElementSpace(m, vfec, m->SpaceDimension()); } meshstate.SetGridFunction(new GridFunction(vfes)); GridFunction * const g = meshstate.grid_f.get(); if (vfec) { g->MakeOwner(vfec); } m->GetNodes(*g); if (g->Size() == init_nodes->Size()) { subtract(*init_nodes, *g, *g); } else { cout << "Script: incompatible meshes!" << endl; *g = 0.0; } state = std::move(meshstate); } return 0; } void ExecuteScriptCommand() { if (!script) { cout << "No script stream defined! (Bug?)" << endl; return; } istream &scr = *script; string word; int done_one_command = 0; while (!done_one_command) { scr >> ws; if (!scr.good()) { cout << "End of script." << endl; scr_level = 0; return; } if (scr.peek() == '#') { getline(scr, word); continue; } scr >> word; if (word == "{") { scr_level++; } else if (word == "}") { scr_level--; if (scr_level < 0) { scr_level = 0; } } else if (word == "solution" || word == "mesh" || word == "psolution" || word == "quadrature" || word == "pquadrature") { StreamState new_state; if (word == "solution") { if (ScriptReadSolution(scr, new_state)) { done_one_command = 1; continue; } } else if (word == "quadrature") { if (ScriptReadQuadrature(scr, new_state)) { done_one_command = 1; continue; } } else if (word == "mesh") { if (ScriptReadDisplMesh(scr, new_state)) { done_one_command = 1; continue; } if (new_state.mesh == NULL) { cout << "Script: unexpected 'mesh' command!" << endl; done_one_command = 1; continue; } } else if (word == "psolution") { if (ScriptReadParSolution(scr, new_state)) { done_one_command = 1; continue; } } else if (word == "pquadrature") { if (ScriptReadParQuadrature(scr, new_state)) { done_one_command = 1; continue; } } if (stream_state.SetNewMeshAndSolution(std::move(new_state), vs)) { MyExpose(); } else { cout << "Different type of mesh / solution." << endl; } } else if (word == "screenshot") { scr >> ws >> word; cout << "Script: screenshot: " << flush; if (Screenshot(word.c_str(), true)) { cout << "Screenshot(" << word << ") failed." << endl; done_one_command = 1; continue; } cout << "-> " << word << endl; if (scr_min_val > vs->GetMinV()) { scr_min_val = vs->GetMinV(); } if (scr_max_val < vs->GetMaxV()) { scr_max_val = vs->GetMaxV(); } } else if (word == "viewcenter") { scr >> vs->ViewCenterX >> vs->ViewCenterY; cout << "Script: viewcenter: " << vs->ViewCenterX << ' ' << vs->ViewCenterY << endl; MyExpose(); } else if (word == "perspective") { scr >> ws >> word; cout << "Script: perspective: " << word; if (word == "off") { vs->OrthogonalProjection = 1; } else if (word == "on") { vs->OrthogonalProjection = 0; } else { cout << '?'; } cout << endl; MyExpose(); } else if (word == "light") { scr >> ws >> word; cout << "Script: light: " << word; if (word == "off") { vs->SetLight(false); } else if (word == "on") { vs->SetLight(true); } else { cout << '?'; } cout << endl; MyExpose(); } else if (word == "view") { double theta, phi; scr >> theta >> phi; cout << "Script: view: " << theta << ' ' << phi << endl; vs->SetView(theta, phi); MyExpose(); } else if (word == "zoom") { double factor; scr >> factor; cout << "Script: zoom: " << factor << endl; vs->Zoom(factor); MyExpose(); } else if (word == "shading") { scr >> ws >> word; cout << "Script: shading: " << flush; VisualizationSceneScalarData::Shading s = VisualizationSceneScalarData::Shading::Invalid; if (word == "flat") { s = VisualizationSceneScalarData::Shading::Flat; } else if (word == "smooth") { s = VisualizationSceneScalarData::Shading::Smooth; } else if (word == "cool") { s = VisualizationSceneScalarData::Shading::Noncomforming; } if (s != VisualizationSceneScalarData::Shading::Invalid) { vs->SetShading(s, false); cout << word << endl; MyExpose(); } else { cout << word << " ?" << endl; } } else if (word == "subdivisions") { int t, b; scr >> t >> b; cout << "Script: subdivisions: " << flush; vs->SetRefineFactors(t, b); cout << t << ' ' << b << endl; MyExpose(); } else if (word == "valuerange") { double min, max; scr >> min >> max; cout << "Script: valuerange: " << flush; vs->SetValueRange(min, max); cout << min << ' ' << max << endl; MyExpose(); } else if (word == "autoscale") { scr >> ws >> word; cout << "Script: autoscale: " << word; if (word == "off") { vs->SetAutoscale(0); } else if (word == "on") { vs->SetAutoscale(1); } else if (word == "value") { vs->SetAutoscale(2); } else if (word == "mesh") { vs->SetAutoscale(3); } else { cout << '?'; } cout << endl; } else if (word == "levellines") { double min, max; int num; scr >> min >> max >> num; cout << "Script: levellines: " << flush; vs->SetLevelLines(min, max, num); vs->UpdateLevelLines(); cout << min << ' ' << max << ' ' << num << endl; MyExpose(); } else if (word == "axis_numberformat") { char delim; string axis_formatting; scr >> ws >> delim; getline(scr, axis_formatting, delim); cout << "Script: axis_numberformat: " << flush; vs->SetAxisNumberFormat(axis_formatting); cout << axis_formatting << endl; MyExpose(); } else if (word == "colorbar_numberformat") { char delim; string colorbar_formatting; scr >> ws >> delim; getline(scr, colorbar_formatting, delim); cout << "Script: colorbar_numberformat: " << flush; vs->SetColorbarNumberFormat(colorbar_formatting); cout << colorbar_formatting << endl; MyExpose(); } else if (word == "window") { scr >> window_x >> window_y >> window_w >> window_h; cout << "Script: window: " << window_x << ' ' << window_y << ' ' << window_w << ' ' << window_h << endl; MoveResizeWindow(window_x, window_y, window_w, window_h); MyExpose(); } else if (word == "keys") { scr >> stream_state.keys; cout << "Script: keys: '" << stream_state.keys << "'" << endl; // SendKeySequence(keys.c_str()); CallKeySequence(stream_state.keys.c_str()); MyExpose(); } else if (word == "palette") { int pal; scr >> pal; cout << "Script: palette: " << pal << endl; vs->palette.SetIndex(pal-1); MyExpose(); } else if (word == "palette_repeat") { int rpt_times; scr >> rpt_times; cout << "Script: palette_repeat: " << rpt_times << endl; vs->palette.SetRepeatTimes(rpt_times); vs->palette.Init(); MyExpose(); } else if (word == "toggle_attributes") { Array attr_list; cout << "Script: toggle_attributes:"; for (scr >> ws; scr.peek() != ';'; scr >> ws) { attr_list.Append(0); scr >> attr_list.Last(); if (attr_list.Size() <= 256) { cout << ' ' << attr_list.Last(); } else if (attr_list.Size() == 257) { cout << " ... " << flush; } } scr.get(); // read the end symbol: ';' cout << endl; vs->ToggleAttributes(attr_list); MyExpose(); } else if (word == "rotmat") { cout << "Script: rotmat:"; for (int i = 0; i < 16; i++) { scr >> vs->rotmat[i/4][i%4]; cout << ' ' << vs->rotmat[i/4][i%4]; } cout << endl; MyExpose(); } else if (word == "camera") { double cam[9]; cout << "Script: camera:"; for (int i = 0; i < 9; i++) { scr >> cam[i]; cout << ' ' << cam[i]; } cout << endl; vs->cam.Set(cam); MyExpose(); } else if (word == "scale") { double scale; cout << "Script: scale:"; scr >> scale; cout << ' ' << scale; cout << endl; vs->Scale(scale); MyExpose(); } else if (word == "translate") { double x, y, z; cout << "Script: translate:"; scr >> x >> y >> z; cout << ' ' << x << ' ' << y << ' ' << z; cout << endl; vs->Translate(x, y, z); MyExpose(); } else if (word == "plot_caption") { char delim; scr >> ws >> delim; getline(scr, plot_caption, delim); vs->PrepareCaption(); // turn on or off the caption MyExpose(); } else { cout << "Unknown command in script: " << word << endl; } done_one_command = 1; } } void ScriptControl(); void ScriptIdleFunc() { ExecuteScriptCommand(); if (scr_level == 0) { ScriptControl(); } } void ScriptControl() { if (scr_running) { scr_running = 0; RemoveIdleFunc(ScriptIdleFunc); } else { scr_running = 1; AddIdleFunc(ScriptIdleFunc); } } void PlayScript(istream &scr) { string word; scr_min_val = numeric_limits::infinity(); scr_max_val = -scr_min_val; // read initializing commands while (1) { scr >> ws; if (!scr.good()) { cout << "Error in script" << endl; return; } if (scr.peek() == '#') { getline(scr, word); continue; } scr >> word; if (word == "window") { scr >> window_x >> window_y >> window_w >> window_h; } else if (word == "solution") { if (ScriptReadSolution(scr, stream_state)) { return; } // start the visualization break; } else if (word == "quadrature") { if (ScriptReadQuadrature(scr, stream_state)) { return; } // start the visualization break; } else if (word == "psolution") { if (ScriptReadParSolution(scr, stream_state)) { return; } // start the visualization break; } else if (word == "pquadrature") { if (ScriptReadParQuadrature(scr, stream_state)) { return; } // start the visualization break; } else if (word == "mesh") { if (ScriptReadDisplMesh(scr, stream_state)) { return; } if (stream_state.mesh) { break; } } else { cout << "Unknown command in script: " << word << endl; } } scr_level = scr_running = 0; script = &scr; stream_state.keys.clear(); // Make sure the singleton object returned by GetMainThread() is // initialized from the main thread. GetMainThread(); std::thread worker_thread { [&](StreamState local_state) { // set the thread-local StreamState stream_state = std::move(local_state); if (c_plot_caption != string_none) { plot_caption = c_plot_caption; } if (GLVisInitVis((stream_state.grid_f->VectorDim() == 1) ? StreamState::FieldType::SCALAR : StreamState::FieldType::VECTOR, {})) { GetAppWindow()->setOnKeyDown(SDLK_SPACE, ScriptControl); GLVisStartVis(); } }, std::move(stream_state) }; SDLMainLoop(); worker_thread.join(); delete init_nodes; init_nodes = NULL; cout << "Script: min_val = " << scr_min_val << ", max_val = " << scr_max_val << endl; script = NULL; } struct Session { StreamCollection input_streams; StreamState state; StreamState::FieldType ft = StreamState::FieldType::UNKNOWN; std::thread handler; Session(bool fix_elem_orient, bool save_coloring) { state.fix_elem_orient = fix_elem_orient; state.save_coloring = save_coloring; } Session(StreamState::FieldType other_ft, StreamState other_state) : state(std::move(other_state)) , ft(other_ft) { } ~Session() = default; Session(Session&& from) = default; Session& operator= (Session&& from) = default; void StartSession() { auto funcThread = [](StreamState thread_state, StreamState::FieldType ftype, StreamCollection is) { // Set thread-local stream state stream_state = std::move(thread_state); if (c_plot_caption != string_none) { plot_caption = c_plot_caption; } if (GLVisInitVis(ftype, std::move(is))) { GLVisStartVis(); } }; handler = std::thread {funcThread, std::move(state), ft, std::move(input_streams)}; handler.detach(); } bool StartSavedSession(std::string stream_file) { unique_ptr ifs(new ifstream(stream_file)); if (!(*ifs)) { cout << "Can not open stream file: " << stream_file << endl; return false; } string data_type; *ifs >> data_type >> ws; ft = state.ReadStream(*ifs, data_type); input_streams.emplace_back(std::move(ifs)); StartSession(); return true; } }; void GLVisServer(int portnum, bool save_stream, bool fix_elem_orient, bool save_coloring) { std::vector current_sessions; string data_type; int viscount = 0; unsigned int nproc = 1, proc = 0; #ifdef MFEM_USE_GNUTLS unique_ptr state; unique_ptr params; if (secure) { state.reset(new GnuTLS_global_state); // state->set_log_level(1000); string home_dir(getenv("HOME")); string server_dir = home_dir + "/.config/glvis/server/"; #ifndef MFEM_USE_GNUTLS_X509 string pubkey = server_dir + "pubring.gpg"; string privkey = server_dir + "secring.gpg"; string trustedkeys = server_dir + "trusted-clients.gpg"; #else string pubkey = server_dir + "cert.pem"; string privkey = server_dir + "key.pem"; string trustedkeys = server_dir + "trusted-clients.pem"; #endif params.reset(new GnuTLS_session_params( *state, pubkey.c_str(), privkey.c_str(), trustedkeys.c_str(), GNUTLS_SERVER)); if (!params->status.good()) { cout << " public key = " << pubkey << '\n' << " private key = " << privkey << '\n' << " trusted keys = " << trustedkeys << endl; cout << "Error setting GLVis server parameters.\n" "Generate your GLVis keys with:" " bash glvis-keygen.sh [\"Your Name\"] [\"Your Email\"]" << endl; return; } } #endif const int backlog = 128; socketserver server(portnum, backlog); if (server.good()) { cout << "Waiting for data on port " << portnum << " ..." << endl; } else { cout << "Server already running on port " << portnum << ".\n" << endl; exit(2); } while (1) { unique_ptr isock; #ifndef MFEM_USE_GNUTLS isock.reset(new socketstream); #else isock.reset(secure ? new socketstream(*params) : new socketstream(false)); #endif vector> input_streams; while (server.accept(*isock) < 0) { #ifdef GLVIS_DEBUG cout << "GLVis: server.accept(...) failed." << endl; #endif } *isock >> data_type >> ws; if (save_stream) { viscount++; } int par_data = 0; if (data_type == "parallel") { par_data = 1; unsigned int np = 0; do { *isock >> nproc >> proc; #ifdef GLVIS_DEBUG cout << "new connection: parallel " << nproc << ' ' << proc << endl; #endif if (np == 0) { if (nproc <= 0) { cout << "Invalid number of processors: " << nproc << endl; mfem_error(); } input_streams.resize(nproc); } else { if (nproc != input_streams.size()) { cout << "Unexpected number of processors: " << nproc << ", expected: " << input_streams.size() << endl; mfem_error(); } } if (proc >= nproc) { cout << "Invalid processor rank: " << proc << ", number of processors: " << nproc << endl; mfem_error(); } if (input_streams[proc]) { cout << "Second connection attempt from processor rank: " << proc << endl; mfem_error(); } input_streams[proc] = std::move(isock); #ifndef MFEM_USE_GNUTLS isock.reset(new socketstream); #else isock.reset(secure ? new socketstream(*params) : new socketstream(false)); #endif np++; if (np == nproc) { break; } // read next available socket stream while (server.accept(*isock) < 0) { #ifdef GLVIS_DEBUG cout << "GLVis: server.accept(...) failed." << endl; #endif } *isock >> data_type >> ws; // "parallel" if (data_type != "parallel") { cout << "Expected keyword \"parallel\", got \"" << data_type << '"' << endl; mfem_error(); } } while (1); } Session new_session(fix_elem_orient, save_coloring); constexpr int tmp_filename_size = 50; char tmp_file[tmp_filename_size]; if (save_stream) { snprintf(tmp_file, tmp_filename_size, "glvis-saved.%04d", viscount); ofstream ofs(tmp_file); if (!par_data) { ofs << data_type << '\n'; ofs << isock->rdbuf(); isock->close(); } else { new_session.state.ReadStreams(input_streams); new_session.state.WriteStream(ofs); } ofs.close(); cout << "Data saved in " << tmp_file << endl; new_session.StartSavedSession(tmp_file); } else { if (!par_data) { new_session.ft = new_session.state.ReadStream(*isock, data_type); input_streams.emplace_back(std::move(isock)); } else { new_session.ft = new_session.state.ReadStreams(input_streams); } // Pass ownership of input streams into session object new_session.input_streams = std::move(input_streams); new_session.StartSession(); } current_sessions.emplace_back(std::move(new_session)); } } int main (int argc, char *argv[]) { #ifdef _WIN32 // Call needed to avoid SDL_Init failure when not substituting main() for // SDL_main(). SDL_SetMainReady(); #endif // variables for command line arguments int np = 0; bool save_stream = false; const char *stream_file = string_none; const char *script_file = string_none; const char *font_name = string_default; int portnum = 19916; int multisample = GetMultisample(); double line_width = GetLineWidth(); double ms_line_width = GetLineWidthMS(); int geom_ref_type = Quadrature1D::ClosedUniform; bool legacy_gl_ctx = false; bool enable_hidpi = true; OptionsParser args(argc, argv); args.AddOption(&mesh_file, "-m", "--mesh", "Mesh file to visualize."); args.AddOption(&gfunc_file, "-g", "--grid-function", "Solution (GridFunction) file to visualize."); args.AddOption(&gf_component, "-gc", "--grid-function-component", "Select a grid function component, [0-) or" " -1 for all."); args.AddOption(&qfunc_file, "-q", "--quadrature-function", "Quadrature function file to visualize."); args.AddOption(&qf_component, "-qc", "--quadrature-function-component", "Select a quadrature function component, [0-) or" " -1 for all."); args.AddOption(&sol_file, "-s", "--scalar-solution", "Scalar solution (vertex values) file to visualize."); args.AddOption(&vec_sol_file, "-v", "--vector-solution", "Vector solution (vertex values) file to visualize."); args.AddOption(&np, "-np", "--num-proc", "Load mesh/solution from multiple processors."); args.AddOption(&pad_digits, "-d", "--pad-digits", "Number of digits used for processor ranks in file names."); args.AddOption(&script_file, "-run", "--run-script", "Run a GLVis script file."); args.AddOption(&arg_keys, "-k", "--keys", "Execute key shortcut commands in the GLVis window."); args.AddOption(&stream_state.fix_elem_orient, "-fo", "--fix-orientations", "-no-fo", "--dont-fix-orientations", "Attempt to fix the orientations of inverted elements."); args.AddOption(&stream_state.keep_attr, "-a", "--real-attributes", "-ap", "--processor-attributes", "When opening a parallel mesh, use the real mesh attributes" " or replace them with the processor rank."); args.AddOption(&geom_ref_type, "-grt", "--geometry-refiner-type", "Set of points to use when refining geometry:" " 3 = uniform, 1 = Gauss-Lobatto, (see mfem::Quadrature1D)."); args.AddOption(&stream_state.save_coloring, "-sc", "--save-coloring", "-no-sc", "--dont-save-coloring", "Save the mesh coloring generated when opening only a mesh."); args.AddOption(&portnum, "-p", "--listen-port", "Specify the port number on which to accept connections."); args.AddOption(&secure, "-sec", "--secure-sockets", "-no-sec", "--standard-sockets", "Enable or disable GnuTLS secure sockets."); args.AddOption(&save_stream, "-save", "--save-stream", "-no-save", "--dont-save-stream", "In server mode, save incoming data to a file before" " visualization."); args.AddOption(&stream_file, "-saved", "--saved-stream", "Load a GLVis stream saved to a file."); args.AddOption(&window_w, "-ww", "--window-width", "Set the window width."); args.AddOption(&window_h, "-wh", "--window-height", "Set the window height."); args.AddOption(&window_title, "-wt", "--window-title", "Set the window title."); args.AddOption(&c_plot_caption, "-c", "--plot-caption", "Set the plot caption (visible when colorbar is visible)."); args.AddOption(&font_name, "-fn", "--font", "Set the font: [[:style=