diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7625f4f..cd46295 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,137 +1,142 @@ name: CI on: workflow_dispatch: pull_request: push: branches: - master jobs: standard: strategy: fail-fast: false matrix: runs-on: [ubuntu-latest, macos-latest, windows-latest] include: - runs-on: ubuntu-latest config: -DBUILD_TESTS=1 -DBUILD_EXAMPLES=1 conda: docs/examples/environment.yaml prop: tests & examples - runs-on: macos-latest - config: -DBUILD_TESTS=1 -DBUILD_EXAMPLES=0 + config: -DBUILD_TESTS=1 -DBUILD_EXAMPLES=0 -DBUILD_DOCS=1 conda: environment.yaml prop: tests - runs-on: windows-latest config: -DBUILD_TESTS=1 -DBUILD_EXAMPLES=0 conda: environment.yaml prop: tests defaults: run: shell: bash -l {0} name: "${{ matrix.runs-on }} • x64 ${{ matrix.args }}" runs-on: ${{ matrix.runs-on }} steps: - name: Basic GitHub action setup uses: actions/checkout@v2 - name: Set conda environment if: runner.os != 'Windows' uses: mamba-org/provision-with-micromamba@main with: environment-file: ${{ matrix.conda }} environment-name: myenv - name: Set conda environment if: runner.os == 'Windows' uses: conda-incubator/setup-miniconda@v2 with: mamba-version: "*" channels: conda-forge,defaults channel-priority: true environment-file: ${{ matrix.conda }} activate-environment: myenv auto-activate-base: false - name: Set dummy version run: echo "SETUPTOOLS_SCM_PRETEND_VERSION=ci" >> $GITHUB_ENV - name: Configure using CMake (!Windows) if: runner.os != 'Windows' run: cmake -Bbuild ${{ matrix.config }} - name: Configure using CMake (Windows) if: runner.os == 'Windows' run: | conda install -c conda-forge clang_win-64 ninja cmake -Bbuild -G Ninja ${{ matrix.config }} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - name: Build C++ ${{ matrix.prop }} working-directory: build run: cmake --build . - name: Run C++ ${{ matrix.prop }} working-directory: build run: ctest --output-on-failure - name: Build and install Python module run: | python setup.py build python setup.py install - name: Run Python tests working-directory: test/basic-python run: | python version.py python MeshQuad4.py + - name: Build doxygen-docs (error on warning) + if: runner.os == 'macOS' + working-directory: build + run: make docs + py: strategy: fail-fast: false matrix: runs-on: [windows-latest] include: - runs-on: windows-latest conda: .ci_environment_py.yaml defaults: run: shell: bash -l {0} name: "${{ matrix.runs-on }} • x64 ${{ matrix.args }} • py" runs-on: ${{ matrix.runs-on }} steps: - name: Basic GitHub action setup uses: actions/checkout@v2 - name: Set conda environment "test" uses: conda-incubator/setup-miniconda@v2 with: mamba-version: "*" channels: conda-forge,defaults channel-priority: true environment-file: ${{ matrix.conda }} activate-environment: test auto-activate-base: false - name: Build and install Python module run: | python setup.py build python setup.py install - name: Run Python tests working-directory: test/basic-python run: | python version.py python MeshQuad4.py diff --git a/docs/doxystyle/doxygen-awesome.css b/docs/doxystyle/doxygen-awesome.css index d80b767..3fc49ef 100644 --- a/docs/doxystyle/doxygen-awesome.css +++ b/docs/doxystyle/doxygen-awesome.css @@ -1,1371 +1,1367 @@ /** Doxygen Awesome https://github.com/jothepro/doxygen-awesome-css MIT License Copyright (c) 2021 jothepro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ +*/ :root { /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ --primary-color: #1982d2; --primary-dark-color: #00559f; --primary-light-color: #7aabd6; --primary-lighter-color: #cae1f1; --primary-lightest-color: #e9f1f8; /* page base colors */ --page-background-color: white; --page-foreground-color: #2c3e50; --page-secondary-foreground-color: #67727e; /* color for all separators on the website: hr, borders, ... */ --separator-color: #dedede; /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ --border-radius-large: 8px; --border-radius-small: 4px; --border-radius-medium: 6px; /* default spacings. Most compontest reference these values for spacing, to provide uniform spacing on the page. */ --spacing-small: 5px; --spacing-medium: 10px; --spacing-large: 16px; /* default box shadow used for raising an element above the normal content. Used in dropdowns, Searchresult, ... */ --box-shadow: 0 2px 10px 0 rgba(0,0,0,.1); --odd-color: rgba(0,0,0,.03); /* font-families. will affect all text on the website * font-family: the normal font for text, headlines, menus * font-family-monospace: used for preformatted text in memtitle, code, fragments */ --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; --font-family-monospace: source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace; /* font sizes */ --page-font-size: 15.6px; --navigation-font-size: 14.4px; --code-font-size: 14.4px; /* affects code, fragment */ --title-font-size: 22px; /* content text properties. These only affect the page content, not the navigation or any other ui elements */ --content-line-height: 27px; /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ --content-maxwidth: 900px; /* colors for various content boxes: @warning, @note, @deprecated @bug */ --warning-color: #fca49b; --warning-color-dark: #b61825; --warning-color-darker: #75070f; --note-color: rgba(255,229,100,.3); --note-color-dark: #c39900; --note-color-darker: #8d7400; --deprecated-color: rgb(214, 216, 224); --deprecated-color-dark: #5b6269; --deprecated-color-darker: #43454a; --bug-color: rgb(246, 208, 178); --bug-color-dark: #a53a00; --bug-color-darker: #5b1d00; --invariant-color: #b7f8d0; --invariant-color-dark: #00ba44; --invariant-color-darker: #008622; /* blockquote colors */ --blockquote-background: #f5f5f5; --blockquote-foreground: #727272; /* table colors */ --tablehead-background: #f1f1f1; --tablehead-foreground: var(--page-foreground-color); /* menu-display: block | none * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. * `GENERATE_TREEVIEW` MUST be enabled! */ --menu-display: block; --menu-focus-foreground: var(--page-background-color); --menu-focus-background: var(--primary-color); --menu-selected-background: rgba(0,0,0,.05); --header-background: var(--page-background-color); --header-foreground: var(--page-foreground-color); /* searchbar colors */ --searchbar-background: var(--side-nav-background); --searchbar-foreground: var(--page-foreground-color); /* searchbar size * (`searchbar-width` is only applied on screens >= 768px. * on smaller screens the searchbar will always fill the entire screen width) */ --searchbar-height: 33px; --searchbar-width: 210px; /* code block colors */ --code-background: #f5f5f5; --code-foreground: var(--page-foreground-color); /* fragment colors */ --fragment-background: #282c34; --fragment-foreground: #fff; --fragment-keyword: #cc99cd; --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; --fragment-token: #7ec699; --fragment-comment: #999; --fragment-link: #98c0e3; --fragment-preprocessor: #65cabe; --fragment-linenumber-color: #ccc; --fragment-linenumber-background: #35393c; - --fragment-whitespace: nowrap; + --fragment-lineheight: 20px; /* sidebar navigation (treeview) colors */ --side-nav-background: var(--page-background-color); --side-nav-foreground: var(--page-foreground-color); --side-nav-arrow-color: var(--page-background-color); /* height of an item in any tree / collapsable table */ --tree-item-height: 30px; - } @media screen and (max-width: 767px) { :root { --page-font-size: 16px; --navigation-font-size: 16px; --code-font-size: 15px; /* affects code, fragment */ --title-font-size: 22px; } } @media (prefers-color-scheme: dark) { :root { --primary-color: #00559f; --primary-dark-color: #1982d2; --primary-light-color: #4779ac; --primary-lighter-color: #191e21; --primary-lightest-color: #191a1c; --box-shadow: 0 2px 10px 0 rgba(0,0,0,.35); --odd-color: rgba(0,0,0,.1); --menu-selected-background: rgba(0,0,0,.4); --page-background-color: #1C1D1F; --page-foreground-color: #d2dbde; --page-secondary-foreground-color: #859399; --separator-color: #000000; --side-nav-background: #252628; --code-background: #2a2c2f; --tablehead-background: #2a2c2f; --blockquote-background: #1f2022; --blockquote-foreground: #77848a; --warning-color: #b61825; --warning-color-dark: #510a02; --warning-color-darker: #f5b1aa; --note-color: rgb(255, 183, 0); --note-color-dark: #9f7300; --note-color-darker: #fff6df; --deprecated-color: rgb(88, 90, 96); --deprecated-color-dark: #262e37; --deprecated-color-darker: #a0a5b0; --bug-color: rgb(248, 113, 0); --bug-color-dark: #812a00; --bug-color-darker: #ffd3be; } } body { color: var(--page-foreground-color); background-color: var(--page-background-color); font-size: var(--page-font-size); } body, table, div, p, dl, #nav-tree .label, .title, .sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, .SelectItem, #MSearchField, .navpath li.navelem a, .navpath li.navelem a:hover { font-family: var(--font-family); } h1, h2, h3, h4, h5 { margin-top: .9em; font-weight: 600; line-height: initial; } p, div, table, dl { font-size: var(--page-font-size); } a, a.el:visited, a.el:hover, a.el:focus, a.el:active { color: var(--primary-dark-color); } /* - Title & top navigation + Title and top navigation */ + #top { background: var(--header-background); border-bottom: 1px solid var(--separator-color); } @media screen and (min-width: 768px) { #top { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; } } #main-nav { flex-grow: 5; padding: var(--spacing-small) var(--spacing-medium); } #titlearea { width: auto; padding: var(--spacing-medium) var(--spacing-large); background: none; color: var(--header-foreground); border-bottom: none; } @media screen and (max-width: 767px) { #titlearea { padding-bottom: var(--spacing-small); } - } #titlearea table tbody tr { height: auto !important; } #projectname { font-size: var(--title-font-size); font-weight: 600; } #projectnumber { font-family: inherit; font-size: 60%; } #projectbrief { font-family: inherit; font-size: 80%; } #projectlogo { vertical-align: middle; } #projectlogo img { max-height: calc(var(--title-font-size) * 2); margin-right: var(--spacing-small); } .sm-dox, .tabs, .tabs2, .tabs3 { background: none; padding: 0; } .tabs, .tabs2, .tabs3 { border-bottom: 1px solid var(--separator-color); margin-bottom: -1px; } @media screen and (max-width: 767px) { .sm-dox a span.sub-arrow { background: var(--code-background); } } - @media screen and (min-width: 768px) { .sm-dox li, .tablist li { display: var(--menu-display); } .sm-dox a span.sub-arrow { border-color: var(--header-foreground) transparent transparent transparent; } .sm-dox a:hover span.sub-arrow { border-color: var(--menu-focus-foreground) transparent transparent transparent; } .sm-dox ul a span.sub-arrow { border-color: transparent transparent transparent var(--header-foreground); } .sm-dox ul a:hover span.sub-arrow { border-color: transparent transparent transparent var(--menu-focus-foreground); } - - } .sm-dox ul { background: var(--page-background-color); box-shadow: var(--box-shadow); border: 1px solid var(--separator-color); border-radius: var(--border-radius-medium) !important; padding: var(--spacing-small); animation: ease-out 150ms slideInMenu; } @keyframes slideInMenu { from { opacity: 0; transform: translate(0px, -2px); } to { opacity: 1; transform: translate(0px, 0px); } } .sm-dox ul a { color: var(--page-foreground-color); background: var(--page-background-color); font-size: var(--navigation-font-size); } .sm-dox>li>ul:after { border-bottom-color: var(--page-background-color) !important; } .sm-dox>li>ul:before { border-bottom-color: var(--separator-color) !important; } .sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus { font-size: var(--navigation-font-size); color: var(--menu-focus-foreground); text-shadow: none; background-color: var(--menu-focus-background); border-radius: var(--border-radius-small) !important; } .sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a { text-shadow: none; background: transparent; background-image: none !important; color: var(--header-foreground); font-weight: normal; font-size: var(--navigation-font-size); } .sm-dox a:focus { outline: auto; } .sm-dox a:hover, .sm-dox a:active, .tablist li a:hover { text-shadow: none; font-weight: normal; background: var(--menu-focus-background); color: var(--menu-focus-foreground); border-radius: var(--border-radius-small) !important; font-size: var(--navigation-font-size); } .tablist li.current { border-radius: var(--border-radius-small); background: var(--menu-selected-background); } .tablist li { margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); } .tablist a { padding: 0 var(--spacing-large); } /* Search box */ #MSearchBox { height: var(--searchbar-height); background: var(--searchbar-background); border-radius: var(--searchbar-height); border: 1px solid var(--separator-color); overflow: hidden; width: var(--searchbar-width); position: relative; box-shadow: none; display: block; margin-top: 0; } .left #MSearchSelect { left: 0; } .tabs .left #MSearchSelect { padding-left: 0; } .tabs #MSearchBox { position: absolute; right: var(--spacing-medium); } @media screen and (max-width: 767px) { .tabs #MSearchBox { position: relative; right: 0; margin-left: var(--spacing-medium); margin-top: 0; } } - - #MSearchSelectWindow, #MSearchResultsWindow { z-index: 9999; } #MSearchBox.MSearchBoxActive { border-color: var(--primary-color); box-shadow: inset 0 0 0 1px var(--primary-color); } #main-menu > li:last-child { margin-right: 0; } @media screen and (max-width: 767px) { #main-menu > li:last-child { height: 50px; } } #MSearchField { font-size: var(--navigation-font-size); height: calc(var(--searchbar-height) - 2px); background: transparent; width: calc(var(--searchbar-width) - 64px); } .MSearchBoxActive #MSearchField { color: var(--searchbar-foreground); } #MSearchSelect { top: calc(calc(var(--searchbar-height) / 2) - 11px); } .left #MSearchSelect { padding-left: 8px; } #MSearchBox span.left, #MSearchBox span.right { background: none; } - #MSearchBox span.right { padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); } .tabs #MSearchBox span.right { top: calc(calc(var(--searchbar-height) / 2) - 12px); } @keyframes slideInSearchResults { from { opacity: 0; transform: translate(0, 15px); } to { opacity: 1; transform: translate(0, 20px); } } #MSearchResultsWindow { left: auto !important; right: var(--spacing-medium); border-radius: var(--border-radius-large); border: 1px solid var(--separator-color); transform: translate(0, 20px); box-shadow: var(--box-shadow); animation: ease-out 280ms slideInSearchResults; background: var(--page-background-color); } iframe#MSearchResults { background: var(--page-background-color); margin: 4px; } #MSearchSelectWindow { border: 1px solid var(--separator-color); border-radius: var(--border-radius-medium); box-shadow: var(--box-shadow); background: var(--page-background-color); } #MSearchSelectWindow a.SelectItem { font-size: var(--navigation-font-size); line-height: var(--content-line-height); margin: 0 var(--spacing-small); border-radius: var(--border-radius-small); color: var(--page-foreground-color); } #MSearchSelectWindow a.SelectItem:hover { background: var(--menu-focus-background); color: var(--menu-focus-foreground); } - - @media screen and (max-width: 767px) { #MSearchBox { margin-top: var(--spacing-medium); margin-bottom: var(--spacing-medium); width: calc(100vw - 30px); } #main-menu > li:last-child { float: none !important; } #MSearchField { width: calc(100vw - 95px); } @keyframes slideInSearchResultsMobile { from { opacity: 0; transform: translate(0, 15px); } to { opacity: 1; transform: translate(0, 20px); } } #MSearchResultsWindow { left: var(--spacing-medium) !important; right: var(--spacing-medium); overflow: auto; transform: translate(0, 20px); animation: ease-out 280ms slideInSearchResultsMobile; } - - } /* Tree view */ #side-nav { padding: 0 !important; background: var(--side-nav-background); } @media screen and (max-width: 767px) { #side-nav { display: none; } #doc-content { margin-left: 0 !important; height: auto !important; padding-bottom: calc(2 * var(--spacing-large)); } } #nav-tree { background: transparent; } #nav-tree .label { font-size: var(--navigation-font-size); } #nav-tree .item { height: var(--tree-item-height); line-height: var(--tree-item-height); } #nav-sync { top: 12px !important; right: 12px; } #nav-tree .selected { text-shadow: none; background-image: none; background-color: transparent; box-shadow: inset 4px 0 0 0 var(--primary-dark-color); } #nav-tree a { color: var(--side-nav-foreground); } #nav-tree a:focus { outline-style: auto; } .arrow { color: var(--primary-light-color); font-family: serif; height: auto; text-align: right; } #nav-tree .arrow { opacity: 0; } #nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow { opacity: 1; } #nav-tree .selected a { color: var(--primary-dark-color); font-weight: bolder; } .ui-resizable-e { background: var(--separator-color); width: 1px; } -/** - content +/* + Contents */ div.header { border-bottom: 1px solid var(--separator-color); background-color: var(--page-background-color); background-image: none; } div.contents, div.header .title, div.header .summary { max-width: var(--content-maxwidth); } div.contents, div.header .title { line-height: initial; margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; } div.header .summary { margin: var(--spacing-medium) auto 0 auto; } div.headertitle { padding: 0; } div.header .title { font-weight: 600; font-size: 210%; padding: var(--spacing-medium) var(--spacing-large); word-break: break-word; } div.header .summary { width: auto; display: block; float: none; padding: 0 var(--spacing-large); } td.memSeparator { border-color: var(--separator-color); } .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background: var(--code-background); } .mdescRight { color: var(--page-secondary-foreground-color); } span.mlabel { background: var(--primary-color); border: none; padding: 4px 9px; border-radius: 12px; margin-right: var(--spacing-medium); } span.mlabel:last-of-type { margin-right: 2px; } div.contents { padding: 0 var(--spacing-large); } div.contents p, div.contents li { line-height: var(--content-line-height); } div.contents div.dyncontent { margin: var(--spacing-medium) 0; } @media (prefers-color-scheme: dark) { div.contents div.dyncontent img { filter: hue-rotate(180deg) invert(); } } h2.groupheader { border-bottom: 1px solid var(--separator-color); color: var(--page-foreground-color); } blockquote { padding: var(--spacing-small) var(--spacing-medium); background: var(--blockquote-background); color: var(--blockquote-foreground); border-left: 2px solid var(--blockquote-foreground); margin: 0; } blockquote p { margin: var(--spacing-small) 0 var(--spacing-medium) 0; } .paramname { color: var(--primary-dark-color); } .glow { text-shadow: 0 0 15px var(--primary-light-color) !important; } .alphachar a { color: var(--page-foreground-color); } /* -toc + Table of Contents */ - - div.toc { background-color: var(--side-nav-background); border: 1px solid var(--separator-color); border-radius: var(--border-radius-medium); box-shadow: var(--box-shadow); padding: 0 var(--spacing-large); margin: 0 0 var(--spacing-medium) var(--spacing-medium); } div.toc h3 { color: var(--side-nav-foreground); font-size: var(--navigation-font-size); margin: var(--spacing-large) 0; } div.toc li { font-size: var(--navigation-font-size); padding: 0; background: none; } div.toc li:before { content: '↓'; font-weight: 800; font-family: var(--font-family); margin-right: var(--spacing-small); color: var(--side-nav-foreground); opacity: .4; } div.toc ul li.level1 { margin: 0; } div.toc ul li.level2, div.toc ul li.level3 { margin-top: 0; } @media screen and (max-width: 767px) { div.toc { float: none; width: auto; margin: 0 0 var(--spacing-medium) 0; } } /* -code & fragment + Code & Fragments */ code, div.fragment, pre.fragment { border-radius: var(--border-radius-small); border: none; overflow: hidden; } code { display: inline; background: var(--code-background); color: var(--code-foreground); padding: 2px 6px; word-break: break-word; } div.fragment, pre.fragment { margin: var(--spacing-medium) 0; padding: 14px 16px; background: var(--fragment-background); color: var(--fragment-foreground); overflow-x: auto; } @media screen and (max-width: 767px) { div.fragment, pre.fragment { border-top-right-radius: 0; border-bottom-right-radius: 0; } .contents > div.fragment, .textblock > div.fragment, .textblock > pre.fragment { margin: var(--spacing-medium) calc(0px - var(--spacing-large)); border-radius: 0; } .textblock li > .fragment { margin: var(--spacing-medium) calc(0px - var(--spacing-large)); } .memdoc li > .fragment { margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); } .memdoc > div.fragment, .memdoc > pre.fragment, dl dd > div.fragment, dl dd pre.fragment { margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); border-radius: 0; } } -code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span { +code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span { font-family: var(--font-family-monospace); - font-size: var(--code-font-size); - line-height: inherit; + font-size: var(--code-font-size) !important; } -div.fragment, div.fragment .line, div.fragment span { - white-space: var(--fragment-whitespace); +div.fragment { + line-height: 0; } div.line:after { - content: ''; + margin-right: var(--spacing-medium); +} + +div.fragment .line, pre.fragment { + white-space: pre; + word-wrap: initial; + line-height: var(--fragment-lineheight); } div.fragment span.keyword { color: var(--fragment-keyword); } div.fragment span.keywordtype { color: var(--fragment-keywordtype); } +div.fragment span.keywordflow { + color: var(--fragment-keywordflow); +} + div.fragment span.stringliteral { color: var(--fragment-token) } div.fragment span.comment { color: var(--fragment-comment); } div.fragment a.code { color: var(--fragment-link); } div.fragment span.preprocessor { color: var(--fragment-preprocessor); } div.fragment span.lineno { display: inline-block; width: 27px; border-right: none; background: var(--fragment-linenumber-background); color: var(--fragment-linenumber-color); } div.fragment span.lineno a { background: none; color: var(--fragment-link); } div.fragment .line:first-child .lineno { box-shadow: -9999px 0px 0 9999px var(--fragment-linenumber-background), -9998px 0px 0 9999px rgba(0,0,0,.3); } /* -dl warning, attention, note, deprecated, bug, ... + dl warning, attention, note, deprecated, bug, ... */ dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre { padding: var(--spacing-medium); margin: var(--spacing-medium) 0; color: var(--page-background-color); overflow: hidden; margin-left: 0; border-radius: var(--border-radius-small); } dl.section dd { margin-bottom: 2px; } dl.warning, dl.attention { background: var(--warning-color); border-left: 8px solid var(--warning-color-dark); color: var(--warning-color-darker); } dl.warning dt, dl.attention dt { color: var(--warning-color-dark); } dl.note { background: var(--note-color); border-left: 8px solid var(--note-color-dark); color: var(--note-color-darker); } dl.note dt { color: var(--note-color-dark); } dl.bug { background: var(--bug-color); border-left: 8px solid var(--bug-color-dark); color: var(--bug-color-darker); } dl.bug dt a { color: var(--bug-color-dark) !important; } dl.deprecated { background: var(--deprecated-color); border-left: 8px solid var(--deprecated-color-dark); color: var(--deprecated-color-darker); } dl.deprecated dt a { color: var(--deprecated-color-dark) !important; } dl.section dd, dl.bug dd, dl.deprecated dd { margin-inline-start: 0px; } dl.invariant, dl.pre { background: var(--invariant-color); border-left: 8px solid var(--invariant-color-dark); color: var(--invariant-color-darker); } /* -memitem + memitem */ div.memdoc, div.memproto, h2.memtitle { box-shadow: none; background-image: none; border: none; } div.memdoc { padding: 0 var(--spacing-medium); background: var(--page-background-color); } h2.memtitle, div.memitem { border: 1px solid var(--separator-color); } div.memproto, h2.memtitle { background: var(--code-background); text-shadow: none; } h2.memtitle { font-weight: 500; font-family: monospace, fixed; border-bottom: none; border-top-left-radius: var(--border-radius-medium); border-top-right-radius: var(--border-radius-medium); word-break: break-all; } a:target + h2.memtitle, a:target + h2.memtitle + div.memitem { border-color: var(--primary-light-color); } a:target + h2.memtitle { box-shadow: -3px -3px 3px 0 var(--primary-lightest-color), 3px -3px 3px 0 var(--primary-lightest-color); } a:target + h2.memtitle + div.memitem { box-shadow: 0 0 10px 0 var(--primary-lighter-color); } div.memitem { border-top-right-radius: var(--border-radius-medium); border-bottom-right-radius: var(--border-radius-medium); border-bottom-left-radius: var(--border-radius-medium); overflow: hidden; display: block !important; } div.memdoc { border-radius: 0; } div.memproto { border-radius: 0 var(--border-radius-small) 0 0; overflow: auto; border-bottom: 1px solid var(--separator-color); padding: var(--spacing-medium); margin-bottom: -1px; } div.memtitle { border-top-right-radius: var(--border-radius-medium); border-top-left-radius: var(--border-radius-medium); } div.memproto table.memname { font-family: monospace, fixed; color: var(--page-foreground-color); } table.mlabels, table.mlabels > tbody { display: block; } td.mlabels-left { width: auto; } table.mlabels > tbody > tr:first-child { display: flex; justify-content: space-between; flex-wrap: wrap; } .memname, .memitem span.mlabels { margin: 0 } + /* -reflist + reflist */ dl.reflist { border-radius: var(--border-radius-medium); border: 1px solid var(--separator-color); overflow: hidden; padding: 0; } dl.reflist dt, dl.reflist dd { box-shadow: none; text-shadow: none; background-image: none; border: none; padding: 12px; } dl.reflist dt { border-radius: 0; background: var(--code-background); border-bottom: 1px solid var(--separator-color); color: var(--page-foreground-color) } dl.reflist dd { background: none; } /* -table + Table */ table.markdownTable, table.fieldtable { width: 100%; border: 1px solid var(--separator-color); margin: var(--spacing-medium) 0; } table.fieldtable { box-shadow: none; border-radius: var(--border-radius-small); } th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { background: var(--tablehead-background); color: var(--tablehead-foreground); font-weight: 600; } table.markdownTable td, table.markdownTable th, table.fieldtable dt { border: 1px solid var(--separator-color); padding: var(--spacing-small) var(--spacing-medium); } table.fieldtable th { font-size: var(--page-font-size); font-weight: 600; background-image: none; background-color: var(--tablehead-background); color: var(--tablehead-foreground); border-bottom: 1px solid var(--separator-color); } .fieldtable td.fieldtype, .fieldtable td.fieldname { border-bottom: 1px solid var(--separator-color); border-right: 1px solid var(--separator-color); } .fieldtable td.fielddoc { border-bottom: 1px solid var(--separator-color); } .memberdecls td.glow, .fieldtable tr.glow { background-color: var(--primary-light-color); box-shadow: 0 0 15px var(--primary-lighter-color); } table.memberdecls { display: block; overflow-x: auto; overflow-y: hidden; } /* -hr + Horizontal Rule */ hr { margin-top: var(--spacing-large); margin-bottom: var(--spacing-large); border-top:1px solid var(--separator-color); } .contents hr { box-shadow: var(--content-maxwidth) 0 0 0 var(--separator-color), calc(0px - var(--content-maxwidth)) 0 0 0 var(--separator-color); - } .contents img { max-width: 100%; } /* - directories + Directories */ div.directory { border-top: 1px solid var(--separator-color); border-bottom: 1px solid var(--separator-color); width: auto; } table.directory { font-family: var(--font-family); font-size: var(--page-font-size); font-weight: normal; } .directory td.entry { padding: var(--spacing-small); display: flex; align-items: center; } .directory tr.even { background-color: var(--odd-color); } .icona { width: auto; height: auto; margin: 0 var(--spacing-small); } .icon { background: var(--primary-dark-color); width: 18px; height: 18px; line-height: 18px; } .iconfopen, .icondoc, .iconfclosed { background-position: center; margin-bottom: 0; } .icondoc { filter: saturate(0.2); } @media screen and (max-width: 767px) { div.directory { margin-left: calc(0px - var(--spacing-medium)); margin-right: calc(0px - var(--spacing-medium)); } } @media (prefers-color-scheme: dark) { .iconfopen, .iconfclosed { filter: hue-rotate(180deg) invert(); } } /* -class list + Class list */ .classindex dl.odd { background: var(--odd-color); border-radius: var(--border-radius-small); } @media screen and (max-width: 767px) { .classindex { margin: 0 calc(0px - var(--spacing-small)); } } - /* - footer / nav-path + Footer and nav-path */ #nav-path { margin-bottom: -1px; width: 100%; } #nav-path ul { background-image: none; background: var(--page-background-color); border: none; border-top: 1px solid var(--separator-color); border-bottom: 1px solid var(--separator-color); font-size: var(--navigation-font-size); } img.footer { width: 60px; } .navpath li.footer { color: var(--page-secondary-foreground-color); } address.footer { margin-bottom: var(--spacing-large); } #nav-path li.navelem { background-image: none; display: flex; align-items: center; } .navpath li.navelem a { text-shadow: none; display: inline-block; color: var(--primary-dark-color) } li.navelem { padding: 0; margin-left: -8px; } li.navelem:first-child { margin-left: var(--spacing-large); } li.navelem:first-child:before { display: none; } #nav-path li.navelem:after { content: ''; border: 5px solid var(--page-background-color); border-bottom-color: transparent; border-right-color: transparent; border-top-color: transparent; transform: scaleY(4.2); z-index: 10; margin-left: 6px; } #nav-path li.navelem:before { content: ''; border: 5px solid var(--separator-color); border-bottom-color: transparent; border-right-color: transparent; border-top-color: transparent; transform: scaleY(3.2); margin-right: var(--spacing-small); } @media (prefers-color-scheme: dark) { #nav-path li.navelem:after { text-shadow: 3px 0 0 var(--separator-color), 8px 0 6px rgba(0,0,0,0.4); } } .navpath li.navelem a:hover { color: var(--primary-color); -} \ No newline at end of file +} diff --git a/include/GooseFEM/Mesh.h b/include/GooseFEM/Mesh.h index f12a4c8..d913716 100644 --- a/include/GooseFEM/Mesh.h +++ b/include/GooseFEM/Mesh.h @@ -1,1599 +1,1642 @@ /** Generic mesh operations. \file Mesh.h \copyright Copyright 2017. Tom de Geus. All rights reserved. \license This project is released under the GNU Public License (GPLv3). */ #ifndef GOOSEFEM_MESH_H #define GOOSEFEM_MESH_H #include "config.h" namespace GooseFEM { /** Generic mesh operations, and simple mesh definitions. */ namespace Mesh { /** Enumerator for element-types */ enum class ElementType { Unknown, ///< Unknown element-type Quad4, ///< Quadrilateral: 4-noded element in 2-d Hex8, ///< Hexahedron: 8-noded element in 3-d Tri3 ///< Triangle: 3-noded element in 2-d }; /** Extract the element type based on the connectivity. \param coor Nodal coordinates. \param conn Connectivity. \return ElementType(). */ inline ElementType defaultElementType( const xt::xtensor& coor, const xt::xtensor& conn); /** Abstract class for regular meshes in 2-d. This class does not have a specific element-type in mind, it is used mostly internally to derive from such that common methods do not have to be reimplementation. */ class RegularBase2d { public: RegularBase2d() = default; virtual ~RegularBase2d() = default; /** - \return Number of elements. + Number of elements. + \return unsigned int */ size_t nelem() const; /** - \return Number of nodes. + Number of nodes. + \return unsigned int */ size_t nnode() const; /** - \return Number of nodes-per-element == 4. + Number of nodes-per-element == 4. + \return unsigned int */ size_t nne() const; /** - \return Number of dimensions == 2. + Number of dimensions == 2. + \return unsigned int */ size_t ndim() const; /** - \return Number of elements in x-direction == width of the mesh in units of #h. + Number of elements in x-direction == width of the mesh in units of #h. + \return unsigned int */ virtual size_t nelx() const; /** - \return Number of elements in y-direction == height of the mesh, in units of #h, + Number of elements in y-direction == height of the mesh, in units of #h, + \return unsigned int */ virtual size_t nely() const; /** - \return Linear edge size of one 'block'. + Linear edge size of one 'block'. + \return double */ double h() const; /** - \return The ElementType(). + The ElementType(). + \return element type */ virtual ElementType getElementType() const = 0; /** - \return Nodal coordinates [#nnode, #ndim]. + Nodal coordinates [#nnode, #ndim]. + \return coordinates per node */ virtual xt::xtensor coor() const = 0; /** - \return Connectivity [#nelem, #nne]. + Connectivity [#nelem, #nne]. + \return nodes per element */ virtual xt::xtensor conn() const = 0; /** - \return DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + \return DOFs per node */ xt::xtensor dofs() const; /** Nodes along the bottom edge (y = 0), in order of increasing x. \return List of node numbers. */ virtual xt::xtensor nodesBottomEdge() const = 0; /** Nodes along the top edge (y = #nely * #h), in order of increasing x. \return List of node numbers. */ virtual xt::xtensor nodesTopEdge() const = 0; /** Nodes along the left edge (x = 0), in order of increasing y. \return List of node numbers. */ virtual xt::xtensor nodesLeftEdge() const = 0; /** Nodes along the right edge (x = #nelx * #h), in order of increasing y. \return List of node numbers. */ virtual xt::xtensor nodesRightEdge() const = 0; /** Nodes along the bottom edge (y = 0), without the corners (at x = 0 and x = #nelx * #h). Same as: nodesBottomEdge()[1: -1]. \return List of node numbers. */ virtual xt::xtensor nodesBottomOpenEdge() const = 0; /** Nodes along the top edge (y = #nely * #h), without the corners (at x = 0 and x = #nelx * #h). Same as: nodesTopEdge()[1: -1]. \return List of node numbers. */ virtual xt::xtensor nodesTopOpenEdge() const = 0; /** Nodes along the left edge (x = 0), without the corners (at y = 0 and y = #nely * #h). Same as: nodesLeftEdge()[1: -1]. \return List of node numbers. */ virtual xt::xtensor nodesLeftOpenEdge() const = 0; /** Nodes along the right edge (x = #nelx * #h), without the corners (at y = 0 and y = #nely * #h). Same as: nodesRightEdge()[1: -1]. \return List of node numbers. */ virtual xt::xtensor nodesRightOpenEdge() const = 0; /** The bottom-left corner node (at x = 0, y = 0). Same as nodesBottomEdge()[0] and nodesLeftEdge()[0]. \return Node number. */ virtual size_t nodesBottomLeftCorner() const = 0; /** The bottom-right corner node (at x = #nelx * #h, y = 0). Same as nodesBottomEdge()[-1] and nodesRightEdge()[0]. \return Node number. */ virtual size_t nodesBottomRightCorner() const = 0; /** The top-left corner node (at x = 0, y = #nely * #h). Same as nodesTopEdge()[0] and nodesRightEdge()[-1]. \return Node number. */ virtual size_t nodesTopLeftCorner() const = 0; /** The top-right corner node (at x = #nelx * #h, y = #nely * #h). Same as nodesTopEdge()[-1] and nodesRightEdge()[-1]. \return Node number. */ virtual size_t nodesTopRightCorner() const = 0; /** - \return Alias of nodesBottomLeftCorner(). + Alias of nodesBottomLeftCorner(). */ size_t nodesLeftBottomCorner() const; /** - \return Alias of nodesTopLeftCorner(). + Alias of nodesTopLeftCorner(). */ size_t nodesLeftTopCorner() const; /** - \return Alias of nodesBottomRightCorner(). + Alias of nodesBottomRightCorner(). */ size_t nodesRightBottomCorner() const; /** - \return Alias of nodesTopRightCorner(). + Alias of nodesTopRightCorner(). */ size_t nodesRightTopCorner() const; /** DOF-numbers for the case that the periodicity if fully eliminated. Such that: dofs[nodesRightOpenEdge(), :] = dofs[nodesLeftOpenEdge(), :] dofs[nodesTopOpenEdge(), :] = dofs[nodesBottomOpenEdge(), :] dofs[nodesBottomRightCorner(), :] = dofs[nodesBottomLeftCorner(), :] dofs[nodesTopRightCorner(), :] = dofs[nodesBottomLeftCorner(), :] dofs[nodesTopLeftCorner(), :] = dofs[nodesBottomLeftCorner(), :] \return DOF numbers for each node [#nnode, #ndim]. */ xt::xtensor dofsPeriodic() const; /** Periodic node pairs, in two columns: (independent, dependent). - nodesRightOpenEdge() are tied to nodesLeftOpenEdge(). - nodesTopOpenEdge() are tied to nodesBottomOpenEdge(). - nodesBottomRightCorner() are tied to nodesBottomLeftCorner(). - nodesTopRightCorner() are tied to nodesBottomLeftCorner(). - nodesTopLeftCorner() are tied to nodesBottomLeftCorner(). \return [ntyings, #ndim]. */ xt::xtensor nodesPeriodic() const; /** Reference node to use for periodicity, because all corners are tied to it. \return Alias of nodesBottomLeftCorner(). */ size_t nodesOrigin() const; protected: double m_h; ///< See h() size_t m_nelx; ///< See nelx() size_t m_nely; ///< See nely() size_t m_nelem; ///< See nelem() size_t m_nnode; ///< See nnode() size_t m_nne; ///< See nne() size_t m_ndim; ///< See ndim() }; /** Abstract class for regular meshes in 3-d. This class does not have a specific element-type in mind, it is used mostly internally to derive from such that common methods do not have to be reimplementation. */ class RegularBase3d { public: RegularBase3d() = default; virtual ~RegularBase3d() = default; /** - \return Number of elements. + Number of elements. + \return unsigned int */ size_t nelem() const; /** - \return Number of nodes. + Number of nodes. + \return unsigned int */ size_t nnode() const; /** - \return Number of nodes-per-element == 4. + Number of nodes-per-element == 4. + \return unsigned int */ size_t nne() const; /** - \return Number of dimensions == 2. + Number of dimensions == 2. + \return unsigned int */ size_t ndim() const; /** - \return Number of elements in x-direction == width of the mesh in units of #h. + Number of elements in x-direction == width of the mesh in units of #h. + \return unsigned int */ virtual size_t nelx() const; /** - \return Number of elements in y-direction == height of the mesh, in units of #h, + Number of elements in y-direction == height of the mesh, in units of #h, + \return unsigned int */ virtual size_t nely() const; /** - \return Number of elements in y-direction == height of the mesh, in units of #h, + Number of elements in y-direction == height of the mesh, in units of #h, + \return unsigned int */ virtual size_t nelz() const; /** - \return Linear edge size of one 'block'. + Linear edge size of one 'block'. + \return double */ double h() const; /** - \return The ElementType(). + The ElementType(). + \return element type */ virtual ElementType getElementType() const = 0; /** - \return Nodal coordinates [#nnode, #ndim]. + Nodal coordinates [#nnode, #ndim]. + \return coordinates per node */ virtual xt::xtensor coor() const = 0; /** - \return Connectivity [#nelem, #nne]. + Connectivity [#nelem, #nne]. + \return nodes per element */ virtual xt::xtensor conn() const = 0; /** - \return DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + \return DOFs per node */ xt::xtensor dofs() const; /** Nodes along the bottom face (y = 0). \return List of node numbers. */ virtual xt::xtensor nodesBottom() const = 0; /** Nodes along the top face (y = #nely * #h). \return List of node numbers. */ virtual xt::xtensor nodesTop() const = 0; /** Nodes along the left face (x = 0). \return List of node numbers. */ virtual xt::xtensor nodesLeft() const = 0; /** Nodes along the right face (x = #nelx * #h). \return List of node numbers. */ virtual xt::xtensor nodesRight() const = 0; /** Nodes along the front face (z = 0). \return List of node numbers. */ virtual xt::xtensor nodesFront() const = 0; /** Nodes along the back face (z = #nelz * #h). \return List of node numbers. */ virtual xt::xtensor nodesBack() const = 0; /** Nodes along the edge at the intersection of the front and bottom faces (z = 0 and y = 0). \return List of node numbers. */ virtual xt::xtensor nodesFrontBottomEdge() const = 0; /** Nodes along the edge at the intersection of the front and top faces (z = 0 and y = #nely * #h). \return List of node numbers. */ virtual xt::xtensor nodesFrontTopEdge() const = 0; /** Nodes along the edge at the intersection of the front and left faces (z = 0 and x = 0). \return List of node numbers. */ virtual xt::xtensor nodesFrontLeftEdge() const = 0; /** Nodes along the edge at the intersection of the front and right faces (z = 0 and x = #nelx * #h). \return List of node numbers. */ virtual xt::xtensor nodesFrontRightEdge() const = 0; /** Nodes along the edge at the intersection of the back and bottom faces (z = #nelz * #h and y = #nely * #h). \return List of node numbers. */ virtual xt::xtensor nodesBackBottomEdge() const = 0; /** Nodes along the edge at the intersection of the back and top faces (z = #nelz * #h and x = 0). \return List of node numbers. */ virtual xt::xtensor nodesBackTopEdge() const = 0; /** Nodes along the edge at the intersection of the back and left faces (z = #nelz * #h and x = #nelx * #h). \return List of node numbers. */ virtual xt::xtensor nodesBackLeftEdge() const = 0; /** Nodes along the edge at the intersection of the back and right faces (? = #nelz * #h and ? = ?). \return List of node numbers. */ virtual xt::xtensor nodesBackRightEdge() const = 0; /** Nodes along the edge at the intersection of the bottom and left faces (y = 0 and x = 0). \return List of node numbers. */ virtual xt::xtensor nodesBottomLeftEdge() const = 0; /** Nodes along the edge at the intersection of the bottom and right faces (y = 0 and x = #nelx * #h). \return List of node numbers. */ virtual xt::xtensor nodesBottomRightEdge() const = 0; /** Nodes along the edge at the intersection of the top and left faces (y = 0 and x = #nelx * #h). \return List of node numbers. */ virtual xt::xtensor nodesTopLeftEdge() const = 0; /** Nodes along the edge at the intersection of the top and right faces (y = #nely * #h and x = #nelx * #h). \return List of node numbers. */ virtual xt::xtensor nodesTopRightEdge() const = 0; /** - \return Alias of nodesFrontBottomEdge() + Alias of nodesFrontBottomEdge() */ xt::xtensor nodesBottomFrontEdge() const; /** - \return Alias of nodesBackBottomEdge() + Alias of nodesBackBottomEdge() */ xt::xtensor nodesBottomBackEdge() const; /** - \return Alias of nodesFrontTopEdge() + Alias of nodesFrontTopEdge() */ xt::xtensor nodesTopFrontEdge() const; /** - \return Alias of nodesBackTopEdge() + Alias of nodesBackTopEdge() */ xt::xtensor nodesTopBackEdge() const; /** - \return Alias of nodesBottomLeftEdge() + Alias of nodesBottomLeftEdge() */ xt::xtensor nodesLeftBottomEdge() const; /** - \return Alias of nodesFrontLeftEdge() + Alias of nodesFrontLeftEdge() */ xt::xtensor nodesLeftFrontEdge() const; /** - \return Alias of nodesBackLeftEdge() + Alias of nodesBackLeftEdge() */ xt::xtensor nodesLeftBackEdge() const; /** - \return Alias of nodesTopLeftEdge() + Alias of nodesTopLeftEdge() */ xt::xtensor nodesLeftTopEdge() const; /** - \return Alias of nodesBottomRightEdge() + Alias of nodesBottomRightEdge() */ xt::xtensor nodesRightBottomEdge() const; /** - \return Alias of nodesTopRightEdge() + Alias of nodesTopRightEdge() */ xt::xtensor nodesRightTopEdge() const; /** - \return Alias of nodesFrontRightEdge() + Alias of nodesFrontRightEdge() */ xt::xtensor nodesRightFrontEdge() const; /** - \return Alias of nodesBackRightEdge() + Alias of nodesBackRightEdge() */ xt::xtensor nodesRightBackEdge() const; /** Nodes along the front face excluding edges. Same as different between nodesFront() and [nodesFrontBottomEdge(), nodesFrontTopEdge(), nodesFrontLeftEdge(), nodesFrontRightEdge()] \return list of node numbers. */ virtual xt::xtensor nodesFrontFace() const = 0; /** Nodes along the back face excluding edges. Same as different between nodesBack() and [nodesBackBottomEdge(), nodesBackTopEdge(), nodesBackLeftEdge(), nodesBackRightEdge()] \return list of node numbers. */ virtual xt::xtensor nodesBackFace() const = 0; /** Nodes along the left face excluding edges. Same as different between nodesLeft() and [nodesFrontLeftEdge(), nodesBackLeftEdge(), nodesBottomLeftEdge(), nodesTopLeftEdge()] \return list of node numbers. */ virtual xt::xtensor nodesLeftFace() const = 0; /** Nodes along the right face excluding edges. Same as different between nodesRight() and [nodesFrontRightEdge(), nodesBackRightEdge(), nodesBottomRightEdge(), nodesTopRightEdge()] \return list of node numbers. */ virtual xt::xtensor nodesRightFace() const = 0; /** Nodes along the bottom face excluding edges. Same as different between nodesBottom() and [nodesBackBottomEdge(), nodesBackTopEdge(), nodesBackLeftEdge(), nodesBackRightEdge()] \return list of node numbers. */ virtual xt::xtensor nodesBottomFace() const = 0; /** Nodes along the top face excluding edges. Same as different between nodesTop() and [nodesFrontBottomEdge(), nodesFrontTopEdge(), nodesFrontLeftEdge(), nodesFrontRightEdge()] \return list of node numbers. */ virtual xt::xtensor nodesTopFace() const = 0; /** Same as nodesFrontBottomEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesFrontBottomOpenEdge() const = 0; /** Same as nodesFrontTopEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesFrontTopOpenEdge() const = 0; /** Same as nodesFrontLeftEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesFrontLeftOpenEdge() const = 0; /** Same as nodesFrontRightEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesFrontRightOpenEdge() const = 0; /** Same as nodesBackBottomEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesBackBottomOpenEdge() const = 0; /** Same as nodesBackTopEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesBackTopOpenEdge() const = 0; /** Same as nodesBackLeftEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesBackLeftOpenEdge() const = 0; /** Same as nodesBackRightEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesBackRightOpenEdge() const = 0; /** Same as nodesBottomLeftEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesBottomLeftOpenEdge() const = 0; /** Same as nodesBottomRightEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesBottomRightOpenEdge() const = 0; /** Same as nodesTopLeftEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesTopLeftOpenEdge() const = 0; /** Same as nodesTopRightEdge() but without corners. \return List of node numbers. */ virtual xt::xtensor nodesTopRightOpenEdge() const = 0; /** - \return Alias of nodesFrontBottomOpenEdge(). + Alias of nodesFrontBottomOpenEdge(). */ xt::xtensor nodesBottomFrontOpenEdge() const; /** - \return Alias of nodesBackBottomOpenEdge(). + Alias of nodesBackBottomOpenEdge(). */ xt::xtensor nodesBottomBackOpenEdge() const; /** - \return Alias of nodesFrontTopOpenEdge(). + Alias of nodesFrontTopOpenEdge(). */ xt::xtensor nodesTopFrontOpenEdge() const; /** - \return Alias of nodesBackTopOpenEdge(). + Alias of nodesBackTopOpenEdge(). */ xt::xtensor nodesTopBackOpenEdge() const; /** - \return Alias of nodesBottomLeftOpenEdge(). + Alias of nodesBottomLeftOpenEdge(). */ xt::xtensor nodesLeftBottomOpenEdge() const; /** - \return Alias of nodesFrontLeftOpenEdge(). + Alias of nodesFrontLeftOpenEdge(). */ xt::xtensor nodesLeftFrontOpenEdge() const; /** - \return Alias of nodesBackLeftOpenEdge(). + Alias of nodesBackLeftOpenEdge(). */ xt::xtensor nodesLeftBackOpenEdge() const; /** - \return Alias of nodesTopLeftOpenEdge(). + Alias of nodesTopLeftOpenEdge(). */ xt::xtensor nodesLeftTopOpenEdge() const; /** - \return Alias of nodesBottomRightOpenEdge(). + Alias of nodesBottomRightOpenEdge(). */ xt::xtensor nodesRightBottomOpenEdge() const; /** - \return Alias of nodesTopRightOpenEdge(). + Alias of nodesTopRightOpenEdge(). */ xt::xtensor nodesRightTopOpenEdge() const; /** - \return Alias of nodesFrontRightOpenEdge(). + Alias of nodesFrontRightOpenEdge(). */ xt::xtensor nodesRightFrontOpenEdge() const; /** - \return Alias of nodesBackRightOpenEdge(). + Alias of nodesBackRightOpenEdge(). */ xt::xtensor nodesRightBackOpenEdge() const; /** Front-Bottom-Left corner node. \return Node number. */ virtual size_t nodesFrontBottomLeftCorner() const = 0; /** Front-Bottom-Right corner node. \return Node number. */ virtual size_t nodesFrontBottomRightCorner() const = 0; /** Front-Top-Left corner node. \return Node number. */ virtual size_t nodesFrontTopLeftCorner() const = 0; /** Front-Top-Right corner node. \return Node number. */ virtual size_t nodesFrontTopRightCorner() const = 0; /** Back-Bottom-Left corner node. \return Node number. */ virtual size_t nodesBackBottomLeftCorner() const = 0; /** Back-Bottom-Right corner node. \return Node number. */ virtual size_t nodesBackBottomRightCorner() const = 0; /** Back-Top-Left corner node. \return Node number. */ virtual size_t nodesBackTopLeftCorner() const = 0; /** Back-Top-Right corner node. \return Node number. */ virtual size_t nodesBackTopRightCorner() const = 0; /** - \return Alias of nodesFrontBottomLeftCorner(). + Alias of nodesFrontBottomLeftCorner(). */ size_t nodesFrontLeftBottomCorner() const; /** - \return Alias of nodesFrontBottomLeftCorner(). + Alias of nodesFrontBottomLeftCorner(). */ size_t nodesBottomFrontLeftCorner() const; /** - \return Alias of nodesFrontBottomLeftCorner(). + Alias of nodesFrontBottomLeftCorner(). */ size_t nodesBottomLeftFrontCorner() const; /** - \return Alias of nodesFrontBottomLeftCorner(). + Alias of nodesFrontBottomLeftCorner(). */ size_t nodesLeftFrontBottomCorner() const; /** - \return Alias of nodesFrontBottomLeftCorner(). + Alias of nodesFrontBottomLeftCorner(). */ size_t nodesLeftBottomFrontCorner() const; /** - \return Alias of nodesFrontBottomRightCorner(). + Alias of nodesFrontBottomRightCorner(). */ size_t nodesFrontRightBottomCorner() const; /** - \return Alias of nodesFrontBottomRightCorner(). + Alias of nodesFrontBottomRightCorner(). */ size_t nodesBottomFrontRightCorner() const; /** - \return Alias of nodesFrontBottomRightCorner(). + Alias of nodesFrontBottomRightCorner(). */ size_t nodesBottomRightFrontCorner() const; /** - \return Alias of nodesFrontBottomRightCorner(). + Alias of nodesFrontBottomRightCorner(). */ size_t nodesRightFrontBottomCorner() const; /** - \return Alias of nodesFrontBottomRightCorner(). + Alias of nodesFrontBottomRightCorner(). */ size_t nodesRightBottomFrontCorner() const; /** - \return Alias of nodesFrontTopLeftCorner(). + Alias of nodesFrontTopLeftCorner(). */ size_t nodesFrontLeftTopCorner() const; /** - \return Alias of nodesFrontTopLeftCorner(). + Alias of nodesFrontTopLeftCorner(). */ size_t nodesTopFrontLeftCorner() const; /** - \return Alias of nodesFrontTopLeftCorner(). + Alias of nodesFrontTopLeftCorner(). */ size_t nodesTopLeftFrontCorner() const; /** - \return Alias of nodesFrontTopLeftCorner(). + Alias of nodesFrontTopLeftCorner(). */ size_t nodesLeftFrontTopCorner() const; /** - \return Alias of nodesFrontTopLeftCorner(). + Alias of nodesFrontTopLeftCorner(). */ size_t nodesLeftTopFrontCorner() const; /** - \return Alias of nodesFrontTopRightCorner(). + Alias of nodesFrontTopRightCorner(). */ size_t nodesFrontRightTopCorner() const; /** - \return Alias of nodesFrontTopRightCorner(). + Alias of nodesFrontTopRightCorner(). */ size_t nodesTopFrontRightCorner() const; /** - \return Alias of nodesFrontTopRightCorner(). + Alias of nodesFrontTopRightCorner(). */ size_t nodesTopRightFrontCorner() const; /** - \return Alias of nodesFrontTopRightCorner(). + Alias of nodesFrontTopRightCorner(). */ size_t nodesRightFrontTopCorner() const; /** - \return Alias of nodesFrontTopRightCorner(). + Alias of nodesFrontTopRightCorner(). */ size_t nodesRightTopFrontCorner() const; /** - \return Alias of nodesBackBottomLeftCorner(). + Alias of nodesBackBottomLeftCorner(). */ size_t nodesBackLeftBottomCorner() const; /** - \return Alias of nodesBackBottomLeftCorner(). + Alias of nodesBackBottomLeftCorner(). */ size_t nodesBottomBackLeftCorner() const; /** - \return Alias of nodesBackBottomLeftCorner(). + Alias of nodesBackBottomLeftCorner(). */ size_t nodesBottomLeftBackCorner() const; /** - \return Alias of nodesBackBottomLeftCorner(). + Alias of nodesBackBottomLeftCorner(). */ size_t nodesLeftBackBottomCorner() const; /** - \return Alias of nodesBackBottomLeftCorner(). + Alias of nodesBackBottomLeftCorner(). */ size_t nodesLeftBottomBackCorner() const; /** - \return Alias of nodesBackBottomRightCorner(). + Alias of nodesBackBottomRightCorner(). */ size_t nodesBackRightBottomCorner() const; /** - \return Alias of nodesBackBottomRightCorner(). + Alias of nodesBackBottomRightCorner(). */ size_t nodesBottomBackRightCorner() const; /** - \return Alias of nodesBackBottomRightCorner(). + Alias of nodesBackBottomRightCorner(). */ size_t nodesBottomRightBackCorner() const; /** - \return Alias of nodesBackBottomRightCorner(). + Alias of nodesBackBottomRightCorner(). */ size_t nodesRightBackBottomCorner() const; /** - \return Alias of nodesBackBottomRightCorner(). + Alias of nodesBackBottomRightCorner(). */ size_t nodesRightBottomBackCorner() const; /** - \return Alias of nodesBackTopLeftCorner(). + Alias of nodesBackTopLeftCorner(). */ size_t nodesBackLeftTopCorner() const; /** - \return Alias of nodesBackTopLeftCorner(). + Alias of nodesBackTopLeftCorner(). */ size_t nodesTopBackLeftCorner() const; /** - \return Alias of nodesBackTopLeftCorner(). + Alias of nodesBackTopLeftCorner(). */ size_t nodesTopLeftBackCorner() const; /** - \return Alias of nodesBackTopLeftCorner(). + Alias of nodesBackTopLeftCorner(). */ size_t nodesLeftBackTopCorner() const; /** - \return Alias of nodesBackTopLeftCorner(). + Alias of nodesBackTopLeftCorner(). */ size_t nodesLeftTopBackCorner() const; /** - \return Alias of nodesBackTopRightCorner(). + Alias of nodesBackTopRightCorner(). */ size_t nodesBackRightTopCorner() const; /** - \return Alias of nodesBackTopRightCorner(). + Alias of nodesBackTopRightCorner(). */ size_t nodesTopBackRightCorner() const; /** - \return Alias of nodesBackTopRightCorner(). + Alias of nodesBackTopRightCorner(). */ size_t nodesTopRightBackCorner() const; /** - \return Alias of nodesBackTopRightCorner(). + Alias of nodesBackTopRightCorner(). */ size_t nodesRightBackTopCorner() const; /** - \return Alias of nodesBackTopRightCorner(). + Alias of nodesBackTopRightCorner(). */ size_t nodesRightTopBackCorner() const; /** DOF-numbers for the case that the periodicity if fully eliminated. Such that: dofs[nodesBackFace(), :] = dofs[nodesFrontFace(), :] dofs[nodesRightFace(), :] = dofs[nodesLeftFace(), :] dofs[nodesTopFace(), :] = dofs[nodesBottomFace(), :] dofs[nodesBackBottomOpenEdge(), :] = dofs[nodesFrontBottomOpenEdge(), :] dofs[nodesBackTopOpenEdge(), :] = dofs[nodesFrontBottomOpenEdge(), :] dofs[nodesFrontTopOpenEdge(), :] = dofs[nodesFrontBottomOpenEdge(), :] dofs[nodesBottomRightOpenEdge(), :] = dofs[nodesBottomLeftOpenEdge(), :] dofs[nodesTopRightOpenEdge(), :] = dofs[nodesBottomLeftOpenEdge(), :] dofs[nodesTopLeftOpenEdge(), :] = dofs[nodesBottomLeftOpenEdge(), :] dofs[nodesFrontRightOpenEdge(), :] = dofs[nodesFrontLeftOpenEdge(), :] dofs[nodesBackRightOpenEdge(), :] = dofs[nodesFrontLeftOpenEdge(), :] dofs[nodesBackLeftOpenEdge(), :] = dofs[nodesFrontLeftOpenEdge(), :] dofs[nodesFrontBottomRightCorner(), :] = dofs[nodesFrontBottomLeftCorner(), :] dofs[nodesBackBottomRightCorner(), :] = dofs[nodesFrontBottomLeftCorner(), :] dofs[nodesBackBottomLeftCorner(), :] = dofs[nodesFrontBottomLeftCorner(), :] dofs[nodesFrontTopLeftCorner(), :] = dofs[nodesFrontBottomLeftCorner(), :] dofs[nodesFrontTopRightCorner(), :] = dofs[nodesFrontBottomLeftCorner(), :] dofs[nodesBackTopRightCorner(), :] = dofs[nodesFrontBottomLeftCorner(), :] dofs[nodesBackTopLeftCorner(), :] = dofs[nodesFrontBottomLeftCorner(), :] \return DOF numbers for each node [#nnode, #ndim]. */ xt::xtensor dofsPeriodic() const; /** Periodic node pairs, in two columns: (independent, dependent). - nodesBackFace() are tied to nodesFrontFace(). - nodesRightFace() are tied to nodesLeftFace(). - nodesTopFace() are tied to nodesBottomFace(). - nodesBackBottomOpenEdge() are tied to nodesFrontBottomOpenEdge(). - nodesBackTopOpenEdge() are tied to nodesFrontBottomOpenEdge(). - nodesFrontTopOpenEdge() are tied to nodesFrontBottomOpenEdge(). - nodesBottomRightOpenEdge() are tied to nodesBottomLeftOpenEdge(). - nodesTopRightOpenEdge() are tied to nodesBottomLeftOpenEdge(). - nodesTopLeftOpenEdge() are tied to nodesBottomLeftOpenEdge(). - nodesFrontRightOpenEdge() are tied to nodesFrontLeftOpenEdge(). - nodesBackRightOpenEdge() are tied to nodesFrontLeftOpenEdge(). - nodesBackLeftOpenEdge() are tied to nodesFrontLeftOpenEdge(). - nodesFrontBottomRightCorner() are tied to nodesFrontBottomLeftCorner(). - nodesBackBottomRightCorner() are tied to nodesFrontBottomLeftCorner(). - nodesBackBottomLeftCorner() are tied to nodesFrontBottomLeftCorner(). - nodesFrontTopLeftCorner() are tied to nodesFrontBottomLeftCorner(). - nodesFrontTopRightCorner() are tied to nodesFrontBottomLeftCorner(). - nodesBackTopRightCorner() are tied to nodesFrontBottomLeftCorner(). - nodesBackTopLeftCorner() are tied to nodesFrontBottomLeftCorner(). \return [ntyings, #ndim]. */ xt::xtensor nodesPeriodic() const; /** Reference node to use for periodicity, because all corners are tied to it. \return Alias of nodesFrontBottomLeftCorner(). */ size_t nodesOrigin() const; protected: double m_h; ///< See h() size_t m_nelx; ///< See nelx() size_t m_nely; ///< See nely() size_t m_nelz; ///< See nely() size_t m_nelem; ///< See nelem() size_t m_nnode; ///< See nnode() size_t m_nne; ///< See nne() size_t m_ndim; ///< See ndim() }; /** Find overlapping nodes. The output has the following structure: [[nodes_from_mesh_a], [nodes_from_mesh_b]] \param coor_a Nodal coordinates of mesh "a". \param coor_b Nodal coordinates of mesh "b". \param rtol Relative tolerance for position match. \param atol Absolute tolerance for position match. \return Overlapping nodes. */ inline xt::xtensor overlapping( const xt::xtensor& coor_a, const xt::xtensor& coor_b, double rtol = 1e-5, double atol = 1e-8); /** Stitch two mesh objects, specifying overlapping nodes by hand. */ class ManualStitch { public: ManualStitch() = default; /** \param coor_a Nodal coordinates of mesh "a". \param conn_a Connectivity of mesh "a". \param overlapping_nodes_a Node-numbers of mesh "a" that overlap with mesh "b". \param coor_b Nodal coordinates of mesh "b". \param conn_b Connectivity of mesh "b". \param overlapping_nodes_b Node-numbers of mesh "b" that overlap with mesh "a". \param check_position If ``true`` the nodes are checked for position overlap. \param rtol Relative tolerance for check on position overlap. \param atol Absolute tolerance for check on position overlap. */ ManualStitch( const xt::xtensor& coor_a, const xt::xtensor& conn_a, const xt::xtensor& overlapping_nodes_a, const xt::xtensor& coor_b, const xt::xtensor& conn_b, const xt::xtensor& overlapping_nodes_b, bool check_position = true, double rtol = 1e-5, double atol = 1e-8); /** - \return Number of sub meshes == 2. + Number of sub meshes == 2. + \return unsigned int */ size_t nmesh() const; /** - \return Number of elements. + Number of elements. + \return unsigned int */ size_t nelem() const; /** - \return Number of nodes. + Number of nodes. + \return unsigned int */ size_t nnode() const; /** - \return Number of nodes-per-element. + Number of nodes-per-element. + \return unsigned int */ size_t nne() const; /** - \return Number of dimensions. + Number of dimensions. + \return unsigned int */ size_t ndim() const; /** - \return Nodal coordinates [#nnode, #ndim]. + Nodal coordinates [#nnode, #ndim]. + \return coordinates per node */ xt::xtensor coor() const; /** - \return Connectivity [#nelem, #nne]. + Connectivity [#nelem, #nne]. + \return nodes per element */ xt::xtensor conn() const; /** - \return DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + \return DOFs per node */ xt::xtensor dofs() const; /** - \return Node-map per sub-mesh. + Node-map per sub-mesh. + \return nodes per mesh */ std::vector> nodemap() const; /** - \return Element-map per sub-mesh. + Element-map per sub-mesh. + \return elements per mesh */ std::vector> elemmap() const; /** \param mesh_index Index of the mesh ("a" = 1, "b" = 1). \return Node-map for a given mesh. */ xt::xtensor nodemap(size_t mesh_index) const; /** \param mesh_index Index of the mesh ("a" = 1, "b" = 1). \return Element-map for a given mesh. */ xt::xtensor elemmap(size_t mesh_index) const; /** Convert set of node numbers for an original mesh to the stitched mesh. \param set List of node numbers. \param mesh_index Index of the mesh ("a" = 1, "b" = 1). \return List of node numbers for the stitched mesh. */ xt::xtensor nodeset(const xt::xtensor& set, size_t mesh_index) const; /** Convert set of element numbers for an original mesh to the stitched mesh. \param set List of element numbers. \param mesh_index Index of the mesh ("a" = 1, "b" = 1). \return List of element numbers for the stitched mesh. */ xt::xtensor elemset(const xt::xtensor& set, size_t mesh_index) const; private: xt::xtensor m_coor; xt::xtensor m_conn; xt::xtensor m_map_b; size_t m_nnd_a; size_t m_nel_a; size_t m_nel_b; }; /** Stitch mesh objects, automatically searching for overlapping nodes. */ class Stitch { public: /** \param rtol Relative tolerance for position match. \param atol Absolute tolerance for position match. */ Stitch(double rtol = 1e-5, double atol = 1e-8); /** Add mesh to be stitched. \param coor Nodal coordinates. \param conn Connectivity. */ void push_back(const xt::xtensor& coor, const xt::xtensor& conn); /** - \return Number of sub meshes. + Number of sub meshes. + \return unsigned int */ size_t nmesh() const; /** - \return Number of elements. + Number of elements. + \return unsigned int */ size_t nelem() const; /** - \return Number of nodes. + Number of nodes. + \return unsigned int */ size_t nnode() const; /** - \return Number of nodes-per-element. + Number of nodes-per-element. + \return unsigned int */ size_t nne() const; /** - \return Number of dimensions. + Number of dimensions. + \return unsigned int */ size_t ndim() const; /** - \return Nodal coordinates [#nnode, #ndim]. + Nodal coordinates [#nnode, #ndim]. + \return coordinates per node */ xt::xtensor coor() const; /** - \return Connectivity [#nelem, #nne]. + Connectivity [#nelem, #nne]. + \return nodes per element */ xt::xtensor conn() const; /** - \return DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + DOF numbers for each node (numbered sequentially) [#nnode, #ndim]. + \return DOFs per node */ xt::xtensor dofs() const; /** - \return Node-map per sub-mesh. + Node-map per sub-mesh. + \return nodes per mesh */ std::vector> nodemap() const; /** - \return Element-map per sub-mesh. + Element-map per sub-mesh. + \return elements per mesh */ std::vector> elemmap() const; /** The node numbers in the stitched mesh that are coming from a specific sub-mesh. \param mesh_index Index of the sub-mesh. \return List of node numbers. */ xt::xtensor nodemap(size_t mesh_index) const; /** The element numbers in the stitched mesh that are coming from a specific sub-mesh. \param mesh_index Index of the sub-mesh. \return List of element numbers. */ xt::xtensor elemmap(size_t mesh_index) const; /** Convert set of node-numbers for a sub-mesh to the stitched mesh. \param set List of node numbers. \param mesh_index Index of the sub-mesh. \return List of node numbers for the stitched mesh. */ xt::xtensor nodeset(const xt::xtensor& set, size_t mesh_index) const; /** Convert set of element-numbers for a sub-mesh to the stitched mesh. \param set List of element numbers. \param mesh_index Index of the sub-mesh. \return List of element numbers for the stitched mesh. */ xt::xtensor elemset(const xt::xtensor& set, size_t mesh_index) const; /** Combine set of node numbers for an original to the final mesh (removes duplicates). \param set List of node numbers per mesh. \return List of node numbers for the stitched mesh. */ xt::xtensor nodeset(const std::vector>& set) const; /** Combine set of element numbers for an original to the final mesh. \param set List of element numbers per mesh. \return List of element numbers for the stitched mesh. */ xt::xtensor elemset(const std::vector>& set) const; protected: xt::xtensor m_coor; ///< Nodal coordinates [#nnode, #ndim] xt::xtensor m_conn; ///< Connectivity [#nelem, #nne] std::vector> m_map; ///< See nodemap(size_t) std::vector m_nel; ///< Number of elements per sub-mesh. std::vector m_el_offset; ///< First element of every sub-mesh. double m_rtol; ///< Relative tolerance to find overlapping nodes. double m_atol; ///< Absolute tolerance to find overlapping nodes. }; /** Vertically stack meshes. */ class Vstack : public Stitch { public: /** \param check_overlap Check if nodes are overlapping when adding a mesh. \param rtol Relative tolerance for position match. \param atol Absolute tolerance for position match. */ Vstack(bool check_overlap = true, double rtol = 1e-5, double atol = 1e-8); /** Add a mesh to the top of the current stack. Each time the current `nodes_bottom` are stitched with the then highest `nodes_top`. \param coor Nodal coordinates. \param conn Connectivity. \param nodes_bottom Nodes along the bottom edge. \param nodes_top Nodes along the top edge. */ void push_back( const xt::xtensor& coor, const xt::xtensor& conn, const xt::xtensor& nodes_bottom, const xt::xtensor& nodes_top); private: std::vector> m_nodes_bot; ///< Bottom nodes of each mesh (renumbered). std::vector> m_nodes_top; ///< Top nodes of each mesh (renumbered). bool m_check_overlap; ///< Check if nodes are overlapping when adding a mesh. }; /** Renumber indices to lowest possible index. For example: \f$ \begin{bmatrix} 0 & 1 \\ 5 & 4 \end{bmatrix} \f$ is renumbered to \f$ \begin{bmatrix} 0 & 1 \\ 3 & 2 \end{bmatrix} \f$ Or, in pseudo-code, the result of this function is that: dofs = renumber(dofs) sort(unique(dofs[:])) == range(max(dofs+1)) \note One can use the wrapper function renumber(). This class gives more advanced features. */ class Renumber { public: Renumber() = default; /** \param dofs DOF-numbers. */ template Renumber(const T& dofs); /** Get renumbered DOFs (same as ``Renumber::apply(dofs)``). \param dofs List of (DOF-)numbers. \return Renumbered list of (DOF-)numbers. */ [[deprecated]] xt::xtensor get(const xt::xtensor& dofs) const; /** Apply renumbering to other set. \param list List of (DOF-)numbers. \return Renumbered list of (DOF-)numbers. */ template T apply(const T& list) const; /** Get the list needed to renumber, e.g.: dofs_renumbered(i, j) = index(dofs(i, j)) \return Renumber-index. */ xt::xtensor index() const; private: xt::xtensor m_renum; }; /** Renumber to lowest possible index (see GooseFEM::Mesh::Renumber). \param dofs DOF-numbers. \return Renumbered DOF-numbers. */ inline xt::xtensor renumber(const xt::xtensor& dofs); /** Reorder to lowest possible index, in specific order. For example for ``Reorder({iiu, iip})`` after reordering: iiu = xt::range(nnu); iip = xt::range(nnp) + nnu; */ class Reorder { public: Reorder() = default; /** \param args List of (DOF-)numbers. */ Reorder(const std::initializer_list> args); /** Get reordered DOFs (same as ``Reorder::apply(dofs)``). \param dofs List of (DOF-)numbers. \return Reordered list of (DOF-)numbers. */ [[deprecated]] xt::xtensor get(const xt::xtensor& dofs) const; /** Apply reordering to other set. \param list List of (DOF-)numbers. \return Reordered list of (DOF-)numbers. */ template T apply(const T& list) const; /** Get the list needed to reorder, e.g.: dofs_reordered(i, j) = index(dofs(i, j)) \return Reorder-index. */ xt::xtensor index() const; private: xt::xtensor m_renum; }; /** List with DOF-numbers in sequential order. The output is a sequential list of DOF-numbers for each vector-component of each node. For example for 3 nodes in 2 dimensions the output is \rst .. math:: \begin{bmatrix} 0 & 1 \\ 2 & 3 \\ 4 & 5 \end{bmatrix} \endrst \param nnode Number of nodes. \param ndim Number of dimensions. \return DOF-numbers. */ inline xt::xtensor dofs(size_t nnode, size_t ndim); /** Number of elements connected to each node. \param conn Connectivity. \return Coordination per node. */ inline xt::xtensor coordination(const xt::xtensor& conn); /** Elements connected to each node. \param conn Connectivity. \param sorted If ``true`` the output is sorted. \return Elements per node. */ inline std::vector> elem2node( const xt::xtensor& conn, bool sorted = true); /** Return size of each element edge. \param coor Nodal coordinates. \param conn Connectivity. \param type ElementType. \return Edge-sizes per element. */ inline xt::xtensor edgesize( const xt::xtensor& coor, const xt::xtensor& conn, ElementType type); /** Return size of each element edge. The element-type is automatically determined, see defaultElementType(). \param coor Nodal coordinates. \param conn Connectivity. \return Edge-sizes per element. */ inline xt::xtensor edgesize( const xt::xtensor& coor, const xt::xtensor& conn); /** Coordinates of the center of each element. \param coor Nodal coordinates. \param conn Connectivity. \param type ElementType. \return Center of each element. */ inline xt::xtensor centers( const xt::xtensor& coor, const xt::xtensor& conn, ElementType type); /** Coordinates of the center of each element. The element-type is automatically determined, see defaultElementType(). \param coor Nodal coordinates. \param conn Connectivity. \return Center of each element. */ inline xt::xtensor centers( const xt::xtensor& coor, const xt::xtensor& conn); /** Convert an element-map to a node-map. \param elem_map Element-map such that ``new_elvar = elvar[elem_map]``. \param coor Nodal coordinates. \param conn Connectivity. \param type ElementType. \return Node-map such that ``new_nodevar = nodevar[node_map]`` */ inline xt::xtensor elemmap2nodemap( const xt::xtensor& elem_map, const xt::xtensor& coor, const xt::xtensor& conn, ElementType type); /** Convert an element-map to a node-map. The element-type is automatically determined, see defaultElementType(). \param elem_map Element-map such that ``new_elvar = elvar[elem_map]``. \param coor Nodal coordinates. \param conn Connectivity. \return Node-map such that ``new_nodevar = nodevar[node_map]`` */ inline xt::xtensor elemmap2nodemap( const xt::xtensor& elem_map, const xt::xtensor& coor, const xt::xtensor& conn); } // namespace Mesh } // namespace GooseFEM #include "Mesh.hpp" #endif