diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index db0313a41..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,134 +0,0 @@ -# Python CircleCI 2.0 configuration file -## -# Check https://circleci.com/docs/2.0/language-python/ for more details - -version: 2.1 - -executors: - paramak: - docker: - # could use this image but it has cq 2.1 instead of master - # therefore the export_dagmc_h5m methods won't - # - image: ghcr.io/fusion-energy/paramak:dependencies - - image: ghcr.io/fusion-energy/paramak_cq_master:dependencies - resource_class: large - -commands: - install: - steps: - - run: - name: Install - command: | - pip install .[tests] - codecov-upload: - steps: - - run: - name: Codecov upload - command: bash <(curl -s https://codecov.io/bash) - -jobs: - # Tests: Utils, Shape, Reactor, Parametric Shapes - quick-tests: - executor: paramak - resource_class: medium - steps: - - checkout - - install - - run: - name: run utils tests - command: pytest tests/tests_units/test_utils.py -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml - - run: - name: run shape tests - command: pytest tests/tests_units/test_shape.py -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml - - run: - name: run Reactor tests - command: pytest tests/tests_units/test_reactor.py -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml - - run: - name: run parametric_shapes tests - command: pytest tests/tests_units/test_parametric_shapes/ -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml - - store_test_results: - path: test-reports - - store_artifacts: - path: test-reports - - codecov-upload - - # Tests: Parametric components - parametric-components-tests: - executor: paramak - resource_class: medium - parallelism: 2 - steps: - - checkout - - install - - run: - name: run parametric_components tests - command: | - set -e - TEST_FILES=$(circleci tests glob "tests/tests_units/test_parametric_components/**/*.py" | circleci tests split) - pytest -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml $TEST_FILES - - store_test_results: - path: test-reports - - store_artifacts: - path: test-reports - - codecov-upload - - # Tests: Parametric reactors - parametric-reactors-tests: - executor: paramak - parallelism: 6 - steps: - - checkout - - install - - run: - name: run parametric_reactors tests - command: | - set -e - TEST_FILES=$(circleci tests glob "tests/tests_units/test_parametric_reactors/**/*.py" | circleci tests split) - pytest -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml $TEST_FILES - - store_test_results: - path: test-reports - - store_artifacts: - path: test-reports - - codecov-upload - - # Tests: tests_h5m - neutronics-tests: - executor: paramak - resource_class: medium - steps: - - checkout - - install - - run: - name: run utils tests - command: pytest tests/tests_h5m -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml - - store_test_results: - path: test-reports - - store_artifacts: - path: test-reports - - codecov-upload - - # Tests: tests_show - show-tests: - executor: paramak - resource_class: medium - steps: - - checkout - - install - - run: - name: run utils tests - command: pytest tests/tests_show -v --cov=paramak --cov-append --cov-report term --cov-report xml --junitxml=test-reports/junit.xml - - store_test_results: - path: test-reports - - store_artifacts: - path: test-reports - - codecov-upload - -workflows: - version: 2 - test-build-deploy: - jobs: - - quick-tests - - parametric-components-tests - - parametric-reactors-tests - - neutronics-tests - - show-tests diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index db93bfbc8..000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,22 +0,0 @@ -## Proposed changes - -Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue. - -## Types of changes - -What types of changes does your code introduce to the Paramak? -_Put an `x` in the boxes that apply_ - -- [ ] Bugfix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] Code refactoring -- [ ] Documentation Update (if none of the other choices apply) -- [ ] New tests - -## Checklist - -_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._ - -- [ ] I have added tests that prove my fix is effective or that my feature works -- [ ] I have added necessary documentation (if appropriate) diff --git a/.github/workflows/anaconda-publish.yml b/.github/workflows/anaconda-publish.yml deleted file mode 100644 index 79cbb733b..000000000 --- a/.github/workflows/anaconda-publish.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: anaconda-publish - -on: - workflow_dispatch: - release: - types: [published] - -jobs: - build: - runs-on: ubuntu-latest - container: continuumio/miniconda3:4.10.3 - - steps: - - uses: actions/checkout@v2 - - - name: Set up conda - run: | - apt-get --allow-releaseinfo-change update - apt install -y libgl1-mesa-glx - conda install -y anaconda-client conda-build - conda config --set anaconda_upload no - - name: Build and publish to conda - env: - ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }} - run: | - conda build conda -c fusion-energy -c cadquery -c conda-forge --config-file conda/conda_build_config.yaml - conda convert /opt/conda/conda-bld/linux-64/*.tar.bz2 --platform osx-64 --platform win-64 -o /opt/conda/conda-bld/ - anaconda upload -f /opt/conda/conda-bld/*/*.tar.bz2 diff --git a/.github/workflows/auto_format_pep8.yml b/.github/workflows/auto_format_pep8.yml deleted file mode 100644 index 88ee8807c..000000000 --- a/.github/workflows/auto_format_pep8.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: auto_format_pep8 - -on: - push: - paths: - - '**.py' - -defaults: - run: - shell: bash - -jobs: - black: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: 3.x - - name: Install black - run: | - python -m pip install --upgrade pip - pip install black==22.3.0 - - name: Run black - run: | - black . - - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[skip ci] Apply formatting changes" diff --git a/.github/workflows/auto_lint.yml b/.github/workflows/auto_lint.yml deleted file mode 100644 index 63a74f7d1..000000000 --- a/.github/workflows/auto_lint.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: auto_lint - -on: - push: - paths: - - '**.py' - -defaults: - run: - shell: bash - -jobs: - flake8: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: 3.x - - name: Lint code - run: | - python -m pip install --upgrade pip - pip install flake8 - flake8 . --show-source --statistics --max-line-length 120 - - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[skip ci] Apply formatting changes" diff --git a/.github/workflows/ci_with_docker_build.yml b/.github/workflows/ci_with_docker_build.yml deleted file mode 100644 index 84292aeef..000000000 --- a/.github/workflows/ci_with_docker_build.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Builds a dockerimage and then runs tests from within the docker enviroment - -name: CI with docker build -on: - pull_request: - branches: - - develop - - main - paths: - - "**.py" - - "**.ipynb" - - "**.yml" - - "**.cfg" - - "**.toml" - - "**.sh" - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Build with Docker - run: docker build -t paramak --build-arg cq_version=master . - - - name: Run unit tests - run: docker run --rm paramak pytest ./tests/tests_units - - - name: Test examples - run: docker run --rm paramak pytest ./tests/tests_examples - - # tests_show require jupyter_cadquery which is not available on conda - # therefore these tests have been separated out to help with the conda - # testing. The tests_h5m tests require CQ master which is tested separately as well - - name: Test show - run: docker run --rm paramak pytest ./tests/tests_show diff --git a/.github/workflows/ci_with_install.yml b/.github/workflows/ci_with_install.yml deleted file mode 100644 index dd8946258..000000000 --- a/.github/workflows/ci_with_install.yml +++ /dev/null @@ -1,45 +0,0 @@ -# This CI will lauch a Docker image that contains all the dependencies required -# within that image the pytest test suite is run - -name: CI with install - -on: - pull_request: - branches: - - develop - - main - paths: - - "**.py" - - "**.ipynb" - - "**.yml" - - "**.cfg" - - "**.toml" - - "**.sh" - -jobs: - testing: - runs-on: ubuntu-latest - container: - image: ghcr.io/fusion-energy/paramak_cq_master:dependencies - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: install package - run: | - pip install --upgrade pip - pip install . - python -c "import paramak" - - - name: install package with tests - run: | - pip install .[tests] - - - name: Run tests - run: | - pytest tests/tests_units -v --cov=src/paramak --cov-append --cov-report term --cov-report xml - pytest tests/tests_examples -v --cov=src/paramak --cov-append --cov-report term --cov-report xml - pytest tests/tests_show -v --cov=src/paramak --cov-append --cov-report term --cov-report xml - - - name: Upload to codecov - uses: codecov/codecov-action@v2 diff --git a/.github/workflows/ci_with_install_cq_master.yml b/.github/workflows/ci_with_install_cq_master.yml deleted file mode 100644 index 87816df81..000000000 --- a/.github/workflows/ci_with_install_cq_master.yml +++ /dev/null @@ -1,44 +0,0 @@ -# This CI will launch a Docker image that contains all the dependencies required -# within that image the pytest test suite is run - -name: CI with install CQ master - -on: - pull_request: - branches: - - develop - - main - paths: - - "**.py" - - "**.ipynb" - - "**.yml" - - "**.cfg" - - "**.toml" - - "**.sh" - -jobs: - testing_cq_master: - runs-on: ubuntu-latest - container: - image: ghcr.io/fusion-energy/paramak_cq_master:dependencies - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: install package - run: | - pip install --upgrade pip - pip install .[tests] - - - name: Run tests - run: | - pytest tests/test_units -v --cov=paramak --cov-append --cov-report term --cov-report xml - pytest tests/tests_h5m -v --cov=paramak --cov-append --cov-report term --cov-report xml - -# jupyter cadquery doesn't appear to work with the current version of CQ master -# therefore the show() methods also don't work -# pytest tests/tests_show -v --cov=paramak --cov-append --cov-report term --cov-report xml -# pytest tests/tests_examples -v --cov=paramak --cov-append --cov-report term --cov-report xml - - - name: Upload to codecov - uses: codecov/codecov-action@v2 diff --git a/.github/workflows/conda-build-test.yml b/.github/workflows/conda-build-test.yml deleted file mode 100644 index 207f77bb8..000000000 --- a/.github/workflows/conda-build-test.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: conda-build-test - -on: - workflow_dispatch: - pull_request: - branches: - - develop - - main - -jobs: - build: - runs-on: ubuntu-latest - container: continuumio/miniconda3:4.10.3 - - steps: - - uses: actions/checkout@v2 - - - name: Set up conda - run: | - apt-get --allow-releaseinfo-change update - apt install -y libgl1-mesa-glx - conda install -y anaconda-client conda-build - conda config --set anaconda_upload no - - name: Build and test - env: - GIT_DESCRIBE_TAG: 0.1 - run: | - conda build conda -c fusion-energy -c cadquery -c conda-forge --config-file conda/conda_build_config.yaml diff --git a/.github/workflows/docker_publish.yml b/.github/workflows/docker_publish.yml deleted file mode 100644 index 94b64571c..000000000 --- a/.github/workflows/docker_publish.yml +++ /dev/null @@ -1,77 +0,0 @@ -# This yml file will trigger a Github Action on release creation. -# This Action will build and upload a Docker image to GHCR -# https://github.com/marketplace/actions/publish-docker - -name: docker-publish-release - -on: - # allows us to run workflows manually - workflow_dispatch: - release: - types: [created] - -jobs: - build_and_push_dependencies: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v1 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Cache Docker layers - uses: actions/cache@v2 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-single-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-single-buildx - - - name: Build and push dependencies Docker image CQ=master - uses: docker/build-push-action@v2 - with: - push: true - target: dependencies - tags: ghcr.io/fusion-energy/paramak_cq_master:dependencies - build-args: | - cq_version=master - paramak_version=${{ github.ref_name }} - - - name: Build and push dependencies Docker image CQ=master - uses: docker/build-push-action@v2 - with: - push: true - target: dependencies - tags: ghcr.io/fusion-energy/paramak:dependencies - build-args: | - cq_version=master - paramak_version=${{ github.ref_name }} - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache-new - - # Temp fix - # https://github.com/docker/build-push-action/issues/252 - # https://github.com/moby/buildkit/issues/1896 - - name: Move cache - run: | - rm -rf /tmp/.buildx-cache - mv /tmp/.buildx-cache-new /tmp/.buildx-cache - - - name: Build and push final Docker image - uses: docker/build-push-action@v2 - with: - push: true - tags: ghcr.io/fusion-energy/paramak - build-args: | - cq_version=master diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml deleted file mode 100644 index ac5bbece2..000000000 --- a/.github/workflows/python-publish.yml +++ /dev/null @@ -1,40 +0,0 @@ -# This yml file will trigger a Github Actions event that builds and upload the -# Python package to PiPy. This makes use of Twine and is triggered when a push -# to the main branch occures. For more information see: -# https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries -# and for details on the Autobump version section see: -# https://github.com/grst/python-ci-versioneer - -name: Upload Python Package - -on: - # allows us to run workflows manually - workflow_dispatch: - release: - types: [created] - -jobs: - deploy: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel build twine - - - name: Build and publish - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - python -m build - twine check dist/* - twine upload dist/* diff --git a/.github/workflows/test_demos.yml b/.github/workflows/test_demos.yml deleted file mode 100644 index 12705fe05..000000000 --- a/.github/workflows/test_demos.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Test demos - -# Controls when the action will run. -on: - # Triggers the workflow on push requests to main or develop branches - pull_request: - branches: - - main - - develop - paths: - - "**.py" - - "**.ipynb" - - "**.yml" - - "**.cfg" - - "**.toml" - - "**.sh" - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - container: - image: ghcr.io/fusion-energy/paramak_cq_master:dependencies - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Setup paramak - run: | - pip install .[tests] - - - name: Run the notebooks - run: | - pytest tests/tests_examples -v diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0d947dbda..000000000 --- a/.gitignore +++ /dev/null @@ -1,69 +0,0 @@ - -# graph files produced with export_html -*.html - -*.pov - -# geometry files -*.stp -*.step -*.stl -*.brep - -# output files such as neutronics description files -*.json - -# python files -__pycache__/* -__pycache__ -.cache/ -venv -.eggs/ -paramak.egg-info/ -_version.py - -# test coverage files -coverage.xml -.coverage - -# trelis output files -*.jou -*.log -*.trelis -*.cub - -# neutronics geometry files -*.h5m -*.xml - -# neutronics simulation files -*.h5 -*.out -*.vtk - -# 2D and 3D images of the model -*.svg -*.png -*.vtk -*.jpg -*.xcf -*.gif - -# sphinx built documetation -docs/build/ - -# folders generated by pytest-cov -htmlcov/ -test-reports/ - -# jupyter notebook cache directory -.ipynb_checkpoints -# jupyter notebook files -.ipynb - -# ppp output directory -manifest_processed/ - -# conda buid and dist dir -build/ -dist/ diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index 7df81a3d4..000000000 --- a/CITATION.cff +++ /dev/null @@ -1,52 +0,0 @@ -cff-version: 1.2.0 -message: "If you use this software, please cite it as below." -authors: -- family-names: "Shimwell" - given-names: "Jonathan" - orcid: "https://orcid.org/0000-0001-6909-0946" -- family-names: "Billingsley" - given-names: "John" - orcid: "https://orcid.org/0000-0001-5223-5694" -- family-names: "Delaporte-Mathurin" - given-names: "Rémi" - orcid: "https://orcid.org/0000-0003-1064-8882" -- family-names: "Czentye" - given-names: "Máté" - orcid: "https://orcid.org/0000-0001-6643-7844" -- family-names: "Hearn" - given-names: "Keir" -- family-names: "Shriwise" - given-names: "Patrick" - orcid: "https://orcid.org/0000-0002-3979-7665" -- family-names: "Taylor" - given-names: "Katie" -- family-names: "Edwards" - given-names: "Bruce" -- family-names: "Bluteau" - given-names: "Matthew" - orcid: "https://orcid.org/0000-0001-9498-8475" -- family-names: "Morbey" - given-names: "Declan" - orcid: "https://orcid.org/0000-0001-6207-9832" -- family-names: "Hollands" - given-names: "Angus" -- family-names: "Markan" - given-names: "Zan" -- family-names: "Isacs" - given-names: "Chris" -- family-names: "Davis" - given-names: "Andrew" -- family-names: "Pattinson" - given-names: "Liam" -- family-names: "Peter" - given-names: "Hill" - orcid: "https://orcid.org/0000-0003-3092-1858" -- family-names: "Frank" - given-names: "Schoofs" -- family-names: "Steve" - given-names: "Lilley" - orcid: "https://orcid.org/0000-0002-0547-9378" -title: "The Paramak: automated parametric geometry construction for fusion reactor designs" -version: 0.7.1 -date-released: 2021-1-6 -url: "https://github.com/fusion-energy/paramak" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 9447d914a..000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,77 +0,0 @@ - -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to make participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers 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, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies within all project spaces, and it also applies when -an individual is representing the project or its community in public spaces. -Examples of representing a project or community include using an official -project e-mail address, posting via an official social media account, or acting -as an appointed representative at an online or offline event. Representation of -a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [INSERT EMAIL ADDRESS]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 16e08ffa2..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,41 +0,0 @@ -# Contributing to Paramak - -:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: - - -## Code of Conduct - -This project and everyone participating in it is governed by the [Paramak Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. - -## Resources - -- [GitHub Repository](https://github.com/fusion-energy/paramak) -- [Documentation](http://paramak.readthedocs.io/en/latest) - -## How to Report Bugs - -Paramak is hosted on GitHub and all bugs are reported and tracked through the -[Issues](https://github.com/fusion-energy/paramak/issues) listed on GitHub. - -## How to Suggest Enhancements - -We welcome suggestions for new features or enhancements to the code and -encourage you to submit them as Issues on GitHub. - -## How to Submit Changes - -All changes to Paramak happen through pull requests. We use a -[simplified](https://thomaspoignant.medium.com/simple-git-flow-who-works-dac82430e484) -version of the original [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) workflow that avoids release branches. - -## Code Style - -We have automated PEP formatting of commits using GitHub actions so don't be -surprised if your code gets reformatted when pushing to the repository. - - -## Testing - -We have a handful of tests that run on pull requests and new pull requests are -expected to include tests to show that the feature works. We suggest running -the tests locally before submitting a pull request. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 5f853a64f..000000000 --- a/Dockerfile +++ /dev/null @@ -1,84 +0,0 @@ -# This Dockerfile creates an enviroment with the optional dependancies and the Paramak -# This dockerfile can be built in a few different ways. -# Docker build commands must be run from within the base repository directory -# -# There are build args availalbe for specifying the: -# - cq_version -# The version of CadQuery to use master or 2.1 -# Default is master -# Options: [master, 2, 2.1] -# -# - paramak_version -# The version number applied to the paramak. The CI finds this version number -# from the release tag. -# Default is develop -# Options: version number with three numbers separated by . for example 0.7.1 -# -# Example builds: -# Building using the defaults (cq_version 2.1) -# docker build -t paramak . -# -# Building to include cadquery master. -# Run command from within the base repository directory -# docker build -t paramak --build-arg cq_version=master . -# -# Once build the dockerimage can be run in a few different ways. -# -# Run with the following command for a terminal notebook interface -# docker run -it paramak /bin/bash -# -# Run with the following command for a jupyter notebook interface -# docker run -p 8888:8888 paramak -# -# Once built, the docker image can be tested with either of the following commands -# docker run --rm paramak pytest /tests -# docker run --rm paramak /bin/bash -c "bash run_tests.sh" - -FROM continuumio/miniconda3:4.9.2 as dependencies - -# By default this Dockerfile builds with the latest release of CadQuery 2 -ARG cq_version=master - -ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 \ - DEBIAN_FRONTEND=noninteractive - -RUN apt-get --allow-releaseinfo-change update -RUN apt-get update -y && \ - apt-get upgrade -y - -RUN apt-get install -y libgl1-mesa-glx libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev libosmesa6 libosmesa6-dev libgles2-mesa-dev curl imagemagick && \ - apt-get clean - -# Installing CadQuery and Gmsh -RUN echo installing CadQuery version $cq_version && \ - conda install -c conda-forge -c python python=3.8 && \ - conda install -c conda-forge -c cadquery cadquery="$cq_version" && \ - conda install -c conda-forge moab && \ - conda install -c conda-forge gmsh && \ - conda install -c conda-forge python-gmsh && \ - pip install jupyter-cadquery && \ - conda clean -afy - - -RUN mkdir /home/paramak -EXPOSE 8888 -WORKDIR /home/paramak - - -FROM dependencies as final - -ARG paramak_version=develop - -COPY run_tests.sh run_tests.sh -COPY src src/ -COPY examples examples/ -COPY tests tests/ -COPY pyproject.toml pyproject.toml - -COPY README.md README.md -COPY LICENSE.txt LICENSE.txt - - -RUN SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PARAMAK=${paramak_version} pip install .[tests,docs] - -CMD ["jupyter", "lab", "--notebook-dir=/home/paramak/examples", "--port=8888", "--no-browser", "--ip=0.0.0.0", "--allow-root"] diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 0b011e424..000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2020 UKAEA -Copyright (c) 2021 Paramak contributors - -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/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 78d0ae4fb..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -include README.md -include requirements.txt -include LICENSE.txt \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 20e421ece..000000000 --- a/README.md +++ /dev/null @@ -1,44 +0,0 @@ - -[![N|Python](https://www.python.org/static/community_logos/python-powered-w-100x40.png)](https://www.python.org) - -[![CircleCI](https://circleci.com/gh/fusion-energy/paramak/tree/main.svg?style=svg)](https://circleci.com/gh/fusion-energy/paramak/tree/main) -[![CI with docker build](https://github.com/fusion-energy/paramak/actions/workflows/ci_with_docker_build.yml/badge.svg?branch=main)](https://github.com/fusion-energy/paramak/actions/workflows/ci_with_docker_build.yml) -[![CI with install](https://github.com/fusion-energy/paramak/actions/workflows/ci_with_install.yml/badge.svg?branch=main)](https://github.com/fusion-energy/paramak/actions/workflows/ci_with_install.yml) - -[![codecov](https://codecov.io/gh/fusion-energy/paramak/branch/main/graph/badge.svg)](https://codecov.io/gh/fusion-energy/paramak) - -[![Code Grade](https://api.codiga.io/project/25342/score/svg)](https://app.codiga.io/public/project/25342/paramak/dashboard) -[![Code Grade](https://api.codiga.io/project/25342/status/svg)](https://app.codiga.io/public/project/25342/paramak/dashboard) - - -[![Documentation Status](https://readthedocs.org/projects/paramak/badge/?version=main)](https://paramak.readthedocs.io/en/main/?badge=main) - - -[![Upload Python Package](https://github.com/fusion-energy/paramak/actions/workflows/python-publish.yml/badge.svg)](https://github.com/fusion-energy/paramak/actions/workflows/python-publish.yml) -[![PyPI](https://img.shields.io/pypi/v/paramak?color=brightgreen&label=pypi&logo=grebrightgreenen&logoColor=green)](https://pypi.org/project/paramak/) - -[![anaconda-publish](https://github.com/fusion-energy/paramak/actions/workflows/anaconda-publish.yml/badge.svg)](https://github.com/fusion-energy/paramak/actions/workflows/anaconda-publish.yml) -[![anaconda.org](https://anaconda.org/fusion-energy/paramak/badges/version.svg)](https://anaconda.org/fusion-energy/paramak) - -[![docker-publish-release](https://github.com/fusion-energy/paramak/actions/workflows/docker_publish.yml/badge.svg)](https://github.com/fusion-energy/paramak/actions/workflows/docker_publish.yml) - -[![DOI](https://zenodo.org/badge/269635577.svg)](https://zenodo.org/badge/latestdoi/269635577) - -# Paramak - -Paramak python package allows rapid production of 3D CAD models and neutronics -models of fusion reactors. The purpose of Paramak is to provide geometry for -parametric studies. Paramak can create geometry in standard CAD formats such as -STP, STL, BRep, HTML and DAGMC h5m. - -:point_right: [Documentation](https://paramak.readthedocs.io) - -:point_right: [Video presentation](https://www.youtube.com/embed/fXboew3U7rw) - -:point_right: [Installation](https://paramak.readthedocs.io/en/main/install.html) - -:point_right: [Publication](https://f1000research.com/articles/10-27) - -:point_right: [Docker images](https://github.com/fusion-energy/paramak/pkgs/container/paramak) - -:point_right: Examples with Neutronics [1](https://github.com/fusion-energy/magnetic_fusion_openmc_dagmc_paramak_example), [2](https://github.com/fusion-energy/inertial_fusion_openmc_dagmc_paramak_example), [3](https://github.com/fusion-energy/neutronics-workshop) diff --git a/bld.bat b/bld.bat deleted file mode 100644 index 602113031..000000000 --- a/bld.bat +++ /dev/null @@ -1,2 +0,0 @@ -"%PYTHON%" setup.py install -if errorlevel 1 exit 1 \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100644 index 8c43946e7..000000000 --- a/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -python3 -m pip install --upgrade build -python3 -m build diff --git a/conda/conda_build_config.yaml b/conda/conda_build_config.yaml deleted file mode 100644 index 2465a45a6..000000000 --- a/conda/conda_build_config.yaml +++ /dev/null @@ -1,6 +0,0 @@ -python: - - 3.8 - - 3.9 - # - 3.10 can't solve environment currently as not all dependencies support 3.10 -cadquery: - - master diff --git a/conda/meta.yaml b/conda/meta.yaml deleted file mode 100644 index 5653fac0c..000000000 --- a/conda/meta.yaml +++ /dev/null @@ -1,61 +0,0 @@ -{% set name = "paramak" %} - -package: - name: "{{ name|lower }}" - version: {{ GIT_DESCRIBE_TAG }} - -source: - path: .. - -build: - number: 0 - script: python -m pip install --no-deps --ignore-installed . - -requirements: - build: - - python {{ python }} - - setuptools>=65.4.1 - - setuptools_scm>=7.0.5 - run: - - python {{ python }} - - cadquery {{ cadquery }} - - mpmath - - plasmaboundaries >=0.1.8 - - plotly - - cad_to_dagmc >=0.1.2 # [not win] - - moab * nompi_tempest_* - # - jupyter-cadquery not available on conda - -test: - imports: - - paramak - - paramak.parametric_components - - paramak.parametric_reactors - - paramak.parametric_shapes - requires: - - pytest - - dagmc_h5m_file_inspector # [not win] - source_files: - - tests/tests_units - - examples/ - - tests/tests_h5m/ # [not win] - # - tests/tests_examples/ # TODO include if cadquery_jupyter gets a conda install - commands: - - pytest -v tests/tests_h5m # [not win] - - pytest -v tests/tests_units - # - pytest -v tests/tests_show # TODO include if cadquery_jupyter gets a conda install - # - pytest -v tests/tests_examples # TODO include if cadquery_jupyter gets a conda install - -about: - home: "https://github.com/fusion-energy/paramak" - license: MIT - license_family: MIT - license_file: LICENSE.txt - summary: "Create 3D fusion reactor CAD models based on input parameters" - doc_url: https://paramak.readthedocs.io/ - dev_url: https://github.com/fusion-energy/paramak - summary: Paramak - parameter driven fusion reactor model creation - -extra: - recipe-maintainers: - - shimwell diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 269cadcf8..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -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) \ No newline at end of file diff --git a/docs/build-docs.sh b/docs/build-docs.sh deleted file mode 100644 index c85d2f46f..000000000 --- a/docs/build-docs.sh +++ /dev/null @@ -1,2 +0,0 @@ -sphinx-build -b html ./source/ ./build/html/ -firefox ./build/html/index.html \ No newline at end of file diff --git a/docs/environment.yml b/docs/environment.yml deleted file mode 100644 index 357a89cfd..000000000 --- a/docs/environment.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: docs-environment - -channels: - - conda-forge - - cadquery - -dependencies: - - python=3.9 - - cadquery=master - - pip - - pip: - - plotly - - scipy - - numpy - - matplotlib - - pillow - - plasmaboundaries - - sympy - - sphinx-autodoc-typehints - - sphinxcadquery - - defusedxml - - jupyter-cadquery diff --git a/docs/source/API-Reference.rst b/docs/source/API-Reference.rst deleted file mode 100644 index b08b73cec..000000000 --- a/docs/source/API-Reference.rst +++ /dev/null @@ -1,1954 +0,0 @@ -API-Reference -************* - -Parametric Shapes -================= - - -Rotated Shapes --------------- - -RotateStraightShape() -^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.RotateStraightShape( - points=[ - (400, 100), - (400, 200), - (600, 200), - (600, 100) - ], - rotation_angle = 180 - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.rotate_straight_shape - :members: - :show-inheritance: - -RotateSplineShape() -^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.RotateSplineShape( - points=[ - (500, 0), - (500, -20), - (400, -300), - (300, -300), - (400, 0), - (300, 300), - (400, 300), - (500, 20), - ], - rotation_angle = 180 - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.rotate_spline_shape - :members: - :show-inheritance: - -RotateMixedShape() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.RotateMixedShape( - points=[ - (100, 0, 'straight'), - (200, 0, 'circle'), - (250, 50, 'circle'), - (200, 100, 'straight'), - (150, 100, 'spline'), - (140, 75, 'spline'), - (110, 45, 'spline'), - ], - rotation_angle = 180 - ) - - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.rotate_mixed_shape - :members: - :show-inheritance: - -RotateCircleShape() -^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.RotateCircleShape( - points=[(50, 0)], - radius=5, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.rotate_circle_shape - :members: - :show-inheritance: - - -Extruded Shapes ---------------- - -ExtrudeStraightShape() -^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ExtrudeStraightShape( - points=[ - (300, -300), - (400, 0), - (300, 300), - (400, 300), - (500, 0), - (400, -300), - ], - distance=200 - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.extruded_straight_shape - :members: - :show-inheritance: - -ExtrudeSplineShape() -^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ExtrudeSplineShape( - points=[ - (500, 0), - (500, -20), - (400, -300), - (300, -300), - (400, 0), - (300, 300), - (400, 300), - (500, 20), - ], - distance=200, - - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.extruded_spline_shape - :members: - :show-inheritance: - -ExtrudeMixedShape() -^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ExtrudeMixedShape( - points=[ - (100, 0, 'straight'), - (200, 0, 'circle'), - (250, 50, 'circle'), - (200, 100, 'straight'), - (150, 100, 'spline'), - (140, 75, 'spline'), - (110, 45, 'spline'), - ], - distance=200 - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.extruded_mixed_shape - :members: - :show-inheritance: - -ExtrudeCircleShape() -^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ExtrudeCircleShape( - points=[(50, 0)], - radius=5, - distance=15 - ) - - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.extruded_circle_shape - :members: - :show-inheritance: - - -Swept Shapes ------------- - -SweepStraightShape() -^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.SweepStraightShape( - points=[(-10, 10), (10, 10), (10, -10), (-10, -10)], - path_points=[(50, 0), (30, 50), (70, 100), (50, 150)] - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.sweep_straight_shape - :members: - :show-inheritance: - -SweepSplineShape() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.SweepSplineShape( - points=[(-10, 10), (10, 10), (10, -10), (-10, -10)], - path_points=[(50, 0), (30, 50), (70, 100), (50, 150)] - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.sweep_spline_shape - :members: - :show-inheritance: - -SweepMixedShape() -^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.SweepMixedShape( - points=[(-10, -10, "straight"), (-10, 10, "spline"), (0, 20, "spline"), - (10, 10, "circle"), (0, 0, "circle"), (10, -10, "straight")], - path_points=[(50, 0), (30, 50), (70, 100), (50, 150)] - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.sweep_mixed_shape - :members: - :show-inheritance: - -SweepCircleShape() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.SweepCircleShape( - radius=10, - path_points=[(50, 0), (30, 50), (70, 100), (50, 150)] - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_shapes.sweep_circle_shape - :members: - :show-inheritance: - -Parametric Components -===================== - -These are components that represent a selection of the components found in fusion -reactors and are created from parameters. These components all inherit from the -parametric Shape classes. - -Blankets ---------- - - -BlanketConstantThicknessArcH() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.BlanketConstantThicknessArcH( - inner_lower_point=(300, -200), - inner_mid_point=(400, 0), - inner_upper_point=(300, 200), - thickness=100, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/88293663-38c86d80-ccf3-11ea-9bfa-c166fc99c52c.png - :width: 300 - -.. automodule:: paramak.parametric_components.blanket_constant_thickness_arc_h - :members: - :show-inheritance: - - -BlanketConstantThicknessArcV() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.BlanketConstantThicknessArcV( - inner_lower_point=(300, -200), - inner_mid_point=(500, 0), - inner_upper_point=(300, 200), - thickness=100, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/88293666-39f99a80-ccf3-11ea-8c8d-84275fd0e0ce.png - :width: 350 - -.. automodule:: paramak.parametric_components.blanket_constant_thickness_arc_v - :members: - :show-inheritance: - - -BlanketFP() -^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.BlanketFP( - thickness=100, - stop_angle=-80, - start_angle=250, - offset_from_plasma=30, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/94867319-f0d36e80-0438-11eb-8516-7b8f2a7cc7ee.png - :width: 350 - -.. automodule:: paramak.parametric_components.blanket_fp - :members: - :show-inheritance: - - -BlanketFPPoloidalSegments() -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.BlanketFPPoloidalSegments( - num_segments=7, - segments_gap = 10, - thickness=100, - stop_angle=250, - start_angle=-90, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/98870151-ca0e4c00-246a-11eb-8a37-e7620344d8c1.png - :width: 350 - -.. automodule:: paramak.parametric_components.blanket_poloidal_segment - :members: - :show-inheritance: - - -Blanket Cutting Tools ---------------------- - - -BlanketCutterParallels() -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.BlanketCutterParallels( - thickness=10., - gap_size=30., - height=200., - width=200., - name="blanket_cutter_parallels", - azimuth_placement_angle=[0., 36., 72., 108., 144., 180., 216., 252., 288., 324.], - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/97329670-32580d80-186f-11eb-8b1a-b7712ddb0e83.png - :width: 400 - -.. automodule:: paramak.parametric_components.blanket_cutter_parallels - :members: - :show-inheritance: - - -BlanketCutterStar() -^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.BlanketCutterStar( - height=2000, - width=2000, - distance=100 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/97103794-b0b58380-16a6-11eb-86f0-fb5530d630af.png - :width: 400 - -.. automodule:: paramak.parametric_components.blanket_cutters_star - :members: - :show-inheritance: - - -PoloidalSegmenter() -^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.PoloidalSegments( - shape_to_segment=None, - center_point=(450, 0), - number_of_segments=10, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/93811079-84da5480-fc47-11ea-9c6c-7fd132f6d72d.png - :width: 605px - :align: center - -.. automodule:: paramak.parametric_components.poloidal_segmenter - :members: - :show-inheritance: - - -Center Columns --------------- - -CenterColumnShieldCylinder() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.CenterColumnShieldCylinder( - inner_radius=80, - outer_radius=100, - height=300, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/88293674-3c5bf480-ccf3-11ea-8197-8db75358ff36.png - :width: 370px - -.. automodule:: paramak.parametric_components.center_column_cylinder - :members: - :show-inheritance: - - -CenterColumnShieldHyperbola() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.CenterColumnShieldHyperbola( - inner_radius=50, - mid_radius=75, - outer_radius=100, - height=300, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/88293672-3b2ac780-ccf3-11ea-9907-b1c8fd1ba0f0.png - :width: 410px - -.. automodule:: paramak.parametric_components.center_column_hyperbola - :members: - :show-inheritance: - - -CenterColumnShieldFlatTopHyperbola() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.CenterColumnShieldFlatTopHyperbola( - inner_radius=50, - mid_radius=75, - outer_radius=100, - arc_height=220, - height=300, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/88293680-3ebe4e80-ccf3-11ea-8603-b7a290e6bfb4.png - :width: 370px - -.. automodule:: paramak.parametric_components.center_column_flat_top_hyperbola - :members: - :show-inheritance: - - -CenterColumnShieldFlatTopCircular() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.CenterColumnShieldFlatTopCircular( - inner_radius=50, - mid_radius=75, - outer_radius=100, - arc_height=220, - height=300, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/88293678-3d8d2180-ccf3-11ea-97f7-da9a46beddbf.png - :width: 370px - -.. automodule:: paramak.parametric_components.center_column_flat_top_circular - :members: - :show-inheritance: - - -CenterColumnShieldPlasmaHyperbola() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.CenterColumnShieldPlasmaHyperbola( - inner_radius=150, - mid_offset=50, - edge_offset=40, - height=800, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/86241464-d3bda400-bb9a-11ea-83b4-a3ff0bf630c4.png - :width: 180px - :align: center - -.. automodule:: paramak.parametric_components.center_column_plasma_dependant - :members: - :show-inheritance: - - -InboardFirstwallFCCS() -^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - - shield_to_build_from = paramak.CenterColumnShieldCylinder( - inner_radius=80, - outer_radius=100, - height=300, - rotation_angle=180, - ) - - my_component = paramak.InboardFirstwallFCCS( - central_column_shield=shield_to_build_from, - thickness=50, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - - -.. image:: https://user-images.githubusercontent.com/8583900/94197757-219e2b80-feae-11ea-8e41-0786d56c8b66.png - :width: 786px - :align: center - -.. automodule:: paramak.parametric_components.inboard_firstwall_fccs - :members: - :show-inheritance: - -Coolant Channels ----------------- - - -CoolantChannelRingStraight() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.CoolantChannelRingStraight( - height=200, - channel_radius=10, - ring_radius=70, - number_of_coolant_channels=8, - workplane="XY", - rotation_axis="Z", - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/99048848-ff5f8a80-258d-11eb-9073-123185d7a4fb.png - :width: 230 - -.. automodule:: paramak.parametric_components.coolant_channel_ring_straight - :members: - :show-inheritance: - - -CoolantChannelRingCurved() -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -|CoolantChannelRingCurvedallstp| |CoolantChannelRingCurvedsvg| |CoolantChannelRingCurvedstp| - -.. |CoolantChannelRingCurvedallstp| image:: https://user-images.githubusercontent.com/56687624/99049933-5ade4800-258f-11eb-96c1-4506a8f646a9.png - :width: 200 -.. |CoolantChannelRingCurvedsvg| image:: https://user-images.githubusercontent.com/56687624/99048853-0090b780-258e-11eb-862e-763f7a0f7ec6.png - :width: 230 -.. |CoolantChannelRingCurvedstp| image:: https://user-images.githubusercontent.com/56687624/99049900-4f8b1c80-258f-11eb-81be-bc101e2168e2.png - :width: 100 - -.. automodule:: paramak.parametric_components.coolant_channel_ring_curved - :members: - :show-inheritance: - - -Cutting Tools -------------- - - -CuttingWedge() -^^^^^^^^^^^^^^ - -|CuttingWedgestp| |CuttingWedgesvg| - -.. |CuttingWedgestp| image:: https://user-images.githubusercontent.com/8583900/94726081-a678c180-0354-11eb-93f2-98d4b4a6839e.png - :width: 300px -.. |CuttingWedgesvg| image:: https://user-images.githubusercontent.com/8583900/94726514-433b5f00-0355-11eb-94d2-06b2bba1ed4a.png - :width: 300px - -.. automodule:: paramak.parametric_components.cutting_wedge - :members: - :show-inheritance: - - -CuttingWedgeFS() -^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/94726081-a678c180-0354-11eb-93f2-98d4b4a6839e.png - :width: 300px - -.. automodule:: paramak.parametric_components.cutting_wedge_fs - :members: - :show-inheritance: - - -Divertors ---------- - -ITERtypeDivertor() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ITERtypeDivertor( - # default parameters - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/40028739/88180936-626b9100-cc2e-11ea-92df-1bac68b11e3b.png - :width: 250px - :align: center - -.. automodule:: paramak.parametric_components.divertor_ITER -.. autoclass:: ITERtypeDivertor - :members: - :show-inheritance: - - -ITERtypeDivertorNoDome() -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/56687624/91977407-871d5300-ed1a-11ea-91e5-922e5c9b31a0.png - :width: 250px - :align: center - -.. automodule:: paramak.parametric_components.divertor_ITER_no_dome -.. autoclass:: ITERtypeDivertorNoDome - :members: - :show-inheritance: - - -Inner Toroidal Field Coils --------------------------- - -InnerTfCoilsCircular() -^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.InnerTfCoilsCircular( - inner_radius=25, - outer_radius=100, - number_of_coils=10, - gap_size=5, - height=300, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -|InnerTfCoilsCircularstp| |InnerTfCoilsCircularsvg| - -.. |InnerTfCoilsCircularstp| image:: https://user-images.githubusercontent.com/56687624/86241469-d9b38500-bb9a-11ea-935f-8644fa01ab8c.png - :width: 210px -.. |InnerTFCoilsCircularsvg| image:: https://user-images.githubusercontent.com/56687624/88293695-41b93f00-ccf3-11ea-9ea8-338a64bb5566.png - :width: 390px - -.. automodule:: paramak.parametric_components.inner_tf_coils_circular - :members: - :show-inheritance: - - -InnerTfCoilsFlat() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.InnerTfCoilsFlat( - inner_radius=25, - outer_radius=100, - number_of_coils=10, - gap_size=5, - height=300, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -|InnerTfCoilsFlatstp| |InnerTfCoilsFlatsvg| - -.. |InnerTfCoilsFlatstp| image:: https://user-images.githubusercontent.com/56687624/86241472-db7d4880-bb9a-11ea-8fb9-325b3342fe11.png - :width: 210px -.. |InnerTfCoilsFlatsvg| image:: https://user-images.githubusercontent.com/56687624/88293697-42ea6c00-ccf3-11ea-9e92-dc698813f1ee.png - :width: 390px - -.. automodule:: paramak.parametric_components.inner_tf_coils_flat - :members: - :show-inheritance: - - -Poloidal Field coils --------------------- - -PoloidalFieldCoil() -^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.PoloidalFieldCoil( - center_point=(100, 100), - height=20, - width=20, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -|PoloidalFieldCoilstp| |PoloidalFieldCoilsvg| - -.. |PoloidalFieldCoilstp| image:: https://user-images.githubusercontent.com/56687624/86241487-dfa96600-bb9a-11ea-96ba-54f22ecef1ef.png - :width: 330px -.. |PoloidalFieldCoilsvg| image:: https://user-images.githubusercontent.com/8583900/94807412-86461280-03e7-11eb-9854-ecf66489c262.png - :width: 360px - -.. automodule:: paramak.parametric_components.poloidal_field_coil - :members: - :show-inheritance: - - -PoloidalFieldCoilFP() -^^^^^^^^^^^^^^^^^^^^^ - -|PoloidalFieldCoilFPstp| |PoloidalFieldCoilFPsvg| - -.. |PoloidalFieldCoilFPstp| image:: https://user-images.githubusercontent.com/56687624/86241487-dfa96600-bb9a-11ea-96ba-54f22ecef1ef.png - :width: 330px -.. |PoloidalFieldCoilFPsvg| image:: https://user-images.githubusercontent.com/8583900/95579521-ba47b600-0a2d-11eb-9bdf-7f0415396978.png - :width: 360px - -.. automodule:: paramak.parametric_components.poloidal_field_coil_fp - :members: - :show-inheritance: - - -PoloidalFieldCoilSet() -^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.PoloidalFieldCoilSet( - heights=[10, 10, 20, 20], - widths=[10, 10, 20, 40], - center_points=[(100, 100), (100, 150), (50, 200), (50, 50)], - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/93832861-eb269d80-fc6e-11ea-861c-45de724478a8.png - :width: 395px - :align: center - -.. automodule:: paramak.parametric_components.poloidal_field_coil_set - :members: - :show-inheritance: - - -PoloidalFieldCoilCase() -^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.PoloidalFieldCoilCase( - center_point=(100, 100), - coil_height=20, - coil_width=20, - casing_thickness=10, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -|PoloidalFieldCoilCasestp| |PoloidalFieldCoilCasesvg| - -.. |PoloidalFieldCoilCasestp| image:: https://user-images.githubusercontent.com/56687624/86241492-e1732980-bb9a-11ea-9331-586a39d32cfb.png - :width: 300px -.. |PoloidalFieldCoilCasesvg| image:: https://user-images.githubusercontent.com/8583900/94807553-bab9ce80-03e7-11eb-9a2a-1b78a780b049.png - :width: 370px - -.. automodule:: paramak.parametric_components.poloidal_field_coil_case - :members: - :show-inheritance: - - -PoloidalFieldCoilCaseFC() -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - - pf_coil = paramak.PoloidalFieldCoil( - center_point=(100, 100), - height=20, - width=20, - rotation_angle=180 - ) - - my_component = paramak.PoloidalFieldCoilCaseFC( - pf_coil=pf_coil, - casing_thickness=10, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/56687624/86241492-e1732980-bb9a-11ea-9331-586a39d32cfb.png - :width: 220px - :align: center - -.. automodule:: paramak.parametric_components.poloidal_field_coil_case_fc - :members: - :show-inheritance: - - -PoloidalFieldCoilCaseSet() -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - - my_component = paramak.PoloidalFieldCoilCaseSet( - heights=[10, 10, 20, 20], - widths=[10, 10, 20, 40], - casing_thicknesses=[5, 5, 10, 10], - center_points=[(100, 100), (100, 150), (50, 200), (50, 50)], - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/93908750-e86f8b00-fcf6-11ea-938e-349dd09e5915.png - :width: 586px - :align: center - -.. automodule:: paramak.parametric_components.poloidal_field_coil_case_set - :members: - :show-inheritance: - - -PoloidalFieldCoilCaseSetFC() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - pf_coil_set = paramak.PoloidalFieldCoilSet( - heights=[10, 10, 20, 20], - widths=[10, 10, 20, 40], - center_points=[(100, 100), (100, 150), (50, 200), (50, 50)], - rotation_angle=180 - ) - - my_component = paramak.PoloidalFieldCoilCaseSetFC( - pf_coils=pf_coil_set, - casing_thicknesses=[5, 5, 10, 10], - rotation_angle=180 - ) - - cadquery_object = my_component.solid - - -.. image:: https://user-images.githubusercontent.com/8583900/93908750-e86f8b00-fcf6-11ea-938e-349dd09e5915.png - :width: 586px - :align: center - -.. automodule:: paramak.parametric_components.poloidal_field_coil_case_set_fc - :members: - :show-inheritance: - - -Ports ------ - -CircularPort() -^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - my_component = paramak.CircularPort( - color = (0,1,0), - rotation_angle=45, - blank_flange_thickness=4, - flange_thickness=10, - wall_thickness=2, - distance = 50, - flange_gap=1, - ) - - cadquery_object = my_component.solid - - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - my_component = paramak.CircularPort( - inner_radius = 20, - azimuth_placement_angle= [0., 30., 60., 90., 120., 150., 180., 210., 240., 270., 300., 330.], - color = (0,1,0), - rotation_angle=180, - blank_flange_thickness=4, - flange_thickness=10, - wall_thickness=2, - distance = 50, - flange_gap=0 - ) - - cadquery_object = my_component.solid - - -.. image:: https://user-images.githubusercontent.com/8583900/159140637-ee6c72f8-1094-4261-90a2-b137b2777c92.png - :width: 380px - -.. automodule:: paramak.parametric_components.circular_port - :members: - :show-inheritance: - - -PortCutterRotated() -^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - my_component = paramak.PortCutterRotated( - center_point=(450, 0), - polar_coverage_angle=20, - rotation_angle=10, - polar_placement_angle=45, - azimuth_placement_angle=0 - ) - - cadquery_object = my_component.solid - -|PortCutterRotatedstp| |PortCutterRotatedsvg| - -.. |PortCutterRotatedstp| image:: https://user-images.githubusercontent.com/8583900/95115392-511a2700-073d-11eb-9cb9-d6d2bec80e2c.png - :width: 300px -.. |PortCutterRotatedsvg| image:: https://user-images.githubusercontent.com/8583900/95115923-267c9e00-073e-11eb-898b-bafbb2626b02.png - :width: 380px - -.. automodule:: paramak.parametric_components.port_cutters_rotated - :members: - :show-inheritance: - - -PortCutterRectangular() -^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - my_component = paramak.PortCutterRectangular( - distance=3, - center_point=(0, 0), - height=0.2, - width=0.4, - fillet_radius=0.02, - azimuth_placement_angle=[0, 45, 90, 180] - ) - - cadquery_object = my_component.solid - -|PortCutterRectangularstp| |PortCutterRectangularsvg| - -.. |PortCutterRectangularstp| image:: https://user-images.githubusercontent.com/8583900/95790579-8f808a80-0cd7-11eb-83e1-872a98fe0bc8.png - :width: 300px -.. |PortCutterRectangularsvg| image:: https://user-images.githubusercontent.com/8583900/99831528-1fc3b200-2b57-11eb-9b73-8efab06cf3ef.png - :width: 300px - -.. automodule:: paramak.parametric_components.port_cutters_rectangular - :members: - :show-inheritance: - - -PortCutterCircular() -^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - my_component = paramak.PortCutterCircular( - distance=3, - center_point=(0.25, 0), - radius=0.1, - azimuth_placement_angle=[0, 45, 90], - ) - - cadquery_object = my_component.solid - -|PortCutterCircularstp| |PortCutterCircularsvg| - -.. |PortCutterCircularstp| image:: https://user-images.githubusercontent.com/8583900/95790580-90b1b780-0cd7-11eb-944f-14fe290f8442.png - :width: 300px -.. |PortCutterCircularsvg| image:: https://user-images.githubusercontent.com/8583900/99830949-53eaa300-2b56-11eb-886e-d5ee04c85b4a.png - :width: 300px - -.. automodule:: paramak.parametric_components.port_cutters_circular - :members: - :show-inheritance: - - -Plasmas -------- - -Plasma() -^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.Plasma( - major_radius=620, - minor_radius=210, - triangularity=0.33, - elongation=1.85, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -|Plasmastp| |Plasmasvg| - -.. |Plasmastp| image:: https://user-images.githubusercontent.com/8583900/87316638-f39b8300-c51d-11ea-918b-5194d600d068.png - :width: 300px -.. |Plasmasvg| image:: https://user-images.githubusercontent.com/8583900/94805331-226e1a80-03e4-11eb-8623-3e6db0aa1489.png - :width: 380px - -.. automodule:: paramak.parametric_components.tokamak_plasma - :members: - :show-inheritance: - - -PlasmaFromPoints() -^^^^^^^^^^^^^^^^^^ - -|PlasmaFPstp| |PlasmaFPsvg| - -.. |PlasmaFPstp| image:: https://user-images.githubusercontent.com/8583900/87316638-f39b8300-c51d-11ea-918b-5194d600d068.png - :width: 300px -.. |PlasmaFPsvg| image:: https://user-images.githubusercontent.com/8583900/94805330-213ced80-03e4-11eb-80b4-b162f2f7a565.png - :width: 380px - -.. automodule:: paramak.parametric_components.tokamak_plasma_from_points - :members: - :show-inheritance: - - -PlasmaBoundaries() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.PlasmaBoundaries( - A=-0.155, - major_radius=620, - minor_radius=210, - triangularity=0.33, - elongation=1.85, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/97366104-a958ca80-189e-11eb-8bc6-9892b04ab053.png - :width: 300px - -.. automodule:: paramak.parametric_components.tokamak_plasma_plasmaboundaries - :members: - :show-inheritance: - - -Toroidal Field Coils --------------------- - -TFCoilCasing() -^^^^^^^^^^^^^^ - -|TFCoilCasingallstp| |TFCoilCasingaCutstp| |TFCoilCasingsvg| - -.. |TFCoilCasingallstp| image:: https://user-images.githubusercontent.com/8583900/98821523-94943f00-2427-11eb-8047-68f2762c56d7.png - :width: 200px -.. |TFCoilCasingaCutstp| image:: https://user-images.githubusercontent.com/8583900/98821532-96f69900-2427-11eb-99e1-e2461be67511.png - :width: 130px -.. |TFCoilCasingsvg| image:: https://user-images.githubusercontent.com/8583900/99081345-904c5b00-25ba-11eb-8a4f-956d4ad6bbc0.png - :width: 310px - -.. automodule:: paramak.parametric_components.tf_coil_casing - :members: - :show-inheritance: - - -ToroidalFieldCoilRectangle() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ToroidalFieldCoilRectangle() - - cadquery_object = my_component.solid - -|ToroidalFieldCoilRectangleallstp| |ToroidalFieldCoilRectanglesvg| |ToroidalFieldCoilRectangleastp| - -.. |ToroidalFieldCoilRectangleallstp| image:: https://user-images.githubusercontent.com/8583900/86822598-bcdbed80-c083-11ea-820e-f6c13d639170.png - :width: 200px -.. |ToroidalFieldCoilRectangleastp| image:: https://user-images.githubusercontent.com/8583900/94585086-6abbfa00-0277-11eb-91de-0b2548601587.png - :width: 130px -.. |ToroidalFieldCoilRectanglesvg| image:: https://user-images.githubusercontent.com/56687624/98582375-cd62d580-22ba-11eb-8002-ea7c731bad8a.png - :width: 310px - -.. automodule:: paramak.parametric_components.toroidal_field_coil_rectangle - :members: - :show-inheritance: - - -ToroidalFieldCoilCoatHanger() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ToroidalFieldCoilCoatHanger() - - cadquery_object = my_component.solid - -|ToroidalFieldCoilCoatHangerallstp| |ToroidalFieldCoilCoatHangersvg| |ToroidalFieldCoilCoatHangerastp| - -.. |ToroidalFieldCoilCoatHangersvg| image:: https://user-images.githubusercontent.com/56687624/98582371-cb991200-22ba-11eb-8e15-86d273a8b819.png - :width: 300px -.. |ToroidalFieldCoilCoatHangerastp| image:: https://user-images.githubusercontent.com/8583900/98979392-3775b780-2513-11eb-9649-46839571f5dd.png - :width: 130px -.. |ToroidalFieldCoilCoatHangerallstp| image:: https://user-images.githubusercontent.com/8583900/87075236-f04f8100-c217-11ea-9ffa-4791b722b9e7.png - :width: 210px - -.. automodule:: paramak.parametric_components.toroidal_field_coil_coat_hanger - :members: - :show-inheritance: - - -ToroidalFieldCoilPrincetonD() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ToroidalFieldCoilPrincetonD( - R1=80, - R2=300, - thickness=30, - distance=30, - number_of_coils=1 - ) - - cadquery_object = my_component.solid - -|ToroidalFieldCoilPrincetonDallstp| |ToroidalFieldCoilPrincetonDsvg| |ToroidalFieldCoilPrincetonDastp| - -.. |ToroidalFieldCoilPrincetonDallstp| image:: https://user-images.githubusercontent.com/56687624/92124475-bd7bd080-edf5-11ea-9c49-1db6422d77a0.png - :width: 250px -.. |ToroidalFieldCoilPrincetonDsvg| image:: https://user-images.githubusercontent.com/56687624/112809879-69c32400-9072-11eb-8f9f-34379d74659f.png - :width: 280px -.. |ToroidalFieldCoilPrincetonDastp| image:: https://user-images.githubusercontent.com/8583900/94479853-4c012900-01cd-11eb-9b59-0fcd5f4dc531.png - :width: 170px - -.. automodule:: paramak.parametric_components.toroidal_field_coil_princeton_d - :members: - :show-inheritance: - - -ToroidalFieldCoilTripleArc() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ToroidalFieldCoilTripleArc( - R1=80, - h=200, - radii=(70, 100), - coverages=(60, 60), - thickness=30, - distance=30, - number_of_coils=1, - ) - - cadquery_object = my_component.solid - - - -|ToroidalFieldCoilTripleArcallstp| |ToroidalFieldCoilTripleArcstp| |ToroidalFieldCoilTripleArcsvg| - -.. |ToroidalFieldCoilTripleArcallstp| image:: https://user-images.githubusercontent.com/56687624/92124454-b654c280-edf5-11ea-96d2-c0957f37a733.png - :width: 240px -.. |ToroidalFieldCoilTripleArcstp| image:: https://user-images.githubusercontent.com/8583900/94835218-51e34e00-0409-11eb-9372-0272c43a4844.png - :width: 190px -.. |ToroidalFieldCoilTripleArcsvg| image:: https://user-images.githubusercontent.com/8583900/99848162-2eb75e00-2b71-11eb-80d2-6c695b56821d.png - :width: 320px - -.. automodule:: paramak.parametric_components.toroidal_field_coil_triple_arc - :members: - :show-inheritance: - - -ToroidalFieldCoilRectangleRoundCorners() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ToroidalFieldCoilRectangleRoundCorners( - with_inner_leg=True, - lower_inner_coordinates=(0, 0), - mid_point_coordinates=(100, 100), - thickness=30, - number_of_coils=1, - distance=20, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -|TFCoilRoundCornersvg| |TFCoilRoundCornersvg2| |TFCoilRoundCornerstp| - -.. |TFCoilRoundCornersvg| image:: https://user-images.githubusercontent.com/85617935/125979064-c9aff900-4a07-462d-91bd-53af3bc66559.png - :width: 255 -.. |TFCoilRoundCornersvg2| image:: https://user-images.githubusercontent.com/85617935/125979248-1dbbd7be-916b-4921-86ed-a942b6cda757.png - :width: 255 -.. |TFCoilRoundCornerstp| image:: https://user-images.githubusercontent.com/85617935/125977357-3b893496-fc6b-4f06-8a95-10164cb70d7c.png - :width: 255 - -.. automodule:: paramak.parametric_components.toroidal_field_coil_round_corners - :members: - :show-inheritance: - - -Vacuum Vessels --------------- - -VacuumVessel() -^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.VacuumVessel( - height=20, - inner_radius=10, - thickness=2, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - -|VacuumVesselstp| |VacuumVesselsvgWP| |VacuumVesselsvg| - -.. |VacuumVesselstp| image:: https://user-images.githubusercontent.com/8583900/95792842-2d765400-0cdc-11eb-8a8a-e3a88e923bc0.png - :width: 150 -.. |VacuumVesselsvgWP| image:: https://user-images.githubusercontent.com/8583900/95792839-2c452700-0cdc-11eb-9313-edfd2bfad5dc.png - :width: 350 -.. |VacuumVesselsvg| image:: https://user-images.githubusercontent.com/8583900/95792893-4ed74000-0cdc-11eb-9d19-c66cdb3a5ca3.png - :width: 255 - -.. automodule:: paramak.parametric_components.vacuum_vessel - :members: - :show-inheritance: - - -VacuumVesselInnerLeg() -^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.VacuumVesselInnerLeg( - inner_height=760, - inner_radius=400, - inner_leg_radius=250, - thickness=20, - rotation_angle=180, - ) - - cadquery_object = my_component.solid - - -|VacuumVesselInnerLegstp| |VacuumVesselInnerLegsvg| - -.. |VacuumVesselInnerLegstp| image:: https://user-images.githubusercontent.com/8583900/116575888-fa598200-a906-11eb-8c87-1fcfb7917342.png - :width: 255 -.. |VacuumVesselInnerLegsvg| image:: https://user-images.githubusercontent.com/58937462/116578576-76ed6000-a909-11eb-9592-d87f2e702514.png - :width: 255 - -.. automodule:: paramak.parametric_components.vacuum_vessel_inner_leg - :members: - :show-inheritance: - - -CapsuleVacuumVessel() -^^^^^^^^^^^^^^^^^^^^^ -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.CapsuleVacuumVessel( - outer_start_point=(0, -600), - radius = 300, - thickness=30, - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/85617923/125429341-e5bdf20d-1739-41ce-953b-eabc01c04511.png - :width: 255 - -.. automodule:: paramak.parametric_components.capsule_vacuum_vessel - :members: - :show-inheritance: - - -DishedVacuumVessel() -^^^^^^^^^^^^^^^^^^^^ -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.DishedVacuumVessel(rotation_angle=180) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/160503281-3aabf145-22b0-4953-bc4f-3f75a6696b5e.png - -.. automodule:: paramak.parametric_components.dished_vacuum_vessel - :members: - :show-inheritance: - -ConstantThicknessDome() -^^^^^^^^^^^^^^^^^^^^^^^ -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ConstantThicknessDome(rotation_angle=180) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/160503286-71a6d771-1d47-476e-a0cf-85fb94c9389c.png - -.. automodule:: paramak.parametric_components.constant_thickness_dome - :members: - :show-inheritance: - - - - -Other components ----------------- - -ExtrudeRectangle() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ExtrudeRectangle( - height=10, - width= 10, - distance=20, - center_point=(20, 20) - ) - - cadquery_object = my_component.solid - -.. automodule:: paramak.parametric_components.extrude_rectangle - :members: - :show-inheritance: - -ExtrudeHollowRectangle() -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.ExtrudeHollowRectangle( - height=10, - width=15, - casing_thickness=1, - distance=2 - ) - - cadquery_object = my_component.solid - -.. image:: https://user-images.githubusercontent.com/8583900/145905435-87d05386-d2e5-4de3-8f03-5a08cc5a4b22.png - :width: 200px - -.. automodule:: paramak.parametric_components.extrude_hollow_rectangle - :members: - :show-inheritance: - -HexagonPin() -^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.HexagonPin( - length_of_side=5, - distance=10, - center_point=(10, 20) - ) - - cadquery_object = my_component.solid - -|HexagonPinstp| |HexagonPinsvg| - -.. |HexagonPinstp| image:: https://user-images.githubusercontent.com/8583900/107092190-07307300-67fb-11eb-995c-b5622de717ee.png - :width: 300px -.. |HexagonPinsvg| image:: https://user-images.githubusercontent.com/8583900/107092487-9c336c00-67fb-11eb-8eb1-755462493140.png - :width: 300px - -.. automodule:: paramak.parametric_components.hexagon_pin - :members: - :show-inheritance: - - -RotatedTrapezoid() -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.RotatedTrapezoid( - length_1=10, - length_2=20, - length_3=30, - pivot_angle=0, - pivot_point=(100, 50), - rotation_angle=180 - ) - - cadquery_object = my_component.solid - -|RotatedTrapezoidstp| |RotatedTrapezoidsvg| - -.. |RotatedTrapezoidstp| image:: https://user-images.githubusercontent.com/8583900/101964551-b42aad00-3c09-11eb-8ff2-fc0e52ba33cc.png - :width: 240px -.. |RotatedTrapezoidsvg| image:: https://user-images.githubusercontent.com/8583900/101966787-06230100-3c11-11eb-8d70-587b50aaf987.png - :width: 510px - -.. automodule:: paramak.parametric_components.rotated_trapezoid - :members: - :show-inheritance: - - -RotatedIsoscelesTriangle -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :gridsize: 0 - - import paramak - my_component = paramak.RotatedIsoscelesTriangle( - height=20, - base_length=15, - pivot_angle=0, - pivot_point=(100, 50), - rotation_angle=180, - workplane='XY' - ) - - cadquery_object = my_component.solid - -|RotatedIsoscelesTrianglestp| |RotatedIsoscelesTrianglesvg| - -.. |RotatedIsoscelesTrianglestp| image:: https://user-images.githubusercontent.com/8583900/102000883-e0b2f780-3ce3-11eb-94aa-4cd69d2647e2.png - :width: 240px -.. |RotatedIsoscelesTrianglesvg| image:: https://user-images.githubusercontent.com/8583900/102001079-c37f2880-3ce5-11eb-967e-f9263a231257.png - :width: 510px - -.. automodule:: paramak.parametric_components.rotated_isosceles_triangle - :members: - :show-inheritance: - -Parametric Reactors -=================== - -These some of the reactor designs that can be created using the Paramak. - -.. image:: https://user-images.githubusercontent.com/8583900/115291309-7fe17300-a14c-11eb-9859-be85075eb0b9.png - :width: 713 - :align: center - -Inertial Confinement --------------------- - -FlfSystemCodeReactor() -^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/136050185-da7e3cc8-1ead-4e11-8c17-2cbe2e4a3ad2.png - :width: 450 - :align: center - -.. image:: https://user-images.githubusercontent.com/8583900/211223396-41ed8628-5352-4e7a-8c4a-97914174954e.png - :width: 300 - :align: center - -.. automodule:: paramak.parametric_reactors.flf_system_code_reactor - :members: - :show-inheritance: - - -BallReactors ------------- - -BallReactor() -^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/99136724-91af6f00-261e-11eb-9956-476b818a0ee3.png - :width: 400 - :align: center - -The above image is colored by components. The TF coils are blue, the PF coils -are red, PF coil cases are yellow, the center column shielding is dark green, -the blanket is light green, the divertor is orange, the firstwall is grey -and the rear wall of the blanket is teal. - -.. image:: https://user-images.githubusercontent.com/8583900/119011892-6458ca80-b98d-11eb-92b1-bbc370cb9c84.png - :width: 450 - :align: center - -.. automodule:: paramak.parametric_reactors.ball_reactor - :members: - :show-inheritance: - -SegmentedBlanketBallReactor() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/99136727-94aa5f80-261e-11eb-965d-0ccceb2743fc.png - :width: 400 - :align: center - -The above image is colored by components. The TF coils are blue, the PF coils -are red, PF coil cases are yellow, the center column shielding is dark green, -the blanket is light green, the divertor is orange, the firstwall is grey -and the rear wall of the blanket is teal. - -Note that there is an odd number of blanket segments in this diagram so that -the blanket breeder zone and the first wall can be see in this 180 slice. - -.. image:: https://user-images.githubusercontent.com/8583900/99431100-1db4e580-2902-11eb-82ce-3f864d13524c.png - :width: 450 - :align: center - -Note the above image has the plasma purposefully hidden on the right hand side -so that the internal blanket structure can be seen. - -.. automodule:: paramak.parametric_reactors.segmented_blanket_ball_reactor - :members: - :show-inheritance: - -SingleNullBallReactor() -^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/99136728-983de680-261e-11eb-8398-51ae433f5546.png - :width: 400 - :align: center - -The above image is colored by components. The TF coils are blue, the PF coils -are red, PF coil cases are yellow, the center column shielding is dark green, -the blanket is light green, the divertor is orange, the firstwall is grey and -the rear wall of the blanket is teal. - -.. automodule:: paramak.parametric_reactors.single_null_ball_reactor - :members: - :show-inheritance: - - -Submersion Tokamaks -------------------- - -SubmersionTokamak() -^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/99136719-8e1be800-261e-11eb-907d-a9bafaebdbb8.png - :width: 400 - :align: center - -The above image is colored by components, the TF coils are blue, the PF coils -are red, PF coil cases are yellow, the center column shielding is dark green, the blanket is light green, the -divertor is orange, the firstwall is grey and the rear wall of the blanket is -teal and the support legs are black. - -.. image:: https://user-images.githubusercontent.com/8583900/116117207-e36f2180-a6b3-11eb-8c65-4263336b6a68.png - :width: 450 - :align: center - -.. automodule:: paramak.parametric_reactors.submersion_reactor - :members: - :show-inheritance: - -SingleNullSubmersionTokamak() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/99136731-9aa04080-261e-11eb-87a5-502708dfebcc.png - :width: 400 - :align: center - -The above image is colored by component. The TF coils are blue, the PF coils -are red, PF coil cases are yellow, the center column shielding is dark green, -the blanket is light green, the divertor is orange, the firstwall is grey, the -rear wall of the blanket is teal and the supports are black. - -.. automodule:: paramak.parametric_reactors.single_null_submersion_reactor - :members: - :show-inheritance: - - -Specific use case reactors --------------------------- - -CenterColumnStudyReactor() -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/99136734-9e33c780-261e-11eb-837b-16a0bc59f8a7.png - :width: 400 - :align: center - -The above image is colored by component. The center column shielding is dark -green, the blanket is light green, the divertor is orange, the firstwall is -grey and the blanket is teal. - -Note this reactor is purposefully simple so that center column parameter -studies can be performed quickly. - -.. image:: https://user-images.githubusercontent.com/8583900/98946297-9e7f7600-24eb-11eb-92cd-1c3bd13ad49b.png - :width: 600 - :align: center - -.. automodule:: paramak.parametric_reactors.center_column_study_reactor - :members: - :show-inheritance: - -NegativeTriangularityReactor() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/85617935/144302746-181689dd-a4a8-43d4-9ed5-33518f36d4de.png - :width: 300 - :align: left - -.. image:: https://user-images.githubusercontent.com/85617935/144303187-8cb71e2d-fc35-450f-a8f4-88b6650d56b7.png - :width: 300 - :align: right - -The above image is coloured by component. On the left the low_aspect attribute is True, whereas on the right, the -low_aspect attribute is set to False, as well as the PF coils outside were moved +200 units from default outward. - -.. image:: https://user-images.githubusercontent.com/85617935/144302481-022bf072-c7f7-409e-9701-1e24b7a9a7de.jpg - :width: 400 - :align: center - -.. automodule:: paramak.parametric_reactors.negative_triangularity_reactor - :members: - :show-inheritance: - - -Reactors from publications --------------------------- - -EuDemoFrom2015PaperDiagram() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/110224418-4f62b400-7ed3-11eb-85f1-e40dc74f5671.png - :width: 400 - :align: center - -The above image is colored by component. - -.. automodule:: paramak.parametric_reactors.eu_demo_2015_reactor - :members: - :show-inheritance: - -IterFrom2020PaperDiagram() -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/40028739/110248118-cf3e5c00-7f6f-11eb-9e68-864c1a1e8676.png - :width: 400 - :align: center - -The above image is colored by component. - -.. automodule:: paramak.parametric_reactors.iter_paper_2020 - :members: - :show-inheritance: - -SparcFrom2020PaperDiagram() -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/100032191-5ae01280-2def-11eb-9654-47c3869b3a2c.png - :width: 400 - :align: center - -.. automodule:: paramak.parametric_reactors.sparc_paper_2020 - :members: - :show-inheritance: - - -Shape() class -============= - -The Shape class is the container class for all Shapes and Components. - -Shape() -^^^^^^^ - -.. automodule:: paramak.shape - :members: - :show-inheritance: - - -Reactor() class -=============== - -The Reactor() class allows Shapes() to be grouped together and jointly operated -on. - -Reactor() -^^^^^^^^^ - -.. automodule:: paramak.reactor - :members: - :show-inheritance: - - -Utils functions -=============== - -Utility functions provides useful functions that are used by both the Shape() -class and the Reactor class. They can also be used directly. - -utils -^^^^^ - -.. automodule:: paramak.utils - :members: - :show-inheritance: diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index 3387564c7..000000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,208 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Configuration file for the Sphinx documentation builder. -# -# This file does only contain a selection of the most common options. For a -# full list see the documentation: -# http://www.sphinx-doc.org/en/master/config - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys -import paramak - -sys.path.insert(0, os.path.abspath("../..")) -sys.path.insert(0, os.path.abspath("../../tests")) -sys.path.insert(0, os.path.abspath("../../examples")) - -# -- Project information ----------------------------------------------------- - -project = "Paramak" -author = "Paramak contributors" - -# The short X.Y version -version = ".".join(paramak.__version__.split(".")[0:2]) -# The full version, including alpha/beta/rc tags -release = paramak.__version__ - - -# -- General configuration --------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# -needs_sphinx = "4.1.2" - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx_autodoc_typehints", - "sphinx.ext.coverage", - "sphinx.ext.napoleon", - "sphinxcadquery.sphinxcadquery", -] - - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -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 = None - -# 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 = [] - -# avoids this error -# WARNING: html_static_path entry '_static' does not exist -html_static_path = [] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = None - - -# shorten module names in readme -add_module_names = False - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "default" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -html_theme_options = { - "display_version": True, - "prev_next_buttons_location": "bottom", - "style_external_links": False, - # toc options - "collapse_navigation": True, - "sticky_navigation": True, - "navigation_depth": 3, - "includehidden": True, - "titles_only": False, -} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} - - -# -- Options for HTMLHelp output --------------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = "Paramakdoc" - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "Paramak.tex", - "Paramak Documentation", - "Paramak contributors", - "manual", - ), -] - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "paramak", "Paramak Documentation", [author], 1)] - - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "Paramak", - "Paramak Documentation", - author, - "Paramak", - "One line description of project.", - "Miscellaneous", - ), -] - - -# -- Options for Epub output ------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = project - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -# -# epub_identifier = '' - -# A unique identification for the text. -# -# epub_uid = '' - -# A list of files that should not be packed into the epub file. -epub_exclude_files = ["search.html"] - - -# -- Extension configuration ------------------------------------------------- - -html_favicon = "favicon.ico" diff --git a/docs/source/examples.rst b/docs/source/examples.rst deleted file mode 100644 index 60d2b5847..000000000 --- a/docs/source/examples.rst +++ /dev/null @@ -1,481 +0,0 @@ -Examples -======== - -Parametric Shapes ------------------ - -make_CAD_from_points.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/56687624/88064585-641c5280-cb63-11ea-97b1-1b7dcfabc07c.gif - :width: 450 - :height: 275 - :align: center - -`Link to notebook `__ - - -make_blanket_from_parameters.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/56687624/87058944-9e4f3100-c200-11ea-8bd3-669b3705c179.png - :width: 400 - :height: 400 - :align: center - -`Link to notebook `__ - - -make_blanket_from_points.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/56687624/87058930-998a7d00-c200-11ea-846e-4084dbf82748.png - :width: 400 - :height: 400 - :align: center - -`Link to notebook `__ - - -make_can_reactor_from_parameters.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/56687624/87060447-74970980-c202-11ea-8720-403c24dbabcc.gif - :width: 1300 - :height: 450 - :align: center - -`Link to notebook `__ - - -make_can_reactor_from_points.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/56687624/87060447-74970980-c202-11ea-8720-403c24dbabcc.gif - :width: 1300 - :height: 450 - :align: center - -`Link to notebook `__ - - -make_html_diagram_from_stp_file.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/117488160-fb705c00-af63-11eb-882e-27e284ceb79f.png - :align: center - -`Link to notebook `__ - -Parametric Components ---------------------- - -make_components_blankets.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`Link to notebook `__ - - -make_components_center_column.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`Link to notebook `__ - -make_components_magnets.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`Link to notebook `__ - -make_components_other.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`Link to notebook `__ - - -make_demo_style_blankets.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/93619812-02e0f600-f9d1-11ea-903c-913c8bcb0f1b.png - :width: 1050 - :height: 350 - :align: center - -`Link to notebook `__ - - -make_firstwall_for_neutron_wall_loading.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/93807581-bc92cd80-fc42-11ea-8522-7fe14287b3c4.png - :width: 437 - :height: 807 - :align: center - -`Link to notebook `__ - - -make_magnet_set.ipynb -^^^^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/99276201-5088ac00-2824-11eb-9927-a7ea1094b1e5.png - :width: 500 - :align: center - -`Link to notebook `__ - - -make_plasmas.ipynb -^^^^^^^^^^^^^^^^^^ - -.. image:: https://user-images.githubusercontent.com/8583900/93624384-2e1b1380-f9d8-11ea-99d1-9bf9e4e5b838.png - :width: 1050 - :height: 700 - :align: center - -`Link to notebook `__ - - -make_vacuum_vessel_with_ports.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`Link to notebook `__ - - -make_varible_offset_firstwall.ipynb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`Link to notebook `__ - - -Parametric Reactors -------------------- - - -FlfSystemCodeReactor -^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.FlfSystemCodeReactor( - inner_blanket_radius=100., - blanket_thickness=70., - blanket_height=500., - lower_blanket_thickness=50., - upper_blanket_thickness=40., - blanket_vv_gap=20., - upper_vv_thickness=10., - vv_thickness=10., - lower_vv_thickness=10., - rotation_angle=180, - ) - - cadquery_object = my_reactor.solid - - -ball_reactor -^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.BallReactor( - inner_bore_radial_thickness=10, - inboard_tf_leg_radial_thickness=30, - center_column_shield_radial_thickness=60, - divertor_radial_thickness=150, - inner_plasma_gap_radial_thickness=30, - plasma_radial_thickness=300, - outer_plasma_gap_radial_thickness=30, - plasma_gap_vertical_thickness=50, - firstwall_radial_thickness=30, - blanket_radial_thickness=50, - blanket_rear_wall_radial_thickness=30, - elongation=2, - triangularity=0.55, - number_of_tf_coils=16, - rotation_angle=90, - pf_coil_case_thicknesses=[10, 10, 10, 10], - pf_coil_radial_thicknesses=[20, 50, 50, 20], - pf_coil_vertical_thicknesses=[20, 50, 50, 20], - pf_coil_radial_position=[500, 575, 575, 500], - pf_coil_vertical_position=[300, 100, -100, -300], - rear_blanket_to_tf_gap=50, - outboard_tf_coil_radial_thickness=100, - outboard_tf_coil_poloidal_thickness=50 - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ - - -ball_reactor_single_null -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.SingleNullBallReactor( - inner_bore_radial_thickness=50, - inboard_tf_leg_radial_thickness=50, - center_column_shield_radial_thickness=50, - divertor_radial_thickness=90, - inner_plasma_gap_radial_thickness=50, - plasma_radial_thickness=200, - outer_plasma_gap_radial_thickness=50, - plasma_gap_vertical_thickness=30, - firstwall_radial_thickness=50, - blanket_radial_thickness=100, - blanket_rear_wall_radial_thickness=50, - elongation=2, - triangularity=0.55, - number_of_tf_coils=16, - rotation_angle=90, - pf_coil_case_thicknesses=[10, 10, 10, 10], - pf_coil_radial_thicknesses=[20, 50, 50, 20], - pf_coil_vertical_thicknesses=[20, 50, 50, 20], - pf_coil_radial_position=[500, 575, 575, 500], - pf_coil_vertical_position=[300, 100, -100, -300], - rear_blanket_to_tf_gap=50, - outboard_tf_coil_radial_thickness=100, - outboard_tf_coil_poloidal_thickness=50, - divertor_position="lower" - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ - - -center_column_study_reactor -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.CenterColumnStudyReactor( - inner_bore_radial_thickness=20, - inboard_tf_leg_radial_thickness=50, - center_column_shield_radial_thickness_mid=50, - center_column_shield_radial_thickness_upper=100, - inboard_firstwall_radial_thickness=20, - divertor_radial_thickness=100, - inner_plasma_gap_radial_thickness=80, - plasma_radial_thickness=200, - outer_plasma_gap_radial_thickness=90, - elongation=2.3, - triangularity=0.45, - plasma_gap_vertical_thickness=40, - center_column_arc_vertical_thickness=520, - rotation_angle=90 - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ - -eu_demo_from_2015_paper -^^^^^^^^^^^^^^^^^^^^^^^ - - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.EuDemoFrom2015PaperDiagram( - rotation_angle=90 - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ - - -make_animation -^^^^^^^^^^^^^^ - - -|animation1| |animation2| - -.. |animation1| image:: https://user-images.githubusercontent.com/8583900/107040396-155ca000-67b7-11eb-8b99-4aa9bf8a8655.gif - :width: 300 -.. |animation2| image:: https://user-images.githubusercontent.com/8583900/107030664-e2131480-67a8-11eb-84bb-59656e9e7722.gif - :width: 300 - -`Link to notebook `__ - - -segmented_blanket_ball_reactor -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.SegmentedBlanketBallReactor( - inner_bore_radial_thickness=5, - inboard_tf_leg_radial_thickness=25, - center_column_shield_radial_thickness=45, - divertor_radial_thickness=150, - inner_plasma_gap_radial_thickness=50, - plasma_radial_thickness=300, - outer_plasma_gap_radial_thickness=50, - plasma_gap_vertical_thickness=30, - firstwall_radial_thickness=15, - blanket_radial_thickness=50, - blanket_rear_wall_radial_thickness=30, - elongation=2, - triangularity=0.55, - number_of_tf_coils=16, - pf_coil_case_thicknesses=[10, 10, 10, 10], - pf_coil_radial_thicknesses=[20, 50, 50, 20], - pf_coil_vertical_thicknesses=[20, 50, 50, 20], - pf_coil_radial_position=[500, 550, 550, 500], - pf_coil_vertical_position=[270, 100, -100, -270], - rear_blanket_to_tf_gap=50, - rotation_angle=90, - outboard_tf_coil_radial_thickness=100, - outboard_tf_coil_poloidal_thickness=50, - gap_between_blankets=30, - number_of_blanket_segments=15, - blanket_fillet_radius=15, - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ - -sparc_from_2020_paper -^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.SparcFrom2020PaperDiagram( - rotation_angle=90 - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ - - -submersion_reactor -^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.SubmersionTokamak( - inner_bore_radial_thickness=30, - inboard_tf_leg_radial_thickness=30, - center_column_shield_radial_thickness=30, - divertor_radial_thickness=80, - inner_plasma_gap_radial_thickness=50, - plasma_radial_thickness=200, - outer_plasma_gap_radial_thickness=50, - firstwall_radial_thickness=30, - blanket_rear_wall_radial_thickness=30, - number_of_tf_coils=16, - rotation_angle=180, - support_radial_thickness=90, - inboard_blanket_radial_thickness=30, - outboard_blanket_radial_thickness=30, - elongation=2.00, - triangularity=0.50, - pf_coil_case_thicknesses=[10, 10, 10, 10], - pf_coil_radial_thicknesses=[20, 50, 50, 20], - pf_coil_vertical_thicknesses=[20, 50, 50, 20], - pf_coil_radial_position=[500, 550, 550, 500], - pf_coil_vertical_position=[270, 100, -100, -270], - rear_blanket_to_tf_gap=50, - outboard_tf_coil_radial_thickness=30, - outboard_tf_coil_poloidal_thickness=30, - ) - cadquery_object = my_reactor.solid - -`Link to notebook `__ - - -submersion_reactor_single_null -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.SingleNullSubmersionTokamak( - inner_bore_radial_thickness=30, - inboard_tf_leg_radial_thickness=30, - center_column_shield_radial_thickness=30, - divertor_radial_thickness=80, - inner_plasma_gap_radial_thickness=50, - plasma_radial_thickness=200, - outer_plasma_gap_radial_thickness=50, - firstwall_radial_thickness=30, - blanket_rear_wall_radial_thickness=30, - number_of_tf_coils=16, - rotation_angle=180, - support_radial_thickness=90, - inboard_blanket_radial_thickness=30, - outboard_blanket_radial_thickness=30, - elongation=2.00, - triangularity=0.50, - pf_coil_case_thicknesses=[10, 10, 10, 10], - pf_coil_radial_thicknesses=[20, 50, 50, 20], - pf_coil_vertical_thicknesses=[20, 50, 50, 20], - pf_coil_radial_position=[500, 550, 550, 500], - pf_coil_vertical_position=[270, 100, -100, -270], - rear_blanket_to_tf_gap=50, - outboard_tf_coil_radial_thickness=30, - outboard_tf_coil_poloidal_thickness=30, - divertor_position="lower", - support_position="lower" - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ - - -iter_from_2020_paper -^^^^^^^^^^^^^^^^^^^^ - -.. cadquery:: - :select: cadquery_object - :include-source: true - :gridsize: 0 - - import paramak - my_reactor = paramak.IterFrom2020PaperDiagram( - rotation_angle=90 - ) - - cadquery_object = my_reactor.solid - -`Link to notebook `__ diff --git a/docs/source/favicon.ico b/docs/source/favicon.ico deleted file mode 100644 index f8aa2c31f..000000000 Binary files a/docs/source/favicon.ico and /dev/null differ diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index cda3e777e..000000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,201 +0,0 @@ -Paramak -======= - - -.. cadquery:: - :select: text - :gridsize: 0 - :height: 100px - - import cadquery as cq - text = cq.Workplane().text( - txt="Paramak", - fontsize=0.8, - distance=-0.5, - cut=True, - font="Sans" - ) - -The Paramak python package allows rapid production of 3D CAD models of fusion -reactors. The purpose of the Paramak is to provide geometry for parametric -studies in a variety of geometry formats including STL, STP, Brep, HTML and DAGMC h5m -files. - -CadQuery functions provide the majority of the features, and incorporating -additional capabilities is straightforward for developers with Python knowledge. - -Contributions are welcome. - -.. raw:: html - - - - -History -------- - -The package was originally conceived by Jonathan Shimwell and based on the -`FreeCAD Python API `_ When -`CadQuery 2 `_ was released the project -started to migrate the code base. Shortly after this migration the project -became open-source and has flourished ever since. - -The project has grown largely due to two contributors in particular -(John Billingsley and Remi Delaporte-Mathurin) and others have also helped, -you can see all those who have helped the development in the -`GitHub contributions `_. - -The code has been professionally reviewed by -`PullRequest.com `_ who produced a -`report `_ -and inline `suggestions `_. - -The Paramak source code is distributed with a permissive open-source license -(MIT) and is available from the GitHub repository -`https://github.com/fusion-energy/paramak `_ - - -Publications and Presentations ------------------------------- - -- Published in F1000 Research. `https://f1000research.com/articles/10-27 `_ - -- Presented at the Spanish Fusion HPC Workshop and available in the 3rd video and starts at minute 41. `https://hpcfusion2020.bsc.es/media `_ also available directly `here `_ - -- Slides from first released presentation. `Link `_ - -- Paramak used for geometry creation in an ARC reactor study. `https://iopscience.iop.org/article/10.1088/1741-4326/ac5450 `_ - - -Features --------- - -In general the Paramak takes input arguments and creates 3D objects. This can -be accomplished via the use of parametric Shapes, parametric Components and -parametric Reactors with each level building upon the level below. - -Parametric Shapes are the simplest and accept points and connection information -in 2D space (defaults to x,z plane) and performs operations on them to create 3D -volumes. The points and connections are provided by the user when making -parametric Shapes. Supported CAD operations include (rotate, extrude, sweep) -and Boolean operations such as cut, union and intersect. Additionally the -CadQuery objects created can be combined and modified using CadQuery's powerful -filtering capabilities to further customise the shapes by performing operations -like edge filleting. - -Parametric Components build on top of this foundation and will calculate the -points and connections for you when provided with input arguments. The inputs -differ between components as a center column requires different inputs to a -breeder blanket or a magnet. - -Parametric Reactors build upon these two lower level objects to create an -entire reactor model from input parameters. Linkage between the components is -encoded in each parametric Rector design. - -Some of the different parametric reactor families are shown below. - -.. image:: https://user-images.githubusercontent.com/8583900/118414245-58be8880-b69b-11eb-981e-c5806f721e0f.png - :width: 713 - :align: center - -A sub section of the available parametric Components are shown below. - -.. image:: https://user-images.githubusercontent.com/8583900/98823600-387eea00-242a-11eb-9fe3-df65aaa3dd21.png - :width: 713 - :align: center - -The different families of parametric Shapes that can be made with the Paramak -are shown int he table below. - - - -.. |rotatestraight| image:: https://user-images.githubusercontent.com/56687624/87055469-4f070180-c1fc-11ea-9679-a29e37a90e15.png - :height: 120px - -.. |extrudestraight| image:: https://user-images.githubusercontent.com/56687624/87055493-56c6a600-c1fc-11ea-8c58-f5b62ae72e0e.png - :height: 120px - -.. |sweepstraight| image:: https://user-images.githubusercontent.com/56687624/98713447-8c80c480-237f-11eb-8615-c090e93138f6.png - :height: 120px - -.. |rotatespline| image:: https://user-images.githubusercontent.com/56687624/87055473-50382e80-c1fc-11ea-95dd-b4932b1e78d9.png - :height: 120px - -.. |extrudespline| image:: https://user-images.githubusercontent.com/56687624/98713431-87bc1080-237f-11eb-9075-01bca99b7018.png - :height: 120px - -.. |sweepspline| image:: https://user-images.githubusercontent.com/56687624/98713443-8b4f9780-237f-11eb-83bb-38ca7f222073.png - :height: 120px - -.. |rotatecircle| image:: https://user-images.githubusercontent.com/56687624/98713427-868ae380-237f-11eb-87af-cf6b5fe032b2.png - :height: 120px - -.. |extrudecircle| image:: https://user-images.githubusercontent.com/56687624/87055517-5b8b5a00-c1fc-11ea-83ef-d4329c6815f7.png - :height: 120px - -.. |sweepcircle| image:: https://user-images.githubusercontent.com/56687624/98713436-88ed3d80-237f-11eb-99cd-27dcb4f313b1.png - :height: 120px - -.. |rotatemixed| image:: https://user-images.githubusercontent.com/56687624/87055483-53cbb580-c1fc-11ea-878d-92835684c8ff.png - :height: 120px - -.. |extrudemixed| image:: https://user-images.githubusercontent.com/56687624/87055511-59c19680-c1fc-11ea-8740-8c7987745c45.png - :height: 120px - -.. |sweepmixed| image:: https://user-images.githubusercontent.com/56687624/98713440-8a1e6a80-237f-11eb-9eed-12b9d7731090.png - :height: 120px - - - - - - -+--------------------------------------+--------------------------------------+---------------------------------------+---------------------------------------+ -| | Rotate | Extrude | Sweep | -+======================================+======================================+=======================================+=======================================+ -| Points connected with straight lines | |rotatestraight| | |extrudestraight| | |sweepstraight| | -| | | | | -| | | | | -| | | | | -| | | | | -| | :: | :: | :: | -| | | | | -| | RotateStraightShape() | ExtrudeStraightShape() | SweepStraightShape() | -+--------------------------------------+--------------------------------------+---------------------------------------+---------------------------------------+ -| Points connected with spline curves | |rotatespline| | |extrudespline| | |sweepspline| | -| | | | | -| | | | | -| | | | | -| | | | | -| | :: | :: | :: | -| | | | | -| | RotateSplineShape() | ExtrudeSplineShape() | SweepSplineShape() | -+--------------------------------------+--------------------------------------+---------------------------------------+---------------------------------------+ -| Points connected with a circle | |rotatecircle| | |extrudecircle| | |sweepcircle| | -| | | | | -| | | | | -| | | | | -| | | | | -| | :: | :: | :: | -| | | | | -| | RotateCircleShape() | ExtrudeCircleShape() | SweepCircleShape() | -+--------------------------------------+--------------------------------------+---------------------------------------+---------------------------------------+ -| Points connected with a mixture | |rotatemixed| | |extrudemixed| | |sweepmixed| | -| | | | | -| :: | | | | -| | | | | -| (splines, straights and circles) | | | | -| | :: | :: | :: | -| | | | | -| | RotateMixedShape() | ExtrudeMixedShape() | SweepMixedShape() | -+--------------------------------------+--------------------------------------+---------------------------------------+---------------------------------------+ - -Table Of Contents - -.. toctree:: - :maxdepth: 3 - - install - quick-tour - examples - API-Reference diff --git a/docs/source/install.rst b/docs/source/install.rst deleted file mode 100644 index d2e185249..000000000 --- a/docs/source/install.rst +++ /dev/null @@ -1,218 +0,0 @@ -Install -******* - - -Video tutorials ---------------- - -.. raw:: html - - - - - - -Prerequisites -------------- - -To use the paramak tool you will need Python 3 installed using Miniconda or -Anaconda, or Miniforge - -* `Miniconda `_ -* `Anaconda `_ -* `Miniforge `_ - -Once you have a version of Conda installed then proceed with the Paramak -specific steps. - - -Install (mamba) ---------------- - -This is the recommended method as it installs all the dependencies and Mamba is faster and requires less RAM than the pure Conda method. - -Create a new environment (Python 3.8 and 3.9 are supported). - -.. code-block:: bash - - conda create --name paramak_env python=3.8 - - -Then activate the new environment. - -.. code-block:: bash - - conda activate paramak_env - -Then install mamba. - -.. code-block:: bash - - conda install -c conda-forge mamba - -Then install the Paramak. - -.. code-block:: bash - - mamba install -c fusion-energy -c cadquery -c conda-forge paramak=0.8.7 - -Now you should be ready to import paramak from your new python environment. - -Install (conda) ---------------- - -Create a new environment (Python 3.8 and 3.9 are supported). - -.. code-block:: bash - - conda create --name paramak_env python=3.8 - - -Then activate the new environment. - -.. code-block:: bash - - conda activate paramak_env - - -Then install the Paramak. - -.. code-block:: bash - - conda install -c fusion-energy -c cadquery -c conda-forge paramak=0.8.7 - -Now you should be ready to import paramak from your new python environment. - - -Install (conda + pip) ---------------------- - -Create a new environment (Python 3.8 and 3.9 are supported). - -.. code-block:: bash - - conda create --name paramak_env python=3.8 - - -Then activate the new environment. - -.. code-block:: bash - - conda activate paramak_env - - -Then install the CadQuery. - -.. code-block:: bash - - conda install -c cadquery -c conda-forge cadquery=master - -If you want to make use of the prototype export_dagmc_h5m() method the you will need -MOAB and PyMoab for the export_dagmc_h5m() feature to work. -The MOAB Conda install does not currently support Windows and therefore Windows -users will have to compile MOAB. If the export_dagmc_h5m() feature is not -needed then this stage can be skipped. - -.. code-block:: bash - - conda install -c conda-forge gmsh=4.9.4 - conda install -c conda-forge python-gmsh=4.9.4 - conda install -c conda-forge 'moab>=5.3.0' - -Then pip install the Paramak. - -.. code-block:: bash - - pip install paramak - -Now you should be ready to import paramak from your new python environment. - - -Optional Jupyter-CadQuery install ---------------------------------- - -Jupyter-Cadquery is an extension to CadQuery that allows objects to be rendered -in JupyterLab. This can improve the visualization experience for Paramak users -running Jupyter. Jupyter-Cadquery is also needed when using the export_html_3d() -method. - - `Jupyter-Cadquery GitHub page `_ - -Terminal command to install Jupyter-Cadquery - -.. code-block:: bash - - pip install jupyter-cadquery - - -Docker Image Installation -------------------------- - -Another option is to use the Docker image which contains all the required -dependencies. - -1. Install Docker CE for `Ubuntu `_ , -`Mac OS `_ or -`Windows `_ -including the part where you enable docker use as a non-root user. - -2. Pull the docker image from the store by typing the following command in a -terminal window, or Windows users might prefer PowerShell. - -.. code-block:: bash - - docker pull ghcr.io/fusion-energy/paramak - -3. Now that you have the docker image you can enable graphics linking between -your os and docker, and then run the docker container by typing the following -commands in a terminal window. - -.. code-block:: bash - - sudo docker run -p 8888:8888 ghcr.io/fusion-energy/paramak - -4. A URL should be displayed in the terminal and can now be opened in the -internet browser of your choice. This will load up the examples folder where -you can view the 3D objects created. - -Alternatively the Docker image can be run in interactive terminal mode . - -.. code-block:: bash - - docker run -it --entrypoint /bin/bash ghcr.io/fusion-energy/paramak - -You may also want to make use of the -`--volume `_ -flag when running Docker so that you can retrieve files from the Docker -environment to your base system. - - -Developer Installation ----------------------- - -If you want to contribute to the paramak or then you might want to install the -package in a more dynamic manner. - -Download and install MiniConda, create a new python environment and activate the -environment as covered in the installation procedure above. - -Then install CadQuery. - -.. code-block:: bash - - conda install -c conda-forge -c cadquery cadquery=master - - -Then clone the repository - -.. code-block:: bash - - git clone https://github.com/fusion-energy/paramak.git - -Navigate to the paramak repository and within the terminal install the paramak -package and the dependencies using pip with e -e (developer option). - -.. code-block:: bash - - cd paramak - pip install -e . diff --git a/docs/source/quick-tour.rst b/docs/source/quick-tour.rst deleted file mode 100644 index 135d91ebc..000000000 --- a/docs/source/quick-tour.rst +++ /dev/null @@ -1,137 +0,0 @@ -Quick Tour -========== - - -Usage - Parametric Shapes -------------------------- - -There are a collection of Python scripts in the `examples `_ -folder that demonstrate simple shape construction and visualisation. -However here is a quick example of a RotateStraightShape. - -After importing the class the user then sets the points. By default, points -should be a list of (x,z) points. In this case the points are connected with -straight lines. - -.. code-block:: python - - import paramak - - my_shape = paramak.RotateStraightShape(points = [(20,0), (20,100), (100,0)]) - -Once these properties have been set then users can write 3D volumes in CAD STP -or STL, Brep, HTML and h5m formats. - -.. code-block:: python - - my_shape.export_stp('example.stp') - - my_shape.export_stl('example.stl') - - my_shape.export_brep('example.brep') - - my_shape.export_dagmc_h5m('example.h5m') - - my_shape.export_html_3d('example.html') - -.. image:: https://user-images.githubusercontent.com/56687624/88935761-ff0ae000-d279-11ea-8848-de9b486840d9.png - :width: 350 - :height: 300 - :align: center - -Usage - Parametric Components ------------------------------ - -Parametric components are wrapped versions of the eight basic shapes where -parameters drive the construction of the shape. There are numerous parametric -components for a variety of different reactor components such as center columns, -blankets, poloidal field coils. This example shows the construction of a -plasma. Users could also construct a plasma by using a RotateSplineShape() -combined with coordinates for the points. However a parametric component called -Plasma can construct a plasma from more convenient parameters. Parametric -components also inherit from the Shape object so they have access to the same -methods like export_stp() and export_stl(). - -.. code-block:: python - - import paramak - - my_plasma = paramak.Plasma( - major_radius=620, - minor_radius=210, - triangularity=0.33, - elongation=1.85 - ) - - my_plasma.export_stp('plasma.stp') - -.. image:: https://user-images.githubusercontent.com/56687624/88935871-1ea20880-d27a-11ea-82e1-1afa55ff9ba8.png - :width: 350 - :height: 300 - :align: center - -Usage - Parametric Reactors ---------------------------- - -Parametric Reactors() are wrapped versions of a combination of parametric -shapes and components that comprise a particular reactor design. Some -parametric reactors include a ball reactor and a submersion ball reactor. These -allow full reactor models to be constructed by specifying a series of simple -parameters. This example shows the construction of a simple ball reactor -without the optional outer pf and tf coils. - -.. code-block:: python - - import paramak - - my_reactor = paramak.BallReactor( - inner_bore_radial_thickness = 50, - inboard_tf_leg_radial_thickness = 50, - center_column_shield_radial_thickness= 50, - divertor_radial_thickness = 100, - inner_plasma_gap_radial_thickness = 50, - plasma_radial_thickness = 200, - outer_plasma_gap_radial_thickness = 50, - firstwall_radial_thickness = 50, - blanket_radial_thickness = 100, - blanket_rear_wall_radial_thickness = 50, - elongation = 2, - triangularity = 0.55, - rotation_angle = 180 - ) - - my_reactor.export_stp() - -.. image:: https://user-images.githubusercontent.com/56687624/89203299-465fdc00-d5ac-11ea-8663-a5b7eecfb584.png - :width: 350 - :height: 300 - :align: center - -Usage - Reactor Object ----------------------- - -A reactor object provides a container object for all Shape objects created, and -allows operations to be performed on the whole collection of Shapes. - -.. code-block:: python - - import paramak - -Initiate a Reactor object and pass a list of all Shape objects to the -shapes_and_components parameter. - -.. code-block:: python - - my_reactor = paramak.Reactor(shapes_and_components = [my_shape, my_plasma]) - -A html graph of the combined Shapes can be created. - -.. code-block:: python - - my_reactor.export_html('reactor.html') - -An interactive 3D object can be embedded into a portable html file. - -.. code-block:: python - - my_reactor.export_html_3d('reactor.html') diff --git a/examples/example_parametric_components/make_components_blankets.ipynb b/examples/example_parametric_components/make_components_blankets.ipynb deleted file mode 100644 index 322e5dae3..000000000 --- a/examples/example_parametric_components/make_components_blankets.ipynb +++ /dev/null @@ -1,163 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "rot_angle = 90\n", - "\n", - "plasma = paramak.Plasma(\n", - " # default parameters\n", - " rotation_angle=rot_angle,\n", - ")\n", - "plasma.show()\n", - "\n", - "component = paramak.BlanketFP(\n", - " plasma=plasma,\n", - " thickness=100,\n", - " stop_angle=90,\n", - " start_angle=-90,\n", - " offset_from_plasma=30,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.BlanketCutterStar(\n", - " height=2000,\n", - " width=2000,\n", - " distance=100\n", - ")\n", - "\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.BlanketFP(\n", - " plasma=plasma,\n", - " thickness=100,\n", - " stop_angle=90,\n", - " start_angle=250,\n", - " offset_from_plasma=30,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.BlanketFP(\n", - " plasma=plasma,\n", - " thickness=100,\n", - " stop_angle=250,\n", - " start_angle=-90,\n", - " offset_from_plasma=30,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.BlanketConstantThicknessArcH(\n", - " inner_lower_point=(300, -200),\n", - " inner_mid_point=(400, 0),\n", - " inner_upper_point=(300, 200),\n", - " thickness=100,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.BlanketConstantThicknessArcV(\n", - " inner_lower_point=(300, -200),\n", - " inner_mid_point=(500, 0),\n", - " inner_upper_point=(300, 200),\n", - " thickness=100,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.BlanketFPPoloidalSegments(\n", - " num_segments=7,\n", - " segments_gap = 10,\n", - " thickness=100,\n", - " stop_angle=250,\n", - " start_angle=-90,\n", - " rotation_angle=180\n", - ")\n", - "\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_components_center_column.ipynb b/examples/example_parametric_components/make_components_center_column.ipynb deleted file mode 100644 index 7ab7c6fff..000000000 --- a/examples/example_parametric_components/make_components_center_column.ipynb +++ /dev/null @@ -1,210 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "rot_angle = 90\n", - "\n", - "CenterColumnShieldCylinder = paramak.CenterColumnShieldCylinder(\n", - " inner_radius=80,\n", - " outer_radius=100,\n", - " height=300,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "CenterColumnShieldCylinder.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InboardFirstwallFCCS(\n", - " central_column_shield=CenterColumnShieldCylinder,\n", - " thickness=50,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "CenterColumnShieldHyperbola = paramak.CenterColumnShieldHyperbola(\n", - " inner_radius=50,\n", - " mid_radius=75,\n", - " outer_radius=100,\n", - " height=300,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "CenterColumnShieldHyperbola.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InboardFirstwallFCCS(\n", - " central_column_shield=CenterColumnShieldHyperbola,\n", - " thickness=50,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "CenterColumnShieldCircular = paramak.CenterColumnShieldCircular(\n", - " inner_radius=50,\n", - " mid_radius=75,\n", - " outer_radius=100,\n", - " height=300,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "CenterColumnShieldCircular.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InboardFirstwallFCCS(\n", - " central_column_shield=CenterColumnShieldCircular,\n", - " thickness=50,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "CenterColumnShieldFlatTopHyperbola = paramak.CenterColumnShieldFlatTopHyperbola(\n", - " inner_radius=50,\n", - " mid_radius=75,\n", - " outer_radius=100,\n", - " arc_height=220,\n", - " height=300,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "CenterColumnShieldFlatTopHyperbola.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InboardFirstwallFCCS(\n", - " central_column_shield=CenterColumnShieldFlatTopHyperbola,\n", - " thickness=50,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "CenterColumnShieldFlatTopCircular = paramak.CenterColumnShieldFlatTopCircular(\n", - " inner_radius=50,\n", - " mid_radius=75,\n", - " outer_radius=100,\n", - " arc_height=220,\n", - " height=300,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "CenterColumnShieldFlatTopCircular.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InboardFirstwallFCCS(\n", - " central_column_shield=CenterColumnShieldFlatTopCircular,\n", - " thickness=50,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "CenterColumnShieldPlasmaHyperbola = paramak.CenterColumnShieldPlasmaHyperbola(\n", - " inner_radius=150,\n", - " mid_offset=50,\n", - " edge_offset=40,\n", - " height=800,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "CenterColumnShieldPlasmaHyperbola.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InboardFirstwallFCCS(\n", - " central_column_shield=CenterColumnShieldPlasmaHyperbola,\n", - " thickness=50,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_components_magnets.ipynb b/examples/example_parametric_components/make_components_magnets.ipynb deleted file mode 100644 index 07d243f9b..000000000 --- a/examples/example_parametric_components/make_components_magnets.ipynb +++ /dev/null @@ -1,261 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InnerTfCoilsCircular(\n", - " inner_radius=25,\n", - " outer_radius=100,\n", - " number_of_coils=10,\n", - " gap_size=5,\n", - " height=300,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.InnerTfCoilsFlat(\n", - " inner_radius=25,\n", - " outer_radius=100,\n", - " number_of_coils=10,\n", - " gap_size=5,\n", - " height=300,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "rot_angle = 180\n", - "\n", - "# this makes 4 pf coil cases\n", - "pf_coil_set = paramak.PoloidalFieldCoilCaseSet(\n", - " heights=[10, 10, 20, 20],\n", - " widths=[10, 10, 20, 40],\n", - " casing_thicknesses=[5, 5, 10, 10],\n", - " center_points=[(100, 100), (100, 150), (50, 200), (50, 50)],\n", - " rotation_angle=rot_angle,\n", - ")\n", - "pf_coil_set.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# this makes 4 pf coils\n", - "pf_coil_set = paramak.PoloidalFieldCoilSet(\n", - " heights=[10, 10, 20, 20],\n", - " widths=[10, 10, 20, 40],\n", - " center_points=[(100, 100), (100, 150), (50, 200), (50, 50)],\n", - " rotation_angle=rot_angle,\n", - ")\n", - "pf_coil_set.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# this makes 4 pf coil cases for the 4 pf coils made above\n", - "component = paramak.PoloidalFieldCoilCaseSetFC(\n", - " pf_coils=pf_coil_set,\n", - " casing_thicknesses=[5, 5, 10, 10],\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# this makes 1 pf coils\n", - "pf_coil = paramak.PoloidalFieldCoil(\n", - " center_point=(100, 100),\n", - " height=20,\n", - " width=20,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "pf_coil.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# this makes one PF coil case for the provided pf coil\n", - "component = paramak.PoloidalFieldCoilCaseSetFC(\n", - " pf_coils=[pf_coil],\n", - " casing_thicknesses=[10],\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.PoloidalFieldCoilCaseFC(\n", - " pf_coil=pf_coil,\n", - " casing_thickness=10,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.PoloidalFieldCoilCase(\n", - " center_point=(100, 100),\n", - " coil_height=20,\n", - " coil_width=20,\n", - " casing_thickness=10,\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.ToroidalFieldCoilRectangle(\n", - " horizontal_start_point=(100, 700),\n", - " vertical_mid_point=(800, 0),\n", - " thickness=150,\n", - " distance=60,\n", - " number_of_coils=1,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.ToroidalFieldCoilCoatHanger(\n", - " horizontal_start_point=(200, 500),\n", - " horizontal_length=400,\n", - " vertical_mid_point=(700, 50),\n", - " vertical_length=500,\n", - " thickness=50,\n", - " distance=50,\n", - " number_of_coils=1,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.ToroidalFieldCoilTripleArc(\n", - " R1=80,\n", - " h=200,\n", - " radii=(70, 100),\n", - " coverages=(60, 60),\n", - " thickness=30,\n", - " distance=30,\n", - " number_of_coils=1,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "magnet = paramak.ToroidalFieldCoilPrincetonD(\n", - " R1=80,\n", - " R2=300,\n", - " thickness=30,\n", - " distance=30,\n", - " number_of_coils=1,\n", - ")\n", - "magnet.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.TFCoilCasing(\n", - " magnet=magnet,\n", - " inner_offset=10,\n", - " outer_offset=15,\n", - " vertical_section_offset=20,\n", - " distance=40\n", - ")\n", - "component.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_components_other.ipynb b/examples/example_parametric_components/make_components_other.ipynb deleted file mode 100644 index bae7d3afd..000000000 --- a/examples/example_parametric_components/make_components_other.ipynb +++ /dev/null @@ -1,301 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This python script demonstrates the creation of all parametric shapes available\n", - "in the paramak tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "rot_angle = 180\n", - "all_components = []" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plasma = paramak.Plasma(\n", - " # default parameters\n", - " rotation_angle=rot_angle,\n", - ")\n", - "plasma.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.ITERtypeDivertor(\n", - " # default parameters\n", - " rotation_angle=rot_angle,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.ExtrudeHollowRectangle(\n", - " height=10,\n", - " width=15,\n", - " casing_thickness=1,\n", - " distance=2,\n", - " workplane='YZ'\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.CircularPort(\n", - " color = (0,1,0),\n", - " rotation_angle=45,\n", - " blank_flange_thickness=4,\n", - " flange_thickness=10,\n", - " wall_thickness=2,\n", - " distance = 50,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.PortCutterRotated(\n", - " center_point=(450, 0),\n", - " polar_coverage_angle=20,\n", - " rotation_angle=10,\n", - " polar_placement_angle=45,\n", - " azimuth_placement_angle=0\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.PortCutterRectangular(\n", - " distance=3,\n", - " center_point=(0, 0),\n", - " height=0.2,\n", - " width=0.4,\n", - " fillet_radius=0.02,\n", - " azimuth_placement_angle=[0, 45, 90, 180]\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.PortCutterCircular(\n", - " distance=3,\n", - " center_point=(0.25, 0),\n", - " radius=0.1,\n", - " # azimuth_placement_angle=[0, 45, 90, 180], # TODO: fix issue #548\n", - " azimuth_placement_angle=[0, 45, 90],\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.VacuumVessel(\n", - " height=2, inner_radius=1, thickness=0.2, rotation_angle=270\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.CoolantChannelRingStraight(\n", - " height=200,\n", - " channel_radius=10,\n", - " ring_radius=70,\n", - " number_of_coolant_channels=8,\n", - " workplane=\"XY\",\n", - " rotation_axis=\"Z\",\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.CoolantChannelRingCurved(\n", - " height=200,\n", - " channel_radius=10,\n", - " ring_radius=70,\n", - " mid_offset=-20,\n", - " number_of_coolant_channels=8,\n", - " workplane=\"XY\",\n", - " path_workplane=\"XZ\",\n", - " force_cross_section=True\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.RotatedIsoscelesTriangle(\n", - " height=20,\n", - " base_length=15,\n", - " pivot_angle=0,\n", - " pivot_point=(100, 50),\n", - " rotation_angle=70,\n", - " workplane='XY',\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.RotatedTrapezoid(\n", - " length_1=10,\n", - " length_2=20,\n", - " length_3=30,\n", - " pivot_angle=0,\n", - " pivot_point=(100, 50),\n", - " rotation_angle=45,\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.PoloidalSegments(\n", - " number_of_segments=5,\n", - " center_point=(400, 50)\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.HexagonPin(\n", - " length_of_side=5,\n", - " distance=10,\n", - " center_point=(10, 20)\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.VacuumVesselInnerLeg(\n", - " inner_height=760,\n", - " inner_radius=400,\n", - " inner_leg_radius=250,\n", - " thickness=20\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "component = paramak.BlanketCutterParallels(\n", - " thickness=10.,\n", - " gap_size=30.,\n", - " height=200.,\n", - " width=200.,\n", - " name=\"blanket_cutter_parallels\",\n", - " azimuth_placement_angle=[0., 36., 72., 108., 144., 180., 216., 252., 288., 324.],\n", - ")\n", - "component.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_demo_style_blankets.ipynb b/examples/example_parametric_components/make_demo_style_blankets.ipynb deleted file mode 100644 index 98f14757f..000000000 --- a/examples/example_parametric_components/make_demo_style_blankets.ipynb +++ /dev/null @@ -1,135 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "This script makes a blanket and then segments it in a similar\n", - "manner to the EU DEMO segmentation for remote maintenance.\n", - "\"\"\"\n", - "\n", - "import math\n", - "\n", - "import numpy as np\n", - "import paramak\n", - "\n", - "\n", - "number_of_segments = 5\n", - "gap_size = 15.\n", - "central_block_width = 200\n", - "\n", - "offset = (360 / number_of_segments) / 2\n", - "\n", - "# a plasma shape is made and used by the BlanketFP, which builds around\n", - "# the plasma\n", - "plasma = paramak.Plasma(\n", - " elongation=1.59,\n", - " triangularity=0.33,\n", - " major_radius=910,\n", - " minor_radius=290)\n", - "plasma.solid\n", - "\n", - "# this makes a cutter shape that is used to make the blanket bananna\n", - "# segment that has parallel sides\n", - "parallel_outboard_gaps_outer = paramak.BlanketCutterParallels(\n", - " thickness=gap_size, azimuth_placement_angle=np.linspace(\n", - " 0, 360, number_of_segments, endpoint=False),\n", - " gap_size=central_block_width)\n", - "\n", - "# this makes a gap that seperates the inboard and outboard blanket\n", - "inboard_to_outboard_gaps = paramak.ExtrudeStraightShape(\n", - " points=[(plasma.high_point[0] - (0.5 * gap_size), plasma.high_point[1]),\n", - " (plasma.high_point[0] - (0.5 * gap_size), plasma.high_point[1] + 1000),\n", - " (plasma.high_point[0] + (0.5 * gap_size), plasma.high_point[1] + 1000),\n", - " (plasma.high_point[0] + (0.5 * gap_size), plasma.high_point[1]),\n", - " ],\n", - " distance=math.tan(math.radians(360 / (2 * number_of_segments))) * plasma.high_point[0] * 2,\n", - " azimuth_placement_angle=np.linspace(0, 360, number_of_segments, endpoint=False)\n", - ")\n", - "\n", - "# this makes the regular gaps (non parallel) gaps on the outboard blanket\n", - "outboard_gaps = paramak.BlanketCutterStar(\n", - " distance=gap_size,\n", - " azimuth_placement_angle=np.linspace(\n", - " 0 + offset,\n", - " 360 + offset,\n", - " number_of_segments,\n", - " endpoint=False)\n", - ")\n", - "\n", - "# makes the outboard blanket with cuts for all the segmentation\n", - "outboard_blanket = paramak.BlanketFP(\n", - " plasma=plasma,\n", - " thickness=100,\n", - " stop_angle=90,\n", - " start_angle=-60,\n", - " offset_from_plasma=30,\n", - " rotation_angle=360,\n", - " cut=[\n", - " outboard_gaps,\n", - " parallel_outboard_gaps_outer,\n", - " inboard_to_outboard_gaps])\n", - "\n", - "# this makes the regular gaps on the outboard blanket\n", - "inboard_gaps = paramak.BlanketCutterStar(\n", - " distance=gap_size, azimuth_placement_angle=np.linspace(\n", - " 0, 360, number_of_segments * 2, endpoint=False))\n", - "\n", - "# makes the inboard blanket with cuts for all the segmentation\n", - "inboard_blanket = paramak.BlanketFP(\n", - " plasma=plasma,\n", - " thickness=100,\n", - " stop_angle=90,\n", - " start_angle=260,\n", - " offset_from_plasma=30,\n", - " rotation_angle=360,\n", - " cut=[inboard_gaps, inboard_to_outboard_gaps],\n", - " union=outboard_blanket\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "inboard_blanket.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# saves the blanket as an stp file\n", - "inboard_blanket.export_stp(filename='blanket.stp')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_firstwall_for_neutron_wall_loading.ipynb b/examples/example_parametric_components/make_firstwall_for_neutron_wall_loading.ipynb deleted file mode 100644 index 47febfd1c..000000000 --- a/examples/example_parametric_components/make_firstwall_for_neutron_wall_loading.ipynb +++ /dev/null @@ -1,74 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "For some neutronics tallies such as neutron wall loading it is necessary to\n", - "segment the geometry so that individual neutronics tallies can be recorded\n", - "for each face. This can be done using the PoloidalSegments(). With this\n", - "segmented geometry it is then easier to find neutron wall loading as a function\n", - "of poloidal angle.\n", - "\"\"\"\n", - "\n", - "import paramak\n", - "\n", - "\n", - "# makes the firstwall\n", - "firstwall = paramak.BlanketFP(\n", - " minor_radius=150,\n", - " major_radius=450,\n", - " triangularity=0.55,\n", - " elongation=2.0,\n", - " thickness=2,\n", - " start_angle=270,\n", - " stop_angle=-90,\n", - " rotation_angle=10\n", - ")\n", - "\n", - "# segments the firstwall poloidally into 40 equal angle segments\n", - "segmented_firstwall = paramak.PoloidalSegments(\n", - " shape_to_segment=firstwall,\n", - " center_point=(450, 0), # this is the middle of the plasma\n", - " number_of_segments=40,\n", - ")\n", - "\n", - "segmented_firstwall.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# saves the segmented firstwall as an stp file\n", - "segmented_firstwall.export_stp(filename='segmented_firstwall.stp')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_magnet_set.ipynb b/examples/example_parametric_components/make_magnet_set.ipynb deleted file mode 100644 index b5cf403ea..000000000 --- a/examples/example_parametric_components/make_magnet_set.ipynb +++ /dev/null @@ -1,119 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "\"\"\"\n", - "This script makes a set of toroidal and poloidal field coils. Including PF\n", - "coils, PF coil cases, TF coils, TF coil cases and inboard TF coil supports.\n", - "\"\"\"\n", - "\n", - "import paramak\n", - "\n", - "\n", - "number_of_toroidal_field_coils = 6\n", - "angle_offset = (360 / number_of_toroidal_field_coils) / 2.\n", - "tf_coil_thickness = 50\n", - "tf_coil_distance = 130\n", - "\n", - "tf_coil_casing_distance = tf_coil_distance + 40\n", - "tf_coil_casing_thickness = 20\n", - "\n", - "inner_tf_case = paramak.InnerTfCoilsFlat(\n", - " height=1800,\n", - " inner_radius=330,\n", - " outer_radius=430,\n", - " number_of_coils=number_of_toroidal_field_coils,\n", - " gap_size=5,\n", - " rotation_angle=180,\n", - " azimuth_start_angle=angle_offset\n", - ")\n", - "\n", - "tf_coils = paramak.ToroidalFieldCoilPrincetonD(\n", - " R1=400,\n", - " R2=1500, # height\n", - " thickness=tf_coil_thickness,\n", - " distance=tf_coil_distance,\n", - " number_of_coils=number_of_toroidal_field_coils,\n", - " rotation_angle=180,\n", - ")\n", - "\n", - "tf_coil_casing = paramak.TFCoilCasing(\n", - " magnet=tf_coils,\n", - " distance=tf_coil_casing_distance,\n", - " inner_offset=tf_coil_casing_thickness,\n", - " outer_offset=tf_coil_casing_thickness,\n", - " vertical_section_offset=tf_coil_casing_thickness,\n", - " # rotation_angle=180, # producing occational errors with this arg\n", - ")\n", - "\n", - "pf_coils = paramak.PoloidalFieldCoilSet(\n", - " heights=[100, 120, 80, 80, 120, 180],\n", - " widths=[100, 120, 80, 80, 120, 180],\n", - " center_points=[\n", - " (530, 1030),\n", - " (1370, 790),\n", - " (1740, 250),\n", - " (1750, -250),\n", - " (1360, -780),\n", - " (680, -1050)\n", - " ],\n", - " rotation_angle=180\n", - ")\n", - "\n", - "pf_coils_casing = paramak.PoloidalFieldCoilCaseSetFC(\n", - " pf_coils=pf_coils,\n", - " casing_thicknesses=[10] * 6,\n", - " rotation_angle=180\n", - ")\n", - "\n", - "my_magnets = paramak.Reactor([pf_coils, tf_coils, tf_coil_casing, inner_tf_case])\n", - "\n", - "# uncomment this line to see the magnets\n", - "# my_magnets.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pf_coils.export_stp('pf_coils.stp')\n", - "\n", - "pf_coils_casing.export_stp('pf_coils_case.stp')\n", - "\n", - "tf_coils.export_stp('tf_coil.stp')\n", - "\n", - "tf_coil_casing.export_stp('tf_coil_casing.stp')\n", - "\n", - "inner_tf_case.export_stp('inner_tf_case.stp')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_plasmas.ipynb b/examples/example_parametric_components/make_plasmas.ipynb deleted file mode 100644 index ec8732bba..000000000 --- a/examples/example_parametric_components/make_plasmas.ipynb +++ /dev/null @@ -1,134 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "This python script demonstrates the creation of plasmas\n", - "\"\"\"\n", - "\n", - "import paramak\n", - "\n", - " \n", - "ITER_simple = paramak.Plasma(\n", - " major_radius=620,\n", - " minor_radius=210,\n", - " triangularity=0.33,\n", - " elongation=1.85,\n", - " name=\"ITER_plasma\",\n", - " rotation_angle=1,\n", - " color=(0,1,0)\n", - ")\n", - "\n", - "ITER = paramak.PlasmaBoundaries(\n", - " A=-0.155,\n", - " major_radius=620,\n", - " minor_radius=210,\n", - " triangularity=0.33,\n", - " elongation=1.85,\n", - " name=\"ITER_plasma_plasmaboundaries\",\n", - " rotation_angle=1,\n", - " color=(1,0,0),\n", - " azimuth_placement_angle=(360/7)\n", - ")\n", - "\n", - "EU_DEMO = paramak.Plasma(\n", - " name=\"EU_DEMO_plasma\",\n", - " major_radius=910,\n", - " minor_radius=290,\n", - " triangularity=0.33,\n", - " elongation=1.59,\n", - " rotation_angle=1,\n", - " color=(0.9, 0.1, 0.1),\n", - " azimuth_placement_angle=(360/7)*2\n", - ")\n", - "\n", - "ST = paramak.Plasma(\n", - " name=\"ST_plasma\",\n", - " major_radius=170,\n", - " minor_radius=129,\n", - " triangularity=0.55,\n", - " elongation=2.3,\n", - " rotation_angle=1,\n", - " color=(0.2, 0.6, 0.2),\n", - " azimuth_placement_angle=(360/7)*3\n", - ")\n", - "\n", - "AST = paramak.Plasma(\n", - " name=\"AST_plasma\",\n", - " major_radius=170,\n", - " minor_radius=129,\n", - " triangularity=-0.55,\n", - " elongation=2.3,\n", - " rotation_angle=1,\n", - " color=(0, 0, 0),\n", - " azimuth_placement_angle=(360/7)*4\n", - ")\n", - "\n", - "NSTX_double_null = paramak.PlasmaBoundaries(\n", - " name=\"NSTX_double_null_plasma_plasmaboundaries\",\n", - " A=0,\n", - " major_radius=850,\n", - " minor_radius=680,\n", - " triangularity=0.35,\n", - " elongation=2,\n", - " color=(1, 1, 0),\n", - " rotation_angle=1,\n", - " configuration=\"double-null\",\n", - " azimuth_placement_angle=(360/7)*5\n", - ")\n", - "\n", - "NSTX_single_null = paramak.PlasmaBoundaries(\n", - " name=\"NSTX_single_null_plasma_plasmaboundaries\",\n", - " A=-0.05,\n", - " major_radius=850,\n", - " minor_radius=680,\n", - " triangularity=0.35,\n", - " elongation=2,\n", - " color=(0.6, 0.3, 0.6),\n", - " rotation_angle=1,\n", - " configuration=\"single-null\",\n", - " azimuth_placement_angle=(360/7)*6\n", - ")\n", - "\n", - "# combines all the plasma into a single object\n", - "all_plasmas = paramak.Reactor([ITER_simple, ITER, EU_DEMO, ST, AST, NSTX_double_null, NSTX_single_null])\n", - "\n", - "all_plasmas.show() " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "all_plasmas.export_html()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_vacuum_vessel_with_ports.ipynb b/examples/example_parametric_components/make_vacuum_vessel_with_ports.ipynb deleted file mode 100644 index 260467c75..000000000 --- a/examples/example_parametric_components/make_vacuum_vessel_with_ports.ipynb +++ /dev/null @@ -1,92 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "This python script demonstrates the creation of a vacuum vessel with shaped\n", - "different ports cut out.\n", - "\"\"\"\n", - "\n", - "import numpy as np\n", - "import paramak\n", - "\n", - "\n", - "number_of_ports_in_360_degrees = 12\n", - "angles_for_ports = np.linspace(0, 360, number_of_ports_in_360_degrees)\n", - "\n", - "# makes the upper row of ports\n", - "rotated_ports = paramak.PortCutterRotated(\n", - " center_point=(0, 0),\n", - " polar_coverage_angle=10,\n", - " rotation_angle=10,\n", - " polar_placement_angle=25,\n", - " azimuth_placement_angle=angles_for_ports\n", - ")\n", - "\n", - "# makes the middle row of ports\n", - "circular_ports = paramak.PortCutterCircular(\n", - " distance=5,\n", - " center_point=(0, 0),\n", - " radius=0.2,\n", - " azimuth_placement_angle=angles_for_ports\n", - ")\n", - "\n", - "# makes the lower row of ports\n", - "rectangular_ports = paramak.PortCutterRectangular(\n", - " distance=5,\n", - " center_point=(-1, 0),\n", - " height=0.3,\n", - " width=0.4,\n", - " fillet_radius=0.08,\n", - " azimuth_placement_angle=angles_for_ports\n", - ")\n", - "\n", - "# creates the hollow cylinder vacuum vessel and cuts away the ports\n", - "vacuum_vessel = paramak.VacuumVessel(\n", - " height=4,\n", - " inner_radius=2,\n", - " thickness=0.2,\n", - " cut=[rotated_ports, rectangular_ports, circular_ports]\n", - ")\n", - "\n", - "vacuum_vessel.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# eports images and 3D CAD\n", - "vacuum_vessel.export_svg('vacuum_vessel_with_ports.svg')\n", - "vacuum_vessel.export_stp('vacuum_vessel_with_ports.stp')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_components/make_varible_offset_firstwall.ipynb b/examples/example_parametric_components/make_varible_offset_firstwall.ipynb deleted file mode 100644 index 2af6c4c78..000000000 --- a/examples/example_parametric_components/make_varible_offset_firstwall.ipynb +++ /dev/null @@ -1,91 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "from matplotlib.pyplot import plasma\n", - "from numpy.lib.function_base import angle\n", - "import paramak\n", - "import random\n", - "import subprocess\n", - "\n", - "\n", - "subprocess.call(['rm', 'random_offset_.svg'])\n", - "\n", - "for counter in range(10):\n", - " offset_1 = random.uniform(10, 80)\n", - " offset_2 = random.uniform(10, 80)\n", - " offset_3 = random.uniform(10, 80)\n", - " offset_4 = random.uniform(10, 80)\n", - " offset_5 = random.uniform(10, 80)\n", - "\n", - " offests = [offset_1, offset_2, offset_3, offset_4, offset_5, offset_1]\n", - "\n", - " plasma = paramak.Plasma(\n", - " rotation_angle=35,\n", - " minor_radius=150.0,\n", - " major_radius=450.0,\n", - " triangularity=0.55,\n", - " elongation=2.0,\n", - " )\n", - "\n", - " firstwall = paramak.BlanketFP(\n", - " rotation_angle=35,\n", - " thickness=1,\n", - " start_angle=0,\n", - " stop_angle=360,\n", - " offset_from_plasma=offests\n", - " )\n", - "\n", - " both_shapes = paramak.Reactor([plasma, firstwall])\n", - "\n", - " filename = 'random_offset_'+str(counter).zfill(3)+'.svg'\n", - "\n", - " # saves 3d geomery as svg image, could also be saved as html, stl, or stp\n", - " both_shapes.export_svg(\n", - " filename=filename,\n", - " projectionDir=(5,-5,0),\n", - " showHidden=True,\n", - " )\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# The following command requres imagemagick installed to convert the svg files into a gif animation\n", - "# further details https://imagemagick.org/index.php\n", - "\n", - "# subprocess.check_call(\n", - "# [\"convert\", \"-delay\", \"40\", \"random_offset_*.svg\", \"random_offsets.gif\"])\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/ball_reactor.ipynb b/examples/example_parametric_reactors/ball_reactor.ipynb deleted file mode 100644 index f0099bac7..000000000 --- a/examples/example_parametric_reactors/ball_reactor.ipynb +++ /dev/null @@ -1,87 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "my_reactor = paramak.BallReactor(\n", - " inner_bore_radial_thickness=10,\n", - " inboard_tf_leg_radial_thickness=30,\n", - " center_column_shield_radial_thickness=60,\n", - " divertor_radial_thickness=150,\n", - " inner_plasma_gap_radial_thickness=30,\n", - " plasma_radial_thickness=300,\n", - " outer_plasma_gap_radial_thickness=30,\n", - " plasma_gap_vertical_thickness=50,\n", - " firstwall_radial_thickness=30,\n", - " blanket_radial_thickness=50,\n", - " blanket_rear_wall_radial_thickness=30,\n", - " elongation=2,\n", - " triangularity=0.55,\n", - " number_of_tf_coils=16,\n", - " rotation_angle=180,\n", - " pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - " pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_radial_position=[500, 575, 575, 500],\n", - " pf_coil_vertical_position=[300, 100, -100, -300],\n", - " rear_blanket_to_tf_gap=50,\n", - " outboard_tf_coil_radial_thickness=100,\n", - " outboard_tf_coil_poloidal_thickness=50\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pathlib import Path\n", - "\n", - "\n", - "my_reactor.export_stp(filename='ball_reactor.stp')\n", - "\n", - "my_reactor.export_svg(filename='ball_reactor.svg', projectionDir=(0.8,-0.8,-0.2))\n", - "\n", - "my_reactor.export_stl(filename='ball_reactor.stl')\n", - "\n", - "my_reactor.export_html('ball_reactor.html')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/ball_reactor_single_null.ipynb b/examples/example_parametric_reactors/ball_reactor_single_null.ipynb deleted file mode 100644 index f3d73aae6..000000000 --- a/examples/example_parametric_reactors/ball_reactor_single_null.ipynb +++ /dev/null @@ -1,85 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "my_reactor = paramak.SingleNullBallReactor(\n", - " inner_bore_radial_thickness=50,\n", - " inboard_tf_leg_radial_thickness=50,\n", - " center_column_shield_radial_thickness=50,\n", - " divertor_radial_thickness=90,\n", - " inner_plasma_gap_radial_thickness=50,\n", - " plasma_radial_thickness=200,\n", - " outer_plasma_gap_radial_thickness=50,\n", - " plasma_gap_vertical_thickness=50,\n", - " firstwall_radial_thickness=50,\n", - " blanket_radial_thickness=100,\n", - " blanket_rear_wall_radial_thickness=50,\n", - " elongation=2,\n", - " triangularity=0.55,\n", - " number_of_tf_coils=16,\n", - " rotation_angle=180,\n", - " pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - " pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_radial_position=[500, 575, 575, 500],\n", - " pf_coil_vertical_position=[300, 100, -100, -300],\n", - " rear_blanket_to_tf_gap=50,\n", - " outboard_tf_coil_radial_thickness=100,\n", - " outboard_tf_coil_poloidal_thickness=50,\n", - " divertor_position=\"lower\"\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_stp('single_null_ball_reactor.stp')\n", - "\n", - "my_reactor.export_svg('reactor.svg')\n", - "\n", - "my_reactor.export_stl('single_null_ball_reactor.stl')\n", - "\n", - "my_reactor.export_html('reactor.html')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/center_column_study_reactor.ipynb b/examples/example_parametric_reactors/center_column_study_reactor.ipynb deleted file mode 100644 index a6c737b6f..000000000 --- a/examples/example_parametric_reactors/center_column_study_reactor.ipynb +++ /dev/null @@ -1,74 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "This example creates a center column study reactor using a parametric reactor.\n", - "Adds some TF coils to the reactor. By default the script saves stp, stl,\n", - "html and svg files.\n", - "\"\"\"\n", - "\n", - "import paramak\n", - "\n", - "\n", - "my_reactor = paramak.CenterColumnStudyReactor(\n", - " inner_bore_radial_thickness=20,\n", - " inboard_tf_leg_radial_thickness=50,\n", - " center_column_shield_radial_thickness_mid=50,\n", - " center_column_shield_radial_thickness_upper=100,\n", - " inboard_firstwall_radial_thickness=20,\n", - " divertor_radial_thickness=100,\n", - " inner_plasma_gap_radial_thickness=80,\n", - " plasma_radial_thickness=200,\n", - " outer_plasma_gap_radial_thickness=90,\n", - " elongation=2.3,\n", - " triangularity=0.45,\n", - " plasma_gap_vertical_thickness=40,\n", - " center_column_arc_vertical_thickness=520,\n", - " rotation_angle=180)\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_stp(filename='CenterColumnStudyReactor.png')\n", - "\n", - "my_reactor.export_svg('CenterColumnStudyReactor/reactor.svg')\n", - "\n", - "my_reactor.export_stl(filename='CenterColumnStudyReactor.stl')\n", - "\n", - "my_reactor.export_html('CenterColumnStudyReactor/reactor.html')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/eu_demo_from_2015_paper.ipynb b/examples/example_parametric_reactors/eu_demo_from_2015_paper.ipynb deleted file mode 100644 index 3744cd53d..000000000 --- a/examples/example_parametric_reactors/eu_demo_from_2015_paper.ipynb +++ /dev/null @@ -1,264 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting auto display for cadquery Workplane and Shape\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f1e7f7b27f8546d9aa195a6555c665f9", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(VBox(children=(HBox(children=(Checkbox(value=False, description='Axes', indent=False, _dom_clas…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import paramak\n", - "\n", - "my_reactor = paramak.EuDemoFrom2015PaperDiagram(\n", - " rotation_angle=90\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/iter_from_2020_paper.ipynb b/examples/example_parametric_reactors/iter_from_2020_paper.ipynb deleted file mode 100644 index 87051210f..000000000 --- a/examples/example_parametric_reactors/iter_from_2020_paper.ipynb +++ /dev/null @@ -1,272 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting auto display for cadquery Workplane and Shape\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "29e9fa0d979b4dc7a3c3f812490bc0f7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(VBox(children=(HBox(children=(Checkbox(value=False, description='Axes', indent=False, _dom_clas…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import paramak\n", - "\n", - "my_reactor = paramak.IterFrom2020PaperDiagram(\n", - " rotation_angle=90\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/make_animiation.ipynb b/examples/example_parametric_reactors/make_animiation.ipynb deleted file mode 100644 index 5231b8a46..000000000 --- a/examples/example_parametric_reactors/make_animiation.ipynb +++ /dev/null @@ -1,219 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Creates a series of images of a ball reactor images and combines\n", - "them into gif animations using the command line tool convert, you will need to\n", - "have imagemagick installed to convert the svg images to a gif animation" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Makes a single reactor and exports and svg image with different view angles. Combines the svg images into a gif animation." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import subprocess\n", - "\n", - "import numpy as np\n", - "import paramak\n", - "from scipy.interpolate import interp1d\n", - "\n", - "number_of_images = 5" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# allows the projection angle for the svg to be found via interpolation\n", - "\n", - "angle_finder = interp1d([0, number_of_images], [2.4021, 6.])\n", - "\n", - "my_reactor = paramak.SubmersionTokamak(\n", - " inner_bore_radial_thickness=30,\n", - " inboard_tf_leg_radial_thickness=30,\n", - " center_column_shield_radial_thickness=30,\n", - " divertor_radial_thickness=80,\n", - " inner_plasma_gap_radial_thickness=50,\n", - " plasma_radial_thickness=200,\n", - " outer_plasma_gap_radial_thickness=50,\n", - " firstwall_radial_thickness=30,\n", - " blanket_rear_wall_radial_thickness=30,\n", - " number_of_tf_coils=16,\n", - " rotation_angle=180,\n", - " support_radial_thickness=90,\n", - " inboard_blanket_radial_thickness=30,\n", - " outboard_blanket_radial_thickness=30,\n", - " elongation=2.00,\n", - " triangularity=0.50,\n", - " pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - " pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_radial_position=[500, 550, 550, 500],\n", - " pf_coil_vertical_position=[270, 100, -100, -270],\n", - " rear_blanket_to_tf_gap=50,\n", - " outboard_tf_coil_radial_thickness=30,\n", - " outboard_tf_coil_poloidal_thickness=30,\n", - ")\n", - "\n", - "for i in range(number_of_images):\n", - "\n", - " # uses the rotation angle (in radians) to find new x, y points\n", - " x_vec, y_vec = paramak.utils.rotate([0, 0], [1, 0], angle_finder(i))\n", - " projectionDir = (x_vec, y_vec, 0)\n", - "\n", - " my_reactor.export_svg(\n", - " filename=\"rotation_\" + str(i).zfill(4) + \".svg\",\n", - " projectionDir=projectionDir,\n", - " showHidden=False,\n", - " height=200,\n", - " width=300,\n", - " marginTop=27,\n", - " marginLeft=35,\n", - " strokeWidth=3.5\n", - " )\n", - "\n", - " print(\"made\", str(i + 1), \"models out of\", str(number_of_images))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Converts the svg files into a gif using imagemagick. You will need imagemagick installed https://imagemagick.org/index.php\n", - "# subprocess.check_call(\n", - "# [\"convert\", \"-delay\", \"15\", \"rotation_*.svg\", \"rotated.gif\"])\n", - "\n", - "# print(\"animation file made as saved as rotated.gif\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Makes a series of random sized reactors and exports an svg image for each one. Combines the svg images into a gif animation." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pf_coil_vertical_thicknesses, pf_coil_radial_thicknesses, pf_coil_radial_position, pf_coil_vertical_position not so not making pf coils\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jshim/paramak/paramak/parametric_components/blanket_fp.py:226: UserWarning: BlanketFP: Some points with negative R coordinate have been ignored.\n", - " warnings.warn(msg)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Saved file as random_0000.svg\n", - "made 1 models out of 5\n", - "pf_coil_vertical_thicknesses, pf_coil_radial_thicknesses, pf_coil_radial_position, pf_coil_vertical_position not so not making pf coils\n", - "Saved file as random_0001.svg\n", - "made 2 models out of 5\n", - "pf_coil_vertical_thicknesses, pf_coil_radial_thicknesses, pf_coil_radial_position, pf_coil_vertical_position not so not making pf coils\n", - "Saved file as random_0002.svg\n", - "made 3 models out of 5\n", - "pf_coil_vertical_thicknesses, pf_coil_radial_thicknesses, pf_coil_radial_position, pf_coil_vertical_position not so not making pf coils\n", - "Saved file as random_0003.svg\n", - "made 4 models out of 5\n", - "pf_coil_vertical_thicknesses, pf_coil_radial_thicknesses, pf_coil_radial_position, pf_coil_vertical_position not so not making pf coils\n", - "Saved file as random_0004.svg\n", - "made 5 models out of 5\n", - "animation file made as saved as randoms.gif\n" - ] - } - ], - "source": [ - "# makes a series of reactor models\n", - "for i in range(number_of_images):\n", - "\n", - " my_reactor = paramak.BallReactor(\n", - " inner_bore_radial_thickness=50,\n", - " inboard_tf_leg_radial_thickness=np.random.uniform(20, 50),\n", - " center_column_shield_radial_thickness=np.random.uniform(20, 60),\n", - " divertor_radial_thickness=50,\n", - " inner_plasma_gap_radial_thickness=50,\n", - " plasma_radial_thickness=np.random.uniform(20, 200),\n", - " outer_plasma_gap_radial_thickness=50,\n", - " plasma_gap_vertical_thickness=50,\n", - " firstwall_radial_thickness=5,\n", - " blanket_radial_thickness=np.random.uniform(10, 200),\n", - " blanket_rear_wall_radial_thickness=10,\n", - " elongation=np.random.uniform(1.3, 1.7),\n", - " triangularity=np.random.uniform(0.3, 0.55),\n", - " rotation_angle=180,\n", - " outboard_tf_coil_radial_thickness=100,\n", - " outboard_tf_coil_poloidal_thickness=50,\n", - " )\n", - "\n", - " my_reactor.export_svg(\n", - " filename=\"random_\" + str(i).zfill(4) + \".svg\",\n", - " showHidden=False\n", - " )\n", - "\n", - " print(\"made\", str(i + 1), \"models out of\", str(number_of_images))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Converts the svg files into a gif using imagemagick. You will need imagemagick installed https://imagemagick.org/index.php\n", - "# subprocess.check_call(\n", - "# [\"convert\", \"-delay\", \"40\", \"random_*.svg\", \"randoms.gif\"])\n", - "\n", - "# print(\"animation file made as saved as randoms.gif\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/render_of_random_reactor_collarge.py b/examples/example_parametric_reactors/render_of_random_reactor_collarge.py deleted file mode 100644 index 41500e370..000000000 --- a/examples/example_parametric_reactors/render_of_random_reactor_collarge.py +++ /dev/null @@ -1,103 +0,0 @@ -# This examples creates a 3 by 3 grid of random reactor renders and saves -# them as a png image - -import math - -# to run this example you will need all of the following packages installed -import matplotlib.pyplot as plt -import numpy as np -import paramak -import pyrender -import trimesh - - -def create_reactor_renders( - render_number, - inner_blanket_radius, - blanket_thickness, - blanket_height, - lower_blanket_thickness, - upper_blanket_thickness, - blanket_vv_gap, - number_of_images_in_x, - number_of_images_in_y, -): - - # creates a reactor from the input arguments - my_reactor = paramak.FlfSystemCodeReactor( - rotation_angle=180, - inner_blanket_radius=inner_blanket_radius, - blanket_thickness=blanket_thickness, - blanket_height=blanket_height, - lower_blanket_thickness=lower_blanket_thickness, - upper_blanket_thickness=upper_blanket_thickness, - blanket_vv_gap=blanket_vv_gap, - upper_vv_thickness=10, - vv_thickness=10, - lower_vv_thickness=10, - ) - - # saves the reactor geometry as separate stl files - my_reactor.export_stl() - - # assigns colours to each stl file - stl_files_with_colors = { - "blanket.stl": (255, 255, 0), - "vacuum_vessel.stl": (128, 128, 128), - "upper_blanket.stl": (255, 255, 0), - "lower_blanket.stl": (255, 255, 0), - "lower_vacuum_vessel.stl": (128, 128, 128), - "upper_vacuum_vessel.stl": (128, 128, 128), - } - - scene = pyrender.Scene() - - # for each stl file and color combination - for key, value in stl_files_with_colors.items(): - trimesh_obj = trimesh.load(key) - trimesh_obj.visual.vertex_colors = value - trimesh_obj.visual - - render_mesh = pyrender.Mesh.from_trimesh(trimesh_obj, smooth=False) - scene.add(render_mesh) - - camera = pyrender.camera.PerspectiveCamera(yfov=math.radians(90.0)) # aspectRatio=2.0 could be added here - - # sets the position of the camera using a matrix - cam = 2**-0.5 - camera_pose = np.array([[1, 0, 0, 0], [0, cam, -cam, -350], [0, cam, cam, 350], [0, 0, 0, 1]]) - - # adds a camera and a point light source at the same location - scene.add(camera, pose=camera_pose) - light = pyrender.PointLight(color=np.ones(3), intensity=300000.0) - scene.add(light, pose=camera_pose) - - # renders the scene - my_render = pyrender.OffscreenRenderer(1000, 1000) - color, depth = my_render.render(scene) - - # adds the render to the plot as a subplot in the correct location - plt.subplot(number_of_images_in_y, number_of_images_in_x, render_number + 1) - plt.axis("off") - plt.imshow(color) - - -# creates a blank figure for populating with subplots -plt.figure() - -# loops through adding a random reactor render to the figure with each iteration -for i in range(4 * 3): - create_reactor_renders( - render_number=i, - number_of_images_in_x=4, - number_of_images_in_y=3, - inner_blanket_radius=np.random.uniform(low=50, high=90), - blanket_thickness=np.random.uniform(low=50, high=140), - blanket_height=np.random.uniform(low=400, high=550), - lower_blanket_thickness=np.random.uniform(low=20, high=70), - upper_blanket_thickness=np.random.uniform(low=20, high=70), - blanket_vv_gap=np.random.uniform(low=10, high=90), - ) - -# saves the plot -plt.savefig("render.png", dpi=200) diff --git a/examples/example_parametric_reactors/render_of_random_reactor_render_gif.py b/examples/example_parametric_reactors/render_of_random_reactor_render_gif.py deleted file mode 100644 index 3ebbe82bc..000000000 --- a/examples/example_parametric_reactors/render_of_random_reactor_render_gif.py +++ /dev/null @@ -1,106 +0,0 @@ -# This examples creates Gif animation of 50 reactors by creating individual -# images of reactors and stiching them together using Imagemagick into a Gif -# animation. Two animations are made, of of a 3D render and one of a wireframe -# line drawing. - -import math -import os - -# to run this example you will need all of the following packages installed -import matplotlib.pyplot as plt -import numpy as np -import paramak -import pyrender -import trimesh - - -def create_reactor_renders( - render_number, - inner_blanket_radius, - blanket_thickness, - blanket_height, - lower_blanket_thickness, - upper_blanket_thickness, - blanket_vv_gap, -): - - # creates a blank figure for populating with subplots - plt.figure() - - # creates a reactor from the input arguments - my_reactor = paramak.FlfSystemCodeReactor( - rotation_angle=180, - inner_blanket_radius=inner_blanket_radius, - blanket_thickness=blanket_thickness, - blanket_height=blanket_height, - lower_blanket_thickness=lower_blanket_thickness, - upper_blanket_thickness=upper_blanket_thickness, - blanket_vv_gap=blanket_vv_gap, - upper_vv_thickness=10, - vv_thickness=10, - lower_vv_thickness=10, - ) - - # saves the reactor geometry as separate stl files that are later read in - # for the rendering - my_reactor.export_stl() - - # assigns colours to each stl file - stl_files_with_colors = { - "blanket.stl": (255, 255, 0), - "vessel.stl": (128, 128, 128), - "upper_blanket.stl": (255, 255, 0), - "lower_blanket.stl": (255, 255, 0), - "lower_vessel.stl": (128, 128, 128), - "upper_vessel.stl": (128, 128, 128), - } - - scene = pyrender.Scene() - - # for each stl file and color combination - for key, value in stl_files_with_colors.items(): - trimesh_obj = trimesh.load(key) - trimesh_obj.visual.vertex_colors = value - trimesh_obj.visual - - render_mesh = pyrender.Mesh.from_trimesh(trimesh_obj, smooth=False) - scene.add(render_mesh) - - camera = pyrender.camera.PerspectiveCamera(yfov=math.radians(90.0)) # aspectRatio=2.0 could be added here - - # sets the position of the camera using a matrix - cam = 2**-0.5 - camera_pose = np.array([[1, 0, 0, 0], [0, cam, -cam, -350], [0, cam, cam, 350], [0, 0, 0, 1]]) - - # adds a camera and a point light source at the same location - scene.add(camera, pose=camera_pose) - light = pyrender.PointLight(color=np.ones(3), intensity=300000.0) - scene.add(light, pose=camera_pose) - - # renders the scene - my_render = pyrender.OffscreenRenderer(1000, 1000) - color, _ = my_render.render(scene) - - # adds the render to the plot as a subplot in the correct location - plt.plot() - plt.axis("off") - plt.imshow(color) - # plt.show() - plt.savefig(f"render_{str(render_number).zfill(3)}.png", dpi=200) - - -# loops through adding a random reactor render to the figure with each iteration -for i in range(50): - create_reactor_renders( - render_number=i, - inner_blanket_radius=np.random.uniform(low=50, high=90), - blanket_thickness=np.random.uniform(low=50, high=140), - blanket_height=np.random.uniform(low=400, high=550), - lower_blanket_thickness=np.random.uniform(low=20, high=70), - upper_blanket_thickness=np.random.uniform(low=20, high=70), - blanket_vv_gap=np.random.uniform(low=10, high=90), - ) - -# The convert comand requires imagemagick -# saves the rendered png files as a gif -os.system("convert -delay 40 -loop 0 render_*.png reactors.gif") diff --git a/examples/example_parametric_reactors/render_of_random_reactor_render_with_text_gif.py b/examples/example_parametric_reactors/render_of_random_reactor_render_with_text_gif.py deleted file mode 100644 index e20371341..000000000 --- a/examples/example_parametric_reactors/render_of_random_reactor_render_with_text_gif.py +++ /dev/null @@ -1,134 +0,0 @@ -# This examples creates Gif animation of 50 reactors by creating individual -# images of reactors and stiching them together using Imagemagick into a Gif -# animation. Two animations are made, of of a 3D render and one of a wireframe -# line drawing. - -import math -import os - -# to run this example you will need all of the following packages installed -import matplotlib.pyplot as plt -import numpy as np -import paramak -import pyrender -import trimesh -from PIL import Image, ImageFont, ImageDraw - - -def create_reactor_renders( - render_number, - inner_blanket_radius, - blanket_thickness, - blanket_height, - lower_blanket_thickness, - upper_blanket_thickness, - blanket_vv_gap, - upper_vv_thickness, - vv_thickness, - lower_vv_thickness, -): - - # creates a blank figure for populating with subplots - plt.figure() - - # creates a reactor from the input arguments - my_reactor = paramak.FlfSystemCodeReactor( - rotation_angle=180, - inner_blanket_radius=inner_blanket_radius, - blanket_thickness=blanket_thickness, - blanket_height=blanket_height, - lower_blanket_thickness=lower_blanket_thickness, - upper_blanket_thickness=upper_blanket_thickness, - blanket_vv_gap=blanket_vv_gap, - upper_vv_thickness=upper_vv_thickness, - vv_thickness=vv_thickness, - lower_vv_thickness=lower_vv_thickness, - ) - - # saves the reactor geometry as separate stl files that are later read in - # for the rendering - my_reactor.export_stl() - - # assigns colours to each stl file - stl_files_with_colors = { - "blanket.stl": (255, 255, 0), - "vessel.stl": (128, 128, 128), - "upper_blanket.stl": (255, 255, 0), - "lower_blanket.stl": (255, 255, 0), - "lower_vessel.stl": (128, 128, 128), - "upper_vessel.stl": (128, 128, 128), - } - - scene = pyrender.Scene() - - # for each stl file and color combination - for key, value in stl_files_with_colors.items(): - trimesh_obj = trimesh.load(key) - trimesh_obj.visual.vertex_colors = value - trimesh_obj.visual - - render_mesh = pyrender.Mesh.from_trimesh(trimesh_obj, smooth=False) - scene.add(render_mesh) - - camera = pyrender.camera.PerspectiveCamera(yfov=math.radians(90.0)) # aspectRatio=2.0 could be added here - - # sets the position of the camera using a matrix - cam = 2**-0.5 - camera_pose = np.array([[1, 0, 0, 0], [0, cam, -cam, -600], [0, cam, cam, 600], [0, 0, 0, 1]]) - - # adds a camera and a point light source at the same location - scene.add(camera, pose=camera_pose) - light = pyrender.PointLight(color=np.ones(3), intensity=300000.0) - scene.add(light, pose=camera_pose) - - # renders the scene - my_render = pyrender.OffscreenRenderer(1000, 1000) - color, _ = my_render.render(scene) - - # adds the render to the plot as a subplot in the correct location - plt.plot() - plt.axis("off") - plt.imshow(color) - # plt.show() - plt.savefig("tempfile.png", dpi=400) - - my_image = Image.open("tempfile.png") - title_text = f""" - inner_blanket_radius={round(inner_blanket_radius,1)} - blanket_thickness={round(blanket_thickness,1)} - blanket_height={round(blanket_height,1)} - lower_blanket_thickness={round(lower_blanket_thickness,1)} - upper_blanket_thickness={round(upper_blanket_thickness,1)} - blanket_vv_gap={round(blanket_vv_gap,1)} - upper_vv_thickness={round(upper_vv_thickness,1)} - vv_thickness={round(vv_thickness,1)} - lower_vv_thickness={round(lower_vv_thickness,1)} - """ - image_editable = ImageDraw.Draw(my_image) - - # ttf file from https://fonts.google.com/ - title_font = ImageFont.truetype("EncodeSansSemiExpanded-Medium.ttf", 50) - xy_location = (1000, 1000) - rgb = (0, 0, 0) - image_editable.text(xy_location, title_text, rgb, font=title_font) - my_image.save(f"render_{str(render_number).zfill(3)}.png") - - -# loops through adding a random reactor render to the figure with each iteration -for i in range(50): - create_reactor_renders( - render_number=i, - inner_blanket_radius=np.random.uniform(low=50, high=90), - blanket_thickness=np.random.uniform(low=50, high=140), - blanket_height=np.random.uniform(low=400, high=550), - lower_blanket_thickness=np.random.uniform(low=20, high=70), - upper_blanket_thickness=np.random.uniform(low=20, high=70), - blanket_vv_gap=np.random.uniform(low=10, high=90), - upper_vv_thickness=np.random.uniform(low=5, high=15), - vv_thickness=np.random.uniform(low=5, high=15), - lower_vv_thickness=np.random.uniform(low=5, high=15), - ) - -# The convert comand requires imagemagick -# saves the rendered png files as a gif -os.system("convert -delay 40 -loop 0 render_*.png reactors.gif") diff --git a/examples/example_parametric_reactors/render_of_random_reactor_types_collarge.py b/examples/example_parametric_reactors/render_of_random_reactor_types_collarge.py deleted file mode 100644 index cba75395a..000000000 --- a/examples/example_parametric_reactors/render_of_random_reactor_types_collarge.py +++ /dev/null @@ -1,110 +0,0 @@ -# This examples creates a 3 by 3 grid of random reactor renders and saves -# them as a png image - -import math -import random - -# to run this example you will need all of the following packages installed -import matplotlib.pyplot as plt -import numpy as np -import paramak -import pyrender -import trimesh - - -def generate_random_reactor(): - all_reactors = [ - paramak.BallReactor(), - paramak.CenterColumnStudyReactor(), - paramak.EuDemoFrom2015PaperDiagram(), - paramak.FlfSystemCodeReactor(), - paramak.IterFrom2020PaperDiagram(), - paramak.SegmentedBlanketBallReactor(), - paramak.SingleNullBallReactor(), - paramak.SingleNullSubmersionTokamak(), - paramak.SparcFrom2020PaperDiagram(), - paramak.SubmersionTokamak(), - ] - - my_reactor = random.choice(all_reactors) - - print(my_reactor) - - input_variables = my_reactor.input_variable_names - my_reactor.rotation_angle = 180 - - for input_var in [ - "largest_shapes", - "elongation", - "triangularity", - "rotation_angle", - ]: - try: - input_variables.remove(input_var) - except ValueError: - pass - - print(my_reactor.__dict__, "\n\n") - - for input_arg in my_reactor.input_variables: - if input_arg in my_reactor.__dict__: - if isinstance(my_reactor.__dict__[input_arg], float): - rand_scale = random.uniform(0.8, 1.2) - setattr(my_reactor, input_arg, my_reactor.__dict__[input_arg] * rand_scale) - - return my_reactor - - -def create_reactor_renders(render_number, number_of_images_in_x, number_of_images_in_y, reactor): - - # saves the reactor geometry as separate stl files - reactor.export_stl() - - # assigns colours to each stl file - - scene = pyrender.Scene() - - # for each stl file and color combination - for entry in reactor.shapes_and_components: - trimesh_obj = trimesh.load(entry.name + ".stl") - trimesh_obj.visual.vertex_colors = entry.color - - render_mesh = pyrender.Mesh.from_trimesh(trimesh_obj, smooth=False) - scene.add(render_mesh) - - camera = pyrender.camera.PerspectiveCamera(yfov=math.radians(90.0)) # aspectRatio=2.0 could be added here - - # sets the position of the camera using a matrix - cam = 2**-0.5 - camera_pose = np.array([[1, 0, 0, 0], [0, cam, -cam, -650], [0, cam, cam, 650], [0, 0, 0, 1]]) - - # adds a camera and a point light source at the same location - scene.add(camera, pose=camera_pose) - light = pyrender.PointLight(color=np.ones(3), intensity=300000.0) - scene.add(light, pose=camera_pose) - - # renders the scene - my_render = pyrender.OffscreenRenderer(1000, 1000) - color, depth = my_render.render(scene) - - # adds the render to the plot as a subplot in the correct location - plt.subplot(number_of_images_in_y, number_of_images_in_x, render_number + 1) - plt.axis("off") - plt.imshow(color) - return reactor.reactor_hash_value - - -# creates a blank figure for populating with subplots -plt.figure() - -# loops through adding a random reactor render to the figure with each iteration -for i in range(4 * 3): - reactor_hash_value = create_reactor_renders( - render_number=i, - number_of_images_in_x=4, - number_of_images_in_y=3, - reactor=generate_random_reactor(), - ) - -# saves the plot -plt.savefig("render_random_reactors.png", dpi=200) diff --git a/examples/example_parametric_reactors/render_of_random_reactor_wireframe_with_text_gif.py b/examples/example_parametric_reactors/render_of_random_reactor_wireframe_with_text_gif.py deleted file mode 100644 index 92c70f2bb..000000000 --- a/examples/example_parametric_reactors/render_of_random_reactor_wireframe_with_text_gif.py +++ /dev/null @@ -1,99 +0,0 @@ -# This examples creates Gif animation of 50 reactors by creating individual -# images of reactors and stiching them together using Imagemagick into a Gif -# animation. Two animations are made, of of a 3D render and one of a wireframe -# line drawing. - -import os - -# to run this example you will need all of the following packages installed -import numpy as np -import paramak - -import svgwrite # required to write text to svg file -import svgutils.transform as sg # required to merge text svg files with wireframe svg file - - -def create_reactor_renders( - render_number, - inner_blanket_radius, - blanket_thickness, - blanket_height, - lower_blanket_thickness, - upper_blanket_thickness, - blanket_vv_gap, - upper_vv_thickness=10, - vv_thickness=10, - lower_vv_thickness=10, -): - - # creates a reactor from the input arguments - my_reactor = paramak.FlfSystemCodeReactor( - rotation_angle=180, - inner_blanket_radius=inner_blanket_radius, - blanket_thickness=blanket_thickness, - blanket_height=blanket_height, - lower_blanket_thickness=lower_blanket_thickness, - upper_blanket_thickness=upper_blanket_thickness, - blanket_vv_gap=blanket_vv_gap, - upper_vv_thickness=upper_vv_thickness, - vv_thickness=vv_thickness, - lower_vv_thickness=lower_vv_thickness, - ) - - # exports line drawing of individual reactor - my_reactor.export_svg( - f"wireframe_{str(render_number).zfill(3)}.svg", - projectionDir=[1, -1, -0.1], - strokeWidth=2, - width=1000, - height=800, - ) - - svg_file_object = svgwrite.Drawing( - filename=f"text_{str(render_number).zfill(3)}.svg", - size=("1000px", "800px"), - ) - - lines_of_text_to_write = [ - "Parametric reactor inputs", - f"Inner blanket radius {inner_blanket_radius/100:.1f}m", - f"Blanket thickness {blanket_thickness/100:.1f}m", - f"Blanket thickness {blanket_thickness/100:.1f}m", - f"Blanket height {blanket_height/100:.1f}m", - f"Lower blanket thickness {lower_blanket_thickness/100:.1f}m", - f"Upper blanket thickness {upper_blanket_thickness/100:.1f}m", - f"Blanket vv gap {blanket_vv_gap/100:.1f}m", - f"Upper vv thickness {upper_vv_thickness/100:.1f}m", - f"Vv thickness {vv_thickness/100:.1f}m", - f"Lower vv thickness {lower_vv_thickness/100:.1f}m", - ] - y_value = 50 - for line in lines_of_text_to_write: - y_value = y_value + 40 - svg_file_object.add(svg_file_object.text(line, insert=(555, y_value), font_size=27)) - svg_file_object.save() - - background = sg.fromfile(f"wireframe_{str(render_number).zfill(3)}.svg") - forground = sg.fromfile(f"text_{str(render_number).zfill(3)}.svg") - - root = forground.getroot() - background.append([root]) - - background.save(f"combined_{str(render_number).zfill(3)}.svg") - - -# loops through adding a random reactor render to the figure with each iteration -for i in range(50): - create_reactor_renders( - render_number=i, - inner_blanket_radius=np.random.uniform(low=50, high=90), - blanket_thickness=np.random.uniform(low=50, high=140), - blanket_height=np.random.uniform(low=400, high=550), - lower_blanket_thickness=np.random.uniform(low=20, high=70), - upper_blanket_thickness=np.random.uniform(low=20, high=70), - blanket_vv_gap=np.random.uniform(low=10, high=90), - ) - -# The convert comand requires imagemagick -# saves the line drawing svg files as a gif -os.system("convert -delay 40 -loop 0 combined_*.svg reactors_with_parameters.gif") diff --git a/examples/example_parametric_reactors/segmented_blanket_ball_reactor.ipynb b/examples/example_parametric_reactors/segmented_blanket_ball_reactor.ipynb deleted file mode 100644 index 5b7c04b54..000000000 --- a/examples/example_parametric_reactors/segmented_blanket_ball_reactor.ipynb +++ /dev/null @@ -1,98 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This example creates a ball reactor with segmented blankets using the\n", - "SegmentedBlanketBallReactor parametric reactor. By default the script saves\n", - "stp, stl, html and svg files." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "\n", - "my_reactor = paramak.SegmentedBlanketBallReactor(\n", - " inner_bore_radial_thickness=5,\n", - " inboard_tf_leg_radial_thickness=25,\n", - " center_column_shield_radial_thickness=45,\n", - " divertor_radial_thickness=150,\n", - " inner_plasma_gap_radial_thickness=50,\n", - " plasma_gap_vertical_thickness=50,\n", - " plasma_radial_thickness=300,\n", - " outer_plasma_gap_radial_thickness=50,\n", - " firstwall_radial_thickness=15,\n", - " blanket_radial_thickness=50,\n", - " blanket_rear_wall_radial_thickness=30,\n", - " elongation=2,\n", - " triangularity=0.55,\n", - " number_of_tf_coils=16,\n", - "# Optional magnets are commented out to speed up model creation\n", - "# pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - "# pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - "# pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - "# pf_coil_radial_position=[500, 550, 550, 500],\n", - "# pf_coil_vertical_position=[270, 100, -100, -270],\n", - "# rear_blanket_to_tf_gap=50,\n", - " rotation_angle=180,\n", - " outboard_tf_coil_radial_thickness=100,\n", - " outboard_tf_coil_poloidal_thickness=50,\n", - " gap_between_blankets=30,\n", - " number_of_blanket_segments=15,\n", - " blanket_fillet_radius=15,\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_stp(filename='segmented_blanket_ball_reactor.stp')\n", - "\n", - "my_reactor.export_svg('reactor.svg')\n", - "\n", - "my_reactor.export_stl(filename='SegmentedBlanketBallReactor.stl')\n", - "\n", - "# my_reactor.export_html('reactor.html')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/sparc_from_2020_paper.ipynb b/examples/example_parametric_reactors/sparc_from_2020_paper.ipynb deleted file mode 100644 index 9d9331dfc..000000000 --- a/examples/example_parametric_reactors/sparc_from_2020_paper.ipynb +++ /dev/null @@ -1,504 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting auto display for cadquery Workplane and Shape\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n", - "/home/jshim/miniconda3/envs/openmc-dagmc/lib/python3.8/site-packages/scipy/integrate/odepack.py:247: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.\n", - " warnings.warn(warning_msg, ODEintWarning)\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "61484b26e0684310bc2410cf6d64227b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(VBox(children=(HBox(children=(Checkbox(value=False, description='Axes', indent=False, _dom_clas…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import paramak\n", - "\n", - "my_reactor = paramak.SparcFrom2020PaperDiagram(\n", - " rotation_angle=90\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/submersion_reactor.ipynb b/examples/example_parametric_reactors/submersion_reactor.ipynb deleted file mode 100644 index 5c492e6ef..000000000 --- a/examples/example_parametric_reactors/submersion_reactor.ipynb +++ /dev/null @@ -1,88 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This example creates a submersion reactor using the SubmersionTokamak\n", - "parametric reactor. By default the script saves stp, stl, html and svg files." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "\n", - "my_reactor = paramak.SubmersionTokamak(\n", - " inner_bore_radial_thickness=30,\n", - " inboard_tf_leg_radial_thickness=30,\n", - " center_column_shield_radial_thickness=30,\n", - " divertor_radial_thickness=80,\n", - " inner_plasma_gap_radial_thickness=50,\n", - " plasma_radial_thickness=200,\n", - " outer_plasma_gap_radial_thickness=50,\n", - " firstwall_radial_thickness=30,\n", - " blanket_rear_wall_radial_thickness=30,\n", - " number_of_tf_coils=16,\n", - " rotation_angle=180,\n", - " support_radial_thickness=90,\n", - " inboard_blanket_radial_thickness=30,\n", - " outboard_blanket_radial_thickness=30,\n", - " elongation=2.00,\n", - " triangularity=0.50,\n", - " pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - " pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_radial_position=[500, 550, 550, 500],\n", - " pf_coil_vertical_position=[270, 100, -100, -270],\n", - " rear_blanket_to_tf_gap=50,\n", - " outboard_tf_coil_radial_thickness=30,\n", - " outboard_tf_coil_poloidal_thickness=30,\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "my_reactor.export_stp(filename='SubmersionTokamak.stp')\n", - "\n", - "my_reactor.export_svg('SubmersionTokamak/reactor.svg')\n", - "\n", - "my_reactor.export_stl(filename='SubmersionTokamak.stl')\n", - "\n", - "my_reactor.export_html('SubmersionTokamak/reactor.html')\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_reactors/submersion_reactor_single_null.ipynb b/examples/example_parametric_reactors/submersion_reactor_single_null.ipynb deleted file mode 100644 index fe29edf41..000000000 --- a/examples/example_parametric_reactors/submersion_reactor_single_null.ipynb +++ /dev/null @@ -1,86 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "This example creates a single null submersion reactor using the\n", - "SubmersionTokamak parametric reactor. By default the script saves stp, stl,\n", - "html and svg files.\n", - "\"\"\"\n", - "\n", - "import paramak\n", - "\n", - "my_reactor = paramak.SingleNullSubmersionTokamak(\n", - " inner_bore_radial_thickness=30,\n", - " inboard_tf_leg_radial_thickness=30,\n", - " center_column_shield_radial_thickness=30,\n", - " divertor_radial_thickness=80,\n", - " inner_plasma_gap_radial_thickness=50,\n", - " plasma_radial_thickness=200,\n", - " outer_plasma_gap_radial_thickness=50,\n", - " firstwall_radial_thickness=30,\n", - " blanket_rear_wall_radial_thickness=30,\n", - " number_of_tf_coils=16,\n", - " rotation_angle=180,\n", - " support_radial_thickness=90,\n", - " inboard_blanket_radial_thickness=30,\n", - " outboard_blanket_radial_thickness=30,\n", - " elongation=2.00,\n", - " triangularity=0.50,\n", - " pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - " pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_radial_position=[500, 550, 550, 500],\n", - " pf_coil_vertical_position=[270, 100, -100, -270],\n", - " rear_blanket_to_tf_gap=50,\n", - " outboard_tf_coil_radial_thickness=30,\n", - " outboard_tf_coil_poloidal_thickness=30,\n", - " divertor_position=\"lower\",\n", - " support_position=\"lower\"\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_stp(filename='sub_reactor.stp')\n", - "\n", - "my_reactor.export_svg('reactor.svg')\n", - "\n", - "my_reactor.export_stl(filename='sub_reactor.stl')\n", - "\n", - "my_reactor.export_html('reactor.html')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_shapes/make_CAD_from_points.ipynb b/examples/example_parametric_shapes/make_CAD_from_points.ipynb deleted file mode 100644 index 81a46c8cb..000000000 --- a/examples/example_parametric_shapes/make_CAD_from_points.ipynb +++ /dev/null @@ -1,229 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This python script demonstrates the creation of 3D volumes from points using extrude and rotate methods" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "rotated_straights = paramak.RotateStraightShape(\n", - " points=[\n", - " (400, 100),\n", - " (400, 200),\n", - " (600, 200),\n", - " (600, 100)\n", - " ],\n", - " rotation_angle = 180\n", - ")\n", - "\n", - "rotated_straights.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "rotated_spline = paramak.RotateSplineShape(\n", - " points=[\n", - " (500, 0),\n", - " (500, -20),\n", - " (400, -300),\n", - " (300, -300),\n", - " (400, 0),\n", - " (300, 300),\n", - " (400, 300),\n", - " (500, 20),\n", - " ],\n", - "rotation_angle = 180\n", - ")\n", - "\n", - "rotated_spline.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "rotated_mixed = paramak.RotateMixedShape(\n", - " points=[\n", - " (100, 0, 'straight'),\n", - " (200, 0, 'circle'),\n", - " (250, 50, 'circle'),\n", - " (200, 100, 'straight'),\n", - " (150, 100, 'spline'),\n", - " (140, 75, 'spline'),\n", - " (110, 45, 'spline'),\n", - " ],\n", - " rotation_angle = 180\n", - ")\n", - "\n", - "rotated_mixed.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a circular shape and rotates it to make a solid" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "rotated_circle = paramak.RotateCircleShape(\n", - " points=[(50, 0)],\n", - " radius=5,\n", - " rotation_angle=180\n", - ")\n", - "\n", - "rotated_circle.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "rotated_circle = paramak.ExtrudeCircleShape(\n", - " points=[(50, 0)],\n", - " radius=5,\n", - " distance=15\n", - ")\n", - "\n", - "rotated_circle.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a banana shape with straight edges and extrudes it to make a solid" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "extruded_straight = paramak.ExtrudeStraightShape(\n", - " points=[\n", - " (300, -300),\n", - " (400, 0),\n", - " (300, 300),\n", - " (400, 300),\n", - " (500, 0),\n", - " (400, -300),\n", - " ],\n", - " distance=200\n", - ")\n", - "\n", - "extruded_straight.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a banana shape and rotates it to make a solid" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "extruded_spline = paramak.ExtrudeSplineShape(\n", - " points=[\n", - " (500, 0),\n", - " (500, -20),\n", - " (400, -300),\n", - " (300, -300),\n", - " (400, 0),\n", - " (300, 300),\n", - " (400, 300),\n", - " (500, 20),\n", - " ],\n", - " distance=200,\n", - ")\n", - "\n", - "extruded_spline.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a shape with straight, circular and spline edges and extrudes it to make a solid" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "extruded_mixed = paramak.ExtrudeMixedShape(\n", - " points=[\n", - " (100, 0, 'straight'),\n", - " (200, 0, 'circle'),\n", - " (250, 50, 'circle'),\n", - " (200, 100, 'straight'),\n", - " (150, 100, 'spline'),\n", - " (140, 75, 'spline'),\n", - " (110, 45, 'spline'),\n", - " ],\n", - " distance=200\n", - ")\n", - "\n", - "extruded_mixed.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_shapes/make_blanket_from_parameters.ipynb b/examples/example_parametric_shapes/make_blanket_from_parameters.ipynb deleted file mode 100644 index eb6823acb..000000000 --- a/examples/example_parametric_shapes/make_blanket_from_parameters.ipynb +++ /dev/null @@ -1,63 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "height = 700\n", - "blanket_rear = 400\n", - "blanket_front = 300\n", - "blanket_mid_point = 350\n", - "\n", - "blanket = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (blanket_rear, height / 2.0, \"straight\"),\n", - " (blanket_rear, -height / 2.0, \"straight\"),\n", - " (blanket_front, -height / 2.0, \"spline\"),\n", - " (blanket_mid_point, 0, \"spline\"),\n", - " (blanket_front, height / 2.0, \"straight\"),\n", - " ],\n", - " color=(1,0,0), # red\n", - " name='blanket'\n", - ")\n", - "\n", - "blanket.export_stp(filename=\"blanket_from_parameters.stp\")\n", - "\n", - "blanket.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_shapes/make_blanket_from_points.ipynb b/examples/example_parametric_shapes/make_blanket_from_points.ipynb deleted file mode 100644 index 8b96e3477..000000000 --- a/examples/example_parametric_shapes/make_blanket_from_points.ipynb +++ /dev/null @@ -1,65 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "This python script demonstrates the parametric creation of a shape similar to\n", - "a breeder blanket.\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "\n", - "height = 700\n", - "blanket_rear = 400\n", - "blanket_front = 300\n", - "blanket_mid_point = 350\n", - "\n", - "blanket = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (blanket_rear, height / 2.0, \"straight\"),\n", - " (blanket_rear, -height / 2.0, \"straight\"),\n", - " (blanket_front, -height / 2.0, \"spline\"),\n", - " (blanket_mid_point, 0, \"spline\"),\n", - " (blanket_front, height / 2.0, \"straight\"),\n", - " ]\n", - ")\n", - "\n", - "blanket.export_stp(filename=\"blanket_from_parameters.stp\")\n", - "\n", - "blanket.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_shapes/make_can_reactor_from_parameters.ipynb b/examples/example_parametric_shapes/make_can_reactor_from_parameters.ipynb deleted file mode 100644 index 2e58b8848..000000000 --- a/examples/example_parametric_shapes/make_can_reactor_from_parameters.ipynb +++ /dev/null @@ -1,164 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\"\"\"\n", - "This script creates a can shaped reactor with plasma, center column, blanket, firstwall, divertor and core\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "outer_most_x = 900\n", - "blanket_height = 300\n", - "\n", - "plasma = paramak.Plasma(\n", - " major_radius=250,\n", - " minor_radius=100,\n", - " triangularity=0.5,\n", - " elongation=2.5,\n", - " rotation_angle=180\n", - ")\n", - "\n", - "centre_column = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (74.6, 687.0, \"straight\"),\n", - " (171.0, 687.0, \"straight\"),\n", - " (171.0, 459.9232, \"spline\"),\n", - " (108.001, 249.9402, \"spline\"),\n", - " (92.8995, 0, \"spline\"),\n", - " (108.001, -249.9402, \"spline\"),\n", - " (171.0, -459.9232, \"straight\"),\n", - " (171.0, -687.0, \"straight\"),\n", - " (74.6, -687.0, \"straight\"),\n", - " ]\n", - ")\n", - "\n", - "blanket = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (325.4528, blanket_height, \"straight\"),\n", - " (outer_most_x, blanket_height, \"straight\"),\n", - " (outer_most_x, -blanket_height, \"straight\"),\n", - " (325.4528, -blanket_height, \"spline\"),\n", - " (389.9263, -138.1335, \"spline\"),\n", - " (404.5108, 0, \"spline\"),\n", - " (389.9263, 138.1335, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "firstwall = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (322.9528, blanket_height, \"straight\"),\n", - " (325.4528, blanket_height, \"spline\"),\n", - " (389.9263, 138.1335, \"spline\"),\n", - " (404.5108, 0, \"spline\"),\n", - " (389.9263, -138.1335, \"spline\"),\n", - " (325.4528, -blanket_height, \"straight\"),\n", - " (322.9528, -blanket_height, \"spline\"),\n", - " (387.4263, -138.1335, \"spline\"),\n", - " (402.0108, 0, \"spline\"),\n", - " (387.4263, 138.1335, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "divertor_bottom = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (192.4782, -447.204, \"spline\"),\n", - " (272.4957, -370.5, \"spline\"),\n", - " (322.9528, -blanket_height, \"straight\"),\n", - " (outer_most_x, -blanket_height, \"straight\"),\n", - " (outer_most_x, -687.0, \"straight\"),\n", - " (171.0, -687.0, \"straight\"),\n", - " (171.0, -459.9232, \"spline\"),\n", - " (218.8746, -513.3484, \"spline\"),\n", - " (362.4986, -602.3905, \"straight\"),\n", - " (372.5012, -580.5742, \"spline\"),\n", - " (237.48395, -497.21782, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "divertor_top = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (192.4782, 447.204, \"spline\"),\n", - " (272.4957, 370.5, \"spline\"),\n", - " (322.9528, blanket_height, \"straight\"),\n", - " (outer_most_x, blanket_height, \"straight\"),\n", - " (outer_most_x, 687.0, \"straight\"),\n", - " (171.0, 687.0, \"straight\"),\n", - " (171.0, 459.9232, \"spline\"),\n", - " (218.8746, 513.3484, \"spline\"),\n", - " (362.4986, 602.3905, \"straight\"),\n", - " (372.5012, 580.5742, \"spline\"),\n", - " (237.48395, 497.21782, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "core = paramak.RotateStraightShape(\n", - " rotation_angle=180,\n", - " points=[\n", - " (0, 687.0),\n", - " (74.6, 687.0),\n", - " (74.6, -687.0),\n", - " (0, -687.0)]\n", - ")\n", - "\n", - "\n", - "# initiates a reactor object\n", - "myreactor = paramak.Reactor([plasma,\n", - " blanket,\n", - " core,\n", - " divertor_top,\n", - " divertor_bottom,\n", - " firstwall,\n", - " centre_column])\n", - "\n", - "myreactor.export_stp(filename=\"can_reactor_from_parameters.stp\")\n", - "myreactor.export_stl(filename=\"can_reactor_from_parameters.stl\")\n", - "myreactor.export_html(filename=\"can_reactor_from_parameters/reactor.html\")\n", - "\n", - "myreactor.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_shapes/make_can_reactor_from_points.ipynb b/examples/example_parametric_shapes/make_can_reactor_from_points.ipynb deleted file mode 100644 index 83fc15d46..000000000 --- a/examples/example_parametric_shapes/make_can_reactor_from_points.ipynb +++ /dev/null @@ -1,154 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "This python script demonstrates the creation of 3D volumes\n", - "from points to create an example reactor\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "plasma = paramak.Plasma(\n", - " major_radius=250,\n", - " minor_radius=100,\n", - " triangularity=0.5,\n", - " elongation=2.5,\n", - " rotation_angle=180,\n", - ")\n", - "\n", - "centre_column = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " name='centre_column',\n", - " points=[\n", - " (74.6, 687.0, \"straight\"),\n", - " (171.0, 687.0, \"straight\"),\n", - " (171.0, 459.9232, \"spline\"),\n", - " (108.001, 249.9402, \"spline\"),\n", - " (92.8995, 0, \"spline\"),\n", - " (108.001, -249.9402, \"spline\"),\n", - " (171.0, -459.9232, \"straight\"),\n", - " (171.0, -687.0, \"straight\"),\n", - " (74.6, -687.0, \"straight\"),\n", - " ]\n", - ")\n", - "\n", - "blanket = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " name='blanket',\n", - " points=[\n", - " (325.4886, 300.5, \"straight\"),\n", - " (538.4886, 300.5, \"straight\"),\n", - " (538.4886, -300.5, \"straight\"),\n", - " (325.4528, -300.5, \"spline\"),\n", - " (389.9263, -138.1335, \"spline\"),\n", - " (404.5108, 0, \"spline\"),\n", - " (389.9263, 138.1335, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "firstwall = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " name='firstwall',\n", - " points=[\n", - " (322.9528, 300.5, \"straight\"),\n", - " (325.4528, 300.5, \"spline\"),\n", - " (389.9263, 138.1335, \"spline\"),\n", - " (404.5108, 0, \"spline\"),\n", - " (389.9263, -138.1335, \"spline\"),\n", - " (325.4528, -300.5, \"straight\"),\n", - " (322.9528, -300.5, \"spline\"),\n", - " (387.4263, -138.1335, \"spline\"),\n", - " (402.0108, 0, \"spline\"),\n", - " (387.4263, 138.1335, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "divertor_bottom = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " name='divertor_bottom',\n", - " points=[\n", - " (192.4782, -447.204, \"spline\"),\n", - " (272.4957, -370.5, \"spline\"),\n", - " (322.9528, -300.5, \"straight\"),\n", - " (538.4886, -300.5, \"straight\"),\n", - " (538.4886, -687.0, \"straight\"),\n", - " (171.0, -687.0, \"straight\"),\n", - " (171.0, -459.9232, \"spline\"),\n", - " (218.8746, -513.3484, \"spline\"),\n", - " (362.4986, -602.3905, \"straight\"),\n", - " (372.5012, -580.5742, \"spline\"),\n", - " (237.48395, -497.21782, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "divertor_top = paramak.RotateMixedShape(\n", - " rotation_angle=180,\n", - " name='divertor_top',\n", - " points=[\n", - " (192.4782, 447.204, \"spline\"),\n", - " (272.4957, 370.5, \"spline\"),\n", - " (322.9528, 300.5, \"straight\"),\n", - " (538.4886, 300.5, \"straight\"),\n", - " (538.4886, 687.0, \"straight\"),\n", - " (171.0, 687.0, \"straight\"),\n", - " (171.0, 459.9232, \"spline\"),\n", - " (218.8746, 513.3484, \"spline\"),\n", - " (362.4986, 602.3905, \"straight\"),\n", - " (372.5012, 580.5742, \"spline\"),\n", - " (237.48395, 497.21782, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "core = paramak.RotateStraightShape(\n", - " rotation_angle=180,\n", - " name='core',\n", - " points=[(0, 687.0), (74.6, 687.0), (74.6, -687.0), (0, -687.0)]\n", - ")\n", - "\n", - "myreactor = paramak.Reactor([plasma,\n", - " blanket,\n", - " core,\n", - " divertor_top,\n", - " divertor_bottom,\n", - " firstwall,\n", - " centre_column])\n", - "\n", - "myreactor.export_stp(filename=\"can_reactor_from_points.stp\")\n", - "myreactor.export_stl(filename=\"can_reactor_from_point.stl\")\n", - "myreactor.export_html(\"can_reactor_from_points/reactor.html\")\n", - "\n", - "myreactor.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/example_parametric_shapes/make_html_diagram_from_stp_file.ipynb b/examples/example_parametric_shapes/make_html_diagram_from_stp_file.ipynb deleted file mode 100644 index 0507497dc..000000000 --- a/examples/example_parametric_shapes/make_html_diagram_from_stp_file.ipynb +++ /dev/null @@ -1,119 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Creates a stp file and then loads up the stp file and then facets the wires\n", - "(edges) of the geometry and plots the faceted eges along with the vertices\n", - "within the stp file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "\n", - "\"\"\"Creates an example stp file for plotting html point graphs\"\"\"\n", - "\n", - "# this creates a Shape object\n", - "example_shape = paramak.ExtrudeMixedShape(\n", - " distance=1,\n", - " points=[\n", - " (100, 0, \"straight\"),\n", - " (200, 0, \"circle\"),\n", - " (250, 50, \"circle\"),\n", - " (200, 100, \"straight\"),\n", - " (150, 100, \"spline\"),\n", - " (140, 75, \"spline\"),\n", - " (110, 45, \"spline\"),\n", - " ]\n", - ")\n", - "\n", - "# this exports the shape as a html image with a few different view planes\n", - "example_shape.export_html(\"example_shape_RZ.html\")\n", - "example_shape.export_html(\"example_shape_XYZ.html\", view_plane='XYZ')\n", - "example_shape.export_html(\"example_shape_XZ.html\", view_plane='XZ')\n", - "\n", - "# This exports the Shape object as an stp file that will be imported later\n", - "example_shape.export_stp(\"example_shape.stp\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"Loads an stp file and plots html point graphs\"\"\"\n", - "\n", - "# loads the stp file and obtains the solid shape and list of wires / edges\n", - "solid, wires = paramak.utils.load_stp_file(\n", - " filename=\"example_shape.stp\",\n", - ")\n", - "\n", - "# produces a plot on the R (radius) Z axis and saves the html file\n", - "paramak.utils.export_wire_to_html(\n", - " wires=wires,\n", - " tolerance=0.1,\n", - " view_plane=\"RZ\",\n", - " facet_splines=True,\n", - " facet_circles=True,\n", - " filename=\"example_shape_from_stp_RZ.html\",\n", - ")\n", - "\n", - "# produces a plot on the XZ axis and saves the html file\n", - "paramak.utils.export_wire_to_html(\n", - " wires=wires,\n", - " tolerance=0.1,\n", - " view_plane=\"XZ\",\n", - " facet_splines=True,\n", - " facet_circles=True,\n", - " filename=\"example_shape_from_stp_XZ.html\",\n", - ")\n", - "\n", - "# produces a 3D plot with XYZ axis and saves the html file\n", - "paramak.utils.export_wire_to_html(\n", - " wires=wires,\n", - " tolerance=0.1,\n", - " view_plane=\"XYZ\",\n", - " facet_splines=True,\n", - " facet_circles=True,\n", - " filename=\"example_shape_from_stp_XYZ.html\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.8.3" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/gui.Dockerfile b/gui.Dockerfile deleted file mode 100644 index e020c00ed..000000000 --- a/gui.Dockerfile +++ /dev/null @@ -1,71 +0,0 @@ -# This Dockerfile creates a paramak Graphical User Interface that forms part -# of the xsplot.com webapps -# -# There are build args availalbe for specifying the: -# - cq_version -# The version of CadQuery to use master or 2.1 -# Default is 2.1 -# Options: [master, 2, 2.1] -# -# Example builds: -# Building using the defaults (cq_version master) -# docker build -t paramak_gui . -# -# Building to include cadquery master. -# Run command from within the base repository directory -# docker build -t paramak_gui --build-arg cq_version=master . -# -# Once build the dockerimage can be run in a few different ways. -# -# Run with the following command for a jupyter notebook interface -# docker run -p 8050:8050 paramak_gui - - -FROM continuumio/miniconda3:4.9.2 as dependencies -# -# By default this Dockerfile builds with the latest release of CadQuery 2 -ARG cq_version=master - -ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 \ - DEBIAN_FRONTEND=noninteractive - -RUN apt-get --allow-releaseinfo-change update -RUN apt-get update -y && \ - apt-get upgrade -y - -RUN apt-get install -y libgl1-mesa-glx libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev libosmesa6 libosmesa6-dev libgles2-mesa-dev curl imagemagick && \ - apt-get clean - -# Installing CadQuery and Gmsh -RUN echo installing CadQuery version $cq_version && \ - conda install -c conda-forge -c python python=3.8 && \ - conda install -c conda-forge -c cadquery cadquery="$cq_version" && \ - conda install -c conda-forge moab && \ - conda install -c conda-forge gmsh && \ - conda install -c conda-forge python-gmsh && \ - pip install jupyter-cadquery && \ - conda clean -afy - - -FROM dependencies as install - -ARG paramak_version=develop - -RUN mkdir paramak -COPY src paramak/src/ -COPY pyproject.toml paramak/pyproject.toml - -COPY README.md paramak/README.md -COPY LICENSE.txt paramak/LICENSE.txt - -RUN cd paramak && \ - SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PARAMAK=${paramak_version} pip install .[gui] - -ENV PORT 8501 - -EXPOSE 8501 - -# solves bug of streamlit not running in container -# https://github.com/streamlit/streamlit/issues/4842 -ENTRYPOINT [ "streamlit", "run" ] -CMD [ "paramak/src/paramak/gui/app.py", "--server.headless", "true", "--server.fileWatcherType", "none", "--browser.gatherUsageStats", "false"] diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index ab38dce5b..000000000 --- a/pyproject.toml +++ /dev/null @@ -1,70 +0,0 @@ -[build-system] -requires = [ - "setuptools>=65.5.0", - "setuptools_scm[toml]>=7.0.5" -] -build-backend = "setuptools.build_meta" - -[project] -name = "paramak" -dynamic = ["version"] -description = "Create 3D fusion reactor CAD models based on input parameters" -readme = "README.md" -classifiers = [ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", -] -authors = [ - { name="The Paramak Development Team" }, -] -license = {file = "LICENSE.txt"} -requires-python = ">=3.8" -keywords = ["python", "geometry", "reactor", "model", "cad", "fusion", "parametric", "dagmc", "openmc"] -dependencies = [ - "plotly>=5.1.0", - "scipy>=1.7.0", - "sympy>=1.8", - "numpy>=1.21.1", - "matplotlib>=3.4.2", - "plasmaboundaries>=0.1.8", - "jupyter-client<7", - "jupyter-cadquery>=3.2.0", - "cad_to_dagmc>=0.1.2", - "setuptools_scm[toml]>=7.0.5" -] - -[project.urls] -"Homepage" = "https://github.com/fusion-energy/paramak" -"Bug Tracker" = "https://github.com/fusion-energy/paramak/issues" -"Documentation" = "https://paramak.readthedocs.io" - -[tool.setuptools_scm] -write_to = "src/_version.py" - -[project.optional-dependencies] -tests = [ - "pytest>=5.4.3", - "pytest-cov>=2.12.1", - "pytest-runner>=5.3.1", - "dagmc_h5m_file_inspector>=0.5.0" -] -docs = [ - "sphinx>=4.1.2", - "sphinx_rtd_theme", - "sphinx_autodoc_typehints", - "sphinxcadquery" -] -gui = [ - "streamlit>=1.14.1", - "streamlit-image-select>=0.5.1", -] - -[tool.black] -line-length = 120 - -[tool.setuptools] -package-dir = {"" = "src"} - -[project.scripts] -paramak = "paramak.gui.launch:main" diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index dd7962974..000000000 --- a/pytest.ini +++ /dev/null @@ -1,8 +0,0 @@ -[pytest] -markers = - dtype: Tests Data input types. - length: Tests Input and output Tuple legth. - analytical: Tests using analytical solutions to compare values to. - parametric: Tests using parametric solutions and in-built functions to calculate values. - value: Testing if the value given in one of the argument is correct. -testpaths = tests \ No newline at end of file diff --git a/readthedocs.yml b/readthedocs.yml deleted file mode 100644 index 64b7ec88f..000000000 --- a/readthedocs.yml +++ /dev/null @@ -1,30 +0,0 @@ -# .readthedocs.yml -# Read the Docs configuration file - -# Required -version: 2 - -build: - os: "ubuntu-20.04" - tools: - python: "mambaforge-4.10" - -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: docs/source/conf.py - -# Optional additional build formats no enabled to reduce memory -formats: [] - -# installs paramak package -python: - # version: 3.8 - install: - - method: pip - path: . - extra_requirements: - - docs - -# specify conda environment needed for build -conda: - environment: docs/environment.yml diff --git a/run_tests.sh b/run_tests.sh deleted file mode 100644 index 8d3dad0bb..000000000 --- a/run_tests.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -pytest tests -v --cov=paramak --cov-append --cov-report term --cov-report xml -pytest examples_tests -v diff --git a/src/paramak/__init__.py b/src/paramak/__init__.py deleted file mode 100644 index e0d89913b..000000000 --- a/src/paramak/__init__.py +++ /dev/null @@ -1,249 +0,0 @@ -try: - # this works for python 3.7 and lower - from importlib.metadata import version, PackageNotFoundError -except (ModuleNotFoundError, ImportError): - # this works for python 3.8 and higher - from importlib_metadata import version, PackageNotFoundError -try: - __version__ = version("paramak") -except PackageNotFoundError: - from setuptools_scm import get_version - - __version__ = get_version(root="..", relative_to=__file__) - -__all__ = ["__version__"] - - -from .shape import Shape -from .reactor import Reactor -from .utils import ( - rotate, - extend, - distance_between_two_points, - diff_between_angles, - find_center_point_of_circle, - angle_between_two_points_on_circle, - find_radius_of_circle, - export_solids_to_brep, - export_solids_to_dagmc_h5m, - get_center_of_bounding_box, -) -from .utils import EdgeLengthSelector, FaceAreaSelector - -from .parametric_shapes.extruded_mixed_shape import ExtrudeMixedShape -from .parametric_shapes.extruded_spline_shape import ExtrudeSplineShape -from .parametric_shapes.extruded_straight_shape import ExtrudeStraightShape -from .parametric_shapes.extruded_circle_shape import ExtrudeCircleShape - -from .parametric_shapes.rotate_mixed_shape import RotateMixedShape -from .parametric_shapes.rotate_spline_shape import RotateSplineShape -from .parametric_shapes.rotate_straight_shape import RotateStraightShape -from .parametric_shapes.rotate_circle_shape import RotateCircleShape - -from .parametric_shapes.sweep_mixed_shape import SweepMixedShape -from .parametric_shapes.sweep_spline_shape import SweepSplineShape -from .parametric_shapes.sweep_straight_shape import SweepStraightShape -from .parametric_shapes.sweep_circle_shape import SweepCircleShape - -from .parametric_components.circular_port import CircularPort -from .parametric_components.hexagon_pin import HexagonPin - -from .parametric_components.tokamak_plasma import Plasma -from .parametric_components.tokamak_plasma_from_points import PlasmaFromPoints -from .parametric_components.tokamak_plasma_plasmaboundaries import PlasmaBoundaries - -from .parametric_components.blanket_constant_thickness_arc_h import ( - BlanketConstantThicknessArcH, -) -from .parametric_components.blanket_constant_thickness_arc_v import ( - BlanketConstantThicknessArcV, -) -from .parametric_components.blanket_fp import BlanketFP -from .parametric_components.blanket_poloidal_segment import BlanketFPPoloidalSegments - -from .parametric_components.divertor_ITER import ITERtypeDivertor -from .parametric_components.divertor_ITER_no_dome import ITERtypeDivertorNoDome - -from .parametric_components.center_column_cylinder import CenterColumnShieldCylinder -from .parametric_components.center_column_hyperbola import CenterColumnShieldHyperbola -from .parametric_components.center_column_flat_top_hyperbola import ( - CenterColumnShieldFlatTopHyperbola, -) -from .parametric_components.center_column_plasma_dependant import ( - CenterColumnShieldPlasmaHyperbola, -) -from .parametric_components.center_column_circular import CenterColumnShieldCircular -from .parametric_components.center_column_flat_top_circular import ( - CenterColumnShieldFlatTopCircular, -) - -from .parametric_components.coolant_channel_ring_straight import ( - CoolantChannelRingStraight, -) -from .parametric_components.coolant_channel_ring_curved import CoolantChannelRingCurved - -from .parametric_components.inboard_firstwall_fccs import InboardFirstwallFCCS - -from .parametric_components.poloidal_field_coil import PoloidalFieldCoil -from .parametric_components.poloidal_field_coil_fp import PoloidalFieldCoilFP -from .parametric_components.poloidal_field_coil_case import PoloidalFieldCoilCase -from .parametric_components.poloidal_field_coil_case_fc import PoloidalFieldCoilCaseFC -from .parametric_components.poloidal_field_coil_set import PoloidalFieldCoilSet -from .parametric_components.poloidal_field_coil_case_set import PoloidalFieldCoilCaseSet -from .parametric_components.poloidal_field_coil_case_set_fc import ( - PoloidalFieldCoilCaseSetFC, -) -from .parametric_components.extrude_rectangle import ExtrudeRectangle -from .parametric_components.extrude_hollow_rectangle import ExtrudeHollowRectangle - -from .parametric_components.poloidal_segmenter import PoloidalSegments -from .parametric_components.port_cutters_rotated import PortCutterRotated -from .parametric_components.port_cutters_rectangular import PortCutterRectangular -from .parametric_components.port_cutters_circular import PortCutterCircular -from .parametric_components.rotated_trapezoid import RotatedTrapezoid -from .parametric_components.rotated_isosceles_triangle import RotatedIsoscelesTriangle -from .parametric_components.cutting_wedge import CuttingWedge -from .parametric_components.cutting_wedge_fs import CuttingWedgeFS -from .parametric_components.blanket_cutter_parallels import BlanketCutterParallels -from .parametric_components.blanket_cutters_star import BlanketCutterStar - -from .parametric_components.inner_tf_coils_circular import InnerTfCoilsCircular -from .parametric_components.inner_tf_coils_flat import InnerTfCoilsFlat - -from .parametric_components.toroidal_field_coil_coat_hanger import ( - ToroidalFieldCoilCoatHanger, -) -from .parametric_components.toroidal_field_coil_rectangle import ( - ToroidalFieldCoilRectangle, -) -from .parametric_components.toroidal_field_coil_triple_arc import ( - ToroidalFieldCoilTripleArc, -) -from .parametric_components.toroidal_field_coil_princeton_d import ( - ToroidalFieldCoilPrincetonD, -) -from .parametric_components.tf_coil_casing import TFCoilCasing -from .parametric_components.toroidal_field_coil_round_corners import ( - ToroidalFieldCoilRectangleRoundCorners, -) - -from .parametric_components.constant_thickness_dome import ConstantThicknessDome -from .parametric_components.vacuum_vessel import VacuumVessel - -from .parametric_components.dished_vacuum_vessel import DishedVacuumVessel -from .parametric_components.vacuum_vessel_inner_leg import VacuumVesselInnerLeg -from .parametric_components.capsule_vacuum_vessel import CapsuleVacuumVessel -from .parametric_components.hollow_cube import HollowCube -from .parametric_components.shell_fs import ShellFS - -from .parametric_reactors.eu_demo_2015_reactor import EuDemoFrom2015PaperDiagram -from .parametric_reactors.ball_reactor import BallReactor -from .parametric_reactors.submersion_reactor import SubmersionTokamak -from .parametric_reactors.single_null_submersion_reactor import ( - SingleNullSubmersionTokamak, -) -from .parametric_reactors.single_null_ball_reactor import SingleNullBallReactor -from .parametric_reactors.segmented_blanket_ball_reactor import ( - SegmentedBlanketBallReactor, -) -from .parametric_reactors.center_column_study_reactor import CenterColumnStudyReactor -from .parametric_reactors.sparc_paper_2020 import SparcFrom2020PaperDiagram -from .parametric_reactors.iter_paper_2020 import IterFrom2020PaperDiagram -from .parametric_reactors.flf_system_code_reactor import FlfSystemCodeReactor -from .parametric_reactors.negative_triangularity_reactor import ( - NegativeTriangularityReactor, -) - -__all__ = [ - Shape, - Reactor, - rotate, - extend, - distance_between_two_points, - diff_between_angles, - find_center_point_of_circle, - angle_between_two_points_on_circle, - find_radius_of_circle, - export_solids_to_brep, - export_solids_to_dagmc_h5m, - get_center_of_bounding_box, - EdgeLengthSelector, - FaceAreaSelector, - ExtrudeMixedShape, - ExtrudeSplineShape, - ExtrudeStraightShape, - ExtrudeCircleShape, - RotateMixedShape, - RotateSplineShape, - RotateStraightShape, - RotateCircleShape, - SweepMixedShape, - SweepSplineShape, - SweepStraightShape, - SweepCircleShape, - CircularPort, - HexagonPin, - Plasma, - PlasmaFromPoints, - PlasmaBoundaries, - BlanketConstantThicknessArcH, - BlanketConstantThicknessArcV, - BlanketFP, - BlanketFPPoloidalSegments, - ITERtypeDivertor, - ITERtypeDivertorNoDome, - CenterColumnShieldCylinder, - CenterColumnShieldHyperbola, - CenterColumnShieldFlatTopHyperbola, - CenterColumnShieldPlasmaHyperbola, - CenterColumnShieldCircular, - CenterColumnShieldFlatTopCircular, - CoolantChannelRingStraight, - CoolantChannelRingCurved, - InboardFirstwallFCCS, - PoloidalFieldCoil, - PoloidalFieldCoilFP, - PoloidalFieldCoilCase, - PoloidalFieldCoilCaseFC, - PoloidalFieldCoilSet, - PoloidalFieldCoilCaseSet, - PoloidalFieldCoilCaseSetFC, - ExtrudeRectangle, - ExtrudeHollowRectangle, - PoloidalSegments, - PortCutterRotated, - PortCutterRectangular, - PortCutterCircular, - RotatedTrapezoid, - RotatedIsoscelesTriangle, - CuttingWedge, - CuttingWedgeFS, - BlanketCutterParallels, - BlanketCutterStar, - InnerTfCoilsCircular, - InnerTfCoilsFlat, - ToroidalFieldCoilCoatHanger, - ToroidalFieldCoilRectangle, - ToroidalFieldCoilTripleArc, - ToroidalFieldCoilPrincetonD, - TFCoilCasing, - ToroidalFieldCoilRectangleRoundCorners, - ConstantThicknessDome, - VacuumVessel, - DishedVacuumVessel, - VacuumVesselInnerLeg, - CapsuleVacuumVessel, - HollowCube, - ShellFS, - EuDemoFrom2015PaperDiagram, - BallReactor, - SubmersionTokamak, - SingleNullSubmersionTokamak, - SingleNullBallReactor, - SegmentedBlanketBallReactor, - CenterColumnStudyReactor, - SparcFrom2020PaperDiagram, - IterFrom2020PaperDiagram, - FlfSystemCodeReactor, - NegativeTriangularityReactor, -] diff --git a/src/paramak/gui/app.py b/src/paramak/gui/app.py deleted file mode 100644 index b45952794..000000000 --- a/src/paramak/gui/app.py +++ /dev/null @@ -1,229 +0,0 @@ -import os -from pathlib import Path - -import paramak -import streamlit as st -from streamlit_image_select import image_select - -st.set_page_config( - page_title="Paramak", - page_icon="⚛", - layout="wide", -) - -hide_streamlit_style = """ - - """ -st.markdown(hide_streamlit_style, unsafe_allow_html=True) -st.markdown("# Paramak GUI") -st.markdown( - "## A Graphical User Interface to [Paramak](https://github.com/fusion-energy/paramak) " - "for parametric fusion reactor geometry creation" -) - -# FIXME get images names from https://paramak.readthedocs.io/en/main/API-Reference.html#parametric-reactors -reactor_image_links = [ - "", - "https://user-images.githubusercontent.com/8583900/211223396-41ed8628-5352-4e7a-8c4a-97914174954e.png", - "https://user-images.githubusercontent.com/8583900/99136724-91af6f00-261e-11eb-9956-476b818a0ee3.png", - "https://user-images.githubusercontent.com/8583900/99136728-983de680-261e-11eb-8398-51ae433f5546.png", - "https://user-images.githubusercontent.com/8583900/99136727-94aa5f80-261e-11eb-965d-0ccceb2743fc.png", - "https://user-images.githubusercontent.com/8583900/99136719-8e1be800-261e-11eb-907d-a9bafaebdbb8.png", - "https://user-images.githubusercontent.com/8583900/99136731-9aa04080-261e-11eb-87a5-502708dfebcc.png", - "https://user-images.githubusercontent.com/8583900/99136734-9e33c780-261e-11eb-837b-16a0bc59f8a7.png", - "https://user-images.githubusercontent.com/8583900/110224418-4f62b400-7ed3-11eb-85f1-e40dc74f5671.png", - "https://user-images.githubusercontent.com/40028739/110248118-cf3e5c00-7f6f-11eb-9e68-864c1a1e8676.png", - "https://user-images.githubusercontent.com/8583900/100032191-5ae01280-2def-11eb-9654-47c3869b3a2c.png", - "https://user-images.githubusercontent.com/85617935/144303187-8cb71e2d-fc35-450f-a8f4-88b6650d56b7.png", -] - -reactor_names = [ - "0", - "FlfSystemCodeReactor", - "BallReactor", - "SingleNullBallReactor", - "SegmentedBlanketBallReactor", - "SubmersionTokamak", - "SingleNullSubmersionTokamak", - "CenterColumnStudyReactor", - "EuDemoFrom2015PaperDiagram", - "IterFrom2020PaperDiagram", - "SparcFrom2020PaperDiagram", - "NegativeTriangularityReactor", -] - - -selected_reactor_index = image_select( - label="Select a reactor", - images=reactor_image_links, - captions=reactor_names, - use_container_width=False, - return_value="index", # function returns index instead of image - index=0, # initial selected image is 0 which is blank -) - -# gets the caption name of the selected image -selected_reactor = reactor_names[selected_reactor_index] - -st.write(selected_reactor) -write_cad_buttons = True -col1, col2, col3 = st.columns([1, 1, 1]) - -if selected_reactor_index not in [0, None]: - - if selected_reactor == "FlfSystemCodeReactor": - inner_blanket_radius = col1.number_input("inner blanket radius", value=100.0) - blanket_thickness = col1.number_input("blanket thickness", value=70.0) - blanket_height = col1.number_input("blanket height", value=500.0) - lower_blanket_thickness = col1.number_input("lower blanket thickness", value=50.0) - upper_blanket_thickness = col2.number_input("upper blanket thickness", value=40.0) - blanket_vv_gap = col2.number_input("blanket vv gap", value=20.0) - upper_vv_thickness = col2.number_input("upper vv thickness", value=10.0) - vv_thickness = col3.number_input("vv thickness", value=10.0) - lower_vv_thickness = col3.number_input("lower vv thickness", value=10.0) - rotation_angle = col3.number_input("rotation angle", value=180.0) - - elif selected_reactor == "BallReactor": - inner_bore_radial_thickness = col1.number_input("inner_bore_radial_thickness", value=10.0) - inboard_tf_leg_radial_thickness = col1.number_input("inboard_tf_leg_radial_thickness", value=30.0) - center_column_shield_radial_thickness = col1.number_input("center_column_shield_radial_thickness", value=60.0) - divertor_radial_thickness = col1.number_input("divertor_radial_thickness", value=150.0) - inner_plasma_gap_radial_thickness = col1.number_input("inner_plasma_gap_radial_thickness", value=30.0) - plasma_radial_thickness = col1.number_input("plasma_radial_thickness", value=300.0) - outer_plasma_gap_radial_thickness = col1.number_input("outer_plasma_gap_radial_thickness", value=30.0) - firstwall_radial_thickness = col1.number_input("firstwall_radial_thickness", value=30.0) - blanket_radial_thickness = col2.number_input("firstwall_radial_thickness", value=50.0) - blanket_rear_wall_radial_thickness = col2.number_input("blanket_rear_wall_radial_thickness", value=30.0) - elongation = col2.number_input("elongation", value=2.0) - triangularity = col2.number_input("triangularity", value=0.55) - plasma_gap_vertical_thickness = col2.number_input("plasma_gap_vertical_thickness", value=50.0) - divertor_to_tf_gap_vertical_thickness = col2.number_input("divertor_to_tf_gap_vertical_thickness", value=0.0) - number_of_tf_coils = col2.number_input("number_of_tf_coils", value=12) - rear_blanket_to_tf_gap = col2.number_input("rear_blanket_to_tf_gap", value=0.0) - pf_coil_radial_thicknesses = col3.text_input( - "pf_coil_radial_thicknesses", value="50,40,50", key="input_pf_coil_radial_thicknesses" - ) - pf_coil_vertical_thicknesses = col3.text_input("pf_coil_vertical_thicknesses", value="60,40,60", key="") - pf_coil_radial_position = col3.text_input( - "pf_coil_radial_position", value="500,550,500", key="input_pf_coil_radial_position" - ) - pf_coil_vertical_position = col3.text_input( - "pf_coil_vertical_position", value="-250,0,250", key="input_pf_coil_vertical_position" - ) - pf_coil_case_thicknesses = col3.text_input( - "pf_coil_case_thicknesses", value="5,5,5", key="input_pf_coil_case_thicknesses" - ) - outboard_tf_coil_radial_thickness = col3.number_input( - "outboard_tf_coil_radial_thickness", value=50, key="input_outboard_tf_coil_radial_thickness" - ) - outboard_tf_coil_poloidal_thickness = col3.number_input( - "outboard_tf_coil_radial_thickness", value=50, key="input_outboard_tf_coil_poloidal_thickness" - ) - divertor_position = col3.selectbox("divertor_position", options=["both", "lower", "upper"]) - rotation_angle = col3.number_input("rotation angle", value=180.0) - else: - write_cad_buttons = False - st.write(f"{selected_reactor} not implemented in GUI yet. Contributions are welcome") - - if write_cad_buttons: - with st.spinner("Building the 3d model"): - if selected_reactor == "FlfSystemCodeReactor": - paramak_reactor = paramak.FlfSystemCodeReactor( - inner_blanket_radius=inner_blanket_radius, - blanket_thickness=blanket_thickness, - blanket_height=blanket_height, - lower_blanket_thickness=lower_blanket_thickness, - upper_blanket_thickness=upper_blanket_thickness, - blanket_vv_gap=blanket_vv_gap, - upper_vv_thickness=upper_vv_thickness, - vv_thickness=vv_thickness, - lower_vv_thickness=lower_vv_thickness, - rotation_angle=rotation_angle, - ) - elif selected_reactor == "BallReactor": - paramak_reactor = paramak.BallReactor( - inner_bore_radial_thickness=inner_bore_radial_thickness, - inboard_tf_leg_radial_thickness=inboard_tf_leg_radial_thickness, - center_column_shield_radial_thickness=center_column_shield_radial_thickness, - divertor_radial_thickness=divertor_radial_thickness, - inner_plasma_gap_radial_thickness=inner_plasma_gap_radial_thickness, - plasma_radial_thickness=plasma_radial_thickness, - outer_plasma_gap_radial_thickness=outer_plasma_gap_radial_thickness, - firstwall_radial_thickness=firstwall_radial_thickness, - blanket_radial_thickness=blanket_radial_thickness, - blanket_rear_wall_radial_thickness=blanket_rear_wall_radial_thickness, - elongation=elongation, - triangularity=triangularity, - plasma_gap_vertical_thickness=plasma_gap_vertical_thickness, - divertor_to_tf_gap_vertical_thickness=divertor_to_tf_gap_vertical_thickness, - number_of_tf_coils=number_of_tf_coils, - rear_blanket_to_tf_gap=rear_blanket_to_tf_gap, - pf_coil_radial_thicknesses=[float(v) for v in pf_coil_radial_thicknesses.split(",")], - pf_coil_vertical_thicknesses=[float(v) for v in pf_coil_vertical_thicknesses.split(",")], - pf_coil_radial_position=[float(v) for v in pf_coil_radial_position.split(",")], - pf_coil_vertical_position=[float(v) for v in pf_coil_vertical_position.split(",")], - pf_coil_case_thicknesses=[float(v) for v in pf_coil_case_thicknesses.split(",")], - outboard_tf_coil_radial_thickness=outboard_tf_coil_radial_thickness, - outboard_tf_coil_poloidal_thickness=outboard_tf_coil_poloidal_thickness, - divertor_position=divertor_position, - rotation_angle=rotation_angle, - ) - - save_path = Path(os.path.realpath(__file__)).parent - - save_html_file = save_path / "reactor.html" - paramak_reactor.export_html_3d(save_html_file) - with open(save_html_file, "r", encoding="UTF-8") as file1: - html_data = file1.read() - - save_stp_file = save_path / "reactor.stp" - paramak_reactor.export_stp(str(save_stp_file)) - with open(save_stp_file, "r", encoding="UTF-8") as file2: - stp_data = file2.read() - - # save_stl_file = save_path / "reactor.stl" - # paramak_reactor.export_stl(str(save_stl_file)) - # with open(save_stl_file, "r") as file3: - # stl_data = file3.read() - - # FIXME fix so that it works - # save_h5m_file = save_path / "reactor.h5m" - # paramak_reactor.export_dagmc_h5m(str(save_h5m_file)) - # with open(save_h5m_file, "r") as file4: - # h5m_data = file4.read() - - col1_buttons, col2_buttons = st.columns([1, 1]) - - # FIXME see if on_click arg can be used to make stp file on demand - # https://docs.streamlit.io/library/api-reference/widgets/st.download_button - col1_buttons.download_button( - "Download CAD (STP format)", - stp_data, - file_name="paramak.stp", - ) - col2_buttons.download_button( - "Download CAD (HTML format)", - html_data, - file_name="paramak.html", - ) - - # this is not currently working, perhaps due to binary files - # col2_buttons.download_button( - # "Download CAD (STL format)", - # stl_data, - # file_name="paramak.stl", - # ) - - # FIXME fix so that it works - # st.download_button( - # "Download DAGMC (h5m format)", - # stl_data, - # file_name="paramak.h5m", - # ) - - st.components.v1.html(html_data, height=800) diff --git a/src/paramak/gui/launch.py b/src/paramak/gui/launch.py deleted file mode 100644 index 92f828b41..000000000 --- a/src/paramak/gui/launch.py +++ /dev/null @@ -1,17 +0,0 @@ -import runpy -import sys -from pathlib import Path - -import paramak - - -def main(): - - path_to_app = str(Path(paramak.__path__[0]) / "gui" / "app.py") - - sys.argv = ["streamlit", "run", path_to_app] - runpy.run_module("streamlit", run_name="__main__") - - -if __name__ == "__main__": - main() diff --git a/src/paramak/parametric_components/__init__.py b/src/paramak/parametric_components/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/paramak/parametric_components/blanket_constant_thickness_arc_h.py b/src/paramak/parametric_components/blanket_constant_thickness_arc_h.py deleted file mode 100644 index 2930e5b56..000000000 --- a/src/paramak/parametric_components/blanket_constant_thickness_arc_h.py +++ /dev/null @@ -1,58 +0,0 @@ -from typing import Tuple - -from paramak import RotateMixedShape - - -class BlanketConstantThicknessArcH(RotateMixedShape): - """An outboard blanket volume that follows the curvature of a circular - arc and a constant blanket thickness. The upper and lower edges continue - horizontally for the thickness of the blanket to back of the blanket. - - Arguments: - inner_mid_point: the x,z coordinates of the mid point on the inner - surface of the blanket. - inner_upper_point: the x,z coordinates of the upper point on the - inner surface of the blanket. - inner_lower_point: the x,z coordinates of the lower point on the - inner surface of the blanket. - thickness: the radial thickness of the blanket in cm. - """ - - def __init__( - self, - inner_mid_point: Tuple[float, float], - inner_upper_point: Tuple[float, float], - inner_lower_point: Tuple[float, float], - thickness: float, - **kwargs - ) -> None: - - super().__init__(**kwargs) - - self.inner_upper_point = inner_upper_point - self.inner_lower_point = inner_lower_point - self.inner_mid_point = inner_mid_point - self.thickness = thickness - - def find_points(self): - - self.points = [ - (self.inner_upper_point[0], self.inner_upper_point[1], "circle"), - (self.inner_mid_point[0], self.inner_mid_point[1], "circle"), - (self.inner_lower_point[0], self.inner_lower_point[1], "straight"), - ( - self.inner_lower_point[0] + abs(self.thickness), - self.inner_lower_point[1], - "circle", - ), - ( - self.inner_mid_point[0] + abs(self.thickness), - self.inner_mid_point[1], - "circle", - ), - ( - self.inner_upper_point[0] + abs(self.thickness), - self.inner_upper_point[1], - "straight", - ), - ] diff --git a/src/paramak/parametric_components/blanket_constant_thickness_arc_v.py b/src/paramak/parametric_components/blanket_constant_thickness_arc_v.py deleted file mode 100644 index e4a4a4d43..000000000 --- a/src/paramak/parametric_components/blanket_constant_thickness_arc_v.py +++ /dev/null @@ -1,58 +0,0 @@ -from typing import Tuple - -from paramak import RotateMixedShape - - -class BlanketConstantThicknessArcV(RotateMixedShape): - """An outboard blanket volume that follows the curvature of a circular - arc and a constant blanket thickness. The upper and lower edges continue - vertically for the thickness of the blanket to back of the blanket. - - Arguments: - inner_mid_point: the x,z coordinates of the mid point on the inner - surface of the blanket. - inner_upper_point: the x,z coordinates of the upper point on the - inner surface of the blanket. - inner_lower_point: the x,z coordinates of the lower point on the - inner surface of the blanket. - thickness: the radial thickness of the blanket in cm. - """ - - def __init__( - self, - inner_mid_point: Tuple[float, float], - inner_upper_point: Tuple[float, float], - inner_lower_point: Tuple[float, float], - thickness: float, - **kwargs - ) -> None: - - super().__init__(**kwargs) - - self.inner_upper_point = inner_upper_point - self.inner_lower_point = inner_lower_point - self.inner_mid_point = inner_mid_point - self.thickness = thickness - - def find_points(self): - - self.points = [ - (self.inner_upper_point[0], self.inner_upper_point[1], "circle"), - (self.inner_mid_point[0], self.inner_mid_point[1], "circle"), - (self.inner_lower_point[0], self.inner_lower_point[1], "straight"), - ( - self.inner_lower_point[0], - self.inner_lower_point[1] - abs(self.thickness), - "circle", - ), - ( - self.inner_mid_point[0] + self.thickness, - self.inner_mid_point[1], - "circle", - ), - ( - self.inner_upper_point[0], - self.inner_upper_point[1] + abs(self.thickness), - "straight", - ), - ] diff --git a/src/paramak/parametric_components/blanket_cutter_parallels.py b/src/paramak/parametric_components/blanket_cutter_parallels.py deleted file mode 100644 index 185b15fbc..000000000 --- a/src/paramak/parametric_components/blanket_cutter_parallels.py +++ /dev/null @@ -1,104 +0,0 @@ -from typing import Iterable, Union - -from paramak import ExtrudeStraightShape -from paramak.utils import cut_solid - - -class BlanketCutterParallels(ExtrudeStraightShape): - """Creates an extruded shape with a parallel rectangular section repeated - around the reactor. The shape is used to cut other components (eg. blankets - and firstwalls) in order to create a banana section of the blankets with - parallel sides.Typically used to divide a blanket into vertical - sections with a fixed distance between each section. - - Args: - thickness: extruded distance (cm) of the cutter which translates to - being the gap size between blankets when the cutter is used to - segment blankets. - gap_size: the distance between the inner edges of the two parallel - extrusions - height: height (cm) of the port. Defaults to 2000.0. - width: width (cm) of the port. Defaults to 2000.0. - name: Defaults to "blanket_cutter_Parallels". - azimuth_placement_angle (float or list of floats): Defaults to [0., 36., - 72., 108., 144., 180., 216., 252., 288., 324.]. - """ - - def __init__( - self, - thickness: float, - gap_size: float, - height: float = 2000.0, - width: float = 2000.0, - azimuth_placement_angle: Union[float, Iterable[float]] = [ - 0.0, - 36.0, - 72.0, - 108.0, - 144.0, - 180.0, - 216.0, - 252.0, - 288.0, - 324.0, - ], - name: str = "blanket_cutter_parallels", - **kwargs - ) -> None: - - self.main_cutting_shape = ExtrudeStraightShape( - distance=gap_size / 2.0, - azimuth_placement_angle=azimuth_placement_angle, - ) - self.gap_size = gap_size - self.thickness = thickness - super().__init__(distance=self.distance, azimuth_placement_angle=azimuth_placement_angle, name=name, **kwargs) - self.height = height - self.width = width - - @property - def distance(self): - self.distance = self.gap_size / 2.0 + self.thickness - return self._distance - - @distance.setter - def distance(self, value): - self._distance = value - - @property - def gap_size(self): - return self._gap_size - - @gap_size.setter - def gap_size(self, value): - self.main_cutting_shape.distance = value / 2.0 - self._gap_size = value - - @property - def azimuth_placement_angle(self): - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self.main_cutting_shape.azimuth_placement_angle = value - self._azimuth_placement_angle = value - - def find_points(self): - - points = [ - (0, -self.height / 2), - (self.width, -self.height / 2), - (self.width, self.height / 2), - (0, self.height / 2), - ] - - self.main_cutting_shape.points = points - - self.points = points - - def create_solid(self): - solid = super().create_solid() - solid = cut_solid(solid, self.main_cutting_shape) - self.solid = solid - - return solid diff --git a/src/paramak/parametric_components/blanket_cutters_star.py b/src/paramak/parametric_components/blanket_cutters_star.py deleted file mode 100644 index 8065d096a..000000000 --- a/src/paramak/parametric_components/blanket_cutters_star.py +++ /dev/null @@ -1,61 +0,0 @@ -from typing import Iterable, Union - -from paramak import ExtrudeStraightShape - - -class BlanketCutterStar(ExtrudeStraightShape): - """Creates an extruded shape with a rectangular section that is used to cut - other components (eg. blankets and firstwalls) in order to create banana - style blanket segments. Typically used to divide a blanket into vertical - sections with a fixed gap between each section. - - Args: - distance: extruded distance (cm) of the cutter which translates to being - the gap size between blankets when the cutter is used to segment - blankets. - height: height (cm) of the port. Defaults to 2000.0. - width: width (cm) of the port. Defaults to 2000.0. - azimuth_placement_angle (list or float, optional): Defaults to - [0., 36., 72., 108., 144., 180., 216., 252., 288., 324.] - name: defaults to "blanket_cutter_star". - """ - - def __init__( - self, - distance: float, - height: float = 2000.0, - width: float = 2000.0, - azimuth_placement_angle: Union[float, Iterable[float]] = [ - 0.0, - 36.0, - 72.0, - 108.0, - 144.0, - 180.0, - 216.0, - 252.0, - 288.0, - 324.0, - ], - name: str = "blanket_cutter_star", - **kwargs - ) -> None: - - super().__init__( - extrude_both=True, name=name, azimuth_placement_angle=azimuth_placement_angle, distance=distance, **kwargs - ) - - self.azimuth_placement_angle = azimuth_placement_angle - self.height = height - self.width = width - self.distance = distance - - def find_points(self): - - points = [ - (0, -self.height / 2), - (self.width, -self.height / 2), - (self.width, self.height / 2), - (0, self.height / 2), - ] - self.points = points diff --git a/src/paramak/parametric_components/blanket_fp.py b/src/paramak/parametric_components/blanket_fp.py deleted file mode 100644 index 506320560..000000000 --- a/src/paramak/parametric_components/blanket_fp.py +++ /dev/null @@ -1,273 +0,0 @@ -import warnings -from typing import Optional, Union, Iterable - -import mpmath -import numpy as np -import sympy as sp -from scipy.interpolate import interp1d - -import paramak -from paramak import RotateMixedShape - - -class BlanketFP(RotateMixedShape): - """A blanket volume created from plasma parameters. In might be nessecary - to increase the num_points when making long but thin geometry with this - component. - - Args: - thickness (float or [float] or callable or [(float), (float)]): - the thickness of the blanket (cm). If the thickness is a float then - this produces a blanket of constant thickness. If the thickness is - a tuple of floats, blanket thickness will vary linearly between the - two values. If thickness is callable, then the blanket thickness - will be a function of poloidal angle (in degrees). If thickness is - a list of two lists (thicknesses and angles) then these will be - used together with linear interpolation. - start_angle: the angle in degrees to start the blanket, measured anti - clockwise from 3 o'clock. - stop_angle: the angle in degrees to stop the blanket, measured anti - clockwise from 3 o'clock. - plasma: If not None, the parameters of the plasma Object will be used. - minor_radius: the minor radius of the plasma (cm). - major_radius: the major radius of the plasma (cm). - triangularity: the triangularity of the plasma. - elongation: the elongation of the plasma. - vertical_displacement: the vertical_displacement of the plasma (cm). - offset_from_plasma: the distance between the plasma and the blanket - (cm). If float, constant offset. If list of floats, offset will - vary linearly between the values. If callable, offset will be a - function of poloidal angle (in degrees). If a list of two lists - (angles and offsets) then these will be used together with linear - interpolation. - num_points: number of points that will describe the shape. - """ - - def __init__( - self, - thickness, - start_angle: float, - stop_angle: float, - plasma: Optional[Union[paramak.Plasma, paramak.PlasmaBoundaries, paramak.PlasmaFromPoints]] = None, - minor_radius: float = 150.0, - major_radius: float = 450.0, - triangularity: float = 0.55, - elongation: float = 2.0, - vertical_displacement: float = 0.0, - offset_from_plasma: Union[float, Iterable[float]] = 0.0, - num_points: int = 50, - allow_overlapping_shape=False, - **kwargs - ): - - super().__init__(**kwargs) - - self.thickness = thickness - self.start_angle, self.stop_angle = None, None - self.start_angle = start_angle - self.stop_angle = stop_angle - self.plasma = plasma - self.vertical_displacement = vertical_displacement - self.allow_overlapping_shape = allow_overlapping_shape - if plasma is None: - self.minor_radius = minor_radius - self.major_radius = major_radius - self.triangularity = triangularity - self.elongation = elongation - else: # if plasma object is given, use its parameters - self.minor_radius = plasma.minor_radius - self.major_radius = plasma.major_radius - self.triangularity = plasma.triangularity - self.elongation = plasma.elongation - self.offset_from_plasma = offset_from_plasma - self.num_points = num_points - - @property - def start_angle(self): - return self._start_angle - - @start_angle.setter - def start_angle(self, value): - self._start_angle = value - - @property - def stop_angle(self): - return self._stop_angle - - @stop_angle.setter - def stop_angle(self, value): - self._stop_angle = value - - @property - def minor_radius(self): - return self._minor_radius - - @minor_radius.setter - def minor_radius(self, minor_radius): - self._minor_radius = minor_radius - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, thickness): - self._thickness = thickness - - @property - def inner_points(self): - self.find_points() - return self._inner_points - - @inner_points.setter - def inner_points(self, value): - self._inner_points = value - - @property - def outer_points(self): - self.find_points() - return self._outer_points - - @outer_points.setter - def outer_points(self, value): - self._outer_points = value - - def make_callable(self, attribute): - """This function transforms an attribute (thickness or offset) into a - callable function of theta - """ - # if the attribute is a list, create a interpolated object of the - # values - if isinstance(attribute, (tuple, list)): - if ( - isinstance(attribute[0], (tuple, list)) - and isinstance(attribute[1], (tuple, list)) - and len(attribute) == 2 - ): - # attribute is a list of 2 lists - if len(attribute[0]) != len(attribute[1]): - raise ValueError( - "The length of angles list must equal \ - the length of values list" - ) - list_of_angles = np.array(attribute[0]) - offset_values = attribute[1] - else: - # no list of angles is given - offset_values = attribute - list_of_angles = np.linspace(self.start_angle, self.stop_angle, len(offset_values), endpoint=True) - interpolated_values = interp1d(list_of_angles, offset_values) - - def fun(theta): - if callable(attribute): - return attribute(theta) - elif isinstance(attribute, (tuple, list)): - return interpolated_values(theta) - else: - return attribute - - return fun - - def find_points(self, angles=None): - self._overlapping_shape = False - # create array of angles theta - if angles is None: - thetas = np.linspace( - self.start_angle, - self.stop_angle, - num=self.num_points, - endpoint=True, - ) - else: - thetas = angles - - # create inner points - inner_offset = self.make_callable(self.offset_from_plasma) - inner_points = self.create_offset_points(thetas, inner_offset) - inner_points[-1][2] = "straight" - self.inner_points = inner_points - - # create outer points - thickness = self.make_callable(self.thickness) - - def outer_offset(theta): - return inner_offset(theta) + thickness(theta) - - outer_points = self.create_offset_points(np.flip(thetas), outer_offset) - outer_points[-1][2] = "straight" - self.outer_points = outer_points - - # assemble - points = inner_points + outer_points - if self._overlapping_shape and self.allow_overlapping_shape is False: - msg = "BlanketFP: Some points with negative R coordinate have " "been ignored." - warnings.warn(msg) - - self.points = points - return points - - def create_offset_points(self, thetas, offset): - """generates a list of points following parametric equations with an - offset - - Args: - thetas (np.array): the angles in degrees. - offset (callable): offset value (cm). offset=0 will follow the - parametric equations. - - Returns: - list: list of points [[R1, Z1, connection1], [R2, Z2, connection2], - ...] - """ - # create sympy objects and derivatives - theta_sp = sp.Symbol("theta") - - R_sp, Z_sp = self.distribution(theta_sp, pkg=sp) - R_derivative = sp.diff(R_sp, theta_sp) - Z_derivative = sp.diff(Z_sp, theta_sp) - points = [] - - for theta in thetas: - # get local value of derivatives - val_R_derivative = float(R_derivative.subs("theta", theta)) - val_Z_derivative = float(Z_derivative.subs("theta", theta)) - - # get normal vector components - nx = val_Z_derivative - ny = -val_R_derivative - - # normalise normal vector - normal_vector_norm = (nx**2 + ny**2) ** 0.5 - nx /= normal_vector_norm - ny /= normal_vector_norm - - # calculate outer points - val_R_outer = self.distribution(theta)[0] + offset(theta) * nx - val_Z_outer = self.distribution(theta)[1] + offset(theta) * ny - if float(val_R_outer) > 0: - points.append([float(val_R_outer), float(val_Z_outer), "spline"]) - else: - self._overlapping_shape = True - return points - - def distribution(self, theta, pkg=np): - """Plasma distribution theta in degrees - - Args: - theta (float or np.array or sp.Symbol): the angle(s) in degrees. - pkg (module, optional): Module to use in the funciton. If sp, as - sympy object will be returned. If np, a np.array or a float - will be returned. Defaults to np. - - Returns: - (float, float) or (sympy.Add, sympy.Mul) or - (numpy.array, numpy.array): The R and Z coordinates of the - point with angle theta - """ - if pkg == np: - theta = np.radians(theta) - else: - theta = mpmath.radians(theta) - R = self.major_radius + self.minor_radius * pkg.cos(theta + self.triangularity * pkg.sin(theta)) - Z = self.elongation * self.minor_radius * pkg.sin(theta) + self.vertical_displacement - return R, Z diff --git a/src/paramak/parametric_components/blanket_poloidal_segment.py b/src/paramak/parametric_components/blanket_poloidal_segment.py deleted file mode 100644 index 8e98eb9d4..000000000 --- a/src/paramak/parametric_components/blanket_poloidal_segment.py +++ /dev/null @@ -1,285 +0,0 @@ -import warnings -from typing import Callable, Iterable, Optional, Tuple, Union - -import numpy as np -from scipy.optimize import minimize - -from paramak import BlanketFP, RotateStraightShape -from paramak.utils import cut_solid, distance_between_two_points, extend, rotate - - -class BlanketFPPoloidalSegments(BlanketFP): - """Poloidally segmented Blanket inheriting from paramak.BlanketFP. - - Args: - segments_angles: If not None, the segments ends will - be located at these angles. If None and if the constraints - length_limits and nb_segments_limits are not None, segments angles - will be linearly distributed. Else, an optimum configuration - meeting the set requirements will be found. Defaults to None. - num_segments: Number of segments (ignored if segments_angles is not - None). - length_limits: The minimum and maximum acceptable length of the - segments. Ex: (100, 500), (100, None), (None, 300), None, (None, - None). - nb_segments_limits: The minimum and maximum acceptable number of - segments. Ex: (3, 10), (5, None), (None, 7), None, (None, None). - segments_gap: Distance between segments. - """ - - def __init__( - self, - segments_angles: Optional[Iterable[float]] = None, - num_segments: int = 7, - length_limits: Optional[Tuple[Union[float, None], Union[float, None]]] = None, - nb_segments_limits: Optional[Tuple[float, float]] = None, - segments_gap: Optional[float] = 0.0, - **kwargs - ): - super().__init__(**kwargs) - - self.num_segments = num_segments - self.length_limits = length_limits - self.nb_segments_limits = nb_segments_limits - self.segments_angles = segments_angles - self.segments_gap = segments_gap - self.segments_cutters = None - - @property - def segments_angles(self): - return self._segments_angles - - @segments_angles.setter - def segments_angles(self, value): - if value is not None: - if self.start_angle is not None or self.stop_angle is not None: - msg = "start_angle and stop_angle attributes will be " + "ignored if segments_angles is not None" - warnings.warn(msg) - elif self.num_segments is not None: - msg = "num_segment attribute will be ignored if " + "segments_angles is not None" - warnings.warn(msg) - self._segments_angles = value - - @property - def num_segments(self): - return self._num_segments - - @num_segments.setter - def num_segments(self, value): - if value is not None: - self.num_points = value + 1 - self._num_segments = value - - @property - def segments_cutters(self): - self.create_segment_cutters() - return self._segments_cutters - - @segments_cutters.setter - def segments_cutters(self, value): - self._segments_cutters = value - - def get_angles(self): - """Get the poloidal angles of the segments. - - Returns: - list: the angles - """ - if (self.length_limits, self.nb_segments_limits) != (None, None): - angles = segments_optimiser( - self.length_limits, - self.nb_segments_limits, - self.distribution, - (self.start_angle, self.stop_angle), - stop_on_success=True, - ) - elif self.segments_angles is None: - angles = np.linspace(self.start_angle, self.stop_angle, num=self.num_segments + 1) - else: - angles = self.segments_angles - return angles - - def find_points(self): - points = super().find_points(angles=self.get_angles()) - - # every points straight connections - for point in points: - point[-1] = "straight" - self.points = points[:-1] - - def create_solid(self): - solid = super().create_solid() - segments_cutters = self.segments_cutters - if segments_cutters is not None: - solid = cut_solid(solid, segments_cutters) - self.solid = solid - return solid - - def create_segment_cutters(self): - """Creates a shape for cutting the blanket into segments and store it - in segments_cutter attribute - """ - if self.segments_gap > 0: - # initialise main cutting shape - cutting_shape = RotateStraightShape( - rotation_angle=self.rotation_angle, - azimuth_placement_angle=self.azimuth_placement_angle, - union=[], - ) - # add points to the shape to avoid void solid - cutting_shape.points = [ - (self.major_radius, self.vertical_displacement), - ( - self.major_radius + self.minor_radius / 10, - self.vertical_displacement, - ), - ( - self.major_radius + self.minor_radius / 10, - self.vertical_displacement + self.minor_radius / 10, - ), - ( - self.major_radius, - self.vertical_displacement + self.minor_radius / 10, - ), - ] - - # Create cutters for each gap - for inner_point, outer_point in zip(self.inner_points[:-1], self.outer_points[-1::-1]): - # initialise cutter for gap - cutter = RotateStraightShape( - rotation_angle=self.rotation_angle, - azimuth_placement_angle=self.azimuth_placement_angle, - ) - # create rectangle of dimension |AB|*2.6 x self.segments_gap - A = (inner_point[0], inner_point[1]) - B = (outer_point[0], outer_point[1]) - - # increase rectangle length - security_factor = 0.8 - local_thickness = distance_between_two_points(A, B) - A = extend(A, B, -local_thickness * security_factor) - B = extend(A, B, local_thickness * (1 + 2 * security_factor)) - # create points for cutter - points_cutter = [ - A, - B, - rotate(B, extend(B, A, self.segments_gap), angle=-np.pi / 2), - rotate(A, extend(A, B, self.segments_gap), angle=np.pi / 2), - ] - cutter.points = points_cutter - # add cutter to global cutting shape - cutting_shape.union.append(cutter) - - self.segments_cutters = cutting_shape - - -def compute_lengths_from_angles(angles: Iterable[float], distribution: Callable): - """Computes the length of segments between a set of points on a (x,y) - distribution. - - Args: - angles: Contains the angles of the points (degrees) - distribution: function taking an angle as argument and returning (x,y) - coordinates. - - Returns: - list: contains the lengths of the segments. - """ - points = [] - for angle in angles: - points.append(distribution(angle)) - - lengths = [] - for i in range(len(points) - 1): - lengths.append(distance_between_two_points(points[i], points[i + 1])) - return lengths - - -def segments_optimiser(length_limits, nb_segments_limits, distribution, angles, stop_on_success=True): - """Optimiser segmenting a given R(theta), Z(theta) distribution of points - with constraints regarding the number of segments and the length of the - segments. - - Args: - length_limits ((float, float)): The minimum and maximum acceptable - length of the segments. Ex: (100, 500), (100, None), (None, 300), - None, (None, None) - nb_segments_limits ((int, int)): The minimum and maximum acceptable - number of segments. Ex: (3, 10), (5, None), (None, 7), - None, (None, None) - distribution (callable): function taking an angle as argument and - returning (x,y) coordinates. - angles ((float, float)): the start and stop angles of the distribution. - stop_on_sucess (bool, optional): If set to True, the optimiser will - stop as soon as a configuration meets the requirements. - - Returns: - list: list of optimised angles - """ - if length_limits is None: - min_length, max_length = None, None - else: - min_length, max_length = length_limits - - if nb_segments_limits is None: - min_nb_segments, max_nb_segments = None, None - else: - min_nb_segments, max_nb_segments = nb_segments_limits - - if min_length is None: - min_length = 0 - if max_length is None: - max_length = float("inf") - if min_nb_segments is None: - min_nb_segments = 1 - if max_nb_segments is None: - max_nb_segments = 50 - - start_angle, stop_angle = angles - - # define cost function - def cost_function(angles): - angles_with_extremums = [start_angle, *angles, stop_angle] - - lengths = compute_lengths_from_angles(angles_with_extremums, distribution) - - cost = 0 - for length in lengths: - if not min_length <= length <= max_length: - cost += min(abs(min_length - length), abs(max_length - length)) - return cost - - # test for several numbers of segments the best config - best = [float("inf"), []] - - for nb_segments in range(min_nb_segments, max_nb_segments + 1): - # initialise angles to linspace - list_of_angles = np.linspace(start_angle, stop_angle, num=nb_segments + 1) - - # use scipy minimize to find best set of angles - res = minimize(cost_function, list_of_angles[1:-1], method="Nelder-Mead") - - # complete the optimised angles with extrema - optimised_angles = [start_angle] + list(res.x) + [stop_angle] - - # check that the optimised angles meet the lengths requirements - lengths = compute_lengths_from_angles(optimised_angles, distribution) - break_the_rules = False - for length in lengths: - if not min_length <= length <= max_length: - break_the_rules = True - break - if not break_the_rules: - # compare with previous results and get the minimum - # cost function value - best = min(best, [res.fun, optimised_angles], key=lambda x: x[0]) - if stop_on_success: - return optimised_angles - - # return the results - returned_angles = best[1] - if returned_angles == []: - msg = "Couldn't find optimum configuration for Blanket segments" - raise ValueError(msg) - - return returned_angles diff --git a/src/paramak/parametric_components/capsule_vacuum_vessel.py b/src/paramak/parametric_components/capsule_vacuum_vessel.py deleted file mode 100644 index 26e61432c..000000000 --- a/src/paramak/parametric_components/capsule_vacuum_vessel.py +++ /dev/null @@ -1,123 +0,0 @@ -import math -from typing import Tuple - -from paramak import RotateMixedShape - - -class CapsuleVacuumVessel(RotateMixedShape): - """A cylindrical vessel volume with constant thickness that has addition - hemispherical head. - - Arguments: - outer_start_point: the x,z coordinates of the outer bottom of the - vacuum vessel - radius: the radius from which the centres of the vessel meets the outer - circumference. - thickness: the radial thickness of the vessel in cm. - """ - - def __init__( - self, - radius: float, - outer_start_point: Tuple[float, float], - thickness: float, - **kwargs, - ): - self.radius = radius - self.thickness = thickness - self.outer_start_point = outer_start_point[0], outer_start_point[1] - - super().__init__(**kwargs) - - @property - def radius(self): - return self._radius - - @radius.setter - def radius(self, value): - if not isinstance(value, (float, int)): - raise ValueError("VacuumVessel.radius must be a number. Not", value) - if value <= 0: - msg = "VacuumVessel.radius must be a positive number above 0. " f"Not {value}" - raise ValueError(msg) - self._radius = value - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, value): - if not isinstance(value, (float, int)): - msg = f"VacuumVessel.thickness must be a number. Not {value}" - raise ValueError(msg) - if value <= 0: - msg = f"VacuumVessel.thickness must be a positive number above 0. Not {value}" - raise ValueError(msg) - self._thickness = value - - def find_points(self): - """ - Finds the XZ points joined by straight and circle connections that describe the - 2D profile of the vessel shape. - """ - - radius = self.radius - thickness = self.thickness - bottom_outer_x, bottom_outer_y = self.outer_start_point - top_outer_y = bottom_outer_y + (4 * radius) - top_outer_x = bottom_outer_x - inner_r = radius - thickness - (bottom_outer_x, bottom_outer_y, thickness, radius, top_outer_x, top_outer_y, inner_r,) = ( - float(bottom_outer_x), - float(bottom_outer_y), - float(thickness), - float(radius), - float(top_outer_x), - float(top_outer_y), - float(inner_r), - ) - - point_1 = (bottom_outer_x, bottom_outer_y, "circle") - point_3 = (point_1[0] + radius, point_1[1] + radius, "straight") - point_4 = (point_3[0], point_3[1] + radius * 2, "circle") - point_6 = (top_outer_x, top_outer_y, "straight") - point_7 = (point_6[0], point_6[1] - thickness, "circle") - point_9 = (point_4[0] - thickness, point_4[1], "straight") - point_10 = (point_3[0] - thickness, point_3[1], "circle") - point_12 = (point_1[0], point_1[1] + thickness, "straight") - point_2 = ( - (point_1[0]) + (radius * math.cos((3 * math.pi) / 8)), - (point_1[1] + radius) - (radius * math.sin((3 * math.pi) / 8)), - "circle", - ) - point_5 = ( - (point_6[0] + (radius * math.cos((2 * math.pi) / 8))), - (point_6[1] - radius) + (radius * math.sin((2 * math.pi) / 8)), - "circle", - ) - point_8 = ( - (point_7[0] + (inner_r * math.cos((2 * math.pi) / 8))), - (point_7[1] - inner_r) + (inner_r * math.sin((2 * math.pi) / 8)), - "circle", - ) - point_11 = ( - (point_12[0]) + (inner_r * math.cos((3 * math.pi) / 8)), - (point_12[1] + inner_r) - (inner_r * math.sin((3 * math.pi) / 8)), - "circle", - ) - - self.points = [ - point_1, - point_2, - point_3, - point_4, - point_5, - point_6, - point_7, - point_8, - point_9, - point_10, - point_11, - point_12, - ] diff --git a/src/paramak/parametric_components/center_column_circular.py b/src/paramak/parametric_components/center_column_circular.py deleted file mode 100644 index 32bd9e51c..000000000 --- a/src/paramak/parametric_components/center_column_circular.py +++ /dev/null @@ -1,81 +0,0 @@ -from typing import Optional, Tuple - -from paramak import RotateMixedShape - - -class CenterColumnShieldCircular(RotateMixedShape): - """A center column shield volume with a circular outer profile and constant - cylindrical inner profile. - - Args: - height: height of the center column shield (cm). - inner_radius: the inner radius of the center column shield (cm). - mid_radius: the inner radius of the outer hyperbolic profile of the - center column shield (cm). - outer_radius: the outer radius of the center column shield. - name: Defaults to "center_column_shield". - """ - - def __init__( - self, - height: float, - inner_radius: float, - mid_radius: float, - outer_radius: float, - color: Tuple[float, float, float, Optional[float]] = (0.0, 0.333, 0.0), - **kwargs - ) -> None: - - super().__init__(color=color, **kwargs) - - self.height = height - self.inner_radius = inner_radius - self.mid_radius = mid_radius - self.outer_radius = outer_radius - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, inner_radius): - self._inner_radius = inner_radius - - @property - def mid_radius(self): - return self._mid_radius - - @mid_radius.setter - def mid_radius(self, mid_radius): - self._mid_radius = mid_radius - - @property - def outer_radius(self): - return self._outer_radius - - @outer_radius.setter - def outer_radius(self, outer_radius): - self._outer_radius = outer_radius - - def find_points(self): - """Finds the XZ points and connection types (straight and circle) that - describe the 2D profile of the center column shield shape.""" - - points = [ - (self.inner_radius, 0, "straight"), - (self.inner_radius, self.height / 2, "straight"), - (self.outer_radius, self.height / 2, "circle"), - (self.mid_radius, 0, "circle"), - (self.outer_radius, -self.height / 2, "straight"), - (self.inner_radius, -self.height / 2, "straight"), - ] - - self.points = points diff --git a/src/paramak/parametric_components/center_column_cylinder.py b/src/paramak/parametric_components/center_column_cylinder.py deleted file mode 100644 index 599ae5a25..000000000 --- a/src/paramak/parametric_components/center_column_cylinder.py +++ /dev/null @@ -1,96 +0,0 @@ -from typing import Optional, Tuple, Union - -from paramak import RotateStraightShape - - -class CenterColumnShieldCylinder(RotateStraightShape): - """A cylindrical center column shield volume with constant thickness. - - Args: - height: height of the center column shield. - inner_radius: the inner radius of the center column shield. - outer_radius: the outer radius of the center column shield. - center_height: the vertical height of the center of the component. - """ - - def __init__( - self, - height: float, - inner_radius: float, - outer_radius: float, - center_height: float = 0.0, - name: str = "CenterColumnShieldCylinder", - color: Tuple[float, float, float, Optional[float]] = ( - 0.0, - 0.333, - 0.0, - ), - **kwargs, - ) -> None: - - super().__init__(color=color, name=name, **kwargs) - - self.height = height - self.inner_radius = inner_radius - self.outer_radius = outer_radius - self.center_height = center_height - - @property - def center_height(self): - return self._center_height - - @center_height.setter - def center_height(self, value: Union[float, int]): - if not isinstance(value, (int, float)): - msg = f"CenterColumnShieldBlock.center_height should be a float or int. Not a {type(value)}" - raise TypeError(msg) - - self._center_height = value - - @property - def height(self): - return self._height - - @height.setter - def height(self, value: float): - if value is None: - raise ValueError("height of the CenterColumnShieldBlock cannot be None") - self._height = value - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, value: float): - if hasattr(self, "outer_radius"): - if value >= self.outer_radius: - msg = f"inner_radius ({value}) is larger than outer_radius " "({self.outer_radius})" - raise ValueError(msg) - self._inner_radius = value - - @property - def outer_radius(self): - return self._outer_radius - - @outer_radius.setter - def outer_radius(self, value: float): - if hasattr(self, "inner_radius"): - if value <= self.inner_radius: - msg = f"inner_radius ({self.inner_radius}) is larger than " "outer_radius ({value})" - raise ValueError(msg) - - self._outer_radius = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe the - 2D profile of the center column shield shape.""" - - points = [ - (self.inner_radius, self.center_height + self.height / 2), - (self.outer_radius, self.center_height + self.height / 2), - (self.outer_radius, self.center_height + (-self.height / 2)), - (self.inner_radius, self.center_height + (-self.height / 2)), - ] - - self.points = points diff --git a/src/paramak/parametric_components/center_column_flat_top_circular.py b/src/paramak/parametric_components/center_column_flat_top_circular.py deleted file mode 100644 index d53c7869a..000000000 --- a/src/paramak/parametric_components/center_column_flat_top_circular.py +++ /dev/null @@ -1,101 +0,0 @@ -from typing import Optional, Tuple - -from paramak import RotateMixedShape - - -class CenterColumnShieldFlatTopCircular(RotateMixedShape): - """A center column shield volume with a circular outer profile joined to - flat profiles at the top and bottom of the shield, and a constant - cylindrical inner profile. - - Args: - height: height of the center column shield. - arc_height: height of the outer circular profile of the center column - shield. - inner_radius: the inner radius of the center column shield. - mid_radius: the inner radius of the outer circular profile of the center - column shield. - outer_radius: the outer radius of the center column shield. - name: Defaults to "center_column". - """ - - def __init__( - self, - height: float, - arc_height: float, - inner_radius: float, - mid_radius: float, - outer_radius: float, - name: str = "center_column", - color: Tuple[float, float, float, Optional[float]] = ( - 0.0, - 0.333, - 0.0, - ), - **kwargs - ) -> None: - - super().__init__(name=name, color=color, **kwargs) - - self.height = height - self.arc_height = arc_height - self.mid_radius = mid_radius - self.outer_radius = outer_radius - self.inner_radius = inner_radius - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def arc_height(self): - return self._arc_height - - @arc_height.setter - def arc_height(self, arc_height: float): - self._arc_height = arc_height - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, inner_radius: float): - self._inner_radius = inner_radius - - @property - def mid_radius(self): - return self._mid_radius - - @mid_radius.setter - def mid_radius(self, mid_radius: float): - self._mid_radius = mid_radius - - @property - def outer_radius(self): - return self._outer_radius - - @outer_radius.setter - def outer_radius(self, outer_radius: float): - self._outer_radius = outer_radius - - def find_points(self): - """Finds the XZ points and connection types (straight and circle) that - describe the 2D profile of the center column shield shape.""" - - points = [ - (self.inner_radius, 0, "straight"), - (self.inner_radius, self.height / 2, "straight"), - (self.outer_radius, self.height / 2, "straight"), - (self.outer_radius, self.arc_height / 2, "circle"), - (self.mid_radius, 0, "circle"), - (self.outer_radius, -self.arc_height / 2, "straight"), - (self.outer_radius, -self.height / 2, "straight"), - (self.inner_radius, -self.height / 2, "straight"), - ] - - self.points = points diff --git a/src/paramak/parametric_components/center_column_flat_top_hyperbola.py b/src/paramak/parametric_components/center_column_flat_top_hyperbola.py deleted file mode 100644 index e44bf4291..000000000 --- a/src/paramak/parametric_components/center_column_flat_top_hyperbola.py +++ /dev/null @@ -1,111 +0,0 @@ -from typing import Optional, Tuple - -from paramak import RotateMixedShape - - -class CenterColumnShieldFlatTopHyperbola(RotateMixedShape): - """A center column shield volume with a hyperbolic outer profile joined to - flat profiles at the top and bottom of the shield, and a constant - cylindrical inner profile. - - Args: - height: height of the center column shield. - arc_height: height of the outer hyperbolic profile of the center column - shield. - inner_radius: the inner radius of the center column shield. - mid_radius: the inner radius of the outer hyperbolic profile of the - center column shield. - outer_radius: the outer_radius of the center column shield. - name: Defaults to "center_column". - """ - - def __init__( - self, - height: float, - arc_height: float, - inner_radius: float, - mid_radius: float, - outer_radius: float, - name: str = "center_column", - color: Tuple[float, float, float, Optional[float]] = ( - 0.0, - 0.333, - 0.0, - ), - **kwargs - ) -> None: - - super().__init__(name=name, color=color, **kwargs) - - self.height = height - self.arc_height = arc_height - self.mid_radius = mid_radius - self.outer_radius = outer_radius - self.inner_radius = inner_radius - - @property - def height(self): - return self._height - - @height.setter - def height(self, height: float): - self._height = height - - @property - def arc_height(self): - return self._arc_height - - @arc_height.setter - def arc_height(self, arc_height: float): - self._arc_height = arc_height - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, inner_radius: float): - self._inner_radius = inner_radius - - @property - def mid_radius(self): - return self._mid_radius - - @mid_radius.setter - def mid_radius(self, mid_radius: float): - self._mid_radius = mid_radius - - @property - def outer_radius(self): - return self._outer_radius - - @outer_radius.setter - def outer_radius(self, outer_radius: float): - self._outer_radius = outer_radius - - def find_points(self): - """Finds the XZ points and connection types (straight and spline) that - describe the 2D profile of the center column shield shape.""" - - if not self.inner_radius <= self.mid_radius <= self.outer_radius: - raise ValueError( - "inner_radius must be less than mid_radius. \ - mid_radius must be less than outer_radius." - ) - - if self.arc_height >= self.height: - msg = "arc_height ({self.arc_height}) is larger than height " "({self.height})" - raise ValueError(msg) - - points = [ - (self.inner_radius, 0, "straight"), - (self.inner_radius, self.height / 2, "straight"), - (self.outer_radius, self.height / 2, "straight"), - (self.outer_radius, self.arc_height / 2, "spline"), - (self.mid_radius, 0, "spline"), - (self.outer_radius, -self.arc_height / 2, "straight"), - (self.outer_radius, -self.height / 2, "straight"), - (self.inner_radius, -self.height / 2, "straight"), - ] - - self.points = points diff --git a/src/paramak/parametric_components/center_column_hyperbola.py b/src/paramak/parametric_components/center_column_hyperbola.py deleted file mode 100644 index f94860ec0..000000000 --- a/src/paramak/parametric_components/center_column_hyperbola.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Optional, Tuple - -from paramak import RotateMixedShape - - -class CenterColumnShieldHyperbola(RotateMixedShape): - """A center column shield volume with a hyperbolic outer profile and - constant cylindrical inner profile. - - Args: - height: height of the center column shield. - inner_radius: the inner radius of the center column shield. - mid_radius: the inner radius of the outer hyperbolic profile of - the center column shield. - outer_radius: the outer radius of the center column shield. - name: Defaults to "center_column". - """ - - def __init__( - self, - height: float, - inner_radius: float, - mid_radius: float, - outer_radius: float, - name: str = "center_column", - color: Tuple[float, float, float, Optional[float]] = ( - 0.0, - 0.333, - 0.0, - ), - **kwargs - ) -> None: - - super().__init__(name=name, color=color, **kwargs) - - self.height = height - self.inner_radius = inner_radius - self.mid_radius = mid_radius - self.outer_radius = outer_radius - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, inner_radius): - self._inner_radius = inner_radius - - @property - def mid_radius(self): - return self._mid_radius - - @mid_radius.setter - def mid_radius(self, mid_radius): - self._mid_radius = mid_radius - - @property - def outer_radius(self): - return self._outer_radius - - @outer_radius.setter - def outer_radius(self, outer_radius): - self._outer_radius = outer_radius - - def find_points(self): - """Finds the XZ points and connection types (straight and spline) that - describe the 2D profile of the center column shield shape.""" - - if not self.inner_radius <= self.mid_radius <= self.outer_radius: - raise ValueError( - "inner_radius must be less than mid radius. \ - mid_radius must be less than outer_radius." - ) - - points = [ - (self.inner_radius, 0, "straight"), - (self.inner_radius, self.height / 2, "straight"), - (self.outer_radius, self.height / 2, "spline"), - (self.mid_radius, 0, "spline"), - (self.outer_radius, -self.height / 2, "straight"), - (self.inner_radius, -self.height / 2, "straight"), - ] - - self.points = points diff --git a/src/paramak/parametric_components/center_column_plasma_dependant.py b/src/paramak/parametric_components/center_column_plasma_dependant.py deleted file mode 100644 index 0ee33b1fb..000000000 --- a/src/paramak/parametric_components/center_column_plasma_dependant.py +++ /dev/null @@ -1,147 +0,0 @@ -from paramak import Plasma, RotateMixedShape - - -class CenterColumnShieldPlasmaHyperbola(RotateMixedShape): - """A center column shield volume with a curvature controlled by the shape - of the plasma and offsets specified at the plasma center and edges. Shield - thickness is controlled by the relative values of the shield offsets and - inner radius. - - Args: - height: height of the center column shield. - inner_radius: the inner radius of the center column shield. - mid_offset: the offset of the shield from the plasma at the plasma - center. - edge_offset: the offset of the shield from the plasma at the plasma - edge. - major_radius: the major radius of the plasma. Defaults to 450.0. - minor_radius: the minor radius of the plasma. Defaults to 150.0. - triangularity: the triangularity of the plasma. Defaults to 0.55. - elongation: the elongation of the plasma. Defaults to 2.0. - """ - - def __init__( - self, - height: float, - inner_radius: float, - mid_offset: float, - edge_offset: float, - major_radius: float = 450.0, - minor_radius: float = 150.0, - triangularity: float = 0.55, - elongation: float = 2.0, - **kwargs, - ) -> None: - - super().__init__(**kwargs) - - self.major_radius = major_radius - self.minor_radius = minor_radius - self.triangularity = triangularity - self.elongation = elongation - self.height = height - self.inner_radius = inner_radius - self.mid_offset = mid_offset - self.edge_offset = edge_offset - - @property - def major_radius(self): - return self._major_radius - - @major_radius.setter - def major_radius(self, value): - self._major_radius = value - - @property - def minor_radius(self): - return self._minor_radius - - @minor_radius.setter - def minor_radius(self, value): - self._minor_radius = value - - @property - def triangularity(self): - return self._triangularity - - @triangularity.setter - def triangularity(self, value): - self._triangularity = value - - @property - def elongation(self): - return self._elongation - - @elongation.setter - def elongation(self, value): - self._elongation = value - - @property - def height(self): - return self._height - - @height.setter - def height(self, value): - self._height = value - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, value): - self._inner_radius = value - - @property - def mid_offset(self): - return self._mid_offset - - @mid_offset.setter - def mid_offset(self, value): - self._mid_offset = value - - @property - def edge_offset(self): - return self._edge_offset - - @edge_offset.setter - def edge_offset(self, value): - self._edge_offset = value - - def find_points(self): - """Finds the XZ points and connection types (straight and spline) that - describe the 2D profile of the center column shield shape.""" - - plasma = Plasma() - - plasma.major_radius = self.major_radius - plasma.minor_radius = self.minor_radius - plasma.triangularity = self.triangularity - plasma.elongation = self.elongation - plasma.rotation_angle = self.rotation_angle - plasma.find_points() - - plasma_height = abs(plasma.high_point[1]) + abs(plasma.low_point[1]) - if self.height <= plasma_height: - msg = f"Center column height ({self.height}) is smaller than " "plasma height ({plasma_height}" - raise ValueError(msg) - - if self.inner_radius >= plasma.inner_equatorial_point[0] - self.mid_offset: - raise ValueError("Inner radius is too large") - - points = [ - (self.inner_radius, 0, "straight"), - (self.inner_radius, self.height / 2, "straight"), - (plasma.high_point[0] - self.edge_offset, self.height / 2, "straight"), - (plasma.high_point[0] - self.edge_offset, plasma.high_point[1], "spline"), - ( - plasma.inner_equatorial_point[0] - self.mid_offset, - plasma.inner_equatorial_point[1], - "spline", - ), - (plasma.low_point[0] - self.edge_offset, plasma.low_point[1], "straight"), - (plasma.low_point[0] - self.edge_offset, -1 * self.height / 2, "straight"), - (self.inner_radius, -1 * self.height / 2, "straight"), - ] - - self.points = points diff --git a/src/paramak/parametric_components/circular_port.py b/src/paramak/parametric_components/circular_port.py deleted file mode 100644 index 4e38af9b6..000000000 --- a/src/paramak/parametric_components/circular_port.py +++ /dev/null @@ -1,137 +0,0 @@ -from typing import Optional, Tuple -from paramak import Shape -from cadquery import Workplane -from paramak.utils import calculate_wedge_cut - - -class CircularPort(Shape): - """Creates an extruded pipe with a flange end and optional. - - Args: - inner_radius: inner_radius (cm) of tubular section. - distance: extruded distance (cm) of the tubular section. - wall_thickness: the radial thickness of the tubular section wall. - flange_overhang: the distance of the flange overhang or lip. - flange_thickness: the thickness of the flange, should be a positive - number. Set to None if no blank flange is required. - blank_flange_thickness: the thickness of the blank flange - center_point: center point of the port cutter. Defaults to (0, 0). - workplane: workplane in which the port cutters are created. Defaults - to "ZY". - rotation_axis: axis around which the port cutters are rotated and - placed. Defaults to "Z". - extrusion_start_offset: the distance between 0 and the start of the - extrusion. Defaults to 1.. - name: defaults to "circular_port_cutter". - """ - - def __init__( - self, - inner_radius: float = 30, - distance: float = 20, - wall_thickness: float = 2, - flange_overhang: float = 10, - flange_thickness: float = 5, - flange_gap: float = 0, - blank_flange_thickness: float = 5, - workplane: str = "ZY", - rotation_axis: str = "Z", - extrusion_start_offset: float = 100, - center_point: tuple = (0, 0), - name: str = "circular_port_cutter", - color: Tuple[float, float, float, Optional[float]] = ( - 0.984, - 0.603, - 0.6, - ), - rotation_angle: float = 360, - **kwargs, - ): - super().__init__(color=color, name=name, **kwargs) - - self.inner_radius = inner_radius - self.distance = distance - self.wall_thickness = wall_thickness - self.flange_overhang = flange_overhang - self.flange_thickness = flange_thickness - self.flange_gap = flange_gap - self.blank_flange_thickness = blank_flange_thickness - self.workplane = workplane - self.rotation_axis = rotation_axis - self.extrusion_start_offset = extrusion_start_offset - self.center_point = center_point - self.rotation_angle = rotation_angle - - def find_points(self): - self.points = [self.center_point] - - def create_solid(self): - """Creates a extruded 3d solid using points with circular edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - extrusion_offset = -self.extrusion_start_offset - flange_gap = -self.flange_gap - extrusion_distance = -self.distance - flange_thickness = self.flange_thickness - - inner_wire = ( - Workplane(self.workplane) - .workplane(offset=extrusion_offset) - .moveTo(self.points[0][0], self.points[0][1]) - .circle(self.inner_radius) - ) - inner_solid = inner_wire.extrude(until=extrusion_distance - flange_thickness, both=False) - - outer_wire = ( - Workplane(self.workplane) - .workplane(offset=extrusion_offset) - .moveTo(self.points[0][0], self.points[0][1]) - .circle(self.inner_radius + self.wall_thickness) - ) - outer_solid = outer_wire.extrude(until=extrusion_distance, both=False) - - flange_wire = ( - Workplane(self.workplane) - .workplane(offset=extrusion_offset + extrusion_distance) - .moveTo(self.points[0][0], self.points[0][1]) - .circle(self.inner_radius + self.wall_thickness + self.flange_overhang) - ) - flange_solid = flange_wire.extrude(until=flange_thickness, both=False) - - solid = outer_solid.cut(inner_solid) - flange_solid = flange_solid.cut(inner_solid) - solid = solid.union(flange_solid) - - blank_flange_thickness = self.blank_flange_thickness - - if blank_flange_thickness > 0: - blank_flange_wire = ( - Workplane(self.workplane) - .workplane(offset=extrusion_offset + extrusion_distance + flange_gap - self.blank_flange_thickness) - .moveTo(self.points[0][0], self.points[0][1]) - .circle(self.inner_radius + self.wall_thickness + self.flange_overhang) - ) - blank_flange_solid = blank_flange_wire.extrude(until=blank_flange_thickness, both=False) - solid = solid.union(blank_flange_solid) - elif blank_flange_thickness < 0: - msg = f"blank_flange_thickness should be larger than 0 or None. Not {blank_flange_thickness}" - raise ValueError(msg) - - # TODO combine all wires into one - # self.wire = solid.Wires() - - solid = self.rotate_solid(solid) - - # calculates the size of the component as these attributes are used - # when making the cutting wedge - self.radius = self.extrusion_start_offset + self.distance + self.flange_thickness + blank_flange_thickness - self.height = self.center_point[0] + self.inner_radius + self.wall_thickness - - cutting_wedge = calculate_wedge_cut(self) - solid = self.perform_boolean_operations(solid, wedge_cut=cutting_wedge) - self.solid = solid - - return solid diff --git a/src/paramak/parametric_components/constant_thickness_dome.py b/src/paramak/parametric_components/constant_thickness_dome.py deleted file mode 100644 index d07d0d015..000000000 --- a/src/paramak/parametric_components/constant_thickness_dome.py +++ /dev/null @@ -1,215 +0,0 @@ -import math -import numbers - -import cadquery as cq -from paramak import CuttingWedge, RotateMixedShape, RotateStraightShape, Shape - - -class ConstantThicknessDome(RotateMixedShape): - """A cylindrical vessel volume with constant thickness with a simple dished - head. This style of tank head has no knuckle radius or straight flange. The - dished shape is made from a chord of a circle. - - Arguments: - thickness: the radial thickness of the dome. - chord_center_height: the vertical position of the chord center - chord_width: the width of the chord base - chord_height: the height of the chord which is also distance between - the chord_center_height and the inner surface of the dome - upper_or_lower: Curves the dish with a positive or negative direction - to allow the upper section or lower section of vacuum vessel - domes to be made. - name: the name of the shape, used in the graph legend and as a - filename prefix when exporting. - """ - - def __init__( - self, - thickness: float = 10, - chord_center_height: float = 0, - chord_width: float = 100, - chord_height: float = 20, - upper_or_lower: str = "upper", - name: str = "constant_thickness_dome", - **kwargs, - ): - - self.thickness = thickness - self.chord_center_height = chord_center_height - self.chord_width = chord_width - self.chord_height = chord_height - self.upper_or_lower = upper_or_lower - self.name = name - - super().__init__(name=name, **kwargs) - - @property - def chord_width(self): - return self._chord_width - - @chord_width.setter - def chord_width(self, value: float): - if not isinstance(value, numbers.Number): - raise ValueError("ConstantThicknessDome.chord_width must be a float. Not", value) - if value <= 0: - msg = f"ConstantThicknessDome.chord_width must be a positive number above 0. Not {value}" - raise ValueError(msg) - self._chord_width = value - - @property - def chord_height(self): - return self._chord_height - - @chord_height.setter - def chord_height(self, value: float): - if not isinstance(value, numbers.Number): - raise ValueError("ConstantThicknessDome.chord_height must be a float. Not", value) - if value <= 0: - msg = f"ConstantThicknessDome.chord_height must be a positive number above 0. Not {value}" - raise ValueError(msg) - self._chord_height = value - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, value: float): - if not isinstance(value, numbers.Number): - msg = f"VacuumVessel.thickness must be a float. Not {value}" - raise ValueError(msg) - if value <= 0: - msg = f"VacuumVessel.thickness must be a positive number above 0. Not {value}" - raise ValueError(msg) - self._thickness = value - - def find_points(self): - """ - Finds the XZ points joined by straight and circle connections that - describe the 2D profile of the vessel shape. - """ - - # Note these points are not used in the normal way when constructing - # the solid - # - # 6 - - # | - - # 7 - - - # - - - # - 3 - # - | - # cc 1 -- 2 - # chord center - # - # - # cp - # center point - # - # - # - # - # cc 1 -- 2 - # - | - # - 3 - # - - - # 7 - - - # | - - # 6 - - # far side - - if self.chord_height * 2 >= self.chord_width: - msg = ( - "ConstantThicknessDome requires that the self.chord_width " - "is at least 2 times as large as the chord height" - ) - raise ValueError(msg) - - radius_of_sphere = ((math.pow(self.chord_width, 2)) + (4.0 * math.pow(self.chord_height, 2))) / ( - 8 * self.chord_height - ) - - # TODO set to 0 for now, add ability to shift the center of the chord left and right - chord_center = (0, self.chord_center_height) - - point_1 = (chord_center[0] + (self.chord_width / 2), chord_center[1], "straight") - - if self.upper_or_lower == "upper": - center_point = (chord_center[0], chord_center[1] + self.chord_height - radius_of_sphere) - inner_tri_angle = math.atan((center_point[1] - chord_center[1]) / (self.chord_width / 2)) - outer_tri_adj = math.cos(inner_tri_angle) * self.thickness - point_2 = (point_1[0] + self.thickness, point_1[1], "straight") - outer_tri_opp = math.sqrt(math.pow(self.thickness, 2) - math.pow(outer_tri_adj, 2)) - point_7 = (chord_center[0], chord_center[1] + radius_of_sphere, "straight") - point_6 = (chord_center[0], chord_center[1] + radius_of_sphere + self.thickness, "straight") - self.far_side = (center_point[0], center_point[1] - (radius_of_sphere + self.thickness)) - point_3 = (point_2[0], point_2[1] + outer_tri_opp, "straight") - elif self.upper_or_lower == "lower": - center_point = (chord_center[0], chord_center[1] - self.chord_height + radius_of_sphere) - inner_tri_angle = math.atan((center_point[1] - chord_center[1]) / (self.chord_width / 2)) - outer_tri_adj = math.cos(inner_tri_angle) * self.thickness - point_2 = (point_1[0] + self.thickness, point_1[1], "straight") - outer_tri_opp = math.sqrt(math.pow(self.thickness, 2) - math.pow(outer_tri_adj, 2)) - point_7 = (chord_center[0], chord_center[1] - radius_of_sphere, "straight") - point_6 = (chord_center[0], chord_center[1] - (radius_of_sphere + self.thickness), "straight") - self.far_side = (center_point[0], center_point[1] + radius_of_sphere + self.thickness) - point_3 = (point_2[0], point_2[1] - outer_tri_opp, "straight") - else: - msg = f'upper_or_lower should be either "upper" or "lower". Not {self.upper_or_lower}' - raise ValueError(msg) - - self.points = [point_1, point_2, point_3, point_6, point_7] - - def create_solid(self): - """Creates a rotated 3d solid using points with circular edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - radius_of_sphere = ((math.pow(self.chord_width, 2)) + (4.0 * math.pow(self.chord_height, 2))) / ( - 8 * self.chord_height - ) - - # TODO set to 0 for now, add ability to shift the center of the chord left and right - chord_center = (0, self.chord_center_height) - - if self.upper_or_lower == "upper": - center_point = (chord_center[0], chord_center[1] + self.chord_height - radius_of_sphere) - far_side = (center_point[0], center_point[1] - (radius_of_sphere + self.thickness)) - elif self.upper_or_lower == "lower": - center_point = (chord_center[0], chord_center[1] - self.chord_height + radius_of_sphere) - far_side = (center_point[0], center_point[1] + radius_of_sphere + self.thickness) - else: - raise ValueError("self.upper_or_lower") - - big_sphere = ( - cq.Workplane(self.workplane) - .moveTo(center_point[0], center_point[1]) - .sphere(radius_of_sphere + self.thickness) - ) - small_sphere = cq.Workplane(self.workplane).moveTo(center_point[0], center_point[1]).sphere(radius_of_sphere) - - outer_cylinder_cutter = RotateStraightShape( - workplane=self.workplane, - points=( - (chord_center[0], chord_center[1]), # cc - (self.points[1][0], self.points[1][1]), # point 2 - (self.points[2][0], self.points[2][1]), # point 3 - (self.points[2][0] + radius_of_sphere, self.points[2][1]), # point 3 wider - (self.points[2][0] + radius_of_sphere, far_side[1]), - far_side, - ), - rotation_angle=360, - ) - - cap = Shape() - cap.solid = big_sphere.cut(small_sphere) - - height = 2 * (radius_of_sphere + abs(center_point[1]) + self.thickness) - radius = 2 * (radius_of_sphere + abs(center_point[0]) + self.thickness) - cutter = CuttingWedge(height=height, radius=radius, rotation_angle=self.rotation_angle) - - cap.solid = cap.solid.intersect(cutter.solid) - cap.solid = cap.solid.cut(outer_cylinder_cutter.solid) - - self.solid = cap.solid diff --git a/src/paramak/parametric_components/coolant_channel_ring_curved.py b/src/paramak/parametric_components/coolant_channel_ring_curved.py deleted file mode 100644 index 041ecae56..000000000 --- a/src/paramak/parametric_components/coolant_channel_ring_curved.py +++ /dev/null @@ -1,89 +0,0 @@ -import numpy as np - -from paramak import SweepCircleShape - - -class CoolantChannelRingCurved(SweepCircleShape): - """A ring of equally-spaced curved circular coolant channels with - constant thickness. - - Args: - height: height of each coolant channel in ring. - channel_radius: radius of each coolant channel in ring. - number_of_coolant_channels: number of coolant channels in ring. - ring_radius: radius of coolant channel ring. - start_angle: angle at which the first channel in the ring is placed. - Defaults to 0.0. - rotation_axis: azimuthal axis around which the separate coolant channels - are placed. Default calculated by workplane and path_workplane. - workplane (str, optional): plane in which the cross-sections of the - coolant channels lie. Defaults to "XY". - path_workplane (str, optional): plane in which the cross-sections of the - coolant channels are swept. Defaults to "XZ". - force_cross_section (bool, optional): forces coolant channels to have a - more constant cross-section along their curve. Defaults to False. - """ - - def __init__( - self, - height: float, - channel_radius: float, - number_of_coolant_channels: int, - ring_radius: float, - mid_offset: float, - start_angle: float = 0.0, - **kwargs - ) -> None: - - self.ring_radius = ring_radius - self.mid_offset = mid_offset - self.height = height - self.start_angle = start_angle - - super().__init__(path_points=self.path_points, radius=channel_radius, **kwargs) - - self.channel_radius = channel_radius - self.number_of_coolant_channels = number_of_coolant_channels - - @property - def azimuth_placement_angle(self): - self.find_azimuth_placement_angle() - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self._azimuth_placement_angle = value - - @property - def path_points(self): - self.find_path_points() - return self._path_points - - @path_points.setter - def path_points(self, value): - self._path_points = value - - def find_azimuth_placement_angle(self): - """Calculates the azimuth placement angles based on the number of - coolant channels.""" - - angles = list( - np.linspace( - 0 + self.start_angle, - 360 + self.start_angle, - self.number_of_coolant_channels, - endpoint=False, - ) - ) - - self.azimuth_placement_angle = angles - - def find_path_points(self): - - path_points = [ - (self.ring_radius, -self.height / 2), - (self.ring_radius + self.mid_offset, 0), - (self.ring_radius, self.height / 2), - ] - - self.path_points = path_points diff --git a/src/paramak/parametric_components/coolant_channel_ring_straight.py b/src/paramak/parametric_components/coolant_channel_ring_straight.py deleted file mode 100644 index 9f7c6bd13..000000000 --- a/src/paramak/parametric_components/coolant_channel_ring_straight.py +++ /dev/null @@ -1,71 +0,0 @@ -from typing import Optional - -import numpy as np - -from paramak import ExtrudeCircleShape - - -class CoolantChannelRingStraight(ExtrudeCircleShape): - """A ring of equally-spaced straight circular coolant channels with - constant thickness. - - Args: - height: height of each coolant channel in ring. - channel_radius: radius of each coolant channel in ring. - number_of_coolant_channels: number of coolant channels in ring. - ring radius: radius of coolant channel ring. - start_angle: angle at which the first channel in the ring is placed. - Defaults to 0.0. - rotation_axis (str, optional): azimuthal axis around which the separate - coolant channels are placed. - workplane (str, optional): plane in which the cross-sections of the - coolant channels lie. Defaults to "XY". - """ - - def __init__( - self, - height: float, - channel_radius: float, - number_of_coolant_channels: int, - ring_radius: float, - start_angle: Optional[float] = 0.0, - **kwargs - ) -> None: - - super().__init__(distance=height, radius=channel_radius, **kwargs) - - self.height = height - self.channel_radius = channel_radius - self.number_of_coolant_channels = number_of_coolant_channels - self.ring_radius = ring_radius - self.start_angle = start_angle - - @property - def azimuth_placement_angle(self): - self.find_azimuth_placement_angle() - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self._azimuth_placement_angle = value - - def find_azimuth_placement_angle(self): - """Calculates the azimuth placement angles based on the number of - coolant channels.""" - - angles = list( - np.linspace( - 0 + self.start_angle, - 360 + self.start_angle, - self.number_of_coolant_channels, - endpoint=False, - ) - ) - - self.azimuth_placement_angle = angles - - def find_points(self): - - points = [(self.ring_radius, 0)] - - self.points = points diff --git a/src/paramak/parametric_components/cutting_wedge.py b/src/paramak/parametric_components/cutting_wedge.py deleted file mode 100644 index 7f9011444..000000000 --- a/src/paramak/parametric_components/cutting_wedge.py +++ /dev/null @@ -1,46 +0,0 @@ -from paramak import RotateStraightShape - - -class CuttingWedge(RotateStraightShape): - """Creates a wedge from height, radius and rotation angle arguments than - can be useful for cutting sector models. - - Args: - height: the vertical (z axis) height of the coil (cm). - radius: the horizontal (x axis) width of the coil (cm). - rotation_angle: Defaults to 180.0. - """ - - def __init__(self, height: float, radius: float, rotation_angle: float = 180.0, **kwargs) -> None: - - super().__init__(rotation_angle=rotation_angle, **kwargs) - - self.height = height - self.radius = radius - - @property - def height(self): - return self._height - - @height.setter - def height(self, value: float): - self._height = value - - @property - def radius(self): - return self._radius - - @radius.setter - def radius(self, value: float): - self._radius = value - - def find_points(self): - - points = [ - (0, self.height / 2), - (self.radius, self.height / 2), - (self.radius, -self.height / 2), - (0, -self.height / 2), - ] - - self.points = points diff --git a/src/paramak/parametric_components/cutting_wedge_fs.py b/src/paramak/parametric_components/cutting_wedge_fs.py deleted file mode 100644 index cb474bd12..000000000 --- a/src/paramak/parametric_components/cutting_wedge_fs.py +++ /dev/null @@ -1,117 +0,0 @@ -from collections.abc import Iterable -from operator import itemgetter - -from paramak import CuttingWedge - -SAFETY_FACTOR = 3 - - -class CuttingWedgeFS(CuttingWedge): - """Creates a wedge from a Shape that can be useful for cutting sector - models. - - Args: - shape (paramak.Shape): a paramak.Shape object that is used to find the - height and radius of the wedge - """ - - def __init__(self, shape, **kwargs): - self.shape = shape - super().__init__(height=self.height, radius=self.radius, **kwargs) - - @property - def shape(self): - return self._shape - - @shape.setter - def shape(self, value): - if value.rotation_angle == 360: - msg = "cutting_wedge cannot be created, rotation_angle must be " "less than 360 degrees" - raise ValueError(msg) - self._shape = value - - @property - def radius(self): - self.find_radius_height() - return self._radius - - @radius.setter - def radius(self, value): - self._radius = value - - @property - def height(self): - self.find_radius_height() - return self._height - - @height.setter - def height(self, value: float): - self._height = value - - @property - def rotation_angle(self): - self.rotation_angle = 360 - self.shape.rotation_angle - return self._rotation_angle - - @rotation_angle.setter - def rotation_angle(self, value: float): - self._rotation_angle = value - - @property - def workplane(self): - workplanes = ["XY", "XZ", "YZ"] - for wp in workplanes: - if self.shape.get_rotation_axis()[1] in wp: - self.workplane = wp - break - return self._workplane - - @workplane.setter - def workplane(self, value: str): - self._workplane = value - - @property - def rotation_axis(self): - self.rotation_axis = self.shape.rotation_axis - return self._rotation_axis - - @rotation_axis.setter - def rotation_axis(self, value: str): - self._rotation_axis = value - - @property - def azimuth_placement_angle(self): - if isinstance(self.shape.azimuth_placement_angle, Iterable): - self.azimuth_placement_angle = self.shape.rotation_angle - else: - self.azimuth_placement_angle = self.shape.azimuth_placement_angle + self.shape.rotation_angle - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self._azimuth_placement_angle = value - - def find_radius_height(self): - shape = self.shape - if shape.rotation_angle == 360: - msg = ( - "cutting_wedge cannot be created, the shapes rotation_angle " - f"must be less than 360 degrees. shape.rotation_angle is {shape.rotation_angle}" - ) - raise ValueError(msg) - shape_points = shape.points - if hasattr(shape, "radius") and len(shape_points) == 1: - max_x = shape_points[0][0] + shape.radius - max_y = shape_points[0][1] + shape.radius - - elif len(shape_points) > 1: - max_x = max(shape_points, key=itemgetter(0))[0] - if shape.get_rotation_axis()[1] not in shape.workplane and hasattr(shape, "distance"): - max_y = shape.distance - else: - max_y = max(shape_points, key=itemgetter(1))[1] - - else: - raise ValueError("cutting_wedge cannot be created") - self.radius = SAFETY_FACTOR * max_x - self.height = SAFETY_FACTOR * max_y diff --git a/src/paramak/parametric_components/dished_vacuum_vessel.py b/src/paramak/parametric_components/dished_vacuum_vessel.py deleted file mode 100644 index d1308a866..000000000 --- a/src/paramak/parametric_components/dished_vacuum_vessel.py +++ /dev/null @@ -1,122 +0,0 @@ -from cadquery import Compound -from paramak import RotateMixedShape, CenterColumnShieldCylinder, ConstantThicknessDome - - -class DishedVacuumVessel(RotateMixedShape): - """A cylindrical vessel volume with constant thickness with a simple dished - head. This style of tank head has no knuckle radius or straight flange. - - Arguments: - radius: the radius from which the centres of the vessel meets the outer - circumference. - center_point: the x,z coordinates of the center of the vessel - dish_height: the height of the dish section. This is also the chord - heigh of the circle used to make the dish. - cylinder_height: the height of the cylindrical section of the vacuum - vessel. - thickness: the radial thickness of the vessel in cm. - """ - - def __init__( - self, - radius: float = 300, - center_point: float = 0, - dish_height: float = 50, - cylinder_height: float = 400, - thickness: float = 15, - name: str = "dished_vessel", - **kwargs, - ): - self.radius = radius - self.center_point = center_point - self.dish_height = dish_height - self.cylinder_height = cylinder_height - self.thickness = thickness - self.name = name - - super().__init__(name=name, **kwargs) - - @property - def radius(self): - return self._radius - - @radius.setter - def radius(self, value: float): - if not isinstance(value, (float, int)): - raise ValueError("VacuumVessel.radius must be a number. Not", value) - if value <= 0: - msg = "VacuumVessel.radius must be a positive number above 0. " f"Not {value}" - raise ValueError(msg) - self._radius = value - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, value: float): - if not isinstance(value, (float, int)): - msg = f"VacuumVessel.thickness must be a number. Not {value}" - raise ValueError(msg) - if value <= 0: - msg = f"VacuumVessel.thickness must be a positive number above 0. Not {value}" - raise ValueError(msg) - self._thickness = value - - def create_solid(self): - """Creates a rotated 3d solid using points with circular edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - # - # - - - # - - # - - - - # - - - # - - - # - | - # | | - # | | - # | | - # c,p | | - # | | - # | | - # | | - # - | - # - - - # - - - # - - - - # - - # - - - # - - cylinder_section = CenterColumnShieldCylinder( - height=self.cylinder_height, - inner_radius=self.radius - self.thickness, - outer_radius=self.radius, - center_height=self.center_point, - rotation_angle=self.rotation_angle, - ) - - upper_dome_section = ConstantThicknessDome( - thickness=self.thickness, - chord_center_height=self.center_point + 0.5 * self.cylinder_height, - chord_width=(self.radius - self.thickness) * 2, - chord_height=self.dish_height, - upper_or_lower="upper", - rotation_angle=self.rotation_angle, - ) - - lower_dome_section = ConstantThicknessDome( - thickness=self.thickness, - chord_center_height=self.center_point - 0.5 * self.cylinder_height, - chord_width=(self.radius - self.thickness) * 2, - chord_height=self.dish_height, - upper_or_lower="lower", - rotation_angle=self.rotation_angle, - ) - - shapes = [lower_dome_section.solid.val(), upper_dome_section.solid.val(), cylinder_section.solid.val()] - self.solid = Compound.makeCompound(shapes) diff --git a/src/paramak/parametric_components/divertor_ITER.py b/src/paramak/parametric_components/divertor_ITER.py deleted file mode 100644 index cd6ecfa1b..000000000 --- a/src/paramak/parametric_components/divertor_ITER.py +++ /dev/null @@ -1,235 +0,0 @@ -import math -from typing import Tuple - -import numpy as np -from paramak import RotateMixedShape, distance_between_two_points, extend, rotate - - -class ITERtypeDivertor(RotateMixedShape): - """Creates an ITER-like divertor with inner and outer vertical targets and - dome - - Args: - anchors: xz coordinates of points at the top of vertical targets. - coverages: coverages (anticlockwise) in degrees of the circular parts - of vertical targets. - radii: radii (cm) of circular parts of the vertical targets. - lengths: leg length (cm) of the vertical targets. - dome: if set to False, the dome will not be created. - dome_height: distance (cm) between the dome base and lower points. - dome_length: length of the dome. - dome_thickness: thickness of the dome. - dome_pos: relative location of the dome between vertical targets - (0 inner, 1 outer). Ex: 0.5 will place the dome in between the - targets. - tilts ((float, float), optional): tilt angles (anticlockwise) in - degrees for the vertical targets. - """ - - def __init__( - self, - anchors: Tuple[Tuple[float, float], Tuple[float, float]] = ((450, -300), (561, -367)), - coverages: Tuple[float, float] = (90, 180), - radii: Tuple[float, float] = (50, 25), - lengths: Tuple[float, float] = (78, 87), - dome: bool = True, - dome_height: float = 43, - dome_length: float = 66, - dome_thickness: float = 10, - dome_pos: float = 0.5, - tilts: Tuple[float, float] = (-27, 0), - **kwargs - ): - - super().__init__(**kwargs) - - self.ivt_anchor, self.ovt_anchor = anchors - self.ivt_coverage, self.ovt_coverage = coverages - self.ivt_radius, self.ovt_radius = radii - self.ivt_length, self.ovt_length = lengths - self.ivt_tilt, self.ovt_tilt = tilts - self.dome = dome - self.dome_length = dome_length - self.dome_height = dome_height - self.dome_pos = dome_pos - self.dome_thickness = dome_thickness - - def _create_vertical_target_points( - self, anchor: Tuple[float, float], coverage: float, tilt: float, radius: float, length: float - ): - """Creates a list of points for a vertical target - - Args: - anchor: xz coordinates of point at the top of the vertical target. - coverage: coverages (anticlockwise) in degrees of the circular part - of the vertical target. - tilt: tilt angle (anticlockwise) in degrees for the vertical target. - radius: radius (cm) of circular part of the vertical target. - length: leg length (cm) of the vertical target. - - Returns: - list: list of x y coordinates - """ - points = [] - base_circle_inner = anchor[0] + radius, anchor[1] - A = rotate(base_circle_inner, anchor, coverage) - A_prime = rotate(base_circle_inner, anchor, coverage / 2) - c_coord = (anchor[0], anchor[1] - length) - - A = rotate(anchor, A, tilt) - A_prime = rotate(anchor, A_prime, tilt) - c_coord = rotate(anchor, c_coord, tilt) - # upper inner A - points.append([A[0], A[1]]) - # A' - points.append([A_prime[0], A_prime[1]]) - # B - points.append([anchor[0], anchor[1]]) - # C - points.append([c_coord[0], c_coord[1]]) - return points - - def _create_dome_points( - self, - c_coord: Tuple[float, float], - F: Tuple[float, float], - dome_length: float, - dome_height: float, - dome_thickness: float, - dome_pos: float, - ): - """Creates a list of points for the dome alongside with their - connectivity - - Args: - c_coord: coordinate of inner end of the dome - F: coordinate of outer end of the dome - dome_length: dome length (cm) - dome_height: dome height (cm) - dome_thickness: dome thickness (cm) - dome_pos: position of the dome between the two ends. - - Returns: - list: list of points with connectivity - ([[x, z, 'connection_type'], [...]]) - """ - points = [] - - dome_base = extend(c_coord, F, dome_pos * distance_between_two_points(F, c_coord)) - dome_lower_point = extend(dome_base, rotate(dome_base, c_coord, -math.pi / 2), dome_height) - - d_prime = extend(dome_base, dome_lower_point, dome_height + dome_thickness) - D = extend( - dome_lower_point, - rotate(dome_lower_point, d_prime, math.pi / 2), - dome_length / 2, - ) - E = extend( - dome_lower_point, - rotate(dome_lower_point, d_prime, -math.pi / 2), - dome_length / 2, - ) - - # D - points.append([D[0], D[1], "circle"]) - - # D' - points.append([d_prime[0], d_prime[1], "circle"]) - - # E - points.append([E[0], E[1], "straight"]) - return points - - def _create_casing_points( - self, - anchors: Tuple[float, float], - c_coord: Tuple[float, float], - F: Tuple[float, float], - targets_lengths: Tuple[float, float], - ): - """Creates a list of points for the casing alongside with their - connectivity - - Args: - anchors: xz coordinates of points at the top of vertical targets. - c_coord: coordinate of inner end of the dome - F: coordinate of outer end of the dome - targets_lengths: leg lengths of the vertical targets - - Returns: - list: list of points with connectivity - ([[x, z, 'connection_type'], [...]]) - """ - B, G = anchors - h1, h2 = targets_lengths - points = [] - # I - I_ = extend(c_coord, F, distance_between_two_points(F, c_coord) * 1.1) - points.append([I_[0], I_[1], "straight"]) - # J - J = extend(G, F, h2 * 1.2) - points.append([J[0], J[1], "straight"]) - # K - K = extend(B, c_coord, h1 * 1.2) - points.append([K[0], K[1], "straight"]) - # L - L = extend(F, c_coord, distance_between_two_points(F, c_coord) * 1.1) - points.append([L[0], L[1], "straight"]) - return points - - def find_points(self): - """Finds the XZ points and connection types (straight and circle) that - describe the 2D profile of the ITER-like divertor - """ - - # ivt points - ivt_points = self._create_vertical_target_points( - self.ivt_anchor, - math.radians(self.ivt_coverage), - math.radians(self.ivt_tilt), - -self.ivt_radius, - self.ivt_length, - ) - # add connections - connections = ["circle"] * 2 + ["straight"] * 2 - for i, connection in enumerate(connections): - ivt_points[i].append(connection) - - # ovt points - ovt_points = self._create_vertical_target_points( - self.ovt_anchor, - -math.radians(self.ovt_coverage), - math.radians(self.ovt_tilt), - self.ovt_radius, - self.ovt_length, - ) - # add connections - connections = ["straight"] + ["circle"] * 2 + ["straight"] - for i, connection in enumerate(connections): - ovt_points[i].append(connection) - # ovt_points need to be fliped for correct connections - ovt_points = [[float(e[0]), float(e[1]), e[2]] for e in np.flipud(ovt_points)] - - # Dome points - dome_points = [] - if self.dome: - dome_points = self._create_dome_points( - ivt_points[-1][:2], - ovt_points[0][:2], - self.dome_length, - self.dome_height, - self.dome_thickness, - self.dome_pos, - ) - - # casing points - self.casing_points = self._create_casing_points( - anchors=(self.ivt_anchor, self.ovt_anchor), - c_coord=ivt_points[-1][:2], - F=ovt_points[0][:2], - targets_lengths=(self.ivt_length, self.ovt_length), - ) - - # append all points - points = ivt_points + dome_points + ovt_points + self.casing_points - self.points = points diff --git a/src/paramak/parametric_components/divertor_ITER_no_dome.py b/src/paramak/parametric_components/divertor_ITER_no_dome.py deleted file mode 100644 index 1994c6dbb..000000000 --- a/src/paramak/parametric_components/divertor_ITER_no_dome.py +++ /dev/null @@ -1,9 +0,0 @@ -from paramak import ITERtypeDivertor - - -class ITERtypeDivertorNoDome(ITERtypeDivertor): - """Creates an ITER-like divertor with inner and outer vertical targets""" - - def __init__(self, **kwargs): - - super().__init__(dome=False, dome_height=None, dome_length=None, dome_thickness=None, dome_pos=None, **kwargs) diff --git a/src/paramak/parametric_components/extrude_hollow_rectangle.py b/src/paramak/parametric_components/extrude_hollow_rectangle.py deleted file mode 100644 index e3dda1d6f..000000000 --- a/src/paramak/parametric_components/extrude_hollow_rectangle.py +++ /dev/null @@ -1,171 +0,0 @@ -from typing import List, Optional, Tuple, Union - -from cadquery import Plane -from paramak import ExtrudeStraightShape - - -class ExtrudeHollowRectangle(ExtrudeStraightShape): - """Creates a rectangular with a hollow section extrusion. - - Args: - height: the height of the internal hollow section. - width: the width of the internal hollow section. - distance: the depth of the internal hollow section. - casing_thickness: the thickness of the casing around the hollow section. - name: defaults to "extrude_rectangle". - center_point: the center of the rectangle (x,z) values (cm). - """ - - def __init__( - self, - height: float, - width: float, - distance: float, - casing_thickness: float, - name: str = "extrude_hollow_rectangle", - center_point: Tuple[float, float] = (0, 0), - extrude_both: bool = True, - color: Tuple[float, float, float, Optional[float]] = (0.5, 0.5, 0.5), - azimuth_placement_angle: Union[float, List[float]] = 0.0, - workplane: Union[str, Plane] = "XZ", - cut=None, - intersect=None, - union=None, - extrusion_start_offset: float = 0.0, - **kwargs - ) -> None: - - super().__init__( - name=name, - distance=distance, - extrude_both=extrude_both, - color=color, - azimuth_placement_angle=azimuth_placement_angle, - workplane=workplane, - cut=cut, - intersect=intersect, - union=union, - extrusion_start_offset=extrusion_start_offset, - **kwargs - ) - - self.center_point = center_point - self.height = height - self.width = width - self.casing_thickness = casing_thickness - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, center_point): - self._center_point = center_point - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def width(self): - return self._width - - @width.setter - def width(self, width): - self._width = width - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the shape.""" - - # 9-------------6 - # | 4 -------5,1| - # | | | | - # | | cp | | - # | | | | - # | 3 ------- 2 | - # 8-------------7 - - points = [ - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] - (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] - (self.casing_thickness + self.width / 2.0), - self.center_point[1] - (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] - (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ] - - self.points = points - - def create_solid(self): - - # creates a small box that surrounds the geometry - inner_box = ExtrudeStraightShape( - distance=self.distance, - points=self.points[:4], - extrude_both=self.extrude_both, - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - extrusion_start_offset=self.extrusion_start_offset, - ) - - # creates a large box that surrounds the smaller box - outer_box = ExtrudeStraightShape( - distance=self.distance, - points=self.points[5:9], - extrude_both=self.extrude_both, - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - extrusion_start_offset=self.extrusion_start_offset, - ) - - # subtracts the two boxes to leave a hollow box - new_shape = outer_box.solid.cut(inner_box.solid) - - self.solid = new_shape - - return new_shape diff --git a/src/paramak/parametric_components/extrude_rectangle.py b/src/paramak/parametric_components/extrude_rectangle.py deleted file mode 100644 index e01da021a..000000000 --- a/src/paramak/parametric_components/extrude_rectangle.py +++ /dev/null @@ -1,73 +0,0 @@ -from typing import Tuple - -from paramak import ExtrudeStraightShape - - -class ExtrudeRectangle(ExtrudeStraightShape): - """Creates a rectangular extrusion. - - Args: - height: the vertical (z axis) height of the rectangle (cm). - width: the horizontal (x axis) width of the rectangle (cm). - center_point: the center of the rectangle (x,z) values (cm). - name: defaults to "extrude_rectangle". - """ - - def __init__( - self, height: float, width: float, center_point: Tuple[float, float], name: str = "extrude_rectangle", **kwargs - ) -> None: - - super().__init__(name=name, **kwargs) - - self.center_point = center_point - self.height = height - self.width = width - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, center_point): - self._center_point = center_point - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def width(self): - return self._width - - @width.setter - def width(self, width): - self._width = width - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the shape.""" - - points = [ - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper right - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower right - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower left - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), - ] - - self.points = points diff --git a/src/paramak/parametric_components/hexagon_pin.py b/src/paramak/parametric_components/hexagon_pin.py deleted file mode 100644 index 3b5dbf94d..000000000 --- a/src/paramak/parametric_components/hexagon_pin.py +++ /dev/null @@ -1,70 +0,0 @@ -import math -from typing import Optional, Tuple - -from paramak import ExtrudeStraightShape - - -class HexagonPin(ExtrudeStraightShape): - """Creates an extruded hexagon by a provided distance about a center point. - - Args: - length_of_side: the length of one side of the hexagon (mm). - distance: extruded distance along the y-direction (mm). - center_point: the center of the hexagon on the x-z plane (mm). - name: defaults to "hexagon_pin". - """ - - def __init__( - self, - length_of_side: float, - distance: float, - center_point: Tuple[float, float] = (0, 0), - name: Optional[str] = "hexagon_pin", - **kwargs - ) -> None: - - super().__init__(name=name, distance=distance, **kwargs) - - self.center_point = center_point - self.length_of_side = length_of_side - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, center_point): - self._center_point = center_point - - @property - def length_of_side(self): - return self._length_of_side - - @length_of_side.setter - def length_of_side(self, length_of_side): - self._length_of_side = length_of_side - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the hexagon faced shape.""" - - # map of points - # p3 ---- p2 - # - - - # - - - # - - - # p4 p1 - # - - - # - - - # - - - # p5 ---- p6 - - points = [] - for i in range(6): - point = ( - self.length_of_side * math.cos(math.pi / 3 * i) + self.center_point[0], - self.length_of_side * math.sin(math.pi / 3 * i) + self.center_point[1], - ) - points.append(point) - - self.points = points diff --git a/src/paramak/parametric_components/hollow_cube.py b/src/paramak/parametric_components/hollow_cube.py deleted file mode 100644 index 736e3ff2c..000000000 --- a/src/paramak/parametric_components/hollow_cube.py +++ /dev/null @@ -1,68 +0,0 @@ -from typing import Tuple - -import cadquery as cq -from paramak import Shape - - -class HollowCube(Shape): - """A hollow cube with a constant thickness. Can be used to create a DAGMC - Graveyard. - - Arguments: - length: The length to use for the height, width, depth of the - inner dimensions of the cube. - thickness: thickness of the vessel. - center_coordinate: the location the center of the cube. - """ - - def __init__( - self, - length: float, - thickness: float = 10.0, - center_coordinate: Tuple[float, float, float] = (0.0, 0.0, 0.0), - name: str = "hollow_cube", - **kwargs - ): - super().__init__(name=name, **kwargs) - self.length = length - self.thickness = thickness - self.center_coordinate = center_coordinate - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, value): - self._thickness = value - - @property - def length(self): - return self._length - - @length.setter - def length(self, value): - self._length = value - - def create_solid(self): - - # creates a small box that surrounds the geometry - inner_box = cq.Workplane("front").box(self.length, self.length, self.length).translate(self.center_coordinate) - - # creates a large box that surrounds the smaller box - outer_box = ( - cq.Workplane("front") - .box( - self.length + self.thickness, - self.length + self.thickness, - self.length + self.thickness, - ) - .translate(self.center_coordinate) - ) - - # subtracts the two boxes to leave a hollow box - new_shape = outer_box.cut(inner_box) - - self.solid = new_shape - - return new_shape diff --git a/src/paramak/parametric_components/inboard_firstwall_fccs.py b/src/paramak/parametric_components/inboard_firstwall_fccs.py deleted file mode 100644 index f1bcc82f2..000000000 --- a/src/paramak/parametric_components/inboard_firstwall_fccs.py +++ /dev/null @@ -1,140 +0,0 @@ -from collections.abc import Iterable -from typing import Optional, Tuple - -import paramak -from paramak import ( - CenterColumnShieldCircular, - CenterColumnShieldCylinder, - CenterColumnShieldFlatTopCircular, - CenterColumnShieldFlatTopHyperbola, - CenterColumnShieldHyperbola, - CenterColumnShieldPlasmaHyperbola, - RotateMixedShape, -) - - -class InboardFirstwallFCCS(RotateMixedShape): - """An inboard firstwall component that builds a constant thickness layer - from the central column shield. The center column shields can be of type: - CenterColumnShieldCylinder, CenterColumnShieldHyperbola, - CenterColumnShieldFlatTopHyperbola, CenterColumnShieldCircular, - CenterColumnShieldPlasmaHyperbola or CenterColumnShieldFlatTopCircular - - Args: - central_column_shield: The central column shield object to build from - thickness: the radial thickness of the firstwall (cm) - """ - - def __init__( - self, - central_column_shield: paramak.Shape, - thickness: float, - color: Tuple[float, float, float, Optional[float]] = (0.5, 0.5, 0.5), - **kwargs - ): - - super().__init__(color=color, **kwargs) - - self.central_column_shield = central_column_shield - self.thickness = thickness - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, value): - self._thickness = value - - @property - def central_column_shield(self): - return self._central_column_shield - - @central_column_shield.setter - def central_column_shield(self, value): - self._central_column_shield = value - - def find_points(self): - - # check that is an acceptable class - acceptable_classes = ( - CenterColumnShieldCylinder, - CenterColumnShieldHyperbola, - CenterColumnShieldFlatTopHyperbola, - CenterColumnShieldPlasmaHyperbola, - CenterColumnShieldCircular, - CenterColumnShieldFlatTopCircular, - ) - if not isinstance(self.central_column_shield, acceptable_classes): - raise ValueError( - "InboardFirstwallFCCS.central_column_shield must be an \ - instance of CenterColumnShieldCylinder, \ - CenterColumnShieldHyperbola, \ - CenterColumnShieldFlatTopHyperbola, \ - CenterColumnShieldPlasmaHyperbola, \ - CenterColumnShieldCircular, CenterColumnShieldFlatTopCircular" - ) - - inner_radius = self.central_column_shield.inner_radius - height = self.central_column_shield.height - - if isinstance(self.central_column_shield, CenterColumnShieldCylinder): - firstwall = CenterColumnShieldCylinder( - height=height, - inner_radius=inner_radius, - outer_radius=self.central_column_shield.outer_radius + self.thickness, - ) - - elif isinstance(self.central_column_shield, CenterColumnShieldHyperbola): - firstwall = CenterColumnShieldHyperbola( - height=height, - inner_radius=inner_radius, - mid_radius=self.central_column_shield.mid_radius + self.thickness, - outer_radius=self.central_column_shield.outer_radius + self.thickness, - ) - - elif isinstance(self.central_column_shield, CenterColumnShieldFlatTopHyperbola): - firstwall = CenterColumnShieldFlatTopHyperbola( - height=height, - arc_height=self.central_column_shield.arc_height, - inner_radius=inner_radius, - mid_radius=self.central_column_shield.mid_radius + self.thickness, - outer_radius=self.central_column_shield.outer_radius + self.thickness, - ) - - elif isinstance(self.central_column_shield, CenterColumnShieldPlasmaHyperbola): - firstwall = CenterColumnShieldPlasmaHyperbola( - height=height, - inner_radius=inner_radius, - mid_offset=self.central_column_shield.mid_offset - self.thickness, - edge_offset=self.central_column_shield.edge_offset - self.thickness, - ) - - elif isinstance(self.central_column_shield, CenterColumnShieldCircular): - firstwall = CenterColumnShieldCircular( - height=height, - inner_radius=inner_radius, - mid_radius=self.central_column_shield.mid_radius + self.thickness, - outer_radius=self.central_column_shield.outer_radius + self.thickness, - ) - - elif isinstance(self.central_column_shield, CenterColumnShieldFlatTopCircular): - firstwall = CenterColumnShieldFlatTopCircular( - height=height, - arc_height=self.central_column_shield.arc_height, - inner_radius=inner_radius, - mid_radius=self.central_column_shield.mid_radius + self.thickness, - outer_radius=self.central_column_shield.outer_radius + self.thickness, - ) - - firstwall.rotation_angle = self.rotation_angle - self.connection_type = firstwall.connection_type - self.points = firstwall.points - - # add to cut attribute - if self.cut is None: - self.cut = self.central_column_shield - elif isinstance(self.cut, Iterable): - self.cut = [*self.cut, self.central_column_shield] - else: - self.cut = [*[self.cut], self.central_column_shield] diff --git a/src/paramak/parametric_components/inner_tf_coils_circular.py b/src/paramak/parametric_components/inner_tf_coils_circular.py deleted file mode 100644 index 12e65cd6d..000000000 --- a/src/paramak/parametric_components/inner_tf_coils_circular.py +++ /dev/null @@ -1,204 +0,0 @@ -import math -from typing import Optional - -import numpy as np - -from paramak import ExtrudeMixedShape - - -class InnerTfCoilsCircular(ExtrudeMixedShape): - """A tf coil volume with cylindrical inner and outer profiles and - constant gaps between each coil. - - Args: - height: height of tf coils. - inner_radius: inner radius of tf coils. - outer_radius: outer radius of tf coils. - number_of_coils: number of tf coils. - gap_size: gap between adjacent tf coils. - azimuth_start_angle: Defaults to 0.0. - workplane: Defaults to "XY". - rotation_axis: Defaults to "Z". - """ - - def __init__( - self, - height: float, - inner_radius: float, - outer_radius: float, - number_of_coils: int, - gap_size: float, - azimuth_start_angle: Optional[float] = 0.0, - workplane: Optional[str] = "XY", - rotation_axis: Optional[str] = "Z", - **kwargs - ) -> None: - - super().__init__(distance=height, workplane=workplane, rotation_axis=rotation_axis, **kwargs) - - self.azimuth_start_angle = azimuth_start_angle - self.height = height - self.inner_radius = inner_radius - self.outer_radius = outer_radius - self.number_of_coils = number_of_coils - self.gap_size = gap_size - self.distance = height - - @property - def azimuth_start_angle(self): - return self._azimuth_start_angle - - @azimuth_start_angle.setter - def azimuth_start_angle(self, value): - self._azimuth_start_angle = value - - @property - def azimuth_placement_angle(self): - self.find_azimuth_placement_angle() - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self._azimuth_placement_angle = value - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def distance(self): - return self.height - - @distance.setter - def distance(self, value): - self._distance = value - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, inner_radius): - self._inner_radius = inner_radius - - @property - def outer_radius(self): - return self._outer_radius - - @outer_radius.setter - def outer_radius(self, outer_radius): - self._outer_radius = outer_radius - - @property - def number_of_coils(self): - return self._number_of_coils - - @number_of_coils.setter - def number_of_coils(self, number_of_coils): - self._number_of_coils = number_of_coils - - @property - def gap_size(self): - return self._gap_size - - @gap_size.setter - def gap_size(self, gap_size): - self._gap_size = gap_size - - def find_points(self): - """Finds the points that describe the 2D profile of the tf coil shape""" - - if self.gap_size * self.number_of_coils > 2 * math.pi * self.inner_radius: - raise ValueError("gap_size is too large") - - theta_inner = ((2 * math.pi * self.inner_radius) - (self.gap_size * self.number_of_coils)) / ( - self.inner_radius * self.number_of_coils - ) - omega_inner = math.asin(self.gap_size / (2 * self.inner_radius)) - - theta_outer = ((2 * math.pi * self.outer_radius) - (self.gap_size * self.number_of_coils)) / ( - self.outer_radius * self.number_of_coils - ) - omega_outer = math.asin(self.gap_size / (2 * self.outer_radius)) - - # inner points - point_1 = ( - (self.inner_radius * math.cos(-omega_inner)), - (-self.inner_radius * math.sin(-omega_inner)), - ) - point_2 = ( - ( - self.inner_radius * math.cos(theta_inner / 2) * math.cos(-omega_inner) - + self.inner_radius * math.sin(theta_inner / 2) * math.sin(-omega_inner) - ), - ( - -self.inner_radius * math.cos(theta_inner / 2) * math.sin(-omega_inner) - + self.inner_radius * math.sin(theta_inner / 2) * math.cos(-omega_inner) - ), - ) - point_3 = ( - ( - self.inner_radius * math.cos(theta_inner) * math.cos(-omega_inner) - + self.inner_radius * math.sin(theta_inner) * math.sin(-omega_inner) - ), - ( - -self.inner_radius * math.cos(theta_inner) * math.sin(-omega_inner) - + self.inner_radius * math.sin(theta_inner) * math.cos(-omega_inner) - ), - ) - - # outer points - point_4 = ( - (self.outer_radius * math.cos(-omega_outer)), - (-self.outer_radius * math.sin(-omega_outer)), - ) - point_5 = ( - ( - self.outer_radius * math.cos(theta_outer / 2) * math.cos(-omega_outer) - + self.outer_radius * math.sin(theta_outer / 2) * math.sin(-omega_outer) - ), - ( - -self.outer_radius * math.cos(theta_outer / 2) * math.sin(-omega_outer) - + self.outer_radius * math.sin(theta_outer / 2) * math.cos(-omega_outer) - ), - ) - point_6 = ( - ( - self.outer_radius * math.cos(theta_outer) * math.cos(-omega_outer) - + self.outer_radius * math.sin(theta_outer) * math.sin(-omega_outer) - ), - ( - -self.outer_radius * math.cos(theta_outer) * math.sin(-omega_outer) - + self.outer_radius * math.sin(theta_outer) * math.cos(-omega_outer) - ), - ) - - points = [ - (point_1[0], point_1[1], "circle"), - (point_2[0], point_2[1], "circle"), - (point_3[0], point_3[1], "straight"), - (point_6[0], point_6[1], "circle"), - (point_5[0], point_5[1], "circle"), - (point_4[0], point_4[1], "straight"), - ] - - self.points = points - - def find_azimuth_placement_angle(self): - """Calculates the azimuth placement angles based on the number of tf - coils""" - - angles = list( - np.linspace( - 0 + self.azimuth_start_angle, - 360 + self.azimuth_start_angle, - self.number_of_coils, - endpoint=False, - ) - ) - - self.azimuth_placement_angle = angles diff --git a/src/paramak/parametric_components/inner_tf_coils_flat.py b/src/paramak/parametric_components/inner_tf_coils_flat.py deleted file mode 100644 index b38624bec..000000000 --- a/src/paramak/parametric_components/inner_tf_coils_flat.py +++ /dev/null @@ -1,236 +0,0 @@ -import math -from typing import Optional - -import numpy as np - -from paramak import ExtrudeStraightShape - - -class InnerTfCoilsFlat(ExtrudeStraightShape): - """A tf coil volume with straight inner and outer profiles and - constant gaps between each coil. Note: the inner / outer surface is not - equal distance to the center point everywhere as the corners are further - than the straight sections. - - Args: - height: height of tf coils. - inner_radius: Distance between center point and the inner surface of - the tf coils. - outer_radius: Distance between center point and the outer surface of - the tf coils. - number_of_coils: number of tf coils. - gap_size: gap between adjacent tf coils. - radius_type: Controls the part of the inner surface used when - defining the inner_radius and outer_radius. Can be set to either - 'corner' or 'straight'. - azimuth_start_angle: defaults to 0.0. - workplane:defaults to "XY". - rotation_axis: Defaults to "Z". - """ - - def __init__( - self, - height: float, - inner_radius: float, - outer_radius: float, - number_of_coils: int, - gap_size: float, - radius_type: Optional[str] = "corner", - azimuth_start_angle: Optional[float] = 0.0, - workplane: Optional[str] = "XY", - rotation_axis: Optional[str] = "Z", - **kwargs, - ) -> None: - - super().__init__(distance=height, workplane=workplane, rotation_axis=rotation_axis, **kwargs) - - self.azimuth_start_angle = azimuth_start_angle - self.height = height - self.inner_radius = inner_radius - self.outer_radius = outer_radius - self.radius_type = radius_type - self.number_of_coils = number_of_coils - self.gap_size = gap_size - self.distance = height - - @property - def azimuth_start_angle(self): - return self._azimuth_start_angle - - @azimuth_start_angle.setter - def azimuth_start_angle(self, value): - self._azimuth_start_angle = value - - @property - def radius_type(self): - return self._radius_type - - @radius_type.setter - def radius_type(self, value): - if value not in ["corner", "straight"]: - msg = f'radius_type must be either "corner" or "straight". Not {value}' - raise ValueError(msg) - self._radius_type = value - - @property - def azimuth_placement_angle(self): - self.find_azimuth_placement_angle() - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self._azimuth_placement_angle = value - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def distance(self): - return self.height - - @distance.setter - def distance(self, value): - self._distance = value - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, inner_radius): - self._inner_radius = inner_radius - - @property - def outer_radius(self): - return self._outer_radius - - @outer_radius.setter - def outer_radius(self, outer_radius): - self._outer_radius = outer_radius - - @property - def number_of_coils(self): - return self._number_of_coils - - @number_of_coils.setter - def number_of_coils(self, number_of_coils): - self._number_of_coils = number_of_coils - - @property - def gap_size(self): - return self._gap_size - - @gap_size.setter - def gap_size(self, gap_size): - self._gap_size = gap_size - - def find_points(self): - """Finds the points that describe the 2D profile of the tf coil shape""" - - # / p4 - # / /¦ - # / / ¦ - # / / ¦ - # / / ¦ - # p1/ ¦ - # ¦ ¦ - # x ¦ ¦ - # ¦ ¦ - # p2\ ¦ - # \ \ ¦ - # \ \ ¦ - # \ \ ¦ - # \ p3 - - if self.radius_type == "corner": - distance_to_inner_corner = self.inner_radius - distance_to_rear_corner = self.outer_radius - # this section calculates a new distance to the corners now that we - # know the user provided the distance to the straight - if self.radius_type == "straight": - angle = 360 / (self.number_of_coils * 2) - distance_to_inner_corner = self.inner_radius / math.cos(math.radians(angle)) - distance_to_rear_corner = self.outer_radius / math.cos(math.radians(angle)) - - if self.gap_size * self.number_of_coils > 2 * math.pi * distance_to_inner_corner: - msg = ( - "Gap_size is too large. The gap_size * number of coils must " - "be less than the circumference of the circle made by " - "the inner_radius" - ) - raise ValueError(msg) - - if distance_to_inner_corner != 0.0: - theta_inner = ((2 * math.pi * distance_to_inner_corner) - (self.gap_size * self.number_of_coils)) / ( - distance_to_inner_corner * self.number_of_coils - ) - omega_inner = math.asin(self.gap_size / (2 * distance_to_inner_corner)) - - # inner points - point_1 = ( - (distance_to_inner_corner * math.cos(-omega_inner)), - (-distance_to_inner_corner * math.sin(-omega_inner)), - ) - point_2 = ( - ( - distance_to_inner_corner * math.cos(theta_inner) * math.cos(-omega_inner) - + distance_to_inner_corner * math.sin(theta_inner) * math.sin(-omega_inner) - ), - ( - -distance_to_inner_corner * math.cos(theta_inner) * math.sin(-omega_inner) - + distance_to_inner_corner * math.sin(theta_inner) * math.cos(-omega_inner) - ), - ) - points = [(point_1[0], point_1[1]), (point_2[0], point_2[1])] - - else: - - points = [(0, 0)] - - # print(point_1) - # print(point_2) - - theta_outer = ((2 * math.pi * distance_to_rear_corner) - (self.gap_size * self.number_of_coils)) / ( - distance_to_rear_corner * self.number_of_coils - ) - omega_outer = math.asin(self.gap_size / (2 * distance_to_rear_corner)) - - # outer points - point_4 = ( - (distance_to_rear_corner * math.cos(-omega_outer)), - (-distance_to_rear_corner * math.sin(-omega_outer)), - ) - point_6 = ( - ( - distance_to_rear_corner * math.cos(theta_outer) * math.cos(-omega_outer) - + distance_to_rear_corner * math.sin(theta_outer) * math.sin(-omega_outer) - ), - ( - -distance_to_rear_corner * math.cos(theta_outer) * math.sin(-omega_outer) - + distance_to_rear_corner * math.sin(theta_outer) * math.cos(-omega_outer) - ), - ) - points.append((point_6[0], point_6[1])) - points.append((point_4[0], point_4[1])) - - self.points = points - - def find_azimuth_placement_angle(self): - """Calculates the azimuth placement angles based on the number of tf - coils""" - - angles = list( - np.linspace( - 0 + self.azimuth_start_angle, - 360 + self.azimuth_start_angle, - self.number_of_coils, - endpoint=False, - ) - ) - - self.azimuth_placement_angle = angles diff --git a/src/paramak/parametric_components/poloidal_field_coil.py b/src/paramak/parametric_components/poloidal_field_coil.py deleted file mode 100644 index 545450545..000000000 --- a/src/paramak/parametric_components/poloidal_field_coil.py +++ /dev/null @@ -1,73 +0,0 @@ -from typing import Tuple - -from paramak import RotateStraightShape - - -class PoloidalFieldCoil(RotateStraightShape): - """Creates a rectangular poloidal field coil. - - Args: - height: the vertical (z axis) height of the coil (cm). - width: the horizontal (x axis) width of the coil (cm). - center_point: the center of the coil (x,z) values (cm). - name: defaults to "pf_coil". - """ - - def __init__( - self, height: float, width: float, center_point: Tuple[float, float], name: str = "pf_coil", **kwargs - ) -> None: - - super().__init__(name=name, **kwargs) - - self.center_point = center_point - self.height = height - self.width = width - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, center_point): - self._center_point = center_point - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def width(self): - return self._width - - @width.setter - def width(self, width): - self._width = width - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal field coil shape.""" - - points = [ - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper right - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower right - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower left - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), - ] - - self.points = points diff --git a/src/paramak/parametric_components/poloidal_field_coil_case.py b/src/paramak/parametric_components/poloidal_field_coil_case.py deleted file mode 100644 index 5a89b5236..000000000 --- a/src/paramak/parametric_components/poloidal_field_coil_case.py +++ /dev/null @@ -1,160 +0,0 @@ -from typing import List, Optional, Tuple, Union - -from cadquery import Plane -from paramak import RotateStraightShape - - -class PoloidalFieldCoilCase(RotateStraightShape): - """Creates a casing for a rectangular coil from inputs that - describe the existing coil and the thickness of the casing required. - - Args: - coil_height: the vertical (z axis) height of the coil (cm). - coil_width: the horizontal (x axis) width of the coil (cm). - center_point: the center of the coil (x,z) values (cm). - casing_thickness: the thickness of the coil casing (cm). - """ - - def __init__( - self, - casing_thickness: Tuple[float, float], - coil_height: float, - coil_width: float, - center_point: Tuple[float, float], - name: str = "poloidal_field_coil", - color: Tuple[float, float, float, Optional[float]] = (1.0, 1.0, 0.498), - rotation_axis: Optional[str] = None, - rotation_angle: float = 360.0, - azimuth_placement_angle: Optional[Union[float, List[float]]] = 0.0, - workplane: Optional[Union[str, Plane]] = "XZ", - cut=None, - intersect=None, - union=None, - **kwargs - ) -> None: - - super().__init__(color=color, **kwargs) - - super().__init__( - name=name, - rotation_axis=rotation_axis, - rotation_angle=rotation_angle, - color=color, - azimuth_placement_angle=azimuth_placement_angle, - workplane=workplane, - cut=cut, - intersect=intersect, - union=union, - **kwargs - ) - - self.center_point = center_point - self.height = coil_height - self.width = coil_width - self.casing_thickness = casing_thickness - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, value): - self._center_point = value - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def width(self): - return self._width - - @width.setter - def width(self, width): - self._width = width - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal field coil case shape.""" - - points = [ - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper right - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower right - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower left - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper left - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper right - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] - (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] - (self.casing_thickness + self.width / 2.0), - self.center_point[1] - (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] - (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ] - - self.points = points - - def create_solid(self): - - # creates a small box that surrounds the geometry - inner_box = RotateStraightShape( - points=self.points[:4], - rotation_axis=self.rotation_axis, - # rotation_angle=self.rotation_angle, - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - ) - - # creates a large box that surrounds the smaller box - outer_box = RotateStraightShape( - points=self.points[5:9], - rotation_axis=self.rotation_axis, - rotation_angle=self.rotation_angle, - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - ) - - # subtracts the two boxes to leave a hollow box - new_shape = outer_box.solid.cut(inner_box.solid) - - self.solid = new_shape - - return new_shape diff --git a/src/paramak/parametric_components/poloidal_field_coil_case_fc.py b/src/paramak/parametric_components/poloidal_field_coil_case_fc.py deleted file mode 100644 index 43ec0570e..000000000 --- a/src/paramak/parametric_components/poloidal_field_coil_case_fc.py +++ /dev/null @@ -1,126 +0,0 @@ -from typing import Optional, Tuple - -from paramak import RotateStraightShape, PoloidalFieldCoil - - -class PoloidalFieldCoilCaseFC(RotateStraightShape): - """Creates a casing for a rectangular poloidal field coil by building - around an existing coil (which is passed as an argument on construction). - - Args: - pf_coil: a pf coil object with a set width, height and center point. - casing_thickness: the thickness of the coil casing (cm). - """ - - def __init__( - self, - pf_coil: PoloidalFieldCoil, - casing_thickness: float, - color: Tuple[float, float, float, Optional[float]] = (1.0, 1.0, 0.498), - **kwargs - ): - - super().__init__(color=color, **kwargs) - - self.pf_coil = pf_coil - self.center_point = pf_coil.center_point - self.height = pf_coil.height - self.width = pf_coil.width - self.casing_thickness = casing_thickness - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, value): - self._center_point = value - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def width(self): - return self._width - - @width.setter - def width(self, width): - self._width = width - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal field coil case shape.""" - - points = [ - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper right - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower right - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] - self.height / 2.0, - ), # lower left - ( - self.center_point[0] - self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper left - ( - self.center_point[0] + self.width / 2.0, - self.center_point[1] + self.height / 2.0, - ), # upper right - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] - (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] - (self.casing_thickness + self.width / 2.0), - self.center_point[1] - (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] - (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ( - self.center_point[0] + (self.casing_thickness + self.width / 2.0), - self.center_point[1] + (self.casing_thickness + self.height / 2.0), - ), - ] - - self.points = points - - def create_solid(self): - - # creates a small box that surrounds the geometry - inner_box = self.pf_coil - - # creates a large box that surrounds the smaller box - outer_box = RotateStraightShape( - points=self.points[5:9], - rotation_axis=inner_box.rotation_axis, - rotation_angle=inner_box.rotation_angle, - azimuth_placement_angle=inner_box.azimuth_placement_angle, - workplane=inner_box.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - ) - - # subtracts the two boxes to leave a hollow box - new_shape = outer_box.solid.cut(inner_box.solid) - - self.solid = new_shape - - return new_shape diff --git a/src/paramak/parametric_components/poloidal_field_coil_case_set.py b/src/paramak/parametric_components/poloidal_field_coil_case_set.py deleted file mode 100644 index 2894970b9..000000000 --- a/src/paramak/parametric_components/poloidal_field_coil_case_set.py +++ /dev/null @@ -1,235 +0,0 @@ -from typing import Iterable, Optional, Tuple, Union - -import cadquery as cq -from paramak import RotateStraightShape - - -class PoloidalFieldCoilCaseSet(RotateStraightShape): - """Creates a series of rectangular poloidal field coils. - - Args: - heights (list of floats): the vertical (z axis) heights of the coil - (cm). - widths (list of floats): the horizontal (x axis) widths of the coil - (cm). - casing_thicknesses (float or list of floats): the thicknesses of the - coil casing (cm). If float then the same thickness is applied to - all coils. If list of floats then each entry is applied to a - separate pf_coil, one entry for each pf_coil. - center_points (tuple of floats): the center of the coil (x,z) values - (cm). - name (str, optional): defaults to "pf_coil_case_set". - """ - - def __init__( - self, - heights: Iterable[float], - widths: Iterable[float], - casing_thicknesses: Iterable[float], - center_points: Iterable[float], - name: str = "pf_coil_case_set", - color: Tuple[float, float, float, Optional[float]] = (1.0, 1.0, 0.498), - **kwargs - ): - - super().__init__(name=name, color=color, **kwargs) - - self.center_points = center_points - self.heights = heights - self.widths = widths - self.casing_thicknesses = casing_thicknesses - - @property - def center_points(self): - return self._center_points - - @center_points.setter - def center_points(self, center_points): - self._center_points = center_points - - @property - def heights(self): - return self._heights - - @heights.setter - def heights(self, heights): - self._heights = heights - - @property - def widths(self): - return self._widths - - @widths.setter - def widths(self, widths): - self._widths = widths - - @property - def casing_thicknesses(self): - return self._casing_thicknesses - - @casing_thicknesses.setter - def casing_thicknesses(self, value: Union[Iterable[float], float]): - if isinstance(value, list): - if not all(isinstance(x, (int, float)) for x in value): - raise ValueError("Every entry in Casing_thicknesses must be a float or int") - else: - if not isinstance(value, (float, int)): - raise ValueError("Casing_thicknesses must be a list of numbers or a number") - self._casing_thicknesses = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal field coil shape.""" - - all_points = [] - - if isinstance(self.casing_thicknesses, list): - casing_thicknesses_list = self.casing_thicknesses - else: - casing_thicknesses_list = [self.casing_thicknesses] * len(self.widths) - - if not len(self.heights) == len(self.widths) == len(self.center_points) == len(casing_thicknesses_list): - raise ValueError("The number of heights, widths, center_points and " "casing_thicknesses must be equal") - - for height, width, center_point, casing_thickness in zip( - self.heights, self.widths, self.center_points, casing_thicknesses_list - ): - - if casing_thickness != 0: - - all_points = all_points + [ - ( - center_point[0] + width / 2.0, - center_point[1] + height / 2.0, - ), # upper right - ( - center_point[0] + width / 2.0, - center_point[1] - height / 2.0, - ), # lower right - ( - center_point[0] - width / 2.0, - center_point[1] - height / 2.0, - ), # lower left - ( - center_point[0] - width / 2.0, - center_point[1] + height / 2.0, - ), # upper left - ( - center_point[0] + width / 2.0, - center_point[1] + height / 2.0, - ), # upper right - ( - center_point[0] + (casing_thickness + width / 2.0), - center_point[1] + (casing_thickness + height / 2.0), - ), - ( - center_point[0] + (casing_thickness + width / 2.0), - center_point[1] - (casing_thickness + height / 2.0), - ), - ( - center_point[0] - (casing_thickness + width / 2.0), - center_point[1] - (casing_thickness + height / 2.0), - ), - ( - center_point[0] - (casing_thickness + width / 2.0), - center_point[1] + (casing_thickness + height / 2.0), - ), - ( - center_point[0] + (casing_thickness + width / 2.0), - center_point[1] + (casing_thickness + height / 2.0), - ), - ] - - self.points = all_points - - def create_solid(self): - """Creates a 3d solid using points with straight edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - iter_points = iter(self.points) - pf_coils_set = [] - wires = [] - for p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 in zip( - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - ): - - # creates a small box that surrounds the geometry - inner_box = RotateStraightShape( - points=[p1, p2, p3, p4], - rotation_axis=self.rotation_axis, - rotation_angle=360, # full rotated - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - ) - - outer_box = RotateStraightShape( - points=[p7, p8, p9, p10], - rotation_axis=self.rotation_axis, - rotation_angle=self.rotation_angle, - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - ) - - # subtracts the two boxes to leave a hollow box - new_shape = outer_box.solid.cut(inner_box.solid) - - # makes wires for the inside and outside loops - wire = ( - cq.Workplane(self.workplane) - .polyline( - [ - p1[:2], - p2[:2], - p3[:2], - p4[:2], - p5[:2], - ] - ) - .close() - ) - - wires.append(wire) - - wire = ( - cq.Workplane(self.workplane) - .polyline( - [ - p6[:2], - p7[:2], - p8[:2], - p9[:2], - p10[:2], - ] - ) - .close() - ) - - wires.append(wire) - - pf_coils_set.append(new_shape) - - compound = cq.Compound.makeCompound([a.val() for a in pf_coils_set]) - - self.wire = wires - - self.solid = compound - - return compound diff --git a/src/paramak/parametric_components/poloidal_field_coil_case_set_fc.py b/src/paramak/parametric_components/poloidal_field_coil_case_set_fc.py deleted file mode 100644 index bfbd76201..000000000 --- a/src/paramak/parametric_components/poloidal_field_coil_case_set_fc.py +++ /dev/null @@ -1,243 +0,0 @@ -from typing import Optional, Tuple - -import cadquery as cq -from typing import Iterable -from paramak import PoloidalFieldCoilSet, RotateStraightShape, PoloidalFieldCoil - - -class PoloidalFieldCoilCaseSetFC(RotateStraightShape): - """Creates a series of rectangular poloidal field coils. - - Args: - pf_coils (paramak.PoloidalFieldCoil): a list of pf coil objects or a - CadQuery compound object - casing_thicknesses (float or list of floats): the thicknesses of the - coil casing (cm). If float then the same thickness is applied to - all coils. If list of floats then each entry is applied to a - seperate pf_coil, one entry for each pf_coil. - name (str, optional): defaults to "pf_coil_case_set_fc". - """ - - def __init__( - self, - pf_coils: Iterable[PoloidalFieldCoil], - casing_thicknesses: float, - name: str = "pf_coil_case_set_fc", - color: Tuple[float, float, float, Optional[float]] = (1.0, 1.0, 0.498), - **kwargs - ): - - super().__init__(name=name, color=color, **kwargs) - - self.casing_thicknesses = casing_thicknesses - self.pf_coils = pf_coils - - # calculated internally by the class - self.heights = None - self.widths = None - self.center_points = None - - @property - def casing_thicknesses(self): - return self._casing_thicknesses - - @casing_thicknesses.setter - def casing_thicknesses(self, value: float): - if isinstance(value, list): - if not all(isinstance(x, (int, float)) for x in value): - raise ValueError("Every entry in Casing_thicknesses must be a float or int") - else: - if not isinstance(value, (float, int)): - raise ValueError("Casing_thicknesses must be a list of numbers or a number") - self._casing_thicknesses = value - - @property - def pf_coils(self): - return self._pf_coils - - @pf_coils.setter - def pf_coils(self, value: float): - if not isinstance(value, (list, PoloidalFieldCoilSet)): - msg = ( - "PoloidalFieldCoilCaseSetFC.pf_coils must be either a list " - "paramak.PoloidalFieldCoil or a " - "paramak.PoloidalFieldCoilSet object" - ) - raise ValueError(msg) - self._pf_coils = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal field coil shape.""" - - if isinstance(self.pf_coils, list): - self.heights = [entry.height for entry in self.pf_coils] - self.widths = [entry.width for entry in self.pf_coils] - self.center_points = [entry.center_point for entry in self.pf_coils] - - num_of_coils = len(self.pf_coils) - - elif isinstance(self.pf_coils, PoloidalFieldCoilSet): - self.heights = self.pf_coils.heights - self.widths = self.pf_coils.widths - self.center_points = self.pf_coils.center_points - num_of_coils = len(self.pf_coils.solid.Solids()) - - if isinstance(self.casing_thicknesses, list): - if len(self.casing_thicknesses) != num_of_coils: - raise ValueError( - "The number pf_coils is not equal to the " "number of thichnesses provided. " "casing_thicknesses=", - self.casing_thicknesses, - "num_of_coils=", - num_of_coils, - ) - casing_thicknesses_list = self.casing_thicknesses - else: - casing_thicknesses_list = [self.casing_thicknesses] * num_of_coils - - all_points = [] - - for height, width, center_point, casing_thickness in zip( - self.heights, self.widths, self.center_points, casing_thicknesses_list - ): - - if casing_thickness != 0: - - all_points = all_points + [ - ( - center_point[0] + width / 2.0, - center_point[1] + height / 2.0, - ), # upper right - ( - center_point[0] + width / 2.0, - center_point[1] - height / 2.0, - ), # lower right - ( - center_point[0] - width / 2.0, - center_point[1] - height / 2.0, - ), # lower left - ( - center_point[0] - width / 2.0, - center_point[1] + height / 2.0, - ), # upper left - ( - center_point[0] + width / 2.0, - center_point[1] + height / 2.0, - ), # upper right - ( - center_point[0] + (casing_thickness + width / 2.0), - center_point[1] + (casing_thickness + height / 2.0), - ), - ( - center_point[0] + (casing_thickness + width / 2.0), - center_point[1] - (casing_thickness + height / 2.0), - ), - ( - center_point[0] - (casing_thickness + width / 2.0), - center_point[1] - (casing_thickness + height / 2.0), - ), - ( - center_point[0] - (casing_thickness + width / 2.0), - center_point[1] + (casing_thickness + height / 2.0), - ), - ( - center_point[0] + (casing_thickness + width / 2.0), - center_point[1] + (casing_thickness + height / 2.0), - ), - ] - - self.points = all_points - - def create_solid(self): - """Creates a 3d solid using points with straight edges. Individual - solids in the compound can be accessed using .Solids()[i] where i is an - int - - Returns: - A CadQuery solid: A 3D solid volume - """ - - iter_points = iter(self.points) - pf_coils_set = [] - wires = [] - for p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 in zip( - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - iter_points, - ): - - # creates a small box that surrounds the geometry - inner_box = RotateStraightShape( - points=[p1, p2, p3, p4], - rotation_axis=self.rotation_axis, - rotation_angle=360, # full rotated - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - ) - - outer_box = RotateStraightShape( - points=[p7, p8, p9, p10], - rotation_axis=self.rotation_axis, - rotation_angle=self.rotation_angle, - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.workplane, - cut=self.cut, - intersect=self.intersect, - union=self.union, - ) - - # subtracts the two boxes to leave a hollow box - new_shape = outer_box.solid.cut(inner_box.solid) - - # makes wires for the inside and outside loops - wire = ( - cq.Workplane(self.workplane) - .polyline( - [ - p1[:2], - p2[:2], - p3[:2], - p4[:2], - p5[:2], - ] - ) - .close() - ) - - wires.append(wire) - - wire = ( - cq.Workplane(self.workplane) - .polyline( - [ - p6[:2], - p7[:2], - p8[:2], - p9[:2], - p10[:2], - ] - ) - .close() - ) - - wires.append(wire) - - pf_coils_set.append(new_shape) - - compound = cq.Compound.makeCompound([a.val() for a in pf_coils_set]) - - self.wire = wires - - self.solid = compound - - return compound diff --git a/src/paramak/parametric_components/poloidal_field_coil_fp.py b/src/paramak/parametric_components/poloidal_field_coil_fp.py deleted file mode 100644 index e56e761ac..000000000 --- a/src/paramak/parametric_components/poloidal_field_coil_fp.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Iterable, Tuple -from paramak import PoloidalFieldCoil - - -class PoloidalFieldCoilFP(PoloidalFieldCoil): - """Creates a rectangular poloidal field coil. - - Args: - corner_points (list of float tuples): the coordinates of the opposite - corners of the rectangular shaped coil e.g [(x1, y1), (x2, y2)] - """ - - def __init__(self, corner_points: Iterable[Tuple[float, float]], **kwargs): - - height = abs(corner_points[0][1] - corner_points[1][1]) - width = abs(corner_points[0][0] - corner_points[1][0]) - - center_width = (corner_points[0][0] + corner_points[1][0]) / 2.0 - center_height = (corner_points[0][1] + corner_points[1][1]) / 2.0 - center_point = (center_width, center_height) - - super().__init__(height=height, width=width, center_point=center_point, **kwargs) - - self.corner_points = corner_points - - @property - def corner_points(self): - return self._corner_points - - @corner_points.setter - def corner_points(self, value): - # ToDo check the corner points are a list with two entries - # and each entry is a tuple with two floats - self._corner_points = value diff --git a/src/paramak/parametric_components/poloidal_field_coil_set.py b/src/paramak/parametric_components/poloidal_field_coil_set.py deleted file mode 100644 index 838013d3c..000000000 --- a/src/paramak/parametric_components/poloidal_field_coil_set.py +++ /dev/null @@ -1,128 +0,0 @@ -import cadquery as cq -from typing import Iterable, Tuple -from paramak import RotateStraightShape - - -class PoloidalFieldCoilSet(RotateStraightShape): - """Creates a series of rectangular poloidal field coils. - - Args: - heights: the vertical (z axis) heights of the coils (cm). - widths: the horizontal (x axis) widths of the coils (cm). - center_points: the center of the coil (x,z) values e.g. [(100,100), - (100,200)] (cm). - name: defaults to "pf_coil". - """ - - def __init__( - self, - heights: Iterable[float], - widths: Iterable[float], - center_points: Iterable[Tuple[float, float]], - name="pf_coil", - **kwargs - ): - - super().__init__(name=name, **kwargs) - - self.center_points = center_points - self.heights = heights - self.widths = widths - - if len(self.widths) != len(self.heights) or len(self.heights) != len(self.center_points): - raise ValueError( - "The length of widthts, height and center_points \ - must be the same when making a PoloidalFieldCoilSet" - ) - - @property - def center_points(self): - return self._center_points - - @center_points.setter - def center_points(self, value): - if not isinstance(value, list): - raise ValueError("PoloidalFieldCoilSet center_points must be a list") - self._center_points = value - - @property - def heights(self): - return self._heights - - @heights.setter - def heights(self, value): - if not isinstance(value, list): - raise ValueError("PoloidalFieldCoilSet heights must be a list") - self._heights = value - - @property - def widths(self): - return self._widths - - @widths.setter - def widths(self, value): - if not isinstance(value, list): - raise ValueError("PoloidalFieldCoilSet widths must be a list") - self._widths = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal field coil shape.""" - - all_points = [] - - for height, width, center_point in zip(self.heights, self.widths, self.center_points): - - all_points = all_points + [ - ( - center_point[0] + width / 2.0, - center_point[1] + height / 2.0, - ), # upper right - ( - center_point[0] + width / 2.0, - center_point[1] - height / 2.0, - ), # lower right - ( - center_point[0] - width / 2.0, - center_point[1] - height / 2.0, - ), # lower left - ( - center_point[0] - width / 2.0, - center_point[1] + height / 2.0, - ), # upper left - ] - - self.points = all_points - - def create_solid(self): - """Creates a 3d solid using points with straight connections - edges, azimuth_placement_angle and rotation angle. - individual solids in the compound can be accessed using .Solids()[i] - where i is an int - - Returns: - A CadQuery solid: A 3D solid volume - """ - - iter_points = iter(self.points) - pf_coils_set = [] - wires = [] - for point_1, point_2, point_3, point_4 in zip(iter_points, iter_points, iter_points, iter_points): - - solid = cq.Workplane(self.workplane).polyline([point_1[:2], point_2[:2], point_3[:2], point_4[:2]]) - - wire = solid.close() - - wires.append(wire) - - solid = wire.revolve(self.rotation_angle) - - pf_coils_set.append(solid) - - compound = cq.Compound.makeCompound([a.val() for a in pf_coils_set]) - - self.wire = wires - - self.solid = compound - - return compound diff --git a/src/paramak/parametric_components/poloidal_segmenter.py b/src/paramak/parametric_components/poloidal_segmenter.py deleted file mode 100644 index 50f13fe35..000000000 --- a/src/paramak/parametric_components/poloidal_segmenter.py +++ /dev/null @@ -1,158 +0,0 @@ -import math - -import cadquery as cq -from typing import Tuple, Optional -from paramak import Shape, RotateStraightShape -from paramak.utils import coefficients_of_line_from_points, intersect_solid, rotate - - -class PoloidalSegments(RotateStraightShape): - """Creates a ring of wedges from a central point. When provided with a - shape_to_segment the shape will be segmented by the wedges. This is useful - for segmenting geometry into equal poloidal angles. Intended to segment the - firstwall geometry for using in neutron wall loading simulations. - - Args: - center_point: the center of the segmentation wedges (x,z) values (cm). - shape_to_segment: the Shape to segment, if None then the segmenting - solids will be returned. Defaults to None. - number_of_segments (int, optional): the number of equal angles - segments in 360 degrees. Defaults to 10. - max_distance_from_center (float): the maximum distance from the center - point outwards (cm). Defaults to 1000.0. - name (str, optional): defaults to "poloidal_segmenter". - """ - - def __init__( - self, - center_point: Tuple[float, float], - shape_to_segment: Optional[Shape] = None, - number_of_segments: int = 10, - max_distance_from_center: float = 1000.0, - name: str = "poloidal_segmenter", - **kwargs - ): - - super().__init__(name=name, **kwargs) - - self.center_point = center_point - self.shape_to_segment = shape_to_segment - self.number_of_segments = number_of_segments - self.max_distance_from_center = max_distance_from_center - - @property - def number_of_segments(self): - return self._number_of_segments - - @number_of_segments.setter - def number_of_segments(self, value: int): - if isinstance(value, int) is False: - raise TypeError("PoloidalSegmenter.number_of_segments must be an int.") - if value < 1: - raise ValueError("PoloidalSegmenter.number_of_segments must be a minimum of 1.") - self._number_of_segments = value - - @property - def shape_to_segment(self): - return self._shape_to_segment - - @shape_to_segment.setter - def shape_to_segment(self, value): - self._shape_to_segment = value - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, center_point): - self._center_point = center_point - - @property - def max_distance_from_center(self): - return self._max_distance_from_center - - @max_distance_from_center.setter - def max_distance_from_center(self, value): - self._max_distance_from_center = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal segmentation shape.""" - - angle_per_segment = 360.0 / self.number_of_segments - - points = [] - - current_angle = 0 - - outer_point = ( - self.center_point[0] + self.max_distance_from_center, - self.center_point[1], - ) - for i in range(self.number_of_segments): - - points.append(self.center_point) - - outer_point_1 = rotate(self.center_point, outer_point, math.radians(current_angle)) - - outer_point_2 = rotate( - self.center_point, - outer_point, - math.radians(current_angle + angle_per_segment), - ) - - # if the point goes beyond the zero line then set to zero - for new_point in [outer_point_1, outer_point_2]: - if new_point[0] < 0: - m, c = coefficients_of_line_from_points(new_point, self.center_point) - points.append((0, c)) - else: - points.append(new_point) - - current_angle = current_angle + angle_per_segment - - self.points = points - - def create_solid(self): - """Creates a 3d solid using points with straight edges. Individual - solids in the compound can be accessed using .Solids()[i] where i is an - int. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - iter_points = iter(self.points) - triangle_wedges = [] - wires = [] - for p1, p2, p3 in zip(iter_points, iter_points, iter_points): - - solid = cq.Workplane(self.workplane).polyline([p1[:2], p2[:2], p3[:2]]) - - wire = solid.close() - - wires.append(wire) - - solid = wire.revolve(self.rotation_angle) - - triangle_wedges.append(solid) - - self.wire = wires - - if self.shape_to_segment is None: - - compound = cq.Compound.makeCompound([a.val() for a in triangle_wedges]) - - else: - - intersected_solids = [] - for segment in triangle_wedges: - overlap = intersect_solid(segment, self.shape_to_segment) - intersected_solids.append(overlap) - - compound = cq.Compound.makeCompound([a.val() for a in intersected_solids]) - - self.solid = compound - - return compound diff --git a/src/paramak/parametric_components/port_cutters_circular.py b/src/paramak/parametric_components/port_cutters_circular.py deleted file mode 100644 index 71d0f11f6..000000000 --- a/src/paramak/parametric_components/port_cutters_circular.py +++ /dev/null @@ -1,49 +0,0 @@ -from typing import Tuple - -from paramak import ExtrudeCircleShape - - -class PortCutterCircular(ExtrudeCircleShape): - """Creates an extruded shape with a circular section that is used to cut - other components (eg. blanket, vessel,..) in order to create ports. - - Args: - radius: radius (cm) of port cutter. - distance: extruded distance (cm) of the port cutter. - center_point: center point of the port cutter. Defaults to (0, 0). - workplane: workplane in which the port cutters are created. Defaults - to "ZY". - rotation_axis: axis around which the port cutters are rotated and - placed. Defaults to "Z". - extrusion_start_offset: the distance between 0 and the start of the - extrusion. Defaults to 1.. - name: defaults to "circular_port_cutter". - """ - - def __init__( - self, - radius: float, - distance: float, - center_point: Tuple[float, float] = (0, 0), - workplane: str = "ZY", - rotation_axis: str = "Z", - extrusion_start_offset: float = 1.0, - name: str = "circular_port_cutter", - **kwargs - ): - super().__init__( - workplane=workplane, - rotation_axis=rotation_axis, - extrusion_start_offset=extrusion_start_offset, - radius=radius, - extrude_both=False, - name=name, - distance=distance, - **kwargs - ) - - self.radius = radius - self.center_point = center_point - - def find_points(self): - self.points = [self.center_point] diff --git a/src/paramak/parametric_components/port_cutters_rectangular.py b/src/paramak/parametric_components/port_cutters_rectangular.py deleted file mode 100644 index 7a8db6ebb..000000000 --- a/src/paramak/parametric_components/port_cutters_rectangular.py +++ /dev/null @@ -1,84 +0,0 @@ -from typing import Tuple - -from paramak import ExtrudeStraightShape - - -class PortCutterRectangular(ExtrudeStraightShape): - """Creates an extruded shape with a rectangular section that is used to cut - other components (eg. blanket, vessel,..) in order to create ports. - - Args: - height: height (cm) of the port cutter. - width: width (cm) of the port cutter. - distance: extruded distance (cm) of the port cutter. - center_point: Center point of the port cutter. Defaults to (0, 0). - workplane: workplane in which the port cutters are created. Defaults - to "ZY". - rotation_axis: axis around which the port cutters are rotated and - placed. Defaults to "Z". - extrusion_start_offset (float, optional): the distance between 0 and - the start of the extrusion. Defaults to 1.. - fillet_radius (float, optional): If not None, radius (cm) of fillets - added to edges orthogonal to the Z direction. Defaults to None. - name (str, optional): defaults to "rectangular_port_cutter". - """ - - def __init__( - self, - height: float, - width: float, - distance: float, - center_point: Tuple[float, float] = (0, 0), - workplane: str = "ZY", - rotation_axis: str = "Z", - extrusion_start_offset: float = 1.0, - fillet_radius: float = None, - name: str = "rectangular_port_cutter", - **kwargs - ): - - super().__init__( - workplane=workplane, - rotation_axis=rotation_axis, - extrusion_start_offset=extrusion_start_offset, - extrude_both=False, - name=name, - distance=distance, - **kwargs - ) - - self.height = height - self.width = width - self.center_point = center_point - self.fillet_radius = fillet_radius - - def find_points(self): - if self.workplane[0] < self.workplane[1]: - parameter_1 = self.width - parameter_2 = self.height - else: - parameter_1 = self.height - parameter_2 = self.width - - points = [ - (-parameter_1 / 2, parameter_2 / 2), - (parameter_1 / 2, parameter_2 / 2), - (parameter_1 / 2, -parameter_2 / 2), - (-parameter_1 / 2, -parameter_2 / 2), - ] - points = [(e[0] + self.center_point[0], e[1] + self.center_point[1]) for e in points] - - self.points = points - - def add_fillet(self, solid): - if "X" not in self.workplane: - filleting_edge = "|X" - if "Y" not in self.workplane: - filleting_edge = "|Y" - if "Z" not in self.workplane: - filleting_edge = "|Z" - - if self.fillet_radius is not None and self.fillet_radius != 0: - solid = solid.edges(filleting_edge).fillet(self.fillet_radius) - - return solid diff --git a/src/paramak/parametric_components/port_cutters_rotated.py b/src/paramak/parametric_components/port_cutters_rotated.py deleted file mode 100644 index d157dc89a..000000000 --- a/src/paramak/parametric_components/port_cutters_rotated.py +++ /dev/null @@ -1,110 +0,0 @@ -import math - -from paramak import RotateStraightShape -from paramak.utils import rotate - - -class PortCutterRotated(RotateStraightShape): - """Creates wedges from a central point with angular extent in polar - direction. To control the width the rotation_angle argument can be used. - This is useful as a cutting volume for the creation of ports in blankets. - - Args: - center_point (tuple of floats): the center point where the - ports are aimed towards, typically the center of the plasma. - polar_coverage_angle (float): the angular extent of port in the - polar direction (degrees). Defaults to 10.0. - polar_placement_angle (float): The angle used when rotating the shape - on the polar axis. 0 degrees is the outboard equatorial point. - Defaults to 0.0. - max_distance_from_center (float): the maximum distance from the center - point outwards (cm). Default 3000.0. - fillet_radius (float, optional): If not None, radius (cm) of fillets - added to all edges. Defaults to 0.0. - rotation_angle (float, optional): defaults to 10.0. - name (str, optional): defaults to "port_cutter". - """ - - def __init__( - self, - center_point, - polar_coverage_angle=10.0, - polar_placement_angle=0.0, - max_distance_from_center=3000.0, - fillet_radius=0.0, - rotation_angle=10.0, - name="port_cutter", - **kwargs - ): - - super().__init__(name=name, rotation_angle=rotation_angle, **kwargs) - - self.center_point = center_point - self.polar_coverage_angle = polar_coverage_angle - self.polar_placement_angle = polar_placement_angle - self.max_distance_from_center = max_distance_from_center - self.fillet_radius = fillet_radius - - self.add_fillet() - - @property - def polar_coverage_angle(self): - return self._polar_coverage_angle - - @polar_coverage_angle.setter - def polar_coverage_angle(self, value): - if value > 180: - msg = "polar_coverage_angle must be greater than 180.0" - raise ValueError(msg) - self._polar_coverage_angle = value - - @property - def center_point(self): - return self._center_point - - @center_point.setter - def center_point(self, center_point): - self._center_point = center_point - - @property - def max_distance_from_center(self): - return self._max_distance_from_center - - @max_distance_from_center.setter - def max_distance_from_center(self, value): - self._max_distance_from_center = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe the - 2D profile of the port cutter.""" - - points = [self.center_point] - - outer_point = ( - self.center_point[0] + self.max_distance_from_center, - self.center_point[1], - ) - - outer_point_rotated = rotate(self.center_point, outer_point, math.radians(self.polar_placement_angle)) - - outer_point_1 = rotate( - self.center_point, - outer_point_rotated, - math.radians(0.5 * self.polar_coverage_angle), - ) - - outer_point_2 = rotate( - self.center_point, - outer_point_rotated, - math.radians(-0.5 * self.polar_coverage_angle), - ) - - points.append(outer_point_1) - points.append(outer_point_2) - - self.points = points - - def add_fillet(self): - """adds fillets to all edges""" - if self.fillet_radius != 0: - self.solid = self.solid.edges().fillet(self.fillet_radius) diff --git a/src/paramak/parametric_components/rotated_isosceles_triangle.py b/src/paramak/parametric_components/rotated_isosceles_triangle.py deleted file mode 100644 index 6fb3d5f36..000000000 --- a/src/paramak/parametric_components/rotated_isosceles_triangle.py +++ /dev/null @@ -1,95 +0,0 @@ -import math -from typing import Tuple -from paramak import RotateStraightShape -from paramak.utils import rotate - - -class RotatedIsoscelesTriangle(RotateStraightShape): - """Creates a rotated triangle (truncated triangle) shape. - - Args: - base_length: the length of the base of the triangle (cm). - height: the height of the triangle (cm). - pivot_point: the coordinates of the tip of the triangle at the opposite - side to the base of the triangle. - pivot_angle: the angle (in degrees) to pivot (rotate) the shape by - around the pivot point. Defaults to 0. - name: defaults to "rotated_triangle". - """ - - def __init__( - self, - base_length: float, - height: float, - pivot_point: Tuple[float, float], - pivot_angle: float = 0.0, - name: str = "rotated_triangle", - **kwargs - ): - - super().__init__(name=name, **kwargs) - - self.base_length = base_length - self.height = height - self.pivot_point = pivot_point - self.pivot_angle = pivot_angle - - @property - def pivot_point(self): - return self._pivot_point - - @pivot_point.setter - def pivot_point(self, pivot_point): - self._pivot_point = pivot_point - - @property - def base_length(self): - return self._base_length - - @base_length.setter - def base_length(self, base_length): - self._base_length = base_length - - @property - def height(self): - return self._height - - @height.setter - def height(self, height): - self._height = height - - @property - def pivot_angle(self): - return self._pivot_angle - - @pivot_angle.setter - def pivot_angle(self, pivot_angle): - self._pivot_angle = pivot_angle - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the triangle shape.""" - - non_rotated_points = [ - self.pivot_point, - ( - self.pivot_point[0] - self.base_length / 2.0, - self.pivot_point[1] - self.height, - ), - ( - self.pivot_point[0] + self.base_length / 2.0, - self.pivot_point[1] - self.height, - ), - ] - - points = [] - - for point in non_rotated_points: - x, y = rotate( - origin=self.pivot_point, - point=point, - angle=math.radians(self.pivot_angle), - ) - points.append((x, y)) - - self.points = points diff --git a/src/paramak/parametric_components/rotated_trapezoid.py b/src/paramak/parametric_components/rotated_trapezoid.py deleted file mode 100644 index 889b427cc..000000000 --- a/src/paramak/parametric_components/rotated_trapezoid.py +++ /dev/null @@ -1,107 +0,0 @@ -import math -from typing import Tuple -from paramak import RotateStraightShape -from paramak.utils import rotate - - -class RotatedTrapezoid(RotateStraightShape): - """Creates a rotated trapezoid (truncated triangle) shape. - - Args: - length_1: the length of the top parallel edge of the trapezoid (cm). - length_2: the length of the base parallel edge of the trapezoid (cm). - length_3: the height of the trapezoid, the distances from top to base (cm). - pivot_point: the coordinates of the center of rotation (x,z). The - pivot point is located in the center of the length_1 edge (cm). - pivot_angle: the angle (in degrees) to pivot (rotate) the shape by - around the pivot point. Defaults to 0. - name: defaults to "rotated_trapezoid". - """ - - def __init__( - self, - length_1: float, - length_2: float, - length_3: float, - pivot_point: Tuple[float, float], - pivot_angle: float = 0.0, - name: str = "rotated_trapezoid", - **kwargs - ): - - super().__init__(name=name, **kwargs) - - self.length_1 = length_1 - self.length_2 = length_2 - self.length_3 = length_3 - self.pivot_point = pivot_point - self.pivot_angle = pivot_angle - - @property - def pivot_point(self): - return self._pivot_point - - @pivot_point.setter - def pivot_point(self, pivot_point): - self._pivot_point = pivot_point - - @property - def length_1(self): - return self._length_1 - - @length_1.setter - def length_1(self, length_1): - self._length_1 = length_1 - - @property - def length_2(self): - return self._length_2 - - @length_2.setter - def length_2(self, length_2): - self._length_2 = length_2 - - @property - def length_3(self): - return self._length_3 - - @length_3.setter - def length_3(self, length_3): - self._length_3 = length_3 - - @property - def pivot_angle(self): - return self._pivot_angle - - @pivot_angle.setter - def pivot_angle(self, pivot_angle): - self._pivot_angle = pivot_angle - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the trapezoid shape.""" - - non_rotated_points = [ - (self.pivot_point[0] + self.length_1 / 2.0, self.pivot_point[1]), - (self.pivot_point[0] - self.length_1 / 2.0, self.pivot_point[1]), - ( - self.pivot_point[0] - self.length_2 / 2.0, - self.pivot_point[1] - self.length_3, - ), - ( - self.pivot_point[0] + self.length_2 / 2.0, - self.pivot_point[1] - self.length_3, - ), - ] - - points = [] - - for point in non_rotated_points: - x, y = rotate( - origin=self.pivot_point, - point=point, - angle=math.radians(self.pivot_angle), - ) - points.append((x, y)) - - self.points = points diff --git a/src/paramak/parametric_components/shell_fs.py b/src/paramak/parametric_components/shell_fs.py deleted file mode 100644 index 14d22eaf1..000000000 --- a/src/paramak/parametric_components/shell_fs.py +++ /dev/null @@ -1,63 +0,0 @@ -import cadquery as cq - -from paramak import Shape - - -class ShellFS(Shape): - """Shell From Shape. Creates a shell casing for the provided shape object. - Warning some shapes are too complex to shell. If using a rotated shape then - setting the rotation angle to 360 can simplify the shell. Then intersecting - the resulting shell with the WedgeCutterFs can reduce the shell back down - to the original rotation angle of the shape. - - Args: - shape: the shape to create a shell / 3D offset around - thickness: the thickness of the shell casing around the shape (cm). - Passed directly to CadQuery.shell(). Defaults to 10.0. - kind: the method used to connect gaps in the resulting shelled shape. - Options include 'arc' or 'intersection'. Use 'arc' for rounded - edges 'intersection' for sharp edges. Passed directly to - CadQuery.shell(). Defaults to intersection. - """ - - def __init__(self, shape: Shape, thickness: float = 10.0, kind: str = "intersection", **kwargs): - - super().__init__(**kwargs) - - self.shape = shape - self.thickness = thickness - self.kind = kind - - @property - def shape(self): - return self._shape - - @shape.setter - def shape(self, value): - self._shape = value - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, thickness): - self._thickness = thickness - - def create_solid(self): - """Creates a 3D solid by creating a shell around a Shape""" - - if isinstance(self.shape, cq.Workplane): - solid = self.shape.shell( - thickness=self.thickness, - kind=self.kind, - ) - else: - solid = self.shape.solid.shell( - thickness=self.thickness, - kind=self.kind, - ) - - self.solid = solid - - return solid diff --git a/src/paramak/parametric_components/tf_coil_casing.py b/src/paramak/parametric_components/tf_coil_casing.py deleted file mode 100644 index 4dd4ac40f..000000000 --- a/src/paramak/parametric_components/tf_coil_casing.py +++ /dev/null @@ -1,131 +0,0 @@ -import warnings - -from paramak import ExtrudeMixedShape, ExtrudeStraightShape -from paramak.utils import add_thickness, cut_solid, union_solid - - -class TFCoilCasing(ExtrudeMixedShape): - """Casing component for TF coils - - Args: - magnet: TF coil shape - inner_offset: radial distance between inner coil surface and inner - casing surface (cm) - outer_offset: radial distance between outer coil surface and outer - casing surface (cm) - vertical_section_offset: radial distance between outer coil surface and - outer vertical section surface (cm) - distance: extrusion distance (cm) - """ - - def __init__( - self, magnet, inner_offset: float, outer_offset: float, vertical_section_offset: float, **kwargs - ) -> None: - - self.magnet = magnet - - super().__init__(**kwargs) - - self.inner_offset = inner_offset - self.outer_offset = outer_offset - self.vertical_section_offset = vertical_section_offset - self.leg_shape = ExtrudeStraightShape( - distance=self.distance, - azimuth_placement_angle=self.azimuth_placement_angle, - workplane=self.magnet.workplane, - ) - self.inner_bore_cutting_points = None - self.workplane = self.magnet.workplane - - @property - def azimuth_placement_angle(self): - self.azimuth_placement_angle = self.magnet.azimuth_placement_angle - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - correct_angles = self.magnet.azimuth_placement_angle - if value != correct_angles: - msg = "Casing azimuth_placement_angle should be the" "same value as TFCoilCasing.magnet." - warnings.warn(msg, UserWarning) - self._azimuth_placement_angle = correct_angles - - def find_points(self): - inner_points_magnet = self.magnet.inner_points - outer_points_magnet = self.magnet.outer_points - inner_points_magnet = (inner_points_magnet[:, 0], inner_points_magnet[:, 1]) - outer_points_magnet = (outer_points_magnet[:, 0], outer_points_magnet[:, 1]) - inner_points = add_thickness( - *inner_points_magnet, - thickness=-self.inner_offset, - ) - - outer_points = add_thickness(*outer_points_magnet, thickness=-self.outer_offset) - curve_points = [] - for distrib_points in [inner_points, outer_points]: - curve_points.append([[R, Z, "spline"] for R, Z in zip(distrib_points[0], distrib_points[1])]) - - curve_points[0][-1][2] = "straight" - curve_points[1][-1][2] = "straight" - - points = curve_points[0] + curve_points[1] - self.points = points - - ya = outer_points[1][outer_points[0].index(min(outer_points[0], key=lambda x: abs(x - min(inner_points[0]))))] - self.leg_points = [ - ( - min(outer_points[0]) - self.vertical_section_offset + self.outer_offset, - min(outer_points[1]), - ), - ( - outer_points[0][outer_points[1].index(min(outer_points[1]))], - min(outer_points[1]), - ), - ( - inner_points[0][inner_points[1].index(min(inner_points[1]))], - min(inner_points[1]), - ), - (min(inner_points[0]), min(ya, self.magnet.vertical_displacement - ya)), - # not having this line avoid unexpected surfaces - (inner_points[0][-1], inner_points[1][-1]), - (min(inner_points[0]), max(ya, self.magnet.vertical_displacement - ya)), - ( - inner_points[0][inner_points[1].index(min(inner_points[1]))], - max(inner_points[1]), - ), - ( - outer_points[0][outer_points[1].index(min(outer_points[1]))], - max(outer_points[1]), - ), - ( - min(outer_points[0]) - self.vertical_section_offset + self.outer_offset, - max(outer_points[1]), - ), - ] - - self.inner_bore_cutting_points = [ - (0, self.leg_points[0][1]), - self.leg_points[0], - self.leg_points[-1], - (0, self.leg_points[-1][1]), - ] - - def create_solid(self): - solid = super().create_solid() - - self.leg_shape.points = self.leg_points - self.leg_shape.distance = self.distance - self.leg_shape.azimuth_placement_angle = self.azimuth_placement_angle - solid = union_solid(solid, self.leg_shape) - solid = cut_solid(solid, self.magnet) - - # cut away excess casing outlined in #789 - inner_bore_cutting_shape = ExtrudeStraightShape( - points=self.inner_bore_cutting_points, - distance=self.distance, - azimuth_placement_angle=self.azimuth_placement_angle, - ) - solid = cut_solid(solid, inner_bore_cutting_shape) - - self.solid = solid - return solid diff --git a/src/paramak/parametric_components/tokamak_plasma.py b/src/paramak/parametric_components/tokamak_plasma.py deleted file mode 100644 index e7b74e3c5..000000000 --- a/src/paramak/parametric_components/tokamak_plasma.py +++ /dev/null @@ -1,201 +0,0 @@ -import numpy as np - -from paramak import RotateSplineShape - - -class Plasma(RotateSplineShape): - """Creates a double null tokamak plasma shape that is controlled by 4 - shaping parameters. - - Args: - elongation: the elongation of the plasma. - major_radius: the major radius of the plasma (cm). - minor_radius: the minor radius of the plasma (cm). - triangularity: the triangularity of the plasma. - vertical_displacement: the vertical_displacement of the plasma (cm).. - num_points: number of points to describe the shape. - configuration: plasma configuration ("non-null", "single-null", "double-null"). - x_point_shift: shift parameters for locating the X points in [0, 1].. - name: - """ - - def __init__( - self, - elongation: float = 2.0, - major_radius: float = 450.0, - minor_radius: float = 150.0, - triangularity: float = 0.55, - vertical_displacement: float = 0.0, - num_points: float = 50, - configuration: str = "non-null", - x_point_shift: float = 0.1, - name: str = "plasma", - **kwargs - ): - - super().__init__(name=name, **kwargs) - - # properties needed for plasma shapes - self.elongation = elongation - self.major_radius = major_radius - self.minor_radius = minor_radius - self.triangularity = triangularity - self.vertical_displacement = vertical_displacement - self.num_points = num_points - self.configuration = configuration - self.x_point_shift = x_point_shift - - self.outer_equatorial_point = None - self.inner_equatorial_point = None - self.high_point = None - self.low_point = None - - @property - def high_point(self): - self.high_point = ( - self.major_radius - self.triangularity * self.minor_radius, - self.elongation * self.minor_radius + self.vertical_displacement, - ) - return self._high_point - - @high_point.setter - def high_point(self, value): - self._high_point = value - - @property - def low_point(self): - self.low_point = ( - self.major_radius - self.triangularity * self.minor_radius, - -self.elongation * self.minor_radius + self.vertical_displacement, - ) - return self._low_point - - @low_point.setter - def low_point(self, value): - self._low_point = value - - @property - def outer_equatorial_point(self): - self.outer_equatorial_point = ( - self.major_radius + self.minor_radius, - self.vertical_displacement, - ) - return self._outer_equatorial_point - - @outer_equatorial_point.setter - def outer_equatorial_point(self, value): - self._outer_equatorial_point = value - - @property - def inner_equatorial_point(self): - self.inner_equatorial_point = ( - self.major_radius - self.minor_radius, - self.vertical_displacement, - ) - return self._inner_equatorial_point - - @inner_equatorial_point.setter - def inner_equatorial_point(self, value): - self._inner_equatorial_point = value - - @property - def lower_x_point(self): - self.compute_x_points() - return self._lower_x_point - - @lower_x_point.setter - def lower_x_point(self, value): - self._lower_x_point = value - - @property - def upper_x_point(self): - self.compute_x_points() - return self._upper_x_point - - @upper_x_point.setter - def upper_x_point(self, value): - self._upper_x_point = value - - @property - def vertical_displacement(self): - return self._vertical_displacement - - @vertical_displacement.setter - def vertical_displacement(self, value): - self._vertical_displacement = value - - @property - def minor_radius(self): - return self._minor_radius - - @minor_radius.setter - def minor_radius(self, value): - if value < 1: - raise ValueError("minor_radius is out of range") - else: - self._minor_radius = value - - @property - def major_radius(self): - return self._major_radius - - @major_radius.setter - def major_radius(self, value): - if value < 1: - raise ValueError("major_radius is out of range") - else: - self._major_radius = value - - @property - def elongation(self): - return self._elongation - - @elongation.setter - def elongation(self, value): - if value > 10 or value < 0: - raise ValueError("elongation is out of range") - else: - self._elongation = value - - def compute_x_points(self): - """Computes the location of X points based on plasma parameters and - configuration - - Returns: - ((float, float), (float, float)): lower and upper x points - coordinates. None if no x points - """ - lower_x_point, upper_x_point = None, None # non-null config - shift = self.x_point_shift - elongation = self.elongation - triangularity = self.triangularity - if self.configuration in ["single-null", "double-null"]: - # no X points for non-null config - lower_x_point = ( - 1 - (1 + shift) * triangularity * self.minor_radius, - -(1 + shift) * elongation * self.minor_radius + self.vertical_displacement, - ) - - if self.configuration == "double-null": - # upper_x_point is up-down symmetrical - upper_x_point = ( - lower_x_point[0], - (1 + shift) * elongation * self.minor_radius + self.vertical_displacement, - ) - self.lower_x_point = lower_x_point - self.upper_x_point = upper_x_point - - def find_points(self): - """Finds the XZ points that describe the 2D profile of the plasma.""" - - # create array of angles theta - theta = np.linspace(0, 2 * np.pi, num=self.num_points, endpoint=False) - - # parametric equations for plasma - def R(theta): - return self.major_radius + self.minor_radius * np.cos(theta + self.triangularity * np.sin(theta)) - - def Z(theta): - return self.elongation * self.minor_radius * np.sin(theta) + self.vertical_displacement - - self.points = np.stack((R(theta), Z(theta)), axis=1).tolist() diff --git a/src/paramak/parametric_components/tokamak_plasma_from_points.py b/src/paramak/parametric_components/tokamak_plasma_from_points.py deleted file mode 100644 index ed9918c4b..000000000 --- a/src/paramak/parametric_components/tokamak_plasma_from_points.py +++ /dev/null @@ -1,65 +0,0 @@ -from typing import Tuple -from paramak import Plasma - - -class PlasmaFromPoints(Plasma): - """Creates a double null tokamak plasma shape that is controlled by 3 - coordinates. - - Args: - outer_equatorial_x_point: the x value of the outer equatorial of the - plasma (cm). - inner_equatorial_x_point: the x value of the inner equatorial of the - plasma (cm). - high_point (tuple of 2 floats): the (x,z) coordinate values of the top - of the plasma (cm). - """ - - def __init__( - self, - outer_equatorial_x_point: Tuple[float, float], - inner_equatorial_x_point: Tuple[float, float], - high_point: Tuple[float, float], - **kwargs - ): - - minor_radius = (outer_equatorial_x_point - inner_equatorial_x_point) / 2.0 - major_radius = inner_equatorial_x_point + minor_radius - elongation = high_point[1] / minor_radius - triangularity = (major_radius - high_point[0]) / minor_radius - - super().__init__( - elongation=elongation, - major_radius=major_radius, - minor_radius=minor_radius, - triangularity=triangularity, - **kwargs - ) - - self.outer_equatorial_x_point = outer_equatorial_x_point - self.inner_equatorial_x_point = inner_equatorial_x_point - self.high_point = high_point - - @property - def outer_equatorial_x_point(self): - return self._outer_equatorial_x_point - - @outer_equatorial_x_point.setter - def outer_equatorial_x_point(self, value): - self._outer_equatorial_x_point = value - - @property - def inner_equatorial_x_point(self): - return self._inner_equatorial_x_point - - @inner_equatorial_x_point.setter - def inner_equatorial_x_point(self, value): - self._inner_equatorial_x_point = value - - @property - def high_point(self): - return self._high_point - - @high_point.setter - def high_point(self, value): - self._high_point = value diff --git a/src/paramak/parametric_components/tokamak_plasma_plasmaboundaries.py b/src/paramak/parametric_components/tokamak_plasma_plasmaboundaries.py deleted file mode 100644 index 0ee60a681..000000000 --- a/src/paramak/parametric_components/tokamak_plasma_plasmaboundaries.py +++ /dev/null @@ -1,76 +0,0 @@ -from plasmaboundaries import get_separatrix_coordinates - -from paramak import Plasma - - -class PlasmaBoundaries(Plasma): - """Creates a double null tokamak plasma shape that is controlled - by 5 shaping parameters using the plasmaboundaries package to calculate - points. For more details see: - http://github.com/fusion-energy/plasmaboundaries - - Args: - A: plasma parameter see plasmaboundaries doc. - elongation: the elongation of the plasma. - major_radius: the major radius of the plasma (cm). - minor_radius: the minor radius of the plasma (cm). - triangularity: the triangularity of the plasma. - vertical_displacement: the vertical_displacement of the plasma (cm). - configuration (str, optional): plasma configuration ("non-null", "single-null", "double-null"). - x_point_shift: Shift parameters for locating the X points in [0, 1]. Defaults to 0.1. - """ - - def __init__( - self, - A: float = 0.05, - elongation: float = 2.0, - major_radius: float = 450.0, - minor_radius: float = 150.0, - triangularity: float = 0.55, - vertical_displacement: float = 0.0, - configuration: str = "non-null", - x_point_shift: float = 0.1, - **kwargs - ): - - super().__init__( - elongation=elongation, - major_radius=major_radius, - minor_radius=minor_radius, - triangularity=triangularity, - vertical_displacement=vertical_displacement, - configuration=configuration, - x_point_shift=x_point_shift, - **kwargs - ) - - # properties needed for plasma shapes - self.A = A - - def find_points(self): - """Finds the XZ points that describe the 2D profile of the plasma.""" - aspect_ratio = self.minor_radius / self.major_radius - params = { - "A": self.A, - "aspect_ratio": aspect_ratio, - "elongation": self.elongation, - "triangularity": self.triangularity, - } - points = get_separatrix_coordinates(params, self.configuration) - # add vertical displacement - points[:, 1] += self.vertical_displacement - # rescale to cm - points[:] *= self.major_radius - - # remove unnecessary points - # if non-null these are the y bounds - lower_point_y = self.low_point[1] - upper_point_y = self.high_point[1] - # else use x points - if self.configuration in ["single-null", "double-null"]: - lower_point_y = self.lower_x_point[1] - if self.configuration == "double-null": - upper_point_y = self.upper_x_point[1] - - points = points[(points[:, 1] >= lower_point_y) & (points[:, 1] <= upper_point_y)] - self.points = points.tolist()[:-1] diff --git a/src/paramak/parametric_components/toroidal_field_coil.py b/src/paramak/parametric_components/toroidal_field_coil.py deleted file mode 100644 index a62fc4110..000000000 --- a/src/paramak/parametric_components/toroidal_field_coil.py +++ /dev/null @@ -1,114 +0,0 @@ -from typing import Optional, Tuple - -import numpy as np - -from paramak import ExtrudeMixedShape, ExtrudeStraightShape - - -class ToroidalFieldCoil(ExtrudeMixedShape): - """Toroidal field coil based on Princeton-D curve - - Args: - thickness: magnet thickness (cm) - distance: extrusion distance (cm) - number_of_coils: the number of tf coils. This changes by the - azimuth_placement_angle dividing up 360 degrees by the number of - coils. - vertical_displacement: vertical displacement (cm). Defaults to 0.0. - with_inner_leg: Include the inner tf leg. Defaults to True. - azimuth_start_angle: The azimuth angle to for the first TF coil which - offsets the placement of coils around the azimuthal angle - rotation_angle: rotation angle of solid created. A cut is performed - from rotation_angle to 360 degrees. Defaults to 360.0. - """ - - def __init__( - self, - thickness: float, - distance: float, - number_of_coils: int, - vertical_displacement: float = 0.0, - with_inner_leg: bool = True, - azimuth_start_angle: float = 0, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = (0.0, 0.0, 1.0), - **kwargs - ) -> None: - - super().__init__(distance=distance, color=color, **kwargs) - - self.thickness = thickness - self.distance = distance - self.number_of_coils = number_of_coils - self.vertical_displacement = vertical_displacement - self.with_inner_leg = with_inner_leg - self.azimuth_start_angle = azimuth_start_angle - self.rotation_angle = rotation_angle - self.inner_leg_connection_points = None - - @property - def azimuth_placement_angle(self): - self.find_azimuth_placement_angle() - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self._azimuth_placement_angle = value - - def find_azimuth_placement_angle(self): - """Calculates the azimuth placement angles based on the number of tf - coils""" - - angles = list( - np.linspace( - self.azimuth_start_angle, - 360 + self.azimuth_start_angle, - self.number_of_coils, - endpoint=False, - ) - ) - - self.azimuth_placement_angle = angles - - def create_solid(self): - """Creates a 3d solid using points with straight edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - if self.with_inner_leg: - outer_leg = ExtrudeMixedShape( - name=self.name, - points=self.points, - distance=self.distance, - azimuth_placement_angle=self.azimuth_placement_angle, - color=self.color, - rotation_angle=self.rotation_angle, - ) - inner_leg = ExtrudeStraightShape( - name=self.name, - points=self.inner_leg_connection_points, - distance=self.distance, - azimuth_placement_angle=self.azimuth_placement_angle, - color=self.color, - rotation_angle=self.rotation_angle, - union=[outer_leg], - ) - solids = inner_leg.solid - else: - outer_leg = ExtrudeMixedShape( - name=self.name, - points=self.points, - distance=self.distance, - azimuth_placement_angle=self.azimuth_placement_angle, - color=self.color, - rotation_angle=self.rotation_angle, - ) - solids = outer_leg.solid - - # TODO check the wires are made correctly - # self.wire = wires - - self.solid = solids - return solids diff --git a/src/paramak/parametric_components/toroidal_field_coil_coat_hanger.py b/src/paramak/parametric_components/toroidal_field_coil_coat_hanger.py deleted file mode 100644 index aed5109ba..000000000 --- a/src/paramak/parametric_components/toroidal_field_coil_coat_hanger.py +++ /dev/null @@ -1,202 +0,0 @@ -import math -from typing import Optional, Tuple - -from .toroidal_field_coil import ToroidalFieldCoil -from paramak.utils import rotate, patch_workplane - -patch_workplane() - - -class ToroidalFieldCoilCoatHanger(ToroidalFieldCoil): - """Creates a coat hanger shaped toroidal field coil. - - Args: - horizontal_start_point: the (x,z) coordinates of the inner upper - point (cm). - horizontal_length: the radial length of the horizontal section of - the TF coil (cm). - vertical_mid_point: the (x,z) coordinates of the mid point of the - outboard vertical section (cm). - vertical_length: the radial length of the outboard vertical section - of the TF coil (cm). - thickness: the thickness of the toroidal field coil. - distance: the extrusion distance. - number_of_coils: the number of TF coils. This changes with - azimuth_placement_angle dividing up 360 degrees by the number of - coils. - with_inner_leg: Include the inner TF leg. Defaults to True. - azimuth_start_angle: The azimuth angle to for the first TF coil which - offsets the placement of coils around the azimuthal angle - """ - - def __init__( - self, - name: str = "toroidal_field_coil", - horizontal_start_point: Tuple[float, float] = (40, 200), - horizontal_length: float = 200, - vertical_mid_point: Tuple[float, float] = (400, 0), - vertical_length: float = 250, - thickness: float = 30, - distance: float = 20, - number_of_coils: int = 12, - with_inner_leg: bool = True, - azimuth_start_angle: float = 0, - vertical_displacement: float = 0.0, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = (0.0, 0.0, 1.0), - **kwargs - ) -> None: - - super().__init__( - name=name, - thickness=thickness, - number_of_coils=number_of_coils, - vertical_displacement=vertical_displacement, - with_inner_leg=with_inner_leg, - azimuth_start_angle=azimuth_start_angle, - rotation_angle=rotation_angle, - distance=distance, - color=color, - **kwargs - ) - - self.horizontal_start_point = horizontal_start_point - self.horizontal_length = horizontal_length - self.vertical_mid_point = vertical_mid_point - self.vertical_length = vertical_length - - def find_points(self): - """Finds the XZ points joined by straight connections that describe the - 2D profile of the poloidal field coil shape.""" - - # 16---15 - # - - - # - 14 - # - - - # 1---2 - - # - - - # - 13 - # - - - # 3 12 - # - - - # - - - # - - - # 4 11 - # - - - # - 10 - # - - - # 6---5 - - # - - - # - 9 - # - - - # 7---8 - - adjacent_length = self.vertical_mid_point[0] - (self.horizontal_start_point[0] + self.horizontal_length) - oppersite_length = self.horizontal_start_point[1] - (self.vertical_mid_point[1] + 0.5 * self.vertical_length) - - point_rotation = math.atan(oppersite_length / adjacent_length) - point_rotation_mid = math.radians(90) - point_rotation - - points = [ - self.horizontal_start_point, # point 1 - ( - self.horizontal_start_point[0] + self.horizontal_length, - self.horizontal_start_point[1], - ), # point 2 - ( - self.vertical_mid_point[0], - self.vertical_mid_point[1] + 0.5 * self.vertical_length, - ), # point 3 - ( - self.vertical_mid_point[0], - self.vertical_mid_point[1] - 0.5 * self.vertical_length, - ), # point 4 - ( - self.horizontal_start_point[0] + self.horizontal_length, - -self.horizontal_start_point[1], - ), # point 5 - ( - self.horizontal_start_point[0], - -self.horizontal_start_point[1], - ), # point 6 - ( - self.horizontal_start_point[0], - -self.horizontal_start_point[1] - self.thickness, - ), # point 7 - ( - self.horizontal_start_point[0] + self.horizontal_length, - -self.horizontal_start_point[1] - self.thickness, - ), # point 8 - rotate( - ( - self.horizontal_start_point[0] + self.horizontal_length, - -self.horizontal_start_point[1], - ), # same as point 5 - ( - self.horizontal_start_point[0] + self.horizontal_length, - -self.horizontal_start_point[1] - self.thickness, - ), # same as point 8 - point_rotation, - ), # point 9 - rotate( - ( - self.vertical_mid_point[0], - self.vertical_mid_point[1] - 0.5 * self.vertical_length, - ), # same as point 4 - ( - self.vertical_mid_point[0] + self.thickness, - self.vertical_mid_point[1] - 0.5 * self.vertical_length, - ), # same as point 11 - -point_rotation_mid, - ), # point 10 - ( - self.vertical_mid_point[0] + self.thickness, - self.vertical_mid_point[1] - 0.5 * self.vertical_length, - ), # point 11 - ( - self.vertical_mid_point[0] + self.thickness, - self.vertical_mid_point[1] + 0.5 * self.vertical_length, - ), # point 12 - rotate( - ( - self.vertical_mid_point[0], - self.vertical_mid_point[1] + 0.5 * self.vertical_length, - ), # same as point 3 - ( - self.vertical_mid_point[0] + self.thickness, - self.vertical_mid_point[1] + 0.5 * self.vertical_length, - ), # same as point 12 - point_rotation_mid, - ), # point 13 - rotate( - ( - self.horizontal_start_point[0] + self.horizontal_length, - self.horizontal_start_point[1], - ), # same as point 2 - ( - self.horizontal_start_point[0] + self.horizontal_length, - self.horizontal_start_point[1] + self.thickness, - ), # same as point 15 - -point_rotation, - ), # point 14 - ( - self.horizontal_start_point[0] + self.horizontal_length, - self.horizontal_start_point[1] + self.thickness, - ), # point 15 - ( - self.horizontal_start_point[0], - self.horizontal_start_point[1] + self.thickness, - ), # point 16 - ] - - self.inner_leg_connection_points = [ - points[0], - (points[0][0] + self.thickness, points[0][1]), - (points[5][0] + self.thickness, points[5][1]), - points[5], - ] - - # adds any vertical displacement and the connection type to the points - points = [(point[0], point[1] + self.vertical_displacement, "straight") for point in points] - - self.points = points diff --git a/src/paramak/parametric_components/toroidal_field_coil_princeton_d.py b/src/paramak/parametric_components/toroidal_field_coil_princeton_d.py deleted file mode 100644 index b02936e97..000000000 --- a/src/paramak/parametric_components/toroidal_field_coil_princeton_d.py +++ /dev/null @@ -1,181 +0,0 @@ -from typing import Optional, Tuple - -import numpy as np -from scipy import integrate -from scipy.optimize import minimize - -from .toroidal_field_coil import ToroidalFieldCoil -from paramak.utils import add_thickness - - -class ToroidalFieldCoilPrincetonD(ToroidalFieldCoil): - """Toroidal field coil based on Princeton-D curve - - Args: - R1: smallest radius (cm) - R2: largest radius (cm) - thickness: magnet thickness (cm) - distance: extrusion distance (cm) - number_of_coils: the number of tf coils. This changes by the - azimuth_placement_angle dividing up 360 degrees by the number of - coils. - vertical_displacement: vertical displacement (cm). Defaults to 0.0. - with_inner_leg: Include the inner tf leg. Defaults to True. - azimuth_start_angle: The azimuth angle to for the first TF coil which - offsets the placement of coils around the azimuthal angle - rotation_angle: rotation angle of solid created. A cut is performed - from rotation_angle to 360 degrees. Defaults to 360.0. - """ - - def __init__( - self, - name: str = "toroidal_field_coil", - R1: float = 100, - R2: float = 300, - thickness: float = 30, - distance: float = 20, - number_of_coils: int = 12, - vertical_displacement: float = 0.0, - with_inner_leg: bool = True, - azimuth_start_angle: float = 0, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = (0.0, 0.0, 1.0), - **kwargs - ) -> None: - - super().__init__( - name=name, - thickness=thickness, - number_of_coils=number_of_coils, - vertical_displacement=vertical_displacement, - with_inner_leg=with_inner_leg, - azimuth_start_angle=azimuth_start_angle, - rotation_angle=rotation_angle, - distance=distance, - color=color, - **kwargs - ) - - self.R1 = R1 - self.R2 = R2 - self.inner_leg_connection_points = None - - @property - def inner_points(self): - self.points - return self._inner_points - - @inner_points.setter - def inner_points(self, value): - self._inner_points = value - - @property - def outer_points(self): - self.points - return self._outer_points - - @outer_points.setter - def outer_points(self, value): - self._outer_points = value - - @property - def azimuth_placement_angle(self): - self.find_azimuth_placement_angle() - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - self._azimuth_placement_angle = value - - def _compute_inner_points(self, R1, R2): - """Computes the inner curve points - - Args: - R1 (float): smallest radius (cm) - R2 (float): largest radius (cm) - - Returns: - (list, list, list): R, Z and derivative lists for outer curve - points - """ - - def error(z_0, R0, R2): - segment = get_segment(R0, R2, z_0) - return abs(segment[1][-1]) - - def get_segment(a, b, z_0): - a_R = np.linspace(a, b, num=70, endpoint=True) - asol = integrate.odeint(solvr, [z_0[0], 0], a_R) - return a_R, asol[:, 0], asol[:, 1] - - def solvr(Y, R): - return [Y[1], -1 / (k * R) * (1 + Y[1] ** 2) ** (3 / 2)] - - R0 = (R1 * R2) ** 0.5 - k = 0.5 * np.log(R2 / R1) - - # computing of z_0 - # z_0 is computed by ensuring outer segment end is zero - z_0 = 10 # initial guess for z_0 - res = minimize(error, z_0, args=(R0, R2)) - z_0 = res.x - - # compute inner and outer segments - segment1 = get_segment(R0, R1, z_0) - segment2 = get_segment(R0, R2, z_0) - - r_values = np.concatenate( - [ - np.flip(segment1[0]), - segment2[0][1:], - np.flip(segment2[0])[1:], - segment1[0][1:], - ] - ) - z_values = np.concatenate( - [ - np.flip(segment1[1]), - segment2[1][1:], - -np.flip(segment2[1])[1:], - -segment1[1][1:], - ] - ) - return r_values, z_values - - def find_points(self): - """Finds the XZ points joined by connections that describe the 2D - profile of the toroidal field coil shape.""" - # compute inner points - r_inner, z_inner = self._compute_inner_points(self.R1 + self.thickness, self.R2) - - # compute outer points - dz_dr = np.diff(z_inner) / np.diff(r_inner) - dz_dr[0] = float("-inf") - dz_dr = np.append(dz_dr, float("inf")) - r_outer, z_outer = add_thickness(r_inner, z_inner, self.thickness, dy_dx=dz_dr) - r_outer, z_outer = np.flip(r_outer), np.flip(z_outer) - - # add vertical displacement - z_outer += self.vertical_displacement - z_inner += self.vertical_displacement - - # extract helping points for inner leg - self.inner_leg_connection_points = [ - (r_inner[0], z_inner[0]), - (r_inner[-1], z_inner[-1]), - (r_outer[0], z_outer[0]), - (r_outer[-1], z_outer[-1]), - ] - - # add connections - inner_points = [[r, z, "spline"] for r, z in zip(r_inner, z_inner)] - outer_points = [[r, z, "spline"] for r, z in zip(r_outer, z_outer)] - - inner_points[-1][2] = "straight" - outer_points[-1][2] = "straight" - - points = inner_points + outer_points - self.outer_points = np.vstack((r_outer, z_outer)).T - self.inner_points = np.vstack((r_inner, z_inner)).T - - self.points = points diff --git a/src/paramak/parametric_components/toroidal_field_coil_rectangle.py b/src/paramak/parametric_components/toroidal_field_coil_rectangle.py deleted file mode 100644 index 18e6e8d0b..000000000 --- a/src/paramak/parametric_components/toroidal_field_coil_rectangle.py +++ /dev/null @@ -1,119 +0,0 @@ -from typing import Optional, Tuple - -from .toroidal_field_coil import ToroidalFieldCoil -from paramak.utils import patch_workplane - -patch_workplane() - - -class ToroidalFieldCoilRectangle(ToroidalFieldCoil): - """Creates a rectangular shaped toroidal field coil. - - Args: - horizontal_start_point: the (x,z) coordinates of the inner upper - point (cm). - vertical_mid_point: the (x,z) coordinates of the mid point of the - vertical section (cm). - thickness: the thickness of the toroidal field coil. - distance: the extrusion distance. - number_of_coils: the number of tf coils. This changes by the - azimuth_placement_angle dividing up 360 degrees by the number of - coils. - with_inner_leg: include the inner tf leg. Defaults to True. - azimuth_start_angle: The azimuth angle to for the first TF coil which - offsets the placement of coils around the azimuthal angle - """ - - def __init__( - self, - name: str = "toroidal_field_coil", - horizontal_start_point: Tuple[float, float] = (20, 200), - vertical_mid_point: Tuple[float, float] = (350, 0), - thickness: float = 30, - distance: float = 20, - number_of_coils: int = 12, - with_inner_leg: bool = True, - azimuth_start_angle: float = 0, - vertical_displacement: float = 0.0, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = (0.0, 0.0, 1.0), - **kwargs - ) -> None: - - super().__init__( - name=name, - thickness=thickness, - number_of_coils=number_of_coils, - vertical_displacement=vertical_displacement, - with_inner_leg=with_inner_leg, - azimuth_start_angle=azimuth_start_angle, - rotation_angle=rotation_angle, - distance=distance, - color=color, - **kwargs - ) - - self.horizontal_start_point = horizontal_start_point - self.vertical_mid_point = vertical_mid_point - self.inner_leg_connection_points = None - - def find_points(self): - """Finds the XZ points joined by straight connections that describe - the 2D profile of the poloidal field coil shape.""" - - if self.horizontal_start_point[0] >= self.vertical_mid_point[0]: - raise ValueError( - "horizontal_start_point x should be smaller than the \ - vertical_mid_point x value" - ) - if self.vertical_mid_point[1] >= self.horizontal_start_point[1]: - raise ValueError( - "vertical_mid_point y value should be smaller than the \ - horizontal_start_point y value" - ) - - points = [ - self.horizontal_start_point, # connection point - # connection point - ( - self.horizontal_start_point[0] + self.thickness, - self.horizontal_start_point[1], - ), - (self.vertical_mid_point[0], self.horizontal_start_point[1]), - (self.vertical_mid_point[0], -self.horizontal_start_point[1]), - # connection point - ( - self.horizontal_start_point[0] + self.thickness, - -self.horizontal_start_point[1], - ), - # connection point - (self.horizontal_start_point[0], -self.horizontal_start_point[1]), - ( - self.horizontal_start_point[0], - -(self.horizontal_start_point[1] + self.thickness), - ), - ( - self.vertical_mid_point[0] + self.thickness, - -(self.horizontal_start_point[1] + self.thickness), - ), - ( - self.vertical_mid_point[0] + self.thickness, - self.horizontal_start_point[1] + self.thickness, - ), - ( - self.horizontal_start_point[0], - self.horizontal_start_point[1] + self.thickness, - ), - ] - - # adds any vertical displacement and the connection type to the points - points = [(point[0], point[1] + self.vertical_displacement, "straight") for point in points] - - self.inner_leg_connection_points = [ - (points[0][0], points[0][1]), - (points[1][0], points[1][1]), - (points[4][0], points[4][1]), - (points[5][0], points[5][1]), - ] - - self.points = points diff --git a/src/paramak/parametric_components/toroidal_field_coil_round_corners.py b/src/paramak/parametric_components/toroidal_field_coil_round_corners.py deleted file mode 100644 index 7e8674f67..000000000 --- a/src/paramak/parametric_components/toroidal_field_coil_round_corners.py +++ /dev/null @@ -1,394 +0,0 @@ -from typing import Optional, Tuple, Union - -import cadquery as cq -import numpy as np - - -from paramak.parametric_shapes.extruded_mixed_shape import ExtrudeMixedShape -from paramak.utils import calculate_wedge_cut, patch_workplane - -patch_workplane() - - -class ToroidalFieldCoilRectangleRoundCorners(ExtrudeMixedShape): - """Creates geometry for TF coil with rounded corners. Finds the coordinates - for vertices of a TF coil, in a 2D profile on the XZ plane using the main - function find_points() which takes 3 positional arguments for the TF coil - parameters, and takes three additional boolean arguments. - - Arguments: - lower_inner_coordinates: the (X,Z) coordinate of the inner corner of - the lower end of the coil (cm) - mid_point_coordinates: the (X,Z) coordinate of the mid point of the - vertical section (cm) - thickness: The thickness in the (X,Z) plane of the toroidal field coils - (cm) - extrusiondistance: The total extruded thickness of the coils when in - the y-direction (centered extrusion) - coil_count: The number of coils placed in the model - (changing azimuth_placement_angle by dividing 360 by the amount - given). Defaults to 1 - with_inner_leg: Boolean to include the inside of the Coils - azimuth_start_angle: The azimuth angle to for the first TF coil which - offsets the placement of coils around the azimuthal angle - """ - - def __init__( - self, - name: str = "toroidal_field_coil", - lower_inner_coordinates: Tuple[float, float] = (100, 250), - mid_point_coordinates: Tuple[float, float] = (500, 0), - thickness: Union[float, int] = 30, - distance: float = 20, - number_of_coils: int = 12, - with_inner_leg: Optional[bool] = True, - azimuth_start_angle: float = 0, - # vertical_displacement:float = 0.0, - # rotation_angle:float = 360., - color: Tuple[float, float, float, Optional[float]] = (0.0, 0.0, 1.0), - **kwargs - ) -> None: - - super().__init__(name=name, distance=distance, color=color, **kwargs) - - self._lower_inner_coordinates = lower_inner_coordinates - self._mid_point_coordinates = mid_point_coordinates - self._thickness = thickness - self._distance = distance - self.number_of_coils = number_of_coils - self._with_inner_leg = with_inner_leg - self.inner_leg_connection_points = [] - self._analyse_attributes = [0, 0, 0, 0] - self._base_length = 0 - self._height = 0 - self._inner_curve_radius = 0 - self._outter_curve_radius = 0 - self.azimuth_start_angle = azimuth_start_angle - # TODO to the create points - # self.vertical_displacement = vertical_displacement - # TODO add to to the create solid part - # self.rotation_angle = rotation_angle - - # TODO move to setters - if len(lower_inner_coordinates) != 2 or len(mid_point_coordinates) != 2: - msg = "The input tuples are too long or too short, they must be " "2 element long" - raise ValueError(msg) - - if self._lower_inner_coordinates[0] > self._mid_point_coordinates[0]: - raise ValueError( - "The middle point's x-coordinate must be larger than the lower", - "inner point's x-coordinate", - ) - - def _find_base_and_height(self): - # Adding hidden attributes for analyse list population - # inner base length of the coil - self._base_length = self._mid_point_coordinates[0] - self._lower_inner_coordinates[0] - self._analyse_attributes[0] = self._base_length - - # height of the coil - self._height = abs(self.mid_point_coordinates[1] - self.lower_inner_coordinates[1]) * 2 - self._analyse_attributes[1] = self._height - - def _find_radii(self): - # Inner and outter radius of curvature for the corners - # The inner curvature is scales as a function of the base length - # of the coil and its thickness as long as the thickness does not exceed the base length - # if the thickness/base length ratio is larger or equal to 1 - # it takes 10% of the thickness as the inner curve radius - # this to avoid having coordinates before the previous or at the same spot as Paramak - # cannot compute it - self._find_base_and_height() - if self._thickness / self._base_length >= 1: - self._inner_curve_radius = self._thickness * 0.1 - self._outter_curve_radius = self._thickness * 1.1 - else: - self._outter_curve_radius = (1 + (self._thickness / self._base_length)) * self._thickness - self._inner_curve_radius = (self._thickness**2) / self._base_length - - self._analyse_attributes[2] = self._inner_curve_radius - self._analyse_attributes[3] = self._outter_curve_radius - - @property - def azimuth_placement_angle(self): - self.find_azimuth_placement_angle() - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, val): - self._azimuth_placement_angle = val - - @property - def lower_inner_coordinates(self): - return self._lower_inner_coordinates - - @lower_inner_coordinates.setter - def lower_inner_coordinates(self, val): - if not isinstance(val, tuple): - raise TypeError("Input Coordinate must be a tuple!") - if len(val) != 2: - raise ValueError("Input Tuple must be 2 elements long!") - if not isinstance(val[0], (float, int)): - raise TypeError("Input X Coordinates must be a number!") - if not isinstance(val[1], (float, int)): - raise TypeError("Input Z Coordinates must be a number!") - if val[0] > self._mid_point_coordinates[0]: - raise ValueError("Mid Point's x-coordinate, must be larger than lower point's!") - self._lower_inner_coordinates = val - - @property - def mid_point_coordinates(self): - return self._mid_point_coordinates - - @mid_point_coordinates.setter - def mid_point_coordinates(self, val): - if not isinstance(val, tuple): - raise TypeError("Input Coordinate must be a tuple!") - if len(val) != 2: - raise ValueError("Input Tuple must be 2 elements long!") - if not isinstance(val[0], (float, int)): - raise TypeError("Input X Coordinates must be a number!") - if not isinstance(val[1], (float, int)): - raise TypeError("Input Z Coordinates must be a number!") - if val[0] < self._lower_inner_coordinates[0]: - raise ValueError("Mid Point's x-coordinate, must be larger than lower point's!") - self._mid_point_coordinates = val - - @property - def thickness(self): - return self._thickness - - @thickness.setter - def thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Input Thickness must be a number!") - self._find_radii() - self._thickness = val - - @property - def distance(self): - return self._distance - - @distance.setter - def distance(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Input Distance must be a number!") - self._distance = val - - @property - def number_of_coils(self): - return self._number_of_coils - - @number_of_coils.setter - def number_of_coils(self, val): - if not isinstance(val, int): - raise TypeError("Input Distance must be an integer number!") - self._number_of_coils = val - - @property - def analyse_attributes(self): - self.find_points() - return self._analyse_attributes - - @property - def with_inner_leg(self): - return self._with_inner_leg - - @with_inner_leg.setter - def with_inner_leg(self, val): - if not isinstance(val, bool): - raise TypeError("With Inner Leg must be True or False") - - def find_points(self): - """ - lower_inner_coordinates must be a 2 element tuple - mid_point_coordinates must be a 2 elemenet tuple - thickness must be a float or an int - """ - self._find_radii() - - lower_x, lower_z = self._lower_inner_coordinates - mid_x, mid_z = self._mid_point_coordinates - - # redifine values to be floats to make it look consistent - lower_x, lower_z, mid_x, mid_z, thickness = ( - float(lower_x), - float(lower_z), - float(mid_x), - float(mid_z), - float(self._thickness), - ) - - # Define differences to avoid miss claculation due to signs - base_length = self._analyse_attributes[0] - height = self._analyse_attributes[1] - - # 10 points/tuples for initial calculation and to get aux points - point1 = (lower_x, lower_z) - point2 = (point1[0] + base_length, point1[1]) - point3 = (point2[0], point2[1] + height) - point4 = (point1[0], point1[1] + height) - point5 = (point4[0], point4[1] + thickness) - point6 = (point3[0], point4[1] + thickness) - # point7 = (point3[0] + thickness, point3[1]) - point8 = (point2[0] + thickness, point2[1]) - # point9 = (point2[0], point2[1] - thickness) - point10 = (lower_x, lower_z - thickness) - - inner_curve_radius = self._analyse_attributes[2] - outter_curve_radius = self._analyse_attributes[3] - - # New subroutines to calculate inner and outter curve mid-points, # - # x and y displacement from existing points # - # long shift does a sin(45)*radius of curvature shift # - # short shift does a (1-sin(45))*radius of curvature shift # - - def shift_long(radius): - """radius is the radius of curvature""" - return (2**0.5) * 0.5 * radius - - def shift_short(radius): - """radius is the radius of curvature""" - return (2 - (2**0.5)) * 0.5 * radius - - point11 = (point2[0] - inner_curve_radius, point2[1]) - point12 = ( - point11[0] + shift_long(inner_curve_radius), - point11[1] + shift_short(inner_curve_radius), - ) - point13 = (point2[0], point2[1] + inner_curve_radius) - point14 = (point3[0], point3[1] - inner_curve_radius) - point15 = ( - point14[0] - shift_short(inner_curve_radius), - point14[1] + shift_long(inner_curve_radius), - ) - point16 = (point3[0] - inner_curve_radius, point3[1]) - point17 = (point6[0] - inner_curve_radius, point6[1]) - point18 = ( - point17[0] + shift_long(outter_curve_radius), - point17[1] - shift_short(outter_curve_radius), - ) - point19 = (point14[0] + thickness, point14[1]) - point20 = (point8[0], point8[1] + inner_curve_radius) - point21 = (point18[0], point20[1] - shift_long(outter_curve_radius)) - point22 = (point11[0], point11[1] - thickness) - - # List holding the points that are being returned by the function - points = [ - point1, - point11, - point12, - point13, - point14, - point15, - point16, - point4, - point5, - point17, - point18, - point19, - point20, - point21, - point22, - point10, - ] - # List that holds the points with the corresponding line types - tri_points = [] - lines = ( - ["straight"] - + ["circle"] * 2 - + ["straight"] - + ["circle"] * 2 - + ["straight"] * 3 - + ["circle"] * 2 - + ["straight"] - + ["circle"] * 2 - + ["straight"] * 2 - ) - - for i in enumerate(points): - tri_points.append(points[i[0]] + (lines[i[0]],)) - - self.points = tri_points - - inner_point1 = (point1[0], point1[1]) - inner_point2 = (point1[0] + thickness, point1[1]) - inner_point3 = (point4[0] + thickness, point4[1]) - inner_point4 = (point4[0], point4[1]) - - self.inner_leg_connection_points = [ - inner_point1, - inner_point2, - inner_point3, - inner_point4, - ] - - return tri_points - - def find_azimuth_placement_angle(self): - """Finds the placement angles from the number of coils - given in a 360 degree""" - - angles = list( - np.linspace( - self.azimuth_start_angle, - 360 + self.azimuth_start_angle, - self.number_of_coils, - endpoint=False, - ) - ) - - self.azimuth_placement_angle = angles - - def create_solid(self): - """Creates a Cadquery 3D geometry - - Returns: - CadQuery solid: A 3D solid Volume""" - - # Create solid from points - points = [ps[:2] for ps in self.processed_points] - - wire = ( - cq.Workplane(self.workplane) - .moveTo(points[0][0], points[0][1]) - .lineTo(points[1][0], points[1][1]) - .threePointArc((points[2][0], points[2][1]), (points[3][0], points[3][1])) - .lineTo(points[4][0], points[4][1]) - .threePointArc((points[5][0], points[5][1]), (points[6][0], points[6][1])) - .lineTo(points[7][0], points[7][1]) - .lineTo(points[8][0], points[8][1]) - .lineTo(points[9][0], points[9][1]) - .threePointArc((points[10][0], points[10][1]), (points[11][0], points[11][1])) - .lineTo(points[12][0], points[12][1]) - .threePointArc((points[13][0], points[13][1]), (points[14][0], points[14][1])) - .lineTo(points[15][0], points[15][1]) - .lineTo(points[16][0], points[16][1]) - .close() - .consolidateWires() - ) - - solid = wire.extrude(until=-self._distance / 2, both=True) - solid = self.rotate_solid(solid) - - cutting_wedge = calculate_wedge_cut(self) - solid = self.perform_boolean_operations(solid, wedge_cut=cutting_wedge) - - self.solid = solid - - if self._with_inner_leg: - inner_leg_solid = cq.Workplane(self.workplane) - inner_leg_solid = ( - inner_leg_solid.polyline(self.inner_leg_connection_points) - .close() - .extrude(until=-self._distance / 2, both=True) - ) - - inner_leg_solid = self.rotate_solid(inner_leg_solid) - inner_leg_solid = self.perform_boolean_operations(inner_leg_solid, wedge_cut=cutting_wedge) - - solid = cq.Compound.makeCompound([a.val() for a in [inner_leg_solid, solid]]) - - self.solid = solid - - return solid diff --git a/src/paramak/parametric_components/toroidal_field_coil_triple_arc.py b/src/paramak/parametric_components/toroidal_field_coil_triple_arc.py deleted file mode 100644 index 5a8ddb8fe..000000000 --- a/src/paramak/parametric_components/toroidal_field_coil_triple_arc.py +++ /dev/null @@ -1,141 +0,0 @@ -from typing import Optional, Tuple - -import numpy as np - -from .toroidal_field_coil import ToroidalFieldCoil - - -class ToroidalFieldCoilTripleArc(ToroidalFieldCoil): - """Toroidal field coil made of three arcs - - Args: - R1: smallest radius (cm). - h: height of the straight section (cm). - radii: radii of the small and medium arcs (cm). - coverages: coverages of the small and medium arcs (deg). - thickness: magnet thickness (cm). - distance: extrusion distance (cm). - number_of_coils: the number of TF coils. This changes by the - azimuth_placement_angle dividing up 360 degrees by the number of - coils. - vertical_displacement: vertical displacement (cm). Defaults to 0.0. - with_inner_leg: Include the inner tf leg. Defaults to True. - azimuth_start_angle: The azimuth angle to for the first TF coil which - offsets the placement of coils around the azimuthal angle - """ - - def __init__( - self, - name: str = "toroidal_field_coil", - R1: float = 80, - h: float = 200, - radii: Tuple[float, float] = (70, 100), - coverages: Tuple[float, float] = (60, 60), - thickness: float = 30, - distance: float = 20, - number_of_coils: int = 12, - vertical_displacement: float = 0.0, - with_inner_leg: bool = True, - azimuth_start_angle: float = 0, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = (0.0, 0.0, 1.0), - **kwargs - ) -> None: - - super().__init__( - name=name, - thickness=thickness, - number_of_coils=number_of_coils, - vertical_displacement=vertical_displacement, - with_inner_leg=with_inner_leg, - azimuth_start_angle=azimuth_start_angle, - rotation_angle=rotation_angle, - distance=distance, - color=color, - **kwargs - ) - - self.R1 = R1 - self.h = h - self.small_radius, self.mid_radius = radii - self.small_coverage, self.mid_coverage = coverages - self.inner_leg_connection_points = None - - def _compute_curve(self, R1, h, radii, coverages): - npoints = 500 - - small_radius, mid_radius = radii - small_coverage, mid_coverage = coverages - asum = small_coverage + mid_coverage - - # small arc - theta = np.linspace(0, small_coverage, round(0.5 * npoints * small_coverage / np.pi)) - small_arc_R = R1 + small_radius * (1 - np.cos(theta)) - small_arc_Z = h + small_radius * np.sin(theta) - - # mid arc - theta = np.linspace(theta[-1], asum, round(0.5 * npoints * mid_coverage / np.pi)) - mid_arc_R = small_arc_R[-1] + mid_radius * (np.cos(small_coverage) - np.cos(theta)) - mid_arc_Z = small_arc_Z[-1] + mid_radius * (np.sin(theta) - np.sin(small_coverage)) - - # large arc - large_radius = (mid_arc_Z[-1]) / np.sin(np.pi - asum) - theta = np.linspace(theta[-1], np.pi, 60) - large_arc_R = mid_arc_R[-1] + large_radius * (np.cos(np.pi - theta) - np.cos(np.pi - asum)) - large_arc_Z = mid_arc_Z[-1] - large_radius * (np.sin(asum) - np.sin(np.pi - theta)) - - R = np.concatenate((small_arc_R, mid_arc_R[1:], large_arc_R[1:])) - R = np.append(R, np.flip(R)[1:]) - Z = np.concatenate((small_arc_Z, mid_arc_Z[1:], large_arc_Z[1:])) - Z = np.append(Z, -np.flip(Z)[1:]) - return R, Z - - def find_points(self): - """Finds the XZ points joined by connections that describe the 2D - profile of the toroidal field coil shape.""" - - thickness = self.thickness - small_radius, mid_radius = self.small_radius, self.mid_radius - small_coverage, mid_coverage = self.small_coverage, self.mid_coverage - small_coverage *= np.pi / 180 # convert to radians - mid_coverage *= np.pi / 180 - - # create inner coordinates - R_inner, Z_inner = self._compute_curve( - self.R1 + thickness, - self.h * 0.5, - radii=(small_radius, mid_radius), - coverages=(small_coverage, mid_coverage), - ) - - # create outer coordinates - R_outer, Z_outer = self._compute_curve( - self.R1, - self.h * 0.5, - radii=(small_radius + thickness, mid_radius + thickness), - coverages=(small_coverage, mid_coverage), - ) - R_outer, Z_outer = np.flip(R_outer), np.flip(Z_outer) - - # add vertical displacement - Z_outer += self.vertical_displacement - Z_inner += self.vertical_displacement - - # extract helping points for inner leg - self.inner_leg_connection_points = [ - (R_inner[0], Z_inner[0]), - (R_inner[-1], Z_inner[-1]), - (R_outer[0], Z_outer[0]), - (R_outer[-1], Z_outer[-1]), - ] - - # add connections - inner_points = [[r, z, "spline"] for r, z in zip(R_inner, Z_inner)] - outer_points = [[r, z, "spline"] for r, z in zip(R_outer, Z_outer)] - - inner_points[-1][2] = "straight" - outer_points[-1][2] = "straight" - - points = inner_points + outer_points - - self.points = points diff --git a/src/paramak/parametric_components/vacuum_vessel.py b/src/paramak/parametric_components/vacuum_vessel.py deleted file mode 100644 index 6f6f8c3f5..000000000 --- a/src/paramak/parametric_components/vacuum_vessel.py +++ /dev/null @@ -1,61 +0,0 @@ -from paramak import RotateStraightShape - - -class VacuumVessel(RotateStraightShape): - """A cylindrical vessel volume with constant thickness. - - Arguments: - height: height of the vessel. - inner_radius: the inner radius of the vessel. - thickness: thickness of the vessel - """ - - def __init__(self, height: float, inner_radius: float, thickness: float, **kwargs): - self.height = height - self.inner_radius = inner_radius - self.thickness = thickness - super().__init__(**kwargs) - - @property - def height(self): - return self._height - - @height.setter - def height(self, value): - if not isinstance(value, (float, int)): - raise ValueError("VacuumVessel.height must be a number. Not " f"{value}") - if value <= 0: - msg = "VacuumVessel.height must be a positive number above 0. " f"Not {value}" - raise ValueError(msg) - self._height = value - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, value): - assert value > 0 - self._inner_radius = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe the - 2D profile of the vessel shape.""" - thickness = self.thickness - inner_radius = self.inner_radius - height = self.height - - inner_points = [ - (0, height / 2), - (inner_radius, height / 2), - (inner_radius, -height / 2), - (0, -height / 2), - ] - - outer_points = [ - (0, height / 2 + thickness), - (inner_radius + thickness, height / 2 + thickness), - (inner_radius + thickness, -(height / 2 + thickness)), - (0, -(height / 2 + thickness)), - ] - self.points = inner_points + outer_points[::-1] diff --git a/src/paramak/parametric_components/vacuum_vessel_inner_leg.py b/src/paramak/parametric_components/vacuum_vessel_inner_leg.py deleted file mode 100644 index 817f8be16..000000000 --- a/src/paramak/parametric_components/vacuum_vessel_inner_leg.py +++ /dev/null @@ -1,131 +0,0 @@ -import cadquery as cq - -from paramak import RotateStraightShape - - -class VacuumVesselInnerLeg(RotateStraightShape): - """A cylindrical vessel volume with constant thickness. - - Arguments: - inner_height: height of the vessel. - inner_radius: the inner radius of the vessel. - inner_leg_radius: the inner radius of the inner leg. - thickness: thickness of the vessel - """ - - def __init__( - self, - inner_height: float, - inner_radius: float, - inner_leg_radius: float, - thickness: float, - **kwargs, - ): - self.inner_height = inner_height - self.inner_radius = inner_radius - self.inner_leg_radius = inner_leg_radius - self.thickness = thickness - super().__init__(**kwargs) - - @property - def inner_height(self): - return self._inner_height - - @inner_height.setter - def inner_height(self, value): - if not isinstance(value, (float, int)): - raise ValueError("VacuumVesselInnerLeg.inner_height must be a number. Not", value) - if value <= 0: - msg = f"VacuumVesselInnerLeg.inner_height must be a positive number above 0. Not {value}" - raise ValueError(msg) - self._inner_height = value - - @property - def inner_radius(self): - return self._inner_radius - - @inner_radius.setter - def inner_radius(self, value): - if not isinstance(value, (float, int)): - msg = f"VacuumVesselInnerLeg.inner_radius must be a number. Not {value}" - raise ValueError(msg) - if value <= 0: - msg = f"VacuumVesselInnerLeg.inner_radius must be a positive number above 0. Not {value}" - raise ValueError(msg) - - self._inner_radius = value - - def find_points(self): - """Finds the XZ points joined by straight connections that describe the - 2D profile of the vessel shape.""" - thickness = self.thickness - inner_radius = self.inner_radius - inner_height = self.inner_height - inner_leg_radius = self.inner_leg_radius - - point_1 = ( - inner_leg_radius + 2 * thickness + inner_radius, - thickness + (inner_height / 2.0), - ) - point_2 = (0, thickness + (inner_height / 2.0)) - point_3 = (0, -(thickness + (inner_height / 2.0))) - point_4 = ( - inner_leg_radius + 2 * thickness + inner_radius, - -(thickness + (inner_height / 2)), - ) - - point_5 = (inner_leg_radius + thickness + inner_radius, inner_height / 2) - point_6 = (inner_leg_radius + thickness, inner_height / 2) - point_7 = (inner_leg_radius + thickness, -inner_height / 2) - point_8 = (inner_leg_radius + thickness + inner_radius, -inner_height / 2) - - points_9 = (inner_leg_radius, thickness + inner_height / 2) - points_10 = (inner_leg_radius, -(thickness + inner_height / 2)) - - self.points = [ - point_1, - point_2, - point_3, - point_4, - point_5, - point_6, - point_7, - point_8, - points_9, - points_10, - ] - - def create_solid(self): - """Creates a 3d solid using points with straight edges. Individual - solids in the compound can be accessed using .Solids()[i] where i is an - int - - Returns: - A CadQuery solid: A 3D solid volume - """ - - local_points = [] - for point in self.points: - local_points.append((point[0], point[1])) - - big_wire = (cq.Workplane(self.workplane).polyline(local_points[:4])).close() - - small_wire = (cq.Workplane(self.workplane).polyline(local_points[4:8])).close() # list of points has 10 entries - - inner_wire = ( - cq.Workplane(self.workplane).polyline([local_points[1], local_points[2], local_points[9], local_points[8]]) - ).close() - - inner_solid = inner_wire.revolve(self.rotation_angle) - big_solid = big_wire.revolve(self.rotation_angle) - small_solid = small_wire.revolve(self.rotation_angle) - - solid = big_solid.cut(small_solid).cut(inner_solid) - - self.wire = [big_wire, small_wire] - solid = self.rotate_solid(solid) - solid = self.perform_boolean_operations(solid) - - self.solid = solid - - return solid diff --git a/src/paramak/parametric_reactors/__init__.py b/src/paramak/parametric_reactors/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/paramak/parametric_reactors/ball_reactor.py b/src/paramak/parametric_reactors/ball_reactor.py deleted file mode 100644 index c42853103..000000000 --- a/src/paramak/parametric_reactors/ball_reactor.py +++ /dev/null @@ -1,591 +0,0 @@ -import warnings -from typing import List, Optional - -import paramak - - -class BallReactor(paramak.Reactor): - """Creates geometry for a simple ball reactor including a plasma, - cylindrical center column shielding, square toroidal field coils. - There is no inboard breeder blanket on this ball reactor like - most spherical reactors. - - Arguments: - inner_bore_radial_thickness: the radial thickness of the inner bore - (cm) - inboard_tf_leg_radial_thickness: the radial thickness of the inner leg - of the toroidal field coils (cm) - center_column_shield_radial_thickness: the radial thickness of the - center column shield (cm) - divertor_radial_thickness: the radial thickness of the divertor - (cm), this fills the gap between the center column shield and - blanket - inner_plasma_gap_radial_thickness: the radial thickness of the - inboard gap between the plasma and the center column shield (cm) - plasma_radial_thickness: the radial thickness of the plasma - outer_plasma_gap_radial_thickness: the radial thickness of the - outboard gap between the plasma and firstwall (cm) - firstwall_radial_thickness: the radial thickness of the first wall (cm) - blanket_radial_thickness: the radial thickness of the blanket (cm) - blanket_rear_wall_radial_thickness: the radial thickness of the rear - wall of the blanket (cm) - elongation: the elongation of the plasma - triangularity: the triangularity of the plasma - plasma_gap_vertical_thickness: the vertical thickness of the gap - between the plasma and firstwall (cm). - divertor_to_tf_gap_vertical_thickness: the vertical thickness of the - gap between the divertor and the TF coils. - number_of_tf_coils: the number of tf coils - rear_blanket_to_tf_gap: the radial distance between the back of the - blankets and the start of the TF coils. - pf_coil_radial_thicknesses: the radial - thickness of each poloidal field coil. - pf_coil_vertical_thicknesses: the vertical - thickness of each poloidal field coil. - pf_coil_radial_position: The radial (x) position(s) of the centers of - the poloidal field coils. - pf_coil_vertical_position: The vertical (z) position(s) of the centers - of the poloidal field coils. - pf_coil_case_thicknesses: the thickness(s) to use in both the radial - and vertical direction for the casing around the pf coils. Each - float value in the list will be applied to the pf coils one by one. - To have no casing set each entry to 0 or leave as an empty list. - outboard_tf_coil_radial_thickness: the radial thickness of the toroidal - field coil. - outboard_tf_coil_poloidal_thickness: the poloidal thickness of the - toroidal field coil. - divertor_position: the position of the divertor, "upper", "lower" or - "both". - rotation_angle: the angle of the sector that is desired. - """ - - def __init__( - self, - inner_bore_radial_thickness: float = 10.0, - inboard_tf_leg_radial_thickness: float = 30.0, - center_column_shield_radial_thickness: float = 60.0, - divertor_radial_thickness: float = 150.0, - inner_plasma_gap_radial_thickness: float = 30.0, - plasma_radial_thickness: float = 300.0, - outer_plasma_gap_radial_thickness: float = 30.0, - firstwall_radial_thickness: float = 30.0, - blanket_radial_thickness: float = 50.0, - blanket_rear_wall_radial_thickness: float = 30.0, - elongation: float = 2.0, - triangularity: float = 0.55, - plasma_gap_vertical_thickness: float = 50.0, - divertor_to_tf_gap_vertical_thickness: Optional[float] = 0.0, - number_of_tf_coils: Optional[int] = 12, - rear_blanket_to_tf_gap: Optional[float] = None, - pf_coil_radial_thicknesses: List[float] = [], - pf_coil_vertical_thicknesses: List[float] = [], - pf_coil_radial_position: List[float] = [], - pf_coil_vertical_position: List[float] = [], - pf_coil_case_thicknesses: List[float] = [], - outboard_tf_coil_radial_thickness: float = None, - outboard_tf_coil_poloidal_thickness: float = None, - divertor_position: Optional[str] = "both", - rotation_angle: Optional[str] = 180.0, - ): - - super().__init__([]) - - self.inner_bore_radial_thickness = inner_bore_radial_thickness - self.inboard_tf_leg_radial_thickness = inboard_tf_leg_radial_thickness - self.center_column_shield_radial_thickness = center_column_shield_radial_thickness - self.divertor_radial_thickness = divertor_radial_thickness - self.inner_plasma_gap_radial_thickness = inner_plasma_gap_radial_thickness - self.plasma_radial_thickness = plasma_radial_thickness - self.outer_plasma_gap_radial_thickness = outer_plasma_gap_radial_thickness - self.firstwall_radial_thickness = firstwall_radial_thickness - self.blanket_radial_thickness = blanket_radial_thickness - self.blanket_rear_wall_radial_thickness = blanket_rear_wall_radial_thickness - - self.pf_coil_vertical_position = pf_coil_vertical_position - self.pf_coil_radial_position = pf_coil_radial_position - self.pf_coil_radial_thicknesses = pf_coil_radial_thicknesses - self.pf_coil_vertical_thicknesses = pf_coil_vertical_thicknesses - self.rear_blanket_to_tf_gap = rear_blanket_to_tf_gap - - self.pf_coil_case_thicknesses = pf_coil_case_thicknesses - self.outboard_tf_coil_radial_thickness = outboard_tf_coil_radial_thickness - self.outboard_tf_coil_poloidal_thickness = outboard_tf_coil_poloidal_thickness - self.divertor_position = divertor_position - self.rotation_angle = rotation_angle - - self.plasma_gap_vertical_thickness = plasma_gap_vertical_thickness - self.divertor_to_tf_gap_vertical_thickness = divertor_to_tf_gap_vertical_thickness - - self.elongation = elongation - self.triangularity = triangularity - - self.number_of_tf_coils = number_of_tf_coils - self.rotation_angle = rotation_angle - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "inner_bore_radial_thickness", - "inboard_tf_leg_radial_thickness", - "center_column_shield_radial_thickness", - "divertor_radial_thickness", - "inner_plasma_gap_radial_thickness", - "plasma_radial_thickness", - "outer_plasma_gap_radial_thickness", - "firstwall_radial_thickness", - "blanket_radial_thickness", - "blanket_rear_wall_radial_thickness", - "elongation", - "triangularity", - "plasma_gap_vertical_thickness", - "divertor_to_tf_gap_vertical_thickness", - "number_of_tf_coils", - "rear_blanket_to_tf_gap", - "pf_coil_radial_thicknesses", - "pf_coil_vertical_thicknesses", - "pf_coil_radial_position", - "pf_coil_vertical_position", - "pf_coil_case_thicknesses", - "outboard_tf_coil_radial_thickness", - "outboard_tf_coil_poloidal_thickness", - "divertor_position", - "rotation_angle", - ] - - # set by make_plasma - self.major_radius = None - self.minor_radius = None - - # set during geometry creation - self._pf_coils = None - self._pf_coils_casing = None - self._divertor_lower = None - self._divertor_upper = None - - @property - def rotation_angle(self): - return self._rotation_angle - - @rotation_angle.setter - def rotation_angle(self, value): - if value == 360: - msg = "360 degree rotation may result in a " "Standard_ConstructionError or AttributeError" - warnings.warn(msg, UserWarning) - elif value > 360: - raise ValueError("rotation_angle can not be larger than 360") - self._rotation_angle = value - - @property - def pf_coil_vertical_position(self): - return self._pf_coil_vertical_position - - @pf_coil_vertical_position.setter - def pf_coil_vertical_position(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_vertical_position must be a list") - self._pf_coil_vertical_position = value - - @property - def pf_coil_radial_position(self): - return self._pf_coil_radial_position - - @pf_coil_radial_position.setter - def pf_coil_radial_position(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_radial_position must be a list") - self._pf_coil_radial_position = value - - @property - def pf_coil_radial_thicknesses(self): - return self._pf_coil_radial_thicknesses - - @pf_coil_radial_thicknesses.setter - def pf_coil_radial_thicknesses(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_radial_thicknesses must be a list") - self._pf_coil_radial_thicknesses = value - - @property - def pf_coil_vertical_thicknesses(self): - return self._pf_coil_vertical_thicknesses - - @pf_coil_vertical_thicknesses.setter - def pf_coil_vertical_thicknesses(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_vertical_thicknesses must be a list") - self._pf_coil_vertical_thicknesses = value - - @property - def divertor_position(self): - return self._divertor_position - - @divertor_position.setter - def divertor_position(self, value): - acceptable_values = ["upper", "lower", "both"] - if value in acceptable_values: - self._divertor_position = value - else: - msg = "divertor_position must be 'upper', 'lower' or 'both'" - raise ValueError(msg) - - def create_solids(self): - """Creates a list of paramak.Shape for components and saves it in - self.shapes_and_components - """ - - uncut_shapes = [] - - uncut_shapes.append(self._make_plasma()) - self._make_radial_build() - self._make_vertical_build() - uncut_shapes.append(self._make_inboard_tf_coils()) - uncut_shapes.append(self._make_center_column_shield()) - uncut_shapes += self._make_blankets_layers() - uncut_shapes += self._make_divertor() - uncut_shapes += self._make_tf_coils() - pf_coils = self._make_pf_coils() - - if pf_coils is None: - shapes_and_components = uncut_shapes - else: - for shape in uncut_shapes: - for pf_coil in pf_coils: - shape.solid = shape.solid.cut(pf_coil.solid) - shapes_and_components = uncut_shapes + pf_coils - - self.shapes_and_components = shapes_and_components - - def _make_plasma(self): - - inner_equatorial_point = ( - self.inner_bore_radial_thickness - + self.inboard_tf_leg_radial_thickness - + self.center_column_shield_radial_thickness - + self.inner_plasma_gap_radial_thickness - ) - outer_equatorial_point = inner_equatorial_point + self.plasma_radial_thickness - - # sets major radius and minor radius from equatorial_points to allow a - # radial build. This helps avoid the plasma overlapping the center - # column and other components - self.major_radius = (outer_equatorial_point + inner_equatorial_point) / 2 - self.minor_radius = self.major_radius - inner_equatorial_point - - plasma = paramak.Plasma( - major_radius=self.major_radius, - minor_radius=self.minor_radius, - elongation=self.elongation, - triangularity=self.triangularity, - rotation_angle=self.rotation_angle, - ) - - self._plasma = plasma - return self._plasma - - def _make_radial_build(self): - - # this is the radial build sequence, where one component stops and - # another starts - - self._inner_bore_start_radius = 0 - self._inner_bore_end_radius = self._inner_bore_start_radius + self.inner_bore_radial_thickness - - self._inboard_tf_coils_start_radius = self._inner_bore_end_radius - self._inboard_tf_coils_end_radius = self._inboard_tf_coils_start_radius + self.inboard_tf_leg_radial_thickness - - self._center_column_shield_start_radius = self._inboard_tf_coils_end_radius - self._center_column_shield_end_radius = ( - self._center_column_shield_start_radius + self.center_column_shield_radial_thickness - ) - - self._divertor_start_radius = self._center_column_shield_end_radius - self._divertor_end_radius = self._center_column_shield_end_radius + self.divertor_radial_thickness - - self._firstwall_start_radius = ( - self._center_column_shield_end_radius - + self.inner_plasma_gap_radial_thickness - + self.plasma_radial_thickness - + self.outer_plasma_gap_radial_thickness - ) - self._firstwall_end_radius = self._firstwall_start_radius + self.firstwall_radial_thickness - - self._blanket_start_radius = self._firstwall_end_radius - self._blanket_end_radius = self._blanket_start_radius + self.blanket_radial_thickness - - self._blanket_rear_wall_start_radius = self._blanket_end_radius - self._blanket_rear_wall_end_radius = ( - self._blanket_rear_wall_start_radius + self.blanket_rear_wall_radial_thickness - ) - - def _make_vertical_build(self): - - # this is the vertical build sequence, components build on each other - # in a similar manner to the radial build - - self._firstwall_start_height = self._plasma.high_point[1] + self.plasma_gap_vertical_thickness - self._firstwall_end_height = self._firstwall_start_height + self.firstwall_radial_thickness - - self._blanket_start_height = self._firstwall_end_height - self._blanket_end_height = self._blanket_start_height + self.blanket_radial_thickness - - self._blanket_rear_wall_start_height = self._blanket_end_height - self._blanket_rear_wall_end_height = ( - self._blanket_rear_wall_start_height + self.blanket_rear_wall_radial_thickness - ) - - self._tf_coil_start_height = self._blanket_rear_wall_end_height + self.divertor_to_tf_gap_vertical_thickness - - self._center_column_shield_height = self._blanket_rear_wall_end_height * 2 - - if self.rear_blanket_to_tf_gap is not None: - self._tf_coil_start_radius = self._blanket_rear_wall_end_radius + self.rear_blanket_to_tf_gap - self._tf_coil_end_radius = self._tf_coil_start_radius + self.outboard_tf_coil_radial_thickness - - def _make_inboard_tf_coils(self): - - self._inboard_tf_coils = paramak.CenterColumnShieldCylinder( - height=self._tf_coil_start_height * 2, - inner_radius=self._inboard_tf_coils_start_radius, - outer_radius=self._inboard_tf_coils_end_radius, - rotation_angle=self.rotation_angle, - name="inboard_tf_coils", - color=(0, 0, 1), - ) - return self._inboard_tf_coils - - def _make_center_column_shield(self): - - self._center_column_shield = paramak.CenterColumnShieldCylinder( - height=self._center_column_shield_height, - inner_radius=self._center_column_shield_start_radius, - outer_radius=self._center_column_shield_end_radius, - rotation_angle=self.rotation_angle, - color=(0.0, 0.333, 0.0), - name="center_column_shield", - ) - return self._center_column_shield - - def _make_blankets_layers(self): - - offset_from_plasma = [ - self.major_radius - self.minor_radius, - self.plasma_gap_vertical_thickness, - self.outer_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.major_radius - self.minor_radius, - ] - - self._center_column_cutter = paramak.CenterColumnShieldCylinder( - # extra 0.5 to ensure overlap, - height=self._center_column_shield_height * 1.5, - inner_radius=0, - outer_radius=self._center_column_shield_end_radius, - rotation_angle=360, - color=(0.0, 0.0, 1.0), - ) - - self._firstwall = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.firstwall_radial_thickness, - offset_from_plasma=offset_from_plasma, - start_angle=-180, - stop_angle=180, - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - name="firstwall", - cut=[self._center_column_cutter], - allow_overlapping_shape=True, - ) - - self._blanket = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.blanket_radial_thickness, - offset_from_plasma=[e + self.firstwall_radial_thickness for e in offset_from_plasma], - start_angle=-180, - stop_angle=180, - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 0.498), - name="blanket", - cut=[self._center_column_cutter], - allow_overlapping_shape=True, - ) - - self._blanket_rear_wall = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.blanket_rear_wall_radial_thickness, - offset_from_plasma=[ - e + self.firstwall_radial_thickness + self.blanket_radial_thickness for e in offset_from_plasma - ], - start_angle=-180, - stop_angle=180, - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 1.0), - name="blanket_rear_wall", - cut=[self._center_column_cutter], - allow_overlapping_shape=True, - ) - - return [self._firstwall, self._blanket, self._blanket_rear_wall] - - def _make_divertor(self): - - offset_from_plasma = [ - self.major_radius - self.minor_radius, - self.plasma_gap_vertical_thickness, - self.outer_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.major_radius - self.minor_radius, - ] - - # used as an intersect when making the divertor - self._blanket_fw_rear_wall_envelope = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.firstwall_radial_thickness - + self.blanket_radial_thickness - + self.blanket_rear_wall_radial_thickness, - offset_from_plasma=offset_from_plasma, - start_angle=-180, - stop_angle=180, - rotation_angle=self.rotation_angle, - allow_overlapping_shape=True, - ) - - divertor_height = self._blanket_rear_wall_end_height * 2 - - divertor_height_top = divertor_height - divertor_height_bottom = -divertor_height - - if self.divertor_position in ["lower", "both"]: - self._divertor_lower = paramak.RotateStraightShape( - points=[ - (self._divertor_start_radius, divertor_height_bottom), - (self._divertor_end_radius, divertor_height_bottom), - (self._divertor_end_radius, 0), - (self._divertor_start_radius, 0), - ], - intersect=self._blanket_fw_rear_wall_envelope, - name="divertor_lower", - color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, - ) - if self.divertor_position in ["upper", "both"]: - self._divertor_upper = paramak.RotateStraightShape( - points=[ - (self._divertor_start_radius, 0), - (self._divertor_end_radius, 0), - (self._divertor_end_radius, divertor_height_top), - (self._divertor_start_radius, divertor_height_top), - ], - intersect=self._blanket_fw_rear_wall_envelope, - name="divertor_upper", - color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, - ) - - for component in [self._firstwall, self._blanket, self._blanket_rear_wall]: - if self.divertor_position in ["upper", "both"]: - component.cut.append(self._divertor_upper) - if self.divertor_position in ["lower", "both"]: - component.cut.append(self._divertor_lower) - - if self.divertor_position == "upper": - return [self._divertor_upper] - if self.divertor_position == "lower": - return [self._divertor_lower] - if self.divertor_position == "both": - return [self._divertor_upper, self._divertor_lower] - - def _make_pf_coils(self): - - pf_input_lists = [ - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, - self.pf_coil_vertical_position, - self.pf_coil_radial_position, - ] - - # checks if lists are all the same length - if all(len(input_list) == len(pf_input_lists[0]) for input_list in pf_input_lists): - number_of_pf_coils = len(pf_input_lists[0]) - if number_of_pf_coils == 0: - return None - - center_points = [(x, y) for x, y in zip(self.pf_coil_radial_position, self.pf_coil_vertical_position)] - - self._pf_coils = [] - for counter, (center_point, pf_coil_vertical_thickness, pf_coil_radial_thickness,) in enumerate( - zip( - center_points, - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, - ), - 1, - ): - pf_coil = paramak.PoloidalFieldCoil( - height=pf_coil_vertical_thickness, - width=pf_coil_radial_thickness, - center_point=center_point, - rotation_angle=self.rotation_angle, - name=f"pf_coil_{counter}", - ) - self._pf_coils.append(pf_coil) - - if self.pf_coil_case_thicknesses == []: - return self._pf_coils - - self._pf_coils_casing = [] - if len(self.pf_coil_case_thicknesses) == number_of_pf_coils: - for counter, (pf_coil_case_thickness, pf_coil) in enumerate( - zip(self.pf_coil_case_thicknesses, self._pf_coils), 1 - ): - pf_coils_casing = paramak.PoloidalFieldCoilCaseFC( - pf_coil=pf_coil, - casing_thickness=pf_coil_case_thickness, - rotation_angle=self.rotation_angle, - name=f"pf_coil_case_{counter}", - ) - self._pf_coils_casing.append(pf_coils_casing) - else: - raise ValueError( - "pf_coil_case_thicknesses is not the same length as the other " - "PF coil inputs (pf_coil_vertical_thicknesses, " - "pf_coil_radial_thicknesses, pf_coil_radial_position, " - "pf_coil_vertical_position) so can not make pf coils cases" - ) - - return self._pf_coils + self._pf_coils_casing - - raise ValueError( - "pf_coil_vertical_thicknesses, pf_coil_radial_thicknesses, " - "pf_coil_radial_position, pf_coil_vertical_position are not " - "the same length so can not make PF coils" - ) - - def _make_tf_coils(self): - comp = [] - # checks that all the required information has been input by the user - if ( - None - not in [ - self.rear_blanket_to_tf_gap, - self.outboard_tf_coil_radial_thickness, - self.outboard_tf_coil_poloidal_thickness, - self.number_of_tf_coils, - ] - and self.number_of_tf_coils > 1 - ): - - self._tf_coil = paramak.ToroidalFieldCoilRectangle( - with_inner_leg=False, - horizontal_start_point=( - self._inboard_tf_coils_start_radius, - self._tf_coil_start_height, - ), - vertical_mid_point=(self._tf_coil_start_radius, 0), - thickness=self.outboard_tf_coil_radial_thickness, - number_of_coils=self.number_of_tf_coils, - distance=self.outboard_tf_coil_poloidal_thickness, - name="tf_coil", - rotation_angle=self.rotation_angle, - ) - comp = [self._tf_coil] - return comp diff --git a/src/paramak/parametric_reactors/center_column_study_reactor.py b/src/paramak/parametric_reactors/center_column_study_reactor.py deleted file mode 100644 index 386bd800e..000000000 --- a/src/paramak/parametric_reactors/center_column_study_reactor.py +++ /dev/null @@ -1,306 +0,0 @@ -import warnings -from typing import List - -import paramak - - -class CenterColumnStudyReactor(paramak.Reactor): - """Creates geometry for a simple reactor that is optimised for carrying - out parametric studies on the center column shield. Several aspects - such as outboard magnets are intentionally missing from this reactor - so that the model runs quickly and only includes components that have a - significant impact on the center column shielding. This allows the - neutronics simulations to run quickly and the column design space to be - explored efficiently. - - Arguments: - inner_bore_radial_thickness (float): the radial thickness of the - inner bore (cm) - inboard_tf_leg_radial_thickness (float): the radial thickness of - the inner leg of the toroidal field coils (cm) - center_column_shield_radial_thickness_mid (float): the radial thickness - of the center column shield at the mid point (cm) - center_column_shield_radial_thickness_upper (float): the radial - thickness of the center column shield at the upper point (cm) - inboard_firstwall_radial_thickness (float): the radial thickness - of the inboard firstwall (cm) - divertor_radial_thickness (float): the radial thickness of the divertor - (cm) - inner_plasma_gap_radial_thickness (float): the radial thickness of - the inboard gap between the plasma and the center column shield - (cm) - plasma_radial_thickness (float): the radial thickness of the plasma - (cm) - outer_plasma_gap_radial_thickness (float): the radial thickness of - the outboard gap between the plasma and the first wall (cm) - elongation (float): the elongation of the plasma - triangularity (float): the triangularity of the plasma - center_column_arc_vertical_thickness (float): height of the outer - hyperbolic profile of the center column shield. - plasma_gap_vertical_thickness (float): the vertical thickness of - the upper gap between the plasma and the blanket (cm) - rotation_angle (float): the angle of the sector that is desired. - Defaults to 360.0. - """ - - def __init__( - self, - inner_bore_radial_thickness: float = 20, - inboard_tf_leg_radial_thickness: float = 50.0, - center_column_shield_radial_thickness_mid: float = 50.0, - center_column_shield_radial_thickness_upper: float = 100.0, - inboard_firstwall_radial_thickness: float = 20.0, - divertor_radial_thickness: float = 100.0, - inner_plasma_gap_radial_thickness: float = 80.0, - plasma_radial_thickness: float = 200.0, - outer_plasma_gap_radial_thickness: float = 90, - center_column_arc_vertical_thickness: float = 520.0, - elongation: float = 2.3, - triangularity: float = 0.45, - plasma_gap_vertical_thickness: float = 40, - rotation_angle: float = 180.0, - ): - - super().__init__([]) - - self.inner_bore_radial_thickness = inner_bore_radial_thickness - self.inboard_tf_leg_radial_thickness = inboard_tf_leg_radial_thickness - self.center_column_shield_radial_thickness_mid = center_column_shield_radial_thickness_mid - self.center_column_shield_radial_thickness_upper = center_column_shield_radial_thickness_upper - self.inboard_firstwall_radial_thickness = inboard_firstwall_radial_thickness - self.divertor_radial_thickness = divertor_radial_thickness - self.inner_plasma_gap_radial_thickness = inner_plasma_gap_radial_thickness - self.plasma_radial_thickness = plasma_radial_thickness - self.outer_plasma_gap_radial_thickness = outer_plasma_gap_radial_thickness - self.plasma_gap_vertical_thickness = plasma_gap_vertical_thickness - self.center_column_arc_vertical_thickness = center_column_arc_vertical_thickness - self.rotation_angle = rotation_angle - self.elongation = elongation - self.triangularity = triangularity - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "inner_bore_radial_thickness", - "inboard_tf_leg_radial_thickness", - "center_column_shield_radial_thickness_mid", - "center_column_shield_radial_thickness_upper", - "inboard_firstwall_radial_thickness", - "divertor_radial_thickness", - "inner_plasma_gap_radial_thickness", - "plasma_radial_thickness", - "outer_plasma_gap_radial_thickness", - "center_column_arc_vertical_thickness", - "elongation", - "triangularity", - "plasma_gap_vertical_thickness", - "rotation_angle", - ] - - # set by make_plasma - self.major_radius = None - self.minor_radius = None - - def create_solids(self): - """Creates a 3d solids for each component. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - - """ - shapes_and_components = [] - - self._rotation_angle_check() - shapes_and_components.append(self._make_plasma()) - self._make_radial_build() - self._make_vertical_build() - shapes_and_components.append(self._make_inboard_tf_coils()) - shapes_and_components.append(self._make_center_column_shield()) - shapes_and_components.append(self._make_inboard_firstwall()) - shapes_and_components.append(self._make_outboard_blanket()) - shapes_and_components.append(self._make_divertor()) - - self.shapes_and_components = shapes_and_components - - def _rotation_angle_check(self): - - if self.rotation_angle == 360: - msg = "360 degree rotation may result " + "in a Standard_ConstructionError or AttributeError" - warnings.warn(msg, UserWarning) - - def _make_plasma(self): - - # sets major radius and minor radius from equatorial_points to allow a - # radial build this helps avoid the plasma overlapping the center - # column and other components - - inner_equatorial_point = ( - self.inner_bore_radial_thickness - + self.inboard_tf_leg_radial_thickness - + self.center_column_shield_radial_thickness_mid - + self.inner_plasma_gap_radial_thickness - ) - outer_equatorial_point = inner_equatorial_point + self.plasma_radial_thickness - self.major_radius = (outer_equatorial_point + inner_equatorial_point) / 2 - self.minor_radius = self.major_radius - inner_equatorial_point - - plasma = paramak.Plasma( - major_radius=self.major_radius, - minor_radius=self.minor_radius, - elongation=self.elongation, - triangularity=self.triangularity, - rotation_angle=self.rotation_angle, - ) - - self._plasma = plasma - return plasma - - def _make_radial_build(self): - - # this is the radial build sequence, where one component stops and - # another starts - - self._inner_bore_start_radius = 0 - self._inner_bore_end_radius = self._inner_bore_start_radius + self.inner_bore_radial_thickness - - self._inboard_tf_coils_start_radius = self._inner_bore_end_radius - self._inboard_tf_coils_end_radius = self._inboard_tf_coils_start_radius + self.inboard_tf_leg_radial_thickness - - self._center_column_shield_start_radius = self._inboard_tf_coils_end_radius - self._center_column_shield_end_radius_upper = ( - self._center_column_shield_start_radius + self.center_column_shield_radial_thickness_upper - ) - self._center_column_shield_end_radius_mid = ( - self._center_column_shield_start_radius + self.center_column_shield_radial_thickness_mid - ) - - self._inboard_firstwall_start_radius = self._center_column_shield_end_radius_upper - self._inboard_firstwall_end_radius = ( - self._inboard_firstwall_start_radius + self.inboard_firstwall_radial_thickness - ) - - self._divertor_start_radius = self._inboard_firstwall_end_radius - self._divertor_end_radius = self._divertor_start_radius + self.divertor_radial_thickness - - self._inner_plasma_gap_start_radius = ( - self._center_column_shield_end_radius_mid + self.inboard_firstwall_radial_thickness - ) - - self._inner_plasma_gap_end_radius = self._inner_plasma_gap_start_radius + self.inner_plasma_gap_radial_thickness - - self._plasma_start_radius = self._inner_plasma_gap_end_radius - self._plasma_end_radius = self._plasma_start_radius + self.plasma_radial_thickness - - self._outer_plasma_gap_start_radius = self._plasma_end_radius - self._outer_plasma_gap_end_radius = self._outer_plasma_gap_start_radius + self.outer_plasma_gap_radial_thickness - - self._outboard_blanket_start_radius = self._outer_plasma_gap_end_radius - self._outboard_blanket_end_radius = self._outboard_blanket_start_radius + 100.0 - - def _make_vertical_build(self): - - # this is the vertical build sequence, componets build on each other in - # a similar manner to the radial build - - self._plasma_to_blanket_gap_start_height = self._plasma.high_point[1] - self._plasma_to_blanket_gap_end_height = ( - self._plasma_to_blanket_gap_start_height + self.plasma_gap_vertical_thickness - ) - - self._blanket_start_height = self._plasma_to_blanket_gap_end_height - self._blanket_end_height = self._blanket_start_height + 100.0 - - self._center_column_shield_end_height = self._blanket_end_height - self._inboard_firstwall_end_height = self._blanket_end_height - - def _make_inboard_tf_coils(self): - - self._inboard_tf_coils = paramak.CenterColumnShieldCylinder( - height=self._blanket_end_height * 2, - inner_radius=self._inboard_tf_coils_start_radius, - outer_radius=self._inboard_tf_coils_end_radius, - rotation_angle=self.rotation_angle, - name="inboard_tf_coils", - color=(0.0, 0.0, 1.0), - ) - return self._inboard_tf_coils - - def _make_center_column_shield(self): - - self._center_column_shield = paramak.CenterColumnShieldFlatTopHyperbola( - height=self._center_column_shield_end_height * 2.0, - arc_height=self.center_column_arc_vertical_thickness, - inner_radius=self._center_column_shield_start_radius, - mid_radius=self._center_column_shield_end_radius_mid, - outer_radius=self._center_column_shield_end_radius_upper, - rotation_angle=self.rotation_angle, - name="center_column_shield", - ) - return self._center_column_shield - - def _make_inboard_firstwall(self): - - self._inboard_firstwall = paramak.InboardFirstwallFCCS( - central_column_shield=self._center_column_shield, - thickness=self.inboard_firstwall_radial_thickness, - rotation_angle=self.rotation_angle, - name="inboard_first_wall", - ) - return self._inboard_firstwall - - def _make_outboard_blanket(self): - - self._center_column_cutter = paramak.CenterColumnShieldCylinder( - # extra 1.5 to ensure overlap, - height=self._inboard_firstwall_end_height * 2.5, - inner_radius=0, - outer_radius=self._inboard_firstwall_end_radius, - rotation_angle=self.rotation_angle, - ) - - self._blanket = paramak.BlanketFP( - plasma=self._plasma, - thickness=100.0, - offset_from_plasma=[ - self.inner_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.outer_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.inner_plasma_gap_radial_thickness, - ], - start_angle=-180, - stop_angle=180, - color=(0.0, 1.0, 0.498), - rotation_angle=self.rotation_angle, - cut=[self._center_column_cutter], - name="blanket", - ) - return self._blanket - - def _make_divertor(self): - blanket_envelope = paramak.BlanketFP( - plasma=self._plasma, - thickness=100.0, - offset_from_plasma=[ - self.inner_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.outer_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.inner_plasma_gap_radial_thickness, - ], - start_angle=-180, - stop_angle=180, - rotation_angle=self.rotation_angle, - cut=[self._center_column_cutter], - ) - - self._divertor = paramak.CenterColumnShieldCylinder( - height=self._center_column_shield_end_height * 2.5, # extra 0.5 to ensure overlap - inner_radius=self._divertor_start_radius, - outer_radius=self._divertor_end_radius, - rotation_angle=self.rotation_angle, - intersect=blanket_envelope, - color=(1.0, 0.667, 0.0), - name="divertor", - ) - self._blanket.cut.append(self._divertor) - return self._divertor diff --git a/src/paramak/parametric_reactors/eu_demo_2015_reactor.py b/src/paramak/parametric_reactors/eu_demo_2015_reactor.py deleted file mode 100644 index 27704d3dc..000000000 --- a/src/paramak/parametric_reactors/eu_demo_2015_reactor.py +++ /dev/null @@ -1,426 +0,0 @@ -import numpy as np - -import paramak - - -class EuDemoFrom2015PaperDiagram(paramak.Reactor): - """Creates geometry of a simplified EU DEMO model based on the published - diagram in Figure 2 of Definition of the basic DEMO tokamak geometry based - on systems code studies. Published in Fusion Engineering and Design - http://dx.doi.org/10.1016/j.fusengdes.2015.06.097 . Coordinates extracted - from the figure are not exact and therefore this model does not perfectly - represent the reactor. - - Arguments: - rotation_angle: the angle of the sector that is desired. - number_of_tf_coils: the number of tf coils to include in the model - """ - - def __init__( - self, - rotation_angle: float = 180.0, - number_of_tf_coils: int = 16, - ): - - super().__init__([]) - - self.rotation_angle = rotation_angle - self.number_of_tf_coils = number_of_tf_coils - - # adds self.input_variable_names from the Reactor class - self.input_variable_names = self.input_variable_names + [ - "number_of_tf_coils", - "rotation_angle", - ] - - def create_tf_coils(self, vac_vessel_inner, vac_vessel) -> list: - """Creates a 3d solids for each tf coil. - - Args: - vac_vessel (Paramak.Shape): The vac_vessel that is used in a - Boolean cut opperation to prevent overlaps - vac_vessel_inner (Paramak.Shape): The vac_vessel_inner that is - used in a Boolean cut opperation to prevent overlaps - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - # coil could be approximated with a ToroidalFieldCoilPrincetonD but is - # not included in the paper diagram - # R1 = 511 - 50 / 2 - # R2 = 1340 + 50 / 2 - # coil_thickness = 25 - - tf_coil_casing = paramak.ExtrudeMixedShape( - points=[ - (805.5787769784172, 755, "spline"), - (956.8024674963419, 744.1181924666533, "spline"), - (1019.8101517726496, 731.2212103849513, "spline"), - (1082.8178360489574, 710.3882685687647, "spline"), - (1145.8255203252652, 680.4042517472378, "spline"), - (1208.833204601573, 642.5177956124913, "spline"), - (1271.8408888778808, 593.9467051995316, "spline"), - (1332.8160672097915, 533.1872171654991, "spline"), - (1382.6124628475186, 468.4187133516837, "spline"), - (1420.2138228188637, 405.19488907747836, "spline"), - (1450.1932854987194, 339.5005122098444, "spline"), - (1472.0427244009875, 273.43725790865426, "spline"), - (1486.7783924978662, 209.78591729219943, "spline"), - (1498.1749436860923, 130.9324032157914, "spline"), - (1506.997123663055, -64.35717673922625, "spline"), - (1499.4815546503473, -158.26084228529953, "spline"), - (1489.8271514144617, -227.50802018403465, "spline"), - (1473.5671038592855, -301.2681259821559, "spline"), - (1453.7501709014145, -371.5510611717634, "spline"), - (1429.3600995686502, -437.8837368553043, "spline"), - (1402.4293958053895, -500.68420005071425, "spline"), - (1367.3686682645407, -566.760952419447, "spline"), - (1327.1758632140895, -630.9951968657044, "spline"), - (1276.5156525499938, -694.4364968444456, "spline"), - (1214.930722434764, -753.1636044922695, "spline"), - (1151.9230381584562, -796.9412746643368, "spline"), - (1088.9153538821483, -828.8191952873351, "spline"), - (1025.9076696058407, -851.7220231166343, "spline"), - (962.899985329533, -866.3620671041153, "spline"), - (805.5787769784172, -875.0, "straight"), - (377.70287769784176, -875.0, "straight"), - (375.4508992805756, 755, "straight"), - ], - distance=200, - cut=[vac_vessel_inner, vac_vessel], - azimuth_placement_angle=np.linspace(0, 360, self.number_of_tf_coils, endpoint=False), - rotation_angle=self.rotation_angle, - color=(1.0, 1.0, 0.498), - name="tf_coil_casing", - ) - - return [tf_coil_casing] - - def create_vessel_components(self) -> list: - """Creates a 3d solids for each vessel component. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - blanket = paramak.RotateMixedShape( - points=[ - (1028.5051619363035, -506.43908961374075, "spline"), - (1192.275810836831, -281.2815003658492, "spline"), - (1257.92101205376, -56.43827165248217, "spline"), - (1244.8344044363996, 216.28835367966997, "spline"), - (1153.671764932414, 400.5162013324601, "spline"), - (988.2423861054414, 520.3252882504712, "spline"), - (807.595124581199, 539.8030669696149, "spline"), - (670.5280987407093, 475.18311549274034, "spline"), - (584.8527692840913, 334.5130635036775, "spline"), - (574.292831670967, 81.767193745908, "spline"), - (579.3751030153657, -158.89465706473618, "spline"), - (580.3587684368622, -363.4679185119577, "straight"), - (686.29567682058, -355.1059282936036, "spline"), - (657.9911865059497, -182.71061116031922, "straight"), - (657.4125597874224, -62.3733985443065, "straight"), - (656.6796326106211, 90.05373743597613, "straight"), - (671.3960388185003, 294.67729656872143, "spline"), - (725.9412508183462, 379.089387299264, "spline"), - (804.2487333923825, 419.4532799322212, "spline"), - (1036.1333908422225, 356.0153240651591, "spline"), - (1095.4908483844877, 255.92292987253006, "spline"), - (1127.4889059190507, 131.6750722070317, "spline"), - (1128.4147086686944, -60.864467978588436, "spline"), - (1082.0859960719372, -221.46497785651047, "spline"), - (945.6554596218276, -418.4558632109989, "straight"), - ], - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 0.498), - name="blanket", - ) - - # SN Divertor - divertor = paramak.RotateMixedShape( - points=[ - (580.3587684368622, -363.4679185119577, "straight"), - (678.5035036777448, -367.1647983979668, "straight"), - (698.2057434436014, -383.14688797319684, "straight"), - (706.2100797165632, -415.21166249470514, "straight"), - (698.4950568028651, -443.3154942812033, "straight"), - (694.7436269110794, -479.42923248738805, "straight"), - (690.8764716755882, -491.47552817037024, "straight"), - (726.2209203989679, -495.3735987984752, "straight"), - (745.6917094774136, -463.22080332730013, "straight"), - (769.222529364193, -459.1341163784806, "straight"), - (788.8861940154811, -467.093725112643, "straight"), - (808.5691462240535, -479.0645742673395, "straight"), - (863.866572957985, -551.0908599376131, "straight"), - (891.3995609812453, -563.0365602495477, "straight"), - (895.1702784303153, -530.9340624638968, "straight"), - (883.2602118072937, -502.8931027843033, "straight"), - (886.9923541417953, -462.76812415758457, "straight"), - (945.6554596218276, -418.4558632109989, "straight"), - (1028.5051619363035, -506.43908961374075, "straight"), - (985.8893041167635, -622.9033804444106, "straight"), - (946.7548503870296, -647.096567181423, "straight"), - (801.5291878153039, -647.5618207725194, "straight"), - (675.5814387491815, -575.7618746871029, "straight"), - (612.3761135287094, -491.72701659798975, "straight"), - (584.5345245889013, -415.60146955751554, "straight"), - ], - rotation_angle=self.rotation_angle, - color=(1.0, 0.667, 0.0), - name="divertor", - ) - - # Vacuum vessel - vac_vessel_inner = paramak.RotateSplineShape( - points=[ - (574.1267649651465, 101.10991818268735), - (578.248235352396, 276.2517419573795), - (576.2157294079991, 183.80759081183805), - (574.6913499497014, 165.8825455403886), - (592.9839034492745, 356.1350119397756), - (618.3902277542372, 410.1718551122461), - (660.0565996143763, 462.707847631295), - (711.8855011965004, 503.98791778753997), - (763.7144027786246, 528.2384308674821), - (800.8076362638702, 535.0747131490673), - (957.8187204685404, 529.1614255259608), - (1009.6476220506645, 511.7304778365887), - (1061.4765236327887, 484.3593637684569), - (1113.3054252149127, 445.67421552338743), - (1160.0530619360443, 396.81085941923095), - (1196.1300424490914, 343.45306647581924), - (1221.5363667540544, 290.06656753580216), - (1239.3207937675284, 234.97736402844578), - (1251.5158294339103, 177.39960361334886), - (1259.8999164545482, 119.15248445488135), - (1262.8978627225338, 91.48061850063345), - (1257.7636381996099, -69.66392221833257), - (1248.4670705173148, -117.9739684683608), - (1236.2720348509329, -162.39122749437956), - (1219.5038608096575, -215.31064328924913), - (1198.1625483934886, -267.65634357273507), - (1171.7399711163273, -320.87421415048993), - (1140.7442554642726, -372.27816805066277), - (1102.6347690068283, -425.0006755712611), - (1058.9358912022924, -476.2931568156555), - (1022.8589106892452, -523.1641842564957), - (998.4688393564809, -582.3229466099988), - (961.8837323573345, -633.8322193152558), - (788.1044741113889, -641.8422854712626), - (746.4381022512498, -626.4054742155761), - (694.6092006691258, -595.170356965071), - (646.3371844896964, -549.174826941633), - (610.7683304627485, -496.43258230780384), - (588.9188915604805, -442.35157799696844), - (578.1466100551762, -383.4976698929381), - (577.6991331872189, -343.8423522802541), - (576.2157294079991, -254.96634344146696), - (576.2157294079991, -201.97055742152952), - (576.2157294079991, -148.97477140159208), - (576.2157294079991, -95.97898538165487), - ], - rotation_angle=self.rotation_angle, - # avoid overlap between VV and blanket divertor - union=[blanket, divertor], - name="vessel_inner", - ) - vac_vessel = paramak.RotateSplineShape( - points=[ - (515.494614319138, 96.83488831627005), - (515.494614319138, 142.76183497286695), - (515.8212670602018, 194.68137603861783), - (518.0121500911752, 287.54134932536317), - (532.0087251173638, 362.3780050073017), - (553.3500375335325, 416.5461291634835), - (586.3782591299841, 470.34782313240567), - (631.601516392818, 520.0453534354622), - (683.4304179749421, 557.8818925196001), - (735.2593195570662, 582.9203420676915), - (785.0557151947934, 596.532729851823), - (975.0950209959151, 588.576086076301), - (1026.9239225780393, 570.6573643071777), - (1078.7528241601635, 545.2847562872191), - (1130.5817257422875, 510.37733286778285), - (1181.9228258977564, 463.9075673559904), - (1225.5731493936205, 410.0396175787416), - (1258.121473753201, 357.0383914794887), - (1283.0196715720645, 304.7333152394166), - (1302.3284780438362, 252.00512715901004), - (1316.5560196546153, 198.48201099512573), - (1326.9576677230002, 139.3967559638328), - (1333.0932271113002, 100.84655663599938), - (1343.486723417876, -64.80499360522106), - (1336.0857506855605, -109.3437847848545), - (1327.3439358210303, -183.2032210908526), - (1318.0168833021507, -232.47769228107745), - (1302.8366045299354, -287.56146830105854), - (1285.5603040025608, -341.50033045928376), - (1263.7108651002927, -396.8254592659823), - (1237.2882878231312, -451.74417276722556), - (1207.308825143275, -505.037036237552), - (1172.7562240885259, -556.0143836057805), - (1128.0410933117912, -612.4026336941533), - (1076.7203182157664, -658.2571906430871), - (1024.8914166336422, -689.9315329406068), - (973.0625150515181, -711.7812967192153), - (799.7913832916718, -721.926761925964), - (771.8444265562126, -713.390499628048), - (720.0155249740885, -692.618352547739), - (668.6744248186197, -662.2813242945683), - (617.902426327582, -618.1096350415803), - (575.7076029218998, -565.7680010488721), - (546.7443932142421, -511.7869024735646), - (524.9457669605843, -451.3051510254827), - (516.7486775621876, -393.5263922426077), - (516.7486775621876, -334.6332113145754), - (516.7486775621876, -281.637425294638), - (516.7486775621876, -228.64163927470076), - (516.7486775621876, -175.64585325476332), - (516.7486775621876, -107.40944903301386), - ], - cut=vac_vessel_inner, # hollow shape - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 1.0), - name="vessel", - ) - - return [divertor, blanket, vac_vessel, vac_vessel_inner] - - def create_plasma(self) -> list: - """Creates a 3d solids for the plasma. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - plasma = paramak.PlasmaFromPoints( - outer_equatorial_x_point=1118, - inner_equatorial_x_point=677, - high_point=(853, 368), - configuration="single-null", - rotation_angle=self.rotation_angle, - ) - - return [plasma] - - def create_pf_coils(self) -> list: - """Creates a 3d solids for each pf coil. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - center_points = [ - (689, -985), - (1421, -689), - (1580, -252), - (1550, 293), - (1400, 598), - (621, 811), - ] - widths = [ - 803 - 599, - 1492 - 1351, - 1628 - 1526, - 1598 - 1503, - 1439 - 1360, - 684 - 563, - ] - heights = [ - 803 - 599, - 1492 - 1351, - 1628 - 1526, - 1598 - 1503, - 1439 - 1360, - 684 - 563, - ] - outboard_pf_coils = [] - for counter, (center_point, width, height) in enumerate(zip(center_points, widths, heights), 1): - pf_coil = paramak.PoloidalFieldCoil( - height=height, - width=width, - center_point=center_point, - rotation_angle=self.rotation_angle, - name=f"outboard_pf_coil_{counter}", - ) - outboard_pf_coils.append(pf_coil) - - pf_coils_1 = paramak.RotateStraightShape( - points=[ - (263.6088589363423, -881.6221003581469), - (263.6088589363423, -609.1721122963762), - (363.04586051526934, -609.1721122963762), - (363.04586051526934, -881.6221003581469), - ], - rotation_angle=self.rotation_angle, - name="pf_coils_1", - ) - - pf_coils_2 = paramak.RotateStraightShape( - points=[ - (266.2030353910733, -332.3839488581665), - (357.77071359802824, -332.3839488581665), - (357.77071359802824, -600.8478453421652), - (266.2030353910733, -600.8478453421652), - ], - rotation_angle=self.rotation_angle, - name="pf_coils_2", - ) - - pf_coils_3 = paramak.RotateStraightShape( - points=[ - (263.5606400431317, 217.1559887549579), - (360.3263149381907, 217.1559887549579), - (360.3263149381907, -316.0372010628879), - (263.5606400431317, -316.0372010628879), - ], - rotation_angle=self.rotation_angle, - name="pf_coils_3", - ) - - pf_coils_4 = paramak.RotateStraightShape( - points=[ - (262.2297985905187, 493.9315777717868), - (357.70320714753336, 493.9315777717868), - (357.70320714753336, 229.49149612970268), - (262.2297985905187, 229.49149612970268), - ], - rotation_angle=self.rotation_angle, - name="pf_coils_4", - ) - - pf_coils_5 = paramak.RotateStraightShape( - points=[ - (261.01468248161126, 746.6397242654133), - (356.35307813763615, 746.6397242654133), - (356.35307813763615, 510.27832556706545), - (261.01468248161126, 510.27832556706545), - ], - rotation_angle=self.rotation_angle, - name="pf_coils_5", - ) - - return outboard_pf_coils + [ - pf_coils_1, - pf_coils_2, - pf_coils_3, - pf_coils_4, - pf_coils_5, - ] - - def create_solids(self): - """Creates a 3d solids for each component. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - plasma = self.create_plasma() - pf_coils = self.create_pf_coils() - vessel = self.create_vessel_components() - tf_coil_casing = self.create_tf_coils(vessel[-1], vessel[-2]) - - shapes_and_components = plasma + pf_coils + vessel[:-1] + tf_coil_casing - self.shapes_and_components = shapes_and_components - - return shapes_and_components diff --git a/src/paramak/parametric_reactors/flf_system_code_reactor.py b/src/paramak/parametric_reactors/flf_system_code_reactor.py deleted file mode 100644 index 86680a0a5..000000000 --- a/src/paramak/parametric_reactors/flf_system_code_reactor.py +++ /dev/null @@ -1,214 +0,0 @@ -from typing import List, Optional - -import paramak - - -class FlfSystemCodeReactor(paramak.Reactor): - """Creates the 3D geometry for the a simplified FLF reactor model based - on parameters. Model design was originally presented at University of - York in 2019. Model shown at 50 mins 48 seconds in presentation - https://www.youtube.com/watch?v=DtvcEkIb4D4 - - Arguments: - inner_blanket_radius: The radial distance between the center of the - reactor on the start of the blanket (cm). - blanket_thickness: The radial thickness of the blanket (cm). - blanket_height: The height (z axis direction) of the blanket (cm). - lower_blanket_thickness: The thickness (z axis direction) of the - lower blanket pool (cm). - upper_blanket_thickness: The thickness (z axis direction) of the - upper blanket pool (cm). - blanket_vv_gap: The radial distance between the outer edge of the - blanket and the inner edge of the vaccum vessel (cm). - upper_vv_thickness: The thickness (z axis direction) of the - upper section of vaccum vessel (cm). - vv_thickness: The radial thickness of the vaccum vessel (cm) - lower_vv_thickness: The thickness (z axis direction) of the - lower section of vaccum vessel (cm). - rotation_angle: The angle of the sector simulated. Set to 360 for - simulations and less when creating models for visualization. - """ - - def __init__( - self, - inner_blanket_radius: Optional[float] = 100.0, - blanket_thickness: Optional[float] = 70.0, - blanket_height: Optional[float] = 500.0, - lower_blanket_thickness: Optional[float] = 50.0, - upper_blanket_thickness: Optional[float] = 40.0, - blanket_vv_gap: Optional[float] = 20.0, - upper_vv_thickness: Optional[float] = 10.0, - vv_thickness: Optional[float] = 10.0, - lower_vv_thickness: Optional[float] = 10.0, - rotation_angle: Optional[float] = 180.0, - ): - - super().__init__([]) - - self.rotation_angle = rotation_angle - self.inner_blanket_radius = inner_blanket_radius - self.blanket_thickness = blanket_thickness - self.blanket_height = blanket_height - self.lower_blanket_thickness = lower_blanket_thickness - self.upper_blanket_thickness = upper_blanket_thickness - self.blanket_vv_gap = blanket_vv_gap - self.upper_vv_thickness = upper_vv_thickness - self.vv_thickness = vv_thickness - self.lower_vv_thickness = lower_vv_thickness - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "inner_blanket_radius", - "blanket_thickness", - "blanket_height", - "lower_blanket_thickness", - "upper_blanket_thickness", - "blanket_vv_gap", - "upper_vv_thickness", - "vv_thickness", - "lower_vv_thickness", - "rotation_angle", - ] - - def create_solids(self): - """Creates a list of paramak.Shape for components and saves it in - self.shapes_and_components - """ - inner_wall = self.inner_blanket_radius + self.blanket_thickness + self.blanket_vv_gap - lower_vv = paramak.RotateStraightShape( - points=[ - (inner_wall, 0), - ( - inner_wall, - self.lower_vv_thickness, - ), - ( - 0, - self.lower_vv_thickness, - ), - (0, 0), - ], - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - name="lower_vessel", - ) - - lower_blanket = paramak.RotateStraightShape( - points=[ - (inner_wall, self.lower_vv_thickness), - (inner_wall, self.lower_vv_thickness + self.lower_blanket_thickness), - (0, self.lower_vv_thickness + self.lower_blanket_thickness), - (0, self.lower_vv_thickness), - ], - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 0.498), - name="lower_blanket", - ) - - blanket = paramak.CenterColumnShieldCylinder( - height=self.blanket_height, - center_height=self.lower_vv_thickness + self.lower_blanket_thickness + 0.5 * self.blanket_height, - inner_radius=self.inner_blanket_radius, - outer_radius=self.blanket_thickness + self.inner_blanket_radius, - rotation_angle=self.rotation_angle, - cut=lower_blanket, - color=(0.0, 1.0, 0.498), - name="blanket", - ) - - upper_vv = paramak.RotateStraightShape( - points=[ - (inner_wall, self.lower_vv_thickness + self.lower_blanket_thickness + self.blanket_height), - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - ( - 0, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - (0, self.lower_vv_thickness + self.lower_blanket_thickness + self.blanket_height), - ], - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - name="upper_vessel", - ) - - upper_blanket = paramak.RotateStraightShape( - points=[ - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - ( - 0, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - ( - 0, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - ], - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 0.498), - name="upper_blanket", - ) - - vac_ves = paramak.RotateStraightShape( - points=[ - (inner_wall, 0), - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - ( - inner_wall + self.vv_thickness, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - (inner_wall + self.vv_thickness, 0), - ], - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - name="vessel", - ) - - self.shapes_and_components = [ - blanket, - vac_ves, - upper_blanket, - lower_blanket, - lower_vv, - upper_vv, - ] diff --git a/src/paramak/parametric_reactors/iter_paper_2020.py b/src/paramak/parametric_reactors/iter_paper_2020.py deleted file mode 100644 index 98efa5345..000000000 --- a/src/paramak/parametric_reactors/iter_paper_2020.py +++ /dev/null @@ -1,339 +0,0 @@ -from typing import List - -import numpy as np -import paramak - - -class IterFrom2020PaperDiagram(paramak.Reactor): - """Creates geometry of a simplified ITER model. The geometry was based on - "ITER Project: International Cooperation and Energy Investment" - available at https://link.springer.com/chapter/10.1007/978-3-030-42913-3_26 - Many shapes are built-in paramak shapes therefore the model does not match - the diagram exactly. - - Arguments: - rotation_angle: the angle of the sector that is desired. - number_of_tf_coils: the number of tf coils to include in the model - """ - - def __init__( - self, - rotation_angle: float = 180.0, - number_of_tf_coils: int = 18, - ): - - super().__init__([]) - - self.rotation_angle = rotation_angle - self.number_of_tf_coils = number_of_tf_coils - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "number_of_tf_coils", - "rotation_angle", - ] - - def create_tf_coils(self) -> list: - """Creates a 3d solids for each tf coil. - - Args: - - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - R1 = 219 - R2 = 1.026e3 + 30 - coil_thickness = R1 - 130 - - tf_coil = paramak.ToroidalFieldCoilPrincetonD( - R1=R1, - R2=R2, - thickness=coil_thickness, - distance=coil_thickness, - number_of_coils=self.number_of_tf_coils, - rotation_angle=self.rotation_angle, - name="tf_coils", - ) - - return [tf_coil] - - def create_vessel_components(self) -> list: - """Creates a 3d solids for each vessel component. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - # Blanket computed from plasma - blanket = paramak.BlanketFP( - plasma=self.plasma, - thickness=4.06e2 - 3.52e2, - start_angle=-70, - stop_angle=230, - rotation_angle=self.rotation_angle, - vertical_displacement=self.plasma.vertical_displacement, - offset_from_plasma=[[-70, 0, 90, 180, 230], [50, 20, 59, 16, 50]], - name="blanket", - ) - - # SN Divertor - divertor = paramak.ITERtypeDivertor( - anchors=((4.34e2, -3.3e2), (5.56e2, -3.74e2)), - coverages=(105, 125), - lengths=(45, 75), - radii=(68, 65), - tilts=(-30, 2), - dome_height=45, - dome_pos=0.45, - rotation_angle=self.rotation_angle, - name="divertor", - ) - - # Vacuum vessel - divertor.points # trigger the building of the points for divertor - # the inner part of the vacuum vessel is computed from the outer - # points of the blanket and the divertor - vac_vessel_inner = paramak.RotateMixedShape( - points=blanket.outer_points + divertor.casing_points, - rotation_angle=self.rotation_angle, - name="vessel", - ) - - vac_vessel = paramak.RotateSplineShape( - points=[ - (327.77, 36.5026668124882), - (327.77, 73.37741270075162), - (327.77, 108.31180820215741), - (327.77, 143.2462037035632), - (327.77, 178.18059920496898), - (327.77, 213.11499470637477), - (327.77, 248.04939020778068), - (327.77, 282.98378570918646), - (327.77, 317.9181812105922), - (328.6121587814181, 368.23899806938385), - (336.18303032328333, 422.4306297110355), - (350.4835654579176, 457.5437492206628), - (371.95910957013655, 492.47041663587777), - (404.3208742000702, 522.0151685493631), - (439.6516080621078, 544.4559826211985), - (474.98234192414554, 556.3610266211815), - (510.2245275810152, 564.0927634387052), - (545.6438096482208, 565.1200145185009), - (565.832800426528, 563.1864687746993), - (580.9745435102584, 559.4390362932862), - (616.3052773722961, 548.4109567158157), - (651.6360112343338, 533.224020531035), - (686.9667450963714, 515.3041214328789), - (722.297478958409, 492.23516177329117), - (757.6282128204466, 466.8689289401416), - (792.9589466824843, 437.10619055069265), - (825.7660566972336, 403.7167485984509), - (853.525919017406, 369.42176700251196), - (877.9209495411939, 333.90960594986575), - (898.9511482685972, 300.5186330502012), - (916.616515199616, 265.2383422522439), - (932.5994662324425, 230.72194441870647), - (946.0587934179808, 193.1122328856627), - (956.1532888071343, 156.87835598377137), - (962.8829523999035, 118.10702768634405), - (967.9302000944803, 80.39197257542594), - (968.7714080435763, 38.24754419835381), - (968.7714080435763, 25.77097437642317), - (964.5653682980957, -1.670738783514139), - (956.9944967562304, -29.93883090626548), - (956.1532888071343, -34.59540221679083), - (946.0587934179808, -71.15339839027786), - (931.7582582833464, -104.25874435511184), - (914.9340993014238, -139.91477225259314), - (898.9511482685972, -174.48160361826422), - (883.8094051848669, -213.64300914878197), - (867.8264541520404, -248.21908241802464), - (851.0022951701176, -284.2078188440911), - (834.1781361881949, -319.9470238737184), - (818.1951851553683, -359.0978394110024), - (800.5298182243495, -391.2313539579658), - (776.1347877005617, -427.87174371008393), - (744.1688856349085, -460.45530873911446), - (708.8381517728709, -490.0255912806248), - (673.5074179108332, -512.7040543014494), - (638.1766840487956, -528.371873327094), - (602.8459501867579, -539.0490644239661), - (567.5152163247203, -546.1219131278361), - (532.1844824626827, -548.9566889080664), - (496.85374860064496, -547.7514325554811), - (461.52301473860734, -541.3971156414638), - (426.1922808765697, -527.596464992453), - (390.8615470145321, -501.2796363633471), - (360.57806084707124, -468.0473902249954), - (340.389070068764, -431.4355817359209), - (329.87397070506233, -399.072068113844), - (327.770950832322, -357.4796824533661), - (327.770950832322, -311.73270913617455), - (327.770950832322, -276.79831363476876), - (327.770950832322, -241.86391813336297), - (327.770950832322, -206.92952263195718), - (327.770950832322, -171.99512713055117), - (327.770950832322, -137.06073162914538), - (327.770950832322, -102.12633612773948), - (327.770950832322, -67.19194062633369), - ], - cut=[vac_vessel_inner], # to make a hollow shape - rotation_angle=self.rotation_angle, - name="vessel_inner", - ) - - return [divertor, blanket, vac_vessel, vac_vessel_inner] - - def create_plasma(self) -> list: - """Creates a 3d solids for the plasma. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - self.plasma = paramak.Plasma( - major_radius=6.2e2, - minor_radius=2e2, - elongation=1.7, - triangularity=0.33, - vertical_displacement=5.7e1, - configuration="single-null", - rotation_angle=self.rotation_angle, - ) - - return [self.plasma] - - def create_pf_coils(self) -> list: - """Creates a 3d solids for each pf coil. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - # from diagram - lower_lefts = np.array( - [ - (345.5429497568881, -788.0537547271744), - (800.6482982171799, -703.3664235548353), - (1160.9400324149108, -272.69381415451096), - (1158.833063209076, 268.97622906537015), - (798.5413290113453, 621.6369529983793), - (345.5429497568881, 707.7795786061589), - ] - ) - - top_rights = np.array( - [ - (511.99351701782825, -690.4038357644516), - (880.7131280388979, -611.8280659103187), - (1222.0421393841166, -162.37506753106413), - (1230.4700162074555, 379.2780929227446), - (861.7504051863858, 681.9523230686117), - (446.677471636953, 803.4508373851974), - ] - ) - - outboard_pf_coils = [] - for counter, (top_right, lower_left) in enumerate(zip(top_rights, lower_lefts), 1): - pf_coil = paramak.PoloidalFieldCoilFP( - corner_points=(top_right, lower_left), - rotation_angle=self.rotation_angle, - name=f"outboard_pf_coils_{counter}", - ) - outboard_pf_coils.append(pf_coil) - - x_inner, x_outer = 132.73905996758506, 202.26904376012968 - - pf_coils_1 = paramak.RotateStraightShape( - points=[ - (x_inner, -600), - (x_outer, -600), - (x_outer, -400), - (x_inner, -400), - ], - rotation_angle=self.rotation_angle, - name="pf_coil_1", - ) - - pf_coils_2 = paramak.RotateStraightShape( - points=[ - (x_inner, -400), - (x_outer, -400), - (x_outer, -200), - (x_inner, -200), - ], - rotation_angle=self.rotation_angle, - name="pf_coil_2", - ) - - pf_coils_3 = paramak.RotateStraightShape( - points=[ - (x_inner, -200), - (x_outer, -200), - (x_outer, 0), - (x_inner, 0), - ], - rotation_angle=self.rotation_angle, - name="pf_coil_3", - ) - - pf_coils_4 = paramak.RotateStraightShape( - points=[ - (x_inner, 0), - (x_outer, 0), - (x_outer, 200), - (x_inner, 200), - ], - rotation_angle=self.rotation_angle, - name="pf_coil_4", - ) - - pf_coils_5 = paramak.RotateStraightShape( - points=[ - (x_inner, 200), - (x_outer, 200), - (x_outer, 400), - (x_inner, 400), - ], - rotation_angle=self.rotation_angle, - name="pf_coil_5", - ) - - pf_coils_6 = paramak.RotateStraightShape( - points=[ - (x_inner, 400), - (x_outer, 400), - (x_outer, 600), - (x_inner, 600), - ], - rotation_angle=self.rotation_angle, - name="pf_coil_6", - ) - - return outboard_pf_coils + [ - pf_coils_1, - pf_coils_2, - pf_coils_3, - pf_coils_4, - pf_coils_5, - pf_coils_6, - ] - - def create_solids(self): - """Creates a 3d solids for each component. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - """ - - plasma = self.create_plasma() - pf_coils = self.create_pf_coils() - tf_coil = self.create_tf_coils() - vessel = self.create_vessel_components() - - shapes_and_components = plasma + pf_coils + vessel[:-1] + tf_coil - self.shapes_and_components = shapes_and_components - - return shapes_and_components diff --git a/src/paramak/parametric_reactors/negative_triangularity_reactor.py b/src/paramak/parametric_reactors/negative_triangularity_reactor.py deleted file mode 100644 index 34e805054..000000000 --- a/src/paramak/parametric_reactors/negative_triangularity_reactor.py +++ /dev/null @@ -1,964 +0,0 @@ -from typing import List, Union, Optional -import paramak - - -class NegativeTriangularityReactor(paramak.Reactor): - """ - New class of reactor that builds a negative triangularity tokamak model. - - Arguments: - inner_tf_coil_thickness: radial thickness of the Toroidal Field coil's - inner leg (cm), - vacuum_vessel_thickness: the radial and vertical thickness of the - vacuum vessel (cm), - central_shield_thickness: radial thickness of the central heat shield - (cm), - wall_to_plasma_gap: gap of inner blanket wall and the plasma outter - edge (cm), - plasma_radial_thickness: radial thickness of the plasma - (2x minor radius) (cm), - elongation: plasma elongation, - triangularity: plasma triangularity - both positive or negative values - will result in negative triangularity, - inner_wall_thickness: plasma facing blanket wall thickness (cm), - blanket_thickness: breeder blanket thickness (cm), - rear_wall_thickness: outer blanket wall thickness (cm), - divertor_radial_thickness: radial thickness of the divertor (cm), - divertor_height_full: divertor vertical thickness (cm), - number_of_coils: number of Toroidal Field coils around the reactor - evenly spaced, - tf_width: Toroidal Field coil extrusion distance / thickness (cm), - pf_coil_heights: List of Poloidal field coil heights (cm), - pf_coil_widths: List of Poloidal field coil widths (cm), - pf_coil_center_points: List of Poloidal field coil center points on the - XZ workplane (cm), - pf_coil_casing_thickness: List of Poloidal field coil casing thickness - (cm), - rotation_angle: Angle of rotation arounbd the Z axis of which the - reactor is shown - 180° shows half a reactor, - inner_bore_radius: Inner bore radial thickness (cm); Defaults to 5 cm, - port_side_lengths: List containing the side lengths of the ports (cm), - port_heights: List containing the heights of the ports (cm), - port_angles: List containing the angles of the ports center points (°), - port_z_pos: List containing the Z position of the ports as Zero in the - centre of the reactor (cm), - outer_tf_coil_thickness: Outer Toroidal Field coil thickness (cm) - - defaults to the inner Toroidal Field coil thickness,, - low_aspect: Boolean allowing a swift switch between a lower - aspect-ratio reactor (True) where the inner blanket is cut by the - center column, whereas (False) non-low-aspect will produce a full - inner blanket and only part being cut by the centre column is the - rear blanket wall, - """ - - def __init__( - self, - inner_tf_coil_thickness: float = 100, - vacuum_vessel_thickness: float = 50, - central_shield_thickness: float = 30, - wall_to_plasma_gap: float = 150, - plasma_radial_thickness: float = 650, - elongation: float = 2, - triangularity: float = 0.6, - inner_wall_thickness: float = 20, - blanket_thickness: float = 105, - rear_wall_thickness: float = 20, - divertor_radial_thickness: float = 430, - divertor_height_full: float = 300, - number_of_coils: int = 12, - tf_width: float = 75, - pf_coil_heights: Optional[Union[float, List[float]]] = [75, 75, 150, 75, 75], - pf_coil_widths: Optional[Union[float, List[float]]] = [70, 70, 150, 70, 70], - pf_coil_center_points: Optional[Union[list, tuple]] = [ - (350, 850), - (1350, 650), - (1350, 0), - (1350, -650), - (350, -850), - ], - pf_coil_casing_thickness: Optional[List[float]] = [15, 15, 15, 15, 15], - rotation_angle: float = 180, - inner_bore_radius: float = 50, - port_side_lengths: Optional[List[float]] = [200, 200, 150], - port_heights: Optional[List[float]] = [200, 100, 400], - port_angles: Optional[List[float]] = [75, 170, 15], - port_z_pos: Optional[List[float]] = [500, -500, 200], - outer_tf_coil_thickness: Optional[float] = None, - low_aspect: bool = False, - ): - - super().__init__([]) - self._inner_tf_coil_thickness = inner_tf_coil_thickness - self._vacuum_vessel_thickness = vacuum_vessel_thickness - self._central_shield_thickness = central_shield_thickness - self._wall_to_plasma_gap = wall_to_plasma_gap - self._plasma_radial_thickness = plasma_radial_thickness - self._elongation = elongation - self._triangularity = -1 * abs(triangularity) - self._inner_wall_thickness = inner_wall_thickness - self._blanket_thickness = blanket_thickness - self._rear_wall_thickness = rear_wall_thickness - self._divertor_radial_thickness = divertor_radial_thickness - self._divertor_height_full = divertor_height_full - self._inner_bore_radius = inner_bore_radius - - if outer_tf_coil_thickness is None: - self._outer_tf_coil_thickness = inner_tf_coil_thickness - else: - self._outer_tf_coil_thickness = outer_tf_coil_thickness - - self._pf_coil_heights = pf_coil_heights - self._pf_coil_widths = pf_coil_widths - self._pf_coil_center_points = pf_coil_center_points - self._pf_casing_thickness = pf_coil_casing_thickness - - self._rotation_angle = rotation_angle - self._low_aspect = low_aspect - self._number_of_coils = number_of_coils - self._tf_width = tf_width - self._port_side_lengths = port_side_lengths - self._port_heights = port_heights - self._ports_angles = port_angles - self._port_z_pos = port_z_pos - - self.input_variable_names = [ - "inner_tf_coil_thickness", - "vacuum_vessel_thickness", - "central_shield_thickness", - "wall_to_plasma_gap", - "plasma_radial_thickness", - "elongation", - "triangularity", - "inner_wall_thickness", - "blanket_thickness", - "rear_wall_thickness", - "divertor_radial_thickness", - "divertor_height_full", - "number_of_coils", - "tf_width", - "pf_coil_heights", - "pf_coil_widths", - "pf_coil_center_points", - "pf_coil_casing_thickness", - "rotation_angle", - "inner_bore_radius", - "port_side_lengths", - "port_heights", - "port_angles", - "port_z_pos", - "outer_tf_coil_thickness", - "low_aspect", - ] - - if None in [ - self._ports_angles, - self._port_side_lengths, - self._port_heights, - self._port_z_pos, - ]: - self._ports_enable = False - else: - self._ports_enable = True - - if None in [ - self._pf_coil_heights, - self._pf_coil_widths, - self._pf_coil_center_points, - self._pf_casing_thickness, - ]: - self._pf_enabled = False - else: - self._pf_enabled = True - - self._plasma_geometry() - self._equatorial_points() - - # Set by plasma, radial or vertical build - self._plasma = None - self._tf_coils_init = None - self._pf_coils = None - self._pf_casing = None - self._ports = None - self._bore_cutter = None - self._tf_inner_leg = None - self._vacuum_vessel_inner_wall = None - self._inner_shield = None - self._divertor_cutter_cutter = None - self._divertor_cutter = None - self._rear_wall = None - self._breeder_blanket = None - self._inner_wall = None - self._divertor_extention_cutter = None - self._divertor_midplane_cutter = None - self._divertor = None - self._vacuum_vessel_body = None - self._tf_coils = None - - self._inner_bore_start_rad = 0 - self._inner_bore_stop_rad = 0 - self._inner_tf_leg_height = 0 - self._tf_inner_leg_start_rad = 0 - self._tf_inner_leg_end_rad = 0 - self._inner_shield_height = 0 - self._inner_shield_start_rad = 0 - self._inner_shield_end_rad = 0 - self._blanket_start_height_top = 0 - self._blanket_end_height_top = 0 - self._blanket_offset = 0 - self._inner_wall_start_height = 0 - self._inner_wall_end_height = 0 - self._rear_wall_start_height_top = 0 - self._rear_wall_end_height_top = 0 - self._divertor_start_height = 0 - self._divertor_end_height_top = 0 - self._vacuum_vessel_start_height = 0 - self._vacuum_vessel_end_height = 0 - self._vacuum_vessel_height = 0 - self._vacuum_vessel_body_start_rad = 0 - self._vacuum_vessel_body_end_rad = 0 - self._outer_blanket_height = 0 - self._vacuum_vessel_inwall_start_rad = 0 - self._vacuum_vessel_inwall_end_rad = 0 - self._rear_wall_plasma_offset = 0 - self._divertor_start_rad = 0 - self._divertor_end_rad = 0 - self._small_rad_displacement = 0 - self._tf_start_rad = 0 - self._tf_end_rad = 0 - - def _plasma_geometry(self): - """Calculating plasma geometry from parameters. Adjust a gap between - inner TF leg and vacuum vessel to accommodate a wider range of - thicknesses""" - core_width = ( - self._inner_bore_radius - + self._inner_tf_coil_thickness - + self._vacuum_vessel_thickness - + self._central_shield_thickness - ) - blanket_width = self._inner_wall_thickness + self._blanket_thickness + self._rear_wall_thickness - wdth_diff = blanket_width - core_width - - if wdth_diff > 0: - self._inner_leg_to_vacuum_inner_wall_gap = wdth_diff - else: - self._inner_leg_to_vacuum_inner_wall_gap = 0 - - def _equatorial_points(self): - # Define Equatorial points - self._inner_equatorial_point = ( - self._inner_bore_radius - + self._inner_tf_coil_thickness - + self._vacuum_vessel_thickness - + self._central_shield_thickness - + self._wall_to_plasma_gap - + self._inner_leg_to_vacuum_inner_wall_gap - ) - if not self._low_aspect: - self._inner_equatorial_point += ( - self._inner_wall_thickness + self._blanket_thickness + self._rear_wall_thickness - ) - - self._outer_equatorial_point = self._inner_equatorial_point + self._plasma_radial_thickness - - self._major_radius = (self._outer_equatorial_point + self._inner_equatorial_point) / 2 - self._minor_radius = self._major_radius - self._inner_equatorial_point - - # Getters - @property - def aspect_ratio(self): - return self._major_radius / self._minor_radius - - @property - def minor_radius(self): - return self._minor_radius - - @property - def major_radius(self): - return self._major_radius - - @property - def inner_equatorial_point(self): - return self._inner_equatorial_point - - @property - def outer_equatorial_point(self): - return self._outer_equatorial_point - - @property - def inner_bore_radius(self): - return self._inner_bore_radius - - @property - def inner_tf_coil_thickness(self): - return self._inner_tf_coil_thickness - - @property - def vacuum_vessel_thickness(self): - return self._vacuum_vessel_thickness - - @property - def central_shield_thickness(self): - return self._central_shield_thickness - - @property - def wall_to_plasma_gap(self): - return self._wall_to_plasma_gap - - @property - def plasma_radial_thickness(self): - return self._plasma_radial_thickness - - @property - def elongation(self): - return self._elongation - - @property - def triangularity(self): - return self._triangularity - - @property - def inner_wall_thickness(self): - return self._inner_wall_thickness - - @property - def blanket_thickness(self): - return self._blanket_thickness - - @property - def rear_wall_thickness(self): - return self._rear_wall_thickness - - @property - def divertor_radial_thickness(self): - return self._divertor_radial_thickness - - @property - def divertor_height(self): - return self._divertor_height_full - - @property - def tf_width(self): - return self.tf_width - - @property - def port_side_lengths(self): - return self._port_side_lengths - - @property - def port_heights(self): - return self._port_heights - - @property - def port_angles(self): - return self._ports_angles - - @property - def port_z_pos(self): - return self._port_z_pos - - @property - def pf_coil_heights(self): - return self._pf_coil_heights - - @property - def pf_coil_widths(self): - return self._pf_coil_widths - - @property - def pf_coil_center_points(self): - return self._pf_coil_center_points - - @property - def pf_coil_casing_thickness(self): - return self._pf_casing_thickness - - @property - def low_aspect(self): - return self._low_aspect - - # Setters - - @inner_bore_radius.setter - def inner_bore_radius(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Inbore radius must be float or integer value!") - self._inner_bore_radius = val - - @inner_tf_coil_thickness.setter - def inner_tf_coil_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Inbore tf coil thickness must be float or integer value!") - self._inner_tf_coil_thickness = val - - @vacuum_vessel_thickness.setter - def vacuum_vessel_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Vacuum vessel thickness must be float or integer value!") - self._vacuum_vessel_thickness = val - - @central_shield_thickness.setter - def central_shield_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Inbore heat shield thickness must be float or integer value!") - self._central_shield_thickness = val - - @wall_to_plasma_gap.setter - def wall_to_plasma_gap(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Plasma to wall gap must be float or integer value!") - self._wall_to_plasma_gap = val - - @plasma_radial_thickness.setter - def plasma_radial_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("plasma radial thickness must be float or integer value!") - self._plasma_radial_thickness = val - - @elongation.setter - def elongation(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Elongation must be float or integer value!") - self._elongation = val - - @triangularity.setter - def triangularity(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Triangularity must be float or integer value!") - if val > 1 or val < -1: - raise ValueError("Triangularity must be between -1 and 1!") - self._triangularity = val - - @inner_wall_thickness.setter - def inner_wall_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Inner blanket wall must be float or integer value!") - self._inner_wall_thickness = val - - @blanket_thickness.setter - def blanket_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Blanket thickness must be float or integer value!") - self._blanket_thickness = val - - @rear_wall_thickness.setter - def rear_wall_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("rear blanket wall must be float or integer value!") - self._rear_wall_thickness = val - - @divertor_radial_thickness.setter - def divertor_radial_thickness(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Divertor radial thickness must be float or integer value!") - self._divertor_radial_thickness = val - - @divertor_height.setter - def divertor_height(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Divertor height must be float or integer value!") - self._divertor_height_full = val - - @tf_width.setter - def tf_width(self, val): - if not isinstance(val, (float, int)): - raise TypeError("Tf coil width must be float or integer value!") - self._tf_width = val - - @port_side_lengths.setter - def port_side_lengths(self, val): - if not isinstance(val, list) or False in [isinstance(x, (float, int)) for x in val]: - raise TypeError("Port side lengths must be a list of numbers!") - self._port_checks() - self._port_side_lengths = val - - @port_heights.setter - def port_heights(self, val): - if not isinstance(val, list) or False in [isinstance(x, (float, int)) for x in val]: - raise TypeError("Port heights must be a list of numbers!") - self._port_checks() - self._port_thickness = val - - @port_angles.setter - def port_angles(self, val): - if not isinstance(val, list) or False in [isinstance(x, (float, int)) for x in val]: - raise TypeError("Port angles must be a list of numbers!") - self._port_checks() - self._ports_angles = val - - @port_z_pos.setter - def port_z_pos(self, val): - if not isinstance(val, list) or False in [isinstance(x, (float, int)) for x in val]: - raise TypeError("Port Z positions must be a list of numbers!") - self._port_checks() - self._port_z_pos = val - - @pf_coil_heights.setter - def pf_coil_heights(self, val): - if not isinstance(val, list) or False in [isinstance(x, (float, int)) for x in val]: - raise TypeError("Pf coil heights must be a list of numbers!") - self._pf_checks(False) - self._pf_coil_heights = val - - @pf_coil_widths.setter - def pf_coil_widths(self, val): - if not isinstance(val, list) or False in [isinstance(x, (float, int)) for x in val]: - raise TypeError("Pf coil width must be a list of numbers!") - self._pf_checks(False) - self._pf_coil_widths = val - - @pf_coil_center_points.setter - def pf_coil_center_points(self, val): - if not isinstance(val, list) or False in [isinstance(x, tuple) for x in val]: - raise TypeError("Pf coil center points must be a list of tuples!") - self._pf_checks(True) - self._pf_coil_center_points = val - - @pf_coil_casing_thickness.setter - def pf_coil_casing_thickness(self, val): - if not isinstance(val, list) or False in [isinstance(x, (float, int)) for x in val]: - raise TypeError("Pf coil heights must be a list of numbers!") - self._pf_checks(False) - self._pf_casing_thickness = val - - @low_aspect.setter - def low_aspect(self, val): - if not isinstance(val, bool): - raise TypeError("Low-aspect argument must be True or False!") - self._low_aspect = val - - def create_solid(self): - - shapes_and_components = [] - - self._plasma_geometry() - self._equatorial_points() - self._make_plasma() - self._make_vertical_build() - self._make_radial_build() - - shapes_and_components.append(self._make_plasma()) - - if self._ports_enable: - self._make_ports() - if self._pf_enabled: - shapes_and_components += self._make_pf_coils() - - shapes_and_components += self._make_tf_inner_leg() - shapes_and_components += self._make_vacuum_vessel_inner_wall() - shapes_and_components += self._make_inner_shield() - shapes_and_components += self._make_blankets() - shapes_and_components += self._make_divertor() - shapes_and_components += self._make_tf_coils() - shapes_and_components += self._make_vacuum_vessel() - - self.shapes_and_components = shapes_and_components - - def _make_plasma(self): - self._plasma = paramak.Plasma( - major_radius=self._major_radius, - minor_radius=self._minor_radius, - elongation=self._elongation, - triangularity=self._triangularity, - rotation_angle=self._rotation_angle, - color=(0, 0.5, 0.5), - ) - return self._plasma - - def _make_vertical_build(self): - # Above the plasma - # Inner wall - self._inner_wall_start_height = self._plasma.high_point[1] + self._wall_to_plasma_gap - self._inner_wall_end_height = self._inner_wall_start_height + self._inner_wall_thickness - # Blanket - self._blanket_start_height_top = self._inner_wall_end_height - self._blanket_end_height_top = self._blanket_start_height_top + self._blanket_thickness - # Rear wall - self._rear_wall_start_height_top = self._blanket_end_height_top - self._rear_wall_end_height_top = self._rear_wall_start_height_top + self._rear_wall_thickness - # Divertor - self._divertor_start_height = self._plasma.high_point[1] - self._divertor_end_height_top = self._divertor_start_height + self._divertor_height_full - - # Diverter height check - min_div_h = self._rear_wall_end_height_top - self._divertor_start_height - if min_div_h > self._divertor_height_full: - print( - f"Set divertor height is too low. \ - Diverter height is set to minimum of {round(min_div_h)} cm" - ) - self._divertor_end_height_top = self._divertor_start_height + min_div_h - # Vacuum Vessel Inner Wall - self._vacuum_vessel_start_height = self._divertor_end_height_top - self._vacuum_vessel_end_height = self._vacuum_vessel_start_height + self._vacuum_vessel_thickness - # Central Heights - self._inner_tf_leg_height = self._vacuum_vessel_end_height * 2 - self._vacuum_vessel_height = self._vacuum_vessel_start_height * 2 - self._inner_shield_height = self._vacuum_vessel_start_height * 2 - # Outer Blanket Height - self._outer_blanket_height = self._inner_shield_height - (2 * self._divertor_height_full) - if self._outer_blanket_height < 0: - raise ValueError("The divertors are overlapping at the center plane.") - - def _make_radial_build(self): - # Bore - self._inner_bore_start_rad = 0 - self._inner_bore_stop_rad = self._inner_bore_radius - # Inner TF Coil - self._tf_inner_leg_start_rad = self._inner_bore_stop_rad - self._tf_inner_leg_end_rad = self._tf_inner_leg_start_rad + self._inner_tf_coil_thickness - # Vacuum Vessel Inner wall - self._vacuum_vessel_inwall_start_rad = self._tf_inner_leg_end_rad + self._inner_leg_to_vacuum_inner_wall_gap - self._vacuum_vessel_inwall_end_rad = self._vacuum_vessel_inwall_start_rad + self._vacuum_vessel_thickness - # Central Column Shield - self._inner_shield_start_rad = self._vacuum_vessel_inwall_end_rad - self._inner_shield_end_rad = self._inner_shield_start_rad + self._central_shield_thickness - # Blanket Offset - self._blanket_offset = self._wall_to_plasma_gap + self._inner_wall_thickness - # Rear Wall offset - self._rear_wall_plasma_offset = self._wall_to_plasma_gap + self._blanket_thickness + self._inner_wall_thickness - - # Run check for diverter parameters - full_outer_blanket_rad = ( - self._major_radius - + self._minor_radius - + self._wall_to_plasma_gap - + self._inner_wall_thickness - + self._blanket_thickness - + self._rear_wall_thickness - ) - - width_parameter_difference = full_outer_blanket_rad - self._plasma.high_point[0] - - if self._divertor_radial_thickness < width_parameter_difference: - print( - f"The given radial thickness of the divertor is too small.\ - Diverter set to minimum radial thickness of \ - {round(width_parameter_difference, 2)} cm" - ) - self._divertor_radial_thickness = width_parameter_difference - - # Divertor parts - self._divertor_start_rad = self._plasma.high_point[0] - self._divertor_end_rad = self._divertor_start_rad + self._divertor_radial_thickness - # Vacuum Vessel Body - self._vacuum_vessel_body_start_rad = self._divertor_end_rad - self._vacuum_vessel_body_end_rad = self._vacuum_vessel_body_start_rad + self._vacuum_vessel_thickness - # TF Coils - # Getting small radius for inner corner - self._tf_coils_init = paramak.ToroidalFieldCoilRectangleRoundCorners( - with_inner_leg=False, - lower_inner_coordinates=( - self._inner_bore_stop_rad, - -self._inner_tf_leg_height / 2, - ), - mid_point_coordinates=(self._vacuum_vessel_body_end_rad, 0), - thickness=self._outer_tf_coil_thickness, - number_of_coils=self._number_of_coils, - distance=self._tf_width, - rotation_angle=self._rotation_angle, - color=(0.2, 1, 0.2), - ) - - self._small_rad_displacement = self._tf_coils_init.analyse_attributes[2] - - self._tf_start_rad = self._vacuum_vessel_body_end_rad + self._small_rad_displacement - self._tf_end_rad = self._tf_start_rad + self._inner_tf_coil_thickness - - def _make_pf_coils(self): - - self._pf_checks(True) - - check_list = [x[0] >= self._tf_end_rad for x in self._pf_coil_center_points] - if False in check_list: - print("One or more Poloidal Field Coil is within the Reactor geometry!") - - self._pf_coils = paramak.PoloidalFieldCoilSet( - heights=self._pf_coil_heights, - widths=self._pf_coil_widths, - center_points=self._pf_coil_center_points, - name="pf_coil_set", - color=(0.7, 0.7, 0.2), - rotation_angle=self._rotation_angle, - ) - - self._pf_casing = paramak.PoloidalFieldCoilCaseSet( - heights=self._pf_coil_heights, - widths=self._pf_coil_widths, - center_points=self._pf_coil_center_points, - casing_thicknesses=self._pf_casing_thickness, - name="pf_coil_set_case", - color=(0.7, 0.5, 0.2), - rotation_angle=self._rotation_angle, - ) - return [self._pf_coils, self._pf_casing] - - def _make_ports(self): - - self._port_checks() - - self._ports = [] - - for index, val in enumerate(self._port_side_lengths): - - _port = paramak.PortCutterRectangular( - height=self._port_heights[index], - width=val, - distance=self._tf_end_rad, - center_point=(self._port_z_pos[index], 0), - extrusion_start_offset=0, - azimuth_placement_angle=self._ports_angles[index], - name=f"port_{index}", - ) - self._ports.append(_port) - return self._ports - - def _make_tf_inner_leg(self): - - _cutting_list = [self._pf_coils, self._pf_casing] - if self._inner_bore_radius != 0: - self._bore_cutter = paramak.CenterColumnShieldCylinder( - height=self._inner_tf_leg_height + 10, - inner_radius=0, - outer_radius=self._inner_bore_stop_rad, - rotation_angle=self._rotation_angle, - ) - _cutting_list.append(self._bore_cutter) - - self._tf_inner_leg = paramak.CenterColumnShieldCylinder( - height=self._inner_tf_leg_height, - inner_radius=0, - outer_radius=self._tf_inner_leg_end_rad, - rotation_angle=self._rotation_angle, - name="tf_inner_leg", - cut=_cutting_list, - color=(0.2, 1, 0.2), - ) - - return [self._tf_inner_leg] - - def _make_vacuum_vessel_inner_wall(self): - - self._vacuum_vessel_inner_wall = paramak.CenterColumnShieldCylinder( - height=self._vacuum_vessel_height, - inner_radius=self._vacuum_vessel_inwall_start_rad, - outer_radius=self._vacuum_vessel_inwall_end_rad, - rotation_angle=self._rotation_angle, - name="vessel_inner_wall", - color=(0.5, 0.5, 0.5), - cut=[self._pf_coils, self._pf_casing], - ) - - return [self._vacuum_vessel_inner_wall] - - def _make_inner_shield(self): - - self._inner_shield = paramak.CenterColumnShieldCylinder( - height=self._inner_shield_height, - inner_radius=self._inner_shield_start_rad, - outer_radius=self._inner_shield_end_rad, - rotation_angle=self._rotation_angle, - name="inner_shield", - color=(1.0, 0.7, 0.5), - cut=[self._pf_coils, self._pf_casing], - ) - - return [self._inner_shield] - - def _make_blankets(self): - - # Cutters - - self._divertor_cutter_cutter = paramak.CenterColumnShieldCylinder( - height=self._divertor_start_height * 2, - inner_radius=0, - outer_radius=self._divertor_end_rad + 10, - ) - - self._divertor_cutter = paramak.CenterColumnShieldCylinder( - height=self._inner_tf_leg_height + 10, - inner_radius=self._divertor_start_rad, - outer_radius=self._divertor_end_rad, - cut=[self._divertor_cutter_cutter], - ) - - central_cutter = paramak.CenterColumnShieldCylinder( - height=self._inner_tf_leg_height + 10, # for overlap - inner_radius=0, - outer_radius=self._inner_shield_end_rad, - ) - - # Blanket layers - - self._rear_wall = paramak.BlanketFP( - thickness=self._rear_wall_thickness, - start_angle=0, - stop_angle=360, - plasma=self._make_plasma(), - rotation_angle=self._rotation_angle, - offset_from_plasma=self._inner_wall_thickness + self._blanket_thickness + self._wall_to_plasma_gap, - name="blanket_rear_wall", - cut=[ - central_cutter, - self._divertor_cutter, - self._pf_coils, - self._pf_casing, - ], - color=(0.3, 0.3, 0.3), - ) - - self._breeder_blanket = paramak.BlanketFP( - thickness=self._blanket_thickness, - start_angle=0, - stop_angle=360, - plasma=self._make_plasma(), - rotation_angle=self._rotation_angle, - offset_from_plasma=self._inner_wall_thickness + self._wall_to_plasma_gap, - name="blanket", - cut=[ - central_cutter, - self._divertor_cutter, - self._pf_coils, - self._pf_casing, - ], - color=(0.5, 1.0, 0.5), - ) - - self._inner_wall = paramak.BlanketFP( - thickness=self._inner_wall_thickness, - start_angle=0, - stop_angle=360, - plasma=self._make_plasma(), - rotation_angle=self._rotation_angle, - offset_from_plasma=self._wall_to_plasma_gap, - name="firstwall", - cut=[ - central_cutter, - self._divertor_cutter, - self._pf_coils, - self._pf_casing, - ], - color=(0.3, 0.3, 0.3), - ) - return [self._rear_wall, self._breeder_blanket, self._inner_wall] - - def _make_divertor(self): - - self._divertor_extention_cutter = paramak.BlanketFP( - thickness=-self._wall_to_plasma_gap, - start_angle=180, - stop_angle=-180, - plasma=self._make_plasma(), - rotation_angle=self._rotation_angle, - offset_from_plasma=[ - self._wall_to_plasma_gap, - self._wall_to_plasma_gap, - self._wall_to_plasma_gap, - ], - ) - self._divertor_midplane_cutter = paramak.CenterColumnShieldCylinder( - height=(self._divertor_start_height) * 2, - inner_radius=self._divertor_start_rad, - outer_radius=self._divertor_end_rad, - rotation_angle=self._rotation_angle, - ) - self._divertor = paramak.CenterColumnShieldCylinder( - height=self._divertor_end_height_top * 2, - inner_radius=self._divertor_start_rad, - outer_radius=self._divertor_end_rad, - rotation_angle=self._rotation_angle, - cut=[ - self._divertor_extention_cutter, - self._divertor_midplane_cutter, - self._pf_coils, - self._pf_casing, - ], - color=(1.0, 0.2, 0.2), - name="divertor", - ) - - return [self._divertor] - - def _make_vacuum_vessel(self): - vac_cutter = paramak.CenterColumnShieldCylinder( - height=self._vacuum_vessel_height, - inner_radius=self._vacuum_vessel_inwall_start_rad, - outer_radius=self._vacuum_vessel_body_start_rad, - rotation_angle=self._rotation_angle, - color=(0.5, 0.5, 0.5), - ) - if self._ports_enable: - cutting_list = [vac_cutter, self._pf_coils, self._pf_casing] + self._ports - else: - cutting_list = [vac_cutter, self._pf_coils, self._pf_casing] - self._vacuum_vessel_body = paramak.CenterColumnShieldCylinder( - height=self._vacuum_vessel_height + (self._vacuum_vessel_thickness * 2), - inner_radius=self._vacuum_vessel_inwall_start_rad, - outer_radius=self._vacuum_vessel_body_end_rad, - rotation_angle=self._rotation_angle, - name="vessel_body", - cut=cutting_list, - color=(0.5, 0.5, 0.5), - ) - return [self._vacuum_vessel_body] - - def _make_tf_coils(self): - self._tf_coils = paramak.ToroidalFieldCoilRectangleRoundCorners( - with_inner_leg=False, - lower_inner_coordinates=( - self._inner_bore_stop_rad, - -self._inner_tf_leg_height / 2, - ), - mid_point_coordinates=(self._tf_start_rad, 0), - thickness=self._outer_tf_coil_thickness, - number_of_coils=self._number_of_coils, - distance=self._tf_width, - rotation_angle=self._rotation_angle, - name="tf_coil_outer", - color=(0.2, 1, 0.2), - cut=[self._pf_coils, self._pf_casing], - ) - - return [self._tf_coils] - - # Checks and test - def _port_checks(self): - if ( - len(self._ports_angles) != len(self._port_heights) - or len(self._ports_angles) != len(self._port_side_lengths) - or len(self._port_z_pos) != len(self._port_side_lengths) - or len(self._port_z_pos) != len(self._port_heights) - or len(self._port_z_pos) != len(self._ports_angles) - ): - raise ValueError("Number of elements in Port Parameters don't match!") - _port_coord_list = self._port_side_lengths + self._ports_angles + self._port_heights + self._ports_angles - for cord in _port_coord_list: - if not isinstance(cord, (float, int)): - raise TypeError("Port parameters must be float or integer values!") - - def _pf_checks(self, tuple_bool): - if ( - len(self._pf_coil_heights) != len(self._pf_coil_widths) - or len(self._pf_coil_heights) != len(self._pf_coil_center_points) - or len(self._pf_coil_heights) != len(self._pf_casing_thickness) - or len(self._pf_coil_widths) != len(self._pf_casing_thickness) - or len(self._pf_coil_center_points) != len(self._pf_casing_thickness) - ): - raise ValueError("Number of elements in PF Parameters don't match!") - if not tuple_bool: - _pf_lists = self._pf_coil_heights + self._pf_coil_widths + self._pf_casing_thickness - - for cord in _pf_lists: - if not isinstance(cord, (float, int)): - raise TypeError("PF parameters must be float or integer values! yay") - else: - _pf_lists = ( - self._pf_coil_heights - + self._pf_coil_widths - + self._pf_casing_thickness - + [x[0] for x in self._pf_coil_center_points] - + [x[1] for x in self._pf_coil_center_points] - ) - for cord in _pf_lists: - if not isinstance(cord, (float, int)): - raise TypeError("PF parameters must be float or integer values!") diff --git a/src/paramak/parametric_reactors/segmented_blanket_ball_reactor.py b/src/paramak/parametric_reactors/segmented_blanket_ball_reactor.py deleted file mode 100644 index 887d58209..000000000 --- a/src/paramak/parametric_reactors/segmented_blanket_ball_reactor.py +++ /dev/null @@ -1,119 +0,0 @@ -from typing import List - -import cadquery as cq -import numpy as np -import paramak - - -class SegmentedBlanketBallReactor(paramak.BallReactor): - """Creates geometry for a single ball reactor with a single divertor - including a plasma, cylindrical center column shielding, square toroidal - field coils. There is no inboard breeder blanket on this ball reactor like - most spherical reactors. - - Arguments: - gap_between_blankets (float): the distance between adjacent blanket - segments, - number_of_blanket_segments (int): the number of segments to divide the - blanket up into. This for a full 360 degrees rotation - blanket_fillet_radius (float): the fillet radius to apply to the - interface between the firstwall and th breeder zone. Set to 0 for - no fillet. Defaults to 10.0. - """ - - def __init__( - self, - gap_between_blankets: float = 15.0, - number_of_blanket_segments: int = 12, - blanket_fillet_radius: float = 10.0, - **kwargs - ): - - self.gap_between_blankets = gap_between_blankets - self.number_of_blanket_segments = number_of_blanket_segments - self.blanket_fillet_radius = blanket_fillet_radius - - super().__init__(**kwargs) - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "gap_between_blankets", - "number_of_blanket_segments", - "blanket_fillet_radius", - ] - - @property - def gap_between_blankets(self): - return self._gap_between_blankets - - @gap_between_blankets.setter - def gap_between_blankets(self, value): - """Sets the SegmentedBlanketBallReactor.gap_between_blankets - attribute which controls the horitzonal distance between blanket - segments.""" - if isinstance(value, (float, int)) and value > 0: - self._gap_between_blankets = float(value) - else: - raise ValueError("gap_between_blankets but be a positive value float") - - @property - def number_of_blanket_segments(self): - """Sets the SegmentedBlanketBallReactor.number_of_blanket_segments - attribute which controls the number of blanket segments.""" - return self._number_of_blanket_segments - - @number_of_blanket_segments.setter - def number_of_blanket_segments(self, value): - if isinstance(value, int) and value > 2: - self._number_of_blanket_segments = value - else: - raise ValueError("number_of_blanket_segments but be an int greater than 2") - - def _make_blankets_layers(self): - super()._make_blankets_layers() - azimuth_placement_angles = np.linspace(0, 360, self.number_of_blanket_segments, endpoint=False) - thin_cutter = paramak.BlanketCutterStar( - distance=self.gap_between_blankets, - azimuth_placement_angle=azimuth_placement_angles, - ) - - thick_cutter = paramak.BlanketCutterStar( - distance=self.gap_between_blankets + 2 * self.firstwall_radial_thickness, - azimuth_placement_angle=azimuth_placement_angles, - ) - - self._blanket.cut = [self._center_column_cutter, thick_cutter] - - if self.blanket_fillet_radius != 0: - # tried firstwall start radius here already - x = self.major_radius + 1 - front_face_b = self._blanket.solid.faces(cq.NearestToPointSelector((0, x, 0))) - front_edge_b = front_face_b.edges(cq.NearestToPointSelector((0, x, 0))) - front_edge_length_b = front_edge_b.val().Length() - self._blanket.solid = self._blanket.solid.edges(paramak.EdgeLengthSelector(front_edge_length_b)).fillet( - self.blanket_fillet_radius - ) - self._firstwall.thickness += self.blanket_radial_thickness - self._firstwall.cut = [self._center_column_cutter, thin_cutter, self._blanket] - - # TODO this segfaults at the moment but works as an opperation on the - # reactor after construction in jupyter - # tried different x values and (0, x, 0) - # noticed that it much quicker as a post process so perhaps some - # unwanted looping is happening - # if self.blanket_fillet_radius != 0: - # x = self.major_radius # tried firstwall start radius here already - # front_face = \ - # self._firstwall.solid.faces( - # cq.NearestToPointSelector((x, 0, 0))) - # print('found front face') - # front_edge = front_face.edges( - # cq.NearestToPointSelector((x, 0, 0))) - # print('found front edge') - # front_edge_length = front_edge.val().Length() - # print('found front edge length', front_edge_length) - # self._firstwall.solid = self._firstwall.solid.edges( - # paramak.EdgeLengthSelector(front_edge_length)).fillet(self.blanket_fillet_radius) - # print('finished') - - return [self._firstwall, self._blanket, self._blanket_rear_wall] diff --git a/src/paramak/parametric_reactors/single_null_ball_reactor.py b/src/paramak/parametric_reactors/single_null_ball_reactor.py deleted file mode 100644 index 025ef1ca1..000000000 --- a/src/paramak/parametric_reactors/single_null_ball_reactor.py +++ /dev/null @@ -1,16 +0,0 @@ -import paramak - - -class SingleNullBallReactor(paramak.BallReactor): - """Creates geometry for a single ball reactor with a single divertor - including a plasma, cylindrical center column shielding, square toroidal - field coils. There is no inboard breeder blanket on this ball reactor like - most spherical reactors. - - Arguments: - divertor_position (str): Defaults to "upper". - """ - - def __init__(self, divertor_position: str = "upper", **kwargs): - - super().__init__(divertor_position=divertor_position, **kwargs) diff --git a/src/paramak/parametric_reactors/single_null_submersion_reactor.py b/src/paramak/parametric_reactors/single_null_submersion_reactor.py deleted file mode 100644 index 7a3928270..000000000 --- a/src/paramak/parametric_reactors/single_null_submersion_reactor.py +++ /dev/null @@ -1,17 +0,0 @@ -import paramak - - -class SingleNullSubmersionTokamak(paramak.SubmersionTokamak): - """Creates geometry for a submersion reactor with a single divertor - including a plasma, cylindrical center column shielding, square toroidal - field coils. There is an inboard breeder blanket on this submersion - reactor. - - Arguments: - divertor_position (str): Defaults to "upper". - support_position (str): Defaults to "upper". - """ - - def __init__(self, divertor_position: str = "upper", support_position: str = "upper", **kwargs): - - super().__init__(divertor_position=divertor_position, support_position=support_position, **kwargs) diff --git a/src/paramak/parametric_reactors/sparc_paper_2020.py b/src/paramak/parametric_reactors/sparc_paper_2020.py deleted file mode 100644 index 6e9e7db51..000000000 --- a/src/paramak/parametric_reactors/sparc_paper_2020.py +++ /dev/null @@ -1,409 +0,0 @@ -from typing import List - -import paramak - - -class SparcFrom2020PaperDiagram(paramak.Reactor): - """Creates geometry of a simple SPARC reactor based on the published - diagram in Figure 4 of Overview of the SPARC tokamak. Journal of Plasma - Physics, 86(5), 865860502. doi:10.1017/S0022377820001257. Coordinates - extracted from the figure are not exact and therefore this model does not - perfectly represent the reactor. - - Arguments: - rotation_angle (float): the angle of the sector that is desired. - Defaults to 360.0. - """ - - def __init__( - self, - rotation_angle: float = 180.0, - ): - - super().__init__([]) - - self.rotation_angle = rotation_angle - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "rotation_angle", - ] - - def create_pf_coils(self): - """Creates a 3d solids for each pf coil. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - - """ - - center_points = [ - (53.5, -169.58), - (53.5, -118.43), - (53.5, -46.54), - (53.5, 46.54), - (53.5, 118.43), - (53.5, 169.58), - ] - heights = [ - 41.5, - 40.5, - 82.95, - 82.95, - 40.5, - 41.5, - ] - widths = [27.7, 27.7, 27.7, 27.7, 27.7, 27.7] - - inboard_pf_coils = [] - for counter, (center_point, width, height) in enumerate(zip(center_points, widths, heights), 1): - pf_coil = paramak.PoloidalFieldCoil( - height=height, - width=width, - center_point=center_point, - rotation_angle=self.rotation_angle, - name=f"inboard_pf_coil_{counter}", - ) - inboard_pf_coils.append(pf_coil) - - center_points = [ - (86, 230), - (86, -230), - (164, 241), - (164, -241), - (263, 222), - (263, -222), - (373, 131), - (373, -131), - ] - widths = [ - 32, - 32, - 50, - 50, - 43, - 43, - 48, - 48, - ] - heights = [ - 40, - 40, - 30, - 30, - 28, - 28, - 37, - 37, - ] - outboard_pf_coils = [] - for counter, (center_point, width, height) in enumerate(zip(center_points, widths, heights), 1): - pf_coil = paramak.PoloidalFieldCoil( - height=height, - width=width, - center_point=center_point, - rotation_angle=self.rotation_angle, - name=f"outboard_pf_coil_{counter}", - ) - outboard_pf_coils.append(pf_coil) - - center_points = [ - (207, 144), - (207, 125), - (207, -144), - (207, -125), - ] - widths = [15, 15, 15, 15] - heights = [15, 15, 15, 15] - - div_coils = [] - for counter, (center_point, width, height) in enumerate(zip(center_points, widths, heights), 1): - pf_coil = paramak.PoloidalFieldCoil( - height=height, - width=width, - center_point=center_point, - rotation_angle=self.rotation_angle, - name=f"div_coil_{counter}", - ) - div_coils.append(pf_coil) - - efccu_coils_1 = paramak.RotateStraightShape( - points=[ - (235.56581986143186, -127.64976958525347), - (240.1847575057737, -121.19815668202767), - (246.65127020785218, -125.80645161290323), - (242.0323325635104, -132.25806451612902), - ], - rotation_angle=self.rotation_angle, - name="efccu_coils_1", - ) - - efccu_coils_2 = paramak.RotateStraightShape( - points=[ - (262.3556581986143, -90.78341013824888), - (266.97459584295615, -84.33179723502303), - (273.44110854503464, -88.94009216589859), - (268.82217090069287, -94.47004608294935), - ], - rotation_angle=self.rotation_angle, - name="efccu_coils_2", - ) - - efccu_coils_3 = paramak.RotateStraightShape( - points=[ - (281.7551963048499, -71.42857142857144), - (289.1454965357968, -71.42857142857144), - (289.1454965357968, -78.80184331797238), - (281.7551963048499, -78.80184331797238), - ], - rotation_angle=self.rotation_angle, - name="efccu_coils_3", - ) - - efccu_coils_4 = paramak.RotateStraightShape( - points=[ - (235.56581986143186, 127.64976958525347), - (240.1847575057737, 121.19815668202767), - (246.65127020785218, 125.80645161290323), - (242.0323325635104, 132.25806451612902), - ], - rotation_angle=self.rotation_angle, - name="efccu_coils_4", - ) - - efccu_coils_5 = paramak.RotateStraightShape( - points=[ - (262.3556581986143, 90.78341013824888), - (266.97459584295615, 84.33179723502303), - (273.44110854503464, 88.94009216589859), - (268.82217090069287, 94.47004608294935), - ], - rotation_angle=self.rotation_angle, - name="efccu_coils_5", - ) - - efccu_coils_6 = paramak.RotateStraightShape( - points=[ - (281.7551963048499, 71.42857142857144), - (289.1454965357968, 71.42857142857144), - (289.1454965357968, 78.80184331797238), - (281.7551963048499, 78.80184331797238), - ], - rotation_angle=self.rotation_angle, - name="efccu_coils_6", - ) - - # these are cut away from the vessel components - center_points = [ - (240, 70), - (240, -70), - ] - widths = [10, 10] - heights = [10, 10] - - vs_coils = [] - for counter, (center_point, width, height) in enumerate(zip(center_points, widths, heights), 1): - pf_coil = paramak.PoloidalFieldCoil( - height=height, - width=width, - center_point=center_point, - rotation_angle=self.rotation_angle, - name=f"vs_coil_{counter}", - ) - vs_coils.append(pf_coil) - - return ( - vs_coils - + inboard_pf_coils - + outboard_pf_coils - + div_coils - + [ - efccu_coils_1, - efccu_coils_2, - efccu_coils_3, - efccu_coils_4, - efccu_coils_5, - efccu_coils_6, - ] - ) - - def create_tf_coils(self): - """Creates a 3d solids for each tf coil. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - - """ - - tf_coil = paramak.ToroidalFieldCoilPrincetonD( - R1=72, - R2=339, - thickness=33, - distance=33, - number_of_coils=12, - rotation_angle=self.rotation_angle, - name="tf_coil", - ) - - return [tf_coil] - - def create_vessel_components(self, vs_coils): - """Creates a 3d solids for each vessel component. - - Args: - vs_coils (Paramak.Shape): The vs coils that are used in a - Boolean cut with the inner vessel. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - - - """ - - antenna = paramak.RotateMixedShape( - points=[ - (263.2794457274827, 46.5437788018433, "straight"), - (263.2794457274827, -46.54377880184336, "straight"), - (231.87066974595842, -46.54377880184336, "spline"), - (243.87990762124713, 0, "spline"), - (231.87066974595842, 46.5437788018433, "straight"), - ], - rotation_angle=self.rotation_angle, - name="antenna", - ) - - vac_vessel = paramak.RotateStraightShape( - points=[ - (117.32101616628177, 126.72811059907835), - (163.51039260969978, 170.04608294930875), - (181.98614318706697, 171.88940092165896), - (196.76674364896073, 169.12442396313364), - (196.76674364896073, 115.66820276497694), - (236.4896073903002, 114.74654377880185), - (273.44110854503464, 65.89861751152074), - (272.51732101616625, -65.89861751152074), - (236.4896073903002, -115.66820276497697), - (196.76674364896073, -115.66820276497697), - (196.76674364896073, -169.12442396313367), - (181.98614318706697, -172.81105990783408), - (163.51039260969978, -170.04608294930875), - (117.32101616628177, -126.72811059907832), - (117.32101616628177, 123.04147465437785), - (123.78752886836028, 123.04147465437785), - (123.78752886836028, -123.963133640553), - (165.3579676674365, -162.67281105990781), - (181.98614318706697, -164.5161290322581), - (190.3002309468822, -162.67281105990781), - (190.3002309468822, -112.90322580645159), - (193.99538106235568, -109.21658986175117), - (232.7944572748268, -109.21658986175117), - (266.97459584295615, -63.13364055299536), - (266.05080831408776, 62.21198156682027), - (232.7944572748268, 109.21658986175115), - (193.99538106235568, 109.21658986175115), - (190.3002309468822, 111.98156682027647), - (190.3002309468822, 162.67281105990784), - (181.98614318706697, 164.51612903225805), - (165.3579676674365, 162.67281105990784), - (123.78752886836028, 123.04147465437785), - (117.32101616628177, 123.04147465437785), - ], - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 1.0), - name="vessel", - ) - - inner_vessel = paramak.RotateMixedShape( - points=[ - (269.7459584295612, -46.54377880184336, "straight"), - (231.87066974595842, -46.5437788018433, "spline"), - (223.55658198614316, -62.21198156682027, "spline"), - (207.85219399538107, -80.64516129032262, "spline"), - (166.28175519630486, -115.66820276497697, "spline"), - (164.43418013856814, -119.35483870967744, "spline"), - (164.43418013856814, -122.11981566820276, "straight"), - (173.67205542725173, -140.5529953917051, "straight"), - (184.75750577367205, -140.5529953917051, "straight"), - (184.75750577367205, -158.98617511520735, "straight"), - (181.98614318706697, -159.9078341013825, "straight"), - (147.80600461893764, -118.43317972350235, "straight"), - (129.33025404157044, -123.04147465437785, "straight"), - (145.95842956120094, -111.05990783410135, "straight"), - (126.55889145496536, -50.23041474654377, "straight"), - (127.48267898383372, 50.23041474654377, "straight"), - (145.95842956120094, 110.13824884792626, "straight"), - (128.40646651270208, 123.04147465437785, "straight"), - (147.80600461893764, 117.51152073732717, "straight"), - (181.98614318706697, 159.90783410138246, "straight"), - (185.6812933025404, 158.98617511520735, "straight"), - (184.75750577367205, 140.55299539170505, "straight"), - (172.74826789838338, 140.55299539170505, "spline"), - (164.43418013856814, 121.19815668202764, "spline"), - (164.43418013856814, 118.43317972350229, "spline"), - (165.3579676674365, 115.66820276497694, "spline"), - (173.67205542725173, 111.05990783410135, "spline"), - (207.85219399538107, 80.64516129032256, "spline"), - (220.7852193995381, 66.82027649769586, "spline"), - (231.87066974595842, 46.5437788018433, "spline"), - (268.82217090069287, 46.5437788018433, "straight"), - (268.82217090069287, 63.13364055299536, "straight"), - (233.71824480369514, 111.98156682027647, "straight"), - (193.99538106235568, 112.90322580645159, "straight"), - (192.14780600461893, 164.51612903225805, "straight"), - (163.51039260969978, 166.35944700460828, "straight"), - (121.93995381062356, 123.96313364055297, "straight"), - (121.0161662817552, -125.80645161290323, "straight"), - (163.51039260969978, -166.35944700460834, "straight"), - (192.14780600461893, -166.35944700460834, "straight"), - (193.99538106235568, -112.90322580645159, "straight"), - (234.64203233256353, -111.9815668202765, "straight"), - (269.7459584295612, -63.13364055299536, "straight"), - ], - rotation_angle=self.rotation_angle, - cut=[vac_vessel, antenna] + vs_coils, - color=(0.0, 1.0, 0.498), - name="inner_vessel", - ) - - return [antenna, vac_vessel, inner_vessel] - - def create_plasma(self): - """Creates a 3d solids for the plasma. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - - """ - - # The minor radius in the paper is specified as 57 - # a small ofset is needed to avoid overlaps - minor_radius = 57 - 6 - - plasma = paramak.Plasma( - major_radius=185, - minor_radius=minor_radius, - triangularity=0.31, - elongation=1.97, - rotation_angle=self.rotation_angle, - ) - - return [plasma] - - def create_solids(self): - """Creates a 3d solids for each component. - - Returns: - A list of CadQuery solids: A list of 3D solid volumes - - """ - - plasma = self.create_plasma() - pf_coils = self.create_pf_coils() - tf_coils = self.create_tf_coils() - vessel = self.create_vessel_components([pf_coils[0], pf_coils[1]]) - - all_shapes_and_components = plasma + pf_coils + tf_coils + vessel - - self.shapes_and_components = all_shapes_and_components - - return all_shapes_and_components diff --git a/src/paramak/parametric_reactors/submersion_reactor.py b/src/paramak/parametric_reactors/submersion_reactor.py deleted file mode 100644 index 5c6144396..000000000 --- a/src/paramak/parametric_reactors/submersion_reactor.py +++ /dev/null @@ -1,703 +0,0 @@ -import warnings -from typing import List, Optional - -import cadquery as cq - -import paramak - - -class SubmersionTokamak(paramak.Reactor): - """Creates geometry for a simple submersion reactor including a plasma, - cylindrical center column shielding, inboard and outboard breeder blanket, - divertor (upper and lower), support legs. Optional coat hanger shaped - toroidal field coils and pf coils. - - Arguments: - inner_bore_radial_thickness: the radial thickness of the inner bore - (cm) - inboard_tf_leg_radial_thickness: the radial thickness of the inner leg - of the toroidal field coils (cm) - center_column_shield_radial_thickness: the radial thickness of the - center column shield (cm) - inboard_blanket_radial_thickness: the radial thickness of the inboard - blanket (cm) - firstwall_radial_thickness: the radial thickness of the first wall (cm) - inner_plasma_gap_radial_thickness: the radial thickness of the inboard - gap between the plasma and the center column shield (cm) - plasma_radial_thickness: the radial thickness of the plasma (cm) - divertor_radial_thickness: the radial thickness of the divertors (cm) - support_radial_thickness: the radial thickness of the upper and lower - supports (cm) - outer_plasma_gap_radial_thickness: the radial thickness of the outboard - gap between the plasma and the first wall (cm) - outboard_blanket_radial_thickness: the radial thickness of the blanket - (cm) - blanket_rear_wall_radial_thickness: the radial thickness of the rear - wall of the blanket (cm) - elongation: the elongation of the plasma - triangularity: the triangularity of the plasma - number_of_tf_coils: the number of tf coils. - rotation_angle: the angle of the sector that is desired. - outboard_tf_coil_radial_thickness: the radial thickness of the toroidal - field coil. - rear_blanket_to_tf_gap: the radial distance between the rear of the - blanket and the toroidal field coil. - outboard_tf_coil_poloidal_thickness: the vertical thickness of each - poloidal field coil. - pf_coil_vertical_thicknesses: the vertical thickness of each poloidal - field coil. - pf_coil_radial_thicknesses: the radial thickness of each poloidal - field coil. - divertor_position: the position of the divertor, "upper", "lower" or - "both". Defaults to "both". - support_position: the position of the supports, "upper", "lower" or - "both". Defaults to "both". - """ - - def __init__( - self, - inner_bore_radial_thickness: float = 30.0, - inboard_tf_leg_radial_thickness: float = 30, - center_column_shield_radial_thickness: float = 30, - inboard_blanket_radial_thickness: float = 80, - firstwall_radial_thickness: float = 20, - inner_plasma_gap_radial_thickness: float = 50, - plasma_radial_thickness: float = 200, - divertor_radial_thickness: float = 80, - support_radial_thickness: float = 90, - outer_plasma_gap_radial_thickness: float = 50, - outboard_blanket_radial_thickness: float = 30, - blanket_rear_wall_radial_thickness: float = 30, - elongation: float = 2.0, - triangularity: float = 0.5, - number_of_tf_coils: int = 16, - rotation_angle: float = 180.0, - outboard_tf_coil_radial_thickness: Optional[float] = None, - rear_blanket_to_tf_gap: Optional[float] = None, - outboard_tf_coil_poloidal_thickness: Optional[float] = None, - pf_coil_radial_thicknesses: List[float] = [], - pf_coil_vertical_thicknesses: List[float] = [], - pf_coil_radial_position: List[float] = [], - pf_coil_vertical_position: List[float] = [], - pf_coil_case_thicknesses: List[float] = [], - divertor_position: Optional[str] = "both", - support_position: Optional[str] = "both", - ): - - super().__init__([]) - - self.inner_bore_radial_thickness = inner_bore_radial_thickness - self.inboard_tf_leg_radial_thickness = inboard_tf_leg_radial_thickness - self.center_column_shield_radial_thickness = center_column_shield_radial_thickness - self.inboard_blanket_radial_thickness = inboard_blanket_radial_thickness - self.firstwall_radial_thickness = firstwall_radial_thickness - self.inner_plasma_gap_radial_thickness = inner_plasma_gap_radial_thickness - self.plasma_radial_thickness = plasma_radial_thickness - self.outer_plasma_gap_radial_thickness = outer_plasma_gap_radial_thickness - self.outboard_blanket_radial_thickness = outboard_blanket_radial_thickness - self.blanket_rear_wall_radial_thickness = blanket_rear_wall_radial_thickness - self.pf_coil_radial_thicknesses = pf_coil_radial_thicknesses - self.outboard_tf_coil_radial_thickness = outboard_tf_coil_radial_thickness - self.outboard_tf_coil_poloidal_thickness = outboard_tf_coil_poloidal_thickness - self.divertor_radial_thickness = divertor_radial_thickness - self.support_radial_thickness = support_radial_thickness - self.elongation = elongation - self.triangularity = triangularity - self.rear_blanket_to_tf_gap = rear_blanket_to_tf_gap - self.pf_coil_vertical_thicknesses = pf_coil_vertical_thicknesses - self.pf_coil_case_thicknesses = pf_coil_case_thicknesses - self.number_of_tf_coils = number_of_tf_coils - self.rotation_angle = rotation_angle - self.divertor_position = divertor_position - self.support_position = support_position - self.pf_coil_vertical_position = pf_coil_vertical_position - self.pf_coil_radial_position = pf_coil_radial_position - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "inner_bore_radial_thickness", - "inboard_tf_leg_radial_thickness", - "center_column_shield_radial_thickness", - "inboard_blanket_radial_thickness", - "firstwall_radial_thickness", - "inner_plasma_gap_radial_thickness", - "plasma_radial_thickness", - "divertor_radial_thickness", - "support_radial_thickness", - "outer_plasma_gap_radial_thickness", - "outboard_blanket_radial_thickness", - "blanket_rear_wall_radial_thickness", - "elongation", - "triangularity", - "number_of_tf_coils", - "rotation_angle", - "outboard_tf_coil_radial_thickness", - "rear_blanket_to_tf_gap", - "outboard_tf_coil_poloidal_thickness", - "pf_coil_vertical_thicknesses", - "pf_coil_radial_thicknesses", - "pf_coil_radial_position", - "pf_coil_vertical_position", - "pf_coil_case_thicknesses", - "divertor_position", - "support_position", - ] - - # set by make_plasma - self.major_radius = None - self.minor_radius = None - - # set during geometry creation - self._pf_coils = None - self._pf_coils_casing = None - self._divertor_lower = None - self._divertor_upper = None - - @property - def pf_coil_radial_position(self): - return self._pf_coil_radial_position - - @pf_coil_radial_position.setter - def pf_coil_radial_position(self, value): - if not isinstance(value, list) and value is not None: - raise ValueError("pf_coil_radial_position must be a list") - self._pf_coil_radial_position = value - - @property - def pf_coil_radial_thicknesses(self): - return self._pf_coil_radial_thicknesses - - @pf_coil_radial_thicknesses.setter - def pf_coil_radial_thicknesses(self, value): - if not isinstance(value, list) and value is not None: - raise ValueError("pf_coil_radial_thicknesses must be a list") - self._pf_coil_radial_thicknesses = value - - @property - def pf_coil_vertical_thicknesses(self): - return self._pf_coil_vertical_thicknesses - - @pf_coil_vertical_thicknesses.setter - def pf_coil_vertical_thicknesses(self, value): - if not isinstance(value, list) and value is not None: - raise ValueError("pf_coil_vertical_thicknesses must be a list") - self._pf_coil_vertical_thicknesses = value - - @property - def divertor_position(self): - return self._divertor_position - - @divertor_position.setter - def divertor_position(self, value): - acceptable_values = ["upper", "lower", "both"] - if value in acceptable_values: - self._divertor_position = value - else: - msg = "divertor_position must be 'upper', 'lower' or 'both'" - raise ValueError(msg) - - @property - def support_position(self): - return self._support_position - - @support_position.setter - def support_position(self, value): - acceptable_values = ["upper", "lower", "both"] - if value in acceptable_values: - self._support_position = value - else: - msg = "support_position must be 'upper', 'lower' or 'both'" - raise ValueError(msg) - - def create_solids(self): - """Creates a list of paramak.Shape for components and saves it in - self.shapes_and_components - """ - - uncut_shapes = [] - - self._rotation_angle_check() - uncut_shapes.append(self._make_plasma()) - self._make_radial_build() - self._make_vertical_build() - uncut_shapes.append(self._make_center_column_shield()) - uncut_shapes.append(self._make_firstwall()) - uncut_shapes.append(self._make_blanket()) - uncut_shapes += self._make_divertor() - uncut_shapes.append(self._make_supports()) - uncut_shapes.append(self._make_rear_blanket_wall()) - uncut_shapes += self._make_tf_coils() - pf_coils = self._make_pf_coils() - - if pf_coils is None: - shapes_and_components = uncut_shapes - else: - for shape in uncut_shapes: - print(shape, shape.name) - for pf_coil in pf_coils: - shape.solid = shape.solid.cut(pf_coil.solid) - shapes_and_components = pf_coils + uncut_shapes - - self.shapes_and_components = shapes_and_components - - def _rotation_angle_check(self): - - if self.rotation_angle == 360: - msg = "360 degree rotation may result" + " in a Standard_ConstructionError or AttributeError" - warnings.warn(msg, UserWarning) - - def _make_radial_build(self): - - # this is the radial build sequence, where one component stops and - # another starts - - self._inner_bore_start_radius = 0 - self._inner_bore_end_radius = self._inner_bore_start_radius + self.inner_bore_radial_thickness - - self._inboard_tf_coils_start_radius = self._inner_bore_end_radius - self._inboard_tf_coils_end_radius = self._inboard_tf_coils_start_radius + self.inboard_tf_leg_radial_thickness - - self._center_column_shield_start_radius = self._inboard_tf_coils_end_radius - self._center_column_shield_end_radius = ( - self._center_column_shield_start_radius + self.center_column_shield_radial_thickness - ) - - self._inboard_blanket_start_radius = self._center_column_shield_end_radius - self._inboard_blanket_end_radius = self._inboard_blanket_start_radius + self.inboard_blanket_radial_thickness - - self._inboard_firstwall_start_radius = self._inboard_blanket_end_radius - self._inboard_firstwall_end_radius = self._inboard_firstwall_start_radius + self.firstwall_radial_thickness - - self._inner_plasma_gap_start_radius = self._inboard_firstwall_end_radius - self._inner_plasma_gap_end_radius = self._inner_plasma_gap_start_radius + self.inner_plasma_gap_radial_thickness - - self._plasma_start_radius = self._inner_plasma_gap_end_radius - self._plasma_end_radius = self._plasma_start_radius + self.plasma_radial_thickness - - self._outer_plasma_gap_start_radius = self._plasma_end_radius - self._outer_plasma_gap_end_radius = self._outer_plasma_gap_start_radius + self.outer_plasma_gap_radial_thickness - - self._outboard_firstwall_start_radius = self._outer_plasma_gap_end_radius - self._outboard_firstwall_end_radius = self._outboard_firstwall_start_radius + self.firstwall_radial_thickness - - self._outboard_blanket_start_radius = self._outboard_firstwall_end_radius - self._outboard_blanket_end_radius = self._outboard_blanket_start_radius + self.outboard_blanket_radial_thickness - - self._blanket_rear_wall_start_radius = self._outboard_blanket_end_radius - self._blanket_rear_wall_end_radius = ( - self._blanket_rear_wall_start_radius + self.blanket_rear_wall_radial_thickness - ) - - self._tf_info_provided = False - if ( - self.outboard_tf_coil_radial_thickness is not None - and self.rear_blanket_to_tf_gap is not None - and self.outboard_tf_coil_poloidal_thickness is not None - ): - self._tf_info_provided = True - self._outboard_tf_coil_start_radius = self._blanket_rear_wall_end_radius + self.rear_blanket_to_tf_gap - self._outboard_tf_coil_end_radius = ( - self._outboard_tf_coil_start_radius + self.outboard_tf_coil_radial_thickness - ) - - self._divertor_start_radius = self._plasma.high_point[0] - 0.5 * self.divertor_radial_thickness - self._divertor_end_radius = self._plasma.high_point[0] + 0.5 * self.divertor_radial_thickness - - self._support_start_radius = self._plasma.high_point[0] - 0.5 * self.support_radial_thickness - self._support_end_radius = self._plasma.high_point[0] + 0.5 * self.support_radial_thickness - - def _make_vertical_build(self): - - # this is the vertical build sequence, componets build on each other in - # a similar manner to the radial build - - self._plasma_start_height = 0 - self._plasma_end_height = self._plasma.high_point[1] - - self._plasma_to_divertor_gap_start_height = self._plasma_end_height - self._plasma_to_divertor_gap_end_height = ( - self._plasma_to_divertor_gap_start_height + self.outer_plasma_gap_radial_thickness - ) - - # the firstwall is cut by the divertor but uses the same control points - self._firstwall_start_height = self._plasma_to_divertor_gap_end_height - self._firstwall_end_height = self._firstwall_start_height + self.firstwall_radial_thickness - - self._blanket_start_height = self._firstwall_end_height - self._blanket_end_height = self._blanket_start_height + self.outboard_blanket_radial_thickness - - self._blanket_rear_wall_start_height = self._blanket_end_height - self._blanket_rear_wall_end_height = ( - self._blanket_rear_wall_start_height + self.blanket_rear_wall_radial_thickness - ) - - if self._tf_info_provided: - self._outboard_tf_coils_vertical_height = self._blanket_rear_wall_end_height * 1.5 - self._outboard_tf_coils_horizontal_length = self._blanket_rear_wall_end_radius * 0.75 - - def _make_center_column_shield(self): - - self._center_column_shield = paramak.CenterColumnShieldCylinder( - height=self._blanket_rear_wall_end_height * 2, - inner_radius=self._center_column_shield_start_radius, - outer_radius=self._center_column_shield_end_radius, - rotation_angle=self.rotation_angle, - name="center_column_shield", - ) - return self._center_column_shield - - def _make_plasma(self): - - # sets major radius and minor radius from equatorial_points to allow a - # radial build this helps avoid the plasma overlapping the center - # column and other components - inner_equatorial_point = ( - self.inner_bore_radial_thickness - + self.inboard_tf_leg_radial_thickness - + self.center_column_shield_radial_thickness - + self.inboard_blanket_radial_thickness - + self.firstwall_radial_thickness - + self.inner_plasma_gap_radial_thickness - ) - outer_equatorial_point = inner_equatorial_point + self.plasma_radial_thickness - self.major_radius = (outer_equatorial_point + inner_equatorial_point) / 2 - self.minor_radius = self.major_radius - inner_equatorial_point - - plasma = paramak.Plasma( - major_radius=self.major_radius, - minor_radius=self.minor_radius, - elongation=self.elongation, - triangularity=self.triangularity, - rotation_angle=self.rotation_angle, - ) - - self._plasma = plasma - return self._plasma - - def _make_firstwall(self): - - # this is used to cut the inboard blanket and then fused / unioned with - # the firstwall - self._inboard_firstwall = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.inner_plasma_gap_radial_thickness, - start_angle=90, - stop_angle=270, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - ) - - self._firstwall = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.outer_plasma_gap_radial_thickness, - start_angle=90, - stop_angle=-90, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, - name="outboard_firstwall", - union=self._inboard_firstwall, - color=(0.5, 0.5, 0.5), - ) - return self._firstwall - - def _make_divertor(self): - fw_envelope_inboard = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.inner_plasma_gap_radial_thickness, - start_angle=90, - stop_angle=270, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, - ) - - fw_envelope = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.outer_plasma_gap_radial_thickness, - start_angle=90, - stop_angle=-90, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, - name="outboard_firstwall", - union=fw_envelope_inboard, - ) - divertor_height = self._blanket_rear_wall_end_height - - divertor_height_top = divertor_height - divertor_height_bottom = -divertor_height - - if self.divertor_position in ["lower", "both"]: - self._divertor_lower = paramak.RotateStraightShape( - points=[ - (self._divertor_start_radius, divertor_height_bottom), - (self._divertor_end_radius, divertor_height_bottom), - (self._divertor_end_radius, 0), - (self._divertor_start_radius, 0), - ], - intersect=fw_envelope, - name="divertor_lower", - color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, - ) - if self.divertor_position in ["upper", "both"]: - self._divertor_upper = paramak.RotateStraightShape( - points=[ - (self._divertor_start_radius, 0), - (self._divertor_end_radius, 0), - (self._divertor_end_radius, divertor_height_top), - (self._divertor_start_radius, divertor_height_top), - ], - intersect=fw_envelope, - name="divertor_upper", - color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, - ) - - if self.divertor_position == "upper": - cut_list = [self._divertor_upper] - if self.divertor_position == "lower": - cut_list = [self._divertor_lower] - if self.divertor_position == "both": - cut_list = [self._divertor_lower, self._divertor_upper] - self._firstwall.cut = cut_list - self._inboard_firstwall.cut = cut_list - - if self.divertor_position == "upper": - return [self._divertor_upper] - if self.divertor_position == "lower": - return [self._divertor_lower] - if self.divertor_position == "both": - return [self._divertor_upper, self._divertor_lower] - - def _make_blanket(self): - self._inboard_blanket = paramak.CenterColumnShieldCylinder( - height=self._blanket_end_height * 2, - inner_radius=self._inboard_blanket_start_radius, - outer_radius=max(self._inboard_firstwall.points)[0], - rotation_angle=self.rotation_angle, - cut=self._inboard_firstwall, - ) - - # this takes a single solid from a compound of solids by finding the - # solid nearest to a point - # TODO: find alternative - self._inboard_blanket.solid = self._inboard_blanket.solid.solids(cq.selectors.NearestToPointSelector((0, 0, 0))) - - # this is the outboard fused /unioned with the inboard blanket - - self._blanket = paramak.BlanketFP( - plasma=self._plasma, - start_angle=90, - stop_angle=-90, - offset_from_plasma=self.outer_plasma_gap_radial_thickness + self.firstwall_radial_thickness, - thickness=self.outboard_blanket_radial_thickness, - rotation_angle=self.rotation_angle, - name="blanket", - color=(0.0, 1.0, 0.498), - union=self._inboard_blanket, - ) - return self._blanket - - def _make_supports(self): - blanket_envelope = paramak.BlanketFP( - plasma=self._plasma, - start_angle=90, - stop_angle=-90, - offset_from_plasma=self.outer_plasma_gap_radial_thickness + self.firstwall_radial_thickness, - thickness=self.outboard_blanket_radial_thickness, - rotation_angle=self.rotation_angle, - union=self._inboard_blanket, - ) - support_height = self._blanket_rear_wall_end_height - support_height_top = support_height - support_height_bottom = -support_height - - if self.support_position == "lower": - support_height_top = 0 - elif self.support_position == "upper": - support_height_bottom = 0 - - self._supports = paramak.RotateStraightShape( - points=[ - (self._support_start_radius, support_height_bottom), - (self._support_end_radius, support_height_bottom), - (self._support_end_radius, support_height_top), - (self._support_start_radius, support_height_top), - ], - rotation_angle=self.rotation_angle, - name="supports", - color=(0.0, 0.0, 0.0), - intersect=blanket_envelope, - ) - - self._blanket.solid = self._blanket.solid.cut(self._supports.solid) - - return self._supports - - def _make_rear_blanket_wall(self): - self._outboard_rear_blanket_wall_upper = paramak.RotateStraightShape( - points=[ - ( - self._center_column_shield_end_radius, - self._blanket_rear_wall_start_height, - ), - ( - self._center_column_shield_end_radius, - self._blanket_rear_wall_end_height, - ), - ( - max(self._inboard_firstwall.points)[0], - self._blanket_rear_wall_end_height, - ), - ( - max(self._inboard_firstwall.points)[0], - self._blanket_rear_wall_start_height, - ), - ], - rotation_angle=self.rotation_angle, - ) - - self._outboard_rear_blanket_wall_lower = paramak.RotateStraightShape( - points=[ - ( - self._center_column_shield_end_radius, - -self._blanket_rear_wall_start_height, - ), - ( - self._center_column_shield_end_radius, - -self._blanket_rear_wall_end_height, - ), - ( - max(self._inboard_firstwall.points)[0], - -self._blanket_rear_wall_end_height, - ), - ( - max(self._inboard_firstwall.points)[0], - -self._blanket_rear_wall_start_height, - ), - ], - rotation_angle=self.rotation_angle, - ) - - self._outboard_rear_blanket_wall = paramak.BlanketFP( - plasma=self._plasma, - start_angle=90, - stop_angle=-90, - offset_from_plasma=self.outer_plasma_gap_radial_thickness - + self.firstwall_radial_thickness - + self.outboard_blanket_radial_thickness, - thickness=self.blanket_rear_wall_radial_thickness, - rotation_angle=self.rotation_angle, - name="outboard_rear_blanket_wall", - color=(0.0, 1.0, 1.0), - union=[ - self._outboard_rear_blanket_wall_upper, - self._outboard_rear_blanket_wall_lower, - ], - ) - - return self._outboard_rear_blanket_wall - - def _make_pf_coils(self): - - pf_input_lists = [ - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, - self.pf_coil_vertical_position, - self.pf_coil_radial_position, - ] - - # checks if lists are all the same length - if all(len(input_list) == len(pf_input_lists[0]) for input_list in pf_input_lists): - number_of_pf_coils = len(pf_input_lists[0]) - if number_of_pf_coils == 0: - return None - - center_points = [(x, y) for x, y in zip(self.pf_coil_radial_position, self.pf_coil_vertical_position)] - - self._pf_coils = [] - for counter, (center_point, pf_coil_vertical_thickness, pf_coil_radial_thickness,) in enumerate( - zip( - center_points, - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, - ), - 1, - ): - pf_coil = paramak.PoloidalFieldCoil( - height=pf_coil_vertical_thickness, - width=pf_coil_radial_thickness, - center_point=center_point, - rotation_angle=self.rotation_angle, - name=f"pf_coil_{counter}", - ) - self._pf_coils.append(pf_coil) - - if self.pf_coil_case_thicknesses == []: - return self._pf_coils - - self._pf_coils_casing = [] - if len(self.pf_coil_case_thicknesses) == number_of_pf_coils: - for counter, (pf_coil_case_thickness, pf_coil) in enumerate( - zip(self.pf_coil_case_thicknesses, self._pf_coils), 1 - ): - pf_coils_casing = paramak.PoloidalFieldCoilCaseFC( - pf_coil=pf_coil, - casing_thickness=pf_coil_case_thickness, - rotation_angle=self.rotation_angle, - name=f"pf_coil_case_{counter}", - ) - self._pf_coils_casing.append(pf_coils_casing) - else: - raise ValueError( - "pf_coil_case_thicknesses is not the same length as the other " - "PF coil inputs (pf_coil_vertical_thicknesses, " - "pf_coil_radial_thicknesses, pf_coil_radial_position, " - "pf_coil_vertical_position) so can not make pf coils cases" - ) - - return self._pf_coils + self._pf_coils_casing - - def _make_tf_coils(self): - list_of_components = [] - - self._inboard_tf_coils = paramak.CenterColumnShieldCylinder( - height=self._blanket_rear_wall_end_height * 2, - inner_radius=self._inboard_tf_coils_start_radius, - outer_radius=self._inboard_tf_coils_end_radius, - rotation_angle=self.rotation_angle, - name="inboard_tf_coils", - color=(0, 0, 1), - ) - list_of_components.append(self._inboard_tf_coils) - - if ( - None - not in [ - self.rear_blanket_to_tf_gap, - self.outboard_tf_coil_radial_thickness, - self.outboard_tf_coil_poloidal_thickness, - self.number_of_tf_coils, - ] - and self.number_of_tf_coils > 1 - ): - - if self._tf_info_provided: - self._tf_coil = paramak.ToroidalFieldCoilCoatHanger( - with_inner_leg=False, - horizontal_start_point=( - self._inboard_tf_coils_start_radius, - self._blanket_rear_wall_end_height, - ), - vertical_mid_point=(self._outboard_tf_coil_start_radius, 0), - thickness=self.outboard_tf_coil_radial_thickness, - number_of_coils=self.number_of_tf_coils, - distance=self.outboard_tf_coil_poloidal_thickness, - rotation_angle=self.rotation_angle, - horizontal_length=self._outboard_tf_coils_horizontal_length, - vertical_length=self._outboard_tf_coils_vertical_height, - name="tf_coils", - ) - list_of_components.append(self._tf_coil) - - return list_of_components diff --git a/src/paramak/parametric_shapes/__init__.py b/src/paramak/parametric_shapes/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/paramak/parametric_shapes/extruded_circle_shape.py b/src/paramak/parametric_shapes/extruded_circle_shape.py deleted file mode 100644 index 365bdc810..000000000 --- a/src/paramak/parametric_shapes/extruded_circle_shape.py +++ /dev/null @@ -1,127 +0,0 @@ -from typing import Optional, Tuple - -from cadquery import Workplane - -from paramak import Shape -from paramak.utils import calculate_wedge_cut, patch_workplane - -patch_workplane() - - -class ExtrudeCircleShape(Shape): - """Extrudes a circular 3d CadQuery solid from a central point and a radius - - Args: - distance: the extrusion distance to use - radius: radius of the shape. - extrusion_start_offset: - rotation_angle: rotation_angle of solid created. a cut is performed - from rotation_angle to 360 degrees. Defaults to 360. - extrude_both: if set to True, the extrusion will occur in both - directions. Defaults to True. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - distance: float, - radius: float, - extrusion_start_offset: float = 0.0, - rotation_angle: float = 360, - extrude_both: bool = True, - color: Tuple[float, float, float, Optional[float]] = ( - 0.984, - 0.603, - 0.6, - ), - name: str = "extrudecircleshape", - translate: Optional[Tuple[float, float, float]] = None, - **kwargs - ): - - super().__init__(color=color, name=name, **kwargs) - - self.distance = distance - self.radius = radius - self.extrusion_start_offset = extrusion_start_offset - self.rotation_angle = rotation_angle - self.extrude_both = extrude_both - self.color = color - self.name = name - self.translate = translate - - @property - def radius(self): - return self._radius - - @radius.setter - def radius(self, value): - self._radius = value - - @property - def distance(self): - return self._distance - - @distance.setter - def distance(self, value): - self._distance = value - - @property - def rotation_angle(self): - return self._rotation_angle - - @rotation_angle.setter - def rotation_angle(self, value): - self._rotation_angle = value - - @property - def extrusion_start_offset(self): - return self._extrusion_start_offset - - @extrusion_start_offset.setter - def extrusion_start_offset(self, value): - self._extrusion_start_offset = value - - def create_solid(self): - """Creates a extruded 3d solid using points with circular edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - # so a positive offset moves extrusion further from axis of azimuthal - # placement rotation - extrusion_offset = -self.extrusion_start_offset - - if not self.extrude_both: - extrusion_distance = -self.distance - else: - extrusion_distance = -self.distance / 2.0 - - wire = ( - Workplane(self.workplane) - .workplane(offset=extrusion_offset) - .moveTo(self.points[0][0], self.points[0][1]) - .circle(self.radius) - ) - - self.wire = wire - - solid = wire.extrude(until=extrusion_distance, both=self.extrude_both) - - solid = self.rotate_solid(solid) - cutting_wedge = calculate_wedge_cut(self) - solid = self.perform_boolean_operations(solid, wedge_cut=cutting_wedge) - - if self.translate: - solid = solid.translate(self.translate) - - self.solid = solid - - return solid diff --git a/src/paramak/parametric_shapes/extruded_mixed_shape.py b/src/paramak/parametric_shapes/extruded_mixed_shape.py deleted file mode 100644 index 48ec83958..000000000 --- a/src/paramak/parametric_shapes/extruded_mixed_shape.py +++ /dev/null @@ -1,113 +0,0 @@ -from typing import Optional, Tuple - -from paramak import Shape -from paramak.utils import calculate_wedge_cut, patch_workplane - -patch_workplane() - - -class ExtrudeMixedShape(Shape): - """Extrudes a 3d CadQuery solid from points connected with a mixture of - straight and spline connections. - - Args: - distance: the extrusion distance to use - extrude_both: If set to True, the extrusion will occur in both - directions. Defaults to True. - rotation_angle: rotation angle of solid created. A cut is performed - from rotation_angle to 360 degrees. Defaults to 360.0. - extrusion_start_offset: - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - distance: float, - extrude_both: bool = True, - rotation_angle: float = 360.0, - extrusion_start_offset: float = 0.0, - color: Tuple[float, float, float, Optional[float]] = ( - 0.2, - 0.627, - 0.172, - ), - name: str = "extrudemixedshape", - translate: Optional[Tuple[float, float, float]] = None, - **kwargs - ): - - super().__init__(color=color, name=name, **kwargs) - self.distance = distance - self.extrude_both = extrude_both - self.rotation_angle = rotation_angle - self.extrusion_start_offset = extrusion_start_offset - self.color = color - self.name = name - self.translate = translate - - @property - def distance(self): - return self._distance - - @distance.setter - def distance(self, value): - self._distance = value - - @property - def rotation_angle(self): - return self._rotation_angle - - @rotation_angle.setter - def rotation_angle(self, value): - self._rotation_angle = value - - @property - def extrusion_start_offset(self): - return self._extrusion_start_offset - - @extrusion_start_offset.setter - def extrusion_start_offset(self, value): - self._extrusion_start_offset = value - - def create_solid(self): - """Creates an extruded 3d solid using points connected with straight - and spline edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - solid = super().create_solid() - - if not self.extrude_both: - extrusion_distance = -self.distance - else: - extrusion_distance = -self.distance / 2.0 - - wire = solid.close() - - self.wire = wire - - solid = wire.extrude(until=extrusion_distance, both=self.extrude_both) - - # filleting rectangular port cutter edges - # must be done before azimuthal placement - if hasattr(self, "add_fillet"): - solid = self.add_fillet(solid) - - solid = self.rotate_solid(solid) - cutting_wedge = calculate_wedge_cut(self) - solid = self.perform_boolean_operations(solid, wedge_cut=cutting_wedge) - - if self.translate: - solid = solid.translate(self.translate) - - self.solid = solid - - return solid diff --git a/src/paramak/parametric_shapes/extruded_spline_shape.py b/src/paramak/parametric_shapes/extruded_spline_shape.py deleted file mode 100644 index 30bd97f95..000000000 --- a/src/paramak/parametric_shapes/extruded_spline_shape.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Optional, Tuple - -from paramak import ExtrudeMixedShape - - -class ExtrudeSplineShape(ExtrudeMixedShape): - """Extrudes a 3d CadQuery solid from points connected with spline - connections. - - Args: - distance: the extrusion distance to use - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - distance: float, - color: Tuple[float, float, float, Optional[float]] = ( - 0.984, - 0.603, - 0.6, - ), - name: str = "extrudesplineshape", - **kwargs - ): - - super().__init__(distance=distance, connection_type="spline", color=color, name=name, **kwargs) diff --git a/src/paramak/parametric_shapes/extruded_straight_shape.py b/src/paramak/parametric_shapes/extruded_straight_shape.py deleted file mode 100644 index 23dc27f71..000000000 --- a/src/paramak/parametric_shapes/extruded_straight_shape.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Optional, Tuple - -from paramak import ExtrudeMixedShape - - -class ExtrudeStraightShape(ExtrudeMixedShape): - """Extrudes a 3d CadQuery solid from points connected with straight lines. - - Args: - distance: the extrusion distance to use - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - distance: float, - color: Tuple[float, float, float, Optional[float]] = ( - 1.0, - 0.498, - 0.0, - ), - name: str = "extrudestraightshape", - **kwargs - ): - - super().__init__(distance=distance, connection_type="straight", color=color, name=name, **kwargs) diff --git a/src/paramak/parametric_shapes/rotate_circle_shape.py b/src/paramak/parametric_shapes/rotate_circle_shape.py deleted file mode 100644 index c4b038585..000000000 --- a/src/paramak/parametric_shapes/rotate_circle_shape.py +++ /dev/null @@ -1,77 +0,0 @@ -from typing import Optional, Tuple - -from cadquery import Workplane - -from paramak import Shape - - -class RotateCircleShape(Shape): - """Rotates a circular 3d CadQuery solid from a central point and a radius - - Args: - radius: radius of the shape - rotation_angle: The rotation_angle to use when revolving the solid - (degrees). Defaults to 360.0. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - radius: float, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = (1.0, 1.0, 0.6), - name: str = "rotatecircleshape", - translate: Optional[Tuple[float, float, float]] = None, - **kwargs - ): - - super().__init__(color=color, name=name, **kwargs) - self.radius = radius - self.rotation_angle = rotation_angle - self.color = color - self.name = name - self.translate = translate - - @property - def rotation_angle(self): - return self._rotation_angle - - @rotation_angle.setter - def rotation_angle(self, value): - self._rotation_angle = value - - @property - def radius(self): - return self._radius - - @radius.setter - def radius(self, value): - self._radius = value - - def create_solid(self): - """Creates a rotated 3d solid using points with circular edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - wire = Workplane(self.workplane).moveTo(self.points[0][0], self.points[0][1]).circle(self.radius) - - self.wire = wire - - solid = wire.revolve(self.rotation_angle) - - solid = self.rotate_solid(solid) - solid = self.perform_boolean_operations(solid) - - if self.translate: - solid = solid.translate(self.translate) - - self.solid = solid - return solid diff --git a/src/paramak/parametric_shapes/rotate_mixed_shape.py b/src/paramak/parametric_shapes/rotate_mixed_shape.py deleted file mode 100644 index ce494258a..000000000 --- a/src/paramak/parametric_shapes/rotate_mixed_shape.py +++ /dev/null @@ -1,72 +0,0 @@ -from typing import Optional, Tuple - -from paramak import Shape - - -class RotateMixedShape(Shape): - """Rotates a 3d CadQuery solid from points connected with a mixture of - straight lines and splines. - - Args: - rotation_angle: The rotation_angle to use when revolving the solid - (degrees). Defaults to 360.0. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = ( - 0.121, - 0.47, - 0.705, - ), - name: str = "rotatemixedshape", - translate: Optional[Tuple[float, float, float]] = None, - **kwargs - ): - - super().__init__(color=color, name=name, **kwargs) - self.rotation_angle = rotation_angle - self.color = color - self.name = name - self.translate = translate - - @property - def rotation_angle(self): - return self._rotation_angle - - @rotation_angle.setter - def rotation_angle(self, value): - self._rotation_angle = value - - def create_solid(self): - """Creates a rotated 3d solid using points with straight and spline - edges. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - solid = super().create_solid() - - wire = solid.close() - - self.wire = wire - - solid = wire.revolve(self.rotation_angle) - - solid = self.rotate_solid(solid) - solid = self.perform_boolean_operations(solid) - - if self.translate: - solid = solid.translate(self.translate) - - self.solid = solid - return solid diff --git a/src/paramak/parametric_shapes/rotate_spline_shape.py b/src/paramak/parametric_shapes/rotate_spline_shape.py deleted file mode 100644 index 93c40f5b7..000000000 --- a/src/paramak/parametric_shapes/rotate_spline_shape.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Optional, Tuple - -from paramak import RotateMixedShape - - -class RotateSplineShape(RotateMixedShape): - """Rotates a 3d CadQuery solid from points connected with splines. - - Args: - rotation_angle: The rotation_angle to use when revolving the solid. - Defaults to 360.0. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = ( - 0.415, - 0.239, - 0.603, - ), - name: str = "rotatesplineshape", - **kwargs - ): - - super().__init__(rotation_angle=rotation_angle, color=color, connection_type="spline", name=name, **kwargs) diff --git a/src/paramak/parametric_shapes/rotate_straight_shape.py b/src/paramak/parametric_shapes/rotate_straight_shape.py deleted file mode 100644 index f8f9e03de..000000000 --- a/src/paramak/parametric_shapes/rotate_straight_shape.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Optional, Tuple - -from paramak import RotateMixedShape - - -class RotateStraightShape(RotateMixedShape): - """Rotates a 3d CadQuery solid from points connected with straight - connections. - - Args: - rotation_angle: The rotation angle to use when revolving the solid - (degrees). - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - rotation_angle: float = 360.0, - color: Tuple[float, float, float, Optional[float]] = ( - 0.89, - 0.101, - 0.109, - ), - name: str = "rotatestraightshape", - **kwargs - ): - - super().__init__(rotation_angle=rotation_angle, color=color, connection_type="straight", name=name, **kwargs) diff --git a/src/paramak/parametric_shapes/sweep_circle_shape.py b/src/paramak/parametric_shapes/sweep_circle_shape.py deleted file mode 100644 index 669f9aa62..000000000 --- a/src/paramak/parametric_shapes/sweep_circle_shape.py +++ /dev/null @@ -1,150 +0,0 @@ -from typing import List, Optional, Tuple - -from cadquery import Workplane - -from paramak import Shape - - -class SweepCircleShape(Shape): - """Sweeps a 2D circle of a defined radius along a defined spline path to - create a 3D CadQuery solid. Note, some variation in the cross-section of - the solid may occur. - - Args: - radius: Radius of 2D circle to be swept. - path_points: A list of XY, YZ or XZ coordinates connected by spline - connections which define the path along which the 2D shape is swept - workplane: Workplane in which the circle to be swept - is defined. Defaults to "XY". - path_workplane: Workplane in which the spline path is - defined. Defaults to "XZ". - force_cross_section: If True, cross-section of solid is forced to be - shape defined by points in workplane at each path_point. Defaults - to False. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - radius: float, - path_points: List[Tuple[float, float]], - workplane: str = "XY", - path_workplane: str = "XZ", - force_cross_section: bool = False, - color: Tuple[float, float, float, Optional[float]] = ( - 0.651, - 0.808, - 0.89, - ), - name: str = "sweepcircleshape", - translate: Optional[Tuple[float, float, float]] = None, - **kwargs - ): - - super().__init__(workplane=workplane, color=color, name=name, **kwargs) - - self.radius = radius - self.path_points = path_points - self.workplane = workplane - self.path_workplane = path_workplane - self.force_cross_section = force_cross_section - self.color = color - self.name = name - self.translate = translate - - @property - def radius(self): - return self._radius - - @radius.setter - def radius(self, value): - self._radius = value - - @property - def path_points(self): - return self._path_points - - @path_points.setter - def path_points(self, value): - self._points = value - self._path_points = value - - @property - def path_workplane(self): - return self._path_workplane - - @path_workplane.setter - def path_workplane(self, value): - if value[0] != self.workplane[0]: - raise ValueError("workplane and path_workplane must start with the same letter") - elif value == self.workplane: - raise ValueError("workplane and path_workplane must be different") - else: - self._path_workplane = value - - def create_solid(self): - """Creates a swept 3D solid from a 2D circle. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - path = Workplane(self.path_workplane).spline(self.path_points) - - factor = 1 - if self.workplane in ["XZ", "YX", "ZY"]: - factor *= -1 - - wires = [] - if self.force_cross_section: - wire = Workplane(self.workplane).center(0, 0) - for point in self.path_points[:-1]: - wire = wire.workplane(offset=point[1] * factor).center(point[0], 0).circle(self.radius) - - wires.append(wire) - - wire = wire.center(-point[0], 0).workplane(offset=-point[1] * factor) - - self.wire = wires - - solid = ( - wire.workplane(offset=self.path_points[-1][1] * factor) - .center(self.path_points[-1][0], 0) - .circle(self.radius) - .sweep(path, multisection=True) - ) - - else: - - wire = ( - Workplane(self.workplane) - .workplane(offset=self.path_points[0][1] * factor) - .center(self.path_points[0][0], 0) - .workplane() - .circle(self.radius) - .center(-self.path_points[0][0], 0) - .workplane(offset=-self.path_points[0][1] * factor) - .workplane(offset=self.path_points[-1][1] * factor) - .center(self.path_points[-1][0], 0) - .workplane() - .circle(self.radius) - ) - - self.wire = wire - - solid = wire.sweep(path, multisection=True) - - solid = self.rotate_solid(solid) - solid = self.perform_boolean_operations(solid) - - if self.translate: - solid = solid.translate(self.translate) - - self.solid = solid - return solid diff --git a/src/paramak/parametric_shapes/sweep_mixed_shape.py b/src/paramak/parametric_shapes/sweep_mixed_shape.py deleted file mode 100644 index 42fc756d8..000000000 --- a/src/paramak/parametric_shapes/sweep_mixed_shape.py +++ /dev/null @@ -1,103 +0,0 @@ -from typing import List, Optional, Tuple - -from cadquery import Workplane - -from paramak import Shape - - -class SweepMixedShape(Shape): - """Sweeps a 2D shape created from points connected with straight, spline - or circle connections along a defined spline path to create a 3D CadQuery - solid. Note, some variation in cross-section of the solid may occur. - - Args: - path_points: A list of XY, YZ or XZ coordinates connected by spline - connections which define the path along which the 2D shape is - swept. - workplane: Workplane in which the 2D shape to be swept is defined. - Defaults to "XY". - path_workplane: Workplane in which the spline path is defined. Defaults - to "XZ". - force_cross_section (bool, optional): If True, cross-section of solid - is forced to be shape defined by points in workplane at each - path_point. Defaults to False. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - path_points: List[Tuple[float, float]], - workplane: str = "XY", - path_workplane: str = "XZ", - force_cross_section: bool = False, - color: Tuple[float, float, float, Optional[float]] = ( - 0.792, - 0.698, - 0.839, - ), - name: str = "sweepmixedshape", - translate: Optional[Tuple[float, float, float]] = None, - **kwargs - ): - - super().__init__(workplane=workplane, color=color, name=name, **kwargs) - - self.path_points = path_points - self.workplane = workplane - self.path_workplane = path_workplane - self.force_cross_section = force_cross_section - self.color = color - self.name = name - self.translate = translate - - @property - def path_points(self): - return self._path_points - - @path_points.setter - def path_points(self, value): - self._path_points = value - - @property - def path_workplane(self): - return self._path_workplane - - @path_workplane.setter - def path_workplane(self, value): - if value[0] != self.workplane[0]: - raise ValueError("workplane and path_workplane must start with the same letter") - elif value == self.workplane: - raise ValueError("workplane and path_workplane must be different") - else: - self._path_workplane = value - - def create_solid(self): - """Creates a swept 3D solid from a 2D shape with mixed connections. - - Returns: - A CadQuery solid: A 3D solid volume - """ - - solid = super().create_solid() - path = Workplane(self.path_workplane).spline(self.path_points) - - wire = solid.close() - - self.wire = wire - - solid = wire.sweep(path, multisection=True) - - solid = self.rotate_solid(solid) - solid = self.perform_boolean_operations(solid) - - if self.translate: - solid = solid.translate(self.translate) - - self.solid = solid - return solid diff --git a/src/paramak/parametric_shapes/sweep_spline_shape.py b/src/paramak/parametric_shapes/sweep_spline_shape.py deleted file mode 100644 index cfb53a4d5..000000000 --- a/src/paramak/parametric_shapes/sweep_spline_shape.py +++ /dev/null @@ -1,55 +0,0 @@ -from typing import List, Optional, Tuple - -from paramak import SweepMixedShape - - -class SweepSplineShape(SweepMixedShape): - """Sweeps a 2D shape created from points connected with spline connections - along a defined spline path to create a 3D CadQuery solid. Note, some - variation in the cross-section of the solid may occur. - - Args: - path_points: A list of XY, YZ or XZ coordinates connected by spline - connections which define the path along which the 2D shape is - swept. - workplane: Workplane in which the 2D shape to be swept is defined. - Defaults to "XY". - path_workplane: Workplane in which the spline path is defined. Defaults - to "XZ". - force_cross_section (bool, optional): If True, cross-setion of solid - is forced to be shape defined by points in workplane at each - path_point. Defaults to False. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - path_points: List[Tuple[float, float]], - workplane: str = "XY", - path_workplane: str = "XZ", - force_cross_section: bool = False, - color: Tuple[float, float, float, Optional[float]] = ( - 0.992, - 0.749, - 0.435, - ), - name: str = "sweepsplineshape", - **kwargs - ): - - super().__init__( - path_points=path_points, - workplane=workplane, - path_workplane=path_workplane, - connection_type="spline", - force_cross_section=force_cross_section, - color=color, - name=name, - **kwargs - ) diff --git a/src/paramak/parametric_shapes/sweep_straight_shape.py b/src/paramak/parametric_shapes/sweep_straight_shape.py deleted file mode 100644 index 1e5a72523..000000000 --- a/src/paramak/parametric_shapes/sweep_straight_shape.py +++ /dev/null @@ -1,54 +0,0 @@ -from typing import List, Optional, Tuple - -from paramak import SweepMixedShape - - -class SweepStraightShape(SweepMixedShape): - """Sweeps a 2D shape created from points connected with straight lines - along a defined spline path to create a 3D CadQuery solid. Note, some - variation in the cross-section of the solid may occur. - - Args: - path_points: A list of XY, YZ or XZ coordinates connected by spline - connections which define the path along which the 2D shape is swept - workplane: Workplane in which the 2D shape to be swept is defined. - Defaults to "XY". - path_workplane: Workplane in which the spline path is defined. Defaults - to "XZ". - force_cross_section: If True, cross-section of solid is forced to be - shape defined by points in workplane at each path_point. Defaults - to False. - color: the color to use when exporting the shape to CAD formats that - support color. A tuple of three floats each ranging between 0 - and 1. - name: the name of the shape, used to name files when exporting and - as a legend in plots. - translate: distance to translate / move the shape by. Specified as - a vector of (X,Y,Z) directions. - """ - - def __init__( - self, - path_points: List[Tuple[float, float]], - workplane: str = "XY", - path_workplane: str = "XZ", - force_cross_section: bool = False, - color: Tuple[float, float, float, Optional[float]] = ( - 0.698, - 0.8745, - 0.541, - ), - name: str = "sweepstraightshape", - **kwargs - ): - - super().__init__( - path_points=path_points, - workplane=workplane, - path_workplane=path_workplane, - connection_type="straight", - force_cross_section=force_cross_section, - color=color, - name=name, - **kwargs - ) diff --git a/src/paramak/reactor.py b/src/paramak/reactor.py deleted file mode 100644 index 1d660284e..000000000 --- a/src/paramak/reactor.py +++ /dev/null @@ -1,684 +0,0 @@ -from collections.abc import Iterable -from pathlib import Path -from typing import List, Optional, Tuple, Union - -import cadquery as cq -import matplotlib.pyplot as plt -from cadquery import exporters - -import paramak -from paramak.utils import ( - _replace, - get_hash, - get_bounding_box, - get_largest_dimension, - export_solids_to_brep, - export_solids_to_dagmc_h5m, -) - - -class Reactor: - """The Reactor object allows shapes and components to be added and then - collective operations to be performed on them. Combining all the shapes is - required for creating images of the whole reactor. - - Args: - shapes_and_components: list of paramak.Shape objects - """ - - def __init__( - self, - shapes_and_components: List[paramak.Shape] = [], - ): - - self.shapes_and_components = shapes_and_components - - self.input_variable_names: List[str] = [ - # 'shapes_and_components', commented out to avoid calculating solids - ] - - self.stp_filenames: List[str] = [] - self.stl_filenames: List[str] = [] - - self.solid = None - self.reactor_hash_value = None - - @property - def input_variables(self): - all_input_variables = {} - for name in self.input_variable_names: - all_input_variables[name] = getattr(self, name) - return all_input_variables - - @property - def largest_dimension(self): - """Calculates a bounding box for the Reactor and returns the largest - absolute value of the largest dimension of the bounding box""" - - largest_dimension = get_largest_dimension(self.solid) - - return largest_dimension - - @largest_dimension.setter - def largest_dimension(self, value): - self._largest_dimension = value - - @property - def bounding_box(self): - """Calculates a bounding box for the Shape and returns the coordinates of - the corners lower-left and upper-right. This function is useful when - creating OpenMC mesh tallies as the bounding box is required in this form""" - - return get_bounding_box(self.solid) - - @bounding_box.setter - def bounding_box(self, value): - self._bounding_box = value - - @property - def shapes_and_components(self): - """Adds a list of parametric shape(s) and or parametric component(s) - to the Reactor object. This allows collective operations to be - performed on all the shapes in the reactor.""" - if hasattr(self, "create_solids"): - ignored_keys = ["reactor_hash_value"] - if get_hash(self, ignored_keys) != self.reactor_hash_value: - self.create_solids() - self.reactor_hash_value = get_hash(self, ignored_keys) - return self._shapes_and_components - - @shapes_and_components.setter - def shapes_and_components(self, value): - if not isinstance(value, (Iterable, str)): - raise ValueError("shapes_and_components must be a list") - self._shapes_and_components = value - - @property - def solid(self): - """This combines all the parametric shapes and components in the - reactor object. - """ - - list_of_cq_vals = [] - for shape_or_compound in self.shapes_and_components: - if isinstance( - shape_or_compound.solid, - (cq.occ_impl.shapes.Shape, cq.occ_impl.shapes.Compound), - ): - for solid in shape_or_compound.solid.Solids(): - list_of_cq_vals.append(solid) - else: - list_of_cq_vals.append(shape_or_compound.solid.val()) - - compound = cq.Compound.makeCompound(list_of_cq_vals) - - return compound - - @solid.setter - def solid(self, value): - self._solid = value - - @property - def name(self): - """Returns a list of names of the individual Shapes that make up the - reactor""" - - all_names = [] - for shape in self.shapes_and_components: - all_names.append(shape.name) - - return all_names - - def show(self, **kwargs): - """Shows / renders the CadQuery the 3d object in Jupyter Lab. Imports - show from jupyter_cadquery and returns show(Reactor.solid, kwargs) - - Args: - kwargs: keyword arguments passed to jupyter-cadquery show() - function. See https://github.com/bernhard-42/jupyter-cadquery#usage - for more details on acceptable keywords - - - Returns: - jupyter_cadquery show object - """ - - try: - from jupyter_cadquery import show - except ImportError: - msg = ( - "To use Reactor.show() you must install jupyter_cadquery version " - '3.2.0 or above. To install jupyter_cadquery type "pip install ' - 'jupyter_cadquery" in the terminal' - ) - raise ImportError(msg) - - assembly = cq.Assembly(name="reactor") - for entry in self.shapes_and_components: - if entry.color is None: - assembly.add(entry.solid) - else: - assembly.add(entry.solid, color=cq.Color(*entry.color)) - - return show(assembly, **kwargs) - - def export_dagmc_h5m( - self, - filename: str = "dagmc.h5m", - min_mesh_size: float = 5, - max_mesh_size: float = 20, - exclude: List[str] = None, - verbose: bool = False, - volume_atol: float = 0.000001, - center_atol: float = 0.000001, - bounding_box_atol: float = 0.000001, - tags: Optional[List[str]] = None, - ) -> str: - """Export a DAGMC compatible h5m file for use in neutronics simulations. - This method makes use of Gmsh to create a surface mesh of the geometry. - MOAB is used to convert the meshed geometry into a h5m with parts tagged by - using the reactor.shape_and_components.name properties. You will need - Gmsh installed and MOAB installed to use this function. Acceptable - tolerances may need increasing to match reactor parts with the parts - in the intermediate Brep file produced during the process - - Args: - filename: the filename of the DAGMC h5m file to write - min_mesh_size: the minimum mesh element size to use in Gmsh. Passed - into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size) - max_mesh_size: the maximum mesh element size to use in Gmsh. Passed - into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size) - exclude: A list of shape names to not include in the exported - geometry. 'plasma' is often excluded as not many neutron - interactions occur within a low density plasma. - volume_atol: the absolute volume tolerance to allow when matching - parts in the intermediate brep file with the cadquery parts - center_atol: the absolute center coordinates tolerance to allow - when matching parts in the intermediate brep file with the - cadquery parts - bounding_box_atol: the absolute volume tolerance to allow when - matching parts in the intermediate brep file with the cadquery - parts - tags: the dagmc tag to use in when naming the shape in the h5m file. - If left as None then the Shape.name will be used. This allows - the DAGMC geometry created to be compatible with a wider range - of neutronics codes that have specific DAGMC tag requirements. - """ - - shapes_to_convert = [] - - for shape in self.shapes_and_components: - # allows components like the plasma to be removed - if exclude: - if shape.name not in exclude: - shapes_to_convert.append(shape) - else: - shapes_to_convert.append(shape) - - assembly = cq.Assembly(name="reactor") - for solid in self.shapes_and_components: - assembly.add(solid.solid) - - if tags is None: - tags = [] - for shape in self.shapes_and_components: - tags.append(shape.name) - - expamded_tags = [] - - if len(tags) != len(self.shapes_and_components): - msg = ( - f"Number of tags {len(tags)} is not equal to the number of " - "shapes_and_components {len(self.shapes_and_components)}" - ) - raise ValueError(msg) - - for tag, s_c in zip(tags, self.shapes_and_components): - # solids could contain compounds - # before accessing the .val() check it exists - if hasattr(s_c.solid, "val"): - # if it is a compound then we may need more material tags - if isinstance(s_c.solid.val(), cq.occ_impl.shapes.Compound): - required_num_tags = len(s_c.solid.val().Solids()) - else: - required_num_tags = 1 - elif isinstance(s_c.solid, cq.occ_impl.shapes.Compound): - required_num_tags = len(s_c.solid.Solids()) - else: - required_num_tags = 1 - expamded_tags = expamded_tags + [tag] * required_num_tags - - output_filename = export_solids_to_dagmc_h5m( - solids=assembly, - filename=filename, - min_mesh_size=min_mesh_size, - max_mesh_size=max_mesh_size, - verbose=verbose, - volume_atol=volume_atol, - center_atol=center_atol, - bounding_box_atol=bounding_box_atol, - tags=expamded_tags, - ) - - return output_filename - - def export_stp( - self, - filename: Union[List[str], str] = None, - mode: Optional[str] = "solid", - units: Optional[str] = "mm", - ) -> Union[List[str], str]: - """Exports the 3D reactor model as a stp file or files. - - Args: - filename: Accepts a single filename as a string which exports the - full reactor model to a single file. Alternativley filename can - also accept a list of strings where each string is the filename - of the the individual shapes that make it up. This will result - in separate files for each shape in the reactor. Defaults to - None which uses the Reactor.name with '.stp' appended to the end - of each entry. - mode: the object to export can be either 'solid' which exports 3D - solid shapes or the 'wire' which exports the wire edges of the - shape. - units: the units of the stp file, options are 'cm' or 'mm'. - Default is mm. - Returns: - The stp filename(s) created - """ - - if isinstance(filename, str): - - # exports a single file for the whole model - assembly = cq.Assembly(name="reactor") - for entry in self.shapes_and_components: - if entry.color is None: - assembly.add(entry.solid) - else: - assembly.add(entry.solid, color=cq.Color(*entry.color)) - - assembly.save(filename, exportType="STEP") - - if units == "cm": - _replace(filename, "SI_UNIT(.MILLI.,.METRE.)", "SI_UNIT(.CENTI.,.METRE.)") - - return [filename] - - if filename is None: - if None in self.name: - msg = ( - "Shape.name is None and therefore it can't be used " - "to name a stp file. Try setting Shape.name for all " - "shapes in the reactor" - ) - raise ValueError(msg) - filename = [f"{name}.stp" for name in self.name] - - # exports the reactor solid as a separate stp files - if len(filename) != len(self.shapes_and_components): - msg = ( - f"The Reactor contains {len(self.shapes_and_components)} " - f"Shapes and {len(filename)} filenames have be provided. " - f"The names of the shapes are {self.name}" - ) - raise ValueError(msg) - - for stp_filename, entry in zip(filename, self.shapes_and_components): - - entry.export_stp( - filename=stp_filename, - mode=mode, - units=units, - verbose=False, - ) - - if units == "cm": - _replace(stp_filename, "SI_UNIT(.MILLI.,.METRE.)", "SI_UNIT(.CENTI.,.METRE.)") - - return filename - - def export_brep( - self, - filename: str = "reactor.brep", - ) -> str: - """Exports a brep file for the Reactor. - - Args: - filename: the filename of exported the brep file. - - Returns: - filename of the brep created - """ - - geometry_to_save = [shape.solid for shape in self.shapes_and_components] - - output_filename = export_solids_to_brep( - solids=geometry_to_save, - filename=filename, - ) - - return output_filename - - def export_stl( - self, - filename: Union[List[str], str] = None, - tolerance: float = 0.001, - angular_tolerance: float = 0.1, - ) -> Union[str, List[str]]: - """Writes stl files (CAD geometry) for each Shape object in the reactor - - Args: - filename: Accepts a single filename as a string which exports the - full reactor model to a single file. Alternativley filename can - also accept a list of strings where each string is the filename - of the the individual shapes that make it up. This will result - in separate files for each shape in the reactor. Defaults to - None which uses the Reactor.name with '.stl' appended to the end - of each entry. - tolerance (float): the precision of the faceting - - Returns: - list: a list of stl filenames created - """ - - if isinstance(filename, str): - - path_filename = Path(filename) - - if path_filename.suffix != ".stl": - path_filename = path_filename.with_suffix(".stl") - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - exporters.export( - self.solid, - str(path_filename), - exportType="STL", - tolerance=tolerance, - angularTolerance=angular_tolerance, - ) - return str(path_filename) - - if filename is None: - if None in self.name: - msg = ( - "Shape.name is None and therefore it can't be used " - "to name a stl file. Try setting Shape.name for all " - "shapes in the reactor" - ) - raise ValueError() - filename = [f"{name}.stl" for name in self.name] - - # exports the reactor solid as a separate stl files - if len(filename) != len(self.shapes_and_components): - msg = ( - f"The Reactor contains {len(self.shapes_and_components)} " - f"Shapes and {len(filename)} filenames have be provided. " - f"The names of the shapes are {self.name}" - ) - raise ValueError(msg) - - for stl_filename, entry in zip(filename, self.shapes_and_components): - - entry.export_stl( - filename=stl_filename, - tolerance=tolerance, - verbose=False, - ) - - return filename - - def make_sector_wedge( - self, - height: Optional[float] = None, - radius: Optional[float] = None, - rotation_angle: Optional[float] = None, - ) -> Union[paramak.Shape, None]: - """Creates a rotated wedge shaped object that is useful for creating - sector models in DAGMC where reflecting surfaces are needed. If the - rotation - - Args: - height: The height of the rotated wedge. If None then the - largest_dimension of the model will be used. - radius: The radius of the rotated wedge. If None then the - largest_dimension of the model will be used - rotation_angle: The rotation angle of the wedge will be the - inverse of the sector - - Returns: - the paramak.Shape object created - """ - - if rotation_angle is None: - if hasattr(self, "rotation_angle"): - rotation_angle = self.rotation_angle - if rotation_angle is None: - Warning("No sector_wedge can be made as rotation_angle" " or Reactor.rotation_angle have not been set") - return None - - if rotation_angle > 360: - Warning("No wedge can be made for a rotation angle of 360 or above") - return None - - if rotation_angle == 360: - print("No sector wedge made as rotation angle is 360") - return None - - # todo this should be cetered around the center point - - if height is None: - height = self.largest_dimension * 2 - - if radius is None: - radius = self.largest_dimension * 2 - - sector_cutting_wedge = paramak.CuttingWedge( - height=height, - radius=radius, - rotation_angle=360 - rotation_angle, - surface_reflectivity=True, - azimuth_placement_angle=rotation_angle, - ) - - self.sector_wedge = sector_cutting_wedge - - return sector_cutting_wedge - - def export_svg( - self, - filename: Optional[str] = "reactor.svg", - projectionDir: Tuple[float, float, float] = (-1.75, 1.1, 5), - width: Optional[float] = 1000, - height: Optional[float] = 800, - marginLeft: Optional[float] = 120, - marginTop: Optional[float] = 100, - strokeWidth: Optional[float] = None, - strokeColor: Optional[Tuple[int, int, int]] = (0, 0, 0), - hiddenColor: Optional[Tuple[int, int, int]] = (100, 100, 100), - showHidden: Optional[bool] = False, - showAxes: Optional[bool] = False, - ) -> str: - """Exports an svg file for the Reactor.solid. If the filename provided - doesn't end with .svg it will be added. - - Args: - filename: the filename of the svg file to be exported. Defaults to - "reactor.svg". - projectionDir: The direction vector to view the geometry from - (x, y, z). Defaults to (-1.75, 1.1, 5) - width: the width of the svg image produced in pixels. Defaults to - 1000 - height: the height of the svg image produced in pixels. Defaults to - 800 - marginLeft: the number of pixels between the left edge of the image - and the start of the geometry. - marginTop: the number of pixels between the top edge of the image - and the start of the geometry. - strokeWidth: the width of the lines used to draw the geometry. - Defaults to None which automatically selects an suitable width. - strokeColor: the color of the lines used to draw the geometry in - RGB format with each value between 0 and 255. Defaults to - (0, 0, 0) which is black. - hiddenColor: the color of the lines used to draw the geometry in - RGB format with each value between 0 and 255. Defaults to - (100, 100, 100) which is light grey. - showHidden: If the edges obscured by geometry should be included in - the diagram. Defaults to False. - showAxes: If the x, y, z axis should be included in the image. - Defaults to False. - - Returns: - str: the svg filename created - """ - - path_filename = Path(filename) - - if path_filename.suffix != ".svg": - path_filename = path_filename.with_suffix(".svg") - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - opt = { - "width": width, - "height": height, - "marginLeft": marginLeft, - "marginTop": marginTop, - "showAxes": showAxes, - "projectionDir": projectionDir, - "strokeColor": strokeColor, - "hiddenColor": hiddenColor, - "showHidden": showHidden, - } - - if strokeWidth is not None: - opt["strokeWidth"] = strokeWidth - - exporters.export(self.solid, str(path_filename), exportType="SVG", opt=opt) - - print("Saved file as ", path_filename) - - return str(path_filename) - - def export_2d_image( - self, - filename: Optional[str] = "2d_slice.png", - xmin: Optional[float] = 0.0, - xmax: Optional[float] = 900.0, - ymin: Optional[float] = -600.0, - ymax: Optional[float] = 600.0, - ) -> str: - """Creates a 2D slice image (png) of the reactor. - - Args: - filename (str): output filename of the image created - - Returns: - str: png filename created - """ - - path_filename = Path(filename) - - if path_filename.suffix != ".png": - path_filename = path_filename.with_suffix(".png") - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - fig, ax = plt.subplots() - - # creates indvidual patches for each Shape which are combined together - for entry in self.shapes_and_components: - patch = entry._create_patch() - ax.add_collection(patch) - - ax.axis("equal") - ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax)) - ax.set_aspect("equal", "box") - - Path(filename).parent.mkdir(parents=True, exist_ok=True) - plt.savefig(filename, dpi=100) - plt.close() - - print("\n saved 2d image to ", str(path_filename)) - - return str(path_filename) - - def export_html_3d(self, filename: Optional[str] = "reactor_3d.html", **kwargs) -> Optional[str]: - """Saves an interactive 3d html view of the Reactor to a html file. - - Args: - filename: the filename used to save the html graph. Defaults to - reactor_3d.html - kwargs: keyword arguments passed to jupyter-cadquery show() - function. See https://github.com/bernhard-42/jupyter-cadquery#usage - for more details on acceptable keywords - - Returns: - str: filename of the created html file - """ - - view = self.show(**kwargs) - - view.export_html(filename) - - return filename - - def export_html( - self, - filename: Optional[str] = "reactor.html", - facet_splines: Optional[bool] = True, - facet_circles: Optional[bool] = True, - tolerance: Optional[float] = 1.0, - view_plane: Optional[str] = "RZ", - ): - """Creates a html graph representation of the points for the Shape - objects that make up the reactor. Shapes are colored by their .color - property. Shapes are also labelled by their .name. If filename provided - doesn't end with .html then .html will be added. - - Args: - filename: the filename used to save the html graph. Defaults to - reactor.html - facet_splines: If True then spline edges will be faceted. Defaults - to True. - facet_circles: If True then circle edges will be faceted. Defaults - to True. - tolerance: faceting toleranceto use when faceting cirles and - splines. Defaults to 1e-3. - view_plane: The plane to project. Options are 'XZ', 'XY', 'YZ', - 'YX', 'ZY', 'ZX', 'RZ' and 'XYZ'. Defaults to 'RZ'. Defaults to - 'RZ'. - Returns: - plotly.Figure(): figure object - """ - - fig = paramak.utils.export_wire_to_html( - wires=self.solid.Edges(), - filename=filename, - view_plane=view_plane, - facet_splines=facet_splines, - facet_circles=facet_circles, - tolerance=tolerance, - title=f"coordinates of the {self.__class__.__name__} reactor, viewed from the {view_plane} plane", - mode="lines", - ) - - return fig - - def volume(self, split_compounds: bool = False) -> List[float]: - """Get the volumes of the Shapes in the Reactor. - - Args: - split_compounds: If the Shape is a compound of Shapes and therefore - contains multiple volumes. This option allows access to the separate - volumes of each component within a Shape (True) or the volumes of - compounds can be summed (False). - - Returns: - The the volumes of the Shapes - """ - - all_volumes = [] - for shape in self.shapes_and_components: - all_volumes.append(shape.volume(split_compounds=split_compounds)) - return all_volumes diff --git a/src/paramak/shape.py b/src/paramak/shape.py deleted file mode 100644 index ade656951..000000000 --- a/src/paramak/shape.py +++ /dev/null @@ -1,1251 +0,0 @@ -import numbers -from collections.abc import Iterable -from pathlib import Path -from typing import List, Optional, Tuple, Union - -import matplotlib.pyplot as plt -from cadquery import Assembly, Color, Compound, Plane, Workplane, exporters, importers -from cadquery.occ_impl import shapes -from matplotlib.collections import PatchCollection -from matplotlib.patches import Polygon - -import paramak -from paramak.utils import ( - _replace, - cut_solid, - facet_wire, - get_hash, - intersect_solid, - union_solid, - get_largest_dimension, - get_bounding_box, - export_solids_to_brep, - export_solids_to_dagmc_h5m, -) - - -class Shape: - """A shape object that represents a 3d volume and can have materials and - neutronics tallies assigned. Shape objects are not intended to be used - directly by the user but provide basic functionality for user-facing - classes that inherit from Shape. Provides a .show attribute for rendering - in Jupyter Lab - - Args: - points (tuple of (float, float, float), optional): the x, y, z - coordinates of points that make up the shape. Defaults to None. - connection_type (str, optional): The type of connection between points. - Possible values are "straight", "circle", "spline", "mixed". - Defaults to "mixed". - name (str, optional): the name of the shape, used in the graph legend - by export_html. Defaults to None. - color ((float, float, float [, float]), optional): The color to use - when exporting as html graphs or png images. Can be in RGB or RGBA - format with floats between 0 and 1. Defaults to (0.5, 0.5, 0.5). - azimuth_placement_angle (iterable of floats or float, optional): the - azimuth angle(s) used when positioning the shape. If a list of - angles is provided, the shape is duplicated at all angles. - Defaults to 0.0. - workplane: the orientation of the Cadquery workplane. Options include - strings "XY", "YZ", "XZ" or a Cadquery.Plane(). Defaults to "XZ". - rotation_axis (str or list, optional): rotation axis around which the - solid is rotated. If None, the rotation axis will depend on the - workplane or path_workplane if applicable. Can be set to "X", "-Y", - "Z", etc. A custom axis can be set by setting a list of two XYZ - floats. Defaults to None. - cut (paramak.shape or list, optional): If set, the current solid will - be cut with the provided solid or iterable in cut. Defaults to - None. - intersect (paramak.shape or list, optional): If set, the current solid - will be interested with the provided solid or iterable of solids. - Defaults to None. - union (paramak.shape or list, optional): If set, the current solid - will be united with the provided solid or iterable of solids. - Defaults to None. - """ - - def __init__( - self, - points: Union[tuple, list] = None, - connection_type: Optional[str] = "mixed", - name: Optional[str] = None, - color: Tuple[float, float, float, Optional[float]] = (0.5, 0.5, 0.5), - azimuth_placement_angle: Optional[Union[float, List[float]]] = 0.0, - workplane: Optional[Union[str, Plane]] = "XZ", - rotation_axis: Optional[str] = None, - # TODO defining Shape types as paramak.Shape results in circular import - cut=None, - intersect=None, - union=None, - ): - - self.connection_type = connection_type - self.points = points - self.color = color - self.name = name - - self.cut = cut - self.intersect = intersect - self.union = union - - self.azimuth_placement_angle = azimuth_placement_angle - self.workplane = workplane - self.rotation_axis = rotation_axis - - # initialise to something different than self.points - # old_points is used in the processed_points getter - self.old_points = 0 - - # properties calculated internally by the class - self.solid = None - self.wire = None - self.render_mesh = None - - # set here but only used by Sweep shapes - self.path_points = None - self.force_cross_section = None - - # set here but only used by Extrude shapes - self.extrusion_start_offset = None - - self.processed_points = None - # self.volume = None - self.hash_value = None - self.points_hash_value = None - self.x_min = None - self.x_max = None - self.z_min = None - self.z_max = None - self.patch = None - - @property - def solid(self): - """The CadQuery solid of the 3d object. Returns a CadQuery workplane - or CadQuery Compound""" - - ignored_keys = ["_solid", "_hash_value"] - if get_hash(self, ignored_keys) != self.hash_value: - self.create_solid() - self.hash_value = get_hash(self, ignored_keys) - - return self._solid - - @solid.setter - def solid(self, value): - self._solid = value - - @property - def wire(self): - """The CadQuery wire of the 3d object. Returns a CadQuery workplane - or CadQuery Compound""" - - ignored_keys = ["_wire", "_solid", "_hash_value"] - if get_hash(self, ignored_keys) != self.hash_value: - self.create_solid() - self.hash_value = get_hash(self, ignored_keys) - - return self._wire - - @wire.setter - def wire(self, value): - self._wire = value - - @property - def cut(self): - return self._cut - - @cut.setter - def cut(self, value): - self._cut = value - - @property - def intersect(self): - return self._intersect - - @intersect.setter - def intersect(self, value): - self._intersect = value - - @property - def union(self): - return self._union - - @union.setter - def union(self, value): - self._union = value - - @property - def largest_dimension(self) -> float: - """Calculates a bounding box for the Reactor and returns the largest - absolute value of the largest dimension of the bounding box""" - - return get_largest_dimension(self.solid) - - @largest_dimension.setter - def largest_dimension(self, value): - self._largest_dimension = value - - @property - def bounding_box(self): - """Calculates a bounding box for the Shape and returns the coordinates of - the corners lower-left and upper-right. This function is useful when - creating OpenMC mesh tallies as the bounding box is required in this form""" - - return get_bounding_box(self.solid) - - @bounding_box.setter - def bounding_box(self, value): - self._bounding_box = value - - @property - def workplane(self): - return self._workplane - - @workplane.setter - def workplane(self, value): - if isinstance(value, Plane): - self._workplane = value - elif isinstance(value, str): - acceptable_values = ["XY", "YZ", "XZ", "YX", "ZY", "ZX"] - if value in acceptable_values: - self._workplane = value - else: - raise ValueError("Shape.workplane must be one of ", acceptable_values, " not ", value) - else: - raise TypeError("Shape.workplane must be a string or a ", "cadquery.Plane object") - - @property - def rotation_axis(self): - return self._rotation_axis - - @rotation_axis.setter - def rotation_axis(self, value): - if isinstance(value, str): - acceptable_values = ["X", "Y", "Z", "-X", "-Y", "-Z", "+X", "+Y", "+Z"] - if value not in acceptable_values: - msg = "Shape.rotation_axis must be one of " + " ".join(acceptable_values) + " not " + value - raise ValueError(msg) - elif isinstance(value, Iterable): - msg = "Shape.rotation_axis must be a tuple of three floats (X, Y, Z)" - if len(value) != 2: - raise ValueError(msg) - for point in value: - if not isinstance(point, Iterable): - msg = f"Shape.rotation_axis must be an iterable of iterables, not {type(point)}" - raise ValueError(msg) - if len(point) != 3: - msg = f"Shape.rotation_axis must be an iterable of iterables with 3 entries, not {len(point)}" - raise ValueError(msg) - for val in point: - if not isinstance(val, (int, float)): - msg = ( - "Shape.rotation_axis should be an iterable of " - "iterables where the nested iterables are " - f"numerical, not {type(val)}" - ) - raise ValueError(msg) - - if value[0] == value[1]: - msg = "The two coordinates points for rotation_axis must be different" - raise ValueError(msg) - elif value is not None: - msg = "Shape.rotation_axis must be an iterable or a string or None" - raise ValueError(msg) - self._rotation_axis = value - - @property - def area(self): - """Get the total surface area of the Shape. Returns a float""" - if isinstance(self.solid, Compound): - return self.solid.Area() - - return self.solid.val().Area() - - @property - def areas(self): - """Get the surface areas of the Shape. Compound shapes provide a - separate area value for each entry. Returns a list of floats""" - all_areas = [] - if isinstance(self.solid, Compound): - for face in self.solid.Faces(): - all_areas.append(face.Area()) - return all_areas - - for face in self.solid.val().Faces(): - all_areas.append(face.Area()) - return all_areas - - @property - def hash_value(self): - return self._hash_value - - @hash_value.setter - def hash_value(self, value): - self._hash_value = value - - @property - def points_hash_value(self): - return self._points_hash_value - - @points_hash_value.setter - def points_hash_value(self, value): - self._points_hash_value = value - - @property - def color(self): - return self._color - - @color.setter - def color(self, value): - if isinstance(value, (list, tuple)): - if len(value) in [3, 4]: - for i in value: - if not isinstance(i, (int, float)): - raise ValueError("Individual entries in the Shape.color must a " "number (float or int)") - if i > 1 or i < 0: - raise ValueError("Individual entries in the Shape.color must be " "between 0 and 1") - else: - raise ValueError("Shape.color must be a list or tuple of 3 or 4 floats") - else: - raise ValueError("Shape.color must be a list or tuple") - - self._color = value - - @property - def name(self): - """The name of the Shape, used to identify Shapes when exporting_html""" - return self._name - - @name.setter - def name(self, value): - if value is not None and not isinstance(value, str): - raise ValueError("Shape.name must be a string", value) - self._name = value - - @property - def processed_points(self): - """Shape.processed_points attributes is set internally from the - Shape.points""" - - if self.points is not None: - # if .points have changed since last time this was run - if self.old_points != self.points: - # assign current .points value to .old_points - self.old_points = self.points - - # compute .processed_points - if self.connection_type == "mixed": - values = self.points - else: - values = [(*p, self.connection_type) for p in self.points] - - if values[0][:2] != values[-1][:2]: - values.append(values[0]) - - self._processed_points = values - return self._processed_points - return None - - @processed_points.setter - def processed_points(self, value): - self._processed_points = value - - @property - def points(self): - """Sets the Shape.point attributes. - - Args: - points (a tuple of tuples): tuple of points that create the - shape - - Raises: - incorrect type: only list of lists or tuples are accepted - """ - ignored_keys = ["_points", "_points_hash_value"] - if self.find_points() and self.points_hash_value != get_hash(self, ignored_keys): - self.find_points() - self.points_hash_value = get_hash(self, ignored_keys) - - return self._points - - @points.setter - def points(self, values_in): - if values_in is None: - values = values_in - else: - values = values_in[:] - if values is not None: - if not isinstance(values, (list, tuple)): - raise ValueError("points must be a list or a tuple") - - for value in values: - if not isinstance(value, (list, tuple)): - msg = f"individual points must be a tuple.{value} in of " f"type {type(value)}" - raise ValueError(msg) - - for counter, value in enumerate(values): - if self.connection_type == "mixed": - if len(value) != 3: - if counter != len(values) - 1: # last point doesn't need connections - msg = ( - "individual points should contain 3 " - "entries when the Shape.connection_type is " - '"mixed". The entries should contain two ' - f"coordinates and a connection type. {value} " - "has a length of {len(value)}" - ) - print(values) - raise ValueError(msg) - else: - if len(value) != 2: - msg = ( - "individual points should contain 2 entries " - "when the Shape.connection_type is " - f"{self.connection_type}. The entries should " - f"just contain the coordinates {value} has a " - "length of {len(value)}" - ) - raise ValueError(msg) - - # Checks that the XY points are numbers - if not isinstance(value[0], numbers.Number): - msg = ( - "The first value in the tuples that make up the " - "points represents the X value and must be a number " - f"{value}" - ) - raise ValueError(msg) - if not isinstance(value[1], numbers.Number): - msg = ( - "The second value in the tuples that make up the " - "points represents the X value and must be a " - f"number {value}" - ) - raise ValueError(msg) - - # Checks that only straight and spline are in the connections - # part of points - if len(value) == 3: - if value[2] not in ["straight", "spline", "circle"]: - msg = "individual connections must be either " '"straight", "circle" or "spline"' - raise ValueError(msg) - - if len(values) > 1: - if values[0][:2] == values[-1][:2]: - msg = "The coordinates of the last and first points are " "the same." - raise ValueError(msg) - - self._points = values - - @property - def azimuth_placement_angle(self): - return self._azimuth_placement_angle - - @azimuth_placement_angle.setter - def azimuth_placement_angle(self, value): - error = False - if isinstance(value, (int, float, Iterable)) and not isinstance(value, str): - if isinstance(value, Iterable): - for i in value: - if not isinstance(i, (int, float)): - error = True - else: - error = True - - if error: - msg = "azimuth_placement_angle must be a float or list of floats" - raise ValueError(msg) - self._azimuth_placement_angle = value - - def from_stp_file(self, filename: str): - """Loads the filename using CadQuery and populates the Shape.solid - with the contents - - Args: - filename: the file name of the stp / step file to be loaded - """ - result = importers.importStep(filename) - self.solid = result - - def show(self, **kwargs): - """Shows / renders the CadQuery the 3d object in Jupyter Lab. Imports - show from jupyter_cadquery and returns show(Shape.solid, kwargs) - - Args: - kwargs: keyword arguments passed to jupyter-cadquery show() - function. See https://github.com/bernhard-42/jupyter-cadquery#usage - for more details on acceptable keywords - - Returns: - jupyter_cadquery show object - """ - - try: - from jupyter_cadquery import Part, PartGroup, show - except ImportError: - msg = ( - "To use Reactor.show() you must install jupyter_cadquery version " - '3.0.0 or above. To install jupyter_cadquery type "pip install ' - 'jupyter_cadquery" in the terminal' - ) - raise ImportError(msg) - - parts = [] - if self.name is None: - name = "Shape.name not set" - else: - name = self.name - - scaled_color = [int(i * 255) for i in self.color[0:3]] - if isinstance(self.solid, (shapes.Shape, shapes.Compound)): - for i, solid in enumerate(self.solid.Solids()): - parts.append(Part(solid, name=f"{name}{i}", color=scaled_color, show_edges=True)) - else: - parts.append( - Part( - self.solid.val(), - name=f"{name}", - color=scaled_color, - show_edges=True, - ) - ) - - return show(PartGroup(parts), **kwargs) - - def create_solid(self) -> Workplane: - solid = None - if self.processed_points is not None: - # obtains the first two values of the points list - XZ_points = [(p[0], p[1]) for p in self.processed_points] - - # obtains the last values of the points list - connections = [p[2] for p in self.processed_points[:-1]] - - current_linetype = connections[0] - current_points_list = [] - instructions = [] - # groups together common connection types - for i, connection in enumerate(connections): - if connection == current_linetype: - current_points_list.append(XZ_points[i]) - else: - current_points_list.append(XZ_points[i]) - instructions.append({current_linetype: current_points_list}) - current_linetype = connection - current_points_list = [XZ_points[i]] - instructions.append({current_linetype: current_points_list}) - - if list(instructions[-1].values())[0][-1] != XZ_points[0]: - keyname = list(instructions[-1].keys())[0] - instructions[-1][keyname].append(XZ_points[0]) - - if self.path_points: - - factor = 1 - if self.workplane in ["XZ", "YX", "ZY"]: - factor *= -1 - - solid = Workplane(self.workplane).center(0, 0) - - if self.force_cross_section: - for point in self.path_points[:-1]: - solid = solid.workplane(offset=point[1] * factor).center(point[0], 0).workplane() - for entry in instructions: - connection_type = list(entry.keys())[0] - if connection_type == "spline": - solid = solid.spline(listOfXYTuple=list(entry.values())[0]) - elif connection_type == "straight": - solid = solid.polyline(list(entry.values())[0]) - elif connection_type == "circle": - p0, p1, p2 = list(entry.values())[0][:3] - solid = solid.moveTo(p0[0], p0[1]).threePointArc(p1, p2) - solid = solid.close() - solid = solid.center(-point[0], 0).workplane(offset=-point[1] * factor) - - elif self.force_cross_section is False: - solid = ( - solid.workplane(offset=self.path_points[0][1] * factor) - .center(self.path_points[0][0], 0) - .workplane() - ) - for entry in instructions: - connection_type = list(entry.keys())[0] - if connection_type == "spline": - solid = solid.spline(listOfXYTuple=list(entry.values())[0]) - elif connection_type == "straight": - solid = solid.polyline(list(entry.values())[0]) - elif connection_type == "circle": - p0 = list(entry.values())[0][0] - p1 = list(entry.values())[0][1] - p2 = list(entry.values())[0][2] - solid = solid.moveTo(p0[0], p0[1]).threePointArc(p1, p2) - - solid = ( - solid.close() - .center(0, 0) - .center(-self.path_points[0][0], 0) - .workplane(offset=-self.path_points[0][1] * factor) - ) - - solid = ( - solid.workplane(offset=self.path_points[-1][1] * factor) - .center(self.path_points[-1][0], 0) - .workplane() - ) - - else: - # for rotate and extrude shapes - solid = Workplane(self.workplane) - # for extrude shapes - if self.extrusion_start_offset: - extrusion_offset = -self.extrusion_start_offset - solid = solid.workplane(offset=extrusion_offset) - - for entry in instructions: - if list(entry.keys())[0] == "spline": - solid = solid.spline(listOfXYTuple=list(entry.values())[0]) - if list(entry.keys())[0] == "straight": - solid = solid.polyline(list(entry.values())[0]) - if list(entry.keys())[0] == "circle": - p0 = list(entry.values())[0][0] - p1 = list(entry.values())[0][1] - p2 = list(entry.values())[0][2] - solid = solid.moveTo(p0[0], p0[1]).threePointArc(p1, p2) - - return solid - - def rotate_solid(self, solid: Optional[Workplane]) -> Workplane: - # Checks if the azimuth_placement_angle is a list of angles - if isinstance(self.azimuth_placement_angle, Iterable): - azimuth_placement_angles = self.azimuth_placement_angle - else: - azimuth_placement_angles = [self.azimuth_placement_angle] - - rotated_solids = [] - # Perform separate rotations for each angle - for angle in azimuth_placement_angles: - rotated_solids.append(solid.rotate(*self.get_rotation_axis()[0], angle)) - solid = Workplane(self.workplane) - - # Joins the seperate solids together - for i in rotated_solids: - solid = solid.union(i) - return solid - - def get_rotation_axis(self): - # TODO add return type hinting -> Tuple[List[Tuple[int, int, int], - # Tuple[int, int, int]], str] - """Returns the rotation axis for a given shape. If self.rotation_axis - is None, the rotation axis will be computed from self.workplane (or - from self.path_workplane if applicable). If self.rotation_axis is an - acceptable string (eg. "X", "+Y", "-Z"...) then this axis will be used. - If self.rotation_axis is a list of two points, then these two points - will be used to form an axis. - - Returns: - list, str: list of two XYZ points and the string of the axis (eg. - "X", "Y"..) - """ - rotation_axis = { - "X": [(-1, 0, 0), (1, 0, 0)], - "-X": [(1, 0, 0), (-1, 0, 0)], - "Y": [(0, -1, 0), (0, 1, 0)], - "-Y": [(0, 1, 0), (0, -1, 0)], - "Z": [(0, 0, -1), (0, 0, 1)], - "-Z": [(0, 0, 1), (0, 0, -1)], - } - if isinstance(self.rotation_axis, str): - # X, Y or Z axis - return ( - rotation_axis[self.rotation_axis.replace("+", "")], - self.rotation_axis, - ) - elif isinstance(self.rotation_axis, Iterable): - # Custom axis - return self.rotation_axis, "custom_axis" - elif self.rotation_axis is None: - # Axis from workplane or path_workplane - if hasattr(self, "path_workplane"): - # compute from path_workplane instead - workplane = self.path_workplane - else: - workplane = self.workplane - return rotation_axis[workplane[1]], workplane[1] - - def create_limits(self) -> Tuple[float, float, float, float]: - """Finds the x,y,z limits (min and max) of the points that make up the - face of the shape. Note the Shape may extend beyond this boundary if - splines are used to connect points. - - Raises: - ValueError: if no points are defined - - Returns: - float, float, float, float, float, float: x_minimum, x_maximum, - y_minimum, y_maximum, z_minimum, z_maximum - """ - - self.find_points() - if self.points is None: - raise ValueError("No points defined for", self) - - self.x_min = float(min([row[0] for row in self.points])) - self.x_max = float(max([row[0] for row in self.points])) - - self.z_min = float(min([row[1] for row in self.points])) - self.z_max = float(max([row[1] for row in self.points])) - - return self.x_min, self.x_max, self.z_min, self.z_max - - def find_points(self): - """Calculates the shape points. Empty method which some components - overright when inheritting.""" - return None - - def export_stl( - self, - filename: str, - tolerance: float = 0.001, - angular_tolerance: float = 0.1, - verbose: bool = True, - ) -> str: - """Exports an stl file for the Shape.solid. - - Args: - filename: the filename of exported the stl file. Defaults to None - which will attempt to use the Shape.stl_filename. If both are - None then a valueError will be raised. - tolerance: the deflection tolerance of the faceting - angular_tolerance: the angular tolerance, in radians - verbose: Enables (True) or disables (False) the printing of the - file produced. - """ - - path_filename = Path(filename) - - if path_filename.suffix != ".stl": - msg = f"filename should end with .stl, not {path_filename.suffix}" - raise ValueError(msg) - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - exporters.export( - self.solid, - str(path_filename), - exportType="STL", - tolerance=tolerance, - angularTolerance=angular_tolerance, - ) - - if verbose: - print("Saved file as ", path_filename) - - return str(path_filename) - - def export_brep(self, filename="shape.brep") -> str: - """Exports a brep file for the Shape. - - Args: - filename: the filename of exported the brep file. - - Returns: - filename of the brep created - """ - - geometry_to_save = [self.solid] - - output_filename = export_solids_to_brep( - solids=geometry_to_save, - filename=filename, - ) - - return output_filename - - def export_dagmc_h5m( - self, - filename: str = "dagmc.h5m", - min_mesh_size: float = 5, - max_mesh_size: float = 20, - verbose: bool = False, - volume_atol: float = 0.000001, - center_atol: float = 0.000001, - bounding_box_atol: float = 0.000001, - tags: Optional[List[str]] = None, - ) -> str: - """Export a DAGMC compatible h5m file for use in neutronics simulations. - This method makes use of Gmsh to create a surface mesh of the geometry. - MOAB is used to convert the meshed geometry into a h5m with parts tagged by - using the reactor.shape_and_components.name properties. You will need - Gmsh installed and MOAB installed to use this function. Acceptable - tolerances may need increasing to match reactor parts with the parts - in the intermediate Brep file produced during the process - - Args: - filename: the filename of the DAGMC h5m file to write - min_mesh_size: the minimum mesh element size to use in Gmsh. Passed - into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size) - max_mesh_size: the maximum mesh element size to use in Gmsh. Passed - into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size) - volume_atol: the absolute volume tolerance to allow when matching - parts in the intermediate brep file with the cadquery parts - center_atol: the absolute center coordinates tolerance to allow - when matching parts in the intermediate brep file with the - cadquery parts - bounding_box_atol: the absolute volume tolerance to allow when - matching parts in the intermediate brep file with the cadquery - parts - tags: the dagmc tag to use in when naming the shape in the h5m file. - If left as None then the Shape.name will be used. This allows - the DAGMC geometry created to be compatible with a wider range - of neutronics codes that have specific DAGMC tag requirements. - """ - - if tags is None: - tags = [self.name] - import cadquery as cq - - assembly = cq.Assembly(name="shape") - assembly.add(self.solid) - - # solids could contain compounds - # before accessing the .val() check it exists - if hasattr(self.solid, "val"): - # if it is a compound then we may need more material tags - if isinstance(self.solid.val(), cq.occ_impl.shapes.Compound): - required_num_tags = len(self.solid.val().Solids()) - else: - required_num_tags = 1 - elif isinstance(self.solid, cq.occ_impl.shapes.Compound): - required_num_tags = len(self.solid.Solids()) - else: - required_num_tags = 1 - - if len(tags) != required_num_tags: - tags = tags * required_num_tags - - output_filename = export_solids_to_dagmc_h5m( - solids=assembly, - filename=filename, - min_mesh_size=min_mesh_size, - max_mesh_size=max_mesh_size, - verbose=verbose, - volume_atol=volume_atol, - center_atol=center_atol, - bounding_box_atol=bounding_box_atol, - tags=tags, - ) - - return output_filename - - def export_stp( - self, - filename: str, - units: Optional[str] = "mm", - mode: Optional[str] = "solid", - verbose: Optional[bool] = True, - ) -> str: - """Exports an stp file for the Shape.solid. - - Args: - filename: the filename of exported the stp file. - units: the units of the stp file, options are 'cm' or 'mm'. - Default is mm. - mode: the object to export can be either - 'solid' which exports 3D solid shapes or the 'wire' which - exports the wire edges of the shape. Defaults to 'solid'. - verbose: Enables (True) or disables (False) the printing of the - file produced. - """ - - path_filename = Path(filename) - - if path_filename.suffix == ".stp" or path_filename.suffix == ".step": - pass - else: - msg = f"filename should end with .stp or .step, not {path_filename.suffix}" - raise ValueError(msg) - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - if mode == "solid": - - assembly = Assembly(name=self.name) - - if self.color is None: - assembly.add(self.solid) - else: - assembly.add(self.solid, color=Color(*self.color)) - - assembly.save(str(path_filename), exportType="STEP") - - # previous method does not support colours but puts the solid in the base file level - # exporters.export(self.solid, str(path_filename), exportType='STEP') - - elif mode == "wire": - exporters.export(self.wire, str(path_filename), exportType="STEP") - else: - raise ValueError( - "The mode argument for export_stp \ - only accepts 'solid' or 'wire'", - self, - ) - - if units == "cm": - _replace( - str(path_filename), - "SI_UNIT(.MILLI.,.METRE.)", - "SI_UNIT(.CENTI.,.METRE.)", - ) - - if verbose: - print(f"Saved file as {path_filename}") - - return str(path_filename) - - def export_svg( - self, - filename: Optional[str] = "shape.svg", - projectionDir: Tuple[float, float, float] = (-1.75, 1.1, 5), - width: Optional[float] = 800, - height: Optional[float] = 800, - marginLeft: Optional[float] = 100, - marginTop: Optional[float] = 100, - strokeWidth: Optional[float] = None, - strokeColor: Optional[Tuple[int, int, int]] = (0, 0, 0), - hiddenColor: Optional[Tuple[int, int, int]] = (100, 100, 100), - showHidden: Optional[bool] = True, - showAxes: Optional[bool] = False, - ) -> str: - """Exports an svg file for the Reactor.solid. If the filename provided - doesn't end with .svg it will be added. - - Args: - filename: the filename of the svg file to be exported. Defaults to - "reactor.svg". - projectionDir: The direction vector to view the geometry from - (x, y, z). Defaults to (-1.75, 1.1, 5) - width: the width of the svg image produced in pixels. Defaults to - 1000 - height: the height of the svg image produced in pixels. Defaults to - 800 - marginLeft: the number of pixels between the left edge of the image - and the start of the geometry. - marginTop: the number of pixels between the top edge of the image - and the start of the geometry. - strokeWidth: the width of the lines used to draw the geometry. - Defaults to None which automatically selects an suitable width. - strokeColor: the color of the lines used to draw the geometry in - RGB format with each value between 0 and 255. Defaults to - (0, 0, 0) which is black. - hiddenColor: the color of the lines used to draw the geometry in - RGB format with each value between 0 and 255. Defaults to - (100, 100, 100) which is light grey. - showHidden: If the edges obscured by geometry should be included in - the diagram. Defaults to True. - showAxes: If the x, y, z axis should be included in the image. - Defaults to False. - - Returns: - str: the svg filename created - """ - - path_filename = Path(filename) - - if path_filename.suffix != ".svg": - path_filename = path_filename.with_suffix(".svg") - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - opt = { - "width": width, - "height": height, - "marginLeft": marginLeft, - "marginTop": marginTop, - "showAxes": showAxes, - "projectionDir": projectionDir, - "strokeColor": strokeColor, - "hiddenColor": hiddenColor, - "showHidden": showHidden, - } - - if strokeWidth is not None: - opt["strokeWidth"] = strokeWidth - - exporters.export(self.solid, str(path_filename), exportType="SVG", opt=opt) - - print("Saved file as ", path_filename) - - return str(path_filename) - - def export_html_3d(self, filename: Optional[str] = "shape_3d.html", **kwargs): - """Saves an interactive 3d html view of the Shape to a html file. - - Args: - filename: the filename used to save the html graph. Defaults to - shape_3d.html - kwargs: keyword arguments passed to jupyter-cadquery show() - function. See https://github.com/bernhard-42/jupyter-cadquery#usage - for more details on acceptable keywords - - Returns: - str: filename of the created html file - """ - - view = self.show(**kwargs) - - view.export_html(filename) - - return filename - - def export_html( - self, - filename: str = "shape.html", - facet_splines: bool = True, - facet_circles: bool = True, - tolerance: float = 1e-3, - view_plane: Optional[str] = None, - ): - """Creates a html graph representation of the points and connections - for the Shape object. Shapes are colored by their .color property. - Shapes are also labelled by their .name. If filename provided doesn't - end with .html then .html will be added. - - Args: - filename: the filename used to save the html graph. Defaults to - shape.html - facet_splines: If True then spline edges will be faceted. Defaults - to True. - facet_circles: If True then circle edges will be faceted. Defaults - to True. - tolerance: faceting toleranceto use when faceting cirles and - splines. Defaults to 1e-3. - view_plane: The plane to project. Options are 'XZ', 'XY', 'YZ', - 'YX', 'ZY', 'ZX', 'RZ' and 'XYZ'. Defaults to 'RZ'. Defaults to - the workplane of the paramak.Shape. - - Returns: - plotly.Figure(): figure object - """ - - # if view plane is not set then use the shape workplane - if view_plane is None: - view_plane = self.workplane - - if self.solid is None: - raise ValueError("No solid was found for ", self) - - if isinstance(self.solid, Workplane): - edges = self.solid.val().Edges() - else: - edges = self.solid.Edges() - - fig = paramak.utils.export_wire_to_html( - wires=edges, - filename=None, - view_plane=view_plane, - facet_splines=facet_splines, - facet_circles=facet_circles, - tolerance=tolerance, - title=f"coordinates of {self.__class__.__name__} shape, viewed from the {view_plane} plane", - ) - - if filename is not None: - - Path(filename).parents[0].mkdir(parents=True, exist_ok=True) - - path_filename = Path(filename) - - if path_filename.suffix != ".html": - path_filename = path_filename.with_suffix(".html") - - fig.write_html(str(path_filename)) - - return fig - - def export_2d_image( - self, - filename: Optional[str] = "shape.png", - xmin: Optional[float] = 0.0, - xmax: Optional[float] = 900.0, - ymin: Optional[float] = -600.0, - ymax: Optional[float] = 600.0, - ): - """Exports a 2d image (png) of the reactor. Components are colored by - their Shape.color property. If filename provided doesn't end with .png - then .png will be added. - - Args: - filename: the filename of the saved png image. - xmin: the minimum x value of the x axis. - Defaults to 0.. - xmax: the maximum x value of the x axis. - Defaults to 900.. - ymin: the minimum y value of the y axis. - Defaults to -600.. - ymax: the maximum y value of the y axis. - Defaults to 600.. - - Returns: - matplotlib.plt(): a plt object - """ - - fig, ax = plt.subplots() - - patch = self._create_patch() - - ax.add_collection(patch) - - ax.axis("equal") - ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax)) - ax.set_aspect("equal", "box") - - plt.savefig(filename, dpi=100) - plt.close() - print( - f"\n saved 2d image to {filename}", - ) - - return plt - - def _create_patch(self): - """Creates a matplotlib polygon patch from the Shape points. This is - used when making 2d images of the Shape object. - - Raises: - ValueError: No points defined for the Shape - - Returns: - Matplotlib object patch: a plotable polygon shape - """ - - if self.processed_points is None: - raise ValueError("No processed_points defined for", self) - - patches = [] - - edges = facet_wire(wire=self.wire, facet_splines=True, facet_circles=True) - - fpoints = [] - for edge in edges: - for vertice in edge.Vertices(): - fpoints.append((vertice.X, vertice.Z)) - - polygon = Polygon(fpoints, closed=True) - patches.append(polygon) - - patch = PatchCollection(patches) - - if self.color is not None: - print("color is ", self.color) - patch.set_facecolor(self.color[0:3]) - patch.set_color(self.color[0:3]) - patch.color = self.color[0:3] - patch.edgecolor = self.color[0:3] - # checks to see if an alpha value is provided in the color - if len(self.color) == 4: - patch.set_alpha = self.color[-1] - self.patch = patch - return patch - - def perform_boolean_operations(self, solid: Workplane, **kwargs): - """Performs boolean cut, intersect and union operations if shapes are - provided""" - - # If a cut solid is provided then perform a boolean cut - if self.cut is not None: - solid = cut_solid(solid, self.cut) - - # If a wedge cut is provided then perform a boolean cut - # Performed independently to avoid use of self.cut - # Prevents repetition of 'outdated' wedge cuts - if "wedge_cut" in kwargs: - if kwargs["wedge_cut"] is not None: - solid = cut_solid(solid, kwargs["wedge_cut"]) - - # If an intersect is provided then perform a boolean intersect - if self.intersect is not None: - solid = intersect_solid(solid, self.intersect) - - # If an intersect is provided then perform a boolean intersect - if self.union is not None: - solid = union_solid(solid, self.union) - - return solid - - def convert_all_circle_connections_to_splines( - self, tolerance: Optional[float] = 0.1 - ) -> List[Tuple[float, float, str]]: - """Replaces circle edges in Shape.processed_points points with spline - edges. The spline control coordinates are obtained by faceting the - circle edge with the provided tolerance. The Shape.processed_points - will be updated to exclude the circle points and include the new spline - points. This method works best when the connection before and after the - circle is a straight connection type. This method is useful when - converting the stp file into other formats due to errors in the - conversion of circle edges. - - Args: - tolerance: the precision of the faceting. - - Returns: - The new points with spline connections - """ - - new_points = [] - counter = 0 - while counter < len(self.processed_points): - - if self.processed_points[counter][2] == "circle": - p_0 = self.processed_points[counter][:2] - p_1 = self.processed_points[counter + 1][:2] - p_2 = self.processed_points[counter + 2][:2] - - points = paramak.utils.convert_circle_to_spline(p_0, p_1, p_2, tolerance=tolerance) - - # the last point needs to have the connection type of p2 - for point in points[:-1]: - new_points.append((point[0], point[1], "spline")) - - new_points.append(self.processed_points[counter + 2]) - counter = counter + 3 - else: - new_points.append(self.processed_points[counter]) - counter = counter + 1 - - # @jon I'm not 100% if this change is correct or not - self.processed_points = new_points - return new_points - - def volume(self, split_compounds: bool = False) -> Union[float, List[float]]: - """Get the total volume of the Shape. - - Args: - split_compounds: If the Shape is a compound of Shapes and therefore - contains multiple volumes. This option allows access to the - separate volumes of each component within a Shape (True) or the - volumes of compounds can be summed (False). - - Returns: - The the volume(s) of the Shape - """ - - if not isinstance(split_compounds, bool): - msg = f"split_compounds must be True or False. Not {split_compounds}" - raise ValueError(msg) - - # returns a list of floats - if split_compounds: - all_volumes = [] - if isinstance(self.solid, Compound): - for solid in self.solid.Solids(): - all_volumes.append(solid.Volume()) - return all_volumes - - return [self.solid.val().Volume()] - - # returns a float - - if isinstance(self.solid, Compound): - return self.solid.Volume() - - return self.solid.val().Volume() diff --git a/src/paramak/utils.py b/src/paramak/utils.py deleted file mode 100644 index e06bcdf40..000000000 --- a/src/paramak/utils.py +++ /dev/null @@ -1,961 +0,0 @@ -import math -from collections.abc import Iterable -from hashlib import blake2b -from os import fdopen, remove -from pathlib import Path -from shutil import copymode, move -from tempfile import mkstemp -from typing import List, Optional, Tuple, Union - -import cadquery as cq -import numpy as np -import plotly.graph_objects as go -from cadquery import importers -from OCP.GCPnts import GCPnts_QuasiUniformDeflection -from cadquery.occ_impl import shapes -import OCP - - -def export_solids_to_brep_object( - solids: Iterable, -): - """Returns a brep object from a iterable of solids with merged surfaces. - - Args: - solids: a list of cadquery solids - - Returns: - brep cadquery object - """ - - bldr = OCP.BOPAlgo.BOPAlgo_Splitter() - - if len(solids) == 1: - return solids[0].val() - - for solid in solids: - # checks if solid is a compound as .val() is not needed for compounds - if isinstance(solid, cq.occ_impl.shapes.Compound): - bldr.AddArgument(solid.wrapped) - else: - bldr.AddArgument(solid.val().wrapped) - - bldr.SetNonDestructive(True) - - bldr.Perform() - - bldr.Images() - - merged_solid = cq.Compound(bldr.Shape()) - - return merged_solid - - -def export_solids_to_brep( - solids: Iterable, - filename: str = "reactor.brep", -): - """Exports a brep file for the Reactor.solid. - - Args: - solids: a list of cadquery solids - filename: the filename of exported the brep file. - - Returns: - filename of the brep created - """ - - path_filename = Path(filename) - - if path_filename.suffix != ".brep": - msg = "When exporting a brep file the filename must end with .brep" - raise ValueError(msg) - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - merged_solid = export_solids_to_brep_object(solids) - - merged_solid.exportBrep(str(path_filename)) - - return str(path_filename) - - -def export_solids_to_dagmc_h5m( - solids, - filename: str = "dagmc.h5m", - min_mesh_size: float = 5, - max_mesh_size: float = 20, - verbose: bool = True, - volume_atol: float = 0.000001, - center_atol: float = 0.000001, - bounding_box_atol: float = 0.000001, - tags: List[str] = None, -): - - # a local import is used here as these packages need Moab to work - from cad_to_dagmc import CadToDagmc - - my_model = CadToDagmc() - - my_model.add_cadquery_object(cadquery_object=solids, material_tags=tags) - - my_model.export_dagmc_h5m_file(max_mesh_size=max_mesh_size, min_mesh_size=min_mesh_size, filename=filename) - - return filename - - -def get_bounding_box(solid) -> Tuple[Tuple[float, float, float], Tuple[float, float, float]]: - """Calculates a bounding box for the Shape and returns the coordinates of - the corners lower-left and upper-right. This function is useful when - creating OpenMC mesh tallies as the bounding box is required in this form""" - - if isinstance(solid, (cq.Compound, shapes.Solid)): - - bound_box = solid.BoundingBox() - # previous method lopped though solids but this is not needed - # for single_solid in solid.Solids(): - # bound_box = single_solid.BoundingBox() - - else: - bound_box = solid.val().BoundingBox() - - lower_left = (bound_box.xmin, bound_box.ymin, bound_box.zmin) - - upper_right = (bound_box.xmax, bound_box.ymax, bound_box.zmax) - - return (lower_left, upper_right) - - -def get_center_of_bounding_box(solid): - """Calculates the geometric center of the solids bounding box""" - - bounding_box = get_bounding_box(solid) - - center = ( - (bounding_box[0][0] + bounding_box[1][0]) / 2, - (bounding_box[0][1] + bounding_box[1][1]) / 2, - (bounding_box[0][2] + bounding_box[1][2]) / 2, - ) - - return center - - -def get_largest_dimension(solid): - """Calculates the extent of the geometry in the x,y and z axis and returns - the largest of the three.""" - - bounding_box = get_bounding_box(solid) - - largest_dimension = max( - abs(bounding_box[0][0] - bounding_box[0][1]), - abs(bounding_box[0][2] - bounding_box[1][0]), - abs(bounding_box[1][1] - bounding_box[1][2]), - ) - - return largest_dimension - - -def get_largest_distance_from_origin(solid): - """Calculates the distance from (0, 0, 0) to the furthest part of - the geometry. This distance is returned as an positive value.""" - - bounding_box = get_bounding_box(solid) - - largest_dimension = max( - ( - abs(bounding_box[0][0]), - abs(bounding_box[0][1]), - abs(bounding_box[0][2]), - abs(bounding_box[1][0]), - abs(bounding_box[1][1]), - abs(bounding_box[1][2]), - ) - ) - - return largest_dimension - - -def transform_curve(edge, tolerance: Optional[float] = 1e-3): - """Converts a curved edge into a series of straight lines (facetets) with - the provided tolerance. - - Args: - edge (cadquery.Wire): The CadQuery wire to redraw as a series of - straight lines (facet) - tolerance: faceting toleranceto use when faceting cirles and - splines. Defaults to 1e-3. - - Returns: - cadquery.Wire - """ - - curve = edge._geomAdaptor() # adapt the edge into curve - start = curve.FirstParameter() - end = curve.LastParameter() - - points = GCPnts_QuasiUniformDeflection(curve, tolerance, start, end) - verts = (cq.Vector(points.Value(i + 1)) for i in range(points.NbPoints())) - - return cq.Wire.makePolygon(verts) - - -def facet_wire( - wire, - facet_splines: Optional[bool] = True, - facet_circles: Optional[bool] = True, - tolerance: Optional[float] = 1e-3, -): - """Converts specified curved edge types from a wire into a series of - straight lines (facetets) with the provided tol (tolerance). - - Args: - wire (cadquery.Wire): The CadQuery wire to select edge from which will - be redraw as a series of straight lines (facet). - facet_splines: If True then spline edges will be faceted. Defaults - to True. - facet_splines: If True then circle edges will be faceted.Defaults - to True. - tolerance: faceting toleranceto use when faceting cirles and - splines. Defaults to 1e-3. - - Returns: - cadquery.Wire - """ - edges = [] - - types_to_facet = [] - if facet_splines: - types_to_facet.append("BSPLINE") - if facet_circles: - types_to_facet.append("CIRCLE") - - if isinstance(wire, cq.occ_impl.shapes.Edge): - # this is for when a edge is passed - iterable_of_wires = [wire] - elif isinstance(wire, cq.occ_impl.shapes.Wire): - # this is for imported stp files - iterable_of_wires = wire.Edges() - else: - # this is for cadquery generated solids - iterable_of_wires = wire.val().Edges() - - for edge in iterable_of_wires: - if edge.geomType() in types_to_facet: - edges.extend(transform_curve(edge, tolerance=tolerance).Edges()) - else: - edges.append(edge) - - return edges - - -def coefficients_of_line_from_points(point_a: Tuple[float, float], point_b: Tuple[float, float]) -> Tuple[float, float]: - """Computes the m and c coefficients of the equation (y=mx+c) for - a straight line from two points. - - Args: - point_a: point 1 coordinates - point_b: point 2 coordinates - - Returns: - m coefficient and c coefficient - """ - - points = [point_a, point_b] - x_coords, y_coords = zip(*points) - coord_array = np.vstack([x_coords, np.ones(len(x_coords))]).T - m, c = np.linalg.lstsq(coord_array, y_coords, rcond=None)[0] - return m, c - - -def cut_solid(solid, cutter): - """ - Performs a boolean cut of a solid with another solid or iterable of solids. - - Args: - solid Shape: The Shape that you want to cut from - cutter Shape: The Shape(s) that you want to be the cutting object - - Returns: - Shape: The original shape cut with the cutter shape(s) - """ - - # Allows for multiple cuts to be applied - if isinstance(cutter, Iterable): - for cutting_solid in cutter: - solid = solid.cut(cutting_solid.solid) - else: - solid = solid.cut(cutter.solid) - return solid - - -def diff_between_angles(angle_a: float, angle_b: float) -> float: - """Calculates the difference between two angles angle_a and angle_b - - Args: - angle_a (float): angle in degree - angle_b (float): angle in degree - - Returns: - float: difference between the two angles in degree. - """ - - delta_mod = (angle_b - angle_a) % 360 - if delta_mod > 180: - delta_mod -= 360 - return delta_mod - - -def angle_between_two_points_on_circle( - point_1: Tuple[float, float], point_2: Tuple[float, float], radius_of_circle: float -): - - separation = distance_between_two_points(point_1, point_2) - isos_tri_term = (2 * math.pow(radius_of_circle, 2) - math.pow(separation, 2)) / (2 * math.pow(radius_of_circle, 2)) - angle = math.acos(isos_tri_term) - return angle - - -def distance_between_two_points(point_a: Tuple[float, float], point_b: Tuple[float, float]) -> float: - """Computes the distance between two points. - - Args: - point_a (float, float): X, Y coordinates of the first point - point_b (float, float): X, Y coordinates of the second point - - Returns: - float: distance between A and B - """ - - xa, ya = point_a[0], point_a[1] - xb, yb = point_b[0], point_b[1] - u_vec = [xb - xa, yb - ya] - return np.linalg.norm(u_vec) - - -def extend(point_a: Tuple[float, float], point_b: Tuple[float, float], L: float) -> Tuple[float, float]: - """Creates a point C in (ab) direction so that \\|aC\\| = L - - Args: - point_a (float, float): X, Y coordinates of the first point - point_b (float, float): X, Y coordinates of the second point - L (float): distance AC - Returns: - float, float: point C coordinates - """ - - xa, ya = point_a[0], point_a[1] - xb, yb = point_b[0], point_b[1] - u_vec = [xb - xa, yb - ya] - u_vec /= np.linalg.norm(u_vec) - - xc = xa + L * u_vec[0] - yc = ya + L * u_vec[1] - return xc, yc - - -def find_center_point_of_circle( - point_a: Tuple[float, float], - point_b: Tuple[float, float], - point_3: Tuple[float, float], -) -> Union[Tuple[float, float], None]: - """ - Calculates the center of a circle passing through 3 points. - Args: - point_a: point 1 coordinates - point_b: point 2 coordinates - point_3: point 3 coordinates - Returns: - center of the circle coordinates or None if 3 points on a line are - input and the radius - """ - - temp = point_b[0] * point_b[0] + point_b[1] * point_b[1] - bc = (point_a[0] * point_a[0] + point_a[1] * point_a[1] - temp) / 2 - cd = (temp - point_3[0] * point_3[0] - point_3[1] * point_3[1]) / 2 - det = (point_a[0] - point_b[0]) * (point_b[1] - point_3[1]) - (point_b[0] - point_3[0]) * (point_a[1] - point_b[1]) - - if abs(det) < 1.0e-6: - return None - - # Center of circle - cx = (bc * (point_b[1] - point_3[1]) - cd * (point_a[1] - point_b[1])) / det - cy = ((point_a[0] - point_b[0]) * cd - (point_b[0] - point_3[0]) * bc) / det - - return (cx, cy) - - -def find_radius_of_circle( - center_point: Tuple[float, float], - edge_point: Tuple[float, float], -) -> float: - """Calculates the radius of a circle. - - Args: - center_point: x, y coordinates of the center of te circle - edge_point: x, y coordinates of a point on the edge of the circle - Returns: - the radius of the circle - """ - - if center_point == edge_point: - return np.inf - - radius = np.sqrt((center_point[0] - edge_point[0]) ** 2 + (center_point[1] - edge_point[1]) ** 2) - - return radius - - -def intersect_solid(solid, intersecter): - """ - Performs a boolean intersection of a solid with another solid or iterable of - solids. - Args: - solid Shape: The Shape that you want to intersect - intersecter Shape: The Shape(s) that you want to be the intersecting object - Returns: - Shape: The original shape cut with the intersecter shape(s) - """ - - # Allows for multiple cuts to be applied - if isinstance(intersecter, Iterable): - for intersecting_solid in intersecter: - solid = solid.intersect(intersecting_solid.solid) - else: - solid = solid.intersect(intersecter.solid) - return solid - - -def rotate(origin: Tuple[float, float], point: Tuple[float, float], angle: float): - """ - Rotate a point counterclockwise by a given angle around a given origin. - The angle should be given in radians. - - Args: - origin (float, float): coordinates of origin point - point (float, float): coordinates of point to be rotated - angle (float): rotation angle in radians (counterclockwise) - Returns: - float, float: rotated point coordinates. - """ - - ox, oy = origin - px, py = point[0], point[1] - - qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy) - qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy) - return qx, qy - - -def union_solid(solid, joiner): - """ - Performs a boolean union of a solid with another solid or iterable of solids - - Args: - solid (Shape): The Shape that you want to union from - joiner (Shape): The Shape(s) that you want to form the union with the - solid - Returns: - Shape: The original shape union with the joiner shape(s) - """ - - # Allows for multiple unions to be applied - if isinstance(joiner, Iterable): - for joining_solid in joiner: - solid = solid.union(joining_solid.solid) - else: - solid = solid.union(joiner.solid) - return solid - - -def calculate_wedge_cut(self): - """Calculates a wedge cut with the given rotation_angle""" - - if self.rotation_angle == 360: - return None - - from paramak import CuttingWedgeFS - - cutting_wedge = CuttingWedgeFS(self) - return cutting_wedge - - -def add_thickness(x: List[float], y: List[float], thickness: float, dy_dx: List[float] = None) -> Tuple[list, list]: - """Computes outer curve points based on thickness - - Args: - x (list): list of floats containing x values - y (list): list of floats containing y values - thickness (float): thickness of the magnet - dy_dx (list): list of floats containing the first order - derivatives - - Returns: - R and Z lists for outer curve points - """ - - if dy_dx is None: - dy_dx = np.diff(y) / np.diff(x) - - x_outer, y_outer = [], [] - for i in range(len(dy_dx)): - if dy_dx[i] == float("-inf"): - nx, ny = -1, 0 - elif dy_dx[i] == float("inf"): - nx, ny = 1, 0 - else: - nx = -dy_dx[i] - ny = 1 - if i != len(dy_dx) - 1: - if x[i] < x[i + 1]: - convex = False - else: - convex = True - - if convex: - nx *= -1 - ny *= -1 - # normalize normal vector - normal_vector_norm = (nx**2 + ny**2) ** 0.5 - nx /= normal_vector_norm - ny /= normal_vector_norm - # calculate outer points - val_x_outer = x[i] + thickness * nx - val_y_outer = y[i] + thickness * ny - x_outer.append(val_x_outer) - y_outer.append(val_y_outer) - - return x_outer, y_outer - - -def get_hash(shape, ignored_keys: List = None) -> str: - """Computes a unique hash value for the shape. - - Args: - shape (list): The paramak.Shape object to find the hash value for. - ignored_keys (list, optional): list of shape.__dict__ keys to ignore - when creating the hash. - - Returns: - (list, list): R and Z lists for outer curve points - """ - - hash_object = blake2b() - shape_dict = dict(shape.__dict__) - - if ignored_keys is not None: - for key in ignored_keys: - if key in shape_dict.keys(): - shape_dict[key] = None - - hash_object.update(str(list(shape_dict.values())).encode("utf-8")) - value = hash_object.hexdigest() - return value - - -def _replace(filename: str, pattern: str, subst: str) -> None: - """Opens a file and replaces occurrences of a particular string - (pattern)with a new string (subst) and overwrites the file. - Used internally within the paramak to ensure .STP files are - in units of cm not the default mm. - Args: - filename (str): the filename of the file to edit - pattern (str): the string that should be removed - subst (str): the string that should be used in the place of the - pattern string - """ - # Create temp file - file_handle, abs_path = mkstemp() - with fdopen(file_handle, "w") as new_file: - with open(filename) as old_file: - for line in old_file: - new_file.write(line.replace(pattern, subst)) - - # Copy the file permissions from the old file to the new file - copymode(filename, abs_path) - - # Remove original file - remove(filename) - - # Move new file - move(abs_path, filename) - - -def plotly_trace( - points: Union[List[Tuple[float, float]], List[Tuple[float, float, float]]], - mode: str = "markers+lines", - name: str = None, - color: Union[Tuple[float, float, float], Tuple[float, float, float, float]] = None, -) -> Union[go.Scatter, go.Scatter3d]: - """Creates a plotly trace representation of the points of the Shape - object. This method is intended for internal use by Shape.export_html. - - Args: - points: A list of tuples containing the X, Z points of to add to - the trace. - mode: The mode to use for the Plotly.Scatter graph. Options include - "markers", "lines" and "markers+lines". Defaults to - "markers+lines" - name: The name to use in the graph legend color - - Returns: - plotly trace: trace object - """ - - if color is None: - color_string = "rgb(125, 125, 125)" - else: - color_list = [i * 255 for i in color] - - if len(color_list) == 3: - color_string = "rgb(" + str(color_list).strip("[]") + ")" - elif len(color_list) == 4: - color_string = "rgba(" + str(color_list).strip("[]") + ")" - - if name is None: - name = "Shape not named" - else: - name = name - - text_values = [] - - for i, point in enumerate(points): - text = f"point number= {i}
x={point[0]}
y= {point[1]}" - if len(point) == 3: - text = text + f"
z= {point[2]}
" - - text_values.append(text) - - if all(len(entry) == 3 for entry in points): - trace = go.Scatter3d( - x=[row[0] for row in points], - y=[row[1] for row in points], - z=[row[2] for row in points], - mode=mode, - marker={"size": 3, "color": color_string}, - name=name, - ) - - return trace - - trace = go.Scatter( - x=[row[0] for row in points], - y=[row[1] for row in points], - hoverinfo="text", - text=text_values, - mode=mode, - marker={"size": 5, "color": color}, - name=name, - ) - - return trace - - -def extract_points_from_edges( - edges: Union[List[cq.Wire], cq.Wire], - view_plane: Optional[str] = "XZ", -) -> Union[Tuple[float, float, float], Tuple[float, float]]: - """Extracts points (coordinates) from a CadQuery Edge, optionally projects - the points to a plane and returns the points. - - Args: - edges (CadQuery.Wires): The edges to extract points (coordinates from). - view_plane: The axis to view the points and faceted edges from. The - options are 'XZ', 'XY', 'YZ', 'YX', 'ZY', 'ZX', 'RZ' and 'XYZ'. - Defaults to 'RZ'. - - Returns: - List of Tuples: A list of tuples with float entries for every point - """ - - if isinstance(edges, Iterable): - list_of_edges = edges - else: - list_of_edges = [edges] - - points = [] - - for edge in list_of_edges: - for vertex in edge.Vertices(): - if view_plane == "XZ": - points.append((vertex.X, vertex.Z)) - elif view_plane == "XY": - points.append((vertex.X, vertex.Y)) - elif view_plane == "YZ": - points.append((vertex.Y, vertex.Z)) - elif view_plane == "YX": - points.append((vertex.Y, vertex.X)) - elif view_plane == "ZY": - points.append((vertex.Z, vertex.Y)) - elif view_plane == "ZX": - points.append((vertex.Z, vertex.X)) - elif view_plane == "RZ": - xy_coord = math.pow(vertex.X, 2) + math.pow(vertex.Y, 2) - points.append((math.sqrt(xy_coord), vertex.Z)) - elif view_plane == "XYZ": - points.append((vertex.X, vertex.Y, vertex.Z)) - else: - raise ValueError("view_plane value of ", view_plane, " is not supported") - return points - - -def load_stp_file(filename: str, scale_factor: float = 1.0): - """Loads a stp file and makes the 3D solid and wires available for use. - - Args: - filename: the filename used to save the html graph. - scale_factor: a scaling factor to apply to the geometry that can be - used to increase the size or decrease the size of the geometry. - Useful when converting the geometry to cm for use in neutronics - simulations. - - Returns: - CadQuery.solid, CadQuery.Wires: solid and wires belonging to the object - """ - - part = importers.importStep(str(filename)).val() - - scaled_part = part.scale(scale_factor) - solid = scaled_part - wire = scaled_part.Wires() - return solid, wire - - -def export_wire_to_html( - wires, - filename=None, - view_plane: str = "RZ", - facet_splines: bool = True, - facet_circles: bool = True, - tolerance: float = 1e-3, - title: Optional[str] = None, - mode="markers+lines", -): - """Creates a html graph representation of the points within the wires. - Edges of certain types (spines and circles) can optionally be faceted. - If filename provided doesn't end with .html then .html will be added. - Viewed from the XZ plane - - Args: - wires (CadQuery.Wire): the wire (edge) or list of wires to plot points - from and to optionally facet. - filename: the filename used to save the html graph. If None then no - html file will saved but a ploty figure will still be returned. - Defaults to None. - view_plane: The axis to view the points and faceted edges from. The - options are 'XZ', 'XY', 'YZ', 'YX', 'ZY', 'ZX', 'RZ' and 'XYZ'. - Defaults to 'RZ' - facet_splines: If True then spline edges will be faceted. Defaults to - True. - facet_circles: If True then circle edges will be faceted. Defaults to - True. - tolerance: faceting toleranceto use when faceting cirles and splines. - Defaults to 1e-3. - title: the title of the plotly plot. - mode: the plotly trace mode to use when plotting the data. Options - include 'markers+lines', 'markers', 'lines'. Defaults to 'lines'. - - Returns: - plotly.Figure(): figure object - """ - - fig = go.Figure() - fig.update_layout(title=title, hovermode="closest") - - if view_plane == "XYZ": - fig.update_layout( - title=title, - scene_aspectmode="data", - scene=dict( - xaxis_title=view_plane[0], - yaxis_title=view_plane[1], - zaxis_title=view_plane[2], - ), - ) - else: - - fig.update_layout( - yaxis=dict(scaleanchor="x", scaleratio=1), - xaxis_title=view_plane[0], - yaxis_title=view_plane[1], - ) - - if isinstance(wires, list): - list_of_wires = wires - else: - list_of_wires = [wires] - - for counter, wire in enumerate(list_of_wires): - - edges = facet_wire( - wire=wire, - facet_splines=facet_splines, - facet_circles=facet_circles, - tolerance=tolerance, - ) - - points = extract_points_from_edges(edges=edges, view_plane=view_plane) - - fig.add_trace(plotly_trace(points=points, mode=mode, name="edge " + str(counter))) - - for counter, wire in enumerate(list_of_wires): - - if isinstance(wire, cq.occ_impl.shapes.Edge): - # this is for when an edge is passed - edges = wire - elif isinstance(wire, cq.occ_impl.shapes.Wire): - # this is for imported stp files - edges = wire.Edges() - else: - # this is for cadquery generated solids - edges = wire.val().Edges() - - points = extract_points_from_edges(edges=edges, view_plane=view_plane) - - fig.add_trace(plotly_trace(points=points, mode="markers", name="points on wire " + str(counter))) - - if filename is not None: - - Path(filename).parents[0].mkdir(parents=True, exist_ok=True) - - path_filename = Path(filename) - - if path_filename.suffix != ".html": - path_filename = path_filename.with_suffix(".html") - - fig.write_html(str(path_filename)) - - print("Exported html graph to ", path_filename) - - return fig - - -def convert_circle_to_spline( - p_0: Tuple[float, float], - p_1: Tuple[float, float], - p_2: Tuple[float, float], - tolerance: Optional[float] = 0.1, -) -> List[Tuple[float, float, str]]: - """Converts three points on the edge of a circle into a series of points - on the edge of the circle. This is done by creating a circle edge from the - the points provided (p_0, p_1, p_2), facets the circle with the provided - tolerance to extracts the points on the faceted edge and returns them. - - Args: - p_0: coordinates of the first point - p_1: coordinates of the second point - p_2: coordinates of the third point - tolerance: the precision of the faceting. - - Returns: - The new points - """ - - # work plane is arbitrarily selected and has no impact of function - solid = cq.Workplane("XZ").center(0, 0) - solid = solid.moveTo(p_0[0], p_0[1]).threePointArc(p_1, p_2) - edge = solid.vals()[0] - - new_edge = transform_curve(edge, tolerance=tolerance) - - points = extract_points_from_edges(edges=new_edge, view_plane="XZ") - - return points - - -class FaceAreaSelector(cq.Selector): - """A custom CadQuery selector the selects faces based on their area with a - tolerance. The following useage example will fillet the faces of an extrude - shape with an area of 0.5. paramak.ExtrudeStraightShape(points=[(1,1), - (2,1), (2,2)], distance=5).solid.faces(FaceAreaSelector(0.5)).fillet(0.1) - - Args: - area (float): The area of the surface to select. - tolerance (float, optional): The allowable tolerance of the length - (+/-) while still being selected by the custom selector. - """ - - def __init__(self, area, tolerance=0.1): - self.area = area - self.tolerance = tolerance - - def filter(self, object_list): - """Loops through all the faces in the object checking if the face - meets the custom selector requirements or not. - - Args: - object_list (cadquery): The object to filter the faces from. - - Returns: - object_list (cadquery): The face that match the selector area within - the specified tolerance. - """ - - new_obj_list = [] - for obj in object_list: - face_area = obj.Area() - - # Only return faces that meet the requirements - if face_area > self.area - self.tolerance and face_area < self.area + self.tolerance: - new_obj_list.append(obj) - - return new_obj_list - - -class EdgeLengthSelector(cq.Selector): - """A custom CadQuery selector the selects edges based on their length with - a tolerance. The following useage example will fillet the inner edge of a - rotated triangular shape. paramak.RotateStraightShape(points=[(1,1),(2,1), - (2,2)]).solid.edges(paramak.EdgeLengthSelector(6.28)).fillet(0.1) - - Args: - length (float): The length of the edge to select. - tolerance (float, optional): The allowable tolerance of the length - (+/-) while still being selected by the custom selector. - - """ - - def __init__(self, length: float, tolerance: float = 0.1): - self.length = length - self.tolerance = tolerance - - def filter(self, object_list): - """Loops through all the edges in the object checking if the edge - meets the custom selector requirements or not. - - Args: - object_list (cadquery): The object to filter the edges from. - - Returns: - object_list (cadquery): The edge that match the selector length - within the specified tolerance. - """ - - new_obj_list = [] - print("filleting edge#") - for obj in object_list: - - edge_len = obj.Length() - - # Only return edges that meet our requirements - if edge_len > self.length - self.tolerance and edge_len < self.length + self.tolerance: - - new_obj_list.append(obj) - print("length(new_obj_list)", len(new_obj_list)) - return new_obj_list - - -def patch_workplane(): - """Going from CadQuery 2.1 to 2.2, the 'distance' arg to extrude was renamed 'until'. - This patch ensures that either version works fine using 'until'. - """ - from cadquery import Workplane - - if "distance" in Workplane.extrude.__code__.co_varnames: - extrude_func = Workplane.extrude - - def extrude(*args, **kwargs): - if "until" in kwargs.keys(): - kwargs["distance"] = kwargs.pop("until") - return extrude_func(*args, **kwargs) - - Workplane.extrude = extrude diff --git a/tests/tests_examples/__init__.py b/tests/tests_examples/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/tests_examples/test_examples.py b/tests/tests_examples/test_examples.py deleted file mode 100644 index af3533971..000000000 --- a/tests/tests_examples/test_examples.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest -import nbformat -import platform -from nbconvert.preprocessors import ExecutePreprocessor -from nbconvert.preprocessors.execute import CellExecutionError -from pathlib import Path - - -def notebook_run(path): - """ - Execute a notebook via nbconvert and collect output. - :returns (parsed nb object, execution errors) - """ - kernel_name = "python%s" % platform.python_version_tuple()[0] - - with open(path) as file: - note_book = nbformat.read(file, as_version=4) - note_book.metadata.get("kernelspec", {})["name"] = kernel_name - ep = ExecutePreprocessor(kernel_name=kernel_name, timeout=800) - - try: - ep.preprocess(note_book) - - except CellExecutionError as e: - if "SKIP" in e.traceback: - print(str(e.traceback).split("\n")[-2]) - else: - raise e - - -@pytest.mark.parametrize( - "notebook", - Path().rglob("examples/*/*.ipynb"), - ids=lambda x: x.stem, -) -def test_example(notebook): - notebook_run(notebook) diff --git a/tests/tests_h5m/__init__.py b/tests/tests_h5m/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/tests_h5m/test_reactor_export_h5m.py b/tests/tests_h5m/test_reactor_export_h5m.py deleted file mode 100644 index e36569fc1..000000000 --- a/tests/tests_h5m/test_reactor_export_h5m.py +++ /dev/null @@ -1,113 +0,0 @@ -import pytest -from pathlib import Path - -import dagmc_h5m_file_inspector as di -import paramak - - -@pytest.fixture -def reactor_1(): - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], name="test_shape") - - test_shape_3 = paramak.PoloidalFieldCoilSet(heights=[2, 2], widths=[3, 3], center_points=[(50, -100), (50, 100)]) - - # this reactor has a compound shape in the geometry - test_reactor_compound = paramak.Reactor([test_shape, test_shape_3]) - return test_reactor_compound - - -@pytest.fixture -def reactor_2(): - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], name="test_shape") - test_shape2 = paramak.ExtrudeStraightShape( - points=[(100, 100), (50, 100), (50, 50)], distance=20, name="test_shape2" - ) - reactor_2 = paramak.Reactor([test_shape, test_shape2]) - return reactor_2 - - -def test_dagmc_h5m_custom_tags_export(reactor_1, reactor_2): - """Exports a reactor with two shapes checks that the tags are correctly - named in the resulting h5m file""" - - reactor_1.rotation_angle = 180 - reactor_1.export_dagmc_h5m("dagmc_reactor.h5m", tags=["1", "2"]) - - vols = di.get_volumes_from_h5m("dagmc_reactor.h5m") - assert vols == [1, 2, 3] # there are three volumes in reactor_1 - - mats = di.get_materials_from_h5m("dagmc_reactor.h5m") - assert mats == ["1", "2"] - - vols_and_mats = di.get_volumes_and_materials_from_h5m("dagmc_reactor.h5m") - assert vols_and_mats == { - 1: "1", - 2: "2", - 3: "2", - } - - # default shape names used as tags - reactor_2.export_dagmc_h5m("reactor_2.h5m") - assert di.get_volumes_and_materials_from_h5m("reactor_2.h5m") == { - 1: "test_shape", - 2: "test_shape2", - } - - -def test_dagmc_h5m_export(reactor_1): - """Exports a reactor with two shapes checks that the tags are correctly - named in the resulting h5m file""" - - reactor_1.rotation_angle = 180 - reactor_1.export_dagmc_h5m("dagmc_reactor.h5m") - - vols = di.get_volumes_from_h5m("dagmc_reactor.h5m") - assert vols == [1, 2, 3] # there are two shapes three volumes in reactor_1 - - mats = di.get_materials_from_h5m("dagmc_reactor.h5m") - print(mats) - assert mats == ["pf_coil", "test_shape"] - - vols_and_mats = di.get_volumes_and_materials_from_h5m("dagmc_reactor.h5m") - assert vols_and_mats == { - 1: "test_shape", - 2: "pf_coil", - 3: "pf_coil", - } - - -def test_dagmc_h5m_export_mesh_size(reactor_1): - """Exports h5m file with higher resolution mesh and checks that the - file sizes increases""" - - reactor_1.export_dagmc_h5m("dagmc_default.h5m", min_mesh_size=10, max_mesh_size=20) - reactor_1.export_dagmc_h5m("dagmc_bigger.h5m", min_mesh_size=2, max_mesh_size=9) - - assert Path("dagmc_bigger.h5m").stat().st_size > Path("dagmc_default.h5m").stat().st_size - - -def test_dagmc_h5m_export_error_handling(reactor_1): - """Exports a shape with the wrong amount of tags""" - - with pytest.raises(ValueError): - reactor_1.rotation_angle = 180 - reactor_1.export_dagmc_h5m("dagmc_reactor.h5m", tags=["1"]) - - with pytest.raises(ValueError): - reactor_1.rotation_angle = 180 - reactor_1.export_dagmc_h5m("dagmc_reactor.h5m", tags=["1", "2", "3"]) - - -def test_center_column_study_reactor(): - """Exports the CenterColumnStudyReactor with default parameters""" - reactor = paramak.CenterColumnStudyReactor() - reactor.export_dagmc_h5m("CenterColumnStudyReactor.h5m") - assert di.get_volumes_and_materials_from_h5m("CenterColumnStudyReactor.h5m") == { - 1: "plasma", - 2: "inboard_tf_coils", - 3: "center_column_shield", - 4: "inboard_first_wall", - 5: "blanket", - 6: "divertor", - 7: "divertor", - } diff --git a/tests/tests_h5m/test_rotate_straight_shape_export_h5m.py b/tests/tests_h5m/test_rotate_straight_shape_export_h5m.py deleted file mode 100644 index 6423ed602..000000000 --- a/tests/tests_h5m/test_rotate_straight_shape_export_h5m.py +++ /dev/null @@ -1,102 +0,0 @@ -from pathlib import Path - -import dagmc_h5m_file_inspector as di -from paramak import RotateStraightShape - - -def test_dagmc_h5m_export_multi_volume(): - """Exports a shape with multiple volumes and checks that they all - exist (volume ids and material tags) in the resulting h5m file""" - - test_shape = RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)]) - test_shape.rotation_angle = 10 - test_shape.azimuth_placement_angle = [0, 90, 180, 270] - test_shape.name = "my_material_name" - test_shape.export_dagmc_h5m("dagmc_multi_volume.h5m") - - vols = di.get_volumes_from_h5m("dagmc_multi_volume.h5m") - assert vols == [1, 2, 3, 4] - - mats = di.get_materials_from_h5m("dagmc_multi_volume.h5m") - assert mats == ["my_material_name"] - - vols_and_mats = di.get_volumes_and_materials_from_h5m("dagmc_multi_volume.h5m") - assert vols_and_mats == { - 1: "my_material_name", - 2: "my_material_name", - 3: "my_material_name", - 4: "my_material_name", - } - - -def test_dagmc_h5m_export_custom_tag_multi_volume(): - """Exports a shape with multiple volumes and checks that they all - exist (volume ids and material tags) in the resulting h5m file""" - - test_shape = RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)]) - test_shape.rotation_angle = 10 - test_shape.azimuth_placement_angle = [0, 90, 180, 270] - test_shape.name = "my_material_name" - test_shape.export_dagmc_h5m("dagmc_multi_volume.h5m", tags=["1"]) - - vols = di.get_volumes_from_h5m("dagmc_multi_volume.h5m") - assert vols == [1, 2, 3, 4] - - mats = di.get_materials_from_h5m("dagmc_multi_volume.h5m") - assert mats == ["1"] - - vols_and_mats = di.get_volumes_and_materials_from_h5m("dagmc_multi_volume.h5m") - assert vols_and_mats == { - 1: "1", - 2: "1", - 3: "1", - 4: "1", - } - - -def test_dagmc_h5m_export_single_volume(): - """Exports a shape with a single volume and checks that it - exist (volume id and material tag) in the resulting h5m file""" - - test_shape = RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)]) - test_shape.rotation_angle = 180 - test_shape.name = "my_material_name_single" - test_shape.export_dagmc_h5m("dagmc_single_volume.h5m") - - vols = di.get_volumes_from_h5m("dagmc_single_volume.h5m") - assert vols == [1] - - mats = di.get_materials_from_h5m("dagmc_single_volume.h5m") - assert mats == ["my_material_name_single"] - - vols_and_mats = di.get_volumes_and_materials_from_h5m("dagmc_single_volume.h5m") - assert vols_and_mats == {1: "my_material_name_single"} - - -def test_dagmc_h5m_export_single_volume_custom_tags(): - """Exports a shape with a single volume and checks that it - exist (volume id and custom material tag) in the resulting h5m file""" - - test_shape = RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)]) - test_shape.rotation_angle = 180 - test_shape.export_dagmc_h5m("dagmc_custom_tag_single_volume.h5m", tags=["1"]) - - vols = di.get_volumes_from_h5m("dagmc_custom_tag_single_volume.h5m") - assert vols == [1] - - mats = di.get_materials_from_h5m("dagmc_custom_tag_single_volume.h5m") - assert mats == ["1"] - - vols_and_mats = di.get_volumes_and_materials_from_h5m("dagmc_single_volume.h5m") - assert vols_and_mats == {1: "my_material_name_single"} - - -def test_dagmc_h5m_export_mesh_size(): - """Exports h5m file with higher resolution mesh and checks that the - file sizes increases""" - - test_shape = RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)]) - test_shape.export_dagmc_h5m("dagmc_default.h5m", min_mesh_size=10, max_mesh_size=20) - test_shape.export_dagmc_h5m("dagmc_bigger.h5m", min_mesh_size=2, max_mesh_size=9) - - assert Path("dagmc_bigger.h5m").stat().st_size > Path("dagmc_default.h5m").stat().st_size diff --git a/tests/tests_show/__init__.py b/tests/tests_show/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/tests_show/test_center_column_study_reactor.py b/tests/tests_show/test_center_column_study_reactor.py deleted file mode 100644 index 80139236e..000000000 --- a/tests/tests_show/test_center_column_study_reactor.py +++ /dev/null @@ -1,29 +0,0 @@ -import os -from pathlib import Path - -import paramak - - -def test_html_file_creation(): - """Creates a reactor with exports the step files and check they exist""" - - os.system("rm *.html") - test_reactor = paramak.CenterColumnStudyReactor( - inner_bore_radial_thickness=20, - inboard_tf_leg_radial_thickness=50, - center_column_shield_radial_thickness_mid=50, - center_column_shield_radial_thickness_upper=100, - inboard_firstwall_radial_thickness=20, - divertor_radial_thickness=100, - inner_plasma_gap_radial_thickness=80, - plasma_radial_thickness=200, - outer_plasma_gap_radial_thickness=90, - elongation=2.3, - triangularity=0.45, - plasma_gap_vertical_thickness=40, - center_column_arc_vertical_thickness=520, - rotation_angle=359, - ) - - test_reactor.export_html_3d("cylinder.html") - assert Path("cylinder.html").is_file() diff --git a/tests/tests_show/test_reactor.py b/tests/tests_show/test_reactor.py deleted file mode 100644 index c999d088f..000000000 --- a/tests/tests_show/test_reactor.py +++ /dev/null @@ -1,73 +0,0 @@ -import os -import unittest -from pathlib import Path - -import paramak - - -class TestReactor(unittest.TestCase): - """Tests the show attribute of the Reactor class which requires - jupyter_cadquery""" - - def setUp(self): - self.test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], name="test_shape") - - self.test_shape2 = paramak.ExtrudeStraightShape( - points=[(100, 100), (50, 100), (50, 50)], distance=20, name="test_shape2" - ) - - test_shape_3 = paramak.PoloidalFieldCoilSet( - heights=[2, 2], widths=[3, 3], center_points=[(50, -100), (50, 100)] - ) - - self.test_reactor = paramak.Reactor([self.test_shape]) - - self.test_reactor_2 = paramak.Reactor([self.test_shape, self.test_shape2]) - - # this reactor has a compound shape in the geometry - self.test_reactor_3 = paramak.Reactor([self.test_shape, test_shape_3]) - - def test_export_3d_html(self): - """Checks the 3d html file is exported by the export_html_3d method - with the correct filename""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - test_reactor = paramak.Reactor([test_shape]) - - os.system("rm filename.html") - filename = test_reactor.export_html_3d("filename.html") - if filename is not None: - assert Path("filename.html").exists() is True - - def test_show_runs_without_error(self): - """checks that the jupyter notebook (with cadquery addition) runs - without error.""" - - self.test_reactor.show() - - def test_show_runs_without_error_when_names_are_set(self): - """checks that the jupyter notebook (with cadquery addition) runs - without error even when the .name property is set""" - - self.test_reactor.shapes_and_components[0].name = "test" - self.test_reactor.show() - - def test_show_runs_without_error_when_compounds_are_used(self): - """checks that the jupyter notebook (with cadquery addition) runs - without error even when the .name property is set""" - - test_shape = paramak.PoloidalFieldCoilCaseSet( - heights=[10, 20], - widths=[10, 20], - casing_thicknesses=10, - center_points=[(100, 200), (400, 400)], - name="test name", - ) - - test_reactor = paramak.Reactor([test_shape]) - test_reactor.show() - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_show/test_shape.py b/tests/tests_show/test_shape.py deleted file mode 100644 index bfc46fc43..000000000 --- a/tests/tests_show/test_shape.py +++ /dev/null @@ -1,65 +0,0 @@ -import os -import unittest -from pathlib import Path - -import paramak - - -class TestShape(unittest.TestCase): - """Tests the show attribute of the Shape class which requires - jupyter_cadquery""" - - def setUp(self): - - self.my_shape = paramak.CenterColumnShieldHyperbola( - height=500, - inner_radius=50, - mid_radius=60, - outer_radius=100, - ) - - self.test_rotate_mixed_shape = paramak.RotateMixedShape( - rotation_angle=1, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "straight"), - (110, 45, "straight"), - ], - ) - self.test_extrude_mixed_shape = paramak.ExtrudeMixedShape( - distance=1, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "straight"), - (110, 45, "straight"), - ], - ) - - def test_show_runs_without_error(self): - """checks that the jupyter notebook (with cadquery addition) runs - without error.""" - - self.test_extrude_mixed_shape.show() - - def test_export_3d_html(self): - """Checks the 3d html file is exported by the export_html_3d method - with the correct filename""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)], rotation_angle=360) - - os.system("rm filename.html") - filename = test_shape.export_html_3d("filename.html") - if filename is not None: - assert Path("filename.html").exists() is True - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/__init__.py b/tests/tests_units/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/tests_units/local_test_examples.py b/tests/tests_units/local_test_examples.py deleted file mode 100644 index 540dba135..000000000 --- a/tests/tests_units/local_test_examples.py +++ /dev/null @@ -1,90 +0,0 @@ -import json -import os -import unittest -from pathlib import Path - -import pytest - -import paramak - -cwd = os.getcwd() - -"These tests require a visual front end which is not well suported on docker based CI systems" - - -class TestLocalExamples(unittest.TestCase): - def test_make_collarge(self): - """Runs the example and checks the output files are produced""" - os.chdir(Path(cwd)) - os.chdir(Path("examples")) - output_filenames = [ - "output_collarge/1.png", - "output_collarge/2.png", - "output_collarge/3.png", - "output_collarge/4.png", - "output_collarge/5.png", - "output_collarge/6.png", - "output_collarge/7.png", - "output_collarge/8.png", - "output_collarge/9.png", - "output_collarge/combine_images1.sh", - "output_collarge/combine_images2.sh", - "output_collarge/paramak_array1.svg", - "output_collarge/paramak_array2.svg", - ] - for output_filename in output_filenames: - os.system("rm " + output_filename) - os.system("python make_collarge.py") - for output_filename in output_filenames: - assert Path(output_filename).exists() - os.system("rm " + output_filename) - - def test_make_paramak_animation(self): - """Runs the example and checks the output files are produced""" - os.chdir(Path(cwd)) - os.chdir(Path("examples")) - output_filenames = [ - "output_for_animation_2d/0.png", - "output_for_animation_2d/1.png", - "output_for_animation_2d/2.png", - "output_for_animation_3d/0.png", - "output_for_animation_3d/1.png", - "output_for_animation_3d/2.png", - "2d.gif", - "3d.gif", - ] - for output_filename in output_filenames: - os.system("rm " + output_filename) - os.system("python make_animation.py -n 3") - for output_filename in output_filenames: - assert Path(output_filename).exists() - os.system("rm " + output_filename) - - def test_export_3d_image(self): - """checks that export_3d_image() exports png files with the correct suffix""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)]) - test_shape.rotation_angle = 360 - os.system("rm filename.png") - test_shape.export_3d_image("filename") - assert Path("filename.png").exists() is True - os.system("rm filename.png") - test_shape.export_3d_image("filename.png") - assert Path("filename.png").exists() is True - os.system("rm filename.png") - - def test_neutronics_cell_tally(self): - """Runs the neutronics example and checks the TBR""" - os.chdir(Path(cwd)) - os.chdir(Path("examples/neutronics")) - output_filename = "simulation_result.json" - os.system("rm " + output_filename) - os.system("python make_simple_neutronics_model.py") - with open(output_filename) as json_file: - data = json.load(json_file) - assert data["TBR"] == pytest.approx(0.456, abs=0.01) - os.system("rm " + output_filename) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_components/__init__.py b/tests/tests_units/test_parametric_components/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/tests_units/test_parametric_components/test_CuttingWedge.py b/tests/tests_units/test_parametric_components/test_CuttingWedge.py deleted file mode 100644 index 6b1ce814b..000000000 --- a/tests/tests_units/test_parametric_components/test_CuttingWedge.py +++ /dev/null @@ -1,28 +0,0 @@ -import math -import random -import unittest - -import pytest - -import paramak - - -class TestCuttingWedge(unittest.TestCase): - """Creates a random sized cutting wedge and changes the volume""" - - def test_volume_of_for_5_random_dimentions(self): - for test_number in range(5): - height = random.uniform(1.0, 2000.0) - radius = random.uniform(1.0, 1000) - rotation_angle = random.uniform(1.0, 360.0) - azimuth_placement_angle = random.uniform(1.0, 360.0) - - test_shape = paramak.CuttingWedge( - height=height, - radius=radius, - rotation_angle=rotation_angle, - azimuth_placement_angle=azimuth_placement_angle, - ) - angle_fraction = 360 / rotation_angle - correct_volume = (math.pi * radius**2 * height) / angle_fraction - assert test_shape.volume() == pytest.approx(correct_volume) diff --git a/tests/tests_units/test_parametric_components/test_blanket_constant_thickness_arch.py b/tests/tests_units/test_parametric_components/test_blanket_constant_thickness_arch.py deleted file mode 100644 index 9e4f23086..000000000 --- a/tests/tests_units/test_parametric_components/test_blanket_constant_thickness_arch.py +++ /dev/null @@ -1,74 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestBlanketConstantThicknessArcH(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.BlanketConstantThicknessArcH( - inner_lower_point=(300, -200), - inner_mid_point=(500, 0), - inner_upper_point=(300, 200), - thickness=20, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a BlanketConstantThicknessArcH are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_points_calculation(self): - """Checks that the points used to construct the BlanketConstantThicknessArcH component - are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (300, 200, "circle"), - (500, 0, "circle"), - (300, -200, "straight"), - (320, -200, "circle"), - (520, 0, "circle"), - (320, 200, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - BlanketConstantThicknessArcH component are calculated correctly from - the parameters given.""" - - assert self.test_shape.processed_points == [ - (300, 200, "circle"), - (500, 0, "circle"), - (300, -200, "straight"), - (320, -200, "circle"), - (520, 0, "circle"), - (320, 200, "straight"), - (300, 200, "circle"), - ] - - def test_component_creation(self): - """Creates a blanket using the BlanketConstantThicknessArcH parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_relative_shape_volume(self): - """Creates two blankets using the BlanketConstantThicknessArcH parametric component - and checks that their relative volumes are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert test_volume == pytest.approx(self.test_shape.volume() * 2) - - def test_shape_face_areas(self): - """Creates a blanket using the BlanketConstantThicknessArcH parametric component and - checks that the face areas are expected.""" - - assert len(self.test_shape.areas) == 4 - assert len(set([round(i) for i in self.test_shape.areas])) == 3 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 diff --git a/tests/tests_units/test_parametric_components/test_blanket_constant_thickness_arcv.py b/tests/tests_units/test_parametric_components/test_blanket_constant_thickness_arcv.py deleted file mode 100644 index f9eefd27c..000000000 --- a/tests/tests_units/test_parametric_components/test_blanket_constant_thickness_arcv.py +++ /dev/null @@ -1,76 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestBlanketConstantThicknessArcV(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.BlanketConstantThicknessArcV( - inner_lower_point=(300, -200), - inner_mid_point=(500, 0), - inner_upper_point=(300, 200), - thickness=20, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a BlanketConstantThicknessArcV are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_points_calculation(self): - """Checks that the points used to construct the - BlanketConstantThicknessArcH component are calculated correctly from - the parameters given.""" - - assert self.test_shape.points == [ - (300, 200, "circle"), - (500, 0, "circle"), - (300, -200, "straight"), - (300, -220, "circle"), - (520, 0, "circle"), - (300, 220, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - BlanketConstantThicknessArcH component are calculated correctly from - the parameters given.""" - - assert self.test_shape.processed_points == [ - (300, 200, "circle"), - (500, 0, "circle"), - (300, -200, "straight"), - (300, -220, "circle"), - (520, 0, "circle"), - (300, 220, "straight"), - (300, 200, "circle"), - ] - - def test_component_creation(self): - """Creates a blanekt using the BlanketConstantThicknessArcH parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_relative_shape_volume(self): - """Creates two blankets using the BlanketConstantThicknessArcV - parametric component and checks that their relative volumes are - correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert test_volume == pytest.approx(self.test_shape.volume() * 2) - - def test_shape_face_areas(self): - """Creates a blanket using the BlanketConstantThicknessArcV parametric component and - checks that the face areas are expected.""" - - assert len(self.test_shape.areas) == 4 - assert len(set([round(i) for i in self.test_shape.areas])) == 3 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 diff --git a/tests/tests_units/test_parametric_components/test_blanket_cutter_parallels.py b/tests/tests_units/test_parametric_components/test_blanket_cutter_parallels.py deleted file mode 100644 index 346098730..000000000 --- a/tests/tests_units/test_parametric_components/test_blanket_cutter_parallels.py +++ /dev/null @@ -1,73 +0,0 @@ -import unittest - -import paramak - - -class TestBlanketCutterParallels(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.BlanketCutterParallels(thickness=50, gap_size=200) - - def test_default_parameters(self): - """Checks that the default parameters of a BlanketCutterParallel are correct.""" - - assert self.test_shape.azimuth_placement_angle == [ - 0.0, - 36.0, - 72.0, - 108.0, - 144.0, - 180.0, - 216.0, - 252.0, - 288.0, - 324.0, - ] - assert self.test_shape.height == 2000 - assert self.test_shape.width == 2000 - - def test_creation(self): - """Creates solid using the BlanketCutterParallels parametric component - and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_BlanketCutterParallels_distance_volume_impact(self): - """Creates solid using the BlanketCutterParallels parametric component - with a larger thickness and checks that the volume changes accordingly - .""" - - test_volume = self.test_shape.volume() - self.test_shape.thickness = 100 - assert test_volume < self.test_shape.volume() - - def test_cut_modification(self): - """Creates a BlanketCutterParallels parametric component and with another - shape cut out and checks that a solid can be produced.""" - - cut_shape = paramak.ExtrudeCircleShape(1, 1, points=[(0, 0)]) - self.test_shape.cut = cut_shape - assert self.test_shape.solid is not None - - def test_distance_is_modified(self): - test_shape = paramak.BlanketCutterParallels( - thickness=50, - gap_size=50, - ) - - for thickness, gap_size in zip([20, 30, 40], [10, 20, 30]): - test_shape.thickness = thickness - test_shape.gap_size = gap_size - assert test_shape.distance == test_shape.gap_size / 2 + test_shape.thickness - - def test_main_cutting_shape_is_modified(self): - test_shape = paramak.BlanketCutterParallels( - thickness=50, - gap_size=50, - ) - - for gap_size, angles in zip([10, 20, 30], [0, 1, 3]): - test_shape.gap_size = gap_size - test_shape.azimuth_placement_angle = angles - assert test_shape.main_cutting_shape.distance == test_shape.gap_size / 2.0 - assert test_shape.main_cutting_shape.azimuth_placement_angle == test_shape.azimuth_placement_angle diff --git a/tests/tests_units/test_parametric_components/test_blanket_cutter_star.py b/tests/tests_units/test_parametric_components/test_blanket_cutter_star.py deleted file mode 100644 index c9c790dfe..000000000 --- a/tests/tests_units/test_parametric_components/test_blanket_cutter_star.py +++ /dev/null @@ -1,69 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestBlanketCutterStar(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.BlanketCutterStar(distance=100) - - def test_default_parameters(self): - """Checks that the default parameters of a BlanketCutterStar are correct.""" - - assert self.test_shape.azimuth_placement_angle == [ - 0.0, - 36.0, - 72.0, - 108.0, - 144.0, - 180.0, - 216.0, - 252.0, - 288.0, - 324.0, - ] - assert self.test_shape.height == 2000 - assert self.test_shape.width == 2000 - assert self.test_shape.name == "blanket_cutter_star" - - def test_points_calculation(self): - """Checks that the points used to construct the BlanketCutterStar component - are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (0, -1000), - (2000, -1000), - (2000, 1000), - (0, 1000), - ] - - def test_processed_points_calculation(self): - """Checks that the points used to construct the BlanketCutterStar component - are calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (0, -1000, "straight"), - (2000, -1000, "straight"), - (2000, 1000, "straight"), - (0, 1000, "straight"), - (0, -1000, "straight"), - ] - - def test_creation(self): - """Creates a solid using the BlanketCutterStar parametric component - and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_distance_volume_impact(self): - """Creates solid using the BlanketCutterStar parametric component - with different distances and checks that the volume changes accordingly - .""" - - test_volume = self.test_shape.volume() - self.test_shape.distance = 50 - # not quite two times as large as there is overlap in the center - assert test_volume == pytest.approx(self.test_shape.volume() * 2, rel=0.1) diff --git a/tests/tests_units/test_parametric_components/test_blanket_fp.py b/tests/tests_units/test_parametric_components/test_blanket_fp.py deleted file mode 100644 index 7a5f01ded..000000000 --- a/tests/tests_units/test_parametric_components/test_blanket_fp.py +++ /dev/null @@ -1,183 +0,0 @@ -import os -import unittest -import warnings -from pathlib import Path - -import paramak - - -class TestBlanketFP(unittest.TestCase): - def setUp(self): - self.plasma = paramak.Plasma(major_radius=450, minor_radius=150, triangularity=0.55, elongation=2) - - self.test_shape = paramak.BlanketFP( - thickness=150, - start_angle=-90, - stop_angle=240, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a BlanketFP are correct.""" - - assert self.test_shape.plasma is None - assert self.test_shape.minor_radius == 150 - assert self.test_shape.major_radius == 450 - assert self.test_shape.triangularity == 0.55 - assert self.test_shape.elongation == 2 - assert self.test_shape.vertical_displacement == 0 - assert self.test_shape.offset_from_plasma == 0 - assert self.test_shape.num_points == 50 - - def test_creation_plasma(self): - """Checks that a cadquery solid can be created by passing a plasma to - the BlanketFP parametric component.""" - - self.test_shape.plasma = self.plasma - self.test_shape.offset_from_plasma = 30 - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_faces(self): - """creates a blanket using the BlanketFP parametric component and checks - that a solid with the correct number of faces is created""" - - self.test_shape.plasma = self.plasma - self.test_shape.offset_from_plasma = 30 - - assert len(self.test_shape.areas) == 4 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 5 - - def test_creation_noplasma(self): - """Checks that a cadquery solid can be created using the BlanketFP - parametric component when no plasma is passed.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_creation_variable_thickness_from_tuple(self): - """Checks that a cadquery solid can be created using the BlanketFP - parametric component when a tuple of thicknesses is passed as an - argument.""" - - self.test_shape.thickness = (100, 200) - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_creation_variable_thickness_from_2_lists(self): - """Checks that a cadquery solid can be created using the BlanketFP - parametric component when a list of angles and a list of thicknesses - are passed as an argument.""" - - self.test_shape.thickness = [(-90, 240), [10, 30]] - - assert self.test_shape.solid is not None - - def test_creation_variable_thickness_function(self): - """Checks that a cadquery solid can be created using the BlanketFP - parametric component when a thickness function is passed as an - argument.""" - - def thickness(theta): - return 10 + 0.1 * theta - - self.test_shape.thickness = thickness - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_creation_variable_offset_from_tuple(self): - """Checks that a cadquery solid can be created using the BlanketFP - parametric component when a tuple of offsets is passed as an - argument.""" - - self.test_shape.offset_from_plasma = (0, 10) - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_creation_variable_offset_from_2_lists(self): - """Checks that a cadquery solid can be created using the BlanketFP - parametric component when a list of offsets and a list of angles are - passed as an argument.""" - - self.test_shape.start_angle = 90 - self.test_shape.stop_angle = 270 - self.test_shape.offset_from_plasma = [[270, 100, 90], [0, 5, 10]] - - assert self.test_shape.solid is not None - - def test_creation_variable_offset_error(self): - """Checks that an error is raised when two lists with different - lengths are passed in offset_from_plasma as an argument.""" - - def test_different_lengths(): - self.test_shape.start_angle = 90 - self.test_shape.stop_angle = 270 - self.test_shape.offset_from_plasma = [[270, 100, 90], [0, 5, 10, 15]] - self.test_shape.solid - - self.assertRaises(ValueError, test_different_lengths) - - def test_creation_variable_offset_function(self): - """Checks that a cadquery solid can be created using the BlanketFP - parametric component when an offset function is passed.""" - - def offset(theta): - return 10 + 0.1 * theta - - self.test_shape.offset_from_plasma = offset - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_full_cov_stp_export(self): - """Creates a blanket using the BlanketFP parametric component with full - coverage and checks that an stp file can be exported using the export_stp - method.""" - - self.test_shape.rotation_angle = 180 - self.test_shape.start_angle = 0 - self.test_shape.stop_angle = 360 - - self.test_shape.export_stp("test_blanket_full_cov.stp") - assert Path("test_blanket_full_cov.stp").exists() - os.system("rm test_blanket_full_cov.stp") - - def test_full_cov_full_rotation(self): - """Creates a blanket using the BlanketFP parametric component with full - coverage and full rotation and checks that an stp file can be exported using - the export_stp method.""" - - self.test_shape.rotation_angle = 360 - self.test_shape.start_angle = 0 - self.test_shape.stop_angle = 360 - - self.test_shape.export_stp("test_blanket_full_cov_full_rot.stp") - assert Path("test_blanket_full_cov_full_rot.stp").exists() - os.system("rm test_blanket_full_cov_full_rot.stp") - - def test_overlapping(self): - """Creates an overlapping geometry and checks that a warning is raised.""" - - test_shape = paramak.BlanketFP( - major_radius=100, - minor_radius=100, - triangularity=0.5, - elongation=2, - thickness=200, - stop_angle=360, - start_angle=0, - ) - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - for a in w: - print(a.message) - assert test_shape.solid is not None - assert "BlanketFP: Some points with negative R" in str(w[0].message) diff --git a/tests/tests_units/test_parametric_components/test_capsule_vacuum_vessel.py b/tests/tests_units/test_parametric_components/test_capsule_vacuum_vessel.py deleted file mode 100644 index 462cc12e4..000000000 --- a/tests/tests_units/test_parametric_components/test_capsule_vacuum_vessel.py +++ /dev/null @@ -1,114 +0,0 @@ -import math - -import pytest - -import paramak - -"""This test evaluates the perimeter of the resultant points and asserts them against the known value""" - - -def perimeter(outer_start_point, radius, thickness): - - test_shape = paramak.CapsuleVacuumVessel(outer_start_point=outer_start_point, radius=radius, thickness=thickness) - point1 = test_shape.points[0] - # point2 = test_shape.points[1] - point3 = test_shape.points[2] - point4 = test_shape.points[3] - # point5 = test_shape.points[4] - point6 = test_shape.points[5] - point7 = test_shape.points[6] - # point8 = test_shape.points[7] - point9 = test_shape.points[8] - point10 = test_shape.points[9] - # point11 = test_shape.points[10] - point12 = test_shape.points[11] - - straightedges = float( - (point12[1] - point1[1]) + (point6[1] - point7[1]) + (point4[1] - point3[1]) + (point9[1] - point10[1]) - ) - curvededges = float((math.pi * radius) + (math.pi * (radius - thickness))) - total = float(straightedges + curvededges) - - # TODO add an assert statement to test something here - - return total - - -def test_perimeter1(): - testp = perimeter(outer_start_point=(0, 0), radius=300, thickness=10) - assert testp == pytest.approx(3073.54) - - -def test_perimeter2(): - testp = perimeter(outer_start_point=(100, -100), radius=400, thickness=25) - assert testp == pytest.approx(4084.734) - - -def test_perimeter3(): - testp = perimeter(outer_start_point=(1000, -500), radius=5000, thickness=50) - assert testp == pytest.approx(51358.85) - - -def test_pointnum1(): - """this tests if the number of points returned are correct""" - shape = paramak.CapsuleVacuumVessel(outer_start_point=(0, 0), radius=300, thickness=10) - assert len(shape.points) == 12 - assert len(shape.processed_points) == 13 - - -def test_pointnum2(): - """this tests if the number of points returned are correct""" - shape = paramak.CapsuleVacuumVessel(outer_start_point=(100, -100), radius=400, thickness=25) - assert len(shape.points) == 12 - assert len(shape.processed_points) == 13 - - -def test_pointnum3(): - """this tests if the number of points returned are correct""" - shape = paramak.CapsuleVacuumVessel(outer_start_point=(1000, -500), radius=5000, thickness=50) - assert len(shape.points) == 12 - assert len(shape.processed_points) == 13 - - -"""this tests the volume of the created component and asserts it agaist the known value""" - - -def volume(outer_start_point, radius, thickness, angle): - - test_shape = paramak.CapsuleVacuumVessel( - outer_start_point=outer_start_point, - radius=radius, - thickness=thickness, - rotation_angle=angle, - ) - - point3 = test_shape.points[2] - point4 = test_shape.points[3] - - point9 = test_shape.points[8] - point10 = test_shape.points[9] - - outer_volume_cylinder = float(math.pi * (radius**2) * (point4[1] - point3[1])) - inner_volume_cylinder = float(math.pi * ((radius - thickness) ** 2) * (point9[1] - point10[1])) - outer_volume_sphere = float((4 / 3) * math.pi * (radius**3)) - inner_volume_sphere = float((4 / 3) * math.pi * ((radius - thickness) ** 3)) - outer_volume = outer_volume_sphere + outer_volume_cylinder - inner_volume = inner_volume_cylinder + inner_volume_sphere - total_volume = (angle / 360) * (outer_volume - inner_volume) - - return total_volume - - -def testvolume1(): - testvol = volume(outer_start_point=(0, 0), radius=300, thickness=10, angle=180) - assert testvol == pytest.approx(11029084.61) - - -def testvolume2(): - testvol = volume(outer_start_point=(100, -100), radius=400, thickness=25, angle=360) - assert testvol == pytest.approx(95884025.78) - - -def testvolume3(): - testvol = volume(outer_start_point=(1000, -500), radius=5000, thickness=50, angle=90) - assert testvol == pytest.approx(7795207671.41) diff --git a/tests/tests_units/test_parametric_components/test_center_column_shield_circular.py b/tests/tests_units/test_parametric_components/test_center_column_shield_circular.py deleted file mode 100644 index 505a9ba19..000000000 --- a/tests/tests_units/test_parametric_components/test_center_column_shield_circular.py +++ /dev/null @@ -1,61 +0,0 @@ -import unittest - -import paramak - - -class TestCenterColumnShieldCircular(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CenterColumnShieldCircular( - height=600, inner_radius=100, mid_radius=150, outer_radius=200 - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CenterColumnShieldCircular are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_points_calculation(self): - """Checks that the points used to construct the CenterColumnShieldCircular components - are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (100, 0, "straight"), - (100, 300.0, "straight"), - (200, 300.0, "circle"), - (150, 0, "circle"), - (200, -300.0, "straight"), - (100, -300.0, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the CenterColumnShieldCircular components - are calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (100, 0, "straight"), - (100, 300.0, "straight"), - (200, 300.0, "circle"), - (150, 0, "circle"), - (200, -300.0, "straight"), - (100, -300.0, "straight"), - (100, 0, "straight"), - ] - - def test_creation(self): - """Creates a center column shield using the CenterColumnShieldCircular - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_faces(self): - """Creates a center column shield using the CenterColumnShieldCircular - parametric component and checks that a solid is created with the correct - number of faces""" - - assert len(self.test_shape.areas) == 4 - assert len(set([round(i) for i in self.test_shape.areas])) == 3 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 diff --git a/tests/tests_units/test_parametric_components/test_center_column_shield_cylinder.py b/tests/tests_units/test_parametric_components/test_center_column_shield_cylinder.py deleted file mode 100644 index 9230e0c28..000000000 --- a/tests/tests_units/test_parametric_components/test_center_column_shield_cylinder.py +++ /dev/null @@ -1,162 +0,0 @@ -import math -import os -import unittest -from pathlib import Path - -import pytest - -import paramak - - -class TestCenterColumnShieldCylinder(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CenterColumnShieldCylinder(height=600, inner_radius=100, outer_radius=200) - - def test_default_parameters(self): - """Checks that the default parameters of a CenterColumnShieldCylinder are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_creation(self): - """Creates a center column shield using the CenterColumnShieldCylinder - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - CenterColumnShieldCylinder component are calculated correctly from the - parameters given.""" - - assert self.test_shape.processed_points == [ - (100, 300, "straight"), - (200, 300, "straight"), - (200, -300, "straight"), - (100, -300, "straight"), - (100, 300, "straight"), - ] - - def test_points_calculation(self): - """Checks that the points used to construct the - CenterColumnShieldCylinder component are calculated correctly from the - parameters given.""" - - assert self.test_shape.points == [ - (100, 300), - (200, 300), - (200, -300), - (100, -300), - ] - - def test_relative_volume(self): - """Creates CenterColumnShieldCylinder shapes and checks that their - relative volumes are correct""" - - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert test_volume == pytest.approx(self.test_shape.volume() * 2) - - def test_absolute_volume(self): - """Creates a CenterColumnShieldCylinder shape and checks that its - relative volume is correct""" - - assert self.test_shape.volume() == pytest.approx(((math.pi * (200**2)) - (math.pi * (100**2))) * 600) - - def test_absolute_area(self): - """Creates a CenterColumnShieldCylinder shape and checks that the - areas of the faces of the solid created are correct""" - - assert len(self.test_shape.areas) == 4 - assert self.test_shape.area == pytest.approx( - (((math.pi * (200**2)) - (math.pi * (100**2))) * 2) - + (math.pi * (2 * 200) * 600) - + (math.pi * (2 * 100) * 600) - ) - assert self.test_shape.areas.count(pytest.approx((math.pi * (200**2)) - (math.pi * (100**2)))) == 2 - assert self.test_shape.areas.count(pytest.approx(math.pi * (2 * 200) * 600)) == 1 - assert self.test_shape.areas.count(pytest.approx(math.pi * (2 * 100) * 600)) == 1 - - def test_export_stp_CenterColumnShieldCylinder(self): - """Creates a CenterColumnShieldCylinder shape and checks that a stp - file of the shape can be exported using the export_stp method.""" - - os.system("rm center_column_shield.stp") - self.test_shape.export_stp("center_column_shield.stp") - assert Path("center_column_shield.stp").exists() - os.system("rm center_column_shield.stp") - - def test_parametric_component_hash_value(self): - """Creates a parametric component and checks that a cadquery solid with - a unique hash value is created when .solid is called. Checks that the - same cadquery solid with the same unique hash value is returned when - shape.solid is called again after no changes have been made to the - parametric component. Checks that a new cadquery solid with a new - unique hash value is constructed when shape.solid is called after - changes to the parametric component have been made. Checks that the - hash_value of a parametric component is not updated until a new - cadquery solid has been created.""" - - assert self.test_shape.hash_value is None - assert self.test_shape.solid is not None - assert self.test_shape.hash_value is not None - initial_hash_value = self.test_shape.hash_value - assert self.test_shape.solid is not None - assert initial_hash_value == self.test_shape.hash_value - self.test_shape.height = 120 - assert initial_hash_value == self.test_shape.hash_value - assert self.test_shape.solid is not None - assert initial_hash_value != self.test_shape.hash_value - - def test_center_column_shield_cylinder_invalid_parameters_errors(self): - """Checks that the correct errors are raised when invalid arguments are entered - as shape parameters.""" - - def incorrect_inner_radius(): - self.test_shape.inner_radius = 250 - - def incorrect_outer_radius(): - self.test_shape.inner_radius = 100 - self.test_shape.outer_radius = 50 - - def incorrect_height(): - self.test_shape.outer_radius = 200 - self.test_shape.height = None - - def incorrect_center_height(): - self.test_shape.center_height = "string" - - def incorrect_center_height_none(): - self.test_shape.center_height = None - - self.assertRaises(ValueError, incorrect_inner_radius) - self.assertRaises(ValueError, incorrect_outer_radius) - self.assertRaises(ValueError, incorrect_height) - self.assertRaises(TypeError, incorrect_center_height) - self.assertRaises(TypeError, incorrect_center_height_none) - - def test_center_height_usage(self): - """Makes a offset cyclinder using center_height that overlaps half of - the default center_height=0 shape. Cuts shapes and checks volumes. - """ - test_shape1 = paramak.CenterColumnShieldCylinder(inner_radius=3, outer_radius=3.3, height=5, color=(1, 0, 0)) - - test_shape2 = paramak.CenterColumnShieldCylinder( - inner_radius=3, - outer_radius=3.3, - height=5, - center_height=-2.5, - color=(1, 0, 0), - ) - - test_shape3 = paramak.CenterColumnShieldCylinder( - inner_radius=3, - outer_radius=3.3, - height=5, - center_height=0, - color=(1, 0, 0), - cut=test_shape2, - ) - - assert test_shape2.volume() == test_shape1.volume() - assert pytest.approx(test_shape3.volume()) == 0.5 * test_shape1.volume() diff --git a/tests/tests_units/test_parametric_components/test_center_column_shield_flat_top_circular.py b/tests/tests_units/test_parametric_components/test_center_column_shield_flat_top_circular.py deleted file mode 100644 index 1428fe693..000000000 --- a/tests/tests_units/test_parametric_components/test_center_column_shield_flat_top_circular.py +++ /dev/null @@ -1,72 +0,0 @@ -import unittest - -import paramak - - -class TestCenterColumnShieldFlatTopCircular(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CenterColumnShieldFlatTopCircular( - height=600, - arc_height=400, - inner_radius=100, - mid_radius=150, - outer_radius=200, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CenterColumnShieldFlatTopCircular are - correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_points_calculation(self): - """Checks that the points used to construct the CenterColumnShieldFlatTopCircular - component are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (100, 0, "straight"), - (100, 300, "straight"), - (200, 300, "straight"), - (200, 200, "circle"), - (150, 0, "circle"), - (200, -200, "straight"), - (200, -300, "straight"), - (100, -300, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - CenterColumnShieldFlatTopCircular component are calculated correctly - from the parameters given.""" - - assert self.test_shape.processed_points == [ - (100, 0, "straight"), - (100, 300, "straight"), - (200, 300, "straight"), - (200, 200, "circle"), - (150, 0, "circle"), - (200, -200, "straight"), - (200, -300, "straight"), - (100, -300, "straight"), - (100, 0, "straight"), - ] - - def test_creation(self): - """Creates a center column shield using the - CenterColumnShieldFlatTopCircular parametric component and checks that - a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_faces(self): - """Creates a center column shield using the - CenterColumnShieldFlatTopCircular parametric component and checks that - a solid is created with the correct number of faces""" - - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 8 - assert len(set([round(i) for i in self.test_shape.areas])) == 5 diff --git a/tests/tests_units/test_parametric_components/test_center_column_shield_flat_top_hyperbola.py b/tests/tests_units/test_parametric_components/test_center_column_shield_flat_top_hyperbola.py deleted file mode 100644 index 16a5dd553..000000000 --- a/tests/tests_units/test_parametric_components/test_center_column_shield_flat_top_hyperbola.py +++ /dev/null @@ -1,101 +0,0 @@ -import unittest - -import paramak - - -class TestCenterColumnShieldFlatTopHyperbola(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CenterColumnShieldFlatTopHyperbola( - height=600, - arc_height=400, - inner_radius=100, - mid_radius=150, - outer_radius=200, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CenterColumnShieldFlatTopHyperbola are - correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_points_calculation(self): - """Checks that the points used to construct the - CenterColumnShieldFlatTopHyperbola component are calculated correctly - from the parameters given.""" - - assert self.test_shape.points == [ - (100, 0, "straight"), - (100, 300, "straight"), - (200, 300, "straight"), - (200, 200, "spline"), - (150, 0, "spline"), - (200, -200, "straight"), - (200, -300, "straight"), - (100, -300, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - CenterColumnShieldFlatTopHyperbola component are calculated correctly - from the parameters given.""" - - assert self.test_shape.processed_points == [ - (100, 0, "straight"), - (100, 300, "straight"), - (200, 300, "straight"), - (200, 200, "spline"), - (150, 0, "spline"), - (200, -200, "straight"), - (200, -300, "straight"), - (100, -300, "straight"), - (100, 0, "straight"), - ] - - def test_creation(self): - """Creates a center column shield using the - CenterColumnShieldFlatTopHyperbola parametric component and checks that - a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_invalid_parameters_errors(self): - """Checks that the correct errors are raised when invalid arguments are input as - shape parameters.""" - - def incorrect_inner_radius(): - self.test_shape.inner_radius = 220 - self.test_shape.solid - - def incorrect_mid_radius(): - self.test_shape.inner_radius = 100 - self.test_shape.mid_radius = 250 - self.test_shape.solid - - def incorrect_outer_radius(): - self.test_shape.mid_radius = 150 - self.test_shape.outer_radius = 130 - self.test_shape.solid - - def incorrect_arc_height(): - self.test_shape.outer_radius = 200 - self.test_shape.arc_height = 700 - self.test_shape.solid - - self.assertRaises(ValueError, incorrect_inner_radius) - self.assertRaises(ValueError, incorrect_mid_radius) - self.assertRaises(ValueError, incorrect_outer_radius) - self.assertRaises(ValueError, incorrect_arc_height) - - def test_faces(self): - """Creates a center column shield using the - CenterColumnShieldFlatTopHyperbola parametric component and checks - that a solid is created with the correct number of faces.""" - - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 8 - assert len(set([round(i) for i in self.test_shape.areas])) == 5 diff --git a/tests/tests_units/test_parametric_components/test_center_column_shield_hyperbola.py b/tests/tests_units/test_parametric_components/test_center_column_shield_hyperbola.py deleted file mode 100644 index fa3fb1705..000000000 --- a/tests/tests_units/test_parametric_components/test_center_column_shield_hyperbola.py +++ /dev/null @@ -1,87 +0,0 @@ -import unittest - -import paramak - - -class TestCenterColumnShieldHyperbola(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CenterColumnShieldHyperbola( - height=600, inner_radius=100, mid_radius=150, outer_radius=200 - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CenterColumnShieldHyperbola are - correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - CenterColumnShieldHyperbola component are calculated correctly from the - parameters given.""" - - assert self.test_shape.processed_points == [ - (100.0, 0.0, "straight"), - (100.0, 300.0, "straight"), - (200.0, 300.0, "spline"), - (150.0, 0.0, "spline"), - (200.0, -300.0, "straight"), - (100.0, -300.0, "straight"), - (100.0, 0.0, "straight"), - ] - - def test_points_calculation(self): - """Checks that the points used to construct the - CenterColumnShieldHyperbola component are calculated correctly from the - parameters given.""" - - assert self.test_shape.points == [ - (100.0, 0.0, "straight"), - (100.0, 300.0, "straight"), - (200.0, 300.0, "spline"), - (150.0, 0.0, "spline"), - (200.0, -300.0, "straight"), - (100.0, -300.0, "straight"), - ] - - def test_creation(self): - """Creates a center column shield using the - CenterColumnShieldHyperbola parametric component and checks that a - cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_invalid_parameters_errors(self): - """Checks that the correct errors are raised when invalid arguments are input - as shape parameters.""" - - def incorrect_inner_radius(): - self.test_shape.inner_radius = 180 - self.test_shape.solid - - def incorrect_mid_radius(): - self.test_shape.inner_radius = 100 - self.test_shape.mid_radius = 80 - self.test_shape.solid - - def incorrect_outer_radius(): - self.test_shape.mid_radius = 150 - self.test_shape.outer_radius = 130 - self.test_shape.solid - - self.assertRaises(ValueError, incorrect_inner_radius) - self.assertRaises(ValueError, incorrect_mid_radius) - self.assertRaises(ValueError, incorrect_outer_radius) - - def test_faces(self): - """Creates a center column shield using the CenterColumnShieldHyperbola - parametric component and checks that a solid with the correct number of - faces is created""" - - assert len(self.test_shape.areas) == 4 - assert len(set([round(i) for i in self.test_shape.areas])) == 3 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 diff --git a/tests/tests_units/test_parametric_components/test_center_column_shield_plasma_hyperbola.py b/tests/tests_units/test_parametric_components/test_center_column_shield_plasma_hyperbola.py deleted file mode 100644 index 4003ed81c..000000000 --- a/tests/tests_units/test_parametric_components/test_center_column_shield_plasma_hyperbola.py +++ /dev/null @@ -1,89 +0,0 @@ -import unittest - -import paramak - - -class TestCenterColumnShieldPlasmaHyperbola(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CenterColumnShieldPlasmaHyperbola( - height=800, inner_radius=100, mid_offset=40, edge_offset=30 - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CenterColumnShieldPlasmaHyperbola are - correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.major_radius == 450 - assert self.test_shape.minor_radius == 150 - assert self.test_shape.triangularity == 0.55 - assert self.test_shape.elongation == 2 - - def test_creation(self): - """Creates a center column shield using the - CenterColumnShieldPlasmaHyperbola parametric component and checks that - a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_points_calculation(self): - """Checks that the points used to construct the - CenterColumnShieldPlasmaHyperbola component are calculated correctly - from the parameters given.""" - - assert self.test_shape.points == [ - (100, 0, "straight"), - (100, 400.0, "straight"), - (337.5, 400.0, "straight"), - (337.5, 300.0, "spline"), - (260.0, 0.0, "spline"), - (337.5, -300.0, "straight"), - (337.5, -400.0, "straight"), - (100, -400.0, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - CenterColumnShieldPlasmaHyperbola component are calculated correctly - from the parameters given.""" - - assert self.test_shape.processed_points == [ - (100, 0, "straight"), - (100, 400.0, "straight"), - (337.5, 400.0, "straight"), - (337.5, 300.0, "spline"), - (260.0, 0.0, "spline"), - (337.5, -300.0, "straight"), - (337.5, -400.0, "straight"), - (100, -400.0, "straight"), - (100, 0, "straight"), - ] - - def test_invalid_parameters_errors(self): - """Checks that the correct errors are raised when invalid arguments are input as - shape parameters.""" - - def incorrect_inner_radius(): - self.test_shape.inner_radius = 601 - self.test_shape.solid - - def incorrect_height(): - self.test_shape.inner_radius = 100 - self.test_shape.height = 300 - self.test_shape.solid - - self.assertRaises(ValueError, incorrect_inner_radius) - self.assertRaises(ValueError, incorrect_height) - - def test_faces(self): - """Creates a center column shield using the CenterColumnShieldPlasmaHyperbola - parametric component and checks that a solid with the correct number of - faces is created""" - - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 4 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 8 - assert len(set([round(i) for i in self.test_shape.areas])) == 5 diff --git a/tests/tests_units/test_parametric_components/test_circular_port.py b/tests/tests_units/test_parametric_components/test_circular_port.py deleted file mode 100644 index fa9f14980..000000000 --- a/tests/tests_units/test_parametric_components/test_circular_port.py +++ /dev/null @@ -1,59 +0,0 @@ -import unittest - -import paramak - - -class TestCircularPort(unittest.TestCase): - def setUp(self): - - self.test_shape = paramak.CircularPort( - inner_radius=20, - azimuth_placement_angle=[0.0, 30.0, 60.0, 90.0, 120.0, 150.0, 180.0, 210.0, 240.0, 270.0, 300.0, 330.0], - color=(0, 1, 0), - rotation_angle=180, - blank_flange_thickness=4, - flange_thickness=10, - wall_thickness=2, - distance=50, - flange_gap=0, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CircularPort are correct.""" - - assert self.test_shape.inner_radius == 20 - assert self.test_shape.rotation_angle == 180 - assert self.test_shape.blank_flange_thickness == 4 - assert self.test_shape.flange_thickness == 10 - assert self.test_shape.wall_thickness == 2 - assert self.test_shape.distance == 50 - assert self.test_shape.flange_gap == 0 - - def test_creation(self): - """Creates a circular port cutter using the CircularPort parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_gap_makes_extra_surfaces(self): - """Creates a circular port cutter using the CircularPort parametric - component and checks that a cadquery solid with the right number of - surfaces is created.""" - - self.test_shape.azimuth_placement_angle = [0] - self.test_shape.rotation_angle = 360 - assert len(self.test_shape.solid.val().Faces()) == 7 - self.test_shape.flange_gap = 1 - assert len(self.test_shape.solid.val().Faces()) == 9 - - def test_gap_and_cut_makes_extra_surfaces(self): - """Creates a circular port cutter using the CircularPort parametric - component and checks that a cadquery solid with the right number of - surfaces is created.""" - - self.test_shape.azimuth_placement_angle = [0] - self.test_shape.rotation_angle = 180 # this cuts the shape in half - assert len(self.test_shape.solid.val().Faces()) == 8 - self.test_shape.flange_gap = 1 - assert len(self.test_shape.solid.val().Faces()) == 12 diff --git a/tests/tests_units/test_parametric_components/test_constant_thickness_dome.py b/tests/tests_units/test_parametric_components/test_constant_thickness_dome.py deleted file mode 100644 index d2ea6c544..000000000 --- a/tests/tests_units/test_parametric_components/test_constant_thickness_dome.py +++ /dev/null @@ -1,50 +0,0 @@ -import unittest -import pytest - -import paramak - - -class TestConstantThicknessDome(unittest.TestCase): - """tests for the ConstantThicknessDome class""" - - def test_volume_increases_with_rotation_angle(self): - """Tests that the volume doubles when rotation angle doubles""" - - test_shape_1 = paramak.ConstantThicknessDome(rotation_angle=180) - test_shape_2 = paramak.ConstantThicknessDome(rotation_angle=360) - - assert test_shape_1.volume() * 2 == pytest.approx(test_shape_2.volume()) - - def test_upper_lower_flips_points(self): - """Checks that the coords of the flips version are the same for p1 and p2 - and negative for part of p3""" - test_shape_1 = paramak.ConstantThicknessDome(upper_or_lower="upper") - test_shape_2 = paramak.ConstantThicknessDome(upper_or_lower="lower") - assert test_shape_1.points[0] == test_shape_2.points[0] - assert test_shape_1.points[1] == test_shape_2.points[1] - assert test_shape_1.points[2][0] == test_shape_2.points[2][0] - assert test_shape_1.points[2][1] == -test_shape_2.points[2][1] - - assert test_shape_1.volume() == pytest.approx(test_shape_2.volume()) - - def test_invalid_parameters_errors(self): - """Checks that the correct errors are raised when invalid arguments are - input as shape parameters.""" - - def incorrect_shape_height_width_ratio(): - my_shape = paramak.ConstantThicknessDome(chord_width=10, chord_height=40) - my_shape.solid - - def incorrect_thickness(): - paramak.ConstantThicknessDome(thickness=-1) - - def incorrect_chord_height(): - paramak.ConstantThicknessDome(chord_height=-1) - - def incorrect_chord_width(): - paramak.ConstantThicknessDome(chord_width=-1) - - self.assertRaises(ValueError, incorrect_shape_height_width_ratio) - self.assertRaises(ValueError, incorrect_thickness) - self.assertRaises(ValueError, incorrect_chord_height) - self.assertRaises(ValueError, incorrect_chord_width) diff --git a/tests/tests_units/test_parametric_components/test_coolant_channel_ring_curved.py b/tests/tests_units/test_parametric_components/test_coolant_channel_ring_curved.py deleted file mode 100644 index 028473376..000000000 --- a/tests/tests_units/test_parametric_components/test_coolant_channel_ring_curved.py +++ /dev/null @@ -1,51 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestCoolantChannelRingCurved(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CoolantChannelRingCurved( - height=100, - channel_radius=10, - ring_radius=70, - mid_offset=-20, - number_of_coolant_channels=6, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CoolantChannelRingCurved are correct.""" - - # assert self.test_shape.rotation_angle == 360 - assert self.test_shape.start_angle == 0 - - def test_creation(self): - """Creates a coolant channel ring using the CoolantChannelRingCurved parametric shape - and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_relative_volumes(self): - """Creates coolant channel rings using the CoolantChannelRingCurved parametric shape - and checks the relative volumes are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.number_of_coolant_channels = 3 - assert test_volume == pytest.approx(self.test_shape.volume() * 2) - - test_volume = self.test_shape.volume() - self.test_shape.mid_offset = -30 - assert test_volume > self.test_shape.volume() - self.test_shape.force_cross_section = True - assert test_volume < self.test_shape.volume() - - def test_start_angle(self): - """Checks that the coolant channels are placed at the correct azimuthal placement - angles for a given start angle.""" - - assert self.test_shape.azimuth_placement_angle == [0, 60, 120, 180, 240, 300] - self.test_shape.start_angle = 10 - assert self.test_shape.azimuth_placement_angle == [10, 70, 130, 190, 250, 310] diff --git a/tests/tests_units/test_parametric_components/test_coolant_channel_ring_straight.py b/tests/tests_units/test_parametric_components/test_coolant_channel_ring_straight.py deleted file mode 100644 index 90b4b83a0..000000000 --- a/tests/tests_units/test_parametric_components/test_coolant_channel_ring_straight.py +++ /dev/null @@ -1,72 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestCoolantChannelRingStraight(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.CoolantChannelRingStraight( - height=100, channel_radius=10, ring_radius=70, number_of_coolant_channels=8 - ) - - def test_default_parameters(self): - """Checks that the default parameters of a CoolantChannelRingStraight are correct.""" - - # assert self.test_shape.rotation_angle == 360 - assert self.test_shape.start_angle == 0 - - def test_creation(self): - """Creates a coolant channel ring using the CoolantChannelRingStraight parameteric shape - and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_faces(self): - """Creates a CoolantChannelRingStraight shape and checks that the areas of its faces - are correct.""" - - self.test_shape.workplane = "XY" - self.test_shape.rotation_axis = "Z" - - assert self.test_shape.area == pytest.approx((((math.pi * (10**2)) * 2) + (math.pi * (10 * 2) * 100)) * 8) - assert len(self.test_shape.areas) == 24 - assert self.test_shape.areas.count(pytest.approx(math.pi * (10**2))) == 16 - assert self.test_shape.areas.count(pytest.approx(math.pi * (10 * 2) * 100)) == 8 - - def test_volume(self): - """Creates CoolantChannelRingStraight shapes and checks that the volumes are correct.""" - - self.test_shape.workplane = "XY" - self.test_shape.rotation_axis = "Z" - - assert self.test_shape.volume() == pytest.approx(math.pi * (10**2) * 100 * 8) - - def test_start_angle(self): - """Checks that the coolant channels are placed at the correct azimuthal placement - angles for a given start angle.""" - - assert self.test_shape.azimuth_placement_angle == [ - 0, - 45, - 90, - 135, - 180, - 225, - 270, - 315, - ] - self.test_shape.start_angle = 10 - assert self.test_shape.azimuth_placement_angle == [ - 10, - 55, - 100, - 145, - 190, - 235, - 280, - 325, - ] diff --git a/tests/tests_units/test_parametric_components/test_cutting_wedge_fs.py b/tests/tests_units/test_parametric_components/test_cutting_wedge_fs.py deleted file mode 100644 index ce4d07b24..000000000 --- a/tests/tests_units/test_parametric_components/test_cutting_wedge_fs.py +++ /dev/null @@ -1,67 +0,0 @@ -import unittest - -import numpy as np - -import paramak - - -class TestCuttingWedgeFS(unittest.TestCase): - def test_shape_construction_and_volume(self): - """Makes cutting cylinders from shapes and checks the - volume of the cutter shape is larger than the shape it - encompasses.""" - - hoop_shape = paramak.PoloidalFieldCoil(height=20, width=20, center_point=(50, 200), rotation_angle=180) - - cutter = paramak.CuttingWedgeFS( - shape=hoop_shape, - azimuth_placement_angle=0, - ) - - assert cutter.volume() > hoop_shape.volume() - - def test_invalid_parameters_errors(self): - """Checks that the correct errors are raised when invalid arguments are input as - shape parameters.""" - - shape = paramak.ExtrudeStraightShape(distance=1, points=[(0, 0), (0, 1), (1, 1)], rotation_angle=180) - - cutter = paramak.CuttingWedgeFS( - shape=shape, - azimuth_placement_angle=0, - ) - - def incorrect_rotation_angle(): - shape.rotation_angle = 360 - cutter.solid - - def incorrect_shape_points(): - shape.rotation_angle = 180 - cutter.shape.points = [(0, 0, "straight")] - cutter.solid - - def incorrect_shape_rotation_angle(): - cutter.shape.points = [(0, 0), (0, 1), (1, 1)] - shape.rotation_angle = 360 - cutter.shape = shape - - self.assertRaises(ValueError, incorrect_rotation_angle) - self.assertRaises(ValueError, incorrect_shape_points) - self.assertRaises(ValueError, incorrect_shape_rotation_angle) - - def test_different_workplanes(self): - """Test that checks the cutting wedge can be correctly applied to a - shape with non-default workplane and rotation_axis - """ - rectangle = paramak.ExtrudeStraightShape( - 2, - points=[(-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5)], - workplane="XY", - rotation_axis="Z", - ) - rectangle.rotation_angle = 360 - volume_full = rectangle.volume() - assert np.isclose(volume_full, 2) - rectangle.rotation_angle = 90 - volume_quarter = rectangle.volume() - assert np.isclose(volume_quarter, 0.5) diff --git a/tests/tests_units/test_parametric_components/test_dished_vacuum_vessel.py b/tests/tests_units/test_parametric_components/test_dished_vacuum_vessel.py deleted file mode 100644 index 4ff3bdd10..000000000 --- a/tests/tests_units/test_parametric_components/test_dished_vacuum_vessel.py +++ /dev/null @@ -1,9 +0,0 @@ -import pytest - -import paramak - - -def test_volume_increases_with_rotation_angle(): - test_shape_1 = paramak.DishedVacuumVessel(rotation_angle=180) - test_shape_2 = paramak.DishedVacuumVessel(rotation_angle=360) - assert test_shape_1.volume() * 2 == pytest.approx(test_shape_2.volume()) diff --git a/tests/tests_units/test_parametric_components/test_divertor_iter.py b/tests/tests_units/test_parametric_components/test_divertor_iter.py deleted file mode 100644 index ad8ec9f3d..000000000 --- a/tests/tests_units/test_parametric_components/test_divertor_iter.py +++ /dev/null @@ -1,33 +0,0 @@ -import unittest - -import paramak - - -class TestDivertorITER(unittest.TestCase): - def test_creation(self): - """Creates an ITER-type divertor using the ITERtypeDivertor parametric - component and checks that a cadquery solid is created""" - - test_shape = paramak.ITERtypeDivertor() - assert test_shape.solid is not None - - def test_stp_export(self): - """Creates an ITER-type divertor using the ITERtypeDivertor parametric - component and checks that a stp file of the shape can be exported using - the export_stp method""" - - test_shape = paramak.ITERtypeDivertor() - test_shape.export_stp("tests/ITER_div.stp") - - def test_faces(self): - """Creates an ITER-type divertor using the ITERtypeDivertor parametric - component and checks that a solid with the correct number of faces is - created""" - - test_shape = paramak.ITERtypeDivertor() - assert len(test_shape.areas) == 12 - assert len(set(test_shape.areas)) == 12 - - test_shape.rotation_angle = 180 - assert len(test_shape.areas) == 14 - assert len(set(test_shape.areas)) == 13 diff --git a/tests/tests_units/test_parametric_components/test_divertor_iter_no_dome.py b/tests/tests_units/test_parametric_components/test_divertor_iter_no_dome.py deleted file mode 100644 index 8b0e3cf2d..000000000 --- a/tests/tests_units/test_parametric_components/test_divertor_iter_no_dome.py +++ /dev/null @@ -1,33 +0,0 @@ -import unittest - -import paramak - - -class TestDivertorITERNoDome(unittest.TestCase): - def test_creation(self): - """Creates an ITER-type divertor using the ITERtypeDivertorNoDome - parametric component and checks that a cadquery solid is created.""" - - test_shape = paramak.ITERtypeDivertorNoDome() - assert test_shape.solid is not None - - def test_stp_export(self): - """Creates an ITER-type divertor using the ITERtypeDivertorNoDome - parametric component and checks that a stp file of the shape can be - exported using the export_stp method.""" - - test_shape = paramak.ITERtypeDivertorNoDome() - test_shape.export_stp("tests/ITER_div_no_dome.step") - - def test_faces(self): - """Creates an ITER-type divertor using the ITERtypeDivertorNoDome - parametric component and checks that a solid with the correct number - of faces is created""" - - test_shape = paramak.ITERtypeDivertorNoDome() - assert len(test_shape.areas) == 10 - assert len(set(test_shape.areas)) == 10 - - test_shape.rotation_angle = 180 - assert len(test_shape.areas) == 12 - assert len(set(test_shape.areas)) == 11 diff --git a/tests/tests_units/test_parametric_components/test_extrude_hollow_cube.py b/tests/tests_units/test_parametric_components/test_extrude_hollow_cube.py deleted file mode 100644 index fb21dc75a..000000000 --- a/tests/tests_units/test_parametric_components/test_extrude_hollow_cube.py +++ /dev/null @@ -1,36 +0,0 @@ -import unittest - -import paramak - - -class TestHollowCube(unittest.TestCase): - """tests the hoolw cube shape that is used as a graveyard""" - - def setUp(self): - self.test_shape = paramak.HollowCube(length=10, thickness=2) - - def test_default_parameters(self): - """Checks that the default parameters of a HollowCube are - correct.""" - - assert self.test_shape.center_coordinate == (0.0, 0.0, 0.0) - - def test_center_point_changes_bounding_box(self): - """Checks that moving the center results in the bounding box move as well""" - - default_shape_bb = ((-(10 + 2) / 2, -(10 + 2) / 2, -(10 + 2) / 2), ((10 + 2) / 2, (10 + 2) / 2, (10 + 2) / 2)) - assert self.test_shape.bounding_box == default_shape_bb - - self.test_shape.center_coordinate = (1, 1, 1) - - assert self.test_shape.bounding_box == ( - (default_shape_bb[0][0] + 1, default_shape_bb[0][1] + 1, default_shape_bb[0][2] + 1), - (default_shape_bb[1][0] + 1, default_shape_bb[1][1] + 1, default_shape_bb[1][2] + 1), - ) - - self.test_shape.center_coordinate = (-2, 3, 14) - - assert self.test_shape.bounding_box == ( - (default_shape_bb[0][0] - 2, default_shape_bb[0][1] + 3, default_shape_bb[0][2] + 14), - (default_shape_bb[1][0] - 2, default_shape_bb[1][1] + 3, default_shape_bb[1][2] + 14), - ) diff --git a/tests/tests_units/test_parametric_components/test_extrude_hollow_rectangle.py b/tests/tests_units/test_parametric_components/test_extrude_hollow_rectangle.py deleted file mode 100644 index 28f645aae..000000000 --- a/tests/tests_units/test_parametric_components/test_extrude_hollow_rectangle.py +++ /dev/null @@ -1,85 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestExtrudeHollowRectangle(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.ExtrudeHollowRectangle(height=10, width=15, casing_thickness=1, distance=2) - - def test_default_parameters(self): - """Checks that the default parameters of a ExtrudeHollowRectangle are - correct.""" - - assert self.test_shape.center_point == (0, 0) - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - ExtrudeHollowRectangle are calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (7.5, 5.0, "straight"), - (7.5, -5.0, "straight"), - (-7.5, -5.0, "straight"), - (-7.5, 5.0, "straight"), - (7.5, 5.0, "straight"), - (8.5, 6.0, "straight"), - (8.5, -6.0, "straight"), - (-8.5, -6.0, "straight"), - (-8.5, 6.0, "straight"), - (8.5, 6.0, "straight"), - (7.5, 5.0, "straight"), - ] - - def test_points_calculation(self): - """Checks that the points used to construct the ExtrudeHollowRectangle are - calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (7.5, 5.0), - (7.5, -5.0), - (-7.5, -5.0), - (-7.5, 5.0), - (7.5, 5.0), - (8.5, 6.0), - (8.5, -6.0), - (-8.5, -6.0), - (-8.5, 6.0), - (8.5, 6.0), - ] - - def test_creation(self): - """Creates a rectangular extrusion using the ExtrudeHollowRectangle - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 100 - - def test_absolute_volume(self): - """Creates a rectangular extrusion using the ExtrudeHollowRectangle - parametric component and checks that the volume is correct""" - - assert self.test_shape.volume() == pytest.approx((17 * 12 * 2) - (15 * 10 * 2)) - - def test_absolute_areas(self): - """Creates a rectangular extrusion using the ExtrudeHollowRectangle - parametric component and checks that the areas are correct""" - - assert len(self.test_shape.areas) == 10 - assert len(set([round(i) for i in self.test_shape.areas])) == 5 - assert self.test_shape.areas.count(pytest.approx(15 * 2)) == 2 - assert self.test_shape.areas.count(pytest.approx(10 * 2)) == 2 - - def test_center_point_changes_bounding_box(self): - - default_shape_bb = ((-(15 + 2) / 2, -1.0, -(10 + 2) / 2), ((15 + 2) / 2, 1.0, (10 + 2) / 2)) - assert self.test_shape.bounding_box == default_shape_bb - - self.test_shape.center_point = (1, 1) - - assert self.test_shape.bounding_box == ( - (default_shape_bb[0][0] + 1, default_shape_bb[0][1], default_shape_bb[0][2] + 1), - (default_shape_bb[1][0] + 1, default_shape_bb[1][1], default_shape_bb[1][2] + 1), - ) diff --git a/tests/tests_units/test_parametric_components/test_extrude_rectangle.py b/tests/tests_units/test_parametric_components/test_extrude_rectangle.py deleted file mode 100644 index e4c014236..000000000 --- a/tests/tests_units/test_parametric_components/test_extrude_rectangle.py +++ /dev/null @@ -1,62 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestExtrudeRectangle(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.ExtrudeRectangle(height=50, width=60, center_point=(1000, 500), distance=333) - - def test_default_parameters(self): - """Checks that the default parameters of a ExtrudeRectangle are - correct.""" - - assert self.test_shape.distance == 333 - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - ExtrudeRectangle are calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (1030.0, 525.0, "straight"), - (1030.0, 475.0, "straight"), - (970.0, 475.0, "straight"), - (970.0, 525.0, "straight"), - (1030.0, 525.0, "straight"), - ] - - def test_points_calculation(self): - """Checks that the points used to construct the ExtrudeRectangle are - calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (1030.0, 525.0), - (1030.0, 475.0), - (970.0, 475.0), - (970.0, 525.0), - ] - - def test_creation(self): - """Creates a rectangular extrusion using the ExtrudeRectangle - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_absolute_volume(self): - """Creates a rectangular extrusion using the ExtrudeRectangle - parametric component and checks that the volume is correct""" - - assert self.test_shape.volume() == pytest.approx(50 * 60 * 333) - - def test_absolute_areas(self): - """Creates a rectangular extrusion using the ExtrudeRectangle - parametric component and checks that the areas are correct""" - - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 3 - assert self.test_shape.areas.count(pytest.approx(60 * 50)) == 2 - assert self.test_shape.areas.count(pytest.approx(50 * 333)) == 2 - assert self.test_shape.areas.count(pytest.approx(60 * 333)) == 2 diff --git a/tests/tests_units/test_parametric_components/test_hexagon_pin.py b/tests/tests_units/test_parametric_components/test_hexagon_pin.py deleted file mode 100644 index aff4f24a9..000000000 --- a/tests/tests_units/test_parametric_components/test_hexagon_pin.py +++ /dev/null @@ -1,63 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestHexagonPin(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.HexagonPin(length_of_side=5, distance=42.0, center_point=(0, 0)) - - def test_setting_parameters(self): - """Checks that the default parameters and user parameters are set""" - - assert self.test_shape.length_of_side == 5 - assert self.test_shape.distance == 42.0 - assert self.test_shape.center_point == (0, 0) - assert self.test_shape.name == "hexagon_pin" - - def test_volume(self): - """Checks the volume against the actual value""" - - length = self.test_shape.length_of_side - distance = self.test_shape.distance - - hexagon_face_area = (3 * math.sqrt(3) / 2) * math.pow(length, 2) - # this needs a pytest.approx() as the volumes are not exact - assert pytest.approx(self.test_shape.volume(), rel=0.1) == hexagon_face_area * distance - - def test_distance_impacts_volume(self): - """Checks that changing the distance argument results in the - expected volume change""" - - test_shape_volume = self.test_shape.volume() - - self.test_shape.distance = self.test_shape.distance * 2 - - assert pytest.approx(test_shape_volume * 2, rel=0.1) == self.test_shape.volume() - - def test_length_of_sides_impacts_volume(self): - """Checks that changing the length_of_sides argument results in a the - expected volume change""" - - test_shape_volume = self.test_shape.volume() - - self.test_shape.length_of_side = self.test_shape.length_of_side * 2 - - assert pytest.approx(test_shape_volume * 4, rel=0.1) == self.test_shape.volume() - - def test_areas_are_correct(self): - """Tests the areas of the faces are the correct sizes""" - - test_shape_areas = self.test_shape.areas - - length = self.test_shape.length_of_side - distance = self.test_shape.distance - - hexagon_face_area = (3 * math.sqrt(3) / 2) * math.pow(length, 2) - - assert len(test_shape_areas) == 8 - assert test_shape_areas.count(pytest.approx(hexagon_face_area, rel=0.1)) == 2 - assert test_shape_areas.count(pytest.approx(length * distance, rel=0.1)) == 6 diff --git a/tests/tests_units/test_parametric_components/test_inboard_firstwall_fccs.py b/tests/tests_units/test_parametric_components/test_inboard_firstwall_fccs.py deleted file mode 100644 index 56b789ceb..000000000 --- a/tests/tests_units/test_parametric_components/test_inboard_firstwall_fccs.py +++ /dev/null @@ -1,142 +0,0 @@ -import unittest - -import numpy as np - -import paramak - - -class TestInboardFirstwallFCCS(unittest.TestCase): - def test_construction_with_CenterColumnShieldCylinder(self): - """Makes a firstwall from a CenterColumnShieldCylinder and checks - the volume is smaller than the shield.""" - - test_shape_1 = paramak.CenterColumnShieldCylinder(height=100, inner_radius=20, outer_radius=80) - test_shape_2 = paramak.InboardFirstwallFCCS( - central_column_shield=test_shape_1, thickness=20, rotation_angle=180 - ) - assert test_shape_1.solid is not None - assert test_shape_2.solid is not None - assert test_shape_1.volume() > test_shape_2.volume() - - def test_construction_with_CenterColumnShieldHyperbola(self): - """Makes a firstwall from a CenterColumnShieldHyperbola and checks - the volume is smaller than the shield.""" - - a = paramak.CenterColumnShieldHyperbola(height=200, inner_radius=20, mid_radius=80, outer_radius=120) - b = paramak.InboardFirstwallFCCS(central_column_shield=a, thickness=20, rotation_angle=180) - assert a.solid is not None - assert b.solid is not None - assert a.volume() > b.volume() - - def test_construction_with_CenterColumnShieldFlatTopHyperbola(self): - """Makes a firstwall from a CenterColumnShieldFlatTopHyperbola and - checks the volume is smaller than the shield.""" - - a = paramak.CenterColumnShieldFlatTopHyperbola( - height=200, arc_height=100, inner_radius=50, mid_radius=80, outer_radius=100 - ) - b = paramak.InboardFirstwallFCCS(central_column_shield=a, thickness=20, rotation_angle=180) - assert a.solid is not None - assert b.solid is not None - assert a.volume() > b.volume() - - def test_construction_with_CenterColumnShieldPlasmaHyperbola(self): - """Makes a firstwall from a CenterColumnShieldPlasmaHyperbola and - checks the volume is smaller than the shield.""" - - a = paramak.CenterColumnShieldPlasmaHyperbola(height=601, inner_radius=20, mid_offset=50, edge_offset=0) - b = paramak.InboardFirstwallFCCS(central_column_shield=a, thickness=20, rotation_angle=180) - assert a.solid is not None - assert b.solid is not None - assert a.volume() > b.volume() - - def test_construction_with_CenterColumnShieldCircular(self): - """Makes a firstwall from a CenterColumnShieldCircular and checks - the volume is smaller than the shield.""" - - a = paramak.CenterColumnShieldCircular(height=300, inner_radius=20, mid_radius=50, outer_radius=100) - b = paramak.InboardFirstwallFCCS(central_column_shield=a, thickness=20, rotation_angle=180) - assert a.solid is not None - assert b.solid is not None - assert a.volume() > b.volume() - - def test_construction_with_CenterColumnShieldFlatTopCircular(self): - """Makes a firstwall from a CenterColumnShieldFlatTopCircular and - checks the volume is smaller than the shield.""" - - a = paramak.CenterColumnShieldFlatTopCircular( - height=500, arc_height=300, inner_radius=30, mid_radius=70, outer_radius=120 - ) - b = paramak.InboardFirstwallFCCS(central_column_shield=a, thickness=20, rotation_angle=180) - assert a.solid is not None - assert b.solid is not None - assert a.volume() > b.volume() - - def test_construction_with_wrong_column_shield_type(self): - def test_construction_with_string(): - """Only CenterColumnShields are acceptable inputs for inputs, this - should fail as it trys to use a string.""" - - b = paramak.InboardFirstwallFCCS(central_column_shield="incorrect type", thickness=20, rotation_angle=180) - b.solid - - self.assertRaises(ValueError, test_construction_with_string) - - def test_boolean_union(self): - """Makes two halves of a 360 firstwall and performs a union and checks - that the volume corresponds to 2 times the volume of 1 half.""" - - a = paramak.CenterColumnShieldFlatTopCircular( - height=500, arc_height=300, inner_radius=30, mid_radius=70, outer_radius=120 - ) - b = paramak.InboardFirstwallFCCS( - central_column_shield=a, - thickness=20, - rotation_angle=180, - azimuth_placement_angle=0, - ) - - c = paramak.InboardFirstwallFCCS( - central_column_shield=a, - thickness=20, - rotation_angle=180, - azimuth_placement_angle=180, - union=b, - ) - assert np.isclose(c.volume(), 2 * b.volume()) - - def test_azimuth_placement_angle(self): - """Makes two 180 degree firstwalls (one is rotated 90 degree), performs - a cut and checks that the volume corresponds to 0.5 times the volume of - 1 half.""" - - a = paramak.CenterColumnShieldFlatTopCircular( - height=500, arc_height=300, inner_radius=30, mid_radius=70, outer_radius=120 - ) - b = paramak.InboardFirstwallFCCS( - central_column_shield=a, - thickness=20, - rotation_angle=180, - azimuth_placement_angle=0, - ) - - c = paramak.InboardFirstwallFCCS( - central_column_shield=a, - thickness=20, - rotation_angle=180, - azimuth_placement_angle=90, - cut=b, - ) - assert np.isclose(c.volume(), 0.5 * b.volume()) - - def test_cut_attribute(self): - """Creates a firstwall then resets its cut attribute and checks that - the shape is not affected.""" - - a = paramak.CenterColumnShieldCylinder(height=100, inner_radius=20, outer_radius=80) - b = paramak.InboardFirstwallFCCS(central_column_shield=a, thickness=20, rotation_angle=180) - - volume_1 = b.volume() - b.cut = None - volume_2 = b.volume() - assert np.isclose(volume_1, volume_2) diff --git a/tests/tests_units/test_parametric_components/test_inner_tf_coils_circular.py b/tests/tests_units/test_parametric_components/test_inner_tf_coils_circular.py deleted file mode 100644 index 70eea2ce1..000000000 --- a/tests/tests_units/test_parametric_components/test_inner_tf_coils_circular.py +++ /dev/null @@ -1,89 +0,0 @@ -import unittest - -import paramak - - -class TestInnerTfCoilsCircular(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.InnerTfCoilsCircular( - height=500, inner_radius=50, outer_radius=150, number_of_coils=6, gap_size=5 - ) - - def test_default_parameters(self): - """Checks that the default parameters of an InnerTfCoilsCircular are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_start_angle == 0 - assert self.test_shape.workplane == "XY" - assert self.test_shape.rotation_axis == "Z" - - def test_points_calculation(self): - """Checks that the points used to construct the InnerTFCoilsCircular - component are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (49.937460888595446, 2.5, "circle"), - (43.300748759659555, 25.000903120744287, "circle"), - (27.1320420790315, 41.99824154201773, "straight"), - (77.154447582418, 128.6358861991937, "circle"), - (129.90375269002172, 75.00010024693078, "circle"), - (149.97916521970643, 2.5, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - InnerTFCoilsCircular component are calculated correctly from the - parameters given.""" - - assert self.test_shape.processed_points == [ - (49.937460888595446, 2.5, "circle"), - (43.300748759659555, 25.000903120744287, "circle"), - (27.1320420790315, 41.99824154201773, "straight"), - (77.154447582418, 128.6358861991937, "circle"), - (129.90375269002172, 75.00010024693078, "circle"), - (149.97916521970643, 2.5, "straight"), - (49.937460888595446, 2.5, "circle"), - ] - - def test_creation(self): - """Creates an inner tf coil using the InnerTfCoilsCircular parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_azimuth_offset(self): - """Creates an inner tf coil using the InnerTfCoilsCircular parametric - component and checks that the azimuthal start angle can be changed - correctly.""" - - assert self.test_shape.azimuth_placement_angle == [0, 60, 120, 180, 240, 300] - self.test_shape.azimuth_start_angle = 20 - assert self.test_shape.azimuth_placement_angle == [20, 80, 140, 200, 260, 320] - - def test_attributes(self): - """Checks that changing the attributes of InnerTfCoilsCircular affects - the cadquery solid produced.""" - - test_volume = self.test_shape.volume() - - self.test_shape.height = 1000 - assert test_volume == self.test_shape.volume() * 0.5 - self.test_shape.height = 500 - self.test_shape.inner_radius = 30 - assert test_volume < self.test_shape.volume() - self.test_shape.inner_radius = 50 - self.test_shape.outer_radius = 170 - assert test_volume < self.test_shape.volume() - - def test_gap_size(self): - """Checks that a ValueError is raised when a too large gap_size is - used.""" - - def test_incorrect_gap_size(): - self.test_shape.inner_radius = 20 - self.test_shape.outer_radius = 40 - self.test_shape.gap_size = 50 - self.test_shape.solid - - self.assertRaises(ValueError, test_incorrect_gap_size) diff --git a/tests/tests_units/test_parametric_components/test_inner_tf_coils_flat.py b/tests/tests_units/test_parametric_components/test_inner_tf_coils_flat.py deleted file mode 100644 index d514a2ffa..000000000 --- a/tests/tests_units/test_parametric_components/test_inner_tf_coils_flat.py +++ /dev/null @@ -1,142 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestInnerTfCoilsFlat(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.InnerTfCoilsFlat( - height=500, inner_radius=50, outer_radius=150, number_of_coils=6, gap_size=5 - ) - - self.test_shape2 = paramak.InnerTfCoilsFlat( - height=500, - inner_radius=50, - outer_radius=150, - number_of_coils=6, - gap_size=5, - radius_type="straight", - ) - - # hexagon with 0 inner radius - self.test_shape_3 = paramak.InnerTfCoilsFlat( - height=10, - inner_radius=0, - outer_radius=20, - number_of_coils=6, - gap_size=0, - radius_type="straight", - ) - - def test_default_parameters(self): - """Checks that the default parameters of an InnerTfCoilsFlat are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_start_angle == 0 - assert self.test_shape.workplane == "XY" - assert self.test_shape.rotation_axis == "Z" - assert self.test_shape.radius_type == "corner" - - def test_points_calculation(self): - """Checks that the points used to construct the InnerTfCoilsFlat - component are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (49.937460888595446, 2.5), - (27.1320420790315, 41.99824154201773), - (77.154447582418, 128.6358861991937), - (149.97916521970643, 2.5), - ] - - def test_processed_points_calculation(self): - """Checks that the points used to construct the InnerTfCoilsFlat - component are calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (49.937460888595446, 2.5, "straight"), - (27.1320420790315, 41.99824154201773, "straight"), - (77.154447582418, 128.6358861991937, "straight"), - (149.97916521970643, 2.5, "straight"), - (49.937460888595446, 2.5, "straight"), - ] - - def test_creation(self): - """Creates an inner tf coil using the InnerTFCoilsFlat parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_azimuth_offset(self): - """Creates an inner tf coil using the InnerTfCoilsFlat parametric - component and checks that the azimuthal start angle can be changed - correctly.""" - - assert self.test_shape.azimuth_placement_angle == [0, 60, 120, 180, 240, 300] - self.test_shape.azimuth_start_angle = 20 - assert self.test_shape.azimuth_placement_angle == [20, 80, 140, 200, 260, 320] - - def test_attributes(self): - """Checks that changing the attributes of InnerTfCoilsFlat affects the - cadquery solid produced.""" - - test_volume = self.test_shape.volume() - - self.test_shape.height = 1000 - assert test_volume == self.test_shape.volume() * 0.5 - self.test_shape.height = 500 - self.test_shape.inner_radius = 30 - assert test_volume < self.test_shape.volume() - self.test_shape.inner_radius = 50 - self.test_shape.outer_radius = 170 - assert test_volume < self.test_shape.volume() - - def test_gap_size(self): - """Checks that a ValueError is raised when a too large gap_size is - used.""" - - def test_incorrect_gap_size(): - self.test_shape.inner_radius = 20 - self.test_shape.outer_radius = 40 - self.test_shape.gap_size = 50 - self.test_shape.solid - - self.assertRaises(ValueError, test_incorrect_gap_size) - - def test_radius_type(self): - """Checks that a ValueError is raised when radius_type is not a - valid option.""" - - def test_incorrect_radius_type(): - self.test_shape.radius_type = "coucou" - - self.assertRaises(ValueError, test_incorrect_radius_type) - - def test_volume_changes_with_radius_type(self): - """Checks the analytical volume of the hex shaped extrusion and - that adding a hole reduces voulume.""" - - hex_volume = self.test_shape_3.volume() - hex_with_hole = self.test_shape_3 - hex_with_hole.inner_radius = 1 - - assert hex_volume > hex_with_hole.volume() - assert pytest.approx(hex_volume, abs=0.5) == 1385.6 * 10 - - def test_volume_changes_with_radius_type_for_corners(self): - """Checks the analytical volume of the hex shaped extrusion and - that adding a hole reduces voulume when the radius is to the corners.""" - - hex_shape = self.test_shape_3 - hex_shape.radius_type = "corner" - hex_volume = hex_shape.volume() - - assert pytest.approx(hex_volume, abs=0.5) == 1039.2 * 10 - - hex_with_hole = self.test_shape_3 - hex_with_hole.radius_type = "corner" - hex_with_hole.inner_radius = 2 - - assert hex_volume > hex_with_hole.volume() diff --git a/tests/tests_units/test_parametric_components/test_plasma.py b/tests/tests_units/test_parametric_components/test_plasma.py deleted file mode 100644 index f7fb804a5..000000000 --- a/tests/tests_units/test_parametric_components/test_plasma.py +++ /dev/null @@ -1,209 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -import paramak - - -class TestPlasma(unittest.TestCase): - def test_plasma_attributes(self): - """Creates a plasma object using the Plasma parametric component and - checks that its attributes can be set correctly.""" - - test_plasma = paramak.Plasma() - - assert isinstance(test_plasma.elongation, float) - - def test_plasma_elongation_min_setting(): - """checks ValueError is raised when an elongation < 0 is specified""" - - test_plasma.elongation = -1 - - self.assertRaises(ValueError, test_plasma_elongation_min_setting) - - def test_plasma_elongation_max_setting(): - """checks ValueError is raised when an elongation > 4 is specified""" - - test_plasma.elongation = 400 - - self.assertRaises(ValueError, test_plasma_elongation_max_setting) - - def minor_radius_out_of_range(): - """checks ValueError is raised when an minor_radius < 1 is - specified""" - - test_plasma.minor_radius = 0.5 - - self.assertRaises(ValueError, minor_radius_out_of_range) - - def major_radius_out_of_range(): - """checks ValueError is raised when an manor_radius < 1 is - specified""" - - test_plasma.major_radius = 0.5 - - self.assertRaises(ValueError, major_radius_out_of_range) - - def test_plasma_points_of_interest(self): - test_plasma = paramak.Plasma(vertical_displacement=2) - assert test_plasma.high_point == ( - test_plasma.major_radius - test_plasma.triangularity * test_plasma.minor_radius, - test_plasma.elongation * test_plasma.minor_radius + test_plasma.vertical_displacement, - ) - assert test_plasma.low_point == ( - test_plasma.major_radius - test_plasma.triangularity * test_plasma.minor_radius, - -test_plasma.elongation * test_plasma.minor_radius + test_plasma.vertical_displacement, - ) - assert test_plasma.outer_equatorial_point == ( - test_plasma.major_radius + test_plasma.minor_radius, - test_plasma.vertical_displacement, - ) - assert test_plasma.inner_equatorial_point == ( - test_plasma.major_radius - test_plasma.minor_radius, - test_plasma.vertical_displacement, - ) - - def test_plasma_x_points(self): - """Creates several plasmas with different configurations using the - Plasma parametric component and checks the location of the x point for - each.""" - - for (triangularity, elongation, minor_radius, major_radius, vertical_displacement,) in zip( - [-0.7, 0, 0.5], # triangularity - [1, 1.5, 2], # elongation - [100, 200, 300], # minor radius - [300, 400, 600], # major radius - [0, -10, 5], - ): # displacement - - for config in ["non-null", "single-null", "double-null"]: - - # Run - test_plasma = paramak.Plasma( - configuration=config, - triangularity=triangularity, - elongation=elongation, - minor_radius=minor_radius, - major_radius=major_radius, - vertical_displacement=vertical_displacement, - ) - - # Expected - expected_lower_x_point, expected_upper_x_point = None, None - if config == "single-null" or config == "double-null": - expected_lower_x_point = ( - 1 - (1 + test_plasma.x_point_shift) * triangularity * minor_radius, - -(1 + test_plasma.x_point_shift) * elongation * minor_radius + vertical_displacement, - ) - - if config == "double-null": - expected_upper_x_point = ( - expected_lower_x_point[0], - (1 + test_plasma.x_point_shift) * elongation * minor_radius + vertical_displacement, - ) - - # Check - for point, expected_point in zip( - [test_plasma.lower_x_point, test_plasma.upper_x_point], - [expected_lower_x_point, expected_upper_x_point], - ): - assert point == expected_point - - def test_plasma_x_points_plasmaboundaries(self): - """Creates several plasmas with different configurations using the - PlasmaBoundaries parametric component and checks the location of the x - point for each.""" - - for A, triangularity, elongation, minor_radius, major_radius in zip( - [0, 0.05, 0.05], # A - [-0.7, 0, 0.5], # triangularity - [1, 1.5, 2], # elongation - [100, 200, 300], # minor radius - [300, 400, 600], - ): # major radius - - for config in ["non-null", "single-null", "double-null"]: - - # Run - test_plasma = paramak.PlasmaBoundaries( - configuration=config, - A=A, - triangularity=triangularity, - elongation=elongation, - minor_radius=minor_radius, - major_radius=major_radius, - ) - - # Expected - expected_lower_x_point, expected_upper_x_point = None, None - if config == "single-null" or config == "double-null": - expected_lower_x_point = ( - 1 - (1 + test_plasma.x_point_shift) * triangularity * minor_radius, - -(1 + test_plasma.x_point_shift) * elongation * minor_radius, - ) - - if config == "double-null": - expected_upper_x_point = ( - expected_lower_x_point[0], - -expected_lower_x_point[1], - ) - - # Check - for point, expected_point in zip( - [test_plasma.lower_x_point, test_plasma.upper_x_point], - [expected_lower_x_point, expected_upper_x_point], - ): - assert point == expected_point - - def test_plasmaboundaries_solid(self): - """Create a default PlasmaBoundaries shape and check a solid can be - created""" - test_plasma = paramak.PlasmaBoundaries() - for config in ["non-null", "single-null", "double-null"]: - test_plasma.configuration = config - assert test_plasma.solid is not None - - def test_export_plasma_source(self): - """Creates a plasma using the Plasma parametric component and checks a - stp file of the shape can be exported using the export_stp method.""" - - test_plasma = paramak.Plasma() - - os.system("rm plasma.stp") - - test_plasma.export_stp("plasma.stp") - - assert Path("plasma.stp").exists() - os.system("rm plasma.stp") - - def test_export_plasma_from_points_export(self): - """Creates a plasma using the PlasmaFromPoints parametric component - and checks a stp file of the shape can be exported using the export_stp - method.""" - - test_plasma = paramak.PlasmaFromPoints( - outer_equatorial_x_point=500, - inner_equatorial_x_point=300, - high_point=(400, 200), - rotation_angle=180, - ) - - os.system("rm plasma.stp") - - test_plasma.export_stp("plasma.stp") - assert test_plasma.high_point[0] > test_plasma.inner_equatorial_x_point - assert test_plasma.high_point[0] < test_plasma.outer_equatorial_x_point - assert test_plasma.outer_equatorial_x_point > test_plasma.inner_equatorial_x_point - assert Path("plasma.stp").exists() - os.system("rm plasma.stp") - - def test_plasma_relative_volume(self): - """Creates plasmas using the Plasma parametric component and checks that - the relative volumes of the solids created are correct""" - - test_plasma = paramak.Plasma() - test_plasma_volume = test_plasma.volume() - test_plasma.rotation_angle = 180 - assert test_plasma.volume() == pytest.approx(test_plasma_volume * 0.5) diff --git a/tests/tests_units/test_parametric_components/test_poloidal_field_coil.py b/tests/tests_units/test_parametric_components/test_poloidal_field_coil.py deleted file mode 100644 index 1065f5d2c..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_field_coil.py +++ /dev/null @@ -1,62 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestPoloidalFieldCoil(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.PoloidalFieldCoil(height=50, width=60, center_point=(1000, 500)) - - def test_default_parameters(self): - """Checks that the default parameters of a PoloidalFieldCoil are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_points_calculation(self): - """Checks that the points used to construct the PoloidalFieldCoil are - calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (1030.0, 525.0), - (1030.0, 475.0), - (970.0, 475.0), - (970.0, 525.0), - ] - - def test_processed_points_calculation(self): - """Checks that the processed points used to construct the PoloidalFieldCoil are - calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (1030.0, 525.0, "straight"), - (1030.0, 475.0, "straight"), - (970.0, 475.0, "straight"), - (970.0, 525.0, "straight"), - (1030.0, 525.0, "straight"), - ] - - def test_creation(self): - """Creates a pf coil using the PoloidalFieldCoil parametric component - and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_absolute_volume(self): - """Creates a pf coil using the PoloidalFieldCoil parametric component - and checks that the volume is correct""" - - assert self.test_shape.volume() == pytest.approx(50 * 60 * math.pi * 2 * 1000) - - def test_absolute_areas(self): - """Creates a pf coil using the PoloidalFieldCoil parametric component - and checks that the areas are correct""" - - assert len(self.test_shape.areas) == 4 - assert len(set([round(i) for i in self.test_shape.areas])) == 3 - assert self.test_shape.areas.count(pytest.approx(60 * math.pi * 2 * 1000)) == 2 - assert self.test_shape.areas.count(pytest.approx(50 * math.pi * 2 * 970)) == 1 - assert self.test_shape.areas.count(pytest.approx(50 * math.pi * 2 * 1030)) == 1 diff --git a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case.py b/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case.py deleted file mode 100644 index cdcbae0a9..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case.py +++ /dev/null @@ -1,80 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestPoloidalFieldCoilCase(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.PoloidalFieldCoilCase( - casing_thickness=5, coil_height=50, coil_width=50, center_point=(1000, 500) - ) - - def test_default_parameters(self): - """Checks that the default parameters of a PoloidalFieldCoilCase are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - InnerTfCoilsFlat component are calculated correctly from the parameters - given.""" - - assert self.test_shape.processed_points == [ - (1025.0, 525.0, "straight"), - (1025.0, 475.0, "straight"), - (975.0, 475.0, "straight"), - (975.0, 525.0, "straight"), - (1025.0, 525.0, "straight"), - (1030.0, 530.0, "straight"), - (1030.0, 470.0, "straight"), - (970.0, 470.0, "straight"), - (970.0, 530.0, "straight"), - (1030.0, 530.0, "straight"), - (1025.0, 525.0, "straight"), - ] - - def test_points_calculation(self): - """Checks that the points used to construct the InnerTfCoilsFlat - component are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (1025.0, 525.0), - (1025.0, 475.0), - (975.0, 475.0), - (975.0, 525.0), - (1025.0, 525.0), - (1030.0, 530.0), - (1030.0, 470.0), - (970.0, 470.0), - (970.0, 530.0), - (1030.0, 530.0), - ] - - def test_creation(self): - """Creates a pf coil case using the PoloidalFieldCoilCase parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_absolute_volume(self): - """Creates a pf coil case using the PoloidalFieldCoilCase parametric - component and checks that its volume is correct.""" - - assert self.test_shape.volume() == pytest.approx((math.pi * 2 * 1000) * ((60 * 5 * 2) + (50 * 5 * 2))) - - def test_absolute_areas(self): - """Creates a pf coil case using the PoloidalFieldCoilCase parametric - component and checks that the areas of its faces are correct.""" - - assert len(self.test_shape.areas) == 8 - assert len(set([round(i) for i in self.test_shape.areas])) == 6 - assert self.test_shape.areas.count(pytest.approx(50 * math.pi * 2 * 1000)) == 2 - assert self.test_shape.areas.count(pytest.approx(60 * math.pi * 2 * 1000)) == 2 - assert self.test_shape.areas.count(pytest.approx(50 * math.pi * 2 * 1025)) == 1 - assert self.test_shape.areas.count(pytest.approx(50 * math.pi * 2 * 975)) == 1 - assert self.test_shape.areas.count(pytest.approx(60 * math.pi * 2 * 1030)) == 1 - assert self.test_shape.areas.count(pytest.approx(60 * math.pi * 2 * 970)) == 1 diff --git a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_fc.py b/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_fc.py deleted file mode 100644 index f6000c001..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_fc.py +++ /dev/null @@ -1,44 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestPoloidalFieldCoilCaseFC(unittest.TestCase): - def setUp(self): - self.pf_coil = paramak.PoloidalFieldCoil(height=50, width=60, center_point=(1000, 500)) - - self.test_shape = paramak.PoloidalFieldCoilCaseFC(pf_coil=self.pf_coil, casing_thickness=5) - - def test_default_parameters(self): - """Checks that the default parameters of a PoloidalFieldCoilCaseFC are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_creation(self): - """Creates a pf coil case using the PoloidalFieldCoilCaseFC parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_absolute_volume(self): - """Creates a pf coil case using the PoloidalFieldCoilCaseFC parametric - component and checks that its volume is correct.""" - - assert self.test_shape.volume() == pytest.approx((math.pi * 2 * 1000) * ((50 * 5 * 2) + (70 * 5 * 2))) - - def test_absolute_areas(self): - """Creates a pf coil case using the PoloidalFieldCoilCaseFC parametric - component and checks that the areas of its faces are correct""" - - assert len(self.test_shape.areas) == 8 - assert len(set([round(i) for i in self.test_shape.areas])) == 6 - assert self.test_shape.areas.count(pytest.approx(60 * math.pi * 2 * 1000)) == 2 - assert self.test_shape.areas.count(pytest.approx(70 * math.pi * 2 * 1000)) == 2 - assert self.test_shape.areas.count(pytest.approx(50 * math.pi * 2 * 1030)) == 1 - assert self.test_shape.areas.count(pytest.approx(50 * math.pi * 2 * 970)) == 1 - assert self.test_shape.areas.count(pytest.approx(60 * math.pi * 2 * 1035)) == 1 - assert self.test_shape.areas.count(pytest.approx(60 * math.pi * 2 * 965)) == 1 diff --git a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_set.py b/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_set.py deleted file mode 100644 index c7959cfff..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_set.py +++ /dev/null @@ -1,220 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestPoloidalFieldCoilCaseSet(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.PoloidalFieldCoilCaseSet( - heights=[10, 10, 20, 20], - widths=[10, 10, 20, 40], - center_points=[(100, 100), (100, 150), (50, 200), (50, 50)], - casing_thicknesses=[5, 10, 5, 10], - ) - - def test_default_parameters(self): - """Checks that the default parameters of a PoloidalFieldCoilCaseSet are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the PoloidalFieldCoilCaseSetFC are - calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (105.0, 105.0, "straight"), - (105.0, 95.0, "straight"), - (95.0, 95.0, "straight"), - (95.0, 105.0, "straight"), - (105.0, 105.0, "straight"), - (110.0, 110.0, "straight"), - (110.0, 90.0, "straight"), - (90.0, 90.0, "straight"), - (90.0, 110.0, "straight"), - (110.0, 110.0, "straight"), - (105.0, 155.0, "straight"), - (105.0, 145.0, "straight"), - (95.0, 145.0, "straight"), - (95.0, 155.0, "straight"), - (105.0, 155.0, "straight"), - (115.0, 165.0, "straight"), - (115.0, 135.0, "straight"), - (85.0, 135.0, "straight"), - (85.0, 165.0, "straight"), - (115.0, 165.0, "straight"), - (60.0, 210.0, "straight"), - (60.0, 190.0, "straight"), - (40.0, 190.0, "straight"), - (40.0, 210.0, "straight"), - (60.0, 210.0, "straight"), - (65.0, 215.0, "straight"), - (65.0, 185.0, "straight"), - (35.0, 185.0, "straight"), - (35.0, 215.0, "straight"), - (65.0, 215.0, "straight"), - (70.0, 60.0, "straight"), - (70.0, 40.0, "straight"), - (30.0, 40.0, "straight"), - (30.0, 60.0, "straight"), - (70.0, 60.0, "straight"), - (80.0, 70.0, "straight"), - (80.0, 30.0, "straight"), - (20.0, 30.0, "straight"), - (20.0, 70.0, "straight"), - (80.0, 70.0, "straight"), - (105.0, 105.0, "straight"), - ] - - def test_points_calculation(self): - """Checks that the points used to construct the PoloidalFieldCoilCaseSetFC are - calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (105.0, 105.0), - (105.0, 95.0), - (95.0, 95.0), - (95.0, 105.0), - (105.0, 105.0), - (110.0, 110.0), - (110.0, 90.0), - (90.0, 90.0), - (90.0, 110.0), - (110.0, 110.0), - (105.0, 155.0), - (105.0, 145.0), - (95.0, 145.0), - (95.0, 155.0), - (105.0, 155.0), - (115.0, 165.0), - (115.0, 135.0), - (85.0, 135.0), - (85.0, 165.0), - (115.0, 165.0), - (60.0, 210.0), - (60.0, 190.0), - (40.0, 190.0), - (40.0, 210.0), - (60.0, 210.0), - (65.0, 215.0), - (65.0, 185.0), - (35.0, 185.0), - (35.0, 215.0), - (65.0, 215.0), - (70.0, 60.0), - (70.0, 40.0), - (30.0, 40.0), - (30.0, 60.0), - (70.0, 60.0), - (80.0, 70.0), - (80.0, 30.0), - (20.0, 30.0), - (20.0, 70.0), - (80.0, 70.0), - ] - - def test_creation(self): - """Creates a set of pf coils using the PoloidalFieldCoilCaseSet - parametric component and passing all required args, and checks - that a solid with the correct number of solids is created.""" - - assert self.test_shape.solid is not None - assert len(self.test_shape.solid.Solids()) == 4 - - def test_creation_with_zero_thickness(self): - """Creates a set of pf coils using the PoloidalFieldCoilCaseSet - parametric component and passing a 0 entry into the casing_thicknesses - list, and checks that a solid with the correct number of solids is - created.""" - - self.test_shape.casing_thicknesses = [5, 0, 10, 10] - - assert self.test_shape.solid is not None - assert len(self.test_shape.solid.Solids()) == 3 - - def test_absolute_volume(self): - """Creates a set of pf coils using the PoloidalFieldCoilCaseSet - parametric component and checks that the volume is correct.""" - - assert self.test_shape.volume() == pytest.approx( - (((20 * 5 * 2) + (10 * 5 * 2)) * math.pi * 2 * 100) - + (((30 * 10 * 2) + (10 * 10 * 2)) * math.pi * 2 * 100) - + (((30 * 5 * 2) + (20 * 5 * 2)) * math.pi * 2 * 50) - + (((60 * 10 * 2) + (20 * 10 * 2)) * math.pi * 2 * 50) - ) - - def test_absolute_areas(self): - """Creates a set of pf coils using the PoloidalFieldCoilCaseSet - parametric component and checks that the areas are correct""" - # self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == (4 + 4) * 4 - assert len(set([round(i) for i in self.test_shape.areas])) == 16 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 2 * 100)) == 6 - assert self.test_shape.areas.count(pytest.approx(40 * math.pi * 2 * 50)) == 4 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 100)) == 4 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 50)) == 2 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 2 * 105)) == 3 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 2 * 95)) == 2 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 110)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 90)) == 1 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 115)) == 1 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 85)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 60)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 40)) == 2 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 65)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 70)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 30)) == 1 - assert self.test_shape.areas.count(pytest.approx(40 * math.pi * 2 * 80)) == 1 - - def test_absolute_areas_180_rotation(self): - """Creates a set of pf coils using the PoloidalFieldCoilCaseSet - parametric component and checks that the areas are correct""" - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == (4 + 4 + 2) * 4 - assert len(set([round(area) for area in self.test_shape.areas])) == 20 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 100)) == 6 - assert self.test_shape.areas.count(pytest.approx(40 * math.pi * 50)) == 4 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 100)) == 4 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 50)) == 2 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 105)) == 3 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 95)) == 2 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 110)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 90)) == 1 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 115)) == 1 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 85)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 60)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 40)) == 2 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 65)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 70)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 30)) == 1 - assert self.test_shape.areas.count(pytest.approx(40 * math.pi * 80)) == 1 - - def test_PoloidalFieldCoilCaseSet_incorrect_thicknesses_1(self): - """Checks that an error is raised when a PoloidalFieldCoilCaseSet is made - with the wrong number of casing thicknesses.""" - - def make_PoloidalFieldCoilCaseSet_incorrect_thicknesses_1(): - self.test_shape.casing_thicknesses = [5, 5, 10] - self.test_shape.solid - - self.assertRaises(ValueError, make_PoloidalFieldCoilCaseSet_incorrect_thicknesses_1) - - def test_PoloidalFieldCoil_incorrect_thicknesses_2(self): - """Checks that an error is raised when a PoloidalFieldCoilCaseSet is made - with invalid casing thicknesses.""" - - def make_PoloidalFieldCoilCaseSet_incorrect_thicknesses_2(): - self.test_shape.casing_thicknesses = [5, 5, 5, "ten"] - - self.assertRaises(ValueError, make_PoloidalFieldCoilCaseSet_incorrect_thicknesses_2) - - def test_PoloidalFieldCoil_incorrect_thicknesses_3(self): - """Checks that an error is raised when a PoloidalFieldCoilCaseSet is made - with invalid casing thicknesses.""" - - def make_PoloidalFieldCoilCaseSet_incorrect_thicknesses_3(): - self.test_shape.casing_thicknesses = "ten" - - self.assertRaises(ValueError, make_PoloidalFieldCoilCaseSet_incorrect_thicknesses_3) diff --git a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_set_fc.py b/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_set_fc.py deleted file mode 100644 index 8586a62e9..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_case_set_fc.py +++ /dev/null @@ -1,247 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestPoloidalFieldCoilCaseSetFC(unittest.TestCase): - def setUp(self): - self.pf_coils_set = paramak.PoloidalFieldCoilSet( - heights=[10, 10, 20, 20], - widths=[10, 10, 20, 40], - center_points=[(100, 100), (100, 150), (50, 200), (50, 50)], - ) - - self.test_shape = paramak.PoloidalFieldCoilCaseSetFC( - pf_coils=self.pf_coils_set, - casing_thicknesses=[5, 10, 5, 10], - ) - - def test_default_parameters(self): - """Checks that the default parameters of a PoloidalFieldCoilCaseSetFC are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - PoloidalFieldCoilCaseSetFC are calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (105.0, 105.0, "straight"), - (105.0, 95.0, "straight"), - (95.0, 95.0, "straight"), - (95.0, 105.0, "straight"), - (105.0, 105.0, "straight"), - (110.0, 110.0, "straight"), - (110.0, 90.0, "straight"), - (90.0, 90.0, "straight"), - (90.0, 110.0, "straight"), - (110.0, 110.0, "straight"), - (105.0, 155.0, "straight"), - (105.0, 145.0, "straight"), - (95.0, 145.0, "straight"), - (95.0, 155.0, "straight"), - (105.0, 155.0, "straight"), - (115.0, 165.0, "straight"), - (115.0, 135.0, "straight"), - (85.0, 135.0, "straight"), - (85.0, 165.0, "straight"), - (115.0, 165.0, "straight"), - (60.0, 210.0, "straight"), - (60.0, 190.0, "straight"), - (40.0, 190.0, "straight"), - (40.0, 210.0, "straight"), - (60.0, 210.0, "straight"), - (65.0, 215.0, "straight"), - (65.0, 185.0, "straight"), - (35.0, 185.0, "straight"), - (35.0, 215.0, "straight"), - (65.0, 215.0, "straight"), - (70.0, 60.0, "straight"), - (70.0, 40.0, "straight"), - (30.0, 40.0, "straight"), - (30.0, 60.0, "straight"), - (70.0, 60.0, "straight"), - (80.0, 70.0, "straight"), - (80.0, 30.0, "straight"), - (20.0, 30.0, "straight"), - (20.0, 70.0, "straight"), - (80.0, 70.0, "straight"), - (105.0, 105.0, "straight"), - ] - - def test_points_calculation(self): - """Checks that the points used to construct the PoloidalFieldCoilCaseSetFC are - calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (105.0, 105.0), - (105.0, 95.0), - (95.0, 95.0), - (95.0, 105.0), - (105.0, 105.0), - (110.0, 110.0), - (110.0, 90.0), - (90.0, 90.0), - (90.0, 110.0), - (110.0, 110.0), - (105.0, 155.0), - (105.0, 145.0), - (95.0, 145.0), - (95.0, 155.0), - (105.0, 155.0), - (115.0, 165.0), - (115.0, 135.0), - (85.0, 135.0), - (85.0, 165.0), - (115.0, 165.0), - (60.0, 210.0), - (60.0, 190.0), - (40.0, 190.0), - (40.0, 210.0), - (60.0, 210.0), - (65.0, 215.0), - (65.0, 185.0), - (35.0, 185.0), - (35.0, 215.0), - (65.0, 215.0), - (70.0, 60.0), - (70.0, 40.0), - (30.0, 40.0), - (30.0, 60.0), - (70.0, 60.0), - (80.0, 70.0), - (80.0, 30.0), - (20.0, 30.0), - (20.0, 70.0), - (80.0, 70.0), - ] - - def test_from_pf_coil_set(self): - """Checks that a set of PF coil cases can be constructed from a PF coils object - using the PoloidalField~CoilCaseSetFC parametric shape.""" - - assert self.test_shape.solid is not None - assert len(self.test_shape.solid.Solids()) == 4 - assert len(self.pf_coils_set.solid.Solids()) == 4 - - def test_with_zero_thickness(self): - """Creates a set of PF coil cases from a PF coils object and sets one - of the casing thicknesses to 0.""" - - self.test_shape.casing_thicknesses = [5, 5, 0, 10] - - assert self.test_shape.solid is not None - assert len(self.test_shape.solid.Solids()) == 3 - assert len(self.pf_coils_set.solid.Solids()) == 4 - - def test_from_pf_coil_set_absolute_volume(self): - """Creates a set of pf coil cases from a pf coil set object and checks - that the volume is correct.""" - - assert self.test_shape.volume() == pytest.approx( - (((20 * 5 * 2) + (10 * 5 * 2)) * math.pi * 2 * 100) - + (((30 * 10 * 2) + (10 * 10 * 2)) * math.pi * 2 * 100) - + (((30 * 5 * 2) + (20 * 5 * 2)) * math.pi * 2 * 50) - + (((60 * 10 * 2) + (20 * 10 * 2)) * math.pi * 2 * 50) - ) - - def test_from_pf_coil_set_absolute_areas(self): - """Creates a set of pf coil cases from a pf coil set object and checks - that the areas are correct""" - - assert len(self.test_shape.areas) == 32 - assert len(set([round(i) for i in self.test_shape.areas])) == 16 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 2 * 100)) == 6 - assert self.test_shape.areas.count(pytest.approx(40 * math.pi * 2 * 50)) == 4 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 100)) == 4 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 50)) == 2 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 2 * 105)) == 3 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * 2 * 95)) == 2 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 110)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 90)) == 1 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 115)) == 1 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 85)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 60)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 40)) == 2 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * 2 * 65)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 70)) == 1 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * 2 * 30)) == 1 - assert self.test_shape.areas.count(pytest.approx(40 * math.pi * 2 * 80)) == 1 - - def test_PoloidalFieldCoilCaseSetFC_incorrect_lengths_FC(self): - """Checks that an error is raised when a PoloidalFieldCoilCaseSetFC is made - with the wrong number of casing thicknesses using a coil set object.""" - - def make_PoloidalFieldCoilCaseSetFC_incorrect_lengths_FC(): - self.test_shape.casing_thicknesses = [5, 5, 10] - self.test_shape.solid - - self.assertRaises(ValueError, make_PoloidalFieldCoilCaseSetFC_incorrect_lengths_FC) - - def test_PoloidalFieldCoilCaseSetFC_incorrect_lengths(self): - """Checks that an error is raised when a PoloidalFieldCoilCaseSetFC is made - with the wrong number of casing thicknesses using a list.""" - - def make_PoloidalFieldCoilCaseSetFC_incorrect_lengths(): - self.pf_coils_set.height = 10 - self.pf_coils_set.width = 10 - self.pf_coils_set.center_point = (100, 100) - - self.test_shape.pf_coils = [self.pf_coils_set] - self.test_shape.solid - - self.assertRaises(ValueError, make_PoloidalFieldCoilCaseSetFC_incorrect_lengths) - - def test_PoloidalFieldCoilCaseSetFC_incorrect_pf_coil(self): - """Checks that an error is raised when a PoloidalFieldCoilCaseSetFC is made - with the pf_coils as an incorrect entry.""" - - def make_PoloidalFieldCoilCaseSetFC_incorrect_pf_coil(): - self.test_shape.pf_coils = 20 - self.test_shape.solid - - self.assertRaises(ValueError, make_PoloidalFieldCoilCaseSetFC_incorrect_pf_coil) - - def test_from_list(self): - """Creates a set of PF coil cases from a list of PF coils with a list - of thicknesses.""" - - pf_coils_1 = paramak.PoloidalFieldCoil(height=10, width=10, center_point=(100, 100)) - - pf_coils_2 = paramak.PoloidalFieldCoil(height=10, width=10, center_point=(100, 150)) - - pf_coils_3 = paramak.PoloidalFieldCoil(height=20, width=20, center_point=(50, 200)) - - pf_coils_4 = paramak.PoloidalFieldCoil(height=20, width=40, center_point=(50, 50)) - - test_shape = paramak.PoloidalFieldCoilCaseSetFC( - pf_coils=[pf_coils_1, pf_coils_2, pf_coils_3, pf_coils_4], - casing_thicknesses=[5, 5, 10, 10], - ) - - assert test_shape.solid is not None - assert len(test_shape.solid.Solids()) == 4 - - def test_PoloidalFieldCoilCaseSetFC_with_number_thickness(self): - """Creates a set of PF coil cases from a list of PF coils with a - single numerical thicknesses.""" - - pf_coils_1 = paramak.PoloidalFieldCoil(height=10, width=10, center_point=(100, 100)) - - pf_coils_2 = paramak.PoloidalFieldCoil(height=10, width=10, center_point=(100, 150)) - - pf_coils_3 = paramak.PoloidalFieldCoil(height=20, width=20, center_point=(50, 200)) - - pf_coils_4 = paramak.PoloidalFieldCoil(height=20, width=40, center_point=(50, 50)) - - test_shape = paramak.PoloidalFieldCoilCaseSetFC( - pf_coils=[pf_coils_1, pf_coils_2, pf_coils_3, pf_coils_4], - casing_thicknesses=10, - ) - - assert test_shape.casing_thicknesses == 10 - assert test_shape.solid is not None - assert len(test_shape.solid.Solids()) == 4 diff --git a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_fp.py b/tests/tests_units/test_parametric_components/test_poloidal_field_coil_fp.py deleted file mode 100644 index 674416c15..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_fp.py +++ /dev/null @@ -1,16 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestPoloidalFieldCoilFP(unittest.TestCase): - def test_shape_construction_and_volume(self): - """Cuts a vessel cylinder with several different size port cutters.""" - - test_component = paramak.PoloidalFieldCoilFP(corner_points=[(10, 10), (20, 22)]) - - assert test_component.volume() == pytest.approx(11309.733552923257) - assert test_component.corner_points == [(10, 10), (20, 22)] - assert test_component.solid is not None diff --git a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_set.py b/tests/tests_units/test_parametric_components/test_poloidal_field_coil_set.py deleted file mode 100644 index 07241ba52..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_field_coil_set.py +++ /dev/null @@ -1,141 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestPoloidalFieldCoilSet(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.PoloidalFieldCoilSet( - heights=[10, 15, 5], - widths=[20, 25, 30], - center_points=[(100, 100), (200, 200), (300, 300)], - ) - - def test_default_parameters(self): - """Checks that the default parameters of a PoloidalFieldCoilSet are correct.""" - - assert self.test_shape.rotation_angle == 360 - - def test_points_calculation(self): - """Checks that the points used to construct the PoloidalFieldCoilSet - are calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (110.0, 105.0), - (110.0, 95.0), - (90.0, 95.0), - (90.0, 105.0), - (212.5, 207.5), - (212.5, 192.5), - (187.5, 192.5), - (187.5, 207.5), - (315.0, 302.5), - (315.0, 297.5), - (285.0, 297.5), - (285.0, 302.5), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - PoloidalFieldCoilSet are calculated correctly from the parameters - given.""" - - assert self.test_shape.processed_points == [ - (110.0, 105.0, "straight"), - (110.0, 95.0, "straight"), - (90.0, 95.0, "straight"), - (90.0, 105.0, "straight"), - (212.5, 207.5, "straight"), - (212.5, 192.5, "straight"), - (187.5, 192.5, "straight"), - (187.5, 207.5, "straight"), - (315.0, 302.5, "straight"), - (315.0, 297.5, "straight"), - (285.0, 297.5, "straight"), - (285.0, 302.5, "straight"), - (110.0, 105.0, "straight"), - ] - - def test_creation(self): - """Creates a solid using the PoloidalFieldCoilSet parametric component - and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert len(self.test_shape.solid.Solids()) == 3 - - def test_absolute_volume(self): - """Creates a set of pf coils using the PoloidalFieldCoilSet parametric - component and checks that the volume is correct.""" - - assert self.test_shape.volume() == ( - pytest.approx( - (10 * 20 * math.pi * (2 * 100)) + (15 * 25 * math.pi * (2 * 200)) + (5 * 30 * math.pi * (2 * 300)) - ) - ) - - def test_absolute_areas(self): - """Creates a set of pf coils using the PoloidalFieldCoilSet parametric - component and checks that the areas of its faces are correct.""" - - assert len(self.test_shape.areas) == 12 - assert len(set(round(i) for i in self.test_shape.areas)) == 9 - assert self.test_shape.areas.count(pytest.approx(20 * math.pi * (2 * 100))) == 2 - assert self.test_shape.areas.count(pytest.approx(25 * math.pi * (2 * 200))) == 2 - assert self.test_shape.areas.count(pytest.approx(30 * math.pi * (2 * 300))) == 2 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * (2 * 90))) == 1 - assert self.test_shape.areas.count(pytest.approx(10 * math.pi * (2 * 110))) == 1 - assert self.test_shape.areas.count(pytest.approx(15 * math.pi * (2 * 187.5))) == 1 - assert self.test_shape.areas.count(pytest.approx(15 * math.pi * (2 * 212.5))) == 1 - assert self.test_shape.areas.count(pytest.approx(5 * math.pi * (2 * 285))) == 1 - assert self.test_shape.areas.count(pytest.approx(5 * math.pi * (2 * 315))) == 1 - - def test_PoloidalFieldCoilSet_incorrect_height(self): - """Checks that an error is raised when a PoloidalFieldCoilSet is made - with height passed as the wrong type.""" - - def make_PoloidalFieldCoilSet_incorrect_height(): - paramak.PoloidalFieldCoilSet( - heights=10, - widths=[20, 20, 20], - center_points=[(100, 100), (200, 200), (300, 300)], - ) - - self.assertRaises(ValueError, make_PoloidalFieldCoilSet_incorrect_height) - - def test_PoloidalFieldCoilSet_incorrect_width(self): - """Checks that an error is raised when a PoloidalFieldCoilSet is made - with width passed as the wrong type.""" - - def make_PoloidalFieldCoilSet_incorrect_width(): - paramak.PoloidalFieldCoilSet( - heights=[10, 10, 10], - widths=20, - center_points=[(100, 100), (200, 200), (300, 300)], - ) - - self.assertRaises(ValueError, make_PoloidalFieldCoilSet_incorrect_width) - - def test_PoloidalFieldCoilSet_incorrect_center_points(self): - """Checks that an error is raised when a PoloidalFieldCoilSet is made - with center_points passed as the wrong type.""" - - def make_PoloidalFieldCoilSet_incorrect_center_points(): - paramak.PoloidalFieldCoilSet(heights=[10, 10, 10], widths=[20, 20, 20], center_points=100) - - self.assertRaises(ValueError, make_PoloidalFieldCoilSet_incorrect_center_points) - - def test_PoloidalFieldCoilSet_incorrect_width_length(self): - """Checks that an error is raised when a PoloidalFieldCoilSet is made - with the incorrect number of widths.""" - - def make_PoloidalFieldCoilSet_incorrect_width_length(): - paramak.PoloidalFieldCoilSet( - heights=[10, 10, 10], - widths=[20, 20], - center_points=[(100, 100), (200, 200), (300, 300)], - ) - - self.assertRaises(ValueError, make_PoloidalFieldCoilSet_incorrect_width_length) diff --git a/tests/tests_units/test_parametric_components/test_poloidal_segments.py b/tests/tests_units/test_parametric_components/test_poloidal_segments.py deleted file mode 100644 index e40adb505..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidal_segments.py +++ /dev/null @@ -1,74 +0,0 @@ -import unittest - -import paramak - - -class TestPoloidalSegments(unittest.TestCase): - def test_solid_count_with_incorrect_input(self): - """Checks the segmenter does not take a float as an input.""" - - def create_shape(): - test_shape_to_segment = paramak.PoloidalFieldCoil(height=100, width=100, center_point=(500, 500)) - - paramak.PoloidalSegments( - shape_to_segment=test_shape_to_segment, - center_point=(500, 500), - number_of_segments=22.5, - ) - - self.assertRaises(TypeError, create_shape) - - def test_solid_count_with_incorrect_inputs2(self): - """Checks the segmenter does not take a negative int as an input.""" - - def create_shape(): - test_shape_to_segment = paramak.PoloidalFieldCoil(height=100, width=100, center_point=(500, 500)) - - paramak.PoloidalSegments( - shape_to_segment=test_shape_to_segment, - center_point=(500, 500), - number_of_segments=-5, - ) - - self.assertRaises(ValueError, create_shape) - - def test_solid_count(self): - """Creates a rotated hollow ring and segments it into poloidal - sections.""" - - pf_coil = paramak.PoloidalFieldCoil(height=100, width=100, center_point=(500, 500)) - - test_shape_to_segment = paramak.PoloidalFieldCoilCaseFC(pf_coil=pf_coil, casing_thickness=100) - - test_shape = paramak.PoloidalSegments( - shape_to_segment=test_shape_to_segment, - center_point=(500, 500), - number_of_segments=22, - ) - - assert test_shape.solid is not None - assert len(test_shape.solid.Solids()) == 22 - - def test_solid_count2(self): - """Creates a rotated ring and segments it into poloidal sections.""" - - test_shape_to_segment = paramak.PoloidalFieldCoil(height=100, width=100, center_point=(500, 500)) - - test_shape = paramak.PoloidalSegments( - shape_to_segment=test_shape_to_segment, - center_point=(500, 500), - number_of_segments=22, - ) - - assert test_shape.solid is not None - assert len(test_shape.solid.Solids()) == 22 - - def test_without_shape_to_segment(self): - """Checks a solid can be created if no shape is given""" - test_shape = paramak.PoloidalSegments( - shape_to_segment=None, - center_point=(500, 500), - number_of_segments=22, - ) - - assert test_shape.solid is not None diff --git a/tests/tests_units/test_parametric_components/test_poloidally_segmented_blanket_fp.py b/tests/tests_units/test_parametric_components/test_poloidally_segmented_blanket_fp.py deleted file mode 100644 index b53c1b102..000000000 --- a/tests/tests_units/test_parametric_components/test_poloidally_segmented_blanket_fp.py +++ /dev/null @@ -1,124 +0,0 @@ -import unittest - -import paramak - - -class TestBlanketFP(unittest.TestCase): - def test_creation(self): - blanket = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=0, stop_angle=180, rotation_angle=180) - assert blanket.solid is not None - - def test_creation_with_optimiser(self): - # Default - blanket = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=0, stop_angle=180, rotation_angle=180) - assert blanket.solid is not None - - # With limits - blanket.length_limits = (10, 300) - blanket.nb_segments_limits = (4, 8) - assert blanket.solid is not None - - # With None length_limits - blanket.length_limits = None - blanket.nb_segments_limits = (4, 8) - assert blanket.solid is not None - - # With None nb_segments_limits - blanket.start_angle = 80 - blanket.length_limits = (100, 300) - blanket.nb_segments_limits = None - assert blanket.solid is not None - - def test_optimiser(self): - blanket = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=0, stop_angle=180, rotation_angle=180) - - blanket.length_limits = (100, 300) - blanket.nb_segments_limits = (2, 8) - assert blanket.solid is not None - - def no_possible_config(): - blanket.length_limits = (10, 20) - blanket.nb_segments_limits = (2, 4) - blanket.solid - - self.assertRaises(ValueError, no_possible_config) - - def test_modifying_nb_segments_limits(self): - """creates a shape and checks that modifying the nb_segments_limits - also modifies segmets_angles accordingly - """ - blanket1 = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=0, stop_angle=180, rotation_angle=180) - - blanket2 = paramak.BlanketFPPoloidalSegments( - thickness=20, - start_angle=0, - stop_angle=180, - rotation_angle=180, - cut=blanket1, - ) - - blanket1.nb_segments_limits = (4, 8) - blanket2.nb_segments_limits = (3, 8) - - assert blanket2.volume() != 0 - - def test_segments_angles_is_modified_num_segments(self): - blanket1 = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=0, stop_angle=180, rotation_angle=180) - - blanket2 = paramak.BlanketFPPoloidalSegments( - thickness=20, - start_angle=0, - stop_angle=180, - rotation_angle=180, - cut=blanket1, - ) - - blanket1.num_segments = 8 - blanket2.num_segments = 5 - assert blanket2.volume() != 0 - - def test_num_point_is_affected(self): - blanket = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=0, stop_angle=180, rotation_angle=180) - assert blanket.num_points == blanket.num_segments + 1 - blanket.num_segments = 60 - assert blanket.num_points == blanket.num_segments + 1 - - def test_segment_angles_affects_solid(self): - blanket1 = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=0, stop_angle=180, rotation_angle=180) - blanket2 = paramak.BlanketFPPoloidalSegments( - thickness=20, - start_angle=0, - stop_angle=180, - rotation_angle=180, - cut=blanket1, - ) - blanket2.segments_angles = [0, 25, 50, 90, 130, 150, 180] - assert blanket2.volume() != 0 - - def test_warning_segment_angles(self): - blanket = paramak.BlanketFPPoloidalSegments(thickness=20, start_angle=1, stop_angle=50, rotation_angle=180) - - def warning1(): - blanket.start_angle = 1 - blanket.stop_angle = 50 - blanket.num_segments = None - blanket.segments_angles = [0, 25, 50, 90, 130, 150, 180] - - def warning2(): - blanket.start_angle = None - blanket.stop_angle = None - blanket.num_segments = 7 - blanket.segments_angles = [0, 25, 50, 90, 130, 150, 180] - - self.assertWarns(UserWarning, warning1) - self.assertWarns(UserWarning, warning2) - - def test_creation_with_gaps(self): - blanket = paramak.BlanketFPPoloidalSegments( - thickness=20, - start_angle=0, - stop_angle=180, - rotation_angle=180, - segments_gap=3, - ) - assert blanket.solid is not None diff --git a/tests/tests_units/test_parametric_components/test_port_cutter_circular.py b/tests/tests_units/test_parametric_components/test_port_cutter_circular.py deleted file mode 100644 index fbb297cf8..000000000 --- a/tests/tests_units/test_parametric_components/test_port_cutter_circular.py +++ /dev/null @@ -1,49 +0,0 @@ -import math -import unittest - -import pytest - -import paramak - - -class TestPortCutterCircular(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.PortCutterCircular(distance=300, radius=20) - - def test_default_parameters(self): - """Checks that the default parameters of a PortCutterCircular are correct.""" - - assert self.test_shape.center_point == (0, 0) - assert self.test_shape.workplane == "ZY" - assert self.test_shape.rotation_axis == "Z" - assert self.test_shape.extrusion_start_offset == 1 - assert self.test_shape.name == "circular_port_cutter" - - def test_creation(self): - """Creates a circular port cutter using the PortCutterCircular parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_relative_volume(self): - """Creates PortCutterCircular shapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - - self.test_shape.extrusion_start_offset = 20 - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - - assert self.test_shape.volume() == pytest.approx(test_volume * 4) - - def test_absolute_volume(self): - """Creates a PortCutterCircular shape and checks that its volume is correct.""" - - assert self.test_shape.volume() == pytest.approx(math.pi * (20**2) * 300) - - self.test_shape.extrusion_start_offset = 20 - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - self.test_shape.radius = 10 - - assert self.test_shape.volume() == pytest.approx(math.pi * (10**2) * 300 * 4) diff --git a/tests/tests_units/test_parametric_components/test_port_cutter_rectangular.py b/tests/tests_units/test_parametric_components/test_port_cutter_rectangular.py deleted file mode 100644 index 9fafffb88..000000000 --- a/tests/tests_units/test_parametric_components/test_port_cutter_rectangular.py +++ /dev/null @@ -1,80 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestPortCutterRectangular(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.PortCutterRectangular(width=20, height=40, distance=300) - - def test_default_parameters(self): - """Checks that the default parameters of a PortCutterRectangular are correct.""" - - assert self.test_shape.center_point == (0, 0) - assert self.test_shape.workplane == "ZY" - assert self.test_shape.rotation_axis == "Z" - assert self.test_shape.extrusion_start_offset == 1 - assert self.test_shape.fillet_radius is None - assert self.test_shape.name == "rectangular_port_cutter" - - def test_creation(self): - """Creates a rectangular port cutter using the PortCutterRectangular parametric - component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - - def test_relative_volume(self): - """Creates PortCutterRectangular shapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - - self.test_shape.extrusion_start_offset = 20 - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - - assert self.test_shape.volume() == pytest.approx(test_volume * 4) - - def test_absolute_volume(self): - """Creates a PortCutterRectangular shape and checks that its volume is correct.""" - - assert self.test_shape.volume() == pytest.approx(20 * 40 * 300) - - self.test_shape.extrusion_start_offset = 20 - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - self.test_shape.width = 20 - self.test_shape.height = 20 - - assert self.test_shape.volume() == pytest.approx(20 * 20 * 300 * 4) - - def test_workplane(self): - """Creates PortCutterRectangular shapes in different workplanes and checks that - the geometries are correct.""" - - cutting_shape = paramak.RotateStraightShape( - points=[(0, 0), (0, 50), (500, 50), (500, 0)], - workplane="YZ", - ) - self.test_shape.cut = cutting_shape - - assert self.test_shape.volume() == pytest.approx(20 * 40 * 300 * 0.5) - - self.test_shape.workplane = "XZ" - cutting_shape.workplane = "YZ" - - assert self.test_shape.volume() == pytest.approx(20 * 40 * 300 * 0.5) - - def test_filleting(self): - """Creates a PortCutterRectangular shape with filleted edges and checks - that its volume is correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.fillet_radius = 5 - - assert self.test_shape.volume() < test_volume - self.test_shape.workplane = "ZX" - assert self.test_shape.volume() < test_volume - self.test_shape.workplane = "YX" - assert self.test_shape.volume() < test_volume diff --git a/tests/tests_units/test_parametric_components/test_port_cutter_rotated.py b/tests/tests_units/test_parametric_components/test_port_cutter_rotated.py deleted file mode 100644 index f5c08e7d1..000000000 --- a/tests/tests_units/test_parametric_components/test_port_cutter_rotated.py +++ /dev/null @@ -1,152 +0,0 @@ -import unittest - -import numpy as np - -import paramak - - -class TestPortCutterRotated(unittest.TestCase): - def test_shape_construction_and_volume(self): - """Cuts a vessel cylinder with several different size port cutters.""" - - small_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=10, - ) - - large_ports = paramak.PortCutterRotated( - polar_coverage_angle=6, - center_point=(100, 0), - polar_placement_angle=10, - azimuth_placement_angle=np.linspace(0, 360, 4), - max_distance_from_center=1000, - rotation_angle=10, - ) - - vessel_with_out_ports = paramak.CenterColumnShieldCylinder(height=500, inner_radius=200, outer_radius=300) - - vessel_with_small_ports = paramak.CenterColumnShieldCylinder( - height=500, inner_radius=200, outer_radius=300, cut=small_ports - ) - - vessel_with_large_ports = paramak.CenterColumnShieldCylinder( - height=500, inner_radius=200, outer_radius=300, cut=large_ports - ) - - assert large_ports.volume() > small_ports.volume() - assert vessel_with_out_ports.volume() > vessel_with_small_ports.volume() - assert vessel_with_small_ports.volume() > vessel_with_large_ports.volume() - - def test_polar_coverage_angle_impacts_volume(self): - """Checks the volumes of two port cutters with different - polar_coverage_angle and checks angle impacts the volume.""" - - small_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=10, - ) - - large_ports = paramak.PortCutterRotated( - polar_coverage_angle=6, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=10, - ) - - assert large_ports.volume() > small_ports.volume() - - def test_max_distance_from_center_impacts_volume(self): - """Checks the volumes of two port cutters with different - max_distance_from_center and checks distance impacts the volume.""" - - small_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=10, - ) - - large_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=2000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=10, - ) - - assert large_ports.volume() > small_ports.volume() - - def test_azimuth_placement_angle_impacts_volume(self): - """Checks the volumes of two port cutters with different - azimuth_placement_angle and checks distance impacts the volume.""" - - small_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=10, - ) - - large_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 5), - rotation_angle=10, - ) - - assert large_ports.volume() > small_ports.volume() - - def test_rotation_angle_impacts_volume(self): - """Checks the volumes of two port cutters with different - rotation_angle and checks distance impacts the volume.""" - - small_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=10, - ) - - large_ports = paramak.PortCutterRotated( - polar_coverage_angle=5, - center_point=(100, 0), - polar_placement_angle=10, - max_distance_from_center=1000, - azimuth_placement_angle=np.linspace(0, 360, 4), - rotation_angle=20, - ) - - assert large_ports.volume() > small_ports.volume() - - def test_outerpoint_negative(self): - """Tests that when polar_coverage_angle is greater than 180 an error is - raised.""" - - def error(): - paramak.PortCutterRotated( - center_point=(1, 1), - polar_coverage_angle=181, - polar_placement_angle=0, - rotation_angle=10, - ) - - self.assertRaises(ValueError, error) diff --git a/tests/tests_units/test_parametric_components/test_rotated_isosceles_triangle.py b/tests/tests_units/test_parametric_components/test_rotated_isosceles_triangle.py deleted file mode 100644 index d8b4df2af..000000000 --- a/tests/tests_units/test_parametric_components/test_rotated_isosceles_triangle.py +++ /dev/null @@ -1,71 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestRotatedIsoscelesTriangle(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.RotatedIsoscelesTriangle( - height=10, - base_length=20, - pivot_angle=0, - pivot_point=(100, 50), - rotation_angle=45, - ) - - def test_component_creation(self): - """Creates a RotatedTrapezoid object and checks that the .solid is not - None.""" - - assert self.test_shape.solid is not None - - def test_check_number_of_surfaces(self): - """Counts the surfaces in a fully rotated and partly rotated - RotatedTrapezoid.""" - - assert len(self.test_shape.areas) == 5 - - self.test_shape.rotation_angle = 360 - - assert len(self.test_shape.areas) == 3 - - def test_args_do_not_impact_volume(self): - """Changes args that should not impact the volume and checks that they - do not impact the volume""" - - test_shape_vol = self.test_shape.volume() - - self.test_shape.pivot_angle = 180 - - assert pytest.approx(self.test_shape.volume(), rel=0.01) == test_shape_vol - - self.test_shape.pivot_point = (100, 300) - - assert pytest.approx(self.test_shape.volume(), rel=0.01) == test_shape_vol - - def test_args_impact_volume(self): - """Changes args that should impact the volume and checks that the - volume changes as a result of the argument changes""" - - test_shape_vol = self.test_shape.volume() - - self.test_shape.pivot_angle = 45 - - assert self.test_shape.volume() > test_shape_vol - - self.test_shape.height = 42 - - assert self.test_shape.volume() > test_shape_vol - - self.test_shape.height = 10 - self.test_shape.length_2 = 42 - - assert self.test_shape.volume() > test_shape_vol - - self.test_shape.height = 10 - self.test_shape.base_length = 20 - self.test_shape.length_3 = 42 - - assert self.test_shape.volume() > test_shape_vol diff --git a/tests/tests_units/test_parametric_components/test_rotated_trapezoid.py b/tests/tests_units/test_parametric_components/test_rotated_trapezoid.py deleted file mode 100644 index fdefa2bf9..000000000 --- a/tests/tests_units/test_parametric_components/test_rotated_trapezoid.py +++ /dev/null @@ -1,72 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestRotatedTrapezoid(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.RotatedTrapezoid( - length_1=10, - length_2=20, - length_3=30, - pivot_angle=0, - pivot_point=(100, 50), - rotation_angle=45, - ) - - def test_component_creation(self): - """Creates a RotatedTrapezoid object and checks that the .solid is not - None.""" - - assert self.test_shape.solid is not None - - def test_check_number_of_surfaces(self): - """Counts the surfaces in a fully rotated and partly rotated - RotatedTrapezoid.""" - - assert len(self.test_shape.areas) == 6 - - self.test_shape.rotation_angle = 360 - - assert len(self.test_shape.areas) == 4 - - def test_args_do_not_impact_volume(self): - """Changes args that should not impact the volume and checks that they - do not impact the volume""" - - test_shape_vol = self.test_shape.volume() - - self.test_shape.pivot_angle = 180 - - assert pytest.approx(self.test_shape.volume(), rel=0.01) == test_shape_vol - - self.test_shape.pivot_point = (100, 300) - - assert pytest.approx(self.test_shape.volume(), rel=0.01) == test_shape_vol - - def test_args_impact_volume(self): - """Changes args that should impact the volume and checks that the - volume changes as a result of the argument changes""" - - test_shape_vol = self.test_shape.volume() - - self.test_shape.pivot_angle = 45 - - assert self.test_shape.volume() > test_shape_vol - - self.test_shape.length_1 = 42 - - assert self.test_shape.volume() > test_shape_vol - - self.test_shape.length_1 = 10 - self.test_shape.length_2 = 42 - - assert self.test_shape.volume() > test_shape_vol - - self.test_shape.length_1 = 10 - self.test_shape.length_2 = 20 - self.test_shape.length_3 = 42 - - assert self.test_shape.volume() > test_shape_vol diff --git a/tests/tests_units/test_parametric_components/test_shell_fs.py b/tests/tests_units/test_parametric_components/test_shell_fs.py deleted file mode 100644 index 5dbbf48dd..000000000 --- a/tests/tests_units/test_parametric_components/test_shell_fs.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest - -import paramak - - -class TestShellFS(unittest.TestCase): - def setUp(self): - # this is the shape that gets shelled - self.test_shape = paramak.PoloidalFieldCoil(height=50, width=50, rotation_angle=90, center_point=(100, 100)) - - def test_creation_with_different_kinds(self): - - casing_int = paramak.ShellFS(shape=self.test_shape, kind="intersection") - casing_int.export_stp("int.stp") - casing_arc = paramak.ShellFS(shape=self.test_shape, kind="arc") - casing_arc.export_stp("arc.stp") - - assert casing_int.solid is not None - assert casing_int.solid is not None - assert casing_int.volume() > casing_arc.volume() - - def test_creation_with_different_thickness(self): - - casing_small = paramak.ShellFS(shape=self.test_shape, thickness=5) - - casing_large = paramak.ShellFS(shape=self.test_shape, thickness=20) - - assert casing_small.solid is not None - assert casing_large.solid is not None - assert casing_large.volume() > casing_small.volume() diff --git a/tests/tests_units/test_parametric_components/test_test_tf_coil_casing.py b/tests/tests_units/test_parametric_components/test_test_tf_coil_casing.py deleted file mode 100644 index 1f42ac709..000000000 --- a/tests/tests_units/test_parametric_components/test_test_tf_coil_casing.py +++ /dev/null @@ -1,55 +0,0 @@ -import os -import unittest -from pathlib import Path - -import paramak - - -class TestTFCoilCasing(unittest.TestCase): - def setUp(self): - inner_offset = 10 - outer_offset = 10 - magnet_thickness = 5 - magnet_extrude_distance = 10 - vertical_section_offset = 20 - casing_extrude_distance = magnet_extrude_distance * 2 - - # create a princeton D magnet - magnet = paramak.ToroidalFieldCoilPrincetonD( - R1=100, - R2=200, - thickness=magnet_thickness, - distance=magnet_extrude_distance, - number_of_coils=1, - ) - - self.test_shape = paramak.TFCoilCasing( - magnet=magnet, - distance=casing_extrude_distance, - inner_offset=inner_offset, - outer_offset=outer_offset, - vertical_section_offset=vertical_section_offset, - ) - - def test_creation(self): - - assert self.test_shape.solid is not None - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") diff --git a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_coat_hanger.py b/tests/tests_units/test_parametric_components/test_toroidal_field_coil_coat_hanger.py deleted file mode 100644 index 2e27b737d..000000000 --- a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_coat_hanger.py +++ /dev/null @@ -1,249 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestToroidalFieldCoilCoatHanger(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.ToroidalFieldCoilCoatHanger( - horizontal_start_point=(200, 500), - horizontal_length=400, - vertical_mid_point=(700, 0), - vertical_length=500, - thickness=50, - distance=30, - number_of_coils=1, - with_inner_leg=True, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a ToroidalFieldCoilCoatHanger - are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.with_inner_leg - - def test_points_calculation(self): - """Checks that the points used to construct the - ToroidalFieldCoilCoatHanger are calculated correctly from the parameters - given.""" - - assert self.test_shape.points == [ - (200, 500, "straight"), - (600, 500, "straight"), - (700, 250.0, "straight"), - (700, -250.0, "straight"), - (600, -500, "straight"), - (200, -500, "straight"), - (200, -550, "straight"), - (600, -550, "straight"), - (646.423834544263, -518.5695338177052, "straight"), - (746.423834544263, -268.5695338177052, "straight"), - (750, -250.0, "straight"), - (750, 250.0, "straight"), - (746.423834544263, 268.5695338177052, "straight"), - (646.423834544263, 518.5695338177052, "straight"), - (600, 550, "straight"), - (200, 550, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed_points used to construct the - ToroidalFieldCoilCoatHanger are calculated correctly from the parameters - given.""" - - assert self.test_shape.processed_points == [ - (200, 500, "straight"), - (600, 500, "straight"), - (700, 250.0, "straight"), - (700, -250.0, "straight"), - (600, -500, "straight"), - (200, -500, "straight"), - (200, -550, "straight"), - (600, -550, "straight"), - (646.423834544263, -518.5695338177052, "straight"), - (746.423834544263, -268.5695338177052, "straight"), - (750, -250.0, "straight"), - (750, 250.0, "straight"), - (746.423834544263, 268.5695338177052, "straight"), - (646.423834544263, 518.5695338177052, "straight"), - (600, 550, "straight"), - (200, 550, "straight"), - (200, 500, "straight"), - ] - - def test_creation_with_inner_leg(self): - """Creates a tf coil with inner leg using the ToroidalFieldCoilCoatHanger - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - assert self.test_shape.inner_leg_connection_points is not None - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=30) - assert test_inner_leg.solid is not None - - def test_creation_with_inner_leg_with_overlap(self): - """Creates tf coils with overlapping inner legs using the ToroidalFieldCoilCoatHanger - parametric component and checks that a cadquery solid is created correctly.""" - - self.test_shape.horizontal_start_point = (0, 500) - self.test_shape.number_of_coils = 8 - assert self.test_shape.solid is not None - - with_inner_leg_volume = self.test_shape.volume() - - self.test_shape.with_inner_leg = False - without_inner_leg_volume = self.test_shape.volume() - - assert self.test_shape.solid is not None - - test_inner_leg = paramak.ExtrudeStraightShape( - points=[(0, 500), (50, 500), (50, -500), (0, -500)], - distance=30, - azimuth_placement_angle=[0, 45, 90, 135, 180, 225, 270, 315], - ) - inner_leg_volume = test_inner_leg.volume() - - assert with_inner_leg_volume == pytest.approx(without_inner_leg_volume + inner_leg_volume) - - def test_creation_no_inner_leg(self): - """Creates a tf coil with no inner leg using the ToroidalFieldCoilRectangle - parametric component and checks that a cadquery solid is created.""" - - test_volume = self.test_shape.volume() - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=30) - inner_leg_volume = test_inner_leg.volume() - - self.test_shape.with_inner_leg = False - - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(test_volume - inner_leg_volume) - - def test_absolute_volume(self): - """Creates a tf coil using the ToroidalFieldCoilCoatHanger parametric - component and checks that the volume is correc.""" - - assert self.test_shape.volume() == pytest.approx( - (400 * 50 * 30 * 2) - + ((50 * 50 * 30 / 2) * 2) - + (50 * 500 * 30) - + (((150 * 250 * 30) - (((100 * 250) / 2) * 30) - (((100 * 250) / 2) * 30)) * 2) - + (50 * 1000 * 30), - rel=0.1, - ) - - self.test_shape.with_inner_leg = False - assert self.test_shape.volume() == pytest.approx( - (400 * 50 * 30 * 2) - + ((50 * 50 * 30 / 2) * 2) - + (50 * 500 * 30) - + (((150 * 250 * 30) - (((100 * 250) / 2) * 30) - (((100 * 250) / 2) * 30)) * 2), - rel=0.1, - ) - - self.test_shape.with_inner_leg = True - self.test_shape.number_of_coils = 8 - assert self.test_shape.volume() == pytest.approx( - ( - (400 * 50 * 30 * 2) - + ((50 * 50 * 30 / 2) * 2) - + (50 * 500 * 30) - + (((150 * 250 * 30) - (((100 * 250) / 2) * 30) - (((100 * 250) / 2) * 30)) * 2) - + (50 * 1000 * 30) - ) - * 8, - rel=0.1, - ) - - self.test_shape.with_inner_leg = False - assert self.test_shape.volume() == pytest.approx( - ( - (400 * 50 * 30 * 2) - + ((50 * 50 * 30 / 2) * 2) - + (50 * 500 * 30) - + (((150 * 250 * 30) - (((100 * 250) / 2) * 30) - (((100 * 250) / 2) * 30)) * 2) - ) - * 8, - rel=0.1, - ) - - def test_absolute_area(self): - """Creates a tf coil using the ToroidalFieldCoilCoatHanger parametric - component and checks that the areas of the faces are correct.""" - - assert self.test_shape.area == pytest.approx( - ( - ( - (400 * 50 * 2) - + (50 * 50 * 0.5 * 2) - + (((150 * 250) - (100 * 250 * 0.5) - (100 * 250 * 0.5)) * 2) - + (500 * 50) - ) - * 2 - ) - + ((50 * 30) * 4) - + ((400 * 30) * 4) - + ((500 * 30) * 2) - + ((((50**2 + 50**2) ** 0.5) * 30) * 2) - + ((((100**2 + 250**2) ** 0.5) * 30) * 4) - + ((50 * 1000) * 2) - + ((1000 * 30) * 2), - rel=0.1, - ) - assert len(self.test_shape.areas) == 18 - - # TODO update these area calculations now that the inner leg and outer leg are fused - # assert self.test_shape.areas.count(pytest.approx(50 * 30)) == 4 - # assert self.test_shape.areas.count(pytest.approx(400 * 30)) == 4 - assert self.test_shape.areas.count(pytest.approx(500 * 30)) == 2 - assert self.test_shape.areas.count(pytest.approx(((100**2 + 250**2) ** 0.5) * 30)) == 4 - # assert self.test_shape.areas.count(pytest.approx(50 * 1000)) == 2 - # assert self.test_shape.areas.count(pytest.approx(1000 * 30)) == 2 - - self.test_shape.with_inner_leg = False - assert self.test_shape.area == pytest.approx( - ( - ( - (400 * 50 * 2) - + (50 * 50 * 0.5 * 2) - + (((150 * 250) - (100 * 250 * 0.5) - (100 * 250 * 0.5)) * 2) - + (500 * 50) - ) - * 2 - ) - + ((50 * 30) * 2) - + ((400 * 30) * 4) - + ((500 * 30) * 2) - + ((((50**2 + 50**2) ** 0.5) * 30) * 2) - + ((((100**2 + 250**2) ** 0.5) * 30) * 4), - rel=0.1, - ) - - def test_rotation_angle(self): - """Creates a tf coil with a rotation_angle < 360 degrees and checks - that the correct cut is performed and the volume is correct.""" - - self.test_shape.number_of_coils = 8 - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "YZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XY" - self.test_shape.rotation_axis = "Y" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5) diff --git a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_princetond.py b/tests/tests_units/test_parametric_components/test_toroidal_field_coil_princetond.py deleted file mode 100644 index 59108d7cb..000000000 --- a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_princetond.py +++ /dev/null @@ -1,84 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestToroidalFieldCoilPrincetonD(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.ToroidalFieldCoilPrincetonD( - R1=100, - R2=300, - thickness=50, - distance=30, - number_of_coils=1, - with_inner_leg=True, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a ToroidalFieldCoilPrincetonD are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.vertical_displacement == 0 - assert self.test_shape.with_inner_leg - - def test_creation_with_inner_leg(self): - """Creates a tf coil with inner leg using the ToroidalFieldCoilPrincetonD - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - assert self.test_shape.inner_leg_connection_points is not None - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=30) - assert test_inner_leg.solid is not None - - def test_creation_no_inner_leg(self): - """Creates a tf coil with no inner leg using the ToroidalFieldCoilPrincetonD - parametric component and checks that a cadquery solid is created.""" - - test_volume = self.test_shape.volume() - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=30) - test_inner_leg.volume() - - self.test_shape.with_inner_leg = False - - assert self.test_shape.solid is not None - assert self.test_shape.volume() < test_volume - - def test_relative_volume(self): - """Creates tf coil shapes with different numbers of tf coils and checks that - their relative volumes are correct.""" - - self.test_shape.number_of_coils = 4 - test_volume = self.test_shape.volume() - - self.test_shape.number_of_coils = 8 - assert test_volume == pytest.approx(self.test_shape.volume() * 0.5, rel=0.01) - - def test_rotation_angle(self): - """Creates a tf coil with a rotation_angle < 360 degrees and checks - that the correct cut is performed and the volume is correct.""" - - self.test_shape.number_of_coils = 8 - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "YZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XY" - self.test_shape.rotation_axis = "Y" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) diff --git a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_rectangle.py b/tests/tests_units/test_parametric_components/test_toroidal_field_coil_rectangle.py deleted file mode 100644 index 147722820..000000000 --- a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_rectangle.py +++ /dev/null @@ -1,212 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestToroidalFieldCoilRectangle(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.ToroidalFieldCoilRectangle( - horizontal_start_point=(100, 700), - vertical_mid_point=(800, 0), - thickness=50, - distance=30, - number_of_coils=1, - with_inner_leg=True, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a ToroidalFieldCoilRectangle are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.with_inner_leg - - def test_points_calculation(self): - """Checks that the points used to construct the ToroidalFieldCoilRectangle are - calculated correctly from the parameters given.""" - - assert self.test_shape.points == [ - (100, 700, "straight"), - (150, 700, "straight"), - (800, 700, "straight"), - (800, -700, "straight"), - (150, -700, "straight"), - (100, -700, "straight"), - (100, -750, "straight"), - (850, -750, "straight"), - (850, 750, "straight"), - (100, 750, "straight"), - ] - - def test_processed_points_calculation(self): - """Checks that the processed points used to construct the ToroidalFieldCoilRectangle are - calculated correctly from the parameters given.""" - - assert self.test_shape.processed_points == [ - (100, 700, "straight"), - (150, 700, "straight"), - (800, 700, "straight"), - (800, -700, "straight"), - (150, -700, "straight"), - (100, -700, "straight"), - (100, -750, "straight"), - (850, -750, "straight"), - (850, 750, "straight"), - (100, 750, "straight"), - (100, 700, "straight"), - ] - - def test_creation_with_inner_leg(self): - """Creates a tf coil with inner leg using the ToroidalFieldCoilRectangle - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - assert self.test_shape.inner_leg_connection_points is not None - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=30) - assert test_inner_leg.solid is not None - - def test_creation_with_inner_leg_with_overlap(self): - """Creates tf coils with overlapping inner legs using the ToroidalFieldCoilRectangle - parametric component and checks that a cadquery solid is created correctly.""" - - self.test_shape.horizontal_start_point = (0, 700) - self.test_shape.number_of_coils = 8 - assert self.test_shape.solid is not None - - with_inner_leg_volume = self.test_shape.volume() - - self.test_shape.with_inner_leg = False - without_inner_leg_volume = self.test_shape.volume() - - assert self.test_shape.solid is not None - - test_inner_leg = paramak.ExtrudeStraightShape( - points=[(0, 700), (50, 700), (50, -700), (0, -700)], - distance=30, - azimuth_placement_angle=[0, 45, 90, 135, 180, 225, 270, 315], - ) - inner_leg_volume = test_inner_leg.volume() - - assert with_inner_leg_volume == pytest.approx(without_inner_leg_volume + inner_leg_volume) - - def test_creation_no_inner_leg(self): - """Creates a tf coil with no inner leg using the ToroidalFieldCoilRectangle - parametric component and checks that a cadquery solid is created.""" - - test_volume = self.test_shape.volume() - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=30) - inner_leg_volume = test_inner_leg.volume() - - self.test_shape.with_inner_leg = False - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(test_volume - inner_leg_volume) - - def test_absolute_volume(self): - """Creates a tf coil using the ToroidalFieldCoilRectangle parametric - component and checks that the volume is correct.""" - - self.test_shape.thickness = 150 - self.test_shape.distance = 50 - - assert self.test_shape.volume() == pytest.approx((850 * 150 * 50 * 2) + (1400 * 150 * 50 * 2)) - - self.test_shape.with_inner_leg = False - assert self.test_shape.volume() == pytest.approx((850 * 150 * 50 * 2) + (1400 * 150 * 50)) - - self.test_shape.with_inner_leg = True - self.test_shape.number_of_coils = 8 - assert self.test_shape.volume() == pytest.approx(((850 * 150 * 50 * 2) + (1400 * 150 * 50 * 2)) * 8) - - self.test_shape.with_inner_leg = False - assert self.test_shape.volume() == pytest.approx(((850 * 150 * 50 * 2) + (1400 * 150 * 50)) * 8) - - def test_absolute_areas(self): - """Creates tf coils using the ToroidalFieldCoilRectangle parametric - component and checks that the areas of the faces are correct.""" - - self.test_shape.thickness = 150 - self.test_shape.distance = 50 - - assert self.test_shape.area == pytest.approx( - (((850 * 150 * 2) + (1400 * 150)) * 2) - + (1400 * 150 * 2) - + (850 * 50 * 2) - + (1700 * 50) - + (1400 * 50 * 3) - + (700 * 50 * 2) - # + (150 * 50 * 4) - ) - assert len(self.test_shape.areas) == 10 - assert self.test_shape.areas.count(pytest.approx(850 * 50)) == 2 - # TODO update these area calculations now that the inner leg and outer leg are fused - # assert ( - # self.test_shape.areas.count(pytest.approx((850 * 150 * 2) + (1400 * 150))) - # == 2 - # ) - # assert self.test_shape.areas.count(pytest.approx((1400 * 150))) == 2 - # assert self.test_shape.areas.count(pytest.approx(1700 * 50)) == 1 - # assert self.test_shape.areas.count(pytest.approx(1400 * 50)) == 3 - # assert self.test_shape.areas.count(pytest.approx(700 * 50)) == 2 - # assert self.test_shape.areas.count(pytest.approx(150 * 50)) == 4 - - self.test_shape.with_inner_leg = False - assert self.test_shape.area == pytest.approx( - (((850 * 150 * 2) + (1400 * 150)) * 2) - + (850 * 50 * 2) - + (1700 * 50) - + (1400 * 50) - + (700 * 50 * 2) - + (150 * 50 * 2) - ) - - def test_rotation_angle(self): - """Creates tf coils with rotation_angles < 360 degrees in different - workplanes and checks that the correct cuts are performed and their - volumes are correct.""" - - self.test_shape.number_of_coils = 8 - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "YZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XY" - self.test_shape.rotation_axis = "Y" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5) - - def test_ToroidalFieldCoilRectangle_incorrect_horizonal_start_point(self): - """Checks that an error is raised when a ToroidalFieldCoilRectangle is made - with an incorrect horizontal_start_point.""" - - def make_ToroidalFieldCoilRectangle_incorrect_horizontal_start_point(): - self.test_shape.vertical_mid_point = (800, 0) - self.test_shape.horizontal_start_point = (801, 700) - self.test_shape.solid - - self.assertRaises(ValueError, make_ToroidalFieldCoilRectangle_incorrect_horizontal_start_point) - - def test_ToroidalFieldCoilRectangle_incorrect_vertical_mid_point(self): - """Checks that an error is raised when a ToroidalFieldCoilRectangle is made - with an incorrect vertical_mid_point.""" - - def make_ToroidalFieldCoilRectangle_incorrect_vertical_mid_point(): - self.test_shape.horizontal_start_point = (100, 700) - self.test_shape.vertical_mid_point = (800, 701) - self.test_shape.solid - - self.assertRaises(ValueError, make_ToroidalFieldCoilRectangle_incorrect_vertical_mid_point) diff --git a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_rectangle_round_corner.py b/tests/tests_units/test_parametric_components/test_toroidal_field_coil_rectangle_round_corner.py deleted file mode 100644 index 96c8c4f93..000000000 --- a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_rectangle_round_corner.py +++ /dev/null @@ -1,406 +0,0 @@ -from math import pi - -import pytest - -# # removed due to flake 8 comment -# from attr.setters import NO_OP - -from paramak import ToroidalFieldCoilRectangleRoundCorners - -obj = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, 100), - thickness=20, - distance=10, - number_of_coils=1, - with_inner_leg=False, -) - -obj2 = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, 100), - thickness=20, - distance=10, - number_of_coils=1, - with_inner_leg=True, -) - - -def surface_area( - lower_left, - middle_right, - thickness, - extrusion_length, - with_inner_leg=False, - xz_face_only=False, - extrusion_area_only=False, -): - """ - Function calculates the total surface area of the TF coil from the - coordinates given in the find_points function - """ - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=lower_left, - mid_point_coordinates=middle_right, - thickness=thickness, - distance=extrusion_length, - number_of_coils=1, - with_inner_leg=with_inner_leg, - ) - - analyse_attributes = test_object.analyse_attributes - - base, height, inner_rad, outter_rad = analyse_attributes - - # The surface area of the face in XZ plane is divisible into 5 segments - base_segment_area = thickness * (base - inner_rad) - vertical_segment_area = thickness * (height - (inner_rad * 2)) - corner_area = (pi / 4) * (outter_rad**2 - inner_rad**2) - - # XZ plane face area - total_face_area = base_segment_area * 2 + vertical_segment_area + corner_area * 2 - # The surface area of the planes in YZ plane - contour_length = inner_rad * (pi - 8) + pi * outter_rad + 2 * (2 * base + thickness + height) - extrusion_area = contour_length * extrusion_length - # Total Area - total_bounding_surface = total_face_area * 2 + extrusion_area - - if with_inner_leg: - # XZ plane face area - total_face_area += thickness * height - print(total_face_area) - total_leg_surface_area = ( - 2 * height * thickness + 2 * extrusion_length * height + 2 * extrusion_length * thickness - ) - - # Total bounding surface - total_bounding_surface += total_leg_surface_area - print( - "Face area: {}\nExtrusion Ares: {}\ntotal bounding area: {}".format( - total_face_area, extrusion_area, total_bounding_surface - ) - ) - - if xz_face_only: - return total_face_area - - if extrusion_area_only: - return extrusion_area - - return total_bounding_surface - - -def volume( - lower_left, - middle_right, - thickness, - extrusion_length, - with_inner_leg=False, -): - """ - The function calculates the volume from the given coordinates used for - parametarising the component in find_points function in core module it - takes an additional variable for extrusion length which is the thickness - of the coil - """ - - face_area = surface_area( - lower_left, - middle_right, - thickness, - extrusion_length, - xz_face_only=True, - with_inner_leg=with_inner_leg, - ) - print(face_area) - total_shape_volume = face_area * extrusion_length - - return total_shape_volume - - -# Parametric Tests - - -@pytest.mark.parametric -def test_parametric_surface_area_with_leg(): - paramak_area = obj2.area - package_area = surface_area((50, 0), (100, 100), 20, 10, with_inner_leg=True) - assert pytest.approx(package_area) == paramak_area - - -@pytest.mark.parametric -def test_parametric_volume_with_leg(): - paramak_vol = obj2.volume() - package_vol = volume((50, 0), (100, 100), 20, 10, with_inner_leg=True) - assert pytest.approx(package_vol) == paramak_vol - - -@pytest.mark.parametric -def test_parametric_surface_area(): - paramak_area = obj.area - package_area = surface_area((50, 0), (100, 100), 20, 10) - assert pytest.approx(package_area) == paramak_area - - -@pytest.mark.parametric -def test_parametric_volume(): - paramak_vol = obj.volume() - package_vol = volume((50, 0), (100, 100), 20, 10) - assert pytest.approx(package_vol) == paramak_vol - - -# Analytical Tests - - -@pytest.mark.analytical -def test_manual_area(): - analytical = 19872.92 - computational = surface_area((50, 0), (100, 100), 20, 10) - assert pytest.approx(computational) == analytical - - -@pytest.mark.analytical -def test_manual_volume(): - analytical = 64909.73 - computational = volume((50, 0), (100, 100), 20, 10) - assert pytest.approx(computational) == analytical - - -# Input Parameter Tests -# Lower Point Coordinate - - -@pytest.mark.dtype -def test_input_param_lower_inner(): - with pytest.raises(TypeError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=1, - mid_point_coordinates=(100, 100), - thickness=20, - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.length -def test_input_lower_point_tuple(): - with pytest.raises(ValueError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0, 5), - mid_point_coordinates=(100, 100), - thickness=20, - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.dtype -def test_input_tuple_element_type_lower_point(): - with pytest.raises(TypeError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, "string"), - mid_point_coordinates=(100, 100), - thickness=20, - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.dtype -def test_setter_lower_point(): - with pytest.raises(TypeError): - obj2.lower_inner_coordinates = 1 - - -@pytest.mark.length -def test_input_lower_point_tuple_length_with_setter(): - with pytest.raises(ValueError): - obj2.lower_inner_coordinates = (0, 0, 0) - - -@pytest.mark.dtype -def test_lower_point_setter_elements_z(): - with pytest.raises(TypeError): - obj.lower_inner_coordinates = (10, "string") - - -@pytest.mark.dtype -def test_lower_point_setter_elements_x(): - with pytest.raises(TypeError): - obj.lower_inner_coordinates = ("string", 10) - - -# Mid Point Coordinate - - -@pytest.mark.dtype -def test_input_param_mid_point(): - with pytest.raises(TypeError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=1, - thickness=20, - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.length -def test_input_tuple2(): - with pytest.raises(ValueError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, 100, 100), - thickness=20, - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.dtype -def test_input_tuple_element_type_mid_point(): - with pytest.raises(TypeError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, "string"), - thickness=20, - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.dtype -def test_setter_mid_point(): - with pytest.raises(TypeError): - obj.mid_point_coordinates = 1 - - -@pytest.mark.length -def test_input_mid_point_tuple_length_with_setter(): - with pytest.raises(ValueError): - obj2.mid_point_coordinates = (0, 0, 0) - - -@pytest.mark.dtype -def test_mid_point_setter_elements_z(): - with pytest.raises(TypeError): - obj.mid_point_coordinates = (10, "string") - - -@pytest.mark.dtype -def test_mid_point_setter_elements_x(): - with pytest.raises(TypeError): - obj.mid_point_coordinates = ("string", 10) - - -# Coordinate Comparison - - -@pytest.mark.value -def test_input_x_coordinates(): - with pytest.raises(ValueError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(0, 100), - thickness=20, - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.value -def test_x_coords_with_setters(): - with pytest.raises(ValueError): - obj.lower_inner_coordinates = (150, 0) - obj.mid_point_coordinates = (100, 0) - - -# Thickness Parameter - - -@pytest.mark.dtype -def test_input_param_thickness(): - with pytest.raises(TypeError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, 100), - thickness="fail", - distance=10, - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.dtype -def test_input_param_thickness2(): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, 100), - thickness=50, - distance=10, - number_of_coils=1, - ) - inner_radius = test_object.analyse_attributes[2] - outer_radius = test_object.analyse_attributes[3] - - check_inner = 50 * 0.1 - check_outer = 50 * 1.1 - assert inner_radius == check_inner - assert outer_radius == check_outer - - -@pytest.mark.dtype -def test_thickness_setter(): - with pytest.raises(TypeError): - obj.thickness = "string" - - -# Extrusion Distance - - -@pytest.mark.dtype -def test_input_param_distance(): - with pytest.raises(TypeError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, 100), - thickness=20, - distance="fail", - number_of_coils=1, - ) - assert test_object.solid is not None - - -@pytest.mark.dtype -def test_distance_setter(): - with pytest.raises(TypeError): - obj.distance = "string" - - -# Number of Coils - - -@pytest.mark.value -def test_input_num_coils(): - with pytest.raises(TypeError): - test_object = ToroidalFieldCoilRectangleRoundCorners( - lower_inner_coordinates=(50, 0), - mid_point_coordinates=(100, 100), - thickness=20, - distance=10, - number_of_coils=1.5, - ) - assert test_object.solid is not None - - -@pytest.mark.dtype -def test_num_coil_setter(): - with pytest.raises(TypeError): - obj2.number_of_coils = 1.4 diff --git a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_triple_arc.py b/tests/tests_units/test_parametric_components/test_toroidal_field_coil_triple_arc.py deleted file mode 100644 index cf4500b64..000000000 --- a/tests/tests_units/test_parametric_components/test_toroidal_field_coil_triple_arc.py +++ /dev/null @@ -1,86 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestToroidalFieldCoilTripleArc(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.ToroidalFieldCoilTripleArc( - R1=100, - h=100, - radii=(100, 200), - coverages=(10, 60), - thickness=10, - distance=50, - number_of_coils=1, - ) - - def test_default_parameters(self): - """Checks that the default parameters of a ToroidalFieldCoilTripleArc are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.with_inner_leg - assert self.test_shape.vertical_displacement == 0 - - def test_creation_with_inner_leg(self): - """Creates a tf coil with inner leg using the ToroidalFieldCoilTripleArc - parametric component and checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 1000 - assert self.test_shape.inner_leg_connection_points is not None - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=50) - assert test_inner_leg.solid is not None - - def test_creation_no_inner_leg(self): - """Creates a tf coil with no inner leg using the ToroidalFieldCoilRectangle - parametric component and checks that a cadquery solid is created.""" - - test_volume = self.test_shape.volume() - - test_inner_leg = paramak.ExtrudeStraightShape(points=self.test_shape.inner_leg_connection_points, distance=50) - inner_leg_volume = test_inner_leg.volume() - - self.test_shape.with_inner_leg = False - - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(test_volume - inner_leg_volume) - - def test_relative_volume(self): - """Creates tf coil shapes with different numbers of tf coils and checks that - their relative volumes are correct.""" - - test_volume = self.test_shape.volume() - - self.test_shape.number_of_coils = 8 - - assert self.test_shape.volume() == pytest.approx(test_volume * 8, rel=0.01) - - def test_rotation_angle(self): - """Creates tf coils with rotation_angles < 360 in different workplanes - and checks that the correct cuts are performed and their volumes are - correct.""" - - self.test_shape.number_of_coils = 8 - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "YZ" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - self.test_shape.rotation_angle = 360 - self.test_shape.workplane = "XY" - self.test_shape.rotation_axis = "Y" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) diff --git a/tests/tests_units/test_parametric_components/test_vacuum_vessel.py b/tests/tests_units/test_parametric_components/test_vacuum_vessel.py deleted file mode 100644 index eebad1850..000000000 --- a/tests/tests_units/test_parametric_components/test_vacuum_vessel.py +++ /dev/null @@ -1,39 +0,0 @@ -import unittest - -import paramak - - -class TestVacuumVessel(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.VacuumVessel(height=2, inner_radius=1, thickness=0.2) - - def test_creation(self): - """Creates a shape using the VacuumVessel parametric component and - checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - - def test_ports(self): - """Creates a vacuum vessel with ports holes in it and checks that a - caquery solid is created.""" - - cutter1 = paramak.PortCutterRectangular( - distance=3, center_point=(0, 0), height=0.2, width=0.4, fillet_radius=0.01 - ) - cutter2 = paramak.PortCutterRectangular( - distance=3, center_point=(0.5, 0), height=0.2, width=0.4, fillet_radius=0.00 - ) - cutter3 = paramak.PortCutterRectangular(distance=3, center_point=(-0.5, 0), height=0.2, width=0.4) - cutter4 = paramak.PortCutterCircular( - distance=3, - center_point=(0.25, 0), - radius=0.1, - azimuth_placement_angle=45, - ) - cutter5 = paramak.PortCutterRotated((0, 0), azimuth_placement_angle=-90, rotation_angle=10, fillet_radius=0.01) - - pre_cut_volume = self.test_shape.volume() - - self.test_shape.cut = [cutter1, cutter2, cutter3, cutter4, cutter5] - assert self.test_shape.solid is not None - assert self.test_shape.volume() < pre_cut_volume diff --git a/tests/tests_units/test_parametric_components/test_vacuum_vessel_inner_leg.py b/tests/tests_units/test_parametric_components/test_vacuum_vessel_inner_leg.py deleted file mode 100644 index 2bc468256..000000000 --- a/tests/tests_units/test_parametric_components/test_vacuum_vessel_inner_leg.py +++ /dev/null @@ -1,35 +0,0 @@ -import unittest - -import paramak - - -class TestVacuumVessel(unittest.TestCase): - def setUp(self): - self.cutter = paramak.PortCutterRectangular( - width=100, - height=100, - distance=1100, - azimuth_placement_angle=[0, 90, 180, 270], - ) - self.test_shape = paramak.VacuumVesselInnerLeg( - inner_height=1100, - inner_radius=700, - inner_leg_radius=100, - thickness=100, - ) - self.test_shape_cut = paramak.VacuumVesselInnerLeg( - inner_height=1100, - inner_radius=700, - inner_leg_radius=100, - thickness=100, - cut=self.cutter, - ) - - def test_creation(self): - """Creates a shape using the VacuumVessel parametric component and - checks that a cadquery solid is created.""" - - assert self.test_shape.solid is not None - - def test_cut(self): - assert self.test_shape.volume() != self.test_shape_cut.volume() diff --git a/tests/tests_units/test_parametric_reactors/__init__.py b/tests/tests_units/test_parametric_reactors/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/tests_units/test_parametric_reactors/test_ball_reactor.py b/tests/tests_units/test_parametric_reactors/test_ball_reactor.py deleted file mode 100644 index 54a09f5c3..000000000 --- a/tests/tests_units/test_parametric_reactors/test_ball_reactor.py +++ /dev/null @@ -1,274 +0,0 @@ -import os -import time -import unittest -import warnings -from pathlib import Path - -import paramak - - -class TestBallReactor(unittest.TestCase): - """Tests functionality of the BallReactor class""" - - def setUp(self): - self.test_reactor = paramak.BallReactor( - inner_bore_radial_thickness=50, - inboard_tf_leg_radial_thickness=200, - center_column_shield_radial_thickness=50, - divertor_radial_thickness=100, - inner_plasma_gap_radial_thickness=150, - plasma_radial_thickness=100, - outer_plasma_gap_radial_thickness=50, - plasma_gap_vertical_thickness=50, - firstwall_radial_thickness=50, - blanket_radial_thickness=100, - blanket_rear_wall_radial_thickness=10, - elongation=2, - triangularity=0.55, - number_of_tf_coils=16, - rotation_angle=180, - ) - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 25 - assert len(self.test_reactor.input_variable_names) == 25 - - def test_creation_with_narrow_divertor(self): - """Creates a BallReactor with a narrow divertor and checks that the correct - number of components are created.""" - - self.test_reactor.divertor_radial_thickness = 50 - - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 8 - - def test_creation_with_wide_divertor(self): - """Creates a BallReactor with a wide divertor and checks that the correct - number of components are created.""" - - self.test_reactor.divertor_radial_thickness = 172.5 - - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 8 - - def test_svg_creation(self): - """Creates a BallReactor and checks that an svg image of the reactor can be - exported using the export_svg method.""" - - os.system("rm test_ballreactor_image.svg") - self.test_reactor.export_svg("filename.svg") - assert Path("filename.svg").exists() is True - os.system("rm filename.svg") - - def test_with_pf_coils(self): - """Checks that a BallReactor with optional pf coils can be created and that - the correct number of components are created.""" - - self.test_reactor.pf_coil_radial_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_radial_position = [200, 200, 200, 200] - self.test_reactor.pf_coil_vertical_position = [200, 100, -100, -200] - self.test_reactor.pf_coil_case_thickness = 10 - - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_rotation_angle_error(self): - """Checks that an error is raised when an angle is over 360.""" - - def invalid_rotation_angle(): - self.test_reactor.rotation_angle = 361 - - self.assertRaises(ValueError, invalid_rotation_angle) - - def test_pf_coil_thicknesses_error(self): - """Checks that an error is raised when invalid pf_coil_radial_thicknesses and - pf_coil_vertical_thicknesses are specified.""" - - def invalid_pf_coil_radial_thicknesses(): - self.test_reactor.pf_coil_radial_thicknesses = 2 - - self.assertRaises(ValueError, invalid_pf_coil_radial_thicknesses) - - def invalid_pf_coil_vertical_thicknesses(): - self.test_reactor.pf_coil_vertical_thicknesses = 2 - - self.assertRaises(ValueError, invalid_pf_coil_vertical_thicknesses) - - def test_with_pf_and_tf_coils(self): - """Checks that a BallReactor with optional pf and tf coils can be created and - that the correct number of components are created.""" - - self.test_reactor.pf_coil_radial_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_radial_position = [200, 200, 200, 200] - self.test_reactor.pf_coil_vertical_position = [200, 100, -100, -200] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.pf_coil_case_thicknesses = [10, 10, 10, 10] - self.test_reactor.outboard_tf_coil_radial_thickness = 50 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 50 - - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 17 - - def test_rotation_angle_warning(self): - """Creates a BallReactor with rotation_angle = 360 and checks that the correct - warning message is printed.""" - - def warning_trigger(): - self.test_reactor.rotation_angle = 360 - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - warning_trigger() - assert len(w) == 1 - assert issubclass(w[-1].category, UserWarning) - assert "360 degree rotation may result in a Standard_ConstructionError or AttributeError" in str( - w[-1].message - ) - - def test_ball_reactor_hash_value(self): - """Creates a ball reactor and checks that all shapes in the reactor are - created when .shapes_and_components is first called. Checks that when - .shapes_and_components is called again with no changes to the reactor, - the shapes in the reactor are not reconstructed and the previously - constructed shapes are returned. Checks that when - .shapes_and_components is called again with changes to the reactor, the - shapes in the reactor are reconstructed and these new shapes are - returned. Checks that the reactor_hash_value is only updated when the - reactor is reconstructed.""" - - self.test_reactor.pf_coil_radial_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_radial_position = [200, 200, 200, 200] - self.test_reactor.pf_coil_vertical_position = [200, 100, -100, -200] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.pf_coil_case_thicknesses = [10, 10, 10, 10] - self.test_reactor.outboard_tf_coil_radial_thickness = 100 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 50 - - assert self.test_reactor.reactor_hash_value is None - # commented out as code inspector suggests all attributs should be - # declaired in class init - # for key in [ - # "_plasma", - # "_inboard_tf_coils", - # "_center_column_shield", - # "_divertor_upper", - # "_divertor_lower", - # "_firstwall", - # "_blanket", - # "_blanket_rear_wall", - # "_pf_coils", - # "_pf_coils_casing", - # "_tf_coil", - # ]: - # assert key not in self.test_reactor.__dict__.keys() - assert self.test_reactor.shapes_and_components is not None - - for key in [ - "_plasma", - "_inboard_tf_coils", - "_center_column_shield", - "_divertor_upper", - "_divertor_lower", - "_firstwall", - "_blanket", - "_blanket_rear_wall", - "_pf_coils", - "_pf_coils_casing", - "_tf_coil", - ]: - assert key in self.test_reactor.__dict__.keys() - assert len(self.test_reactor.shapes_and_components) == 17 - assert self.test_reactor.reactor_hash_value is not None - initial_hash_value = self.test_reactor.reactor_hash_value - self.test_reactor.rotation_angle = 270 - assert self.test_reactor.reactor_hash_value == initial_hash_value - assert self.test_reactor.shapes_and_components is not None - assert self.test_reactor.reactor_hash_value != initial_hash_value - - def test_hash_value_time_saving(self): - """Checks that use of conditional reactor reconstruction via the hash value - gives the expected time saving.""" - - self.test_reactor.pf_coil_radial_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_radial_position = [200, 200, 200, 200] - self.test_reactor.pf_coil_vertical_position = [200, 100, -100, -200] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.pf_coil_case_thicknesses = [10, 10, 10, 10] - self.test_reactor.outboard_tf_coil_radial_thickness = 100 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 50 - - start_time = time.time() - self.test_reactor.shapes_and_components - stop_time = time.time() - initial_construction_time = stop_time - start_time - - start_time = time.time() - self.test_reactor.shapes_and_components - stop_time = time.time() - reconstruction_time = stop_time - start_time - - assert reconstruction_time < initial_construction_time - # assert reconstruction_time < initial_construction_time * 0.01 - - def test_divertor_position_error(self): - """checks an invalid divertor position raises the correct - ValueError.""" - - def invalid_position(): - self.test_reactor.divertor_position = "coucou" - - self.assertRaises(ValueError, invalid_position) - - def test_pf_coil_cases_error(self): - """checks an invalid number of coil case thicknesses raises the correct - ValueError.""" - - def invalid_pf_coil_case_thicknesses(): - self.test_reactor.pf_coil_radial_thicknesses = [30, 30, 30, 30] - self.test_reactor.pf_coil_vertical_thicknesses = [30, 30, 30, 30] - self.test_reactor.pf_coil_radial_position = [100, 100, 200, 200] - self.test_reactor.pf_coil_vertical_position = [100, -100, 200, -200] - self.test_reactor.pf_coil_case_thicknesses = [10, 10] - self.test_reactor.create_solids() - - self.assertRaises(ValueError, invalid_pf_coil_case_thicknesses) - - def test_divertor_upper_lower(self): - """Checks that BallReactors with coils with lower and upper divertors - can be created.""" - self.test_reactor.pf_coil_radial_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_radial_position = [200, 200, 200, 200] - self.test_reactor.pf_coil_vertical_position = [200, 100, -100, -200] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.pf_coil_case_thicknesses = [10, 10, 10, 10] - self.test_reactor.outboard_tf_coil_radial_thickness = 50 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 50 - - self.test_reactor.divertor_position = "lower" - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 16 - - self.test_reactor.divertor_position = "upper" - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 16 - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs folders exist.""" - - os.system("rm reactor_solids.stp") - os.system("rm reactor_wires.stp") - - self.test_reactor.export_stp(filename="reactor_solid.stp", mode="solid") - - self.test_reactor.export_stp(filename="reactor_wires.stp", mode="wire") - - assert Path("reactor_solid.stp").is_file() - assert Path("reactor_wires.stp").is_file() diff --git a/tests/tests_units/test_parametric_reactors/test_center_column_study_reactor.py b/tests/tests_units/test_parametric_reactors/test_center_column_study_reactor.py deleted file mode 100644 index dc6c48086..000000000 --- a/tests/tests_units/test_parametric_reactors/test_center_column_study_reactor.py +++ /dev/null @@ -1,111 +0,0 @@ -import os -import unittest -import warnings -from pathlib import Path - -import pytest - -import paramak - - -class TestCenterColumnStudyReactor(unittest.TestCase): - """Test functionality of the CenterColumnStudyReactor class""" - - def setUp(self): - self.test_reactor = paramak.CenterColumnStudyReactor( - inner_bore_radial_thickness=20, - inboard_tf_leg_radial_thickness=50, - center_column_shield_radial_thickness_mid=50, - center_column_shield_radial_thickness_upper=100, - inboard_firstwall_radial_thickness=20, - divertor_radial_thickness=100, - inner_plasma_gap_radial_thickness=80, - plasma_radial_thickness=200, - outer_plasma_gap_radial_thickness=90, - elongation=2.3, - triangularity=0.45, - plasma_gap_vertical_thickness=40, - center_column_arc_vertical_thickness=520, - rotation_angle=359, - ) - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 14 - assert len(self.test_reactor.input_variable_names) == 14 - - def test_creation(self): - """Creates a ball reactor using the CenterColumnStudyReactor parametric_reactor and checks - the correct number of components are created.""" - - assert len(self.test_reactor.shapes_and_components) == 6 - - def test_creation_with_narrow_divertor(self): - """Creates a ball reactor with a narrow divertor using the CenterColumnStudyReactor - parametric reactor and checks that the correct number of components are created.""" - - self.test_reactor.divertor_radial_thickness = 10 - assert len(self.test_reactor.shapes_and_components) == 6 - - def test_svg_creation(self): - """Creates a ball reactor using the CenterColumnStudyReactor parametric_reactor and checks - an svg image of the reactor can be exported.""" - - os.system("rm test_image.svg") - self.test_reactor.export_svg("test_image.svg") - assert Path("test_image.svg").exists() is True - os.system("rm test_image.svg") - - def test_rotation_angle_impacts_volume(self): - """Creates a CenterColumnStudyReactor reactor with a rotation angle of - 90 and another reactor with a rotation angle of 180. Then checks the - volumes of all the components is double in the 180 reactor.""" - - self.test_reactor.rotation_angle = 90 - r90_comp_vols = [comp.volume() for comp in self.test_reactor.shapes_and_components] - self.test_reactor.rotation_angle = 180 - r180_comp_vols = [comp.volume() for comp in self.test_reactor.shapes_and_components] - for r90_vol, r180_vol in zip(r90_comp_vols, r180_comp_vols): - assert r90_vol == pytest.approx(r180_vol * 0.5, rel=0.1) - - def test_rotation_angle_warning(self): - """Checks that the correct warning message is printed when - rotation_angle = 360.""" - - def warning_trigger(): - try: - self.test_reactor.rotation_angle = 360 - self.test_reactor.shapes_and_components - except BaseException: - pass - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - warning_trigger() - assert len(w) == 1 - assert issubclass(w[-1].category, UserWarning) - assert "360 degree rotation may result in a Standard_ConstructionError or AttributeError" in str( - w[-1].message - ) - - def test_export_brep(self): - """Exports a brep file and checks that the output exist""" - - os.system("rm merged.brep") - - self.test_reactor.export_brep(filename="merged.brep") - - assert Path("merged.brep").exists() is True - - os.system("rm merged.brep") - - def test_export_brep_without_extention(self): - """Exports a brep file without the extention and checks that the - output exist""" - - def missing_extention(): - - self.test_reactor.export_brep(filename="test_reactor_missing") - - self.assertRaises(ValueError, missing_extention) diff --git a/tests/tests_units/test_parametric_reactors/test_eu_demo_2015_reactor.py b/tests/tests_units/test_parametric_reactors/test_eu_demo_2015_reactor.py deleted file mode 100644 index 54c8166bc..000000000 --- a/tests/tests_units/test_parametric_reactors/test_eu_demo_2015_reactor.py +++ /dev/null @@ -1,102 +0,0 @@ -import os -import unittest -from pathlib import Path - -import paramak - - -class TestDemo2015Reactor(unittest.TestCase): - """Tests functionality of the TestDemo2015Reactor class""" - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - my_reactor = paramak.EuDemoFrom2015PaperDiagram(number_of_tf_coils=1) - assert len(my_reactor.input_variables.keys()) == 2 - assert len(my_reactor.input_variable_names) == 2 - - def test_plasma_construction(self): - """Creates the plasma part of the EuDemoFrom2015PaperDiagram and checks - the contruction runs""" - - my_reactor = paramak.EuDemoFrom2015PaperDiagram(number_of_tf_coils=1) - plasma = my_reactor.create_plasma() - assert plasma[0].volume() > 0 - - def test_pf_coil_construction(self): - """Creates the pf coil part of the EuDemoFrom2015PaperDiagram and - checks the contruction runs""" - - my_reactor = paramak.EuDemoFrom2015PaperDiagram(number_of_tf_coils=1) - pf_coils = my_reactor.create_pf_coils() - for coil in pf_coils: - assert coil.volume() > 0 - - def test_vessel_construction(self): - """Creates the pf coil part of the EuDemoFrom2015PaperDiagram and - checks the contruction runs""" - - my_reactor = paramak.EuDemoFrom2015PaperDiagram(number_of_tf_coils=1) - vessel_components = my_reactor.create_vessel_components() - for component in vessel_components: - assert component.volume() > 0 - - def test_make_demo_2015_reactor(self): - """Creates a EuDemoFrom2015PaperDiagram reactor and exports the stp - files checking that each component results in a stp file""" - - output_filenames = [ - "plasma.stp", - "outboard_pf_coil_1.stp", - "outboard_pf_coil_2.stp", - "outboard_pf_coil_3.stp", - "outboard_pf_coil_4.stp", - "outboard_pf_coil_5.stp", - "outboard_pf_coil_6.stp", - "pf_coils_1.stp", - "pf_coils_2.stp", - "pf_coils_3.stp", - "pf_coils_4.stp", - "pf_coils_5.stp", - "divertor.stp", - "blanket.stp", - "vessel.stp", - "tf_coil_casing.stp", - ] - os.system("rm *.stp") - my_reactor = paramak.EuDemoFrom2015PaperDiagram(number_of_tf_coils=1) - my_reactor.export_stp(filename=output_filenames) - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm *.stp") - - def test_make_parametric_demo_2015_rector(self): - """Creates a EuDemoFrom2015PaperDiagram reactor with a non default - rotation angle and exports the stp files checking that each component - results in a stp file""" - - output_filenames = [ - "plasma.stp", - "outboard_pf_coil_1.stp", - "outboard_pf_coil_2.stp", - "outboard_pf_coil_3.stp", - "outboard_pf_coil_4.stp", - "outboard_pf_coil_5.stp", - "outboard_pf_coil_6.stp", - "pf_coils_1.stp", - "pf_coils_2.stp", - "pf_coils_3.stp", - "pf_coils_4.stp", - "pf_coils_5.stp", - "divertor.stp", - "blanket.stp", - "vessel.stp", - "tf_coil_casing.stp", - ] - - os.system("rm *.stp") - my_reactor = paramak.EuDemoFrom2015PaperDiagram(number_of_tf_coils=1, rotation_angle=90) - my_reactor.export_stp(filename=output_filenames) - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm *.stp") diff --git a/tests/tests_units/test_parametric_reactors/test_flf_system_code_reactor.py b/tests/tests_units/test_parametric_reactors/test_flf_system_code_reactor.py deleted file mode 100644 index c5bf3b5fc..000000000 --- a/tests/tests_units/test_parametric_reactors/test_flf_system_code_reactor.py +++ /dev/null @@ -1,100 +0,0 @@ -import math -import os -import unittest -from pathlib import Path -import pytest - -import paramak - - -class TestFlfSystemCodeReactor(unittest.TestCase): - """Tests the FlfSystemCodeReactor functionality""" - - def setUp(self): - self.test_reactor = paramak.FlfSystemCodeReactor( - inner_blanket_radius=100, - blanket_thickness=60, - blanket_height=500, - lower_blanket_thickness=50, - upper_blanket_thickness=40, - blanket_vv_gap=20, - upper_vv_thickness=10, - vv_thickness=10, - lower_vv_thickness=10, - rotation_angle=180, - ) - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 10 - assert len(self.test_reactor.input_variable_names) == 10 - - def test_stp_file_creation(self): - """Exports a step file and checks that it was saved successfully""" - - os.system("rm *.stp") - self.test_reactor.export_stp(filename="cylinder.stp") - assert Path("cylinder.stp").is_file() - - def test_multiple_stp_file_creation(self): - """Exports the reactor as separate step files and checks - that they are saved successfully""" - - os.system("rm *.stp") - self.test_reactor.export_stp() - assert Path("lower_vessel.stp").is_file() - assert Path("lower_blanket.stp").is_file() - assert Path("blanket.stp").is_file() - assert Path("upper_blanket.stp").is_file() - assert Path("upper_vessel.stp").is_file() - assert Path("vessel.stp").is_file() - - def test_order_of_names_in_reactor(self): - """tests the order of Shapes in the reactor is as expected""" - - assert self.test_reactor.name == [ - "blanket", - "vessel", - "upper_blanket", - "lower_blanket", - "lower_vessel", - "upper_vessel", - ] - - def test_blanket_volume_against_analytical_volume(self): - """Checks the volume of the blanket is approximately equal - to the analytical volume of the half cylinder""" - - outer_volume = ( - math.pi - * math.pow( - self.test_reactor.inner_blanket_radius + self.test_reactor.blanket_thickness, - 2, - ) - * self.test_reactor.blanket_height - ) - inner_volume = math.pi * math.pow(self.test_reactor.inner_blanket_radius, 2) * self.test_reactor.blanket_height - sector_fraction = 360.0 / self.test_reactor.rotation_angle - blanket_volume = (outer_volume - inner_volume) / sector_fraction - - assert pytest.approx(self.test_reactor.volume()[0]) == blanket_volume - - def test_upper_blanket_volume_against_analytical_volume(self): - """Checks the volume of the upper_blanket is approximately equal - to the analytical volume of the half cylinder""" - - full_rotation_volume = ( - math.pi - * math.pow( - self.test_reactor.inner_blanket_radius - + self.test_reactor.blanket_thickness - + self.test_reactor.blanket_vv_gap, - 2, - ) - * self.test_reactor.upper_blanket_thickness - ) - sector_fraction = 360.0 / self.test_reactor.rotation_angle - blanket_volume = full_rotation_volume / sector_fraction - - assert pytest.approx(self.test_reactor.volume()[2]) == blanket_volume diff --git a/tests/tests_units/test_parametric_reactors/test_iter_reactor.py b/tests/tests_units/test_parametric_reactors/test_iter_reactor.py deleted file mode 100644 index dfe5d42c6..000000000 --- a/tests/tests_units/test_parametric_reactors/test_iter_reactor.py +++ /dev/null @@ -1,104 +0,0 @@ -import os -import unittest -from pathlib import Path - -import paramak - - -class TestITERReactor(unittest.TestCase): - """Tests functionality of the ITERReactor class""" - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - my_reactor = paramak.IterFrom2020PaperDiagram(number_of_tf_coils=1) - assert len(my_reactor.input_variables.keys()) == 2 - assert len(my_reactor.input_variable_names) == 2 - - def test_plasma_construction(self): - """Creates the plasma part of the ITERTokamak and checks - the contruction runs""" - - my_reactor = paramak.IterFrom2020PaperDiagram(number_of_tf_coils=1) - plasma = my_reactor.create_plasma() - assert plasma[0].volume() > 0 - - def test_pf_coil_construction(self): - """Creates the pf coil part of the ITERTokamak and - checks the contruction runs""" - - my_reactor = paramak.IterFrom2020PaperDiagram(number_of_tf_coils=1) - pf_coils = my_reactor.create_pf_coils() - for coil in pf_coils: - assert coil.volume() > 0 - - def test_vessel_construction(self): - """Creates the pf coil part of the ITERTokamak and - checks the contruction runs""" - - my_reactor = paramak.IterFrom2020PaperDiagram(number_of_tf_coils=1) - my_reactor.create_plasma() - vessel_components = my_reactor.create_vessel_components() - for component in vessel_components: - assert component.volume() > 0 - - def test_make_iter_reactor(self): - """Creates a ITERTokamak reactor and exports the stp - files checking that each component results in a stp file""" - - output_filenames = [ - "plasma.stp", - "outboard_pf_coils_1.stp", - "outboard_pf_coils_2.stp", - "outboard_pf_coils_3.stp", - "outboard_pf_coils_4.stp", - "outboard_pf_coils_5.stp", - "outboard_pf_coils_6.stp", - "pf_coil_1.stp", - "pf_coil_2.stp", - "pf_coil_3.stp", - "pf_coil_4.stp", - "pf_coil_5.stp", - "pf_coil_6.stp", - "divertor.stp", - "blanket.stp", - "vessel_inner.stp", - "tf_coils.stp", - ] - os.system("rm *.stp") - my_reactor = paramak.IterFrom2020PaperDiagram(number_of_tf_coils=1) - my_reactor.export_stp(filename=output_filenames) - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm *.stp") - - def test_make_parametric_iter_rector(self): - """Creates a ITERTokamak reactor with a non defaults - rotation angle and exports the stp files checking that each component - results in a stp file""" - - output_filenames = [ - "plasma.stp", - "outboard_pf_coils_1.stp", - "outboard_pf_coils_2.stp", - "outboard_pf_coils_3.stp", - "outboard_pf_coils_4.stp", - "outboard_pf_coils_5.stp", - "outboard_pf_coils_6.stp", - "pf_coil_1.stp", - "pf_coil_2.stp", - "pf_coil_3.stp", - "pf_coil_4.stp", - "pf_coil_5.stp", - "pf_coil_6.stp", - "divertor.stp", - "blanket.stp", - "vessel_inner.stp", - "tf_coils.stp", - ] - os.system("rm *.stp") - my_reactor = paramak.IterFrom2020PaperDiagram(number_of_tf_coils=1, rotation_angle=90) - my_reactor.export_stp(filename=output_filenames) - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm *.stp") diff --git a/tests/tests_units/test_parametric_reactors/test_negative_triangularity_reactor.py b/tests/tests_units/test_parametric_reactors/test_negative_triangularity_reactor.py deleted file mode 100644 index 27b3dc540..000000000 --- a/tests/tests_units/test_parametric_reactors/test_negative_triangularity_reactor.py +++ /dev/null @@ -1,504 +0,0 @@ -import unittest -import pytest -from paramak.parametric_reactors.negative_triangularity_reactor import ( - NegativeTriangularityReactor, -) - - -class TestNegativeTriangularityReactor(unittest.TestCase): - """ - New Test class for the negative triangularity reactor. - """ - - def setUp(self): - self.test_reactor = NegativeTriangularityReactor( - inner_bore_radius=10, - inner_tf_coil_thickness=100, - vacuum_vessel_thickness=50, - central_shield_thickness=20, - wall_to_plasma_gap=50, - plasma_radial_thickness=650, - elongation=2, - triangularity=0.6, - inner_wall_thickness=20, - blanket_thickness=105, - rear_wall_thickness=20, - divertor_radial_thickness=300, - divertor_height_full=350, - rotation_angle=180, - tf_width=75, - number_of_coils=12, - port_side_lengths=[200, 200, 400], - port_heights=[200, 100, 400], - port_angles=[75, 170, 0], - port_z_pos=[500, -500, 0], - pf_coil_heights=[75, 75, 150, 75, 75], - pf_coil_widths=[75, 75, 150, 75, 75], - pf_coil_center_points=[ - (350, 850), - (1350, 650), - (1400, 0), - (1350, -650), - (350, -850), - ], - pf_coil_casing_thickness=[5, 5, 5, 5, 5], - low_aspect=True, - ) - self.test_reactor.create_solid() - - def test_input_variable_names(self): - """tests for the number of inputs variables""" - assert len(self.test_reactor.input_variable_names) == 26 - - def test_bore_radius_small(self): - """Creates the reactor with 0cm inner bore checks if the right - amount of components are adding to the object.""" - self.test_reactor.inner_bore_radius = 0 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_bore_radius_large(self): - """Creates the reactor with 500cm inner bore checks if the - right amount of components are adding to the object.""" - self.test_reactor.inner_bore_radius = 500 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_bore_radius_type(self): - """Checks for bore radius input type""" - with pytest.raises(TypeError): - self.test_reactor.inner_bore_radius = "asd" - assert self.test_reactor.solid is not None - - def test_inner_tf_leg_small(self): - """Creates the reactor with small thickness inner tf coil""" - self.test_reactor.inner_tf_coil_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_inner_tf_leg_large(self): - """Creates the reactor with large thickness inner tf coil""" - self.test_reactor.inner_tf_coil_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_inner_tf_leg(self): - """Checks inner tf coil input type""" - with pytest.raises(TypeError): - self.test_reactor.inner_tf_coil_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_vacuum_vessel_thickness_small(self): - """Creates the reactor with small thickness vacuum vessel""" - self.test_reactor.vacuum_vessel_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_vacuum_vessel_thickness_large(self): - """Creates the reactor with large thickness vacuum vessel""" - self.test_reactor.vacuum_vessel_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_vacuum_vessel_thickness(self): - """Checks vacuum vessel input type""" - with pytest.raises(TypeError): - self.test_reactor.vacuum_vessel_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_central_shield_thickness_small(self): - """Creates the reactor with small thickness inner shield""" - self.test_reactor.central_shield_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_central_shield_thickness_large(self): - """Creates the reactor with large thickness inner shield""" - self.test_reactor.central_shield_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_central_shield_thickness(self): - """Checks inner shield input type""" - with pytest.raises(TypeError): - self.test_reactor.central_shield_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_wall_to_plasma_gap_small(self): - """Creates the reactor with small plasma gap""" - self.test_reactor.wall_to_plasma_gap = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_wall_to_plasma_gap_large(self): - """Creates the reactor with large plasma gap""" - self.test_reactor.wall_to_plasma_gap = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_wall_to_plasma_gap(self): - """Checks plasma gap input type""" - with pytest.raises(TypeError): - self.test_reactor.wall_to_plasma_gap = "asd" - assert self.test_reactor.solid is not None - - def test_plasma_radial_thickness_small(self): - """Creates the reactor with small radial thickness plasma""" - self.test_reactor.plasma_radial_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_plasma_radial_thickness_large(self): - """Creates the reactor with large radial thickness plasma""" - self.test_reactor.plasma_radial_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_plasma_radial_thickness(self): - """Checks input type of radial plasma thickness""" - with pytest.raises(TypeError): - self.test_reactor.plasma_radial_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_elongation_small(self): - """Creates the reactor with small elongation""" - self.test_reactor.elongation = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_elongation_large(self): - """Creates the reactor with large elongation""" - self.test_reactor.elongation = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_elongation(self): - """Checks input type of elongation""" - with pytest.raises(TypeError): - self.test_reactor.elongation = "asd" - assert self.test_reactor.solid is not None - - def test_triangularity_small(self): - """Creates the reactor with small triangularity""" - with pytest.raises(ValueError): - self.test_reactor.triangularity = -5 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_triangularity_large(self): - """Creates the reactor with large triangularity""" - with pytest.raises(ValueError): - self.test_reactor.triangularity = 5 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_triangularity(self): - """Checks input type of triangularity""" - with pytest.raises(TypeError): - self.test_reactor.triangularity = "asd" - assert self.test_reactor.solid is not None - - def test_inner_wall_thickness_small(self): - """Creates the reactor with small inner wall thickness""" - self.test_reactor.inner_wall_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_inner_wall_thickness_large(self): - """Creates the reactor with large inner wall thickness""" - self.test_reactor.inner_wall_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_inner_wall_thickness(self): - """Checks input type of inner wall thickness""" - with pytest.raises(TypeError): - self.test_reactor.inner_wall_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_blanket_thickness_small(self): - """Creates the reactor with small blanket thickness""" - self.test_reactor.blanket_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_blanket_thickness_large(self): - """Creates the reactor with large blanket thickness""" - self.test_reactor.blanket_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_blanket_thickness(self): - """Checks input type of blanket thickness""" - with pytest.raises(TypeError): - self.test_reactor.blanket_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_rear_wall_thickness_small(self): - """Creates the reactor with small rear wall thickness""" - self.test_reactor.rear_wall_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_rear_wall_thickness_large(self): - """Creates the reactor with large rear wall thickness""" - self.test_reactor.rear_wall_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_rear_wall_thickness(self): - """Checks input type of rear wall thickness""" - with pytest.raises(TypeError): - self.test_reactor.rear_wall_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_divertor_radial_thickness_small(self): - """Creates the reactor with small divertor radial thickness""" - self.test_reactor.divertor_radial_thickness = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_divertor_radial_thickness_large(self): - """Creates the reactor with large divertor radial thickness""" - self.test_reactor.divertor_radial_thickness = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_divertor_radial_thickness(self): - """Checks input type of divertor radial thickness""" - with pytest.raises(TypeError): - self.test_reactor.divertor_radial_thickness = "asd" - assert self.test_reactor.solid is not None - - def test_divertor_height_small(self): - """Creates the reactor with small divertor height""" - self.test_reactor.divertor_height = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_divertor_height_large(self): - """Creates the reactor with large divertor height""" - self.test_reactor.divertor_height = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_divertor_height(self): - """Checks input type of divertor height""" - with pytest.raises(TypeError): - self.test_reactor.divertor_height = "asd" - assert self.test_reactor.solid is not None - - def test_tf_width_small(self): - """Creates the reactor with small toroidal field coil width""" - self.test_reactor.tf_width = 1 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_tf_width_large(self): - """Creates the reactor with large toroidal field coil width""" - self.test_reactor.tf_width = 1000 - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_tf_width(self): - """Checks input type of toroidal field coil width""" - with pytest.raises(TypeError): - self.test_reactor.tf_width = "asd" - assert self.test_reactor.solid is not None - - def test_port_side_lengths_list(self): - """Checks port side lengths is a list""" - self.test_reactor.port_side_lengths = [1, 1, 1] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_side_lengths_val_small(self): - """Creates the reactor with small port side lengths""" - self.test_reactor.port_side_lengths = [5, 5, 5] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_side_lengths_val_large(self): - """Creates the reactor with large port side lengths""" - self.test_reactor.port_side_lengths = [50, 50, 50] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_side_lengths_val(self): - """Checks input type of port side lengths""" - with pytest.raises(TypeError): - self.test_reactor.port_side_lengths = "asd" - assert self.test_reactor.solid is not None - - def test_port_thickness_list(self): - """Checks if list is the same length as the other port related lists""" - self.test_reactor.port_heights = [1, 1, 1, 1] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_thickness_val_small(self): - """Creates the reactor with small port thickness""" - self.test_reactor.port_heights = [5, 5, 5] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_thickness_val_large(self): - """Creates the reactor with large port thickness""" - self.test_reactor.port_heights = [50, 50, 50] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_thickness_val(self): - """Checks input type of port thickness""" - with pytest.raises(TypeError): - self.test_reactor.port_heights = "asd" - assert self.test_reactor.solid is not None - - def test_ports_angles_list(self): - """Checks if list is the same length as the other port related lists""" - self.test_reactor.port_angles = [1, 1, 1, 1, 1] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_ports_angles_val_small(self): - """Creates the reactor with small port angles""" - self.test_reactor.port_angles = [5, 5, 5] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_ports_angles_val_large(self): - """Creates the reactor with large port angles""" - self.test_reactor.port_angles = [250, 250, 250] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_ports_angles_val(self): - """Checks input type of port angles""" - with pytest.raises(TypeError): - self.test_reactor.port_angles = "asd" - assert self.test_reactor.solid is not None - - def test_port_z_pos_list(self): - """Checks if the input lists for port Z-positions are the same length""" - self.test_reactor.port_z_pos = [1, 1, 1, 1, 1, 1] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_z_pos_val_small(self): - """Creates the reactor with positive Z-position of ports""" - self.test_reactor.port_z_pos = [10, 150, 200] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_z_pos_val_large(self): - """Creates the reactor with negative Z-position of ports""" - self.test_reactor.port_z_pos = [-10, -150, -200] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_port_z_pos_val(self): - """Checks input type of Z-position of ports""" - with pytest.raises(TypeError): - self.test_reactor.port_z_pos = "asd" - assert self.test_reactor.solid is not None - - def test_pf_coil_heights_list(self): - """Checks if the input lists for poloidal field coil height are the same length""" - self.test_reactor.pf_coil_heights = [1, 1, 1] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_heights_val_small(self): - """Creates the reactor with small poloidal field coil heights""" - self.test_reactor.pf_coil_heights = [5, 5, 5] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_heights_val_large(self): - """Creates the reactor with large poloidal field coil heights""" - self.test_reactor.pf_coil_heights = [50, 50, 50] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_heights_val(self): - """Checks input type of poloidal field coil heights""" - with pytest.raises(TypeError): - self.test_reactor.pf_coil_heights = "asd" - assert self.test_reactor.solid is not None - - def test_pf_coil_widths_list(self): - """Checks if the input lists for poloidal field coil widths are the same length""" - self.test_reactor.pf_coil_widths = [1, 1, 1, 1, 1, 1, 1, 1] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_widths_val_small(self): - """Creates the reactor with small poloidal field coil widths""" - self.test_reactor.pf_coil_widths = [5, 5, 5] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_widths_val_large(self): - """Creates the reactor with large poloidal field coil widths""" - self.test_reactor.pf_coil_widths = [50, 50, 50] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_widths_val(self): - """Checks input type of poloidal field coil widths""" - with pytest.raises(TypeError): - self.test_reactor.pf_coil_widths = "asd" - assert self.test_reactor.solid is not None - - def test_pf_coil_center_points_list(self): - """Checks if the input lists for poloidal field coil center points are the same length""" - self.test_reactor.pf_coil_center_points = [ - (10, 10), - (10, 10), - (10, 10), - (10, 10), - ] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_center_points_val_small(self): - """Creates the reactor with small poloidal field coil center points""" - self.test_reactor.pf_coil_center_points = [(5, 5), (5, 5), (5, 5)] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_center_points_val_large(self): - """Creates the reactor with large poloidal field coil center points""" - self.test_reactor.pf_coil_center_points = [(500, 500), (500, 500), (500, 500)] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_coil_center_points_val(self): - """Checks input type of poloidal field coil center points""" - with pytest.raises(TypeError): - self.test_reactor.pf_coil_center_points = "asd" - assert self.test_reactor.solid is not None - - def test_pf_casing_thickness_list(self): - """Checks if the input lists for poloidal field coils are the same length""" - self.test_reactor.pf_coil_casing_thickness = [1, 1, 1] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_casing_thickness_val_small(self): - """Creates the reactor with small poloidal field coil casing thickness""" - self.test_reactor.pf_coil_casing_thickness = [5, 5, 5] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_casing_thickness_val_large(self): - """Creates the reactor with large poloidal field coil casing thickness""" - self.test_reactor.pf_coil_casing_thickness = [50, 50, 50] - assert self.test_reactor.solid is not None - assert len(self.test_reactor.shapes_and_components) == 12 - - def test_pf_casing_thickness_val(self): - """Checks input type of poloidal field coil casing thickness""" - with pytest.raises(TypeError): - self.test_reactor.pf_coil_casing_thickness = "asd" - assert self.test_reactor.solid is not None diff --git a/tests/tests_units/test_parametric_reactors/test_segmented_blanket_ball_reactor.py b/tests/tests_units/test_parametric_reactors/test_segmented_blanket_ball_reactor.py deleted file mode 100644 index e1a631582..000000000 --- a/tests/tests_units/test_parametric_reactors/test_segmented_blanket_ball_reactor.py +++ /dev/null @@ -1,88 +0,0 @@ -import unittest - -import paramak - - -class TestSegmentedBlanketBallReactor(unittest.TestCase): - """Tests functionality of the SegmentedBlanketBallReactor class""" - - def setUp(self): - self.test_reactor = paramak.SegmentedBlanketBallReactor( - inner_bore_radial_thickness=10, - inboard_tf_leg_radial_thickness=30, - center_column_shield_radial_thickness=60, - divertor_radial_thickness=150, - inner_plasma_gap_radial_thickness=30, - plasma_radial_thickness=300, - outer_plasma_gap_radial_thickness=30, - plasma_gap_vertical_thickness=30, - firstwall_radial_thickness=20, - blanket_radial_thickness=50, - blanket_rear_wall_radial_thickness=30, - elongation=2, - triangularity=0.55, - number_of_tf_coils=16, - rotation_angle=180, - pf_coil_radial_thicknesses=[50, 50, 50, 50], - pf_coil_vertical_thicknesses=[50, 50, 50, 50], - pf_coil_radial_position=[200, 200, 200, 200], - pf_coil_vertical_position=[200, 100, -100, -200], - rear_blanket_to_tf_gap=50, - outboard_tf_coil_radial_thickness=100, - outboard_tf_coil_poloidal_thickness=50, - gap_between_blankets=30, - number_of_blanket_segments=4, - ) - - def test_input_variable_names(self): - """tests that the number of inputs variable is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 28 - assert len(self.test_reactor.input_variable_names) == 28 - - def test_gap_between_blankets_impacts_volume(self): - """Creates a SegmentedBlanketBallReactor with different - gap_between_blankets and checks the volume of the blankes and the - firstwall changes.""" - - self.test_reactor.create_solids() - small_gap_blanket_volume = self.test_reactor._blanket.volume() - small_gap_firstwall_volume = self.test_reactor._firstwall.volume() - - self.test_reactor.gap_between_blankets = 60 - self.test_reactor.create_solids() - large_gap_blanket_volume = self.test_reactor._blanket.volume() - large_gap_firstwall_volume = self.test_reactor._firstwall.volume() - - assert small_gap_blanket_volume > large_gap_blanket_volume - assert small_gap_firstwall_volume > large_gap_firstwall_volume - - def test_number_of_blanket_segments_impacts_volume(self): - """Creates a SegmentedBlanketBallReactor with different - number_of_blanket_segments and checks the volume of the blanket and - firstwall changes.""" - - self.test_reactor.create_solids() - blanket_volume_few_segments = self.test_reactor._blanket.volume() - firstwall_volume_few_segments = self.test_reactor._firstwall.volume() - - self.test_reactor.number_of_blanket_segments = 6 - self.test_reactor.create_solids() - blanket_volume_many_segments = self.test_reactor._blanket.volume() - firstwall_volume_many_segments = self.test_reactor._firstwall.volume() - - assert blanket_volume_many_segments < blanket_volume_few_segments - assert firstwall_volume_many_segments > firstwall_volume_few_segments - - def test_invalid_parameter_error_raises(self): - """Checks that the correct errors are raised when invalid arguments for - parameters are input.""" - - def invalid_gap_between_blankets(): - self.test_reactor.gap_between_blankets = -1 - - def invalid_number_of_blanket_segments(): - self.test_reactor.number_of_blanket_segments = 1 - - self.assertRaises(ValueError, invalid_gap_between_blankets) - self.assertRaises(ValueError, invalid_number_of_blanket_segments) diff --git a/tests/tests_units/test_parametric_reactors/test_single_null_ball_reactor.py b/tests/tests_units/test_parametric_reactors/test_single_null_ball_reactor.py deleted file mode 100644 index a5434b736..000000000 --- a/tests/tests_units/test_parametric_reactors/test_single_null_ball_reactor.py +++ /dev/null @@ -1,111 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestSingleNullBallReactor(unittest.TestCase): - """tests functionality of the test_SingleNullBallReactor class""" - - def setUp(self): - self.test_reactor = paramak.SingleNullBallReactor( - inner_bore_radial_thickness=50, - inboard_tf_leg_radial_thickness=200, - center_column_shield_radial_thickness=50, - divertor_radial_thickness=100, - inner_plasma_gap_radial_thickness=150, - plasma_radial_thickness=100, - outer_plasma_gap_radial_thickness=50, - plasma_gap_vertical_thickness=50, - firstwall_radial_thickness=50, - blanket_radial_thickness=100, - blanket_rear_wall_radial_thickness=10, - elongation=2, - triangularity=0.55, - number_of_tf_coils=4, - rear_blanket_to_tf_gap=10, - outboard_tf_coil_radial_thickness=10, - outboard_tf_coil_poloidal_thickness=10, - divertor_position="lower", - rotation_angle=180, - pf_coil_case_thicknesses=[10, 10, 10, 10], - pf_coil_radial_thicknesses=[20, 50, 50, 20], - pf_coil_vertical_thicknesses=[20, 50, 50, 20], - pf_coil_radial_position=[500, 575, 575, 500], - pf_coil_vertical_position=[300, 100, -100, -300], - ) - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 25 - assert len(self.test_reactor.input_variable_names) == 25 - - def test_single_null_ball_reactor_with_pf_and_tf_coils(self): - """Checks that a SingleNullBallReactor with optional pf and tf coils can - be created and that the correct number of components are produced.""" - - assert len(self.test_reactor.shapes_and_components) == 16 - - def test_single_null_ball_reactor_rotation_angle_impacts_volume(self): - """Creates SingleNullBallReactors with different rotation angles and - checks that the relative volumes of the components are correct.""" - - self.test_reactor.rotation_angle = 90 - test_reactor_90_components = self.test_reactor.shapes_and_components - self.test_reactor.rotation_angle = 180 - test_reactor_180_components = self.test_reactor.shapes_and_components - - for r90, r180 in zip(test_reactor_90_components, test_reactor_180_components): - assert r90.volume() == pytest.approx(r180.volume() * 0.5, rel=0.1) - - def test_hash_value(self): - """Creates a single null ball reactor and checks that all shapes in the - reactor are created when .shapes_and_components is first called. Checks - that when .shapes_and_components is called again with no changes to the - reactor, the shapes in the reactor are not reconstructed and the - previously constructed shapes are returned. Checks that when - .shapes_and_components is called again with changes to the reactor, the - shapes in the reactor are reconstructed and these new shapes are - returned. Checks that the reactor_hash_value is only updated when the - reactor is reconstruced.""" - - assert self.test_reactor.reactor_hash_value is None - # commented out as code inspector suggests all attributs should be - # declaired in class init - # for key in [ - # "_plasma", - # "_inboard_tf_coils", - # "_center_column_shield", - # "_divertor_lower", - # "_firstwall", - # "_blanket", - # "_blanket_rear_wall", - # "_pf_coils", - # "_pf_coils_casing", - # "_tf_coil", - # ]: - # assert key not in self.test_reactor.__dict__.keys() - assert self.test_reactor.shapes_and_components is not None - - for key in [ - "_plasma", - "_inboard_tf_coils", - "_center_column_shield", - "_divertor_lower", - "_firstwall", - "_blanket", - "_blanket_rear_wall", - "_pf_coils", - "_pf_coils_casing", - "_tf_coil", - ]: - assert key in self.test_reactor.__dict__.keys() - assert len(self.test_reactor.shapes_and_components) == 16 - assert self.test_reactor.reactor_hash_value is not None - initial_hash_value = self.test_reactor.reactor_hash_value - self.test_reactor.rotation_angle = 270 - assert self.test_reactor.reactor_hash_value == initial_hash_value - assert self.test_reactor.shapes_and_components is not None - assert self.test_reactor.reactor_hash_value != initial_hash_value diff --git a/tests/tests_units/test_parametric_reactors/test_single_null_submersion_tokamak.py b/tests/tests_units/test_parametric_reactors/test_single_null_submersion_tokamak.py deleted file mode 100644 index 1c396fea0..000000000 --- a/tests/tests_units/test_parametric_reactors/test_single_null_submersion_tokamak.py +++ /dev/null @@ -1,138 +0,0 @@ -import unittest - -import pytest - -import paramak - - -class TestSingleNullSubmersionTokamak(unittest.TestCase): - """Tests functionality of SingleNullSubmersionTokamak class""" - - def setUp(self): - self.test_reactor = paramak.SingleNullSubmersionTokamak( - inner_bore_radial_thickness=30, - inboard_tf_leg_radial_thickness=30, - center_column_shield_radial_thickness=30, - divertor_radial_thickness=80, - inner_plasma_gap_radial_thickness=50, - plasma_radial_thickness=200, - outer_plasma_gap_radial_thickness=50, - firstwall_radial_thickness=30, - blanket_rear_wall_radial_thickness=30, - number_of_tf_coils=16, - rotation_angle=180, - support_radial_thickness=90, - inboard_blanket_radial_thickness=30, - outboard_blanket_radial_thickness=30, - elongation=2.00, - triangularity=0.50, - pf_coil_case_thicknesses=[10, 10, 10, 10], - pf_coil_radial_thicknesses=[20, 50, 50, 20], - pf_coil_vertical_thicknesses=[20, 50, 50, 20], - pf_coil_radial_position=[500, 550, 550, 500], - pf_coil_vertical_position=[270, 100, -100, -270], - rear_blanket_to_tf_gap=50, - outboard_tf_coil_radial_thickness=30, - outboard_tf_coil_poloidal_thickness=30, - divertor_position="lower", - ) - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 26 - assert len(self.test_reactor.input_variable_names) == 26 - - def test_single_null_submersion_tokamak_with_pf_and_tf_coils(self): - """Creates a SingleNullSubmersionTokamak with pf and tf coils and checks - that the correct number of components are created.""" - - self.test_reactor.pf_coil_radial_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50, 50, 50] - self.test_reactor.pf_coil_case_thicknesses = [10, 20, 10, 10] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.outboard_tf_coil_radial_thickness = 100 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 50 - self.test_reactor.number_of_tf_coils = 16 - - assert len(self.test_reactor.shapes_and_components) == 17 - - def test_single_null_submersion_tokamak_rotation_angle_impacts_volume(self): - """Creates SingleNullSubmersionTokamaks with different rotation angles and - checks that the relative volumes of the components are correct.""" - - self.test_reactor.rotation_angle = 90 - comps_90_vol = [comp.volume() for comp in self.test_reactor.shapes_and_components] - self.test_reactor.rotation_angle = 180 - comps_180_vol = [comp.volume() for comp in self.test_reactor.shapes_and_components] - - for vol_90, vol_180 in zip(comps_90_vol, comps_180_vol): - assert vol_90 == pytest.approx(vol_180 * 0.5, rel=0.1) - - def test_hash_value(self): - """Creates a single null submersion reactor and checks that all shapes - in the reactor are created when .shapes_and_components is first called. - Checks that when .shapes_and_components is called again with no changes - to the reactor, the shapes in the reactor are reconstructed and the - previously constructed shapes are returned. Checks that when - .shapes_and_components is called again with changes to the reactor, - the shapes in the reactor are reconstructed and these new shapes are - returned. Checks that the reactor_hash_value is only updated when the - reactor is reconstructed.""" - - self.test_reactor.pf_coil_radial_thicknesses = [30, 30, 30, 30] - self.test_reactor.pf_coil_vertical_thicknesses = [30, 30, 30, 30] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.pf_coil_case_thicknesses = [10, 20, 20, 30] - self.test_reactor.outboard_tf_coil_radial_thickness = 30 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 30 - self.test_reactor.number_of_tf_coils = 16 - - assert self.test_reactor.reactor_hash_value is None - # commented out as code inspector suggests all attributs should be - # declaired in class init - # for key in [ - # "_inboard_tf_coils", - # "_center_column_shield", - # "_plasma", - # "_inboard_firstwall", - # "_inboard_blanket", - # "_firstwall", - # "_divertor_lower", - # "_blanket", - # "_supports", - # "_outboard_rear_blanket_wall_upper", - # "_outboard_rear_blanket_wall_lower", - # "_outboard_rear_blanket_wall", - # "_tf_coil", - # "_pf_coils", - # "_pf_coils_casing", - # ]: - # assert key not in self.test_reactor.__dict__.keys() - assert self.test_reactor.shapes_and_components is not None - - for key in [ - "_inboard_tf_coils", - "_center_column_shield", - "_plasma", - "_inboard_firstwall", - "_inboard_blanket", - "_firstwall", - "_divertor_lower", - "_blanket", - "_supports", - "_outboard_rear_blanket_wall_upper", - "_outboard_rear_blanket_wall_lower", - "_outboard_rear_blanket_wall", - "_tf_coil", - "_pf_coils", - "_pf_coils_casing", - ]: - assert key in self.test_reactor.__dict__.keys() - assert len(self.test_reactor.shapes_and_components) == 17 - assert self.test_reactor.reactor_hash_value is not None - initial_hash_value = self.test_reactor.reactor_hash_value - self.test_reactor.rotation_angle = 270 - assert self.test_reactor.reactor_hash_value == initial_hash_value - assert self.test_reactor.shapes_and_components is not None - assert self.test_reactor.reactor_hash_value != initial_hash_value diff --git a/tests/tests_units/test_parametric_reactors/test_sparc_2020_reactor.py b/tests/tests_units/test_parametric_reactors/test_sparc_2020_reactor.py deleted file mode 100644 index 183d30957..000000000 --- a/tests/tests_units/test_parametric_reactors/test_sparc_2020_reactor.py +++ /dev/null @@ -1,86 +0,0 @@ -import os -import unittest -from pathlib import Path - -import paramak - - -class TestSparc2020Reactor(unittest.TestCase): - """ "Tests functionality of the Sparc2020Reactor class""" - - def setUp(self): - self.test_reactor = paramak.BallReactor( - inner_bore_radial_thickness=50, - inboard_tf_leg_radial_thickness=200, - center_column_shield_radial_thickness=50, - divertor_radial_thickness=100, - inner_plasma_gap_radial_thickness=150, - plasma_radial_thickness=100, - outer_plasma_gap_radial_thickness=50, - plasma_gap_vertical_thickness=50, - firstwall_radial_thickness=50, - blanket_radial_thickness=100, - blanket_rear_wall_radial_thickness=10, - elongation=2, - triangularity=0.55, - number_of_tf_coils=16, - rotation_angle=180, - ) - - self.output_filenames = [ - "plasma.stp", - "vs_coil_1.stp", - "vs_coil_2.stp", - "inboard_pf_coil_1.stp", - "inboard_pf_coil_2.stp", - "inboard_pf_coil_3.stp", - "inboard_pf_coil_4.stp", - "inboard_pf_coil_5.stp", - "inboard_pf_coil_6.stp", - "outboard_pf_coil_1.stp", - "outboard_pf_coil_2.stp", - "outboard_pf_coil_3.stp", - "outboard_pf_coil_4.stp", - "outboard_pf_coil_5.stp", - "outboard_pf_coil_6.stp", - "outboard_pf_coil_7.stp", - "outboard_pf_coil_8.stp", - "div_coil_1.stp", - "div_coil_2.stp", - "div_coil_3.stp", - "div_coil_4.stp", - "efccu_coils_1.stp", - "efccu_coils_2.stp", - "efccu_coils_3.stp", - "efccu_coils_4.stp", - "efccu_coils_5.stp", - "efccu_coils_6.stp", - "tf_coil.stp", - "antenna.stp", - "vessel.stp", - "inner_vessel.stp", - ] - - def test_input_variables_names(self): - """tests that the number of inputs variables is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 25 - assert len(self.test_reactor.input_variable_names) == 25 - - def test_make_sparc_2020_reactor(self): - """Runs the example to check the output files are produced""" - os.system("rm *.stp") - my_reactor = paramak.SparcFrom2020PaperDiagram() - my_reactor.export_stp(filename=self.output_filenames) - for output_filename in self.output_filenames: - assert Path(output_filename).exists() is True - - def test_make_parametric_sparc_2020_rector(self): - """Runs the example to check the output files are produced for sector - model""" - - os.system("rm *.stp") - my_reactor = paramak.SparcFrom2020PaperDiagram(rotation_angle=90) - my_reactor.export_stp(filename=self.output_filenames) - for output_filename in self.output_filenames: - assert Path(output_filename).exists() is True diff --git a/tests/tests_units/test_parametric_reactors/test_submersion_tokamak.py b/tests/tests_units/test_parametric_reactors/test_submersion_tokamak.py deleted file mode 100644 index 2e81b69d0..000000000 --- a/tests/tests_units/test_parametric_reactors/test_submersion_tokamak.py +++ /dev/null @@ -1,334 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -import paramak - - -class TestSubmersionTokamak(unittest.TestCase): - """Tests functionality of the SubmersionTokamak class""" - - def setUp(self): - self.test_reactor = paramak.SubmersionTokamak( - inner_bore_radial_thickness=10, - inboard_tf_leg_radial_thickness=30, - center_column_shield_radial_thickness=60, - divertor_radial_thickness=50, - inner_plasma_gap_radial_thickness=30, - plasma_radial_thickness=300, - outer_plasma_gap_radial_thickness=30, - firstwall_radial_thickness=30, - blanket_rear_wall_radial_thickness=30, - support_radial_thickness=20, - inboard_blanket_radial_thickness=20, - outboard_blanket_radial_thickness=20, - elongation=2.3, - triangularity=0.45, - rotation_angle=359, - ) - - def test_input_variable_names(self): - """tests that the number of inputs variables is correct""" - - assert len(self.test_reactor.input_variables.keys()) == 26 - assert len(self.test_reactor.input_variable_names) == 26 - - def test_svg_creation(self): - """Creates a SubmersionTokamak and checks that an svg file of the - reactor can be exported using the export_svg method.""" - - os.system("rm test_image.svg") - self.test_reactor.export_svg("test_image.svg") - - assert Path("test_image.svg").exists() is True - os.system("rm test_image.svg") - - def test_minimal_creation(self): - """Creates a SubmersionTokamak and checks that the correct number of - components are created.""" - - assert len(self.test_reactor.shapes_and_components) == 9 - - def test_with_tf_coils_creation(self): - """Creates a SubmersionTokamak with tf coils and checks that the correct - number of components are created.""" - - self.test_reactor.outboard_tf_coil_radial_thickness = 50 - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.pf_coil_radial_position = [100] - self.test_reactor.pf_coil_vertical_position = [100] - self.test_reactor.outboard_tf_coil_poloidal_thickness = 70 - self.test_reactor.number_of_tf_coils = 4 - - assert len(self.test_reactor.shapes_and_components) == 10 - - def test_with_tf_and_pf_coils_creation(self): - """Creates a SubmersionTokamak with tf and pf coils and checks that the - correct number of components are created.""" - - self.test_reactor.outboard_tf_coil_radial_thickness = 50 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 70 - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50, 50, 50, 50] - self.test_reactor.pf_coil_radial_thicknesses = [40, 40, 40, 40, 40] - self.test_reactor.pf_coil_radial_position = [100, 100, 200, 200, 100] - self.test_reactor.pf_coil_vertical_position = [100, -100, 200, -200, 0] - self.test_reactor.pf_coil_case_thicknesses = [10, 10, 10, 10, 10] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.number_of_tf_coils = 4 - - assert len(self.test_reactor.shapes_and_components) == 20 - - def test_minimal_stp_creation(self): - """Creates a SubmersionTokamak and checks that stp files of all - components can be exported using the export_stp method.""" - - os.system("rm -r *.stp") - output_filenames = [ - "plasma.stp", - "center_column_shield.stp", - "outboard_firstwall.stp", - "blanket.stp", - "divertor_upper.stp", - "divertor_lower.stp", - "supports.stp", - "outboard_rear_blanket_wall.stp", - "inboard_tf_coils.stp", - ] - self.test_reactor.export_stp(filename=output_filenames) - - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm -r *.stp") - - def test_stp_creation_with_tf(self): - """Creates a SubmersionTokamak and checks that stp files of all - components can be exported using the export_stp method.""" - - os.system("rm -r *.stp") - self.test_reactor.number_of_tf_coils = 4 - self.test_reactor.outboard_tf_coil_radial_thickness = 10 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 10 - self.test_reactor.rear_blanket_to_tf_gap = 10 - output_filenames = [ - "plasma.stp", - "center_column_shield.stp", - "outboard_firstwall.stp", - "blanket.stp", - "divertor_upper.stp", - "divertor_lower.stp", - "supports.stp", - "outboard_rear_blanket_wall.stp", - "inboard_tf_coils.stp", - "tf_coils.stp", - ] - self.test_reactor.export_stp(filename=output_filenames) - - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm -r *.stp") - - def test_with_pf_coils_stp_creation(self): - """Creates a SubmersionTokamak with pf coils and checks that stp files - of all components can be exported using the export_stp method.""" - - os.system("rm -r pf_SubmersionTokamak") - - self.test_reactor.outboard_tf_coil_radial_thickness = 50 - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50] - self.test_reactor.pf_coil_radial_thicknesses = [40, 40] - self.test_reactor.pf_coil_radial_position = [100, 100] - self.test_reactor.pf_coil_vertical_position = [100, -100] - - output_filenames = [ - "pf_coil_1.stp", - "pf_coil_2.stp", - "plasma.stp", - "center_column_shield.stp", - "outboard_firstwall.stp", - "blanket.stp", - "divertor_lower.stp", - "supports.stp", - "outboard_rear_blanket_wall.stp", - "inboard_tf_coils.stp", - "tf_coils.stp", - ] - - self.test_reactor.export_stp(filename=output_filenames) - - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm -r pf_SubmersionTokamak") - - def test_with_tf_and_pf_coils_stp_creation(self): - """Creates a SubmersionTokamak with tf and pf coils and checks that - stp files of all components can be exported using the export_stp method.""" - - os.system("rm -r *.stp") - - self.test_reactor.outboard_tf_coil_radial_thickness = 50 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 70 - self.test_reactor.pf_coil_vertical_thicknesses = [50, 50] - self.test_reactor.pf_coil_radial_thicknesses = [40, 40] - self.test_reactor.pf_coil_radial_position = [100, 100] - self.test_reactor.pf_coil_vertical_position = [100, -100] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.pf_coil_case_thicknesses = [10, 10] - self.test_reactor.number_of_tf_coils = 4 - - output_filenames = [ - "pf_coil_1.stp", - "pf_coil_2.stp", - "pf_coil_case_1.stp", - "pf_coil_case_2.stp", - "plasma.stp", - "center_column_shield.stp", - "outboard_firstwall.stp", - "blanket.stp", - "divertor_upper.stp", - "divertor_lower.stp", - "supports.stp", - "outboard_rear_blanket_wall.stp", - "inboard_tf_coils.stp", - "tf_coils.stp", - ] - self.test_reactor.export_stp(filename=output_filenames) - - for output_filename in output_filenames: - assert Path(output_filename).exists() is True - os.system("rm -r *.stp") - - def test_rotation_angle_warning(self): - """Creates a SubmersionTokamak with rotation_angle = 360 and checks that the - correct warning message is printed.""" - - def warning_trigger(): - try: - self.test_reactor.rotation_angle = 360 - self.test_reactor._rotation_angle_check() - except BaseException: - pass - - msg = "360 degree rotation may result in a " + "Standard_ConstructionError or AttributeError" - with pytest.warns(UserWarning, match=msg): - warning_trigger() - - def test_submersion_reactor_hash_value(self): - """Creates a submersion reactor and checks that all shapes in the reactor are created - when .shapes_and_components is first called. Checks that when .shapes_and_components - is called again with no changes to the reactor, the shapes in the reactor are - reconstructed and the previously constructed shapes are returned. Checks that when - .shapes_and_components is called again with no changes to the reactor, the shapes in - the reactor are reconstructed and these new shapes are returned. Checks that the - reactor_hash_value is only updated when the reactor is reconstructed.""" - - self.test_reactor.pf_coil_radial_thicknesses = [30, 30, 30, 30] - self.test_reactor.pf_coil_vertical_thicknesses = [30, 30, 30, 30] - self.test_reactor.pf_coil_radial_position = [100, 100, 200, 200] - self.test_reactor.pf_coil_vertical_position = [100, -100, 200, -200] - self.test_reactor.pf_coil_case_thicknesses = [10, 10, 10, 10] - self.test_reactor.rear_blanket_to_tf_gap = 50 - self.test_reactor.outboard_tf_coil_radial_thickness = 30 - self.test_reactor.outboard_tf_coil_poloidal_thickness = 30 - self.test_reactor.number_of_tf_coils = 16 - - assert self.test_reactor.reactor_hash_value is None - # commented out as code inspector suggests all attributs should be - # declaired in class init - # for key in [ - # "_inboard_tf_coils", - # "_center_column_shield", - # "_plasma", - # "_inboard_firstwall", - # "_inboard_blanket", - # "_firstwall", - # "_divertor_upper", - # "_divertor_lower", - # "_blanket", - # "_supports", - # "_outboard_rear_blanket_wall_upper", - # "_outboard_rear_blanket_wall_lower", - # "_outboard_rear_blanket_wall", - # "_tf_coil", - # "_pf_coils", - # "_pf_coils_casing", - # ]: - # assert key not in self.test_reactor.__dict__ - - assert self.test_reactor.shapes_and_components is not None - for key in [ - "_inboard_tf_coils", - "_center_column_shield", - "_plasma", - "_inboard_firstwall", - "_inboard_blanket", - "_firstwall", - "_divertor_upper", - "_divertor_lower", - "_blanket", - "_supports", - "_outboard_rear_blanket_wall_upper", - "_outboard_rear_blanket_wall_lower", - "_outboard_rear_blanket_wall", - "_tf_coil", - "_pf_coils", - "_pf_coils_casing", - ]: - assert key in self.test_reactor.__dict__.keys() - - assert len(self.test_reactor.shapes_and_components) == 18 - assert self.test_reactor.reactor_hash_value is not None - initial_hash_value = self.test_reactor.reactor_hash_value - self.test_reactor.rotation_angle = 270 - assert self.test_reactor.reactor_hash_value == initial_hash_value - assert self.test_reactor.shapes_and_components is not None - assert self.test_reactor.reactor_hash_value != initial_hash_value - - def test_error_divertor_pos(self): - """Checks an invalid divertor and support - position raises the correct ValueError.""" - - def invalid_divertor_position(): - self.test_reactor.divertor_position = "coucou" - - self.assertRaises(ValueError, invalid_divertor_position) - - def invalid_support_position(): - self.test_reactor.support_position = "coucou" - - self.assertRaises(ValueError, invalid_support_position) - - def test_error_coil_case_thickness(self): - """checks an invalid number of coil case thicknesses raises the correct - ValueError.""" - - def invalid_pf_coil_case_thicknesses(): - self.test_reactor.pf_coil_radial_thicknesses = [30, 30, 30, 30] - self.test_reactor.pf_coil_vertical_thicknesses = [30, 30, 30, 30] - self.test_reactor.pf_coil_radial_position = [100, 100, 200, 200] - self.test_reactor.pf_coil_vertical_position = [100, -100, 200, -200] - self.test_reactor.pf_coil_case_thicknesses = [10, 10] - self.test_reactor.create_solids() - - self.assertRaises(ValueError, invalid_pf_coil_case_thicknesses) - - def test_divertors_supports(self): - """Checks that SubmersionTokamaks with lower and upper supports - and divertors can be created.""" - - self.test_reactor.divertor_position = "lower" - self.test_reactor.support_position = "lower" - assert self.test_reactor.solid is not None - - self.test_reactor.divertor_position = "lower" - self.test_reactor.support_position = "upper" - assert self.test_reactor.solid is not None - - self.test_reactor.divertor_position = "upper" - self.test_reactor.support_position = "lower" - assert self.test_reactor.solid is not None - - self.test_reactor.divertor_position = "upper" - self.test_reactor.support_position = "upper" - assert self.test_reactor.solid is not None diff --git a/tests/tests_units/test_parametric_shapes/__init__.py b/tests/tests_units/test_parametric_shapes/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/tests_units/test_parametric_shapes/test_extrude_circle_shape.py b/tests/tests_units/test_parametric_shapes/test_extrude_circle_shape.py deleted file mode 100644 index 57c93abb5..000000000 --- a/tests/tests_units/test_parametric_shapes/test_extrude_circle_shape.py +++ /dev/null @@ -1,105 +0,0 @@ -import math -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import ExtrudeCircleShape - - -class TestExtrudeCircleShape(unittest.TestCase): - def setUp(self): - self.test_shape = ExtrudeCircleShape(points=[(30, 0)], radius=10, distance=30) - - def test_default_parameters(self): - """Checks that the default parameters of an ExtrudeCircleShape are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.extrude_both - - def test_absolute_shape_volume(self): - """Creates an ExtrudeCircleShape and checks that its volume is correct.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(math.pi * (10**2) * 30) - - def test_relative_shape_volume(self): - """Creates two ExtrudeCircleShapes and checks that their relative - volumes are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert test_volume * 4 == pytest.approx(self.test_shape.volume()) - - def test_absolute_shape_areas(self): - """Creates ExtrudeCircleShapes and checks that the areas of each face - are correct.""" - - assert self.test_shape.area == pytest.approx((math.pi * (10**2) * 2) + (math.pi * (2 * 10) * 30)) - assert len(self.test_shape.areas) == 3 - assert self.test_shape.areas.count(pytest.approx(math.pi * (10**2))) == 2 - assert self.test_shape.areas.count(pytest.approx(math.pi * (2 * 10) * 30)) == 1 - - def test_cut_volume(self): - """Creates an ExtrudeCircleShape with another ExtrudeCircleShape cut out - and checks that the volume is correct.""" - - shape_with_cut = ExtrudeCircleShape(points=[(30, 0)], radius=20, distance=40, cut=self.test_shape) - - assert shape_with_cut.volume() == pytest.approx((math.pi * (20**2) * 40) - (math.pi * (10**2) * 30)) - - def test_intersect_volume(self): - """Creates ExtrudeCircleShapes with other ExtrudeCircleShapes - intersected and checks that their volumes are correct.""" - - intersect_shape = ExtrudeCircleShape(points=[(30, 0)], radius=5, distance=50) - - intersected_shape = ExtrudeCircleShape( - points=[(30, 0)], - radius=10, - distance=50, - intersect=[self.test_shape, intersect_shape], - ) - - assert intersected_shape.volume() == pytest.approx(math.pi * 5**2 * 30) - - def test_rotation_angle(self): - """Creates an ExtrudeCircleShape with a rotation_angle < 360 and checks - that the correct cut is performed and the volume is correct.""" - - self.test_shape.azimuth_placement_angle = [45, 135, 225, 315] - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5) - - def test_extrude_both(self): - """Creates an ExtrudeCircleShape with extrude_both = True and False - and checks that the volumes are correct.""" - - test_volume_extrude_both = self.test_shape.volume() - self.test_shape.extrude_both = False - assert self.test_shape.volume() == pytest.approx(test_volume_extrude_both) - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_extrude_mixed_shape.py b/tests/tests_units/test_parametric_shapes/test_extrude_mixed_shape.py deleted file mode 100644 index 179034845..000000000 --- a/tests/tests_units/test_parametric_shapes/test_extrude_mixed_shape.py +++ /dev/null @@ -1,216 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import ExtrudeMixedShape - - -class TestExtrudeMixedShape(unittest.TestCase): - def setUp(self): - self.test_shape = ExtrudeMixedShape( - points=[ - (50, 0, "straight"), - (50, 50, "spline"), - (60, 70, "spline"), - (70, 50, "circle"), - (60, 25, "circle"), - (70, 0, "straight"), - ], - distance=50, - ) - - self.test_shape_2 = ExtrudeMixedShape( - distance=1, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "straight"), - (110, 45, "straight"), - ], - ) - - self.test_shape_3 = ExtrudeMixedShape( - distance=180, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "circle"), - (110, 45, "circle"), - ], - ) - - def test_default_parameters(self): - """Checks that the default parameters of an ExtrudeMixedShape are - correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - - def test_absolute_shape_volume(self): - """Creates an ExtrudeMixedShape and checks that the volume is - correct.""" - - assert self.test_shape.volume() > 20 * 20 * 30 - - def test_relative_shape_volume(self): - """Creates two ExtrudeMixedShapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 180] - - assert self.test_shape.volume() == pytest.approx(test_volume * 2, rel=0.01) - - def test_shape_face_areas(self): - """Creates an ExtrudeMixedShape and checks that the face areas are - expected.""" - - self.test_shape.extrude_both = False - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 5 - - def test_cut_volume(self): - """Creates an ExtrudeMixedShape with another ExtrudeMixedShape cut out - and checks that the volume is correct.""" - - inner_shape = ExtrudeMixedShape( - points=[ - (5, 5, "straight"), - (5, 10, "spline"), - (10, 10, "spline"), - (10, 5, "spline"), - ], - distance=30, - ) - - outer_shape = ExtrudeMixedShape( - points=[ - (3, 3, "straight"), - (3, 12, "spline"), - (12, 12, "spline"), - (12, 3, "spline"), - ], - distance=30, - ) - - outer_shape_with_cut = ExtrudeMixedShape( - points=[ - (3, 3, "straight"), - (3, 12, "spline"), - (12, 12, "spline"), - (12, 3, "spline"), - ], - cut=inner_shape, - distance=30, - ) - - assert inner_shape.volume() == pytest.approx(1068, abs=2) - assert outer_shape.volume() == pytest.approx(3462, abs=2) - assert outer_shape_with_cut.volume() == pytest.approx(2394, abs=2) - - def test_export_stp_extension(self): - """Creates an ExtrudeMixedShape and checks that a stp file of the shape - can be exported with the correct suffix using the export_stp method.""" - - os.system("rm filename.stp filename.step") - self.test_shape.export_stp("filename.stp") - self.test_shape.export_stp("filename.step") - assert Path("filename.stp").exists() is True - assert Path("filename.step").exists() is True - os.system("rm filename.stp filename.step") - - def test_export_stl(self): - """Creates a ExtrudeMixedShape and checks that a stl file of the shape - can be exported with the correct suffix using the export_stl method.""" - - os.system("rm filename.stl") - self.test_shape.export_stl("filename.stl") - assert Path("filename.stl").exists() is True - os.system("rm filename.stl") - - def test_rotation_angle(self): - """Creates an ExtrudeMixedShape with a rotation_angle < 360 and checks - that the correct cut is performed and the volume is correct.""" - - self.test_shape.azimuth_placement_angle = [45, 135, 225, 315] - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - def test_extrude_both(self): - """Creates an ExtrudeMixedShape with extrude_both = True and False and - checks that the volumes are correct.""" - - test_volume_extrude_both = self.test_shape.volume() - self.test_shape.extrude_both = False - assert self.test_shape.volume() == pytest.approx(test_volume_extrude_both) - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert pytest.approx(Path("test_solid.stp").stat().st_size, rel=1) == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_convert_all_circle_points_change_to_splines(self): - """creates a ExtrudeMixedShape with one circular edges and converts - them to spline edges. Checks the new edges have been correctly - replaced with splines""" - - assert len(self.test_shape_2.processed_points) == 8 - self.test_shape_2.convert_all_circle_connections_to_splines() - assert len(self.test_shape_2.processed_points) > 8 - assert self.test_shape_2.processed_points[0] == (100, 0, "straight") - assert self.test_shape_2.processed_points[1] == (200, 0, "spline") - - # last point is the same as the first point - assert self.test_shape_2.processed_points[-1] == (100, 0, "straight") - assert self.test_shape_2.processed_points[-2] == (110, 45, "straight") - assert self.test_shape_2.processed_points[-3] == (140, 75, "straight") - assert self.test_shape_2.processed_points[-4] == (150, 100, "straight") - assert self.test_shape_2.processed_points[-5] == (200, 100, "straight") - - spline_points = len(self.test_shape_2.points) - 5 - for point in self.test_shape_2.processed_points[1:spline_points]: - assert point[2] == "spline" - - def test_convert_circles_to_splines_volume(self): - """creates a RotateMixedShape with a circular edge and converts the - edge to a spline edges. Checks the new shape has approximately the same - volume as the original shape (with circles)""" - - original_volume = self.test_shape_2.volume() - self.test_shape_2.convert_all_circle_connections_to_splines() - new_volume = self.test_shape_2.volume() - - assert pytest.approx(new_volume, rel=0.000001) == original_volume - - original_volume = self.test_shape_3.volume() - self.test_shape_3.convert_all_circle_connections_to_splines() - new_volume = self.test_shape_3.volume() - - assert pytest.approx(new_volume, rel=0.000001) == original_volume - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_extrude_spline_shape.py b/tests/tests_units/test_parametric_shapes/test_extrude_spline_shape.py deleted file mode 100644 index f60637438..000000000 --- a/tests/tests_units/test_parametric_shapes/test_extrude_spline_shape.py +++ /dev/null @@ -1,127 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import ExtrudeSplineShape - - -class TestExtrudeSplineShape(unittest.TestCase): - def setUp(self): - self.test_shape = ExtrudeSplineShape( - points=[ - (50, 0), - (50, 20), - (70, 80), - (90, 50), - (70, 0), - (90, -50), - (70, -80), - (50, -20), - ], - distance=30, - ) - - def test_default_parameters(self): - """Checks that the default parameters of an ExtrudeSplineShape are - correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.extrude_both - - def test_absolute_shape_volume(self): - """Creates an ExtrudeSplineShape and checks that the volume is - correct.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() > 20 * 20 * 30 - - def test_shape_face_areas(self): - """Creates an ExtrudeSplineShape and checks that the face areas are - expected.""" - - self.test_shape.extrude_both = False - assert len(self.test_shape.areas) == 3 - assert len(set([round(i) for i in self.test_shape.areas])) == 2 - - def test_relative_shape_volume(self): - """Creates two ExtrudeSplineShapes and checks that their relative - volumes are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 180] - - assert self.test_shape.volume() == pytest.approx(test_volume * 2, rel=0.01) - - def test_cut_volume(self): - """Creates an ExtrudeSplineShape with another ExtrudeSplineShape cut out - and checks that the volume is correct.""" - - inner_shape = ExtrudeSplineShape(points=[(5, 5), (5, 10), (10, 10), (10, 5)], distance=30) - - outer_shape = ExtrudeSplineShape(points=[(3, 3), (3, 12), (12, 12), (12, 3)], distance=30) - - outer_shape_with_cut = ExtrudeSplineShape( - points=[(3, 3), (3, 12), (12, 12), (12, 3)], - cut=inner_shape, - distance=30, - ) - - assert inner_shape.volume() == pytest.approx(1165, abs=2) - assert outer_shape.volume() == pytest.approx(3775, abs=2) - assert outer_shape_with_cut.volume() == pytest.approx(3775 - 1165, abs=2) - - def test_rotation_angle(self): - """Creates an ExtrudeStraightShape with a rotation_angle < 360 and - checks that the correct cut is performed and the volume is correct.""" - - self.test_shape.azimuth_placement_angle = [45, 135, 225, 315] - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - def test_extrude_both(self): - """Creates an ExtrudeSplineShape with extrude_both = True and False and - checks that the volumes are correct.""" - - test_volume_extrude_both = self.test_shape.volume() - self.test_shape.extrude_both = False - assert self.test_shape.volume() == pytest.approx(test_volume_extrude_both) - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks that the - outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_incorrect_points_input(self): - """Checks that an error is raised when the points are input with the - connection""" - - def incorrect_points_definition(): - self.test_shape.points = [ - (10, 10, "spline"), - (10, 30, "spline"), - (30, 30, "spline"), - (30, 10, "spline"), - ] - - self.assertRaises(ValueError, incorrect_points_definition) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_extrude_straight_shape.py b/tests/tests_units/test_parametric_shapes/test_extrude_straight_shape.py deleted file mode 100644 index 2b01b1e76..000000000 --- a/tests/tests_units/test_parametric_shapes/test_extrude_straight_shape.py +++ /dev/null @@ -1,197 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest -from cadquery import Plane - -from paramak import ExtrudeStraightShape - - -class TestExtrudeStraightShape(unittest.TestCase): - def setUp(self): - self.test_shape = ExtrudeStraightShape(points=[(10, 10), (10, 30), (30, 30), (30, 10)], distance=30) - - def test_bounding_box(self): - """checks the bounding box value""" - - assert self.test_shape.bounding_box == ( - (10.0, -15.0, 10.0), - (30.0, 15.0, 30.0), - ) - - def test_largest_dimension(self): - """checks the largest dimension value""" - - assert self.test_shape.largest_dimension == 25.0 - - def test_translate(self): - """Checks the shape extends to the bounding box and then translates - the shape and checks it is extended to the new bounding box""" - - assert self.test_shape.solid.val().BoundingBox().xmax == 30 - assert self.test_shape.solid.val().BoundingBox().ymax == 15 - assert self.test_shape.solid.val().BoundingBox().zmax == 30 - assert self.test_shape.solid.val().BoundingBox().xmin == 10 - assert self.test_shape.solid.val().BoundingBox().ymin == -15 - assert self.test_shape.solid.val().BoundingBox().zmin == 10 - - self.test_shape.translate = (1, 2, 3) - - assert self.test_shape.solid.val().BoundingBox().xmax == 30 + 1 - assert self.test_shape.solid.val().BoundingBox().xmin == 10 + 1 - assert self.test_shape.solid.val().BoundingBox().ymax == 15 + 2 - assert self.test_shape.solid.val().BoundingBox().ymin == -15 + 2 - assert self.test_shape.solid.val().BoundingBox().zmax == 30 + 3 - assert self.test_shape.solid.val().BoundingBox().zmin == 10 + 3 - - def test_workplane_of_type_cadquery_plane(self): - """Tests that a Cadquery.Plane is accepted as a workplane entry and - makes a shape with the same volume as the default 'XY' workplane""" - - normal_vec = (1, 1, 1) - workplane = Plane(origin=(0, 0, 0), xDir=(-1, 1, 0), normal=normal_vec) - # in future releases of CQ, origin and xDir will be optional - - test_shape_2 = ExtrudeStraightShape( - workplane=workplane, - rotation_axis="X", - points=[(10, 10), (10, 30), (30, 30), (30, 10)], - distance=30, - ) - - assert isinstance(test_shape_2.workplane, Plane) - assert pytest.approx(test_shape_2.volume()) == self.test_shape.volume() - - def test_default_parameters(self): - """Checks that the default parameters of an ExtrudeStraightShape are - correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.extrude_both - - def test_absolute_shape_volume(self): - """Creates an ExtrudeStraightShape and checks that the volume is - correct.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(20 * 20 * 30) - - def test_absolute_shape_areas(self): - """Creates an ExtrudeStraightShape and checks that the volume is - correct.""" - - assert self.test_shape.area == pytest.approx((20 * 20 * 2) + (20 * 30 * 4)) - assert len(self.test_shape.areas) == 6 - assert self.test_shape.areas.count(pytest.approx(20 * 20)) == 2 - assert self.test_shape.areas.count(pytest.approx(20 * 30)) == 4 - - def test_relative_shape_volume(self): - """Creates two ExtrudeStraightShapes and checks that their relative - volumes are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - self.test_shape.rotation_axis = "Y" - assert self.test_shape.volume() == pytest.approx(test_volume * 4) - - def test_cut_volume(self): - """Creates an ExtrudeStraightShape with another ExtrudeStraightShape cut - out and checks that the volume is correct.""" - - shape_with_cut = ExtrudeStraightShape( - points=[(0, 0), (0, 40), (40, 40), (40, 0)], - distance=40, - cut=self.test_shape, - ) - - assert shape_with_cut.volume() == pytest.approx((40 * 40 * 40) - (20 * 20 * 30)) - - def test_union_volume(self): - """Creates a union of two ExtrudeStraightShapes and checks that the - volume is correct.""" - - unioned_shape = ExtrudeStraightShape( - points=[(0, 10), (0, 30), (20, 30), (20, 10)], - distance=30, - union=self.test_shape, - ) - assert unioned_shape.volume() == pytest.approx(30 * 20 * 30) - - def test_intersect_volume(self): - """Creates an ExtrudeStraightShape with another ExtrudeStraightShape - intersected and checks that the volume is correct.""" - - intersected_shape = ExtrudeStraightShape( - points=[(0, 10), (0, 30), (20, 30), (20, 10)], - distance=30, - intersect=self.test_shape, - ) - assert intersected_shape.volume() == pytest.approx(10 * 20 * 30) - - def test_rotation_angle(self): - """Creates an ExtrudeStraightShape with a rotation_angle < 360 and - checks that the correct cut is performed and the volume is correct.""" - - self.test_shape.azimuth_placement_angle = [45, 135, 225, 315] - self.rotation_axis = "Y" - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert self.test_shape.volume() == pytest.approx(test_volume * 0.5, rel=0.01) - - def test_extrude_both(self): - """Creates an ExtrudeStraightShape with extrude_both = True and False - and checks that the volumes are correct.""" - - test_volume_extrude_both = self.test_shape.volume() - self.test_shape.extrude_both = False - assert self.test_shape.volume() == pytest.approx(test_volume_extrude_both) - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks that the - outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_incorrect_points_input(self): - """Checks that an error is raised when the points are input with the - connection""" - - def incorrect_points_definition(): - self.test_shape.points = [ - (10, 10, "straight"), - (10, 30, "straight"), - (30, 30, "straight"), - (30, 10, "straight"), - ] - - self.assertRaises(ValueError, incorrect_points_definition) - - def test_export_html_with_different_workplanes(self): - """Checks that all the workplanes produce an html file when using the - export_html method and that the axis have the correct labels""" - - os.system("rm *.html") - for workplane in ["XY", "YZ", "XZ", "YX", "ZY", "ZX"]: - self.test_shape.workplane = workplane - fig = self.test_shape.export_html(workplane + ".html") - assert Path(workplane + ".html").exists() is True - assert fig.layout.xaxis.title["text"] == workplane[0] - assert fig.layout.yaxis.title["text"] == workplane[1] - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_rotate_circle_shape.py b/tests/tests_units/test_parametric_shapes/test_rotate_circle_shape.py deleted file mode 100644 index f2a2945f3..000000000 --- a/tests/tests_units/test_parametric_shapes/test_rotate_circle_shape.py +++ /dev/null @@ -1,94 +0,0 @@ -import math -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import RotateCircleShape - - -class TestRotateCircleShape(unittest.TestCase): - def setUp(self): - self.test_shape = RotateCircleShape(points=[(60, 0)], radius=10) - - def test_default_parameters(self): - """Checks that the default parameters of a RotateCircleShape are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - - def test_absolute_shape_volume(self): - """Creates RotateCircleShapes and checks that their volumes are correct.""" - - # See Issue #445 - # assert self.test_shape.volume == pytest.approx( - # 2 * math.pi * 60 * math.pi * (10**2) - # ) - self.test_shape.rotation_angle = 270 - assert self.test_shape.volume() == pytest.approx(2 * math.pi * 60 * math.pi * (10**2) * 0.75) - - def test_absolute_shape_areas(self): - """Creates RotateCircleShapes and checks that the areas of each face are - correct.""" - - # See Issue #445 - # assert self.test_shape.area == pytest.approx( - # math.pi * (10 * 2) * math.pi * (60 * 2)) - # assert len(self.test_shape.areas) == 1 - # assert self.test_shape.areas.count(pytest.approx( - # math.pi * (10 * 2) * math.pi * (60 * 2), rel=0.01)) == 1 - - self.test_shape.rotation_angle = 180 - assert self.test_shape.area == pytest.approx( - ((math.pi * (10**2)) * 2) + (math.pi * (10 * 2) * math.pi * (60 * 2) / 2), - rel=0.01, - ) - assert len(self.test_shape.areas) == 3 - assert self.test_shape.areas.count(pytest.approx(math.pi * (10**2))) == 2 - assert self.test_shape.areas.count(pytest.approx(math.pi * (10 * 2) * math.pi * (60 * 2) / 2, rel=0.01)) == 1 - - def test_relative_shape_volume_azimuth_placement_angle(self): - """Creates two RotateCircleShapes with different - azimuth_placement_angles and checks that their relative volumes are - correct.""" - - self.test_shape.rotation_angle = 10 - assert self.test_shape.volume() == pytest.approx((math.pi * 10**2) * ((2 * math.pi * 60) / 36)) - - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert self.test_shape.volume() == pytest.approx((math.pi * 10**2) * ((2 * math.pi * 60) / 36) * 4) - - def test_cut_volume(self): - """Creates a RotateCircleShape with another RotateCircleShape cut out - and checks that the volume is correct.""" - - outer_shape = RotateCircleShape(points=[(60, 0)], radius=15) - outer_shape_volume = outer_shape.volume() - outer_shape.cut = self.test_shape - assert outer_shape.volume() == pytest.approx(outer_shape_volume - self.test_shape.volume()) - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - # the circle wire file is actually larger than the circle solid file - # assert Path("test_wire.stp").stat().st_size < \ - # Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_rotate_mixed_shape.py b/tests/tests_units/test_parametric_shapes/test_rotate_mixed_shape.py deleted file mode 100644 index 19036f65f..000000000 --- a/tests/tests_units/test_parametric_shapes/test_rotate_mixed_shape.py +++ /dev/null @@ -1,269 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import RotateMixedShape - - -class TestRotateMixedShape(unittest.TestCase): - def setUp(self): - self.test_shape = RotateMixedShape( - points=[ - (50, 0, "straight"), - (50, 50, "spline"), - (60, 70, "spline"), - (70, 50, "circle"), - (60, 25, "circle"), - (70, 0, "straight"), - ] - ) - - self.test_shape_2 = RotateMixedShape( - rotation_angle=1, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "straight"), - (110, 45, "straight"), - ], - ) - - self.test_shape_3 = RotateMixedShape( - rotation_angle=180, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "circle"), - (110, 45, "circle"), - ], - ) - - def test_export_2d_image(self): - """Creates a RotateMixedShape object and checks that a png file of the - object with the correct suffix can be exported using the - export_2d_image method.""" - - os.system("rm filename.png") - self.test_shape.export_2d_image("filename") - assert Path("filename.png").exists() is True - os.system("rm filename.png") - self.test_shape.export_2d_image("filename.png") - assert Path("filename.png").exists() is True - os.system("rm filename.png") - - def test_default_parameters(self): - """Checks that the default parameters of a RotateMixedShape are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - - def test_relative_shape_volume_rotation_angle(self): - """Creates two RotateMixedShapes with different rotation_angles and checks - that their relative volumes are correct.""" - - assert self.test_shape.volume() > 100 - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert test_volume == pytest.approx(self.test_shape.volume() * 2) - - def test_relative_shape_volume_azimuth_placement_angle(self): - """Creates two RotateMixedShapes with different azimuth_placement_angles and - checks that their relative volumes are correct.""" - - self.test_shape.rotation_angle = 10 - self.test_shape.azimuth_placement_angle = 0 - test_volume_1 = self.test_shape.volume() - - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert self.test_shape.volume() == pytest.approx(test_volume_1 * 4) - - def test_shape_face_areas(self): - """Creates RotateMixedShapes and checks that the face areas are expected.""" - - assert len(self.test_shape.areas) == 4 - assert len(set(self.test_shape.areas)) == 4 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 6 - assert len(set([round(i) for i in self.test_shape.areas])) == 5 - - def test_union_volume_addition(self): - """Fuses two RotateMixedShapes and checks that their fused volume - is correct""" - - inner_box = RotateMixedShape( - points=[ - (100, 100, "straight"), - (100, 200, "straight"), - (200, 200, "straight"), - (200, 100, "straight"), - ] - ) - - outer_box = RotateMixedShape( - points=[ - (200, 100, "straight"), - (200, 200, "straight"), - (500, 200, "straight"), - (500, 100, "straight"), - ] - ) - - outer_box_and_inner_box = RotateMixedShape( - points=[ - (200, 100, "straight"), - (200, 200, "straight"), - (500, 200, "straight"), - (500, 100, "straight"), - ], - union=inner_box, - ) - - assert inner_box.volume() + outer_box.volume() == pytest.approx(outer_box_and_inner_box.volume()) - - def test_incorrect_connections(self): - """Checks that errors are raised when invalid connection arguments are - used to construct a RotateMixedShape.""" - - def incorrect_string_for_connection_type(): - """Checks ValueError is raised when an invalid connection type is - specified.""" - - RotateMixedShape( - points=[ - (0, 0, "straight"), - (0, 20, "spline"), - (20, 20, "spline"), - (20, 0, "invalid_entry"), - ] - ) - - self.assertRaises(ValueError, incorrect_string_for_connection_type) - - def incorrect_number_of_connections_function(): - """Checks ValueError is raised when an incorrect number of - connections is specified.""" - - RotateMixedShape(points=[(0, 200, "straight"), (200, 100), (0, 0, "spline")]) - - self.assertRaises(ValueError, incorrect_number_of_connections_function) - - def test_cut_volume(self): - """Creates a RotateMixedShape with another RotateMixedShape cut out and - checks that the volume is correct.""" - - outer_shape = RotateMixedShape( - points=[ - (40, -10, "spline"), - (35, 50, "spline"), - (60, 80, "straight"), - (80, 80, "circle"), - (100, 40, "circle"), - (80, 0, "straight"), - (80, -10, "straight"), - ] - ) - outer_shape_volume = outer_shape.volume() - outer_shape.cut = self.test_shape - assert outer_shape.volume() == pytest.approx(outer_shape_volume - self.test_shape.volume()) - - def test_mixed_shape_with_straight_and_circle(self): - """Creates a RotateMixedShape with straight and circular connections and - checks that the volume is correct.""" - - test_shape = RotateMixedShape( - points=[ - (10, 20, "straight"), - (10, 10, "straight"), - (20, 10, "circle"), - (40, 15, "circle"), - (20, 20, "straight"), - ], - rotation_angle=10, - ) - assert test_shape.volume() > 10 * 10 - - def test_export_stp_extension(self): - """Creates a RotateMixedShape and checks that a stp file of the shape - can be exported with the correct suffix using the export_stp method.""" - - os.system("rm filename.stp filename.step") - self.test_shape.export_stp("filename.stp") - self.test_shape.export_stp("filename.step") - assert Path("filename.stp").exists() is True - assert Path("filename.step").exists() is True - os.system("rm filename.stp filename.step") - - def test_export_stl(self): - """Creates a RotateMixedShape and checks that a stl file of the shape - can be exported with the correct suffix using the export_stl method.""" - - os.system("rm filename.stl") - self.test_shape.export_stl("filename.stl") - assert Path("filename.stl").exists() is True - os.system("rm filename.stl") - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_convert_all_circle_points_change_to_splines(self): - """creates a RotateMixedShape with two circular edges and converts - them to spline edges. Checks the new edges have been correctly - replaced with splines""" - - assert len(self.test_shape_3.processed_points) == 8 - self.test_shape_3.convert_all_circle_connections_to_splines() - assert len(self.test_shape_3.processed_points) > 8 - assert self.test_shape_3.processed_points[0] == (100, 0, "straight") - assert self.test_shape_3.processed_points[1][2] == "spline" - assert self.test_shape_3.processed_points[2][2] == "spline" - - # last point is the same as the first point - assert self.test_shape_3.processed_points[-1] == (100, 0, "straight") - assert self.test_shape_3.processed_points[-2][2] == "spline" - assert self.test_shape_3.processed_points[-3][2] == "spline" - - def test_convert_circles_to_splines_volume(self): - """creates a RotateMixedShape with a circular edge and converts the - edge to a spline edges. Checks the new shape has approximately the same - volume as the original shape (with circles)""" - - original_volume = self.test_shape_2.volume() - self.test_shape_2.convert_all_circle_connections_to_splines() - new_volume = self.test_shape_2.volume() - - assert pytest.approx(new_volume, rel=0.000001) == original_volume - - original_volume = self.test_shape_3.volume() - self.test_shape_3.convert_all_circle_connections_to_splines() - new_volume = self.test_shape_3.volume() - - assert pytest.approx(new_volume, rel=0.00001) == original_volume - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_rotate_spline_shape.py b/tests/tests_units/test_parametric_shapes/test_rotate_spline_shape.py deleted file mode 100644 index 8d22f8ecc..000000000 --- a/tests/tests_units/test_parametric_shapes/test_rotate_spline_shape.py +++ /dev/null @@ -1,110 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import RotateSplineShape - - -class TestRotateSplineShape(unittest.TestCase): - def setUp(self): - self.test_shape = RotateSplineShape( - points=[ - (50, 0), - (50, 20), - (70, 80), - (90, 50), - (70, 0), - (90, -50), - (70, -80), - (50, -20), - ] - ) - - def test_default_parameters(self): - """Checks that the default parameters of a RotateSplineShape are - correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - - def test_absolute_shape_volume(self): - """creates a rotated shape using spline connections and checks the - volume is correct""" - - self.test_shape.rotation_angle = 360 - volume_360 = self.test_shape.volume() - - assert self.test_shape.solid is not None - assert volume_360 > 100 - - self.test_shape.rotation_angle = 180 - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(volume_360 * 0.5) - - def test_cut_volume(self): - """Creates a RotateSplineShape with another RotateSplineShape cut out - and checks that the volume is correct.""" - - inner_shape = RotateSplineShape(points=[(5, 5), (5, 10), (10, 10), (10, 5)], rotation_angle=180) - - outer_shape = RotateSplineShape(points=[(3, 3), (3, 12), (12, 12), (12, 3)], rotation_angle=180) - - outer_shape_with_cut = RotateSplineShape( - points=[(3, 3), (3, 12), (12, 12), (12, 3)], - cut=inner_shape, - rotation_angle=180, - ) - - assert inner_shape.volume() == pytest.approx(900.88, abs=0.1) - assert outer_shape.volume() == pytest.approx(2881.76, abs=0.1) - assert outer_shape_with_cut.volume() == pytest.approx(2881.76 - 900.88, abs=0.2) - - def test_shape_face_areas(self): - """Creates RotateSplineShapes and checks that the face areas are - expected.""" - - assert len(self.test_shape.areas) == 1 - assert len(set(self.test_shape.areas)) == 1 - - self.test_shape.rotation_angle = 180 - assert len(self.test_shape.areas) == 3 - assert len(set([round(i) for i in self.test_shape.areas])) == 2 - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_incorrect_points_input(self): - """Checks that an error is raised when the points are input with the - connection""" - - def incorrect_points_definition(): - self.test_shape.points = [ - (10, 10, "spline"), - (10, 30, "spline"), - (30, 30, "spline"), - (30, 10, "spline"), - ] - - self.assertRaises(ValueError, incorrect_points_definition) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_rotate_straight_shape.py b/tests/tests_units/test_parametric_shapes/test_rotate_straight_shape.py deleted file mode 100644 index 25af79925..000000000 --- a/tests/tests_units/test_parametric_shapes/test_rotate_straight_shape.py +++ /dev/null @@ -1,301 +0,0 @@ -import math -import os -import unittest -from pathlib import Path -import pytest -from paramak import RotateStraightShape - - -class TestRotateStraightShape(unittest.TestCase): - def setUp(self): - self.test_shape = RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)]) - - def test_translate(self): - """Checks the shape extends to the bounding box and then translates - the shape and checks it is extended to the new bounding box""" - - assert self.test_shape.solid.val().BoundingBox().xmax == 20 - assert self.test_shape.solid.val().BoundingBox().xmin == -20 - assert self.test_shape.solid.val().BoundingBox().ymax == 20 - assert self.test_shape.solid.val().BoundingBox().ymin == -20 - assert self.test_shape.solid.val().BoundingBox().zmax == 20 - assert self.test_shape.solid.val().BoundingBox().zmin == 0 - - self.test_shape.translate = (1, 2, 3) - - assert self.test_shape.solid.val().BoundingBox().xmax == 20 + 1 - assert self.test_shape.solid.val().BoundingBox().xmin == -20 + 1 - assert self.test_shape.solid.val().BoundingBox().ymax == 20 + 2 - assert self.test_shape.solid.val().BoundingBox().ymin == -20 + 2 - assert self.test_shape.solid.val().BoundingBox().zmax == 20 + 3 - assert self.test_shape.solid.val().BoundingBox().zmin == 0 + 3 - - def test_largest_dimension(self): - """Checks that the largest_dimension is correct.""" - - assert self.test_shape.largest_dimension == 20 - - def test_default_parameters(self): - """Checks that the default parameters of a RotateStraightShape are correct.""" - - assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - - def test_rotation_angle_getting_setting(self): - """Checks that the rotation_angle of a RotateStraightShape can be changed.""" - - assert self.test_shape.rotation_angle == 360 - self.test_shape.rotation_angle = 180 - assert self.test_shape.rotation_angle == 180 - - def test_absolute_shape_volume(self): - """Creates a RotateStraightShape and checks that its volume is correct.""" - - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(math.pi * (20**2) * 20) - - def test_relative_shape_volume(self): - """Creates two RotateStraightShapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.rotation_angle = 180 - assert test_volume == pytest.approx(self.test_shape.volume() * 2) - - def test_union_volume_addition(self): - """Fuses two RotateStraightShapes and checks that their fused volume is - correct.""" - - inner_box = RotateStraightShape( - points=[(100, 100), (100, 200), (200, 200), (200, 100)], - ) - - outer_box = RotateStraightShape( - points=[(200, 100), (200, 200), (500, 200), (500, 100)], - ) - - outer_box_and_inner_box = RotateStraightShape( - points=[(200, 100), (200, 200), (500, 200), (500, 100)], - union=inner_box, - ) - - assert inner_box.volume() + outer_box.volume() == pytest.approx(outer_box_and_inner_box.volume(), rel=0.01) - - def test_absolute_shape_areas(self): - """Creates RotateStraightShapes and checks that the areas of each face - are correct.""" - - assert self.test_shape.area == pytest.approx((math.pi * (20**2) * 2) + (math.pi * (20 * 2) * 20)) - assert len(self.test_shape.areas) == 3 - assert self.test_shape.areas.count(pytest.approx(math.pi * (20**2))) == 2 - assert self.test_shape.areas.count(pytest.approx(math.pi * (20 * 2) * 20)) == 1 - - self.test_shape.rotation_angle = 180 - assert self.test_shape.area == pytest.approx( - ((math.pi * (20**2) / 2) * 2) + (20 * 40) + (math.pi * (20 * 2) * 20 / 2) - ) - assert len(self.test_shape.areas) == 4 - assert self.test_shape.areas.count(pytest.approx(math.pi * (20**2) / 2)) == 2 - assert self.test_shape.areas.count(pytest.approx(20 * 40)) == 1 - assert self.test_shape.areas.count(pytest.approx((math.pi * (20 * 2) * 20) / 2)) == 1 - - test_shape = RotateStraightShape( - points=[(50, 0), (50, 50), (70, 50), (70, 0)], - ) - - assert test_shape.area == pytest.approx( - (((math.pi * (70**2)) - (math.pi * (50**2))) * 2) - + (math.pi * (50 * 2) * 50) - + (math.pi * (70 * 2) * 50) - ) - assert len(test_shape.areas) == 4 - assert test_shape.areas.count(pytest.approx((math.pi * (70**2)) - (math.pi * (50**2)))) == 2 - assert test_shape.areas.count(pytest.approx(math.pi * (50 * 2) * 50)) == 1 - assert test_shape.areas.count(pytest.approx(math.pi * (70 * 2) * 50)) == 1 - - test_shape.rotation_angle = 180 - assert test_shape.area == pytest.approx( - (20 * 50 * 2) - + ((((math.pi * (70**2)) / 2) - ((math.pi * (50**2)) / 2)) * 2) - + ((math.pi * (50 * 2) * 50) / 2) - + ((math.pi * (70 * 2) * 50) / 2) - ) - assert len(test_shape.areas) == 6 - assert test_shape.areas.count(pytest.approx(20 * 50)) == 2 - assert test_shape.areas.count(pytest.approx(((math.pi * (70**2)) / 2) - ((math.pi * (50**2)) / 2))) == 2 - assert test_shape.areas.count(pytest.approx(math.pi * (50 * 2) * 50 / 2)) == 1 - assert test_shape.areas.count(pytest.approx(math.pi * (70 * 2) * 50 / 2)) == 1 - - def test_export_stp_extension(self): - """Creates a RotateStraightShape and checks that a stp file of the - shape can be exported with the correct suffix using the export_stp - method.""" - - os.system("rm filename.stp filename.step") - self.test_shape.export_stp("filename.stp") - self.test_shape.export_stp("filename.step") - assert Path("filename.stp").exists() is True - assert Path("filename.step").exists() is True - os.system("rm filename.stp filename.step") - - def test_export_stp_extension_in_cm(self): - """Creates a RotateStraightShape and checks that a stp file of the - shape can be exported with the correct suffix using the export_stp - method.""" - - os.system("rm filename.stp filename.step") - self.test_shape.export_stp("filename.stp", units="cm") - self.test_shape.export_stp("filename.step", units="cm") - assert Path("filename.stp").exists() is True - assert Path("filename.step").exists() is True - os.system("rm filename.stp filename.step") - self.test_shape.export_stp("filename_cm.stp", units="cm") - assert Path("filename_cm.stp").exists() is True - os.system("rm filename_cm.stp") - - def test_export_stl(self): - """Creates a RotateStraightShape and checks that a stl file of the - shape can be exported with the correct suffix using the export_stl - method.""" - - os.system("rm filename.stl") - self.test_shape.export_stl("filename.stl") - assert Path("filename.stl").exists() is True - os.system("rm filename.stl") - - def test_export_svg(self): - """Creates a RotateStraightShape and checks that a svg file of the - shape can be exported with the correct suffix using the export_svg - method.""" - - os.system("rm filename.svg") - self.test_shape.export_svg("filename.svg") - assert Path("filename.svg").exists() is True - os.system("rm filename.svg") - self.test_shape.export_svg("filename") - assert Path("filename.svg").exists() is True - os.system("rm filename.svg") - - def test_export_svg_options(self): - """Creates a RotateStraightShape and checks that a svg file of the - shape can be exported with the various different export options""" - - os.system("rm *.svg") - self.test_shape.export_svg("width.svg", width=900) - assert Path("width.svg").exists() is True - self.test_shape.export_svg("height.svg", height=900) - assert Path("height.svg").exists() is True - self.test_shape.export_svg("marginLeft.svg", marginLeft=110) - assert Path("marginLeft.svg").exists() is True - self.test_shape.export_svg("marginTop.svg", marginTop=110) - assert Path("marginTop.svg").exists() is True - self.test_shape.export_svg("showAxes.svg", showAxes=True) - assert Path("showAxes.svg").exists() is True - self.test_shape.export_svg("projectionDir.svg", projectionDir=(-1, -1, -1)) - assert Path("projectionDir.svg").exists() is True - self.test_shape.export_svg("strokeColor.svg", strokeColor=(42, 42, 42)) - assert Path("strokeColor.svg").exists() is True - self.test_shape.export_svg("hiddenColor.svg", hiddenColor=(42, 42, 42)) - assert Path("hiddenColor.svg").exists() is True - self.test_shape.export_svg("showHidden.svg", showHidden=False) - assert Path("showHidden.svg").exists() is True - self.test_shape.export_svg("strokeWidth1.svg", strokeWidth=None) - assert Path("strokeWidth1.svg").exists() is True - self.test_shape.export_svg("strokeWidth2.svg", strokeWidth=10) - assert Path("strokeWidth2.svg").exists() is True - - def test_cut_volume(self): - """Creates a RotateStraightShape with another RotateStraightShape - cut out and checks that the volume is correct.""" - - shape_with_cut = RotateStraightShape(points=[(0, -5), (0, 25), (25, 25), (25, -5)], cut=self.test_shape) - - assert shape_with_cut.volume() == pytest.approx((math.pi * (25**2) * 30) - (math.pi * (20**2) * 20)) - - def test_multiple_cut_volume(self): - """Creates a RotateStraightShape with multiple RotateStraightShapes - cut out and checks that the volume is correct.""" - - shape_to_cut_1 = RotateStraightShape( - points=[(20, 0), (20, 200), (40, 200), (40, 0)], - ) - - shape_to_cut_2 = RotateStraightShape( - points=[(120, 0), (120, 200), (140, 200), (140, 0)], - ) - - main_shape_with_cuts = RotateStraightShape( - points=[(0, 0), (0, 200), (200, 200), (200, 0)], - cut=[shape_to_cut_1, shape_to_cut_2], - ) - - assert main_shape_with_cuts.volume() == pytest.approx( - (math.pi * (200**2) * 200) - - ((math.pi * (40**2) * 200) - (math.pi * (20**2) * 200)) - - ((math.pi * (140**2) * 200) - (math.pi * (120**2) * 200)) - ) - - def test_hash_value(self): - """Creates a RotateStraightShape and checks that a cadquery solid with - a unique has value is created when .solid is called. Checks that the same - solid is returned when .solid is called again after no changes have been - made to the shape. Checks that a new solid with a new unique has is - constructed when .solid is called after changes to the shape have been - made. Checks that the hash_value of the shape is not updated until a new - solid has been constructed.""" - - assert self.test_shape.hash_value is None - assert self.test_shape.solid is not None - assert self.test_shape.hash_value is not None - initial_hash_value = self.test_shape.hash_value - assert self.test_shape.solid is not None - assert initial_hash_value == self.test_shape.hash_value - self.test_shape.rotation_angle = 180 - assert initial_hash_value == self.test_shape.hash_value - assert self.test_shape.solid is not None - assert initial_hash_value != self.test_shape.hash_value - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_export_stp_with_incorrect_args(self): - """Checks errors are raised when incorrect arguments are used""" - - def export_mode_incorrect(): - self.test_shape.export_stp("test_solid.stp", mode="coucou") - - self.assertRaises(ValueError, export_mode_incorrect) - - def test_incorrect_points_input(self): - """Checks that an error is raised when the points are input with the - connection""" - - def incorrect_points_definition(): - self.test_shape.points = [ - (10, 10, "straight"), - (10, 30, "straight"), - (30, 30, "straight"), - (30, 10, "straight"), - ] - - self.assertRaises(ValueError, incorrect_points_definition) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_sweep_circle_shape.py b/tests/tests_units/test_parametric_shapes/test_sweep_circle_shape.py deleted file mode 100644 index 6a12f49a4..000000000 --- a/tests/tests_units/test_parametric_shapes/test_sweep_circle_shape.py +++ /dev/null @@ -1,141 +0,0 @@ -import math -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import RotateStraightShape, SweepCircleShape - - -class TestSweepCircleShape(unittest.TestCase): - def setUp(self): - self.test_shape = SweepCircleShape(radius=10, path_points=[(50, 0), (30, 50), (70, 100), (50, 150)]) - - def test_default_parameters(self): - """Checks that the default parameters of a SweepCircleShape are correct.""" - - # assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - assert self.test_shape.workplane == "XY" - assert self.test_shape.path_workplane == "XZ" - assert self.test_shape.force_cross_section is False - - def test_solid_construction_workplane(self): - """Checks that SweepSplineShapes can be created in different workplanes.""" - - self.test_shape.workplane = "YZ" - self.test_shape.path_workplane = "YX" - assert self.test_shape.solid is not None - - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "XY" - assert self.test_shape.solid is not None - - def test_workplane_path_workplane_error_raises(self): - """Checks that errors are raised when SweepCircleShapes are created with - disallowed workplane and path_workplane combinations.""" - - def workplane_and_path_workplane_equal(): - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "XZ" - - def invalid_relative_workplane_and_path_workplane(): - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "YZ" - - self.assertRaises(ValueError, workplane_and_path_workplane_equal) - self.assertRaises(ValueError, invalid_relative_workplane_and_path_workplane) - - def test_absolute_shape_volume(self): - """Creates a SweepCircleShape and checks that the volume is correct.""" - - self.test_shape.path_points = [(50, 0), (50, 50), (50, 100)] - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(math.pi * 10**2 * 100) - - def test_relative_shape_volume_radius(self): - """Creates two SweepCircleShapes and checks that their relative volume - are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.radius = 20 - assert self.test_shape.volume() == pytest.approx(test_volume * 4, rel=0.01) - - def test_relative_shape_volume_azimuthal_placement(self): - """Creates two SweepCircleShapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert self.test_shape.volume() == pytest.approx(test_volume * 4, rel=0.01) - - def test_points_equal_path_points(self): - """Checks that shape.points = shape.path_points upon construction of a - SweepCircleShape.""" - - assert self.test_shape.points == self.test_shape.path_points - - def test_html(self): - """Checks that a html graph of the path_points of a SweepCircleShape can be - exported using the export_html method.""" - - assert self.test_shape.export_html("filename.html") is not None - - def test_force_cross_section(self): - """Checks that a SweepCircleShape with the same cross-section at each path_point - is created when force_cross_section = True.""" - - self.test_shape.force_cross_section = True - - assert self.test_shape.areas.count(pytest.approx(math.pi * (10**2), rel=0.01)) == 2 - - cutting_shape = RotateStraightShape( - points=[(0, 50), (0, 200), (100, 200), (100, 50)], - ) - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(math.pi * (10**2), rel=0.01)) == 2 - - cutting_shape = RotateStraightShape(points=[(0, 100), (0, 200), (100, 200), (100, 100)]) - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(math.pi * (10**2), rel=0.01)) == 2 - - def test_force_cross_section_volume(self): - """Checks that a SweepCircleShape with a larger volume is created when - force_cross_section = True than when force_cross_section = False.""" - - test_volume = self.test_shape.volume() - self.test_shape.force_cross_section = True - assert self.test_shape.volume() > test_volume - - def test_surface_count(self): - """Creates a SweepCircleShape and checks that it has the correct number - of surfaces.""" - - assert len(self.test_shape.areas) == 3 - assert len(set(round(i) for i in self.test_shape.areas)) == 2 - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_sweep_mixed_shape.py b/tests/tests_units/test_parametric_shapes/test_sweep_mixed_shape.py deleted file mode 100644 index 908862cf4..000000000 --- a/tests/tests_units/test_parametric_shapes/test_sweep_mixed_shape.py +++ /dev/null @@ -1,155 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import RotateStraightShape, SweepMixedShape - - -class TestSweepMixedShape(unittest.TestCase): - def setUp(self): - self.test_shape = SweepMixedShape( - points=[ - (-10, -10, "straight"), - (-10, 10, "spline"), - (0, 20, "spline"), - (10, 10, "circle"), - (0, 0, "circle"), - (10, -10, "straight"), - ], - path_points=[(50, 0), (30, 50), (70, 100), (50, 150)], - ) - - def test_default_parameters(self): - """Checks that the default parameters of a SweepMixedShape are correct.""" - - # assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - assert self.test_shape.workplane == "XY" - assert self.test_shape.path_workplane == "XZ" - assert self.test_shape.force_cross_section is False - - def test_solid_construction_workplane(self): - """Checks that SweepMixedShapes can be created in different workplanes""" - - self.test_shape.workplane = "YZ" - self.test_shape.path_workplane = "YX" - assert self.test_shape.solid is not None - - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "XY" - assert self.test_shape.solid is not None - - def test_relative_shape_volume_points(self): - """Creates two SweepMixedShapes and checks that their relative volumes - are correct.""" - - self.test_shape.points = [ - (-10, -10, "straight"), - (-10, 10, "spline"), - (0, 20, "spline"), - (10, 10, "circle"), - (0, 0, "circle"), - (10, -10, "straight"), - ] - test_volume = self.test_shape.volume() - self.test_shape.points = [ - (-20, -20, "straight"), - (-20, 20, "spline"), - (0, 40, "spline"), - (20, 20, "circle"), - (0, 0, "circle"), - (20, -20, "straight"), - ] - assert self.test_shape.volume() == pytest.approx(test_volume * 4, rel=0.01) - - def test_relative_shape_volume_azimuthal_placement(self): - """Creates two SweepMixedShapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert self.test_shape.volume() == pytest.approx(test_volume * 4, rel=0.01) - - def test_workplane_path_workplane_error_raises(self): - """Checks that errors are raised when SweepMixedShapes are created with - disallowed workplane and path_workplane combinations.""" - - def workplane_and_path_workplane_equal(): - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "XZ" - - def invalid_relative_workplane_and_path_workplane(): - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "YZ" - - self.assertRaises(ValueError, workplane_and_path_workplane_equal) - self.assertRaises(ValueError, invalid_relative_workplane_and_path_workplane) - - def test_workplane_opposite_distance(self): - """Checks that a SweepMixedShape can be created with workplane XZ and - path_workplane XY.""" - - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "XY" - - assert self.test_shape.solid is not None - - def test_force_cross_section(self): - """Checks that a SweepMixedshape with the same cross-section at each path_point - is created when force_cross_section = True.""" - - self.test_shape.force_cross_section = True - - test_area = round(min(self.test_shape.areas)) - - assert self.test_shape.areas.count(pytest.approx(test_area, rel=0.01)) == 2 - - cutting_shape = RotateStraightShape(points=[(0, 50), (0, 200), (100, 200), (100, 50)]) - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(test_area, rel=0.01)) == 2 - - cutting_shape.points = [(0, 100), (0, 200), (100, 200), (100, 100)] - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(test_area, rel=0.01)) == 2 - - def test_force_cross_section_volume(self): - """Checks that a SweepMixedShape with a larger volume is created when - force_cross_section = True than when force_cross_section = False.""" - - test_volume = self.test_shape.volume() - self.test_shape.force_cross_section = True - assert self.test_shape.volume() > test_volume - - def test_surface_count(self): - """Creates a SweepStraightShape and checks that it has the correct number - of surfaces.""" - - assert len(self.test_shape.areas) == 6 - assert len(set(round(i) for i in self.test_shape.areas)) == 5 - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_sweep_spline_shape.py b/tests/tests_units/test_parametric_shapes/test_sweep_spline_shape.py deleted file mode 100644 index 69572c891..000000000 --- a/tests/tests_units/test_parametric_shapes/test_sweep_spline_shape.py +++ /dev/null @@ -1,124 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import RotateStraightShape, SweepSplineShape - - -class TestSweepSplineShape(unittest.TestCase): - def setUp(self): - self.test_shape = SweepSplineShape( - points=[(-10, 10), (10, 10), (10, -10), (-10, -10)], - path_points=[(50, 0), (30, 50), (70, 100), (50, 150)], - ) - - def test_default_parameters(self): - """Checks that the default parameters of a SweepSplineShape are correct.""" - - # assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - assert self.test_shape.workplane == "XY" - assert self.test_shape.path_workplane == "XZ" - assert self.test_shape.force_cross_section is False - - def test_solid_construction_workplane(self): - """Checks that SweepSplineShapes can be created in different workplanes.""" - - self.test_shape.workplane = "YZ" - self.test_shape.path_workplane = "YX" - assert self.test_shape.solid is not None - - self.test_shape.workplane = "XZ" - self.test_shape.path_workplane = "XY" - assert self.test_shape.solid is not None - - def test_relative_shape_volume_points(self): - """Creates two SweepSplineShapes and checks that their relative volumes - are correct.""" - - self.test_shape.points = [(-20, 20), (20, 20), (20, -20), (-20, -20)] - test_volume = self.test_shape.volume() - self.test_shape.points = [(-10, 10), (10, 10), (10, -10), (-10, -10)] - assert self.test_shape.volume() == pytest.approx(test_volume * 0.25, rel=0.01) - - def test_relative_shape_volume_azimuthal_placement(self): - """Creates two SweepSplineShapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert self.test_shape.volume() == pytest.approx(test_volume * 4, rel=0.01) - - def test_force_cross_section(self): - """Checks that a SweepSplineShape with the same cross-section at each path_point - is created when force_cross_section = True.""" - - self.test_shape.force_cross_section = True - - test_area = round(min(self.test_shape.areas)) - - assert self.test_shape.areas.count(pytest.approx(test_area, rel=0.01)) == 2 - - cutting_shape = RotateStraightShape(points=[(0, 50), (0, 200), (100, 200), (100, 50)]) - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(test_area, rel=0.01)) == 2 - - cutting_shape.points = [(0, 100), (0, 200), (100, 200), (100, 100)] - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(test_area, rel=0.01)) == 2 - - def test_force_cross_section_volume(self): - """Checks that a SweepSplineShape with a larger volume is created when - force_cross_section = True than when force_cross_section = False.""" - - test_volume = self.test_shape.volume() - self.test_shape.force_cross_section = True - assert self.test_shape.volume() > test_volume - - def test_surface_count(self): - """Creates a SweepSplineShape and checks that it has the correct number - of surfaces.""" - - assert len(self.test_shape.areas) == 3 - assert len(set(round(i) for i in self.test_shape.areas)) == 2 - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_incorrect_points_input(self): - """Checks that an error is raised when the points are input with the - connection""" - - def incorrect_points_definition(): - self.test_shape.points = [ - (10, 10, "spline"), - (10, 30, "spline"), - (30, 30, "spline"), - (30, 10, "spline"), - ] - - self.assertRaises(ValueError, incorrect_points_definition) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_parametric_shapes/test_sweep_straight_shape.py b/tests/tests_units/test_parametric_shapes/test_sweep_straight_shape.py deleted file mode 100644 index 0263934f4..000000000 --- a/tests/tests_units/test_parametric_shapes/test_sweep_straight_shape.py +++ /dev/null @@ -1,162 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest - -from paramak import RotateStraightShape, SweepStraightShape - - -class TestSweepStraightShape(unittest.TestCase): - def setUp(self): - self.test_shape = SweepStraightShape( - points=[(-10, 10), (10, 10), (10, -10), (-10, -10)], - path_points=[(50, 0), (30, 50), (70, 100), (50, 150)], - ) - - def test_translate(self): - """Checks the shape extends to the bounding box and then translates - the shape and checks it is extended to the new bounding box""" - - assert pytest.approx(self.test_shape.solid.val().BoundingBox().xmax) == 80.94405253029915 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().xmin) == 19.055947469700666 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().ymax) == 10.000000100000012 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().ymin) == -10.000000100000012 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().zmax) == 150.00000010000002 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().zmin) == -1.0000000355271367e-07 - - self.test_shape.translate = (1, 2, 3) - - assert pytest.approx(self.test_shape.solid.val().BoundingBox().xmax) == 80.94405253029915 + 1 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().xmin) == 19.055947469700666 + 1 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().ymax) == 10.000000100000012 + 2 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().ymin) == -10.000000100000012 + 2 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().zmax) == 150.00000010000002 + 3 - assert pytest.approx(self.test_shape.solid.val().BoundingBox().zmin) == -1.0000000355271367e-07 + 3 - - def test_default_parameters(self): - """Checks that the default parameters of a SweepStraightShape are - correct.""" - - # assert self.test_shape.rotation_angle == 360 - assert self.test_shape.azimuth_placement_angle == 0 - assert self.test_shape.workplane == "XY" - assert self.test_shape.path_workplane == "XZ" - assert self.test_shape.force_cross_section is False - - def test_absolute_shape_volume(self): - """Creates a SweepStraightShape and checks that the volume is - correct.""" - - self.test_shape.path_points = [(50, 0), (50, 50), (50, 100)] - assert self.test_shape.solid is not None - assert self.test_shape.volume() == pytest.approx(20 * 20 * 100) - - def test_relative_shape_volume(self): - """Creates two SweepStraightShapes and checks that their relative - volumes are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.points = [(-20, 20), (20, 20), (20, -20), (-20, -20)] - assert self.test_shape.volume() == pytest.approx(test_volume * 4) - - def test_relative_shape_volume_again(self): - """Creates two SweepStraightShapes and checks that their relative volumes - are correct.""" - - test_volume = self.test_shape.volume() - self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert self.test_shape.volume() == pytest.approx(test_volume * 4) - - def test_force_cross_section(self): - """Checks that a SweepStraightShape with the same cross-section at each path_point - is created when force_cross_section = True.""" - - self.test_shape.force_cross_section = True - - assert self.test_shape.areas.count(pytest.approx(400, rel=0.01)) == 2 - - cutting_shape = RotateStraightShape( - points=[(0, 50), (0, 200), (100, 200), (100, 50)], - ) - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(400, rel=0.01)) == 2 - - cutting_shape.points = [(0, 100), (0, 200), (100, 200), (100, 100)] - self.test_shape.cut = cutting_shape - - assert self.test_shape.areas.count(pytest.approx(400, rel=0.01)) == 2 - - def test_force_cross_section_volume(self): - """Checks that a SweepStraightShape with a larger volume is created when - force_cross_section = True than when force_cross_section = False.""" - - test_volume = self.test_shape.volume() - self.test_shape.force_cross_section = True - assert self.test_shape.volume() > test_volume - - def test_surface_count(self): - """Creates a SweepStraightShape and checks that it has the correct number - of surfaces.""" - - assert len(self.test_shape.areas) == 6 - assert len(set(round(i) for i in self.test_shape.areas)) == 3 - - def test_export_stp(self): - """Exports and stp file with mode = solid and wire and checks - that the outputs exist and relative file sizes are correct.""" - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - self.test_shape.export_stp("test_solid.stp", mode="solid") - self.test_shape.export_stp("test_solid2.stp") - self.test_shape.export_stp("test_wire.stp", mode="wire") - - assert Path("test_solid.stp").exists() is True - assert Path("test_solid2.stp").exists() is True - assert Path("test_wire.stp").exists() is True - - assert Path("test_solid.stp").stat().st_size == Path("test_solid2.stp").stat().st_size - assert Path("test_wire.stp").stat().st_size < Path("test_solid2.stp").stat().st_size - - os.system("rm test_solid.stp test_solid2.stp test_wire.stp") - - def test_export_brep(self): - """Exports a brep file and checks that the output exist""" - - os.system("rm test_solid.brep") - - self.test_shape.export_brep(filename="test_solid.brep") - - assert Path("test_solid.brep").exists() is True - - os.system("rm test_solid.brep") - - def test_export_brep_without_extention(self): - """Exports a brep file without the extention and checks that the - output exist""" - - def missing_extention(): - - self.test_shape.export_brep(filename="test_solid_missing") - - self.assertRaises(ValueError, missing_extention) - - def test_incorrect_points_input(self): - """Checks that an error is raised when the points are input with the - connection""" - - def incorrect_points_definition(): - self.test_shape.points = [ - (10, 10, "straight"), - (10, 30, "straight"), - (30, 30, "straight"), - (30, 10, "straight"), - ] - - self.assertRaises(ValueError, incorrect_points_definition) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_reactor.py b/tests/tests_units/test_reactor.py deleted file mode 100644 index adc887c1f..000000000 --- a/tests/tests_units/test_reactor.py +++ /dev/null @@ -1,325 +0,0 @@ -import os -import unittest -from pathlib import Path - -import cadquery as cq -import pytest - -import paramak - - -class TestReactor(unittest.TestCase): - def setUp(self): - self.test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], name="test_shape") - - self.test_shape2 = paramak.ExtrudeStraightShape( - points=[(100, 100), (50, 100), (50, 50)], distance=20, name="test_shape2" - ) - - test_shape_3 = paramak.PoloidalFieldCoilSet( - heights=[2, 2], widths=[3, 3], center_points=[(50, -100), (50, 100)] - ) - - self.test_reactor = paramak.Reactor([self.test_shape]) - - self.test_reactor_2 = paramak.Reactor([self.test_shape, self.test_shape2]) - - # this reactor has a compound shape in the geometry - self.test_reactor_3 = paramak.Reactor([self.test_shape, test_shape_3]) - - def test_bounding_box(self): - """checks the bounding box value""" - - bounding_box = self.test_reactor_2.bounding_box - - assert bounding_box[0][0] == pytest.approx(-20.0) - assert bounding_box[0][1] == pytest.approx(-20.0) - assert bounding_box[0][2] == pytest.approx(0.0) - assert bounding_box[1][0] == pytest.approx(100.0) - assert bounding_box[1][1] == pytest.approx(20.0) - assert bounding_box[1][2] == pytest.approx(100.0) - - def test_reactor_export_stp_with_name_set_to_none(self): - """Exports the reactor as separate files and as a single file""" - - def incorrect_name(): - self.test_shape.name = None - - paramak.Reactor([self.test_shape]) - - self.test_reactor.export_stp() - - self.assertRaises(ValueError, incorrect_name) - - def test_reactor_export_stp(self): - """Exports the reactor as separate files and as a single file""" - os.system("rm *.stp") - self.test_reactor_2.export_stp(filename=["RotateStraightShape.stp", "ExtrudeStraightShape.stp"]) - assert Path("RotateStraightShape.stp").is_file() - assert Path("ExtrudeStraightShape.stp").is_file() - self.test_reactor_2.export_stp(filename="single_file.stp", units="cm") - assert Path("single_file.stp").is_file() - - def test_largest_dimension_setting_and_getting_using_largest_shapes(self): - """Makes a neutronics model and checks the default largest_dimension - and that largest_dimension changes with largest_shapes""" - - assert pytest.approx(self.test_reactor.largest_dimension) == 20.0 - assert self.test_reactor_2.largest_dimension == 100.0 - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape2 = paramak.RotateStraightShape(points=[(0, 0), (0, 40), (40, 40)]) - - test_reactor = paramak.Reactor([test_shape, test_shape2]) - assert pytest.approx(test_reactor.largest_dimension) == 40 - - def test_make_sector_wedge(self): - """Checks that the wedge is not made when rotation angle is 360""" - sector_wedge = self.test_reactor.make_sector_wedge(height=100, radius=100, rotation_angle=360) - assert sector_wedge is None - - def test_wrong_number_of_filenames(self): - def test_stl_filename_list_length(): - test_shape = paramak.ExtrudeCircleShape(points=[(20, 20)], radius=10, distance=10) - my_reactor = paramak.Reactor([test_shape]) - my_reactor.export_stl(["wrong.stl", "number_of.stl", "files.stl"]) - - self.assertRaises(ValueError, test_stl_filename_list_length) - - def test_reactor_creation_with_default_properties(self): - """creates a Reactor object and checks that it has no default properties""" - - test_reactor = paramak.Reactor([]) - - assert test_reactor is not None - - def test_adding_component_to_reactor(self): - """creates a Reactor object and checks that shapes can be added to it""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - test_shape.create_solid() - test_reactor = paramak.Reactor([]) - assert len(test_reactor.shapes_and_components) == 0 - test_reactor = paramak.Reactor([test_shape]) - assert len(test_reactor.shapes_and_components) == 1 - - def test_exported_stp_files_exist(self): - """creates a Reactor object with one shape and checks that a stp file - of the reactor can be exported to a specified location using the export_stp - method""" - - os.system("rm test_reactor/*.stp") - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - - os.system("rm test_reactor/test_shape.stp") - - test_reactor = paramak.Reactor([test_shape]) - - test_reactor.export_stp("test_reactor/test_shape.stp") - - assert Path("test_reactor/test_shape.stp").exists() is True - - def test_exported_stl_files_exist(self): - """creates a Reactor object with one shape and checks that a stl file - of the reactor can be exported to a specified location using the - export_stl method""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - os.system("rm test_reactor/test_shape.stl") - test_reactor = paramak.Reactor([test_shape]) - - test_reactor.export_stl(filename="test_reactor/test_shape.stl") - - assert Path("test_reactor/test_shape.stl").exists() is True - os.system("rm test_reactor/test_shape.stl") - - def test_reactor_export_stl_with_name_set_to_none(self): - """Exports the reactor as separate files and as a single file""" - - def incorrect_name(): - self.test_shape.name = None - - paramak.Reactor([self.test_shape]) - - self.test_reactor.export_stl() - - self.assertRaises(ValueError, incorrect_name) - - def test_exported_svg_files_exist(self): - """Creates a Reactor object with one shape and checks that a svg file - of the reactor can be exported to a specified location using the - export_svg method.""" - - os.system("rm test_svg_image.svg") - - self.test_reactor.export_svg("test_svg_image.svg") - - assert Path("test_svg_image.svg").exists() is True - os.system("rm test_svg_image.svg") - - def test_exported_svg_files_exist_no_extension(self): - """creates a Reactor object with one shape and checks that an svg file - of the reactor can be exported to a specified location using the export_svg - method""" - - os.system("rm test_svg_image.svg") - - self.test_reactor.export_svg("test_svg_image") - - assert Path("test_svg_image.svg").exists() is True - os.system("rm test_svg_image.svg") - - def test_export_svg_options(self): - """Exports the test reactor to an svg image and checks that a svg file - can be exported with the various different export options""" - - os.system("rm *.svg") - self.test_reactor.export_svg("r_width.svg", width=900) - assert Path("r_width.svg").exists() is True - self.test_reactor.export_svg("r_height.svg", height=900) - assert Path("r_height.svg").exists() is True - self.test_reactor.export_svg("r_marginLeft.svg", marginLeft=110) - assert Path("r_marginLeft.svg").exists() is True - self.test_reactor.export_svg("r_marginTop.svg", marginTop=110) - assert Path("r_marginTop.svg").exists() is True - self.test_reactor.export_svg("r_showAxes.svg", showAxes=True) - assert Path("r_showAxes.svg").exists() is True - self.test_reactor.export_svg("r_projectionDir.svg", projectionDir=(-1, -1, -1)) - assert Path("r_projectionDir.svg").exists() is True - self.test_reactor.export_svg("r_strokeColor.svg", strokeColor=(42, 42, 42)) - assert Path("r_strokeColor.svg").exists() is True - self.test_reactor.export_svg("r_hiddenColor.svg", hiddenColor=(42, 42, 42)) - assert Path("r_hiddenColor.svg").exists() is True - self.test_reactor.export_svg("r_showHidden.svg", showHidden=False) - assert Path("r_showHidden.svg").exists() is True - self.test_reactor.export_svg("r_strokeWidth1.svg", strokeWidth=None) - assert Path("r_strokeWidth1.svg").exists() is True - self.test_reactor.export_svg("r_strokeWidth2.svg", strokeWidth=10) - assert Path("r_strokeWidth2.svg").exists() is True - - def test_export_2d_image(self): - """Creates a Reactor object and checks that a png file of the reactor - with the correct filename can be exported using the export_2D_image - method.""" - - os.system("rm 2D_test_image.png") - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - test_reactor = paramak.Reactor([test_shape]) - returned_filename = test_reactor.export_2d_image(filename="2D_test_image.png") - - assert Path(returned_filename).exists() is True - os.system("rm 2D_test_image.png") - - def test_export_2d_image_without_extension(self): - """creates a Reactor object and checks that a png file of the reactor - with the correct filename can be exported using the export_2d_image - method""" - - os.system("rm 2d_test_image.png") - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - test_reactor = paramak.Reactor([test_shape]) - returned_filename = test_reactor.export_2d_image(filename="2d_test_image") - - assert Path(returned_filename).exists() is True - os.system("rm 2d_test_image.png") - - def test_export_html(self): - """Creates a Reactor object and checks that a html file of the reactor - with the correct filename can be exported using the export_html - method.""" - - os.system("rm test_html.html") - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - test_reactor = paramak.Reactor([test_shape]) - test_reactor.export_html(filename="test_html.html") - - assert Path("test_html.html").exists() is True - os.system("rm test_html.html") - test_reactor.export_html(filename="test_html") - - assert Path("test_html.html").exists() is True - os.system("rm test_html.html") - - def test_largest_dimension(self): - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - test_shape.rotation_angle = 360 - test_reactor = paramak.Reactor([test_shape]) - assert pytest.approx(test_reactor.largest_dimension, rel=0.1) == 20 - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (30, 20)]) - test_shape.rotation_angle = 360 - test_reactor = paramak.Reactor([test_shape]) - assert pytest.approx(test_reactor.largest_dimension, rel=0.1) == 30 - - def test_shapes_and_components(self): - """Attempts to make a reactor with a single shape instead of a list of - shapes which should raise a ValueError""" - - def incorrect_shapes_and_components(): - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - paramak.Reactor(test_shape) - - self.assertRaises(ValueError, incorrect_shapes_and_components) - - def test_compound_in_shapes(self): - shape1 = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - shape2 = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - shape3 = paramak.Shape() - shape3.solid = cq.Compound.makeCompound([a.val() for a in [shape1.solid, shape2.solid]]) - test_reactor = paramak.Reactor([shape3]) - assert test_reactor.solid is not None - - def test_sector_wedge_with_360_returns_none(self): - """Tries to make a sector wedge with full 360 degree rotation and checks - that None is returned""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)]) - my_reactor = paramak.Reactor([test_shape]) - assert my_reactor.make_sector_wedge(rotation_angle=360) is None - - def test_reactor_volume(self): - """Checks the types returned by the .volume method are correct""" - - assert isinstance(self.test_reactor.volume(), list) - assert isinstance(self.test_reactor.volume(), list) - assert isinstance(self.test_reactor.volume()[0], float) - assert isinstance(self.test_reactor_2.volume()[0], float) - assert isinstance(self.test_reactor_2.volume()[1], float) - assert len(self.test_reactor.volume()) == 1 - assert len(self.test_reactor_2.volume()) == 2 - assert sum(self.test_reactor_2.volume()) > sum(self.test_reactor.volume()) - assert self.test_reactor_2.volume()[0] == self.test_reactor.volume()[0] - - def test_reactor_volume_spliting_compounds(self): - """Checks the volumes returned by the .volume method with splitting of - compounds set to True are correct""" - - assert isinstance(self.test_reactor_3.volume(split_compounds=True), list) - assert isinstance(self.test_reactor_3.volume(split_compounds=False), list) - assert isinstance(self.test_reactor_3.volume(split_compounds=True)[0], list) - assert isinstance(self.test_reactor_3.volume(split_compounds=True)[1], list) - assert isinstance(self.test_reactor_3.volume(split_compounds=False)[0], float) - assert isinstance(self.test_reactor_3.volume(split_compounds=False)[1], float) - assert isinstance(self.test_reactor_3.volume(split_compounds=True)[1][0], float) - assert isinstance(self.test_reactor_3.volume(split_compounds=True)[1][1], float) - assert len(self.test_reactor_3.volume(split_compounds=True)) == 2 - assert len(self.test_reactor_3.volume(split_compounds=True)[1]) == 2 - - vol_1 = self.test_reactor_3.volume(split_compounds=True)[1][0] - vol_2 = self.test_reactor_3.volume(split_compounds=True)[1][1] - assert vol_1 == vol_2 - vol_3 = self.test_reactor_3.volume(split_compounds=False)[1] - assert pytest.approx(vol_3) == vol_1 + vol_2 - - def test_reactor_names(self): - "checks that the names attribute returns the expected results" - assert self.test_reactor_2.name == ["test_shape", "test_shape2"] - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_shape.py b/tests/tests_units/test_shape.py deleted file mode 100644 index 030c9a954..000000000 --- a/tests/tests_units/test_shape.py +++ /dev/null @@ -1,610 +0,0 @@ -import os -import unittest -from pathlib import Path - -import pytest -from cadquery import Plane - -import paramak - - -class TestShape(unittest.TestCase): - def setUp(self): - - self.my_shape = paramak.CenterColumnShieldHyperbola( - height=500, - inner_radius=50, - mid_radius=60, - outer_radius=100, - ) - - self.test_rotate_mixed_shape = paramak.RotateMixedShape( - rotation_angle=1, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "straight"), - (110, 45, "straight"), - ], - ) - self.test_extrude_mixed_shape = paramak.ExtrudeMixedShape( - distance=1, - points=[ - (100, 0, "straight"), - (200, 0, "circle"), - (250, 50, "circle"), - (200, 100, "straight"), - (150, 100, "straight"), - (140, 75, "straight"), - (110, 45, "straight"), - ], - ) - - def test_shape_default_properties(self): - """Creates a Shape object and checks that the points attribute has - a default of None.""" - - test_shape = paramak.Shape() - - assert test_shape.points is None - - def test_azimuth_placement_angle_getting_setting(self): - """Checks that the azimuth_placement_angle of a Shape can be - changed to a single value or iterable.""" - - test_shape = paramak.Shape() - - assert test_shape.azimuth_placement_angle == 0 - test_shape.azimuth_placement_angle = 180 - assert test_shape.azimuth_placement_angle == 180 - test_shape.azimuth_placement_angle = [0, 90, 180, 270] - assert test_shape.azimuth_placement_angle == [0, 90, 180, 270] - - def test_missing_filename_arg_in_export_stp(self): - """Checks that an error is raised when a stp export is requested - without a filename.""" - - def incorrect_args(): - self.my_shape.export_stp() - - self.assertRaises(TypeError, incorrect_args) - - def test_missing_filename_arg_in_export_stl(self): - """Checks that an error is raised when a stl export is requested - without a filename.""" - - def incorrect_args(): - self.my_shape.export_stl() - - self.assertRaises(TypeError, incorrect_args) - - def test_incorrect_color_values(self): - """Checks that an error is raised when the color of a shape is - defined as an invalid string.""" - - def incorrect_color_string(): - paramak.Shape(color=("1", "0", "1")) - - self.assertRaises(ValueError, incorrect_color_string) - - def test_incorrect_workplane(self): - """Creates Shape object with incorrect workplane and checks errors - are raised.""" - - with pytest.raises(ValueError): - paramak.Shape(workplane="AB") - - with pytest.raises(TypeError): - paramak.Shape(workplane=2) - - with pytest.raises(TypeError): - paramak.Shape(workplane=[1, 2]) - - def test_incorrect_points(self): - """Creates Shape objects and checks errors are raised correctly when - specifying points.""" - - test_shape = paramak.Shape() - - def incorrect_points_end_point_is_start_point(): - """Checks ValueError is raised when the start and end points are - the same.""" - # setting straight otherwise another error is caught - test_shape.connection_type = "straight" - test_shape.points = [(0, 200), (200, 100), (0, 0), (0, 200)] - - # check that an error is raised - with pytest.raises(ValueError) as err: - incorrect_points_end_point_is_start_point() - - # check that the correct error was raised - expected_err_message = "The coordinates of the last and first points are" - assert expected_err_message in str(err.value) - - def incorrect_points_missing_z_value(): - """Checks ValueError is raised when a point is missing a z - value.""" - - test_shape.points = [(0, 200), (200), (0, 0), (0, 50)] - - self.assertRaises(ValueError, incorrect_points_missing_z_value) - - def incorrect_points_not_a_list(): - """Checks ValueError is raised when the points are not a list.""" - - test_shape.points = "(0, 0), (0, 20), (20, 20), (20, 0)" - - self.assertRaises(ValueError, incorrect_points_not_a_list) - - def incorrect_points_wrong_number_of_entries(): - """Checks ValueError is raised when individual points dont have 2 - or 3 entries.""" - - test_shape.points = [(0, 0), (0, 20), (20, 20, 20, 20)] - - self.assertRaises(ValueError, incorrect_points_wrong_number_of_entries) - - def incorrect_x_point_value_type(): - """Checks ValueError is raised when X point is not a number.""" - - test_shape.points = [("string", 0), (0, 20), (20, 20)] - - self.assertRaises(ValueError, incorrect_x_point_value_type) - - def incorrect_y_point_value_type(): - """Checks ValueError is raised when Y point is not a number.""" - - test_shape.points = [(0, "string"), (0, 20), (20, 20)] - - self.assertRaises(ValueError, incorrect_y_point_value_type) - - def test_create_limits(self): - """Creates a Shape object and checks that the create_limits function - returns the expected values for x_min, x_max, z_min and z_max.""" - - test_shape = paramak.Shape(connection_type="straight") - - test_shape.points = [ - (0, 0), - (0, 10), - (0, 20), - (10, 20), - (20, 20), - (20, 10), - (20, 0), - (10, 0), - ] - - assert test_shape.create_limits() == (0.0, 20.0, 0.0, 20.0) - - # test with a component which has a find_points method - test_shape2 = paramak.Plasma() - test_shape2.create_limits() - assert test_shape2.x_min is not None - - def test_create_limits_error(self): - """Checks error is raised when no points are given.""" - - test_shape = paramak.Shape() - - def limits(): - test_shape.create_limits() - - self.assertRaises(ValueError, limits) - - def test_initial_solid_construction(self): - """Creates a shape and checks that a cadquery solid with a unique hash - value is created when .solid is called.""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)], rotation_angle=360) - - assert test_shape.hash_value is None - assert test_shape.solid is not None - assert type(test_shape.solid).__name__ == "Workplane" - assert test_shape.hash_value is not None - - def test_solid_return(self): - """Checks that the same cadquery solid with the same unique hash value - is returned when shape.solid is called again after no changes have been - made to the Shape.""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)], rotation_angle=360) - - assert test_shape.solid is not None - initial_hash_value = test_shape.hash_value - assert test_shape.solid is not None - assert initial_hash_value == test_shape.hash_value - - def test_conditional_solid_reconstruction(self): - """Checks that a new cadquery solid with a new unique hash value is - constructed when shape.solid is called after changes to the Shape have - been made.""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], rotation_angle=360) - - assert test_shape.solid is not None - assert test_shape.hash_value is not None - initial_hash_value = test_shape.hash_value - - test_shape.rotation_angle = 180 - - assert test_shape.solid is not None - assert test_shape.hash_value is not None - assert initial_hash_value != test_shape.hash_value - - def test_hash_value_update(self): - """Checks that the hash value of a Shape is not updated until a new - cadquery solid has been created.""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], rotation_angle=360) - test_shape.solid - assert test_shape.hash_value is not None - initial_hash_value = test_shape.hash_value - - test_shape.rotation_angle = 180 - assert test_shape.hash_value == initial_hash_value - test_shape.solid - assert test_shape.hash_value != initial_hash_value - - def test_export_html(self): - """Checks a plotly figure of the Shape is exported by the export_html - method with the correct filename with RGB and RGBA colors.""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)], rotation_angle=360) - - os.system("rm filename.html") - test_shape.export_html("filename") - assert Path("filename.html").exists() is True - os.system("rm filename.html") - test_shape.color = (1, 0, 0, 0.5) - test_shape.export_html("filename") - assert Path("filename.html").exists() is True - os.system("rm filename.html") - - def test_export_html_view_planes(self): - """Checks a plotly figure of the Shape is exported by the export_html - method with a range of different view_plane options.""" - - test_shape = paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20), (20, 0)], rotation_angle=180) - - for view_plane in ["XZ", "XY", "YZ", "YX", "ZY", "ZX", "RZ", "XYZ"]: - os.system("rm *.html") - test_shape.export_html(filename="filename", view_plane=view_plane) - assert Path("filename.html").exists() is True - - def test_export_html_with_points_None(self): - """Checks that an error is raised when points is None and export_html""" - test_shape = paramak.Shape() - - def export(): - test_shape.export_html("out.html") - - self.assertRaises(ValueError, export) - - def test_export_html_with_wire_None(self): - """Checks that an error is raised when wire is None and export_html""" - test_shape = paramak.Shape( - points=[(0, 0), (0, 20), (20, 20), (20, 0)], - connection_type="straight", - ) - test_shape.wire = None - - def export(): - test_shape.export_html("out.html") - - self.assertRaises(ValueError, export) - - def test_invalid_stp_filename(self): - """Checks ValueError is raised when invalid stp filenames are used.""" - - def invalid_filename_suffix(): - - test_shape = paramak.RotateStraightShape( - points=[(0, 0), (0, 20), (20, 20)], - ) - test_shape.export_stp(filename="test_shape.txt") - - self.assertRaises(ValueError, invalid_filename_suffix) - - def invalid_filename_type(): - - test_shape = paramak.RotateStraightShape( - points=[(0, 0), (0, 20), (20, 20)], - ) - test_shape.export_stp(filename=1) - - self.assertRaises(TypeError, invalid_filename_type) - - def test_invalid_stl_filename(self): - """Checks ValueError is raised when invalid stl filenames are used.""" - - def invalid_filename_suffix(): - - test_shape = paramak.RotateStraightShape( - points=[(0, 0), (0, 20), (20, 20)], - ) - test_shape.export_stl(filename="test_shape.txt") - - self.assertRaises(ValueError, invalid_filename_suffix) - - def invalid_filename_type(): - - test_shape = paramak.RotateStraightShape( - points=[(0, 0), (0, 20), (20, 20)], - ) - test_shape.export_stp(filename=1) - - self.assertRaises(TypeError, invalid_filename_type) - - def test_invalid_color(self): - """Checks ValueError is raised when invalid colors are used.""" - - def invalid_color_type(): - - paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], color=255) - - self.assertRaises(ValueError, invalid_color_type) - - def invalid_color_length(): - - paramak.RotateStraightShape(points=[(0, 0), (0, 20), (20, 20)], color=(255, 255, 255, 1, 1)) - - self.assertRaises(ValueError, invalid_color_length) - - def test_volumes_add_up_to_total_volume_Compound(self): - """Checks the volume and volumes attributes are correct types - and that the volumes sum to equalt the volume for a Compound.""" - - test_shape = paramak.PoloidalFieldCoilSet(heights=[10, 10], widths=[20, 20], center_points=[(15, 15), (50, 50)]) - - assert isinstance(test_shape.volume(), float) - assert isinstance(test_shape.volume(split_compounds=True), list) - assert isinstance(test_shape.volume(split_compounds=True)[0], float) - assert isinstance(test_shape.volume(split_compounds=True)[1], float) - assert len(test_shape.volume(split_compounds=True)) == 2 - assert sum(test_shape.volume(split_compounds=True)) == pytest.approx(test_shape.volume()) - - def test_volumes_add_up_to_total_volume(self): - """Checks the volume and volumes attributes are correct types - and that the volumes sum to equalt the volume.""" - - test_shape = paramak.PoloidalFieldCoil(center_point=(100, 100), height=50, width=50) - - assert isinstance(test_shape.volume(), float) - assert isinstance(test_shape.volume(split_compounds=True), list) - assert isinstance(test_shape.volume(split_compounds=True)[0], float) - assert len(test_shape.volume(split_compounds=True)) == 1 - assert sum(test_shape.volume(split_compounds=True)) == pytest.approx(test_shape.volume()) - - def test_areas_add_up_to_total_area_Compound(self): - """Checks the area and areas attributes are correct types - and that the areas sum to equalt the area for a Compound.""" - - test_shape = paramak.PoloidalFieldCoilSet(heights=[10, 10], widths=[20, 20], center_points=[(15, 15), (50, 50)]) - - assert isinstance(test_shape.area, float) - assert isinstance(test_shape.areas, list) - assert isinstance(test_shape.areas[0], float) - assert isinstance(test_shape.areas[1], float) - assert isinstance(test_shape.areas[2], float) - assert isinstance(test_shape.areas[3], float) - assert isinstance(test_shape.areas[4], float) - assert isinstance(test_shape.areas[5], float) - assert isinstance(test_shape.areas[6], float) - assert isinstance(test_shape.areas[7], float) - assert len(test_shape.areas) == 8 - assert sum(test_shape.areas) == pytest.approx(test_shape.area) - - def test_areas_add_up_to_total_area(self): - """Checks the area and areas attributes are correct types - and that the areas sum to equalt the area.""" - - test_shape = paramak.PoloidalFieldCoil(center_point=(100, 100), height=50, width=50) - - assert isinstance(test_shape.area, float) - assert isinstance(test_shape.areas, list) - assert isinstance(test_shape.areas[0], float) - assert isinstance(test_shape.areas[1], float) - assert isinstance(test_shape.areas[2], float) - assert isinstance(test_shape.areas[3], float) - assert len(test_shape.areas) == 4 - assert sum(test_shape.areas) == pytest.approx(test_shape.area) - - def test_create_patch_error(self): - """Checks _create_patch raises a ValueError when points is None.""" - - test_shape = paramak.Shape() - - def patch(): - test_shape._create_patch() - - self.assertRaises(ValueError, patch) - - def test_create_patch_alpha(self): - """Checks _create_patch returns a patch when alpha is given.""" - - test_shape = paramak.PoloidalFieldCoil(center_point=(100, 100), height=50, width=50, color=(0.5, 0.5, 0.5, 0.1)) - assert test_shape._create_patch() is not None - - def test_azimuth_placement_angle_error(self): - """Checks an error is raised when invalid value for - azimuth_placement_angle is set. - """ - - test_shape = paramak.Shape() - - def angle_str(): - test_shape.azimuth_placement_angle = "coucou" - - def angle_str_in_Iterable(): - test_shape.azimuth_placement_angle = [0, "coucou"] - - self.assertRaises(ValueError, angle_str) - self.assertRaises(ValueError, angle_str_in_Iterable) - - def test_name_error(self): - """Checks an error is raised when invalid value for name is set.""" - - test_shape = paramak.Shape() - - def name_float(): - test_shape.name = 2.0 - - def name_int(): - test_shape.name = 1 - - def name_list(): - test_shape.name = ["coucou"] - - self.assertRaises(ValueError, name_float) - self.assertRaises(ValueError, name_int) - self.assertRaises(ValueError, name_list) - - def test_workplane_of_type_cadquery_plane(self): - """Tests that a Cadquery.Plane is accepted as a workplane entry""" - - normal_vec = (1, 1, 1) - workplane = Plane(origin=(0, 0, 0), xDir=(-1, 1, 0), normal=normal_vec) - # in future releases of CQ, origin and xDir will be optional - - test_shape = paramak.Shape( - workplane=workplane, - ) - - assert isinstance(test_shape.workplane, Plane) - - def test_get_rotation_axis(self): - """Creates a shape and test the expected rotation_axis is the correct - values for several cases - """ - shape = paramak.Shape() - expected_dict = { - "X": [(-1, 0, 0), (1, 0, 0)], - "-X": [(1, 0, 0), (-1, 0, 0)], - "Y": [(0, -1, 0), (0, 1, 0)], - "-Y": [(0, 1, 0), (0, -1, 0)], - "Z": [(0, 0, -1), (0, 0, 1)], - "-Z": [(0, 0, 1), (0, 0, -1)], - } - # test with axis from string - for axis in expected_dict: - shape.rotation_axis = axis - assert shape.get_rotation_axis()[0] == expected_dict[axis] - assert shape.get_rotation_axis()[1] == axis - - # test with axis from list of two points - expected_axis = [(-1, -2, -3), (1, 4, 5)] - shape.rotation_axis = expected_axis - assert shape.get_rotation_axis()[0] == expected_axis - assert shape.get_rotation_axis()[1] == "custom_axis" - - # test with axis from workplane - shape.rotation_axis = None - - workplanes = ["XY", "XZ", "YZ"] - expected_axis = ["Y", "Z", "Z"] - for wp, axis in zip(workplanes, expected_axis): - shape.workplane = wp - assert shape.get_rotation_axis()[0] == expected_dict[axis] - assert shape.get_rotation_axis()[1] == axis - - # test with axis from path_workplane - for wp, axis in zip(workplanes, expected_axis): - shape.path_workplane = wp - assert shape.get_rotation_axis()[0] == expected_dict[axis] - assert shape.get_rotation_axis()[1] == axis - - def test_rotation_axis_error(self): - """Checks errors are raised when incorrect values of rotation_axis are - set - """ - incorrect_values = [ - "coucou", - 2, - 2.2, - [(1, 1, 1), "coucou"], - [(1, 1, 1), 1], - [(1, 1, 1), 1.0], - [(1, 1, 1), (1, 1, 1)], - [(1, 1, 1), (1, 0, 1, 2)], - [(1, 1, 1, 2), (1, 0, 2)], - # [(1, 1, 2), [1, 0, 2]], lists are now acceptable - [(1, 1, 1)], - [(1, 1, 1), (1, "coucou", 1)], - [(1, 1, 1), (1, 0, 1), (1, 2, 3)], - ] - shape = paramak.Shape() - - def set_value(): - shape.rotation_axis = incorrect_values[i] - - for i in range(len(incorrect_values)): - self.assertRaises(ValueError, set_value) - - def test_setting_color_incorrectly_too_large(self): - """Sets the shape.colour outside of the the 0 to 1 range""" - - def check_correct_error_is_rasied(): - self.my_shape.color = (255, 255, 2) - - self.assertRaises(ValueError, check_correct_error_is_rasied) - - def test_setting_color_incorrectly_too_small(self): - """Sets the shape.colour outside of the the 0 to 1 range""" - - def check_correct_error_is_rasied(): - self.my_shape.color = (-1, 0, 0) - - self.assertRaises(ValueError, check_correct_error_is_rasied) - - def test_reuse_points_between_shapes(self): - """Checks that points can be reused between shapes""" - points = [ - (100, 0, "straight"), - (200, 0, "straight"), - (250, 50, "straight"), - (200, 100, "straight"), - ] - paramak.Shape(points=points) - paramak.Shape(points=points) - - def test_reuse_points_and_connections(self): - """Checks that points can be reused between shapes""" - points = [ - (100, 0, "straight"), - (200, 0, "straight"), - (250, 50, "straight"), - (200, 100, "straight"), - ] - test_shape = paramak.Shape(points=points) - - assert test_shape.points == [ - (100, 0, "straight"), - (200, 0, "straight"), - (250, 50, "straight"), - (200, 100, "straight"), - ] - - def test_reuse_points(self): - """Checks that points can be reused between shapes""" - points = [ - (100, 0), - (200, 0), - (250, 50), - (200, 100), - ] - test_shape = paramak.Shape(points=points, connection_type="straight") - - assert test_shape.points == [ - (100, 0), - (200, 0), - (250, 50), - (200, 100), - ] - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/tests_units/test_utils.py b/tests/tests_units/test_utils.py deleted file mode 100644 index f42ed3fd0..000000000 --- a/tests/tests_units/test_utils.py +++ /dev/null @@ -1,237 +0,0 @@ -import unittest - -import plotly.graph_objects as go -import pytest - -import paramak -from paramak.utils import ( - EdgeLengthSelector, - FaceAreaSelector, - extract_points_from_edges, - facet_wire, - find_center_point_of_circle, - plotly_trace, - find_radius_of_circle, - get_bounding_box, - get_largest_dimension, - get_largest_distance_from_origin, -) -import cadquery as cq - - -class TestUtilityFunctions(unittest.TestCase): - """ "tests the utility functions""" - - def test_bounding_box_with_single_shape_at_origin(self): - """checks the type and values of the bounding box returned""" - - test_sphere = cq.Workplane("XY").moveTo(0, 0).sphere(10) - - bounding_box = get_bounding_box(test_sphere) - - assert len(bounding_box) == 2 - assert len(bounding_box[0]) == 3 - assert len(bounding_box[1]) == 3 - assert bounding_box[0][0] == -10 - assert bounding_box[0][1] == -10 - assert bounding_box[0][2] == -10 - assert bounding_box[1][0] == 10 - assert bounding_box[1][1] == 10 - assert bounding_box[1][2] == 10 - - def test_bounding_box_with_single_shape(self): - """checks the type and values of the bounding box returned""" - - test_sphere = cq.Workplane("XY").moveTo(100, 50).sphere(10) - - bounding_box = get_bounding_box(test_sphere) - - assert len(bounding_box) == 2 - assert len(bounding_box[0]) == 3 - assert len(bounding_box[1]) == 3 - assert bounding_box[0][0] == 90 - assert bounding_box[0][1] == 40 - assert bounding_box[0][2] == -10 - assert bounding_box[1][0] == 110 - assert bounding_box[1][1] == 60 - assert bounding_box[1][2] == 10 - - def test_bounding_box_with_compound(self): - """checks the type and values of the bounding box returned""" - - test_sphere_1 = cq.Workplane("XY").moveTo(100, 50).sphere(10) - test_sphere_2 = cq.Workplane("XY").moveTo(-100, -50).sphere(10) - - both_shapes = cq.Compound.makeCompound([test_sphere_1.val(), test_sphere_2.val()]) - - bounding_box = get_bounding_box(both_shapes) - - assert len(bounding_box) == 2 - assert len(bounding_box[0]) == 3 - assert len(bounding_box[1]) == 3 - assert bounding_box[0][0] == -110 - assert bounding_box[0][1] == -60 - assert bounding_box[0][2] == -10 - assert bounding_box[1][0] == 110 - assert bounding_box[1][1] == 60 - assert bounding_box[1][2] == 10 - - def test_largest_dimension_with_single_solid_at_origin(self): - - test_sphere = cq.Workplane("XY").moveTo(0, 0).sphere(10) - - largest_dimension = get_largest_dimension(test_sphere) - - assert largest_dimension == 20 - - def test_largest_dimension__from_origin_with_single_solid_at_origin(self): - - test_sphere = cq.Workplane("XY").moveTo(0, 0).sphere(10) - - largest_dimension = get_largest_distance_from_origin(test_sphere) - - assert largest_dimension == 10 - - def test_largest_dimension_with_single_solid(self): - - test_sphere = cq.Workplane("XY").moveTo(100, 0).sphere(10) - - largest_dimension = get_largest_distance_from_origin(test_sphere) - - assert largest_dimension == 110 - - def test_largest_dimension_with_compound(self): - - test_sphere_1 = cq.Workplane("XY").moveTo(100, 50).sphere(10) - test_sphere_2 = cq.Workplane("XY").moveTo(-200, -50).sphere(10) - - both_shapes = cq.Compound.makeCompound([test_sphere_1.val(), test_sphere_2.val()]) - - largest_dimension = get_largest_distance_from_origin(both_shapes) - - assert largest_dimension == 210 - - def test_convert_circle_to_spline(self): - """Tests the conversion of 3 points on a circle into points on a spline - curve.""" - - new_points = paramak.utils.convert_circle_to_spline( - p_0=(200.0, 0.0), p_1=(250.0, 50.0), p_2=(200.0, 100.0), tolerance=0.2 - ) - - # these points can change from 200. to values like 200.00000000000009 - assert pytest.approx(new_points[0][0], abs=0.0000000000001) == 200 - assert pytest.approx(new_points[0][1], abs=0.0000000000001) == 0 - assert pytest.approx(new_points[-1][0], abs=0.0000000000001) == 200 - assert pytest.approx(new_points[-1][1], abs=0.0000000000001) == 100 - - new_points_more_details = paramak.utils.convert_circle_to_spline( - p_0=(200, 0), p_1=(250, 50), p_2=(200, 100), tolerance=0.1 - ) - - assert len(new_points_more_details) > len(new_points) - - def test_extract_points_from_edges(self): - """Extracts points from edges and checks the list returned is the - correct len and contains the correct types""" - - test_points = [(1, 1), (3, 1), (4, 2)] - test_shape = paramak.ExtrudeStraightShape(points=test_points, distance=6, workplane="YZ") - - edges = facet_wire(wire=test_shape.wire) - - points = extract_points_from_edges(edges=edges, view_plane="YZ") - - assert len(points) == 6 - - for point in points: - assert len(point) == 2 - assert isinstance(point[0], float) - assert isinstance(point[1], float) - - points_single_edge = extract_points_from_edges(edges=edges[0], view_plane="YZ") - - assert len(points) > len(points_single_edge) - for point in points_single_edge: - assert len(point) == 2 - assert isinstance(point[0], float) - assert isinstance(point[1], float) - - points_single_edge = extract_points_from_edges(edges=edges[0], view_plane="XYZ") - - assert len(points) > len(points_single_edge) - for point in points_single_edge: - assert len(point) == 3 - assert isinstance(point[0], float) - assert isinstance(point[1], float) - assert isinstance(point[2], float) - - def test_trace_creation(self): - """Creates a plotly trace and checks the type returned""" - trace = plotly_trace( - points=[(0, 20), (20, 0), (0, -20)], - mode="markers+lines", - color=(10, 10, 10, 0.5), - ) - - assert isinstance(trace, go.Scatter) - - def test_trace_creation_3d(self): - """Creates a 3d plotly trace and checks the type returned""" - trace = plotly_trace( - points=[(0, 20, 0), (20, 0, 10), (0, -20, -10)], - mode="markers+lines", - color=(10, 10, 10), - ) - - assert isinstance(trace, go.Scatter3d) - - def test_find_center_point_of_circle(self): - """passes three points on a circle to the function and checks that the - radius and center of the circle is calculated correctly""" - - point_a = (0, 20) - point_b = (20, 0) - point_3 = (0, -20) - - assert find_center_point_of_circle(point_a, point_b, point_3) == (0, 0) - - def test_find_radius_circle(self): - """passes and edge point and the center point of a circle in to the - function and checks the radius is calculated correctly""" - - edge_point = (0, 20) - center_point = (0, 0) - - assert find_radius_of_circle(center_point, edge_point) == 20 - - def test_EdgeLengthSelector_with_fillet_areas(self): - """tests the filleting of a RotateStraightShape results in an extra - surface area""" - - test_shape = paramak.RotateStraightShape(points=[(1, 1), (2, 1), (2, 2)]) - - assert len(test_shape.areas) == 3 - - test_shape.solid = test_shape.solid.edges(EdgeLengthSelector(6.28)).fillet(0.1) - - assert len(test_shape.areas) == 4 - - def test_FaceAreaSelector_with_fillet_areas(self): - """tests the filleting of a ExtrudeStraightShape""" - - test_shape = paramak.ExtrudeStraightShape(distance=5, points=[(1, 1), (2, 1), (2, 2)]) - - assert len(test_shape.areas) == 5 - - test_shape.solid = test_shape.solid.faces(FaceAreaSelector(0.5)).fillet(0.1) - - assert len(test_shape.areas) == 11 - - def test_find_center_point_of_circle_zero_det(self): - """Checks that None is given if det is zero""" - point_a = (0, 0) - point_b = (0, 0) - point_3 = (0, 0) - - assert find_center_point_of_circle(point_a, point_b, point_3) is None diff --git a/tests/tests_units/test_version.py b/tests/tests_units/test_version.py deleted file mode 100644 index 2cd39e7b5..000000000 --- a/tests/tests_units/test_version.py +++ /dev/null @@ -1,20 +0,0 @@ -import paramak - - -def test_version(): - """Check that __version__ exists and is correctly formatted""" - version = paramak.__version__ - # Ensure it is given as a string - assert isinstance(version, str) - # Ensure is has at least two parts -- major and minor version -- separated by '.' - # Ideally we would aim for major.minor.patch, but this has a tendency to break - # CI tests for unknown reasons. - - # develop is used as the default version name in the dockerfile - if version != "develop": - version_bits = version.split(".") - assert len(version_bits) >= 2, f"Version number is {version}" - # Ensure both of the first two parts is convertable to int - # (The third/fourth part, if it exists, may be a development version) - for bit in version_bits[:2]: - assert bit.isdigit(), f"Version number is {version}"