diff --git a/.ci/start_mapdl.sh b/.ci/start_mapdl.sh new file mode 100755 index 00000000..17521da7 --- /dev/null +++ b/.ci/start_mapdl.sh @@ -0,0 +1,18 @@ +#!/bin/bash +docker pull $MAPDL_IMAGE +docker run \ + --name mapdl \ + --restart always \ + --health-cmd="ps aux | grep \"[/]ansys_inc/.*ansys\.e.*grpc\" -q && echo 0 || echo 1" \ + --health-interval=0.5s \ + --health-retries=4 \ + --health-timeout=0.5s \ + --health-start-period=10s \ + -e ANSYSLMD_LICENSE_FILE=1055@$LICENSE_SERVER \ + -e ANSYS_LOCK="OFF" \ + -p $PYMAPDL_PORT:50052 \ + -p $PYMAPDL_DB_PORT:50055 \ + $MAPDL_IMAGE \ + -smp > log.txt & +grep -q 'Server listening on' <(timeout 60 tail -f log.txt) +# python -c "from ansys.mapdl.core import launch_mapdl; print(launch_mapdl())" diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..06c58595 --- /dev/null +++ b/.flake8 @@ -0,0 +1,7 @@ +[flake8] +exclude = venv, __init__.py, doc/_build, .venv, doc/source/technology_showcase_examples +select = W191, W291, W293, W391, E115, E117, E122, E124, E125, E225, E231, E301, E303, E501, F401, F403 +count = True +max-complexity = 10 +max-line-length = 100 +statistics = True \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..b676c6be --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + insecure-external-code-execution: allow + schedule: + interval: "weekly" + labels: + - "maintenance" + - "dependencies" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..60bd9da0 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,11 @@ +Documentation: +- doc/source/**/* +Maintenance: +- .github/**/* +- .flake8 +- ignore_words.txt +- pyproject.toml +Dependencies: +- pyproject.toml +CI/CD: +- .github/**/* diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 00000000..bc6aeecf --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,27 @@ +- name: bug + description: Something isn't working + color: d42a34 + +- name: dependencies + description: Related with project dependencies + color: ffc0cb + +- name: documentation + description: Improvements or additions to documentation + color: 0677ba + +- name: enhancement + description: New features or code improvements + color: FFD827 + +- name: good first issue + description: Easy to solve for newcomers + color: 62ca50 + +- name: maintenance + description: Package and maintenance related + color: f78c37 + +- name: release + description: Anything related to an incoming release + color: ffffff diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml new file mode 100644 index 00000000..0e2c0524 --- /dev/null +++ b/.github/workflows/ci_cd.yml @@ -0,0 +1,241 @@ +# check spelling, codestyle +name: GitHub CI + +# run only on main branch. This avoids duplicated actions on PRs +on: + workflow_dispatch: + schedule: # UTC at 0300 + - cron: "0 3 * * *" + pull_request: + push: + tags: + - "*" + branches: + - main + +env: + MAIN_PYTHON_VERSION: '3.9' + PACKAGE_NAME: 'ansys-math-core' + DOCKER_PACKAGE: ghcr.io/pyansys/pymapdl/mapdl + DOCKER_IMAGE_VERSION_DOCS_BUILD: v22.2.0 + RESET_PIP_CACHE: 0 + DOCUMENTATION_CNAME: 'math.docs.pyansys.com' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + + code-style: + name: "Code style" + runs-on: ubuntu-latest + steps: + - name: PyAnsys code style checks + uses: pyansys/actions/code-style@v2 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + + doc-style: + name: "Documentation Style Check" + runs-on: ubuntu-latest + steps: + - name: PyAnsys documentation style checks + uses: pyansys/actions/doc-style@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + + build_test: + name: "Build and unit testing" + runs-on: ubuntu-latest + needs: [doc-style, code-style] + strategy: + matrix: + mapdl-version: ['v21.1.1', 'v21.2.1', 'v22.1.0', 'v22.2.0'] #'v22.2-ubuntu' + env: + PYMAPDL_PORT: 21000 # default won't work on GitHub runners + PYMAPDL_DB_PORT: 21001 # default won't work on GitHub runners + PYMAPDL_START_INSTANCE: FALSE + + steps: + - name: "Install Git and checkout project" + uses: actions/checkout@v3 + + - name: "Setup Python" + uses: actions/setup-python@v4 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + - name: "Install os packages" + run: | + sudo apt update + + - name: "Cache pip" + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: Python-v${{ env.RESET_PIP_CACHE }}-${{ runner.os }}-${{ matrix.mapdl-version }}-${{ hashFiles('pyproject.toml') }} + restore-keys: | + Python-v${{ env.RESET_PIP_CACHE }}-${{ runner.os }}-${{ matrix.mapdl-version }} + + - name: Install ansys-mapdl-core + run: | + python -m pip install ansys-mapdl-core + + # - name: Install ansys-math-core + # run: | + # python -m pip install build + # python -m build + # python -m pip install dist/*.whl + # xvfb-run python -c "from ansys.math import core as amath; print(amath.Report())" + + - name: "Login in Github container registry" + uses: docker/login-action@v2.1.0 + with: + registry: ghcr.io + username: ${{ secrets.GH_USERNAME }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: "Pull, launch, and validate MAPDL service" + run: .ci/start_mapdl.sh + if: ${{ !contains( matrix.mapdl-version, 'ubuntu') }} + env: + LICENSE_SERVER: ${{ secrets.LICENSE_SERVER }} + MAPDL_IMAGE: ${{ env.DOCKER_PACKAGE }}:${{ matrix.mapdl-version }} + + + - name: "Unit testing requirements installation" + run: | + python -m pip install .[tests] + + - name: "Unit testing" + run: | + pytest -v --durations=10 --maxfail=10 --reruns 7 --reruns-delay 3 --only-rerun MapdlExitedError --only-rerun EmptyRecordError --cov=ansys.mapdl.core --cov-report=xml --cov-report=html + + - uses: codecov/codecov-action@v3 + name: "Upload coverage to Codecov" + + # - name: "Check package" + # run: | + # pip install twine + # twine check dist/* + + - name: "Upload wheel and binaries" + uses: actions/upload-artifact@v3 + with: + name: Ansys-Math-packages + path: dist/ + retention-days: 7 + + - name: "Display files structure" + if: always() + run: | + mkdir logs-${{ matrix.mapdl-version }} && echo "Successfully generated directory ${{ matrix.mapdl-version }}" + echo "::group:: Display files structure" && ls -R && echo "::endgroup::" + ls -R > ./logs-${{ matrix.mapdl-version }}/files_structure.txt + + - name: "Display docker files structures" + if: always() + run: | + echo "::group:: Display files structure" && docker exec mapdl /bin/bash -c "ls -R" && echo "::endgroup::" + docker exec mapdl /bin/bash -c "ls -R" > ./logs-${{ matrix.mapdl-version }}/docker_files_structure.txt + + - name: "Collect MAPDL logs on failure" + if: ${{ always() && !contains( matrix.mapdl-version, 'ubuntu') }} + run: | + docker exec mapdl /bin/bash -c "mkdir -p /mapdl_logs && echo 'Successfully created directory inside docker container'" + docker exec mapdl /bin/bash -c "if compgen -G 'file*.out' > /dev/null ;then cp -f /file*.out /mapdl_logs && echo 'Successfully copied out files.'; fi" + docker exec mapdl /bin/bash -c "if compgen -G 'file*.err' > /dev/null ;then cp -f /file*.err /mapdl_logs && echo 'Successfully copied err files.'; fi" + docker exec mapdl /bin/bash -c "if compgen -G 'file*.log' > /dev/null ;then cp -f /file*.log /mapdl_logs && echo 'Successfully copied log files.'; fi" + docker exec mapdl /bin/bash -c "if compgen -G '*.crash' > /dev/null ;then cp -f /*.crash /mapdl_logs && echo 'Successfully copied crash files.'; fi" + docker cp mapdl:/mapdl_logs/. ./logs-${{ matrix.mapdl-version }}/. + + + - name: "Collect MAPDL logs on failure for ubuntu image" + if: ${{ always() && contains( matrix.mapdl-version,'ubuntu') }} + run: | + docker exec mapdl /bin/bash -c "mkdir -p /mapdl_logs && echo 'Successfully created directory inside docker container'" + docker exec mapdl /bin/bash -c "if compgen -G '/jobs/file*.out' > /dev/null ;then cp -f /jobs/file*.out /mapdl_logs && echo 'Successfully copied out files.'; fi" + docker exec mapdl /bin/bash -c "if compgen -G '/jobs/file*.err' > /dev/null ;then cp -f /jobs/file*.err /mapdl_logs && echo 'Successfully copied err files.'; fi" + docker exec mapdl /bin/bash -c "if compgen -G '/jobs/file*.log' > /dev/null ;then cp -f /jobs/file*.log /mapdl_logs && echo 'Successfully copied log files.'; fi" + docker exec mapdl /bin/bash -c "if compgen -G '/jobs/*.crash' > /dev/null ;then cp -f /jobs/*.crash /mapdl_logs && echo 'Successfully copied crash files.'; fi" + docker cp mapdl:/mapdl_logs/. ./logs-${{ matrix.mapdl-version }}/. + + - name: "Tar logs" + if: always() + run: | + cp log.txt ./logs-${{ matrix.mapdl-version }}/log.txt + tar cvzf ./logs-${{ matrix.mapdl-version }}.tgz ./logs-${{ matrix.mapdl-version }} + + - name: "Upload logs to GitHub" + if: always() + uses: actions/upload-artifact@master + with: + name: logs-${{ matrix.mapdl-version }}.tgz + path: ./logs-${{ matrix.mapdl-version }}.tgz + + - name: "Display MAPDL Logs" + if: always() + run: cat log.txt + + - name: "List main files" + if: always() + run: | + if compgen -G './logs-${{ matrix.mapdl-version }}/*.err' > /dev/null ;then for f in ./logs-${{ matrix.mapdl-version }}/*.err; do echo "::group:: Error file $f" && cat $f && echo "::endgroup::" ; done; fi + if compgen -G './logs-${{ matrix.mapdl-version }}/*.log' > /dev/null ;then for f in ./logs-${{ matrix.mapdl-version }}/*.log; do echo "::group:: Log file $f" && cat $f && echo "::endgroup::" ; done; fi + if compgen -G './logs-${{ matrix.mapdl-version }}/*.out' > /dev/null ;then for f in ./logs-${{ matrix.mapdl-version }}/*.out; do echo "::group:: Output file $f" && cat $f && echo "::endgroup::" ; done; fi + + + doc-build: + name: Doc building + runs-on: ubuntu-latest + needs: [build_test] + steps: + - name: "Run Ansys documentation building action" + uses: pyansys/actions/doc-build@v2 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + + doc-deploy-dev: + name: "Deploy development documentation" + # Deploy development only when merging to main + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + needs: doc-build + steps: + - name: "Deploy the latest documentation" + uses: pyansys/actions/doc-deploy-dev@v2 + with: + cname: ${{ env.DOCUMENTATION_CNAME }} + token: ${{ secrets.GITHUB_TOKEN }} + + + doc-deploy-stable: + name: "Deploy stable documentation" + # Deploy release documentation when creating a new tag + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + runs-on: ubuntu-latest + needs: doc-build + steps: + - name: "Deploy the stable documentation" + uses: pyansys/actions/doc-deploy-stable@v2 + with: + cname: ${{ env.DOCUMENTATION_CNAME }} + token: ${{ secrets.GITHUB_TOKEN }} + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + + release: + name: "Release project to private PyPI, public PyPI and GitHub" + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + needs: [build_test, doc-deploy-stable] + runs-on: ubuntu-latest + steps: + + - name: "Release to GitHub" + uses: pyansys/actions/release-github@v1 + with: + library-name: ${{ env.PACKAGE_NAME }} \ No newline at end of file diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 00000000..ce5fcf3f --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,87 @@ +name: Labeler +on: + pull_request: + types: [opened, reopened] + push: + branches: [ main ] + paths: + - '../labels.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + + label-syncer: + name: Syncer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: micnncim/action-label-syncer@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + labeler: + name: Set labels + needs: [label-syncer] + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + + # Label based on modified files + - name: Label based on changed files + uses: actions/labeler@v4 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + sync-labels: '' + + # Label based on branch name + - uses: actions-ecosystem/action-add-labels@v1 + if: | + startsWith(github.event.pull_request.head.ref, 'doc') || + startsWith(github.event.pull_request.head.ref, 'docs') + with: + labels: documentation + + - uses: actions-ecosystem/action-add-labels@v1 + if: | + startsWith(github.event.pull_request.head.ref, 'maint') || + startsWith(github.event.pull_request.head.ref, 'no-ci') || + startsWith(github.event.pull_request.head.ref, 'ci') + with: + labels: maintenance + + - uses: actions-ecosystem/action-add-labels@v1 + if: startsWith(github.event.pull_request.head.ref, 'feat') + with: + labels: | + enhancement + + - uses: actions-ecosystem/action-add-labels@v1 + if: | + startsWith(github.event.pull_request.head.ref, 'fix') || + startsWith(github.event.pull_request.head.ref, 'patch') + with: + labels: bug + + commenter: + runs-on: ubuntu-latest + needs: labeler + steps: + - name: Suggest to add labels + uses: peter-evans/create-or-update-comment@v2 + # Execute only when no labels have been applied to the pull request + if: toJSON(github.event.pull_request.labels.*.name) == '{}' + with: + issue-number: ${{ github.event.pull_request.number }} + body: | + Please add one of the following labels to add this contribution to the Release Notes :point_down: + - [bug](https://github.com/pyansys/ansys-math/pulls?q=label%3Abug+) + - [documentation](https://github.com/pyansys/ansys-math/pulls?q=label%3Adocumentation+) + - [enhancement](https://github.com/pyansys/ansys-math/pulls?q=label%3Aenhancement+) + - [good first issue](https://github.com/pyansys/ansys-math/pulls?q=label%3Agood+first+issue) + - [maintenance](https://github.com/pyansys/ansys-math/pulls?q=label%3Amaintenance+) + - [release](https://github.com/pyansys/ansys-math/pulls?q=label%3Arelease+) diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..9237c17f --- /dev/null +++ b/.gitignore @@ -0,0 +1,73 @@ +# Compiled source # +################### +*.pyc +*.pyd +*.c +*.cpp +*.so +*.o +*.cache + +# OS generated files # +###################### +.fuse_hidden* +*~ +*swp + +# emacs +flycheck* + +# Old files # +_old/ + +# Pip generated folders # +######################### +*.egg-info/ +build/ +dist/ +wheels/ +wheelhouse/ +lib64/ +parts/ +sdist/ +var/ +*.egg + +# autogenerated docs +_autosummary + + +# Testing +.coverage +.tox/ +*,cover +test-output.xml +.pytest_cache/ + +\#* +.\#* +/.ipynb_checkpoints +.coverage.* +.cache + +# VSCode +.vscode/ + +# Environment +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Pycharm local settings +.idea/ + +# temp testing +tmp.out + +# Sphinx documentation +doc/_build/ +doc/**/_autosummary \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..626f1218 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,48 @@ +repos: + + +- repo: https://github.com/psf/black + rev: 22.10.0 + hooks: + - id: black + args: + - --line-length=120 + +- repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + +- repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + args: + - --max-line-length=120 + +- repo: https://github.com/codespell-project/codespell + rev: v2.2.2 + hooks: + - id: codespell + args: ["--toml", "pyproject.toml"] + additional_dependencies: ["tomli"] + +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-merge-conflict + - id: debug-statements + +# this validates our github workflow files +- repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.19.2 + hooks: + - id: check-github-workflows + +# - repo: https://github.com/pycqa/pydocstyle +# rev: 6.1.1 +# hooks: +# - id: pydocstyle +# files: ^pyoptics/ +# args: ["--ignore=D205,D100,D213"] +# additional_dependencies: [toml] \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..505d21df --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +# CHANGELOG \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..35b51670 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..deebbad3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,2 @@ +# Contributing + diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..ea581cdf --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 ANSYS, Inc. All rights reserved. + +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. diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..e69de29b diff --git a/README.md b/README.md deleted file mode 100644 index 1e12166e..00000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# ansys-math -A Python repository for mathematical libraries diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..4ec02bdf --- /dev/null +++ b/README.rst @@ -0,0 +1,37 @@ +Ansys Math +========== + +Repository holding Ansys mathematical libraries. + + +How to install +-------------- + +Code Style +---------- +Code style can be checked by running: + +.. code-block:: text + + tox -e style + +Previous command will run `pre-commit`_ for checking code quality. + + +Documentation +------------- +Documentation can be rendered by running: + +.. code-block:: text + + tox -e doc + +The resultant HTML files can be inspected using your favorite web browser: + +.. code-block:: text + + .tox/doc_out_html/index.html + +Previous will open the rendered documentation in the desired browser. + + diff --git a/doc/.vale.ini b/doc/.vale.ini new file mode 100644 index 00000000..4f0b6709 --- /dev/null +++ b/doc/.vale.ini @@ -0,0 +1,28 @@ +# Core settings +# ============= + +# Location of our `styles` +StylesPath = "styles" + +# The options are `suggestion`, `warning`, or `error` (defaults to “warning”). +MinAlertLevel = warning + +# By default, `code` and `tt` are ignored. +IgnoredScopes = code, tt + +# By default, `script`, `style`, `pre`, and `figure` are ignored. +SkippedScopes = script, style, pre, figure + +# WordTemplate specifies what Vale will consider to be an individual word. +WordTemplate = \b(?:%s)\b + +# List of Packages to be used for our guidelines +Packages = Google + +# Define the Ansys vocabulary +Vocab = ANSYS + +[*.{md,rst}] + +# Apply the following styles +BasedOnStyles = Vale, Google diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000..608eb1f0 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,32 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -j auto +SPHINXBUILD = sphinx-build +SOURCEDIR = source +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + + +# Customized clean due to examples gallery +clean: + rm -rf $(BUILDDIR)/* + rm -rf $(SOURCEDIR)/examples + find . -type d -name "_autosummary" -exec rm -rf {} + + +# Customized pdf fov svg format images +pdf: + @$(SPHINXBUILD) -M latex "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + cd $(BUILDDIR)/latex && latexmk -r latexmkrc -pdf *.tex -interaction=nonstopmode || true + (test -f $(BUILDDIR)/latex/*.pdf && echo pdf exists) || exit 1 diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 00000000..fbf40050 --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,41 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=_build + +if "%1" == "" goto help +if "%1" == "clean" goto clean + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:clean +rmdir /s /q %BUILDDIR% > /NUL 2>&1 +for /d /r %SOURCEDIR% %%d in (_autosummary) do @if exist "%%d" rmdir /s /q "%%d" +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/source/404.rst b/doc/source/404.rst new file mode 100644 index 00000000..17acef64 --- /dev/null +++ b/doc/source/404.rst @@ -0,0 +1,12 @@ +:orphan: + +.. vale off + +Oops! +===== +.. vale on + +This is unexpected. + + +The page you are requesting does not exist. \ No newline at end of file diff --git a/doc/source/_templates/README.md b/doc/source/_templates/README.md new file mode 100644 index 00000000..86a233ca --- /dev/null +++ b/doc/source/_templates/README.md @@ -0,0 +1 @@ +## Contains templates for the documentation build diff --git a/doc/source/_templates/sidebar-nav-bs.html b/doc/source/_templates/sidebar-nav-bs.html new file mode 100644 index 00000000..0554e82e --- /dev/null +++ b/doc/source/_templates/sidebar-nav-bs.html @@ -0,0 +1,10 @@ + diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 00000000..8ea8c555 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,174 @@ +"""Sphinx documentation configuration file.""" +from datetime import datetime +import os + +from ansys_sphinx_theme import ansys_favicon, get_version_match, pyansys_logo_black + +from ansys.math.core import __version__ + +# Project information +project = "ansys-math-core" +copyright = f"(c) {datetime.now().year} ANSYS, Inc. All rights reserved" +author = "ANSYS, Inc." +release = version = "0.1.dev0" + +# Select desired logo, theme, and declare the html title +html_logo = pyansys_logo_black +html_theme = "ansys_sphinx_theme" +html_short_title = html_title = "Ansys Math" + +cname = os.getenv("DOCUMENTATION_CNAME", "") +"""The canonical name of the webpage hosting the documentation.""" + + +# specify the location of your github repo +html_theme_options = { + "github_url": "https://github.com/pyansys/ansys-math", + "show_prev_next": False, + "show_breadcrumbs": True, + "additional_breadcrumbs": [ + ("PyAnsys", "https://docs.pyansys.com/"), + ], + "icon_links": [ + { + "name": "Support", + "url": "https://github.com/pyansys/ansys-math/discussions", + "icon": "fa fa-comment fa-fw", + }, + ], + "switcher": { + "json_url": f"https://{cname}/release/versions.json", + "version_match": get_version_match(__version__), + }, + "navbar_end": ["version-switcher", "theme-switcher", "navbar-icon-links"], +} + +# Sphinx extensions +extensions = [ + "jupyter_sphinx", + "notfound.extension", # for the not found page. + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "numpydoc", + "sphinx.ext.intersphinx", + "sphinx_copybutton", +] + +# # -- Sphinx Gallery Options --------------------------------------------------- +# sphinx_gallery_conf = { +# # convert rst to md for ipynb +# "pypandoc": True, +# # path to your examples scripts +# "examples_dirs": ["../source/"], +# # path where to save gallery generated examples +# "gallery_dirs": ["verif-manual"], +# # Pattern to search for example files +# "filename_pattern": r"\.py", +# # Remove the "Download all examples" button from the top level gallery +# "download_all_examples": False, +# # directory where function granular galleries are stored +# "backreferences_dir": None, +# # Modules for which function level galleries are created. In +# "doc_module": "ansys-mapdl-core", +# "image_scrapers": ("pyvista", "matplotlib"), +# "ignore_pattern": "flycheck*", +# "thumbnail_size": (350, 350), +# } + +# Intersphinx mapping +intersphinx_mapping = { + "python": ("https://docs.python.org/dev", None), + # kept here as an example + # "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), + # "numpy": ("https://numpy.org/devdocs", None), + # "matplotlib": ("https://matplotlib.org/stable", None), + # "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), + # "pyvista": ("https://docs.pyvista.org/", None), + # "grpc": ("https://grpc.github.io/grpc/python/", None), +} + +# numpydoc configuration +numpydoc_show_class_members = False +numpydoc_xref_param_type = True + +# Consider enabling numpydoc validation. See: +# https://numpydoc.readthedocs.io/en/latest/validation.html# +numpydoc_validate = True +numpydoc_validation_checks = { + "GL06", # Found unknown section + "GL07", # Sections are in the wrong order. + "GL08", # The object does not have a docstring + "GL09", # Deprecation warning should precede extended summary + "GL10", # reST directives {directives} must be followed by two colons + "SS01", # No summary found + "SS02", # Summary does not start with a capital letter + # "SS03", # Summary does not end with a period + "SS04", # Summary contains heading whitespaces + # "SS05", # Summary must start with infinitive verb, not third person + "RT02", # The first line of the Returns section should contain only the + # type, unless multiple values are being returned" +} + +# Favicon +html_favicon = ansys_favicon + +# notfound.extension +notfound_template = "404.rst" +notfound_urls_prefix = "/../" +# static path + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +source_suffix = ".rst" + +# The master toctree document. +master_doc = "index" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + "links.rst", +] + +# make rst_epilog a variable, so you can add other epilog parts to it +rst_epilog = "" +# Read link all targets from file +with open("links.rst") as f: + rst_epilog += f.read() + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# Copy button customization --------------------------------------------------- +# exclude traditional Python prompts from the copied code +copybutton_prompt_text = r">>> ?|\.\.\. " +copybutton_prompt_is_regexp = True + + +html_context = { + "display_github": True, # Integrate GitHub + "github_user": "pyansys", + "github_repo": "ansys-math", + "github_version": "main", + "doc_path": "doc/source", +} +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = "ansysmathdoc" + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [(master_doc, "ansys.math.core", "ansys.math.core Documentation", [author], 1)] diff --git a/doc/source/getting_started/index.rst b/doc/source/getting_started/index.rst new file mode 100644 index 00000000..42da50e1 --- /dev/null +++ b/doc/source/getting_started/index.rst @@ -0,0 +1,7 @@ +=============== +Getting started +=============== +To use Ansys Math, you must have a local installation of Ansys. + +For more information on getting a licensed copy of Ansys, visit +`Ansys `_ . \ No newline at end of file diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 00000000..94494d0a --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,11 @@ + +Ansys math python libraries +=========================== + +This repository holds the Python Ansys mathematical libraries. + +.. toctree:: + :hidden: + :maxdepth: 3 + + getting_started/index \ No newline at end of file diff --git a/doc/source/links.rst b/doc/source/links.rst new file mode 100644 index 00000000..738ad352 --- /dev/null +++ b/doc/source/links.rst @@ -0,0 +1,33 @@ +.. #MAPDL related +.. _mapdl_tech_show: https://ansyshelp.ansys.com/account/secured?returnurl=/Views/Secured/corp/v222/en/wb_wbtec/wb_wbtec.html +.. _mapdl_vm: https://ansyshelp.ansys.com/account/secured?returnurl=/Views/Secured/corp/v222/en/ai_rn/ansys_rn_verif.html + +.. #Other projects +.. _dpf_post_docs: https://post.docs.pyansys.com/ + +.. #Pyansys +.. _pyansys: https://docs.pyansys.com +.. _PyAnsys Developer's guide: https://dev.docs.pyansys.com/ + +.. #PyMAPDL related +.. _pymapdl_docs: https://mapdl.docs.pyansys.com +.. _pymapdl_github: https://github.com/pyansys/pymapdl +.. _pymapdl_examples: https://mapdl.docs.pyansys.com/examples/index.html + +.. # Examples +.. _examples_intro: https://ansyshelp.ansys.com/Views/Secured/corp/v212/en/ans_tec/tecintro.html + +.. # Ansys related +.. _ansys: https://www.ansys.com/ + + +.. # Other tools +.. _black: https://github.com/psf/black +.. _flake8: https://flake8.pycqa.org/en/latest/ +.. _isort: https://github.com/PyCQA/isort +.. _pre-commit: https://pre-commit.com/ +.. _pytest: https://docs.pytest.org/en/stable/ +.. _Sphinx: https://www.sphinx-doc.org/en/master/ +.. _pip: https://pypi.org/project/pip/ +.. _tox: https://tox.wiki/ +.. _venv: https://docs.python.org/3/library/venv.html diff --git a/doc/styles/.gitignore b/doc/styles/.gitignore new file mode 100644 index 00000000..080f12aa --- /dev/null +++ b/doc/styles/.gitignore @@ -0,0 +1,4 @@ +* +!Vocab +!Vocab/** +!.gitignore \ No newline at end of file diff --git a/doc/styles/Vocab/ANSYS/accept.txt b/doc/styles/Vocab/ANSYS/accept.txt new file mode 100644 index 00000000..79019fc8 --- /dev/null +++ b/doc/styles/Vocab/ANSYS/accept.txt @@ -0,0 +1,8 @@ +ANSYS +Ansys +ansyspres +nax +tickness +struc +parm +nce diff --git a/doc/styles/Vocab/ANSYS/reject.txt b/doc/styles/Vocab/ANSYS/reject.txt new file mode 100644 index 00000000..e69de29b diff --git a/ignore_words.txt b/ignore_words.txt new file mode 100644 index 00000000..e69de29b diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..47616dcb --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,75 @@ +[build-system] +requires = ["flit_core >=3.2,<4"] +build-backend = "flit_core.buildapi" + +[project] +# Check https://flit.readthedocs.io/en/latest/pyproject_toml.html for all available sections +name = "ansys-maths" +version = "0.1.dev0" +description = "A Python wrapper for Ansys Math libraries." +readme = "README.rst" +requires-python = ">=3.7" +license = {file = "LICENSE"} +authors = [ + {name = "ANSYS, Inc.", email = "pyansys.support@ansys.com"}, +] +maintainers = [ + {name = "PyAnsys developers", email = "pyansys.maintainers@ansys.com"}, +] +classifiers=[ + "Development Status :: 4 - Beta", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] +dependencies = [ + "ansys-api-mapdl==0.5.1", # supports at least 2020R2 - 2022R1 + "ansys-mapdl-core>=0.63.3", + "numpy>=1.14.0", +] + +[project.optional-dependencies] +tests = [ + "ansys-mapdl-core>=0.63.3", + "scipy>=1.3.0", + "pytest==7.2.0", + "pytest-cov==4.0.0", + "pytest-rerunfailures==10.2", +] +doc = [ + "ansys-mapdl-core>=0.63.3", + "Sphinx==5.3.0", + "ansys-sphinx-theme==0.8.0", + "jupyter_sphinx==0.4.0", + "jupyterlab>=3.2.8", + "numpydoc==1.5.0", + "sphinx-copybutton==0.5.1", + "sphinx-notfound-page==0.8.3", +] + +[tool.flit.module] +name = "ansys.math.core" + +[project.urls] +Source = "https://github.com/pyansys/ansys-math" + +[tool.black] +line-length = 100 + +[tool.isort] +profile = "black" +force_sort_within_sections = true +line_length = 100 +default_section = "THIRDPARTY" +src_paths = ["doc", "src", "tests"] + +[tool.coverage.report] +show_missing = true + +[tool.codespell] +skip = '*.pyc,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./doc/build/*,./doc/images/*,./dist/*,*~,.hypothesis*,./doc/source/examples/*,*cover,*.dat,*.mac,build,./docker/mapdl/v*,./factory/*,./ansys/mapdl/core/mapdl_functions.py,PKG-INFO,*.mypy_cache/*,./docker/mapdl/*,./_unused/*' +ignore-words = "doc/styles/Vocab/ANSYS/accept.txt" +quiet-level = 3 diff --git a/src/ansys/math/core/__init__.py b/src/ansys/math/core/__init__.py new file mode 100644 index 00000000..7bd02775 --- /dev/null +++ b/src/ansys/math/core/__init__.py @@ -0,0 +1 @@ +from ansys.math.core._version import __version__ diff --git a/src/ansys/math/core/_version.py b/src/ansys/math/core/_version.py new file mode 100644 index 00000000..704a2f32 --- /dev/null +++ b/src/ansys/math/core/_version.py @@ -0,0 +1,21 @@ +"""Version of ansys-- library. + +On the ``main`` branch, use 'dev0' to denote a development version. +For example: + +version_info = 0, 1, 'dev0' + +Examples +-------- +Print the version + +>>> from ansys.product import library +>>> print(library.__version__) +0.1.dev0 + +""" +# major, minor, patch +version_info = 0, 1, "dev0" + +# Nice string for the version +__version__ = ".".join(map(str, version_info)) diff --git a/src/ansys/math/core/examples/ansys-math_vs_scipy.ipynb b/src/ansys/math/core/examples/ansys-math_vs_scipy.ipynb new file mode 100644 index 00000000..b22babd5 --- /dev/null +++ b/src/ansys/math/core/examples/ansys-math_vs_scipy.ipynb @@ -0,0 +1,658 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compute Eigenvalues using MAPDL or SciPy {#ref_mapdl_math_mapdl_vs_scipy}\n", + "\n", + "This example shows:\n", + "\n", + "- How to extract the stiffness and mass matrices from a MAPDL model.\n", + "- How to use the `Math` module of PyMapdl to compute the first\n", + " eigenvalues.\n", + "- How to can get these matrices in the SciPy world, to get the same\n", + " solutions using Python resources.\n", + "- How MAPDL is really faster than SciPy :)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import math" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First load python packages we need for this example\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import time\n", + "\n", + "import matplotlib.pylab as plt\n", + "import numpy as np\n", + "import scipy\n", + "from scipy.sparse.linalg import eigsh\n", + "\n", + "import ansys.math.core.math as amath\n", + "mm = amath.MapdlMath()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from ansys.mapdl.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next:\n", + "\n", + "- Load the ansys.mapdl module\n", + "- Get the `Math` module of PyMapdl\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "APDLMath EigenSolve First load the input file using MAPDL.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " /INPUT FILE= D:\\repos\\pyansys\\ansys-math\\.venv\\Lib\\site-packages\\ansys\\mapdl\\core\\examples\\wing.dat LINE= 0\n", + "\n", + " *** WARNING *** CP = 7.141 TIME= 16:27:30\n", + " /BATCH is not a recognized SOLUTION command, abbreviation, or macro. \n", + " This command will be ignored. \n", + "\n", + " FINISH SOLUTION PROCESSING\n", + "\n", + "\n", + " ***** ROUTINE COMPLETED ***** CP = 7.141\n", + "\n", + "\n", + "\n", + " *** MAPDL - ENGINEERING ANALYSIS SYSTEM RELEASE 2022 R2 22.2 ***\n", + " Ansys Mechanical Enterprise \n", + " 00000000 VERSION=WINDOWS x64 16:27:30 DEC 15, 2022 CP= 7.141\n", + "\n", + " \n", + "\n", + "\n", + "\n", + " ***** MAPDL ANALYSIS DEFINITION (PREP7) *****\n", + "\n", + " *** WARNING *** CP = 7.141 TIME= 16:27:30\n", + " Deactivation of element shape checking is not recommended. \n", + "\n", + " *** WARNING *** CP = 7.156 TIME= 16:27:30\n", + " The mesh of area 1 contains PLANE42 triangles, which are much too stiff \n", + " in bending. Use quadratic (6- or 8-node) elements if possible. \n", + "\n", + " *** WARNING *** CP = 7.188 TIME= 16:27:30\n", + " CLEAR, SELECT, and MESH boundary condition commands are not possible \n", + " after MODMSH. \n", + "\n", + "\n", + " ***** ROUTINE COMPLETED ***** CP = 7.188\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "print(mm._mapdl.input(examples.examples.wing_model))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot and mesh using the `eplot` method.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "d:\\repos\\pyansys\\ansys-math\\.venv\\lib\\site-packages\\pyvista\\jupyter\\notebook.py:60: UserWarning: Failed to use notebook backend: \n", + "\n", + "Please install `ipyvtklink` to use this feature: https://github.com/Kitware/ipyvtklink\n", + "\n", + "Falling back to a static output.\n", + " warnings.warn(\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mm._mapdl.eplot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, setup a modal Analysis and request the $K$ and\n", + "math:[M]{.title-ref} matrices to be formed. MAPDL stores these matrices\n", + "in a `.FULL` file.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "***** MAPDL SOLUTION ROUTINE *****\n", + "PERFORM A MODAL ANALYSIS\n", + " THIS WILL BE A NEW ANALYSIS\n", + "USE SYM. BLOCK LANCZOS MODE EXTRACTION METHOD\n", + " EXTRACT 10 MODES\n", + " SHIFT POINT FOR EIGENVALUE CALCULATION= 1.0000 \n", + " NORMALIZE THE MODE SHAPES TO THE MASS MATRIX\n", + "STOP SOLUTION AFTER FULL FILE HAS BEEN WRITTEN\n", + " LOADSTEP = 1 SUBSTEP = 1 EQ. ITER = 1\n" + ] + } + ], + "source": [ + "print(mm._mapdl.slashsolu())\n", + "print(mm._mapdl.antype(antype=\"MODAL\"))\n", + "print(mm._mapdl.modopt(method=\"LANB\", nmode=\"10\", freqb=\"1.\"))\n", + "print(mm._mapdl.wrfull(ldstep=\"1\"))\n", + "\n", + "# store the output of the solve command\n", + "output = mm._mapdl.solve()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read the sparse matrices using PyMapdl.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mm._mapdl.finish()\n", + "mm.free()\n", + "k = mm.stiff(fname=\"file.full\")\n", + "M = mm.mass(fname=\"file.full\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Solve the eigenproblem using PyMapdl with APDLMath.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Elapsed time to solve this problem : 0.54799485206604\n" + ] + } + ], + "source": [ + "nev = 10\n", + "A = mm.mat(k.nrow, nev)\n", + "\n", + "t1 = time.time()\n", + "ev = mm.eigs(nev, k, M, phi=A, fmin=1.0)\n", + "t2 = time.time()\n", + "mapdl_elapsed_time = t2 - t1\n", + "print(\"\\nElapsed time to solve this problem : \", mapdl_elapsed_time)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print eigenfrequencies and accuracy.\n", + "\n", + "Accuracy : $\\frac{||(K-\\lambda.M).\\phi||_2}{||K.\\phi||_2}$\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0] : Freq = 352.39 Hz\t Residual = 1.9659e-08\n", + "[1] : Freq = 385.21 Hz\t Residual = 8.5093e-09\n", + "[2] : Freq = 656.77 Hz\t Residual = 1.1362e-08\n", + "[3] : Freq = 764.72 Hz\t Residual = 8.1529e-09\n", + "[4] : Freq = 825.44 Hz\t Residual = 8.805e-09\n", + "[5] : Freq = 1039.25 Hz\t Residual = 1.1895e-08\n", + "[6] : Freq = 1143.61 Hz\t Residual = 1.1819e-08\n", + "[7] : Freq = 1258.00 Hz\t Residual = 1.8103e-08\n", + "[8] : Freq = 1334.22 Hz\t Residual = 1.1652e-08\n", + "[9] : Freq = 1352.01 Hz\t Residual = 1.7036e-08\n" + ] + } + ], + "source": [ + "mapdl_acc = np.empty(nev)\n", + "\n", + "for i in range(nev):\n", + " f = ev[i] # Eigenfrequency (Hz)\n", + " omega = 2 * np.pi * f # omega = 2.pi.Frequency\n", + " lam = omega**2 # lambda = omega^2\n", + "\n", + " phi = A[i] # i-th eigenshape\n", + " kphi = k.dot(phi) # K.Phi\n", + " mphi = M.dot(phi) # M.Phi\n", + "\n", + " kphi_nrm = kphi.norm() # Normalization scalar value\n", + "\n", + " mphi *= lam # (K-\\lambda.M).Phi\n", + " kphi -= mphi\n", + "\n", + " mapdl_acc[i] = kphi.norm() / kphi_nrm # compute the residual\n", + " print(f\"[{i}] : Freq = {f:8.2f} Hz\\t Residual = {mapdl_acc[i]:.5}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use SciPy to Solve the same Eigenproblem\n", + "\n", + "First get MAPDL sparse matrices into the Python memory as SciPy\n", + "matrices.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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3TokJSVh+vTpxe6jbt262LNnD86cOYPp06cjKSkJ//73vzF27FiNavjwww+xefNm5ObmYsaMGVi9ejUGDhyIY8eOFZo1u6Ts7Oxw6tQpBAUF4ffff8enn36KZcuWIS0tTeGSpzyUfv/995g4cSJ27tyJzz77TO3z9IiqGgNRViM7iYiqka5du+LBgwcqL10Rkf7hGSQiIiIiJQxIREREREoYkIiIiIiUcAwSERERkRKeQSIiIiJSwoBEREREpIQBiYiIiEgJAxIRERGREgYkIiIiIiUMSERERERKGJCIiIiIlDAgERERESlhQCIiIiJSwoBEREREpIQBiYiIiEgJAxIRERGREgYkIiIiIiUMSERERERKGJCIiIiIlDAgERERESlhQCIiIiJSwoBEREREpIQBiYiIiEgJAxIRERGREgYkIiIiIiUMSERERERKGJCIiIiIlDAgERERESlhQCIiIiJSwoBEREREpIQBiYiIiEgJAxIRERGREgYkIiIiIiUMSERERERKGJCIiIiIlDAgERERESlhQCIiIiJSwoBEREREpIQBiYiIiEgJAxIRERGREgYkIiIiIiUMSERERERKGJCIiIiIlDAgERERESlhQCIiIiJSwoBEREREpIQBiYiIiEgJAxIRERGREgYkIiIiIiUMSERERERKGJCIiIiIlDAgERERESlhQCIiIiJSwoBEREREpIQBiYiIiEgJAxIRERGREgYkIiIiIiUMSERERERKGJCIiIiIlDAgESkJCwuDgYEBEhMTK7oUItJDzs7O+PDDDyu6DColBiQqMXmQOHPmjMLyjIwMtGvXDqampti3b5/a7Q8fPgwDAwMYGBjgt99+U9mmU6dOMDAwQKtWrUpU408//YSwsLASbUtEuiXvMwwMDHDs2LFC64UQcHR0hIGBAfr27Vvs/rp27QoDAwM0bdpU5frw8HDp/bZt26Z1vXFxcfjqq6/4ZamaYkAincrMzETPnj1x4cIF7NixA7169Sp2G1NTU2zYsKHQ8sTERJw4cQKmpqYlrqckAWnkyJF49uwZnJycSvy+RKSeumM+IiICt2/fhomJiVb7unbtGk6dOlVo3fr160vVf8TFxeHrr7/WOiDFx8djzZo1JX5fqhwYkEhnHj9+jICAAMTExGD79u3o3bu3Rtv16dMH4eHhePDggcLyDRs2wM7ODt7e3mVR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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pk = k.asarray()\n", + "pm = M.asarray()\n", + "\n", + "# get_ipython().run_line_magic('matplotlib', 'inline')\n", + "\n", + "fig, (ax1, ax2) = plt.subplots(1, 2)\n", + "fig.suptitle(\"K and M Matrix profiles\")\n", + "ax1.spy(pk, markersize=0.01)\n", + "ax1.set_title(\"K Matrix\")\n", + "ax2.spy(pm, markersize=0.01)\n", + "ax2.set_title(\"M Matrix\")\n", + "plt.show(block=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the sparse matrices for SciPy unsymmetric as symmetric matrices in\n", + "SciPy are memory inefficient.\n", + "\n", + "$K = K + K^T - diag(K)$\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pkd = scipy.sparse.diags(pk.diagonal())\n", + "pK = pk + pk.transpose() - pkd\n", + "pmd = scipy.sparse.diags(pm.diagonal())\n", + "pm = pm + pm.transpose() - pmd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot Matrices\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, (ax1, ax2) = plt.subplots(1, 2)\n", + "fig.suptitle(\"K and M Matrix profiles\")\n", + "ax1.spy(pk, markersize=0.01)\n", + "ax1.set_title(\"K Matrix\")\n", + "ax2.spy(pm, markersize=0.01)\n", + "ax2.set_title(\"M Matrix\")\n", + "plt.show(block=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Solve the eigenproblem\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Elapsed time to solve this problem : 9.36325716972351\n" + ] + } + ], + "source": [ + "t3 = time.time()\n", + "vals, vecs = eigsh(A=pK, M=pm, k=10, sigma=1, which=\"LA\")\n", + "t4 = time.time()\n", + "scipy_elapsed_time = t4 - t3\n", + "print(\"\\nElapsed time to solve this problem : \", scipy_elapsed_time)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Convert Lambda values to Frequency values:\n", + "$freq = \\frac{\\sqrt(\\lambda)}{2.\\pi}$\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "freqs = np.sqrt(vals) / (2 * math.pi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the residual error for SciPy.\n", + "\n", + "$Err=\\frac{||(K-\\lambda.M).\\phi||_2}{||K.\\phi||_2}$\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0] : Freq = 352.39 Hz\t Residual = 8.0075e-05\n", + "[1] : Freq = 385.21 Hz\t Residual = 0.00010351\n", + "[2] : Freq = 656.77 Hz\t Residual = 0.00024252\n", + "[3] : Freq = 764.72 Hz\t Residual = 0.00016258\n", + "[4] : Freq = 825.43 Hz\t Residual = 0.00038959\n", + "[5] : Freq = 1039.25 Hz\t Residual = 0.00057544\n", + "[6] : Freq = 1143.61 Hz\t Residual = 0.0025878\n", + "[7] : Freq = 1257.97 Hz\t Residual = 0.00033879\n", + "[8] : Freq = 1334.20 Hz\t Residual = 0.00046617\n", + "[9] : Freq = 1352.01 Hz\t Residual = 0.001126\n" + ] + } + ], + "source": [ + "scipy_acc = np.zeros(nev)\n", + "\n", + "for i in range(nev):\n", + " lam = vals[i] # i-th eigenvalue\n", + " phi = vecs.T[i] # i-th eigenshape\n", + "\n", + " kphi = pk * phi.T # K.Phi\n", + " mphi = pm * phi.T # M.Phi\n", + "\n", + " kphi_nrm = np.linalg.norm(kphi, 2) # Normalization scalar value\n", + "\n", + " mphi *= lam # (K-\\lambda.M).Phi\n", + " kphi -= mphi\n", + "\n", + " scipy_acc[i] = 1 - np.linalg.norm(kphi, 2) / kphi_nrm # compute the residual\n", + " print(f\"[{i}] : Freq = {freqs[i]:8.2f} Hz\\t Residual = {scipy_acc[i]:.5}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MAPDL is more accurate than SciPy.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA/QAAANXCAYAAACbrRQiAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABU2UlEQVR4nO3deZyWBb3///ewowiKbKJsbumogcpI7qikomEumakVYFLpzTEjLWzBNVFPGS13Up6Mfkc92slcyjSNSrRcRg1POUpqYJiCWMoIJrLM7w9rvtEwyDLjPRc+n4/HPB7nvu5rrutz32dOpxfXVtXQ0NAQAAAAoFDaVXoAAAAAYP0JegAAACggQQ8AAAAFJOgBAACggAQ9AAAAFJCgBwAAgAIS9AAAAFBAgh4AAAAKSNADAABAAQl6AHiHueCCC1JVVbVO61ZVVeWCCy5o1XlGjhyZkSNHtuo+AGBTJOgBoEJmzJiRqqqqxp8OHTpk2223zbhx4/KXv/yl0uO1OYMHD17t+/rXnyOPPLLS4wHA265DpQcAgHe6iy66KEOGDMnrr7+eBx54IDNmzMh9992XP/zhD+nSpUuL7++LX/xiJk+e3OLbfTsMGzYsn/nMZ5os79+/fwWmAYDKEvQAUGGjR4/O8OHDkySnn356evXqlcsvvzy33XZbPvjBD7b4/jp06JAOHYr5XwG23XbbfPjDH17v31u6dGk233zzJstXrVqVN954Y6P+4aS5bQNAa3PKPQC0MQceeGCS5Jlnnllt+ZNPPpkPfOAD6dmzZ7p06ZLhw4fntttuW22d5cuX58ILL8xOO+2ULl26ZOutt84BBxyQu+++u3GdNV1Dv2zZsnz6059O7969s8UWW+SYY47Jc88912S2cePGZfDgwU2Wr2mb3//+93PooYemT58+6dy5c6qrq3PVVVet13exIcaNG5du3brlmWeeyVFHHZUtttgip556apI37wkwceLEXHfdddltt93SuXPn3HnnnUmS3/3udxk9enS6d++ebt265bDDDssDDzyw2rb/eZnEPffckzPPPDN9+vTJdttt1+qfCQDWpJj/PA8Am7B58+YlSbbaaqvGZY8//nj233//bLvttpk8eXI233zz/PCHP8yxxx6bm266Kccdd1ySN8N66tSpOf3007PPPvukvr4+Dz/8cB599NG8973vbXafp59+eq699tqccsop2W+//fLLX/4yRx999EZ9jquuuiq77bZbjjnmmHTo0CE/+clPcuaZZ2bVqlUplUobtM3ly5fnpZdearJ88803T9euXRtfr1ixIkcccUQOOOCAfOUrX8lmm23W+N4vf/nL/PCHP8zEiRPTq1evDB48OI8//ngOPPDAdO/ePZ/97GfTsWPHfOc738nIkSNzzz33ZMSIEavt78wzz0zv3r0zZcqULF26dIM+CwBsLEEPABW2ePHivPTSS3n99dfz4IMP5sILL0znzp3zvve9r3GdT33qUxk4cGBqa2vTuXPnJG9G5QEHHJDPfe5zjUF/++2356ijjsp3v/vddd7/Y489lmuvvTZnnnlmyuVykqRUKuXUU0/N//3f/23w57rnnntWi+yJEyfmyCOPzJVXXrnBQX/XXXeld+/eTZZPnTp1tfsCLFu2LCeeeGKmTp3aZN05c+bk97//faqrqxuXHXfccVm+fHnuu+++bL/99kmSj370o3nXu96Vz372s7nnnntW20bPnj0zc+bMtG/ffoM+BwC0BEEPABU2atSo1V4PHjw41157beOp3H/729/yy1/+MhdddFFeffXVvPrqq43rHnHEETn//PPzl7/8Jdtuu2223HLLPP7443nqqaey0047rdP+f/aznyVJzjrrrNWWn3322bn++us3+HP9a8wvXrw4y5cvz8EHH5yf//znWbx4cXr06LHe2xwxYkQuueSSJsvX9FnPOOOMNW7j4IMPXi3mV65cmbvuuivHHntsY8wnyTbbbJNTTjklV199derr69O9e/fG9yZMmCDmAag4QQ8AFVYul7Pzzjtn8eLFueaaazJr1qzGo/BJ8vTTT6ehoSFf+tKX8qUvfWmN23jxxRez7bbb5qKLLsr73//+7Lzzztl9991z5JFH5iMf+Uje/e53N7v/Z599Nu3atcsOO+yw2vJ3vetdG/W5fvOb3+T888/P/fffn9dee2219zY06Hv16tXkH0DWpEOHDs1e2z5kyJDVXi9atCivvfbaGj/vrrvumlWrVmX+/PnZbbfdmt0GAFSCoAeACttnn30a73J/7LHH5oADDsgpp5ySOXPmpFu3blm1alWS5JxzzskRRxyxxm3suOOOSZKDDjoozzzzTG699dbcdddd+a//+q987Wtfy/Tp03P66adv9Kz/fuO7f1q5cuVqr5955pkcdthh2WWXXXLllVdmwIAB6dSpU372s5/la1/7WuNnai2dO3dOu3Zrvvfvv545sKFaYhsAsLEEPQC0Ie3bt8/UqVNzyCGH5Fvf+lYmT57ceBp4x44d1+nodM+ePTN+/PiMHz8+S5YsyUEHHZQLLrig2aAfNGhQVq1alWeeeWa1o9Rz5sxpsu5WW22VV155pcnyZ599drXXP/nJT7Js2bLcdtttGThwYOPyX/3qV285/9utd+/e2Wyzzdb4eZ988sm0a9cuAwYMqMBkALB2HlsHAG3MyJEjs88++2TatGl5/fXX06dPn4wcOTLf+c538sILLzRZf9GiRY3/81//+tfV3uvWrVt23HHHLFu2rNn9jR49OknyjW98Y7Xl06ZNa7LuDjvskMWLF692s7wXXnghN99882rr/fP68oaGhsZlixcvzve///1m56iU9u3b5/DDD8+tt97a+ISBJFm4cGGuv/76HHDAAatdPw8AbYUj9ADQBp177rk58cQTM2PGjHzyk59MuVzOAQcckD322CMTJkzI9ttvn4ULF+b+++/Pc889l8ceeyxJUl1dnZEjR2bvvfdOz5498/DDD+dHP/pRJk6c2Oy+hg0blpNPPjnf/va3s3jx4uy3336ZOXNmnn766SbrfuhDH2q8q/5ZZ52V1157LVdddVV23nnnPProo43rHX744enUqVPGjBmTT3ziE1myZEmuvvrq9OnTZ43/KLGu/vKXv+Taa69tsrxbt2459thjN3i7l1xySe6+++4ccMABOfPMM9OhQ4d85zvfybJly3LFFVds8HYBoDUJegBog44//vjssMMO+cpXvpIJEyakuro6Dz/8cC688MLMmDEjf/3rX9OnT5/sueeemTJlSuPvnXXWWbntttty1113ZdmyZRk0aFAuueSSnHvuuWvd3zXXXJPevXvnuuuuyy233JJDDz00t99+e5NTzbfeeuvcfPPNmTRpUj772c9myJAhmTp1ap566qnVgv5d73pXfvSjH+WLX/xizjnnnPTr1y9nnHFGevfundNOO22Dv5fZs2fnIx/5SJPlgwYN2qig32233XLvvffmvPPOy9SpU7Nq1aqMGDEi1157bZNn0ANAW1HV8K/nwgEAAACF4Bp6AAAAKCBBDwAAAAUk6AEAAKCABD0AAAAUkKAHAACAAhL0AAAAUECeQ/8WVq1aleef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ri61tbWVHgUAAACaWO9T7j/zmc/krLPOyuzZs7PffvslSX7zm99kxowZ+frXv97iAwIAAABNrXfQn3HGGenXr1+++tWv5oc//GGSZNddd82NN96Y97///S0+IAAAANDUegX9ihUrcumll+a0007Lfffd11ozAQAAAG9hva6h79ChQ6644oqsWLGiteYBAAAA1sF63xTvsMMOyz333NMaswAAAADraL2voR89enQmT56c3//+99l7772z+eabr/b+Mccc02LDAQAAAGu23kF/5plnJkmuvPLKJu9VVVVl5cqVGz8VAAAAsFbrHfSrVq1qjTkAAACA9bBe19AvX748HTp0yB/+8IfWmqfNKJfLqa6uTk1NTaVHAQAAgCbWK+g7duyYgQMHviNOqy+VSqmrq0ttbW2lRwEAAIAm1vsu91/4whfy+c9/Pn/7299aYx4AAABgHaz3NfTf+ta38vTTT6d///4ZNGhQk7vcP/rooy02HAAAALBm6x30xx57bCuMAQAAAKyP9Q76888/vzXmAAAAANbDOl9D/9BDD631ZnjLli3LD3/4wxYZCgAAAFi7dQ76fffdN3/9618bX3fv3j1/+tOfGl+/8sorOfnkk1t2OgAAAGCN1jnoGxoa1vq6uWUAAABAy1vvx9atTVVVVUtuDgAAAGhGiwY9AAAA8PZYr7vc19XVZcGCBUnePL3+ySefzJIlS5IkL730UstPBwAAAKzRegX9YYcdttp18u973/uSvHmqfUNDwyZ1yn25XE65XF7rnf0BAACgUtY56OfOnduac7Q5pVIppVIp9fX16dGjR6XHAQAAgNWsc9APGjSoNecAAAAA1oOb4gEAAEABCXoAAAAoIEEPAAAABSToAQAAoIDW67F1/+6ll17Kgw8+mJUrV6ampibbbLNNS80FAAAArMUGB/1NN92Uj33sY9l5552zfPnyzJkzJ+VyOePHj2/J+QAAAIA1WOdT7pcsWbLa6wsvvDAPPfRQHnroofzud7/L//7v/+YLX/hCiw8IAAAANLXOQb/33nvn1ltvbXzdoUOHvPjii42vFy5cmE6dOrXsdAAAAMAarfMp9z//+c9TKpUyY8aMlMvlfP3rX89JJ52UlStXZsWKFWnXrl1mzJjRiqMCAAAA/7TOQT948ODcfvvt+Z//+Z8cfPDBOeuss/L000/n6aefzsqVK7PL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H9fvr027dlXZccjAJMmuO22fZ56dnzMmX5r//uabp9Uvee3vufAzn8jxow9t+vk6d86Abftlzqwf5xf3Ppi7730wZ37+svznVf9f7rnp6nTs2DFVVVVNTo1fvnz9gr99+/a5++6789vf/jZ33XVXvvnNb+YLX/hCHnzwwQwZMmS9ttUaKn6EfuTIkWloaGjy8683Kpg4cWKeffbZLFu2LA8++GBGjBhRuYEBAAAKpnqn7bP0tTdPa3/3rjvluRdezB+feXadf/+f8b39oO2axHyS7LHrThk+tDpXX//jXH/znTntQ+9f7xknl8bnxp/clUd//0SSZK/dd8mcZ57NjkMGNvlp1+7NlO3atUvGHH5wvnHxZ/Pr//1u7n/k//L7J59OkvTeequ8sPClxu0/9ac/N57avyadOr15/f/KlStXW15VVZX9998/F154YX73u9+lU6dOufnmm9f787WGih+hh7bOUbk1cVQOAKAt+utf/5oTTzwxp512Wt7dr2O26LZ5Hn6sLldc9YO8/4g373J/8L5756ARe+WEj5+bK8+flB0HD8iTT89LVVVy5CH7b/C+Tz/52Ez84uXZfLOuOe7IQ976F/7NgG375bgjD8mU/7wqP/3/vpEpn56Q9409OwO37ZcPHD0q7dpV5bG6p/KHJ5/OJZ8rZcaNt2XlqlUZsefu2axrl1z745+la5cuGfSP59gfun9NvjXjxuw7/N1ZuXJVPvflr6djx+YTeNCgQamqqspPf/rTHHXUUenatWsef/zxzJw5M4cffnj69OmTBx98MIsWLcquu+66wd9TSxL0AAAA62HeWWs/lbxF9N9zg36tW7duGTFiRL72ta/lmaf/mOXLV2RA/36ZcMpx+fx/nNa43k1X/2fOufhrOfnMz2fp3/+eHQcPyGXn/cdGjXzysUfm7PO/kpPff0S6dOm8Qdv49IRTs+8x4/LQ7/6QI0bul5/+YFou+trVubz8g3Ts2CG77Dg4p598bJJkyx5b5LJvfT+TLrwyK1euzB677JifzPhatu65ZZLkq1MmZfyk83PgcR9L/7698/WLzs0j/zj6vybbbrttLrzwwkyePDnjx4/PRz/60Xzuc5/LrFmzMm3atNTX12fQoEH56le/mtGjR2/Q52tpVQ1t5X77bdQ/r6FfvHhxunfvXulx1u4C1/o3cUELHEn2vTbVEt9r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8iv1OeHfHl23MQZs2y8njTk85039ZpJkrz12yYJFf02HDh0ao/+fP/96VsLOOwzKpz/96dx11105/vjjG29Y17t37yxYsGC1qJ89e/ZaZ+jUqVNWrlzZZHnv3r0zduzYXHvttZk2bVq++92m/8jQUhyhb0apVEqpVEp9fX169OhR6XEAAADWW/v27fPEr29q/J//3U9/cW9eXlyfj538/tWOxCfJCUcdlu/dcEs++dEPrPP+Xnv99Sx48aWsWLEyz72wMDff+at87errcsZHT8wh+69+sHTun/+S2X+Ys9qynbYfmM0367pO+/rU6adk90NPzMOP1WXUgSOy79575NjTJuWKL34qO28/KM8vWJTbZ96b40Yfmt123j7nXjItHzh6VIbU9Mxzzz2X2tranHDCCUnefKb8okWLcsUVV+QDH/hA7rzzztxxxx3p3r17s/sfPHhwHnzwwcybNy/dunVLz549c8EFF2TvvffObrvtlmXLluWnP/1pdt1113X+/taXoAcAAFgfH/916++j/54ttqnuW3Rr9r3v/c8tGXXAiCYxn7wZ9Fd8+wf5v7o/rnUb/+rq627O1dfdnE6dOmbrrXpk7z12zY1XXZbjRh/aZN1JF17ZZNm9N38vB+yzbp+9euftc/jB78mUr1yVn/33N/Oz//5mvnB5OeMnXZBFf305/Xr3ykHv2TN9e/VM+/bt89eXF+ejn5qShS9NTK9evXL88cfnwgsvTJLsuuuu+fa3v51LL700F198cU444YScc845az26fs4552Ts2LGprq7O3//+98ydOzedOnXKeeedl3nz5qVr16458MADc8MNN6zT59kQVQ1v9SyCd7h/HqFfvHjxWv91pk24wJkETVywuAW24XttoiW+18R3uyb+ZluH77V1+F5bh/+MbT3+ZlvHJvq9vt5tQObu/9UM2bZ3unTYuJu5bZCWCPrnf7fx29gUteA/lmyM119/PXPnzs2QIUPSpUuX1d5b1w51DT0AAAAUkKAHAACAAhL0AAAAUECCHgAAAApI0AMAAPy7f9w73C3EaS0tcX96QQ8AAPBvOi77W7Lyjby2vNKTsKl67bXXkiQdO3bc4G14Dn0zyuVyyuVyVq5cWelRAACAt1n7Fa9ly2fvyIudPpBky2zWMal6O59e9/rrG7+NFU4vWKOW+G43QkNDQ1577bW8+OKL2XLLLdO+ffsN3pagb0apVEqpVGp8/h8AAPDO0u+p65MkLw4anbTv9PbufOncjd/GK4s2fhubopb4blvAlltumX79+m3UNgQ9AADAGlSlIds8dV36/OnHWd5l67f3EP3Ehzd+G986ceO3sSlqie92I3Xs2HGjjsz/k6AHAABYi/Yr/572S597e3fapcvGb2PJ/I3fxqaoJb7bNsJN8QAAAKCABD0AAAAUkKAHAACAAnIN/VtoaHjzUQ/19fUVnmQdLPNYiiZa4n9vvtemWur/Hny3TfmbbR2+19bhe20d/jO29fibbR2+19bhe209BWi7f/bnP3u0OVUNb7XGO9xzzz2XAQMGVHoMAAAA3mHmz5+f7bbbrtn3Bf1bWLVqVZ5//vlsscUWqXo7H1MB/6a+vj4DBgzI/Pnz071790qPA2vl75Wi8TdLkfh7pWj8za6/hoaGvPrqq+nfv3/atWv+Snmn3L+Fdu3arfVfRODt1r17d/9BSGH4e6Vo/M1SJP5eKRp/s+unR48eb7mOm+IBAABAAQl6AAAAKCBBDwXRuXPnnH/++encuXOlR4G35O+VovE3S5H4e6Vo/M22HjfFAwAAgAJyhB4AAAAKSNADAABAAQl6AAAAKCBBDwAAAAUk6KENmzp1ampqarLFFlukT58+OfbYYzNnzpxKjwXr7LLLLktVVVXOPvvsSo8Ca/SXv/wlH/7wh7P11luna9eu2WOPPfLwww9XeixYo5UrV+ZLX/pShgwZkq5du2aHHXbIxRdfHPe4pq2YNWtWxowZk/79+6eqqiq33HLLau83NDRkypQp2WabbdK1a9eMGjUqTz31VGWG3UQIemjD7rnnnpRKpTzwwAO5++67s3z58hx++OFZunRppUeDt1RbW5vvfOc7efe7313pUWCNXn755ey///7p2LFj7rjjjtTV1eWrX/1qttpqq0qPBmt0+eWX56qrrsq3vvWtPPHEE7n88stzxRVX5Jvf/GalR4MkydKlSzN06NCUy+U1vn/FFVfkG9/4RqZPn54HH3wwm2++eY444oi8/vrrb/Okmw6PrYMCWbRoUfr06ZN77rknBx10UKXHgWYtWbIke+21V7797W/nkksuybBhwzJt2rRKjwWrmTx5cn7zm9/k3nvvrfQosE7e9773pW/fvvne977XuOyEE05I165dc+2111ZwMmiqqqoqN998c4499tgkbx6d79+/fz7zmc/knHPOSZIsXrw4ffv2zYwZM/KhD32ogtMWlyP0UCCLFy9OkvTs2bPCk8DalUqlHH300Rk1alSlR4Fm3XbbbRk+fHhOPPHE9OnTJ3vuuWeuvvrqSo8Fzdpvv/0yc+bM/PGPf0ySPPbYY7nvvvsyevToCk8Gb23u3LlZsGDBav/doEePHhkxYkTuv//+Ck5WbB0qPQCwblatWpWzzz47+++/f3bfffdKjwPNuuGGG/Loo4+mtra20qPAWv3pT3/KVVddlUmTJuXzn/98amtrc9ZZZ6VTp04ZO3ZspceDJiZPnpz6+vrssssuad++fVauXJkvf/nLOfXUUys9GrylBQsWJEn69u272vK+ffs2vsf6E/RQEKVSKX/4wx9y3333VXoUaNb8+fPzqU99KnfffXe6dOlS6XFgrVatWpXhw4fn0ksvTZLsueee+cMf/pDp06cLetqkH/7wh7nuuuty/fXXZ7fddsvs2bNz9tlnp3///v5m4R3KKfdQABMnTsxPf/rT/OpXv8p2221X6XGgWY888khefPHF7LXXXunQoUM6dOiQe+65J9/4xjfSoUOHrFy5stIjQqNtttkm1dXVqy3bdddd8+c//7lCE8HanXvuuZk8eXI+9KEPZY899shHPvKRfPrTn87UqVMrPRq8pX79+iVJFi5cuNryhQsXNr7H+hP00IY1NDRk4sSJufnmm/PLX/4yQ4YMqfRIsFaHHXZYfv/732f27NmNP8OHD8+pp56a2bNnp3379pUeERrtv//+TR4F+sc//jGDBg2q0ESwdq+99lratVv9v763b98+q1atqtBEsO6GDBmSfv36ZebMmY3L6uvr8+CDD2bfffet4GTF5pR7aMNKpVKuv/763Hrrrdliiy0ary/q0aNHunbtWuHpoKktttiiyT0eNt9882y99dbu/UCb8+lPfzr77bdfLr300nzwgx/MQw89lO9+97v57ne/W+nRYI3GjBmTL3/5yxk4cGB22223/O53v8uVV16Z0047rdKjQZI3n3Lz9NNPN76eO3duZs+enZ49e2bgwIE5++yzc8kll2SnnXbKkCFD8qUvfSn9+/dvvBM+689j66ANq6qqWuPy73//+xk3btzbOwxsoJEjR3psHW3WT3/605x33nl56qmnMmTIkEyaNCkTJkyo9FiwRq+++mq+9KUv5eabb86LL76Y/v375+STT86UKVPSqVOnSo8H+fWvf51DDjmkyfKxY8dmxowZaWhoyPnnn5/vfve7eeWVV3LAAQfk29/+dnbeeecKTLtpEPQAAABQQK6hBwAAgAIS9AAAAFBAgh4AAAAKSNADAABAAQl6AAAAKCBBDwAAAAUk6AEAAKCABD0AAAAUkKAHAN52v/71r1NVVZVXXnml0qMAQGEJegCgiXHjxqWqqiqf/OQnm7xXKpVSVVWVcePGvf2DAQCNBD0AsEYDBgzIDTfckL///e+Ny15//fVcf/31GThwYAUnAwASQQ8ANGOvvfbKgAED8uMf/7hx2Y9//OMMHDgwe+65Z+OyZcuW5ayzzkqfPn3SpUuXHHDAAamtrV1tWz/72c+y8847p2vXrjnkkEMyb968Jvu77777cuCBB6Zr164ZMGBAzjrrrCxdurTVPh8AFJ2gBwCaddppp+X73/9+4+trrrkm48ePX22dz372s7npppvygx/8II8++mh23HHHHHHEEfnb3/6WJJk/f36OP/74jBkzJrNnz87pp5+eyZMnr7aNZ555JkceeWROOOGE/N///V9uvPHG3HfffZk4cWLrf0gAKKiqhoaGhkoPAQC0LePGjcsrr7ySq6++OgMGDMicOXOSJLvsskvmz5+f008/PVtuuWXK5XK22mqrzJgxI6ecckqSZPny5Rk8eHDOPvvsnHvuufn85z+fW2+9NY8//njj9idPnpzLL788L7/8crbccsucfvrpad++fb7zne80rnPffffl4IMPztKlS9OlS5e39wsAgALoUOkBAIC2q3fv3jn66KMzY8aMNDQ05Oijj06vXr0a33/mmWeyfPny7L///o3LOnbsmH322SdPPPFEkuSJJ57IiBEjVtvuvvvuu9rrxx57LP/3f/+X6667rnFZQ0NDVq1alblz52bXXXdtjY8HAIUm6AGAtTrttNMaT30vl8utso8lS5bkE5/4RM4666wm77kBHwCsmaAHANbqyCOPzBtvvJGqqqocccQRq723ww47pFOnTvnNb36TQYMGJXnzlPva2tqcffbZSZJdd901t91222q/98ADD6z2eq+99kpdXV123HHH1vsgALCJcVM8AGCt2rdvnyeeeCJ1dXVp3779au9tvvnmOeOMM3LuuefmzjvvTF1dXSZMmJDXXnstH/vYx5Ikn/zkJ/PUU0/l3HPPzZw5c3L99ddnxowZq23nc5/7XH77299m4sSJmT17dp566qnceuutbooHAGsh6AGAt9S9e/d07959je9ddtllOeGEE/KRj3wke+21V55++un8/Oc/z1ZbbZXkzVPmb7rpptxyyy0ZOnRopk+fnksvvXS1bbz73e/OPffckz/+8Y858MADs+eee2bKlCnp379/q382ACgqd7kHAACAAnKEHgAAAApI0AMAAEABCXoAAAAoIEEPAAAABSToAQAAoIAEPQAAABSQoAcAAIACEvQAAABQQIIeAAAACkjQAwAAQAEJegAAACig/x9RKjwMVpLueQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig = plt.figure(figsize=(12, 10))\n", + "ax = plt.axes()\n", + "x = np.linspace(1, 10, 10)\n", + "plt.title(\"Residual Error\")\n", + "plt.yscale(\"log\")\n", + "plt.xlabel(\"Mode\")\n", + "plt.ylabel(\"% Error\")\n", + "ax.bar(x, scipy_acc, label=\"SciPy Results\")\n", + "ax.bar(x, mapdl_acc, label=\"MAPDL Results\")\n", + "plt.legend(loc=\"lower right\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MAPDL is faster than SciPy.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mapdl is 17.1 times faster\n" + ] + } + ], + "source": [ + "ratio = scipy_elapsed_time / mapdl_elapsed_time\n", + "print(f\"Mapdl is {ratio:.3} times faster\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "stop mapdl\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mm._mapdl.exit()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10.8 ('.venv': venv)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + }, + "vscode": { + "interpreter": { + "hash": "bf638d82cb992c7aa831d859bf7561f8a1b8aa4ca0d9d2db664cf6501bcc33fa" + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/src/ansys/math/core/math.py b/src/ansys/math/core/math.py new file mode 100644 index 00000000..ddf8fa70 --- /dev/null +++ b/src/ansys/math/core/math.py @@ -0,0 +1,1808 @@ +"""Contains the MapdlMath classes, allowing for math operations within +Ansys Math from Python.""" +from enum import Enum +import os +import random +import string +from warnings import warn + +from ansys.api.mapdl.v0 import ansys_kernel_pb2 as anskernel +from ansys.api.mapdl.v0 import mapdl_pb2 as pb_types +from ansys.mapdl.core.check_version import VersionError, meets_version, version_requires +from ansys.mapdl.core.common_grpc import ( + ANSYS_VALUE_TYPE, + DEFAULT_CHUNKSIZE, + DEFAULT_FILE_CHUNK_SIZE, +) +from ansys.mapdl.core.errors import ANSYSDataTypeError, protect_grpc +from ansys.mapdl.core.launcher import launch_mapdl +from ansys.mapdl.core.misc import load_file +from ansys.mapdl.core.parameters import interp_star_status +import numpy as np + +MYCTYPE = { + np.int32: "I", + np.int64: "L", + np.single: "F", + np.double: "D", + np.complex64: "C", + np.complex128: "Z", +} + + +NP_VALUE_TYPE = {value: key for key, value in ANSYS_VALUE_TYPE.items()} + +# for windows LONG vs INT32 +if os.name == "nt": + NP_VALUE_TYPE[np.intc] = 1 + + +def id_generator(size=6, chars=string.ascii_uppercase): + """Generate a random string""" + return "".join(random.choice(chars) for _ in range(size)) + + +class ObjType(Enum): + """Generic APDLMath Object ( Shared features between Vec Mat and + Solver components""" + + GEN = 1 + VEC = 2 + DMAT = 3 + SMAT = 4 + + +def get_nparray_chunks(name, array, chunk_size=DEFAULT_FILE_CHUNK_SIZE): + """Serializes a numpy array into chunks""" + stype = NP_VALUE_TYPE[array.dtype.type] + arr_sz = array.size + i = 0 # position counter + byte_array = array.tobytes() + while i < len(byte_array): + piece = byte_array[i : i + chunk_size] + chunk = anskernel.Chunk(payload=piece, size=len(piece)) + yield pb_types.SetVecDataRequest(vname=name, stype=stype, size=arr_sz, chunk=chunk) + i += chunk_size + + +def get_nparray_chunks_mat(name, array, chunk_size=DEFAULT_FILE_CHUNK_SIZE): + """Serializes a 2D numpy array into chunks + + Uses the ``SetMatDataRequest`` + + """ + stype = NP_VALUE_TYPE[array.dtype.type] + sh1 = array.shape[0] + sh2 = array.shape[1] + i = 0 # position counter + byte_array = array.tobytes(order="F") + while i < len(byte_array): + piece = byte_array[i : i + chunk_size] + chunk = anskernel.Chunk(payload=piece, size=len(piece)) + yield pb_types.SetMatDataRequest(mname=name, stype=stype, nrow=sh1, ncol=sh2, chunk=chunk) + i += chunk_size + + +def list_allowed_dtypes(): + """Return a list of human readable Mapdl supported datatypes""" + dtypes = list(NP_VALUE_TYPE.keys()) + if None in dtypes: + dtypes.remove(None) + return "\n".join([f"{dtype}" for dtype in dtypes]) + + +class MapdlMath: + """Abstract mapdl math class. + + Examples + -------- + Create an instance. + + >>> from ansys.math.core import launch_math + >>> mm = launch_math() + + Vector addition + + >>> v1 = mm.ones(10) + >>> v2 = mm.ones(10) + >>> v3 = v1 + v2 + + Matrix multiplcation (not yet available) + + >>> v1 = mm.ones(10) + >>> m1 = mm.rand(10, 10) + >>> v2 = m1*v1 + + """ + + def __init__(self, mapdl=None): + if mapdl is None: + mapdl = launch_mapdl() + # if not isinstance(mapdl, MapdlGrpc): + # raise TypeError("``mapdl`` must be a MapdlGrpc instance") + self._mapdl = mapdl + # self._mapdl_weakref = weakref.ref(mapdl) + + # @property + # def _mapdl(self): + # """Return the weakly referenced instance of mapdl.""" + # return self._mapdl_weakref() + + @property + def _server_version(self): + """Return the version of MAPDL which is running in the background.""" + return self._mapdl._server_version + + @property + def _status(self): + """Print out the status of all APDLMath Objects""" + return self._mapdl.run("*STATUS,MATH", mute=False) + + @property + def _parm(self): + return interp_star_status(self._status) + + def free(self): + """Delete all vectors. + + Examples + -------- + >>> mm.free() + """ + self._mapdl.run("*FREE,ALL", mute=True) + + def __repr__(self): + return self._status + + def status(self): + """Print out the status of all APDLMath Objects. + + Examples + -------- + >>> mm.status() + APDLMATH PARAMETER STATUS- ( 4 PARAMETERS DEFINED) + Name Type Mem. (MB) Dims Workspace + NJHLVM SMAT 0.011 [126:126] 1 + RMAXLQ SMAT 0.011 [126:126] 1 + WWYLBR SMAT 0.011 [126:126] 1 + FIOMZR VEC 0.001 126 1 + + """ + print(self._status) + + def vec(self, size=0, dtype=np.double, init=None, name=None, asarray=False): + """Create a vector. + + Parameters + ---------- + size : int + Size of the vector + + dtype : np.dtype, optional + Datatype of the vector. Must be either ``np.int32``, + ``np.int64``, or ``np.double``. + + init : str, optional + Initialization options. Can be ``"ones"``, ``"zeros"``, + or ``"rand"``. + + name : str, optional + Give the vector a name. Otherwise one will be automatically + generated. + + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + ansys.mapdl.math.AnsVec or numpy.ndarray + APDLMath Vector or :class:`numpy.ndarray`. + """ + if dtype not in MYCTYPE: + raise ANSYSDataTypeError + + if not name: + name = id_generator() + + if name.upper() not in self._parm: + self._mapdl.run(f"*VEC,{name},{MYCTYPE[dtype]},ALLOC,{size}", mute=True) + + ans_vec = AnsVec(name, self._mapdl, dtype, init) + + if asarray: + return self._mapdl._vec_data(ans_vec.id) + else: + return ans_vec + + def mat(self, nrow=0, ncol=0, dtype=np.double, init=None, name=None, asarray=False): + """Create an APDLMath matrix. + + Parameters + ---------- + nrow : int + Number of rows. + ncol : int + Number of columns. + dtype : np.dtype, optional + Datatype of the vector. Must be either ``np.int32``, + ``np.int64``, or ``np.double``. + init : str, optional + Initialization options. Can be ``"ones"``, ``"zeros"``, + or ``"rand"``. + name : str, optional + Matrix name. If given, assigns a MAPDL matrix based on + the existing named matrix. Otherwise one will be + automatically generated. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + AnsMat + APDLMath matrix. + """ + if dtype not in MYCTYPE: + raise ValueError("Invalid datatype. Must be one of the following:\n" "np.int32, np.int64, or np.double") + + if not name: + name = id_generator() + self._mapdl.run(f"*DMAT,{name},{MYCTYPE[dtype]},ALLOC,{nrow},{ncol}", mute=True) + mat = AnsDenseMat(name, self._mapdl) + + if init == "rand": + mat.rand() + elif init == "ones": + mat.ones() + elif init == "zeros": + mat.zeros() + elif init is not None: + raise ValueError(f"Invalid init method '{init}'") + else: + info = self._mapdl._data_info(name) + if info.objtype == pb_types.DataType.DMAT: + mat = AnsDenseMat(name, self._mapdl) + elif info.objtype == pb_types.DataType.SMAT: + mat = AnsSparseMat(name, self._mapdl) + else: # pragma: no cover + raise ValueError(f"Unhandled MAPDL matrix object type {info.objtype}") + + if asarray: + mat = mat.asarray() + return mat + + def zeros(self, nrow, ncol=None, dtype=np.double, name=None, asarray=False): + """Create a vector or matrix containing all zeros. + + Parameters + ---------- + nrow : int + Number of rows. + ncol : int, optional + Number of columns. If specified, returns a matrix. + dtype : np.dtype, optional + Datatype of the vector. Must be either ``np.int32``, + ``np.int64``, or ``np.double``. + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + AnsVec or AnsMat + APDLMath vector or matrix depending on if ``ncol`` is specified. + + Examples + -------- + Create a zero vector. + + >>> from ansys.math.core import launch_math + >>> mm = launch_math() + >>> vec = mm.zeros(10) + + Create a zero matrix. + + >>> mat = mm.zeros(10, 10) + """ + if not ncol: + return self.vec(nrow, dtype, init="zeros", name=name, asarray=asarray) + return self.mat(nrow, ncol, dtype, init="zeros", name=name, asarray=asarray) + + def ones(self, nrow, ncol=None, dtype=np.double, name=None, asarray=False): + """Create a vector or matrix containing all ones + + Parameters + ---------- + nrow : int + Number of rows. + ncol : int, optional + Number of columns. If specified, returns a matrix. + dtype : np.dtype, optional + Datatype of the vector. Must be either ``np.int32``, + ``np.int64``, or ``np.double``. + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + AnsVec or AnsMat + APDLMath vector or matrix depending on if "ncol" is + specified. + + Examples + -------- + Create a ones vector. + + >>> from ansys.math.core import launch_math + >>> mm = launch_math() + >>> vec = mm.ones(10) + + Create a ones matrix. + + >>> mat = mm.ones(10, 10) + """ + if not ncol: + return self.vec(nrow, dtype, init="ones", name=name, asarray=asarray) + else: + return self.mat(nrow, ncol, dtype, init="ones", name=name, asarray=asarray) + + def rand(self, nrow, ncol=None, dtype=np.double, name=None, asarray=False): + """Create a vector or matrix containing all random values + + Parameters + ---------- + nrow : int + Number of rows. + ncol : int, optional + Number of columns. If specified, returns a matrix. + dtype : np.dtype, optional + Datatype of the vector. Must be either ``np.int32``, + ``np.int64``, or ``np.double``. + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + AnsVec or AnsMat + APDLMath vector or matrix depending on if "ncol" is + specified. + + Examples + -------- + Create a random vector. + + >>> from ansys.math.core import launch_math + >>> mm = launch_math() + >>> vec = mm.rand(10) + + Create a random matrix. + + >>> mat = mm.rand(10, 10) + """ + if not ncol: + return self.vec(nrow, dtype, init="rand", name=name, asarray=asarray) + return self.mat(nrow, ncol, dtype, init="rand", name=name, asarray=asarray) + + def matrix(self, matrix, name=None, triu=False): + """Send a scipy matrix or numpy array to MAPDL. + + Parameters + ---------- + matrix : np.ndarray + Numpy array to send as a matrix to MAPDL. + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + triu : bool, optional + ``True`` when the matrix is upper triangular, ``False`` + when unsymmetric. + + Returns + ------- + AnsMat + MapdlMath matrix. + + Examples + -------- + Generate a random sparse matrix. + + >>> from scipy import sparse + >>> sz = 5000 + >>> mat = sparse.random(sz, sz, density=0.05, format='csr') + >>> ans_mat = mm.matrix(mat, name) + >>> ans_mat + APDLMath Matrix 5000 x 5000 + + Transfer the matrix back to Python. + + >>> ans_mat.asarray() + <500x5000 sparse matrix of type '' + with 1250000 stored elements in Compressed Sparse Row format> + + """ + if name is None: + name = id_generator() + elif not isinstance(name, str): + raise TypeError("``name`` parameter must be a string") + + from scipy import sparse + + self._set_mat(name, matrix, triu) + if sparse.issparse(matrix): + return AnsSparseMat(name, self._mapdl) + return AnsDenseMat(name, self._mapdl) + + def load_matrix_from_file( + self, + dtype=np.double, + name=None, + fname="file.full", + mat_id="STIFF", + asarray=False, + ): + """Import a matrix from an existing FULL file. + + Parameters + ---------- + dtype : numpy.dtype, optional + Numpy data type to store the vector as. You can use double ("DOUBLE" or "D"), + or complex numbers ("COMPLEX" or "Z"). Alternatively you can also supply a + numpy data type. Defaults to ``np.double``. + fname : str, optional + Filename to read the matrix from. Defaults to ``"file.full"``. + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + mat_id : str, optional + Matrix type. Defaults to ``"STIFF"``. + + * ``"STIFF"`` - Stiffness matrix + * ``"MASS"`` - Mass matrix + * ``"DAMP"`` - Damping matrix + * ``"GMAT"`` - Constraint equation matrix + * ``"K_RE"`` - Real part of the stiffness matrix + * ``"K_IM"`` - Imaginary part of the stiffness matrix + asarray : bool, optional + Return a ``scipy`` array rather than an APDLMath matrix. + + Returns + ------- + scipy.sparse.csr.csr_matrix or AnsMat + Scipy sparse matrix or APDLMath matrix depending on + ``asarray``. + + """ + if name is None: + name = id_generator() + elif not isinstance(name, str): + raise TypeError("``name`` parameter must be a string") + + self._mapdl._log.info("Calling MAPDL to extract the %s matrix from %s", mat_id, fname) + quotes = "'" + allowed_mat_id = ( + "STIFF", + "MASS", + "DAMP", + # "NOD2BCS", # Not allowed since #990 + # "USR2BCS", + "GMAT", + "K_RE", + "K_IM", + ) + if mat_id.upper() not in allowed_mat_id: + raise ValueError( + f"The 'mat_id' parameter supplied ('{mat_id}') is not allowed. " + f"Only the following are allowed: \n" + f"{', '.join([quotes + each + quotes for each in allowed_mat_id])}" + ) + + if isinstance(dtype, str): + if dtype.lower() not in ("complex", "double", "d", "z"): + raise ValueError( + f"Data type ({dtype}) not allowed as a string." + "Use either: 'double' or 'complex', or a valid numpy data type." + ) + if dtype.lower() in ("complex", "z"): + dtype_ = "'Z'" + dtype = np.complex64 + else: + dtype_ = "'D'" + dtype = np.double + else: + if dtype not in ANSYS_VALUE_TYPE.values(): + allowables_np_dtypes = ", ".join( + [str(each).split("'")[1] for each in ANSYS_VALUE_TYPE.values() if each] + ) + raise ValueError(f"Numpy data type not allowed. Only: {allowables_np_dtypes}") + if "complex" in str(dtype): + dtype_ = "'Z'" + else: + dtype_ = "'D'" + + if dtype_ == "'Z'" and mat_id.upper() in ("STIFF", "MASS", "DAMP"): + raise ValueError("Reading the stiffness, mass or damping matrices to a complex " "array is not supported.") + + self._mapdl.run(f"*SMAT,{name},{dtype_},IMPORT,FULL,{fname},{mat_id}", mute=True) + ans_sparse_mat = AnsSparseMat(name, self._mapdl) + if asarray: + return self._mapdl._mat_data(ans_sparse_mat.id).astype(dtype) + return ans_sparse_mat + + def _load_file(self, fname): + """ + Provide file to MAPDL instance. + + If in local: + Checks if the file exists, if not, it raises a FileNotFound exception + + If in not-local: + Check if the file exists locally or in the working directory, if not, + it will raise a FileNotFound exception. + If the file is local, it will be uploaded. + + """ + return load_file(self._mapdl, fname) + + def stiff(self, dtype=np.double, name=None, fname="file.full", asarray=False): # to be moved to .io + """Load the stiffness matrix from a full file. + + Parameters + ---------- + dtype : numpy.dtype, optional + Numpy data type to store the vector as. Only applicable if + ``asarray=True``, otherwise the returned matrix contains + double float numbers. Defaults to ``np.double`` + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + fname : str, optional + Filename to read the matrix from. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + scipy.sparse.csr.csr_matrix or AnsMat + Scipy sparse matrix or APDLMath matrix depending on + ``asarray``. + + Examples + -------- + >>> k = mm.stiff() + APDLMATH Matrix 60 x 60 + + Convert to a scipy array + + >>> mat = k.asarray() + >>> mat + <60x60 sparse matrix of type '' + with 1734 stored elements in Compressed Sparse Row format> + """ + fname = self._load_file(fname) + return self.load_matrix_from_file(dtype, name, fname, "STIFF", asarray) + + def mass(self, dtype=np.double, name=None, fname="file.full", asarray=False): # to be moved to .io + """Load the mass matrix from a full file. + + Parameters + ---------- + dtype : numpy.dtype, optional + Numpy data type to store the vector as. Only applicable if + ``asarray=True``, otherwise the returned matrix contains + double float numbers. Defaults to ``np.double`` + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + fname : str, optional + Filename to read the matrix from. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + scipy.sparse.csr.csr_matrix or AnsMat + Scipy sparse matrix or APDLMath matrix depending on + ``asarray``. + + Examples + -------- + >>> mass = mapdl.math.mass() + >>> mass + APDLMATH Matrix 60 x 60 + + Convert to a scipy array + + >>> mat = mass.asarray() + >>> mat + <60x60 sparse matrix of type '' + with 1734 stored elements in Compressed Sparse Row format> + """ + fname = self._load_file(fname) + return self.load_matrix_from_file(dtype, name, fname, "MASS", asarray) + + def damp(self, dtype=np.double, name=None, fname="file.full", asarray=False): # to be moved to .io + """Load the damping matrix from the full file. + + Parameters + ---------- + dtype : numpy.dtype, optional + Numpy data type to store the vector as. Only applicable if + ``asarray=True``, otherwise the returned matrix contains + double float numbers. Defaults to ``np.double`` + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + fname : str, optional + Filename to read the matrix from. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + scipy.sparse.csr.csr_matrix or AnsMat + Scipy sparse matrix or APDLMath matrix depending on + ``asarray``. + + Examples + -------- + >>> ans_mat = mapdl.math.damp() + >>> ans_mat + APDLMATH Matrix 60 x 60 + + Convert to a scipy array + + >>> mat = ans_mat.asarray() + >>> mat + <60x60 sparse matrix of type '' + with 1734 stored elements in Compressed Sparse Row format> + + """ + fname = self._load_file(fname) + return self.load_matrix_from_file(dtype, name, fname, "DAMP", asarray) + + def get_vec(self, dtype=None, name=None, fname="file.full", mat_id="RHS", asarray=False): # to be moved to .io + """Load a vector from a file. + + Parameters + ---------- + dtype : numpy.dtype, optional + Numpy data type to store the vector as. Defaults to + ``np.double``. + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + fname : str, optional + Filename to read the vector from. + mat_id : str, optional + Vector ID to load. If loading from a ``"*.full"`` file, + can be one of the following: + + * ``"RHS"`` - Load vector + * ``"GVEC"`` - Constraint equation constant terms + * ``"BACK"`` - nodal mapping vector (internal to user). + If this is used, the default ``dtype`` is ``np.int32``. + * ``"FORWARD"`` - nodal mapping vector (user to internal) + If this is used, the default ``dtype`` is ``np.int32``. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + numpy.ndarray or AnsVec + Numpy array or APDLMath vector depending on ``asarray``. + + Examples + -------- + >>> vec = mm.get_vec(fname='PRSMEMB.full', mat_id="RHS") + >>> vec + APDLMath Vector Size 126 + + """ + if name is None: + name = id_generator() + elif not isinstance(name, str): + raise TypeError("``name`` parameter must be a string") + + self._mapdl._log.info("Call MAPDL to extract the %s vector from the file %s", mat_id, fname) + + if mat_id.upper() not in ["RHS", "GVEC", "BACK", "FORWARD"]: + raise ValueError( + f"The 'mat_id' value ({mat_id}) is not allowed." 'Only "RHS", "GVEC", "BACK", or "FORWARD" are allowed.' + ) + + if mat_id.upper() in ["BACK", "FORWARD"] and not dtype: + dtype = np.int32 + else: + dtype = np.double + + fname = self._load_file(fname) + self._mapdl.run(f"*VEC,{name},{MYCTYPE[dtype]},IMPORT,FULL,{fname},{mat_id}", mute=True) + ans_vec = AnsVec(name, self._mapdl) + if asarray: + return self._mapdl._vec_data(ans_vec.id).astype(dtype, copy=False) + return ans_vec + + def set_vec(self, data, name=None): + """Push a numpy array or Python list to the MAPDL memory workspace. + + Parameters + ---------- + data : np.ndarray, list + Numpy array or Python list to push to MAPDL. Must be 1 + dimensional. + name : str, optional + APDLMath vector name. If unset, one will be automatically + generated. + + Returns + ------- + ansys.mapdl.math.AnsVec + MAPDL vector instance generated from the pushed vector. + + Examples + -------- + Push a random vector from numpy to MAPDL. + + >>> data = np.random.random(10) + >>> vec = mm.set_vec(data) + >>> np.isclose(vec.asarray(), data) + True + """ + if name is None: + name = id_generator() + self._set_vec(name, data) + return AnsVec(name, self._mapdl) + + def rhs(self, dtype=np.double, name=None, fname="file.full", asarray=False): # to be moved to .io + """Return the load vector from a full file. + + Parameters + ---------- + dtype : numpy.dtype, optional + Data type to store the vector as. Defaults to ``np.double``. + name : str, optional + APDLMath matrix name. Optional and defaults to a random name. + fname : str, optional + Filename to read the vector from. Defaults to ``"file.full"``. + asarray : bool, optional + Return a `scipy` array rather than an APDLMath matrix. + + Returns + ------- + numpy.ndarray or ansys.mapdl.math.AnsVec + Numpy or APDL vector instance generated from the file. + + Examples + -------- + >>> rhs = mm.rhs(fname='PRSMEMB.full') + APDLMath Vector Size 126 + + """ + fname = self._load_file(fname) + return self.get_vec(dtype, name, fname, "RHS", asarray) + + def svd(self, mat, thresh="", sig="", v="", **kwargs): + """Apply an SVD Algorithm on a matrix. + + The SVD algorithm is only applicable to dense matrices. + Columns that are linearly dependent on others are removed, + leaving the independent or basis vectors. The matrix is + resized according to the new size determined by the algorithm. + + For the SVD algorithm, the singular value decomposition of an + input matrix is a factorization of the form: + + ``M = U*SIGMA*V.T`` + + For more details, see `Singular Value Decomposition + `_. + + Parameters + ---------- + mat : ansys.AnsMat + The array to compress. + thresh : float, optional + Numerical threshold value used to manage the compression. + Default is 1E-7. + sig : str, optional + Name of the vector used to store the ``SIGMA`` values. + v : str, optional + Name of the vector used to store the values from ``v``. + See the equation above. + + Examples + -------- + Apply SVD on an existing Dense Rectangular Matrix, using + default threshold. The matrix is modified in-place. + + >>> mm.svd(mat) + """ + kwargs.setdefault("mute", True) + self._mapdl.run(f"*COMP,{mat.id},SVD,{thresh},{sig},{v}", **kwargs) + + def mgs(self, mat, thresh="", **kwargs): + """Apply Modified Gram-Schmidt algorithm to a matrix. + + The MGS algorithm is only applicable to dense + matrices. Columns that are linearly dependent on others are + removed, leaving the independent or basis vectors. The matrix + is resized according to the new size determined by the + algorithm. + + Parameters + ---------- + mat : ansys.mapdl.core.math.AnsMat + The array to apply Modified Gram-Schmidt algorithm to. + thresh : float, optional + Numerical threshold value used to manage the compression. + The default value is 1E-14 for MGS. + + Examples + -------- + Apply MGS on an existing Dense Rectangular Matrix, using + default threshold. The mat matrix is modified in-situ. + + >>> mm.mgs(mat) + """ + kwargs.setdefault("mute", True) + self._mapdl.run(f"*COMP,{mat.id},MGS,{thresh}", **kwargs) + + def sparse(self, mat, thresh="", **kwargs): + """Sparsify a existing matrix based on a threshold value. + + Parameters + ---------- + mat : ansys.mapdl.core.math.AnsMat + The dense matrix to convert to a sparse matrix. + thresh : float, optional + Numerical threshold value used to sparsify. The default + value is 1E-16. + """ + kwargs.setdefault("mute", True) + self._mapdl.run(f"*COMP,{mat.id},SPARSE,{thresh}", **kwargs) + + def eigs(self, nev, k, m=None, c=None, phi=None, algo=None, fmin=None, fmax=None): + """Solve an eigenproblem. + + Parameters + ---------- + nev : int + Number of eigenvalues to compute. + k : ansys.AnsMat + An array representing the operation ``A * x`` where A is a + square matrix. + m : ansys.AnsMat, optional + An array representing the operation ``M * x`` for the + generalized eigenvalue problem: + + ``K * x = M * x`` + + Examples + -------- + Solve an eigenproblem using the mass and stiffness matrices + stored from a prior ansys run. + + >>> k = mm.stiff() + >>> m = mm.mass() + >>> nev = 10 + >>> a = mm.mat(k.nrow, nev) + >>> ev = mm.eigs(nev, k, m, phi=a) + """ + if not fmin: + fmin = "" + if not fmax: + fmax = "" + + cid = "" + if not c: + if k.sym() and m.sym(): + if not algo: + algo = "LANB" + else: + algo = "UNSYM" + else: + cid = c.id + algo = "DAMP" + + self._mapdl.run("/SOLU", mute=True) + self._mapdl.run("antype,modal", mute=True) + self._mapdl.run(f"modopt,{algo},{nev},{fmin},{fmax}", mute=True) + ev = self.vec() + + phistr = "" if not phi else phi.id + self._mapdl.run(f"*EIG,{k.id},{m.id},{cid},{ev.id},{phistr}", mute=True) + return ev + + def dot(self, vec_a, vec_b): + """Dot product between two ANSYS vector objects. + + Parameters + ---------- + vec_a : ansys.mapdl.math.AnsVec + Ansys vector object. + + vec_b : ansys.mapdl.math.AnsVec + Ansys vector object. + + Returns + ------- + float + Dot product between the two vectors. + + Examples + -------- + >>> v = mm.ones(10) + >>> w = mm.ones(10) + >>> v.dot(w) + """ + return dot(vec_a, vec_b) + + def add(self, obj1, obj2): + """Add two APDLMath vectors or matrices. + + Parameters + ---------- + obj1 : ansys.mapdl.math.AnsVec or ansys.mapdl.math.AnsMat + Ansys object. + obj2 : ansys.mapdl.math.AnsVec or ansys.mapdl.math.AnsMat + Ansys object. + + Returns + ------- + AnsVec or AnsMat + Sum of the two input objects. Type of the output matches + type of the input. Sum of the two vectors/matrices. + + Examples + -------- + Comupute the sum between two vectors. + + >>> v = mm.ones(10) + >>> w = mm.ones(10) + >>> x = mm.add(v, w) + """ + return obj1 + obj2 + + def subtract(self, obj1, obj2): + """Subtract two ANSYS vectors or matrices. + + Parameters + ---------- + obj1 : ansys.mapdl.math.AnsVec or ansys.mapdl.math.AnsMat + Ansys object. + obj2 : ansys.mapdl.math.AnsVec or ansys.mapdl.math.AnsMat + Ansys object. + + Returns + ------- + AnsVec or AnsMat + Difference of the two input vectors or matrices. Type of + the output matches the type of the input. + + Examples + -------- + Subtract two APDLMath vectors. + + >>> v = mm.ones(10) + >>> w = mm.ones(10) + >>> x = mm.subtract(v, w) + """ + return obj1 - obj2 + + def factorize(self, mat, algo=None, inplace=True): + """Factorize a matrix. + + Parameters + ---------- + mat : ansys.mapdl.math.AnsMat + An APDLMath matrix + algo : str, optional + Factorization algorithm. Either ``"LAPACK"`` (default for + dense matrices) or ``"DSP"`` (default for sparse matrices). + inplace : bool, optional + If ``False``, the factorization is performed on a copy + of the input matrix (``mat`` argument), hence this input + matrix (``mat``) is not changed. Default is ``True``. + + Returns + ------- + ansys.mapdl.core.math.AnsSolver + An Ansys Solver object. + + + Examples + -------- + Factorize a random matrix. + + >>> dim = 1000 + >>> m2 = mm.rand(dim, dim) + >>> m3 = m2.copy() + >>> mat = mm.factorize(m2) + + """ + solver = AnsSolver(id_generator(), self._mapdl) + solver.factorize(mat, algo=algo, inplace=inplace) + return solver + + def norm(self, obj, order="nrm2"): + """Matrix or vector norm. + + Parameters + ---------- + obj : ansys.mapdl.math.AnsMat or ansys.mapdl.math.AnsVec + ApdlMath object to compute the norm from. + order : str + Mathematical norm to use. One of: + + * ``'NRM2'``: L2 (Euclidean or SRSS) norm (default). + * ``'NRM1'``: L1 (absolute sum) norm (vectors only). + * ``'NRMINF'`` Maximum norm. + nrm : float + Norm of the matrix or vector(s). + + Examples + -------- + Compute the norm of a APDLMath vector. + v = mm.ones(10) + 3.1622776601683795 + """ + return obj.norm(nrmtype=order) + + @protect_grpc + def _set_vec(self, vname, arr, dtype=None, chunk_size=DEFAULT_CHUNKSIZE): + """Transfer a numpy array to MAPDL as a MAPDL Math vector. + + Parameters + ---------- + vname : str + Vector parameter name. Character ":" is not allowed. + arr : np.ndarray + Numpy array to upload + dtype : np.dtype, optional + Type to upload array as. Defaults to the current array type. + chunk_size : int, optional + Chunk size in bytes. Must be less than 4MB. + + """ + if ":" in vname: + raise ValueError('The character ":" is not permitted in a MAPDL MATH' " vector parameter name") + if not isinstance(arr, np.ndarray): + arr = np.asarray(arr) + + if dtype is not None: + if arr.dtype != dtype: + arr = arr.astype(dtype) + + if arr.dtype not in list(MYCTYPE.keys()): + raise TypeError( + f"Invalid array datatype {arr.dtype}\n" f"Must be one of the following:\n" f"{list_allowed_dtypes()}" + ) + + chunks_generator = get_nparray_chunks(vname, arr, chunk_size) + self._mapdl._stub.SetVecData(chunks_generator) + + @protect_grpc + def _set_mat(self, mname, arr, sym=None, dtype=None, chunk_size=DEFAULT_CHUNKSIZE): + """Transfer a 2D dense or sparse scipy array to MAPDL as a MAPDL Math matrix. + + Parameters + ---------- + mname : str + Matrix parameter name. Character ":" is not allowed. + arr : np.ndarray or scipy.sparse matrix + Matrix to upload + sym : bool + ``True`` when matrix is symmetric. Unused if Matrix is dense. + dtype : np.dtype, optional + Type to upload array as. Defaults to the current array type. + chunk_size : int, optional + Chunk size in bytes. Must be less than 4MB. + + """ + from scipy import sparse + + if ":" in mname: + raise ValueError('The character ":" is not permitted in a MAPDL MATH' " matrix parameter name") + if not len(mname): + raise ValueError("Empty MAPDL matrix name not permitted") + + if isinstance(arr, np.ndarray): + if arr.ndim == 1: + raise ValueError("Input appears to be an array. " "Use ``set_vec`` instead.)") + if arr.ndim > 2: + raise ValueError("Arrays must be 2 dimensional") + + if sparse.issparse(arr): + self._send_sparse(mname, arr, sym, dtype, chunk_size) + else: # must be dense matrix + self._send_dense(mname, arr, dtype, chunk_size) + + @version_requires((0, 4, 0)) + def _send_dense(self, mname, arr, dtype, chunk_size): + """Send a dense numpy array/matrix to MAPDL.""" + if dtype is not None: + if arr.dtype != dtype: + arr = arr.astype(dtype) + + if arr.dtype not in list(NP_VALUE_TYPE.keys()): + raise TypeError( + f"Invalid array datatype {arr.dtype}\n" f"Must be one of the following:\n" f"{list_allowed_dtypes()}" + ) + + chunks_generator = get_nparray_chunks_mat(mname, arr, chunk_size) + self._mapdl._stub.SetMatData(chunks_generator) + + def _send_sparse(self, mname, arr, sym, dtype, chunk_size): + """Send a scipy sparse sparse matrix to MAPDL.""" + if sym is None: + raise ValueError("The symmetric flag ``sym`` must be set for a sparse " "matrix") + from scipy import sparse + + arr = sparse.csr_matrix(arr) + + if arr.shape[0] != arr.shape[1]: + raise ValueError("APDLMath only supports square matrices") + + if dtype is not None: + if arr.data.dtype != dtype: + arr.data = arr.data.astype(dtype) + + if arr.dtype not in list(NP_VALUE_TYPE.keys()): + raise TypeError( + f"Invalid array datatype {arr.dtype}\n" f"Must be one of the following:\n" f"{list_allowed_dtypes()}" + ) + + # data vector + dataname = f"{mname}_DATA" + ans_vec = self.set_vec(arr.data, dataname) + if dtype is None: + info = self._mapdl._data_info(ans_vec.id) + dtype = ANSYS_VALUE_TYPE[info.stype] + + # indptr vector + indptrname = f"{mname}_IND" + indv = arr.indptr.astype("int64") + 1 # FORTRAN indexing + self.set_vec(indv, indptrname) + + # indices vector + indxname = f"{mname}_PTR" + idx = arr.indices + 1 # FORTRAN indexing + self.set_vec(idx, indxname) + + flagsym = "TRUE" if sym else "FALSE" + self._mapdl.run(f"*SMAT,{mname},{MYCTYPE[dtype]},ALLOC,CSR,{indptrname},{indxname}," f"{dataname},{flagsym}") + + +class ApdlMathObj: + """Common class for MAPDL Math objects""" + + def __init__(self, id_, mapdl=None, dtype=ObjType.GEN): + if mapdl is None: + mapdl = launch_mapdl() + self.id = id_ + self._mapdl = mapdl + self.type = dtype + + def __repr__(self): + return f"APDLMath Object {self.id}" + + def __str__(self): + return self._mapdl.run(f"*PRINT,{self.id}", mute=False) + + def copy(self): + """Returns the name of the copy of this object""" + name = id_generator() # internal name of the new vector + info = self._mapdl._data_info(self.id) + dtype = ANSYS_VALUE_TYPE[info.stype] + + if self.type == ObjType.VEC: + acmd = "*VEC" + elif self.type == ObjType.DMAT: + acmd = "*DMAT" + elif self.type == ObjType.SMAT: + acmd = "*SMAT" + else: + raise TypeError(f"Copy aborted: Unknown obj type {self.type}") + + # APDLMath cmd to COPY vin to vout + self._mapdl.run(f"{acmd},{name},{MYCTYPE[dtype]},COPY,{self.id}", mute=True) + return name + + def _init(self, method): + self._mapdl.run(f"*INIT,{self.id},{method}", mute=True) + + def zeros(self): + """Set all values of the vector to zero""" + return self._init("ZERO") + + def ones(self): + """Set all values of the vector to one""" + return self._init("CONST,1") + + def rand(self): + """Set all values of the vector to a random number""" + return self._init("RAND") + + def const(self, value): + """Set all values of the vector to a constant""" + return self._init(f"CONST,{value}") + + def norm(self, nrmtype="nrm2"): + """Matrix or vector norm. + + Parameters + ---------- + nrmtype : str, optional + Mathematical norm to use. One of: + + - ``'NRM2'``: L2 (Euclidean or SRSS) norm (default). + - ``'NRM1'``: L1 (absolute sum) norm (vectors only). + - ``'NRMINF'`` : Maximum norm. + + Returns + ------- + float + Norm of the matrix or vector(s). + + Examples + -------- + >>> dim = 1000 + >>> m2 = mm.rand(dim, dim) + >>> nrm = mm.norm( m2) + """ + val_name = "py_val" + self._mapdl.run(f"*NRM,{self.id},{nrmtype},{val_name}", mute=True) + return self._mapdl.scalar_param(val_name) + + def axpy(self, op, val1, val2): + """Perform the matrix operation: ``M2= v*M1 + w*M2``""" + if not hasattr(op, "id"): + raise TypeError("Must be an ApdlMathObj") + self._mapdl._log.info("Call Mapdl to perform AXPY operation") + self._mapdl.run(f"*AXPY,{val1},0,{op.id},{val2},0,{self.id}", mute=True) + return self + + def __add__(self, op2): + if not hasattr(op2, "id"): + raise TypeError("Must be an ApdlMathObj") + + opout = self.copy() + self._mapdl._log.info("Call Mapdl to perform AXPY operation") + self._mapdl.run(f"*AXPY,1,0,{op2.id},1,0,{opout.id}", mute=True) + return opout + + def __sub__(self, op2): + if not hasattr(op2, "id"): + raise TypeError("Must be an ApdlMathObj") + + opout = self.copy() + self._mapdl._log.info("Call Mapdl to perform AXPY operation") + self._mapdl.run(f"*AXPY,-1,0,{op2.id},1,0,{opout.id}", mute=True) + return opout + + def __matmul__(self, op): + return self.dot(op) + + def __iadd__(self, op): + return self.axpy(op, 1, 1) + + def __isub__(self, op): + return self.axpy(op, -1, 1) + + def __imul__(self, val): + self._mapdl._log.info("Call Mapdl to scale the object") + self._mapdl.run(f"*SCAL,{self.id},{val}", mute=True) + return self + + def __itruediv__(self, val): + if val == 0: + raise ZeroDivisionError("division by zero") + self._mapdl._log.info("Call Mapdl to 1/scale the object") + self._mapdl.run(f"*SCAL,{self.id},{1/val}", mute=True) + return self + + @property + @protect_grpc + def _data_info(self): + """Return the data type of a parameter""" + request = pb_types.ParameterRequest(name=self.id) + return self._stub.GetDataInfo(request) + + +class AnsVec(ApdlMathObj): + """APDLMath Vector Object""" + + def __init__(self, id_, mapdl, dtype=np.double, init=None): + ApdlMathObj.__init__(self, id_, mapdl, ObjType.VEC) + + if init not in ["ones", "zeros", "rand", None]: + raise ValueError(f"Invalid init option {init}.\n" 'Should be "ones", "zeros", "rand", or None') + + if init == "rand": + self.rand() + elif init == "ones": + self.ones() + elif init == "zeros": + self.zeros() + + @property + def size(self): + """Number of items in this vector.""" + sz = self._mapdl.scalar_param(f"{self.id}_DIM") + if sz is None: + raise RuntimeError("This vector has been deleted within MAPDL.") + return int(sz) + + def __repr__(self): + return f"APDLMath Vector Size {self.size}" + + def __getitem__(self, num): + if num < 0: + raise ValueError("Negative indices not permitted") + self._mapdl.run(f"pyval={self.id}({num+1})", mute=True) + return self._mapdl.scalar_param("pyval") + + def __mul__(self, vec): + """Element-Wise product with another Ansys vector object. + + Also known as Hadamard product. + + .. note:: + Requires at least MAPDL version 2021R2. + + Parameters + ---------- + vec : ansys.mapdl.math.AnsVec + Ansys vector object. + + Returns + ------- + AnsVec + Hadamard product between this vector and the other vector. + """ + if not meets_version(self._mapdl._server_version, (0, 4, 0)): # pragma: no cover + raise VersionError("``AnsVec`` requires MAPDL version 2021R2") + + if not isinstance(vec, AnsVec): + raise TypeError("Must be an Ansys vector object") + + name = id_generator() # internal name of the new vector/matrix + info = self._mapdl._data_info(self.id) + dtype = ANSYS_VALUE_TYPE[info.stype] + + # check size consistency + if self.size != vec.size: + raise ValueError("Vectors have inconsistent sizes") + + self._mapdl.run(f"*VEC,{name},{MYCTYPE[dtype]},ALLOC,{info.size1}") + objout = AnsVec(name, self._mapdl) + + # perform the Hadamard product + self._mapdl.run(f"*HPROD,{self.id},{vec.id},{name}") + return objout + + def copy(self): + """Return a copy of this vector""" + return AnsVec(ApdlMathObj.copy(self), self._mapdl) + + def dot(self, vec) -> float: + """Dot product with another APDLMath vector. + + Parameters + ---------- + vec : ansys.mapdl.math.AnsVec + Ansys vector object. + + Returns + ------- + float + Dot product between this vector and the other vector. + """ + if not isinstance(vec, AnsVec): + raise TypeError("Must be an Ansys vector object") + + self._mapdl.run(f"*DOT,{self.id},{vec.id},py_val") + return self._mapdl.scalar_param("py_val") + + def asarray(self) -> np.ndarray: + """Returns vector as a numpy array + + Examples + -------- + >>> from ansys.math.core import launch_math + >>> mm = launch_math() + >>> v = mm.ones(10) + >>> v.asarray() + [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] + """ + return self._mapdl._vec_data(self.id) + + def __array__(self): + """Allow numpy to access this object as if it was an array""" + return self.asarray() + + +class AnsMat(ApdlMathObj): + """APDLMath Matrix Object""" + + def __init__(self, id_, mapdl, type_=ObjType.DMAT): + ApdlMathObj.__init__(self, id_, mapdl, type_) + + @property + def nrow(self) -> int: + """Number of columns in this matrix.""" + return int(self._mapdl.scalar_param(self.id + "_ROWDIM")) + + @property + def ncol(self) -> int: + """Number of rows in this matrix.""" + return int(self._mapdl.scalar_param(self.id + "_COLDIM")) + + @property + def size(self) -> int: + """Number of items in this matrix.""" + return self.nrow * self.ncol + + @property + def shape(self) -> tuple: + """Returns a numpy-like shape. + + Tuple of (rows and columns). + """ + return (self.nrow, self.ncol) + + def sym(self) -> bool: + """Return if matrix is symmetric. + + Returns + ------- + bool + ``True`` when this matrix is symmetric. + + """ + + info = self._mapdl._data_info(self.id) + + if meets_version(self._mapdl._server_version, (0, 5, 0)): # pragma: no cover + return info.mattype in [0, 1, 2] # [UPPER, LOWER, DIAG] respectively + + warn("Call to ``sym`` cannot evaluate if this matrix " "is symmetric with this version of MAPDL.") + return True + + def asarray(self, dtype=None) -> np.ndarray: + """Returns vector as a numpy array. + + Parameters + ---------- + dtype : numpy.dtype, optional + Numpy data type + + Returns + ------- + np.ndarray + Numpy array with the defined data type + + Examples + -------- + >>> from ansys.math.core import launch_math + >>> mm = launch_math() + >>> v = mm.ones(10) + >>> v.asarray() + [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] + >>> v.asarray(dtype=np.int) + [1 1 1 1 1 1 1 1 1 1] + + """ + if dtype: + return self._mapdl._mat_data(self.id).astype(dtype) + else: + return self._mapdl._mat_data(self.id) + + def __mul__(self, vec): + raise AttributeError("Array multiplication is not yet available. " "For dot product, please use `dot()`") + + def dot(self, obj): + """Perform the matrix multiplication by another vector or matrix. + + Parameters + ---------- + obj : ansys.mapdl.math.AnsVec or ansys.mapdl.math.AnsMat + Ansys object. + + Returns + ------- + AnsVec or AnsMat + Matrix multiplication result. + + Examples + -------- + Multiplication of a matrix and vector. + + >>> m1 = mm.rand(10, 10) + >>> v1 = mm.rand(10) + >>> v2 = m1.dot(v1) + >>> assert np.allclose(m1.asarray() @ v1.asarray(), v2) + + """ + name = id_generator() # internal name of the new vector/matrix + info = self._mapdl._data_info(self.id) + dtype = ANSYS_VALUE_TYPE[info.stype] + if obj.type == ObjType.VEC: + self._mapdl.run(f"*VEC,{name},{MYCTYPE[dtype]},ALLOC,{info.size1}", mute=True) + objout = AnsVec(name, self._mapdl) + else: + self._mapdl.run( + f"*DMAT,{name},{MYCTYPE[dtype]},ALLOC,{info.size1},{info.size2}", + mute=True, + ) + objout = AnsDenseMat(name, self._mapdl) + + self._mapdl._log.info("Call Mapdl to perform MV Product") + self._mapdl.run(f"*MULT,{self.id},,{obj.id},,{name}", mute=True) + return objout + + def __getitem__(self, num): + """Return a vector from a given index.""" + name = id_generator() + info = self._mapdl._data_info(self.id) + dtype = ANSYS_VALUE_TYPE[info.stype] + self._mapdl.run(f"*VEC,{name},{MYCTYPE[dtype]},LINK,{self.id},{num+1}", mute=True) + return AnsVec(name, self._mapdl) + + @property + def T(self): + """Returns the transpose of a MAPDL matrix. + + Examples + -------- + >>> from ansys.math.core import launch_math + >>> mm = launch_math() + >>> mat = mm.rand(2, 3) + >>> mat_t = mat.T + + """ + info = self._mapdl._data_info(self.id) + + if info.objtype == 2: + objtype = "*DMAT" + else: + objtype = "*SMAT" + + dtype = ANSYS_VALUE_TYPE[info.stype] + name = id_generator() + self._mapdl._log.info("Call MAPDL to transpose") + self._mapdl.run(f"{objtype},{name},{MYCTYPE[dtype]},COPY,{self.id},TRANS", mute=True) + if info.objtype == 2: + mat = AnsDenseMat(name, self._mapdl) + else: + mat = AnsSparseMat(name, self._mapdl) + return mat + + +class AnsDenseMat(AnsMat): + """Dense APDLMath Matrix""" + + def __init__(self, uid, mapdl): + AnsMat.__init__(self, uid, mapdl, ObjType.DMAT) + + def __array__(self): + """Allow numpy to access this object as if it was an array""" + return self.asarray() + + def __repr__(self): + return f"Dense APDLMath Matrix ({self.nrow}, {self.ncol})" + + def copy(self): + """Return a copy of this matrix""" + return AnsDenseMat(ApdlMathObj.copy(self), self._mapdl) + + +class AnsSparseMat(AnsMat): + """Sparse APDLMath Matrix""" + + def __init__(self, uid, mapdl): + AnsMat.__init__(self, uid, mapdl, ObjType.SMAT) + + def __repr__(self): + return f"Sparse APDLMath Matrix ({self.nrow}, {self.ncol})" + + def copy(self): + """Return a copy of this matrix. + + Matrix remains in MAPDL. + + Examples + -------- + >>> k + Sparse APDLMath Matrix (126, 126) + + >>> kcopy = k.copy() + >>> kcopy + Sparse APDLMath Matrix (126, 126) + + """ + return AnsSparseMat(ApdlMathObj.copy(self), self._mapdl) + + def todense(self) -> np.ndarray: + """Return this array as a dense np.ndarray + + Examples + -------- + >>> k + Sparse APDLMath Matrix (126, 126) + + >>> mat = k.todense() + >>> mat + matrix([[ 2.02925393e-01, 3.78142616e-03, 0.00000000e+00, ..., + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], + [ 0.00000000e+00, 2.00906608e-01, 0.00000000e+00, ..., + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 2.29396542e+03, ..., + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], + ..., + [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., + 2.26431549e+03, -9.11391851e-08, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., + 0.00000000e+00, 3.32179197e+03, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., + 0.00000000e+00, 0.00000000e+00, 2.48282229e-01]]) + + """ + return self.asarray().todense() + + def __array__(self): + """Allow numpy to access this object as if it was an array""" + return self.todense() + + +class AnsSolver(ApdlMathObj): + """APDLMath Solver Class""" + + def __repr__(self): + return "APDLMath Linear Solver" + + def factorize(self, mat, algo=None, inplace=True): + """Factorize a matrix + + Perform the numerical factorization of a linear solver system (:math:`A*x=b`). + + .. warning:: By default, factorization modifies the input matrix ``mat`` + in place. This behavior can be changed using the ``inplace`` argument. + + Parameters + ---------- + mat : ansys.math.core.math.AnsMat + An ansys.mapdl.math matrix. + algo : str, optional + Factorization algorithm. Either ``"LAPACK"`` (default for + dense matrices) or ``"DSP"`` (default for sparse matrices). + inplace : bool, optional + If ``False``, the factorization is performed on a copy + of the input matrix (``mat`` argument), hence this input + matrix (``mat``) is not changed. Default is ``True``. + + Examples + -------- + Factorize a random matrix and solve a linear system. + + >>> dim = 1000 + >>> m2 = mm.rand(dim, dim) + >>> solver = mm.factorize(m2) + >>> b = mm.ones(dim) + >>> x = solver.solve(b) + + """ + mat_id = mat.id + if not inplace: + self._mapdl._log.info("Performing factorization in a copy of the array.") + copy_mat = mat.copy() + mat_id = copy_mat.id + else: + self._mapdl._log.info("Performing factorization inplace. This changes the input array.") + + if not algo: + if mat.type == ObjType.DMAT: + algo = "LAPACK" + elif mat.type == ObjType.SMAT: + algo = "DSP" + + self._mapdl.run(f"*LSENGINE,{algo},{self.id},{mat_id}", mute=True) + self._mapdl._log.info(f"Factorizing using the {algo} package") + self._mapdl.run(f"*LSFACTOR,{self.id}", mute=True) + + def solve(self, b, x=None): + """Solve a linear system + + Parameters + ---------- + b : ansys.mapdl.math.AnsVec + APDLmath vector. + x : ansys.mapdl.math.AnsVec, optional + APDLmath vector to place the solution. + + Returns + ------- + AnsVec + Solution vector. Identical to ``x`` if supplied. + + Examples + -------- + >>> k = mm.stiff(fname='PRSMEMB.full') + >>> s = mm.factorize(k) + >>> b = mm.get_vec(fname='PRSMEMB.full', mat_id="RHS") + >>> x = s.solve(b) + >>> x + APDLMath Vector Size 20000 + + """ + if not x: + x = b.copy() + self._mapdl._log.info("Solving") + self._mapdl.run(f"*LSBAC,{self.id},{b.id},{x.id}", mute=True) + return x + + +def rand(obj): + """Set all values of a mapdl math object to random values. + + Parameters + ---------- + obj : ansys.math.MapdlMath object + MapdlMath object + + Examples + -------- + >>> vec = mm.ones(10) + >>> mm.rand(vec) + """ + obj._mapdl.run(f"*INIT,{obj.id},RAND", mute=True) + + +def solve(mat, b, x=None, algo=None): + solver = AnsSolver(id_generator(), mat._mapdl) + solver.factorize(mat, algo) + if not x: + x = b.copy() + x = solver.solve(b, x) + + del solver + return x + + +def dot(vec1, vec2) -> float: + """Dot product between two APDLMath vectors. + + Parameters + ---------- + vec1 : ansys.mapdl.math.AnsVec + APDLMath vector. + + vec1 : ansys.mapdl.math.AnsVec + APDLMath vector. + + Returns + ------- + float + Dot product between the two vectors + + """ + if vec1.type != ObjType.VEC or vec2.type != ObjType.VEC: + raise TypeError("Both objects must be ANSYS vectors") + + mapdl = vec1._mapdl + mapdl.run(f"*DOT,{vec1.id},{vec2.id},py_val", mute=True) + return mapdl.scalar_param("py_val") + + +# def launch_math(mapdl=None, **kwargs): +# """ +# Launch an MAPDL instance in the background if none is filled. + +# Args: +# mapdl (MAPDL instance, optional): MAPDL instance. Defaults to None. +# """ + +# if mapdl is None: +# from ansys.mapdl.core import launch_mapdl + +# mapdl = launch_mapdl(**kwargs) + +# return MapdlMath(mapdl) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..65b96607 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,153 @@ +import os +from pathlib import Path + +import pytest + +# import time + +pytest_plugins = ["pytester"] + +from ansys.mapdl.core import launch_mapdl +from ansys.mapdl.core._version import SUPPORTED_ANSYS_VERSIONS +from ansys.mapdl.core.errors import MapdlExitedError +from ansys.mapdl.core.launcher import MAPDL_DEFAULT_PORT, get_start_instance +from ansys.mapdl.core.misc import get_ansys_bin + +# Check if MAPDL is installed +# NOTE: checks in this order to get the newest installed version + + +valid_rver = [str(each) for each in SUPPORTED_ANSYS_VERSIONS] + +EXEC_FILE = None +for rver in valid_rver: + if os.path.isfile(get_ansys_bin(rver)): + EXEC_FILE = get_ansys_bin(rver) + break + +# Cache if gRPC MAPDL is installed. +# +# minimum version on linux. Windows is v202, but using v211 for consistency +# Override this if running on CI/CD and PYMAPDL_PORT has been specified +ON_CI = "PYMAPDL_START_INSTANCE" in os.environ and "PYMAPDL_PORT" in os.environ +HAS_GRPC = int(rver) >= 211 or ON_CI + + +# determine if we can launch an instance of MAPDL locally +# start with ``False`` and always assume the remote case +LOCAL = [False] + +# check if the user wants to permit pytest to start MAPDL +START_INSTANCE = get_start_instance() + +if os.name == "nt": + os_msg = """SET PYMAPDL_START_INSTANCE=False +SET PYMAPDL_PORT= (default 50052) +SET PYMAPDL_IP= (default 127.0.0.1)""" +else: + os_msg = """export PYMAPDL_START_INSTANCE=False +export PYMAPDL_PORT= (default 50052) +export PYMAPDL_IP= (default 127.0.0.1)""" + +ERRMSG = f"""Unable to run unit tests without MAPDL installed or +accessible. Either install Ansys 2021R1 or newer or specify the +remote server with: + +{os_msg} + +If you do have Ansys installed, you may have to patch pymapdl to +automatically find your Ansys installation. Email the developer at: +alexander.kaszynski@ansys.com + +""" + +if START_INSTANCE and EXEC_FILE is None: + raise RuntimeError(ERRMSG) + + +@pytest.fixture(scope="session", params=LOCAL) +def mapdl(request, tmpdir_factory): + # don't use the default run location as tests run multiple unit testings + run_path = str(tmpdir_factory.mktemp("ansys")) + + # don't allow mapdl to exit upon collection unless mapdl is local + cleanup = START_INSTANCE + + if request.param: + # usage of a just closed channel on same port causes connectivity issues + port = MAPDL_DEFAULT_PORT + 10 + else: + port = MAPDL_DEFAULT_PORT + + mapdl = launch_mapdl( + EXEC_FILE, + override=True, + run_location=run_path, + cleanup_on_exit=cleanup, + ) + mapdl._show_matplotlib_figures = False # CI: don't show matplotlib figures + + if HAS_GRPC: + mapdl._local = request.param # CI: override for testing + + if mapdl._local: + assert Path(mapdl.directory) == Path(run_path) + assert mapdl._distributed + + # using yield rather than return here to be able to test exit + yield mapdl + + ########################################################################### + # test exit: only when allowed to start PYMAPDL + ########################################################################### + if START_INSTANCE: + mapdl._local = True + mapdl.exit() + assert mapdl._exited + assert "MAPDL exited" in str(mapdl) + + if mapdl._local: + assert not os.path.isfile(mapdl._lockfile) + + # should test if _exited protects from execution + with pytest.raises(MapdlExitedError): + mapdl.prep7() + + # actually test if server is shutdown + if HAS_GRPC: + with pytest.raises(MapdlExitedError): + mapdl._send_command("/PREP7") + with pytest.raises(MapdlExitedError): + mapdl._send_command_stream("/PREP7") + + # verify PIDs are closed + # time.sleep(1) # takes a second for the processes to shutdown + # for pid in mapdl._pids: + # assert not check_pid(pid) + + +@pytest.fixture(scope="function") +def cleared(mapdl): + mapdl.finish(mute=True) + # *MUST* be NOSTART. With START fails after 20 calls... + # this has been fixed in later pymapdl and MAPDL releases + mapdl.clear("NOSTART", mute=True) + mapdl.prep7(mute=True) + yield + + +@pytest.fixture(scope="function") +def cube_solve(cleared, mapdl): + # setup the full file + mapdl.block(0, 1, 0, 1, 0, 1) + mapdl.et(1, 186) + mapdl.esize(0.5) + mapdl.vmesh("all") + + # Define a material (nominal steel in SI) + mapdl.mp("EX", 1, 210e9) # Elastic moduli in Pa (kg/(m*s**2)) + mapdl.mp("DENS", 1, 7800) # Density in kg/m3 + mapdl.mp("NUXY", 1, 0.3) # Poisson's Ratio + + # solve first 10 non-trivial modes + out = mapdl.modal_analysis(nmode=10, freqb=1) diff --git a/tests/test_math.py b/tests/test_math.py new file mode 100644 index 00000000..fd9c6b0b --- /dev/null +++ b/tests/test_math.py @@ -0,0 +1,781 @@ +"""Test APDL Math functionality""" +import os +import re + +from ansys.mapdl.core.check_version import VersionError, meets_version +from ansys.mapdl.core.errors import ANSYSDataTypeError +from ansys.mapdl.core.launcher import get_start_instance +from ansys.mapdl.core.misc import random_string +import numpy as np +import pytest +from scipy import sparse + +import ansys.math.core.math as amath + +# from ansys.math.core.math import launch_math + +# skip entire module unless HAS_GRPC +pytestmark = pytest.mark.skip_grpc + +skip_in_cloud = pytest.mark.skipif( + not get_start_instance(), + reason=""" +Must be able to launch MAPDL locally. Remote execution does not allow for +directory creation. +""", +) + + +@pytest.fixture(scope="module") +def mm(mapdl): + mm = amath.MapdlMath(mapdl) + return mm + + +def test_ones(mm): + v = mm.ones(10) + assert v.size == 10 + assert v[0] == 1 + + +def test_rand(mm): + w = mm.rand(10) + assert w.size == 10 + + +def test_asarray(mm): + v = mm.ones(10) + assert np.allclose(v.asarray(), np.ones(10)) + + +def test_add(mm): + v = mm.ones(10) + w = mm.ones(10) + z = v + w + assert np.allclose(z.asarray(), 2) + + +def test_norm(mm): + v = mm.ones(10) + assert np.isclose(v.norm(), np.linalg.norm(v)) + assert np.isclose(mm.norm(v), v.norm()) + + +def test_inplace_add(mm): + v = mm.ones(10) + w = mm.ones(10) + w += v + assert w[0] == 2 + + +def test_inplace_mult(mm): + v = mm.ones(10) + v *= 2 + assert v[0] == 2 + + +def test_set_vec_large(mm): + # send a vector larger than the gRPC size limit of 4 MB + sz = 1000000 + a = np.random.random(1000000) # 7.62 MB (as FLOAT64) + assert a.nbytes > 4 * 1024**2 + ans_vec = mm.set_vec(a) + assert a[sz - 1] == ans_vec[sz - 1] + assert np.allclose(a, ans_vec.asarray()) + + +def test_dot(mm): + a = np.arange(10000, dtype=np.float) + b = np.arange(10000, dtype=np.float) + np_rst = a.dot(b) + + vec_a = mm.set_vec(a) + vec_b = mm.set_vec(b) + assert np.allclose(vec_a.dot(vec_b), np_rst) + assert np.allclose(mm.dot(vec_a, vec_b), np_rst) + + +def test_invalid_dtype(mm): + with pytest.raises(ANSYSDataTypeError): + mm.vec(10, dtype=np.uint8) + + +def test_vec(mm): + vec = mm.vec(10, asarray=False) + assert isinstance(vec, amath.AnsVec) + + arr = mm.vec(10, asarray=True) + assert isinstance(arr, np.ndarray) + + +def test_vec_from_name(mm): + vec0 = mm.vec(10) + vec1 = mm.vec(name=vec0.id) + assert np.allclose(vec0, vec1) + + vec1 = mm.vec(name=vec0.id, asarray=True) + assert isinstance(vec1, np.ndarray) + + +def test_vec__mul__(mm): + # version check must be performed at runtime + if mm._server_version[1] >= 4: + a = mm.vec(10) + b = mm.vec(10) + assert np.allclose(a * b, np.asarray(a) * np.asarray(b)) + + with pytest.raises(ValueError): + mm.vec(10) * mm.vec(11) + + with pytest.raises(TypeError): + mm.vec(10) * np.ones(10) + + +def test_numpy_max(mm): + apdl_vec = mm.vec(10, init="rand") + assert np.isclose(apdl_vec.asarray().max(), np.max(apdl_vec)) + + +def test_shape(mm): + shape = (10, 8) + m1 = mm.rand(*shape) + assert m1.shape == shape + + +def test_matrix(mm): + sz = 5000 + mat = sparse.random(sz, sz, density=0.05, format="csr") + assert mat.data.nbytes // 1024**2 > 4, "Must test over gRPC message limit" + + name = "TMP_MATRIX" + ans_mat = mm.matrix(mat, name) + assert ans_mat.id == name + + mat_back = ans_mat.asarray() + assert np.allclose(mat.data, mat_back.data) + assert np.allclose(mat.indices, mat_back.indices) + assert np.allclose(mat.indptr, mat_back.indptr) + + +def test_matrix_fail(mm): + mat = sparse.random(10, 10, density=0.05, format="csr") + + with pytest.raises(ValueError, match='":" is not permitted'): + mm.matrix(mat, "my:mat") + + with pytest.raises(TypeError): + mm.matrix(mat.astype(np.int8)) + + +def test_matrix_addition(mm): + m1 = mm.rand(10, 10) + m2 = mm.rand(10, 10) + m3 = m1 + m2 + assert np.allclose(m1.asarray() + m2.asarray(), m3.asarray()) + + +def test_mul(mm): + m1 = mm.rand(10, 10) + w = mm.rand(10) + with pytest.raises(AttributeError): + m1 * w + + +# test kept for the eventual inclusion of mult +# def test_matrix_mult(mm): +# m1 = mm.rand(10, 10) +# w = mm.rand(10) +# v = m1.w +# assert np.allclose(w.asarray() @ m1.asarray(), v.asarray()) + +# m1 = mm.rand(10, 10) +# m2 = mm.rand(10, 10) +# m3 = m1*m2 +# assert np.allclose(m1.asarray() @ m2.asarray(), m3.asarray()) + + +def test_matrix_matmult(mm): + u = mm.rand(10) + v = mm.rand(10) + w = u @ v + assert np.allclose(u.asarray() @ v.asarray(), w) + + m1 = mm.rand(10, 10) + w = mm.rand(10) + v = m1 @ w + assert np.allclose(m1.asarray() @ w.asarray(), v.asarray()) + + m1 = mm.rand(10, 10) + m2 = mm.rand(10, 10) + m3 = m1 @ m2 + assert np.allclose(m1.asarray() @ m2.asarray(), m3.asarray()) + + +def test_getitem(mm): + size_i, size_j = (3, 3) + mat = mm.rand(size_i, size_j) + np_mat = mat.asarray() + + for i in range(size_i): + vec = mat[i] + for j in range(size_j): + # recall that MAPDL uses fortran order + assert vec[j] == np_mat[j, i] + + +def test_load_stiff_mass(mm, cube_solve, tmpdir): + k = mm.stiff() + m = mm.mass() + assert k.shape == m.shape + + +def test_load_stiff_mass_different_location(mm, cube_solve, tmpdir): + full_files = mm._mapdl.download("*.full", target_dir=tmpdir) + fname_ = os.path.join(tmpdir, full_files[0]) + assert os.path.exists(fname_) + + k = mm.stiff(fname=fname_) + m = mm.mass(fname=fname_) + assert k.shape == m.shape + assert all([each > 0 for each in k.shape]) + assert all([each > 0 for each in m.shape]) + + +def test_load_stiff_mass_as_array(mm, cube_solve): + k = mm.stiff(asarray=True) + m = mm.mass(asarray=True) + + assert sparse.issparse(k) + assert sparse.issparse(m) + assert all([each > 0 for each in k.shape]) + assert all([each > 0 for each in m.shape]) + + +def test_stiff_mass_name(mm, cube_solve): + kname = amath.id_generator() + mname = amath.id_generator() + + k = mm.stiff(name=kname) + m = mm.mass(name=mname) + + assert k.id == kname + assert m.id == mname + + +def test_stiff_mass_as_array(mm, cube_solve): + k = mm.stiff() + m = mm.mass() + + k = k.asarray() + m = m.asarray() + + assert sparse.issparse(k) + assert sparse.issparse(m) + assert all([each > 0 for each in k.shape]) + assert all([each > 0 for each in m.shape]) + + +@pytest.mark.parametrize( + "dtype_", + [ + np.int64, + np.double, + pytest.param(np.complex64, marks=pytest.mark.xfail), + pytest.param("Z", marks=pytest.mark.xfail), + "D", + pytest.param("dummy", marks=pytest.mark.xfail), + pytest.param(np.int8, marks=pytest.mark.xfail), + ], +) +def test_load_stiff_mass_different_dtype(mm, cube_solve, dtype_): + # AnsMat object do not support dtype assignment, you need to convert them to array first. + k = mm.stiff(asarray=True, dtype=dtype_) + m = mm.mass(asarray=True, dtype=dtype_) + + if isinstance(dtype_, str): + if dtype_ == "Z": + dtype_ = np.complex_ + else: + dtype_ = np.double + + assert sparse.issparse(k) + assert sparse.issparse(m) + assert all([each > 0 for each in k.shape]) + assert all([each > 0 for each in m.shape]) + assert k.dtype == dtype_ + assert m.dtype == dtype_ + + k = mm.stiff(dtype=dtype_) + m = mm.mass(dtype=dtype_) + + k = k.asarray(dtype=dtype_) + m = m.asarray(dtype=dtype_) + + assert sparse.issparse(k) + assert sparse.issparse(m) + assert all([each > 0 for each in k.shape]) + assert all([each > 0 for each in m.shape]) + assert k.dtype == dtype_ + assert m.dtype == dtype_ + + +def test_load_matrix_from_file_incorrect_mat_id(mm, cube_solve): + with pytest.raises(ValueError, match=r"The 'mat_id' parameter supplied.*is not allowed."): + mm.load_matrix_from_file(fname="file.full", mat_id="DUMMY") + + +def test_load_matrix_from_file_incorrect_name(mm, cube_solve): + with pytest.raises(TypeError, match=r"``name`` parameter must be a string"): + mm.load_matrix_from_file(name=1245) + + +def test_mat_from_name(mm): + mat0 = mm.mat(10, 10) + mat1 = mm.mat(name=mat0.id) + assert np.allclose(mat0, mat1) + + +def test_mat_asarray(mm): + mat0 = mm.mat(10, 10, asarray=True) + mat1 = mm.mat(10, 10) + assert np.allclose(mat0, mat1.asarray()) + + +def test_mat_from_name_sparse(mm): + scipy_mat = sparse.random(5, 5, density=1, format="csr") + mat0 = mm.matrix(scipy_mat) + mat1 = mm.mat(name=mat0.id) + assert np.allclose(mat0, mat1) + + +def test_mat_invalid_dtype(mm): + with pytest.raises(ValueError): + mm.mat(10, 10, dtype=np.uint8) + + +def test_mat_invalid_init(mm): + with pytest.raises(ValueError, match="Invalid init method"): + mm.mat(10, 10, init="foo") + + +def test_solve(mm, cube_solve): + k = mm.stiff() + m = mm.mass() + + nev = 10 + a = mm.mat(k.nrow, nev) + ev = mm.eigs(nev, k, m, phi=a) + assert ev.size == nev + + +# alternative solve using math.solve +def test_solve_alt(mm, cube_solve): + k = mm.stiff() + b = mm.rand(k.nrow) + eig_val = amath.solve(k, b) + assert eig_val.size == k.nrow + + +def test_solve_eigs_km(mapdl, mm, cube_solve): + mapdl.post1() + resp = mapdl.set("LIST") + w_n = np.array(re.findall(r"\s\d*\.\d\s", resp), np.float32) + + k = mm.stiff() + m = mm.mass() + vec = mm.eigs(w_n.size, k, m, fmin=1) + eigval = vec.asarray() + assert np.allclose(w_n, eigval, atol=0.1) + + +def test_solve_py(mapdl, mm, cube_solve): + mapdl.post1() + resp = mapdl.set("LIST") + w_n = np.array(re.findall(r"\s\d*\.\d\s", resp), np.float32) + + # load by default from file.full + k = mm.stiff() + m = mm.mass() + + # convert to numpy + k_py = k.asarray() + m_py = m.asarray() + + mapdl.clear() + my_stiff = mm.matrix(k_py, triu=True) + my_mass = mm.matrix(m_py, triu=True) + + nmode = w_n.size + a = mm.mat(my_stiff.nrow, nmode) # for eigenvectors + vec = mm.eigs(nmode, my_stiff, my_mass, phi=a, fmin=1) + eigval = vec.asarray() + assert np.allclose(w_n, eigval, atol=0.1) + + +def test_copy2(mm): + dim = 1000 + m2 = mm.rand(dim, dim) + m3 = m2.copy() + + assert np.allclose(m2.asarray(), m3.asarray()) + + +def test_dense_solver(mm): + dim = 1000 + m2 = mm.rand(dim, dim) + # factorize do changes inplace in m2, so we + # need a copy to later compare. + # factorize do changes inplace in m2, so we + # need a copy to later compare. + m3 = m2.copy() + + solver = mm.factorize(m2) + + v = mm.ones(dim) + C = solver.solve(v) + + # TODO: we need to verify this works + m3_ = m3.asarray() + v_ = v.asarray() + x = np.linalg.solve(m3_, v_) + + assert np.allclose(C, x) + m3_ = m3.asarray() + v_ = v.asarray() + x = np.linalg.solve(m3_, v_) + + assert np.allclose(C, x) + + +def test_solve_py(mapdl, mm, cube_solve): + rhs0 = mm.get_vec() + rhs1 = mm.rhs() + assert np.allclose(rhs0, rhs1) + + +@pytest.mark.parametrize("vec_type", ["RHS", "BACK", pytest.param("dummy", marks=pytest.mark.xfail)]) +def test_get_vec(mapdl, mm, cube_solve, vec_type): + if vec_type.upper() == "BACK": + vec = mm.get_vec(mat_id=vec_type, asarray=True) # To test asarray arg. + assert vec.dtype == np.int32 + else: + vec = mm.get_vec(mat_id=vec_type).asarray() + assert vec.dtype == np.double + assert vec.shape + + +def test_get_vec_incorrect_name(mm, cube_solve): + with pytest.raises(TypeError, match=r"``name`` parameter must be a string"): + mm.get_vec(name=18536) + + +def test_get_vector(mm): + vec = mm.ones(10) + arr = vec.asarray() + assert np.allclose(arr, 1) + + +def test_vector_add(mm): + vec0 = mm.ones(10) + vec1 = mm.ones(10) + assert np.allclose(vec0 + vec1, mm.add(vec0, vec1)) + + +def test_vector_subtract(mm): + vec0 = mm.ones(10) + vec1 = mm.ones(10) + assert np.allclose(vec0 - vec1, mm.subtract(vec0, vec1)) + + +def test_vector_neg_index(mm): + vec = mm.ones(10) + with pytest.raises(ValueError): + vec[-1] + + +def test_vec_itruediv(mm): + vec = mm.ones(10) + vec /= 2 + assert np.allclose(vec, 0.5) + + +def test_vec_const(mm): + vec = mm.ones(10) + vec.const(2) + assert np.allclose(vec, 2) + + +@pytest.mark.parametrize("pname", ["vector", "my_vec"]) +@pytest.mark.parametrize("vec", [np.random.random(10), [1, 2, 3, 4]]) +def test_set_vector(mm, vec, pname): + ans_vec = mm.set_vec(vec, pname) + assert np.allclose(ans_vec.asarray(), vec) + assert "APDLMath Vector Size" in repr(ans_vec) + assert "" in str(vec[0])[:4] # output from *PRINT + + +def test_set_vector_catch(mm): + + with pytest.raises(ValueError, match='":" is not permitted'): + mm.set_vec(np.ones(10), "my:vec") + + with pytest.raises(TypeError): + mm.set_vec(np.ones(10, dtype=np.int16)) + + with pytest.raises(TypeError): + mm.set_vec(np.array([1, 2, 3], np.uint8)) + + +def test_get_dense(mm): + ans_mat = mm.ones(10, 10) + assert np.allclose(ans_mat.asarray(), 1) + + ans_mat = mm.zeros(10, 10) + assert np.allclose(ans_mat.asarray(), 0) + + +def test_zeros_vec(mm): + assert isinstance(mm.zeros(10), amath.AnsVec) + + +def test_get_sparse(mm): + k = mm.stiff() + matrix = k.asarray() + assert isinstance(matrix, sparse.csr.csr_matrix) + assert np.any(matrix.data) + + +def test_copy(mm): + k = mm.stiff() + kcopy = k.copy() + assert np.allclose(k, kcopy) + + +def test_copy_complex(mm): + data_a = np.random.random(10) + np.random.random(10) * 1j + vec_a = mm.set_vec(data_a) + data_b = vec_a.copy().asarray() + assert data_b.dtype == data_a.dtype + assert np.allclose(data_a, data_b) + + +def test_sparse_repr(mm): + k = mm.stiff() + assert "Sparse APDLMath Matrix" in repr(k) + + +def test_invalid_matrix_size(mm): + mat = sparse.random(10, 9, density=0.05, format="csr") + with pytest.raises(ValueError): + mm.matrix(mat, "NUMPY_MAT") + + +def test_matrix_incorrect_name(mm, cube_solve): + with pytest.raises(TypeError, match=r"``name`` parameter must be a string"): + mm.matrix(np.ones((3, 3)), name=18536) + + +def test_transpose(mm): + mat = sparse.random(5, 5, density=1, format="csr") + apdl_mat = mm.matrix(mat) + apdl_mat_t = apdl_mat.T + assert np.allclose(apdl_mat.asarray().todense().T, apdl_mat_t.asarray().todense()) + + +def test_dense(mm): + # version check must be performed at runtime + if mm._server_version[1] >= 4: + # test if a APDLMath object can treated as an array + array = np.random.random((5, 5)) + apdl_mat = mm.matrix(array) + assert isinstance(apdl_mat, amath.AnsMat) + assert np.allclose(array, apdl_mat) + + with pytest.raises(TypeError): + apdl_mat = mm.matrix(array.astype(np.uint8)) + + assert "Dense APDLMath Matrix" in repr(apdl_mat) + + # check transpose + assert np.allclose(apdl_mat.T, array.T) + + # check dot (vector and matrix) + ones = mm.ones(apdl_mat.nrow) + assert np.allclose(apdl_mat.dot(ones), np.dot(array, np.ones(5))) + assert np.allclose(apdl_mat.dot(apdl_mat), np.dot(array, array)) + + +def test_invalid_sparse_type(mm): + mat = sparse.random(10, 10, density=0.05, format="csr", dtype=np.uint8) + with pytest.raises(TypeError): + mm._send_sparse("pytest01", mat, False, None, 100) + + +def test_invalid_sparse_name(mm): + mat = sparse.random(10, 10, density=0.05, format="csr", dtype=np.uint8) + with pytest.raises(TypeError, match="must be a string"): + mm.matrix(mat, name=1) + + +def test_free(mm): + my_mat = mm.ones(10) + mm.free() + with pytest.raises(RuntimeError, match="This vector has been deleted"): + my_mat.size + + +def test_repr(mm): + assert mm._status == repr(mm) + + +def test__load_file(mm, tmpdir): # pragma: no cover + # generating dummy file + # mm._mapdl._local = True # Uncomment to test locally. + if not mm._mapdl._local: + return True + + fname_ = random_string() + ".file" + fname = str(tmpdir.mkdir("tmpdir").join(fname_)) + + ## Checking non-exists + with pytest.raises(FileNotFoundError): + assert fname_ == mm._load_file(fname) + + with open(fname, "w") as fid: + fid.write("# Dummy") + + ## Checking case where the file is only in python folder + assert fname_ not in mm._mapdl.list_files() + assert fname_ == mm._load_file(fname) + assert fname_ in mm._mapdl.list_files() + + ## Checking case where the file is in both. + with pytest.warns(): + assert fname_ == mm._load_file(fname) + + ## Checking the case where the file is only in the MAPDL folder + os.remove(fname) + assert fname_ == mm._load_file(fname) + assert not os.path.exists(fname) + assert fname_ in mm._mapdl.list_files() + mm._mapdl._local = False + + +def test_status(mm, capsys): + assert mm.status() is None + captured = capsys.readouterr() + printed_output = captured.out + + assert "APDLMATH PARAMETER STATUS-" in printed_output + assert all([each in printed_output for each in ["Name", "Type", "Dims", "Workspace"]]) + + # Checking also _status property + assert "APDLMATH PARAMETER STATUS-" in mm._status + assert all([each in mm._status for each in ["Name", "Type", "Dims", "Workspace"]]) + + +def test_factorize_inplace_arg(mm): + dim = 1000 + m2 = mm.rand(dim, dim) + m3 = m2.copy() + mm.factorize(m2, inplace=False) + + assert np.allclose(m2.asarray(), m3.asarray()) + + +def test_mult(mapdl, mm): + + rand_ = np.random.rand(100, 100) + + if not meets_version(mapdl._server_version, (0, 4, 0)): + with pytest.raises(VersionError): + AA = mm.matrix(rand_, name="AA") + + else: + AA = mm.matrix(rand_, name="AA") + + BB = mm.vec(size=rand_.shape[1]) + CC = mm.vec(size=rand_.shape[1], init="zeros") + BB_trans = mm.matrix(np.random.rand(1, 100), "BBtrans") + + assert mapdl.mult(m1=AA.id, m2=BB.id, m3=CC.id) + assert mapdl.mult(m1=BB.id, t1="Trans", m2=AA.id, m3=CC.id) + assert mapdl.mult(m1=AA.id, m2=BB_trans.id, t2="Trans", m3=CC.id) + + +def test__parm(mm): + sz = 5000 + mat = sparse.random(sz, sz, density=0.05, format="csr") + + rand_ = np.random.rand(100, 100) + if not meets_version(mm._mapdl._server_version, (0, 4, 0)): + + with pytest.raises(VersionError): + AA = mm.matrix(rand_, name="AA") + + else: + AA = mm.matrix(rand_, name="AA") + assert AA.id == "AA" + BB = mm.vec(size=rand_.shape[1], name="BB") + assert BB.id == "BB" + CC = mm.matrix(mat, "CC") + assert CC.id == "CC" + + assert isinstance(mm._parm, dict) + AA_parm = mm._parm["AA"] + assert AA_parm["type"] == "DMAT" + assert AA_parm["dimensions"] == AA.shape + assert AA_parm["workspace"] == 1 + + BB_parm = mm._parm["BB"] + assert BB_parm["type"] == "VEC" + assert BB_parm["dimensions"] == BB.size + assert BB_parm["workspace"] == 1 + + # Sparse matrices are made of three matrices + assert "CC_DATA" in mm._parm + assert "CC_IND" in mm._parm + assert "CC_PTR" in mm._parm + + assert mm._parm["CC_DATA"]["dimensions"] == mat.indices.shape[0] + assert mm._parm["CC_DATA"]["type"] == "VEC" + assert mm._parm["CC_IND"]["dimensions"] == sz + 1 + assert mm._parm["CC_IND"]["type"] == "VEC" + assert mm._parm["CC_PTR"]["dimensions"] == mat.indices.shape[0] + assert mm._parm["CC_PTR"]["type"] == "VEC" + + +def test_vec2(mm): + mm._mapdl.clear() + + assert mm._parm == {} + + # Create a new vector if no name is provided + mm.vec(100) + assert mm._parm != {} + assert len(mm._parm.keys()) == 1 + name_ = list(mm._parm.keys())[0] + parameter_ = mm._parm[name_] + assert parameter_["type"] == "VEC" + assert parameter_["dimensions"] == 100 + + # retrieve a vector if the name is given and exists + vec = mm.vec(10, name=name_) + assert vec.size != 10 + assert vec.size == 100 + assert vec.id == name_ + + parameter_ = mm._parm[name_] + assert parameter_["type"] == "VEC" + assert parameter_["dimensions"] == 100 + + # Create a new vector if a name is given and doesn't exist + vec_ = mm.vec(20, name="ASDF") + parameter_ = mm._parm["ASDF"] + assert parameter_["type"] == "VEC" + assert parameter_["dimensions"] == vec_.size + + +@pytest.fixture(scope="module") +def exit(mm): + return mm._mapdl.exit()