├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .lgtm.yml ├── .mailmap ├── .readthedocs.yaml ├── .zenodo.json ├── CITATION.md ├── LICENSE ├── README.md ├── codecov.yml ├── doc ├── Makefile ├── README.md ├── _sphinxext │ ├── md_include.py │ └── releases_hack.py ├── _static │ └── theme_overrides.css ├── _templates │ ├── autosummary │ │ └── module.rst │ └── layout.html ├── api.rst ├── bibliography.rst ├── books │ ├── Macdonald │ │ ├── Conformal Model.pdf │ │ ├── GAlgebraPrimer.pdf │ │ └── README.md │ ├── bookGA.pdf │ └── galgebra.pdf ├── changelog.rst ├── conf.py ├── galgebra.tex ├── galgebra_guide.rst ├── images │ ├── Dop.svg │ ├── Ltrans.svg │ ├── LtransInst.svg │ ├── basic_op.svg │ ├── basic_op.tex │ ├── dhestenes.jpg │ ├── galgebra.svg │ ├── grad.svg │ ├── grad.tex │ ├── grad_cmp.svg │ ├── grad_cmp.tex │ ├── n_vector_positive_spherical.svg │ ├── st4_M3.svg │ ├── st4_M3.tex │ ├── submanifold.svg │ ├── submanifold1.svg │ └── wkclifford.jpg ├── index.rst ├── make.bat ├── module-components.rst ├── old_installation.md ├── old_introduction.md ├── old_migration_guide.md ├── python │ ├── BACCAB.pdf │ ├── BACCAB.py │ ├── Dirac.pdf │ ├── Dirac.py │ ├── Dop.pdf │ ├── Dop.py │ ├── EMWaves.pdf │ ├── EMWaves.py │ ├── LinearTrans.pdf │ ├── LinearTrans.py │ ├── Ltrans.pdf │ ├── Ltrans.py │ ├── Ltrans.tex │ ├── LtransInst.pdf │ ├── LtransInst.py │ ├── ReciprocalBasis.pdf │ ├── ReciprocalBasis.py │ ├── SphericalCoordinates.pdf │ ├── SphericalCoordinates.py │ ├── TensorDef.py │ ├── diffops.pdf │ ├── submanifold.pdf │ ├── submanifold.py │ └── submanifold1.pdf ├── readthedocs-pip-requirements.txt ├── refs.bib ├── sympy-representation.rst ├── tutorials │ ├── algebra.nblink │ ├── cm3.nblink │ ├── g2.nblink │ ├── g3.nblink │ ├── g4.nblink │ ├── gprint.nblink │ ├── h3.nblink │ ├── lt.nblink │ ├── sp2.nblink │ ├── sp2g3.nblink │ ├── sp2sp3.nblink │ ├── sp3.nblink │ └── spacetime.nblink └── used_by.md ├── examples ├── LaTeX │ ├── 4Derr.pdf │ ├── 4Derr.py │ ├── Dop.pdf │ ├── Dop.py │ ├── FmtChk.pdf │ ├── FmtChk.py │ ├── christoffel_symbols.pdf │ ├── christoffel_symbols.py │ ├── colored_christoffel_symbols.pdf │ ├── colored_christoffel_symbols.py │ ├── curvi_linear_latex.cprof │ ├── curvi_linear_latex.pdf │ ├── curvi_linear_latex.py │ ├── dchk.pdf │ ├── dchk.py │ ├── diffeq_sys.pdf │ ├── diffeq_sys.py │ ├── dirac_derive.pdf │ ├── dirac_derive.py │ ├── em_waves_latex.pdf │ ├── em_waves_latex.py │ ├── groups.pdf │ ├── groups.py │ ├── latex_check.pdf │ ├── latex_check.py │ ├── lin_tran_check.pdf │ ├── lin_tran_check.py │ ├── linear_EM_waves.pdf │ ├── linear_EM_waves.py │ ├── manifold.pdf │ ├── manifold.py │ ├── matrix_latex.pdf │ ├── matrix_latex.py │ ├── new_bug_grad_exp.pdf │ ├── new_bug_grad_exp.py │ ├── physics_check_latex.pdf │ ├── physics_check_latex.py │ ├── print_check_latex.pdf │ ├── print_check_latex.py │ ├── products_latex.py │ ├── second_derivative.pdf │ ├── simple_check_latex.py │ ├── simple_test_latex.pdf │ └── slow.py ├── Macdonald │ ├── Algebras.py │ ├── README.md │ └── cm3.ipynb ├── Old Format │ ├── bad_example.py │ ├── eval_check.py │ ├── exp_check.py │ ├── latex_check.pdf │ ├── latex_check.py │ ├── matrix_latex.py │ ├── mv_setup_options.py │ ├── outdated │ │ ├── manifold_check.py │ │ └── manifold_check_latex.py │ ├── physics_check_latex.pdf │ ├── physics_check_latex.py │ ├── print_check_latex.pdf │ ├── print_check_latex.py │ ├── prob_not_solenoidal.py │ ├── products_latex.py │ ├── reflect_test.pdf │ ├── reflect_test.py │ ├── simple_check.py │ ├── simple_check_latex.py │ ├── simple_test_latex.pdf │ ├── spherical_latex.pdf │ ├── spherical_latex.py │ └── terminal_check.py ├── README.md ├── Terminal │ ├── 1d_grad.py │ ├── ConformalConsole.py │ ├── coefs_test.py │ ├── exp_check.py │ ├── lt_check.py │ ├── lt_test.py │ ├── mv_setup_options.py │ ├── prob_not_solenoidal.py │ ├── reciprocal.py │ ├── rotations.py │ └── terminal_check.py ├── ipython │ ├── LaTeX.ipynb │ ├── Old Format.ipynb │ ├── Smith Sphere.ipynb │ ├── Terminal.ipynb │ ├── colored_christoffel_symbols.ipynb │ ├── conftest.py │ ├── dop.ipynb │ ├── galgebra_ipython_helpers.py │ ├── gr_metrics.ipynb │ ├── gsym-printing.ipynb │ ├── inner_product.ipynb │ ├── issue-511.ipynb │ ├── issue-513.ipynb │ ├── issue-514.ipynb │ ├── issue-516.ipynb │ ├── issue-518.ipynb │ ├── lt.ipynb │ ├── printing-galgebra.ipynb │ ├── second_derivative.ipynb │ ├── simple_ga_test.ipynb │ ├── st4.ipynb │ ├── test_gsg_undual_etc.ipynb │ ├── tutorial_algebra.ipynb │ └── verify_doc_python.ipynb └── primer │ ├── cm3.ipynb │ ├── g2.ipynb │ ├── g3.ipynb │ ├── g4.ipynb │ ├── gprint.ipynb │ ├── h3.ipynb │ ├── primer.ipynb │ ├── sp2.ipynb │ ├── sp2g3.ipynb │ ├── sp2sp3.ipynb │ ├── sp3.ipynb │ └── spacetime.ipynb ├── galgebra ├── __init__.py ├── _backports │ ├── __init__.py │ └── typing.py ├── _utils │ ├── __init__.py │ ├── cached_property.py │ ├── kwarg_parser.py │ ├── parser.py │ └── printable.py ├── _version.py ├── atoms.py ├── deprecated.py ├── dop.py ├── ga.py ├── gprinter.py ├── lt.py ├── metric.py ├── mv.py ├── primer.py ├── printer.py └── utils.py ├── setup.cfg ├── setup.py ├── test ├── .nbval_sanitize.cfg ├── README.md ├── __init__.py ├── fixtures │ ├── test_gprinter.pdf │ └── test_lt_pdf.pdf ├── test_differential_ops.py ├── test_gprinter.py ├── test_lt.py ├── test_misc.py ├── test_mv.py ├── test_printer.py └── test_test.py └── test_requirements.txt /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Python CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: ['*'] 8 | pull_request: 9 | 10 | concurrency: 11 | group: test-${{ github.head_ref }} 12 | cancel-in-progress: true 13 | 14 | env: 15 | PYTHONUNBUFFERED: "1" 16 | FORCE_COLOR: "1" 17 | 18 | jobs: 19 | build: 20 | name: Python ${{ matrix.python-version }} ${{ matrix.extra-env }} 21 | if: >- 22 | !contains(github.event.head_commit.message, '[skip ci]') 23 | && !contains(github.event.head_commit.message, '[skip tests]') 24 | strategy: 25 | matrix: 26 | python-version: ["3.8", "3.9", "3.10", "3.11"] 27 | fail-fast: false 28 | runs-on: ubuntu-22.04 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v3 32 | - name: Set up Python ${{ matrix.python-version }} 33 | uses: actions/setup-python@v4 34 | with: 35 | python-version: ${{ matrix.python-version }} 36 | - name: Install dependencies 37 | run: | 38 | python -m pip install -r test_requirements.txt 39 | python -m pip install -e . 40 | python -m pip check 41 | - name: Lint 42 | run: | 43 | flake8 -v 44 | - uses: hidakatsuya/action-setup-diff-pdf@v1.3.0 45 | if: "matrix.python-version == '3.11'" 46 | with: 47 | diff-pdf-version: '0.5' 48 | - uses: actions/cache@v3 49 | name: Tectonic Cache 50 | if: "matrix.python-version == '3.11'" 51 | with: 52 | path: ~/.cache/Tectonic 53 | key: ${{ runner.os }}-tectonic-${{ hashFiles('**/*.tex') }} 54 | restore-keys: | 55 | ${{ runner.os }}-tectonic- 56 | - uses: wtfjoke/setup-tectonic@v2 57 | if: "matrix.python-version == '3.11'" 58 | with: 59 | github-token: ${{ secrets.GITHUB_TOKEN }} 60 | biber-version: "latest" 61 | - name: Set environment variables 62 | if: "matrix.python-version == '3.11'" 63 | run: | 64 | echo "TEST_GXPDF=1" >> "$GITHUB_ENV" 65 | - name: Test 66 | run: | 67 | PYTEST_ARGS=(); 68 | PYTEST_ARGS+=(-n 2 --dist loadscope); 69 | if [[ ! -z "$PYTEST_K_FILTER" ]]; then 70 | PYTEST_ARGS+=(-k "$PYTEST_K_FILTER"); 71 | fi; 72 | pytest \ 73 | -vv --durations=50 \ 74 | --cov=galgebra \ 75 | --nbval examples/ipython/ \ 76 | --nbval examples/primer/ \ 77 | test \ 78 | --nbval-current-env \ 79 | --nbval-sanitize-with test/.nbval_sanitize.cfg \ 80 | "${PYTEST_ARGS[@]}" 81 | - name: Upload coverage to Codecov 82 | if: "matrix.python-version == '3.11'" 83 | uses: codecov/codecov-action@v3 84 | with: 85 | token: ${{ secrets.CODECOV_TOKEN }} 86 | - uses: actions/upload-artifact@v4 87 | if: "matrix.python-version == '3.11' && failure()" 88 | with: 89 | name: PDF-diffs 90 | path: test/diff 91 | 92 | release: 93 | name: Create release and send to PyPI 94 | needs: build 95 | if: >- 96 | github.ref_type == 'tag' 97 | && startsWith(github.ref, 'refs/tags/v') 98 | && !contains(github.event.head_commit.message, '[skip ci]') 99 | && !contains(github.event.head_commit.message, '[no release]') 100 | runs-on: ubuntu-latest 101 | # https://github.com/pypa/gh-action-pypi-publish/tree/release/v1/?tab=readme-ov-file#trusted-publishing 102 | permissions: 103 | id-token: write 104 | environment: 105 | name: pypi 106 | url: https://pypi.org/p/galgebra 107 | steps: 108 | - name: Check out code 109 | uses: actions/checkout@v3 110 | - name: Set up Python 111 | uses: actions/setup-python@v4 112 | with: 113 | python-version: "3.11" 114 | - name: Install wheel 115 | run: | 116 | python -m pip install wheel packaging 117 | - name: Build a binary wheel 118 | run: | 119 | python setup.py sdist bdist_wheel 120 | - name: Publish package distributions to PyPI 121 | uses: pypa/gh-action-pypi-publish@release/v1 122 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.covercover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | .static_storage/ 57 | .media/ 58 | local_settings.py 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | env.bak/ 92 | venv.bak/ 93 | 94 | # Spyder project settings 95 | .spyderproject 96 | .spyproject 97 | 98 | # Rope project settings 99 | .ropeproject 100 | 101 | # VSCode project settings 102 | .vscode 103 | 104 | # mkdocs documentation 105 | /site 106 | 107 | # mypy 108 | .mypy_cache/ 109 | 110 | # py.test cache 111 | .pytest_cache 112 | 113 | # backup files from 2to3 114 | **/*.bak 115 | 116 | # Sphinx 117 | doc/_build 118 | doc/generated 119 | 120 | # Ignore LaTeX generated intermediate file 121 | # keeping only *.tex and *.pdf 122 | # for doc/ and examples/ 123 | doc/**/*.fdb_latexmk 124 | doc/**/*.aux 125 | doc/**/*.toc 126 | doc/**/*.synctex.gz 127 | doc/**/*.out 128 | doc/**/*.fls 129 | doc/**/*.bak.pdf 130 | examples/**/*.fdb_latexmk 131 | examples/**/*.aux 132 | examples/**/*.toc 133 | examples/**/*.synctex.gz 134 | examples/**/*.out 135 | examples/**/*.fls 136 | examples/**/*.bak.pdf 137 | # *.tex files are output of examples, so it's also ignored 138 | examples/**/*.tex 139 | 140 | # Mac 141 | .DS_Store 142 | 143 | test/generated 144 | test/diff 145 | examples/GSG/ 146 | .aider* 147 | -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | # ignore the example files, we don't need quality there, and they skew our 2 | # stats and drown out real issues 3 | path_classifiers: 4 | examples: 5 | - examples 6 | test: 7 | - test 8 | docs: 9 | - doc 10 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | # Prevent git from showing duplicate names with commands like "git shortlog" 2 | # See the manpage of git-shortlog for details. 3 | # The syntax is: 4 | # Name that should be used Bad name 5 | # 6 | # You can skip Bad name if it is the same as the one that should be used, and is unique. 7 | # 8 | # This file is up-to-date if the command git log --format="%aN <%aE>" | sort -u 9 | # gives no duplicates. 10 | 11 | Alan Bromborsky brombo 12 | Alan Bromborsky 13 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | sphinx: 3 | configuration: doc/conf.py 4 | build: 5 | os: "ubuntu-22.04" 6 | tools: 7 | python: "3.11" 8 | 9 | python: 10 | install: 11 | - requirements: doc/readthedocs-pip-requirements.txt 12 | - method: pip 13 | path: . 14 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": { 3 | "id": "BSD-3-Clause" 4 | }, 5 | "creators": [ 6 | { 7 | "name": "Alan Bromborsky" 8 | }, 9 | { 10 | "name": "Utensil Song", 11 | "orcid": "0000-0003-3994-4466" 12 | }, 13 | { 14 | "affiliation": "University of Cambridge", 15 | "name": "Eric Wieser", 16 | "orcid": "0000-0003-0412-4978" 17 | }, 18 | { 19 | "affiliation": "University of Cambridge", 20 | "name": "Hugo Hadfield", 21 | "orcid": "0000-0003-4318-050X" 22 | }, 23 | { 24 | "name": "{The Pygae Team}" 25 | } 26 | ], 27 | "keywords": [ 28 | "python", 29 | "clifford algebra", 30 | "geometric algebra", 31 | "computer algebra", 32 | "symbolic algebra", 33 | "symbolic computation", 34 | "geometry" 35 | ], 36 | "upload_type": "software" 37 | } 38 | -------------------------------------------------------------------------------- /CITATION.md: -------------------------------------------------------------------------------- 1 | Citing This Library 2 | ------------------- 3 | 4 | `galgebra` is published to zenodo. 5 | DOI [10.5281/zenodo.10902114](https://doi.org/10.5281/zenodo.10902114) refers to all versions of `galgebra`. 6 | 7 | If you want to cite all releases, use: 8 | ```BibTeX 9 | @software{galgebra, 10 | author = {Alan Bromborsky and 11 | Utensil Song and 12 | Eric Wieser and 13 | Hugo Hadfield and 14 | {The Pygae Team}}, 15 | title = {pygae/galgebra}, 16 | month = jun, 17 | year = 2020, 18 | publisher = {Zenodo}, 19 | doi = {10.5281/zenodo.3857096}, 20 | url = {https://doi.org/10.5281/zenodo.3857096} 21 | } 22 | ``` 23 | 24 | To obtain BibTex citation information for a _specific_ release (recommended): 25 | 26 | * Run `python -m pip show galgebra` to determine which version you are using (or print `galgebra.__version__` from python) 27 | * Click on the corresponding version from [this list of versions](https://zenodo.org/search?q=parent.id%3A3857096&f=allversions%3Atrue&l=list&p=1&s=10&sort=version) 28 | * Scroll down to the bottom of the page, and click the "BibTex" link in the "Export" sidebar 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2019, Alan Bromborsky and GAlgebra team 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of galgebra nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | # Keep the project coverage target to auto 6 | target: auto 7 | # Allow the project coverage to drop by 1% 8 | threshold: 1% 9 | patch: 10 | default: 11 | # Set the patch coverage target to 75% 12 | target: 75% 13 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # User-friendly check for notedown 16 | ifeq ($(shell which notedown >/dev/null 2>&1; echo $$?), 1) 17 | $(error The 'notedown' command was not found. If you don't have notedown installed, grab it from https://github.com/aaren/notedown or install it by 'pip install notedown') 18 | endif 19 | 20 | # Put it first so that "make" without argument is like "make help". 21 | help: 22 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 23 | 24 | .PHONY: help Makefile 25 | 26 | # Catch-all target: route all unknown targets to Sphinx using the new 27 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 28 | %: Makefile 29 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Documentation 3 | 4 | This is the directory containing files to generate the documentation for galgebra (except for `books/`, which contains books about `galgebra` or Geometric Algebra in general from different sources). 5 | 6 | For the generated documentation, please visit https://galgebra.readthedocs.io . 7 | 8 | The structure of the `doc` diretory is: 9 | 10 | ```bash 11 | │ # Sphinx Doc Source Files: 12 | │ # 13 | ├─ index.rst # The entry point of the Sphinx doc, it references both 14 | │ # galgebra_guide.ipynb and api.rst 15 | ├─ galgebra.tex # The original LaTeX source that generated books/galgebra.pdf 16 | ├─ galgebra_guide.rst # The convert vertion of the latex document. 17 | │ # This was converted to markdown manually, then to rST via nodedown and nbsphinx. 18 | ├─ api.rst # Use automodule to extract doc from galgebra Python source files 19 | │ 20 | │ # Configurations: 21 | │ # 22 | ├─ readthedocs-pip-requirements.txt # PIP requirements.txt for readthedocs 23 | ├─ conf.py # Configurations for Sphinx 24 | │ 25 | │ # Scripts: 26 | │ # 27 | ├─ Makefile # So `make html` can generate the doc 28 | ├─ make.bat # Do the same as above for Windows 29 | │ 30 | │ # Directories Used By Sphinx: 31 | │ # 32 | ├─ _static/ # Configured html_static_path for Sphinx, see conf.py 33 | ├─ _templates/ # Configured templates_path for Sphinx, see conf.py 34 | ├─ images/ # Images used in doc 35 | │ 36 | │ # Legacy Directories: 37 | │ # 38 | ├─ python/ # Some Python scripts referenced in the doc but not all of them works 39 | └─ books/ # Books about galgebra or Geometric Algebra from different sources 40 | ``` 41 | -------------------------------------------------------------------------------- /doc/_sphinxext/md_include.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os.path 3 | import time 4 | from docutils import io, nodes, statemachine, utils 5 | from docutils.utils.error_reporting import SafeString, ErrorString 6 | from docutils.parsers.rst import Directive 7 | from docutils.parsers.rst import directives, states 8 | 9 | 10 | from sphinx.directives.code import LiteralIncludeReader 11 | from recommonmark.parser import CommonMarkParser 12 | 13 | 14 | class MdInclude(Directive): 15 | 16 | """ Include a markdown file in an rst file. """ 17 | 18 | required_arguments = 1 19 | optional_arguments = 0 20 | final_argument_whitespace = True 21 | option_spec = {'start-line': int, 22 | 'end-line': int, 23 | 'start-after': directives.unchanged_required, 24 | 'end-before': directives.unchanged_required, 25 | 'encoding': directives.encoding,} 26 | 27 | standard_include_path = os.path.join(os.path.dirname(states.__file__), 28 | 'include') 29 | 30 | def run(self): 31 | """Include a file as part of the content of this reST file.""" 32 | 33 | # copied from docutils.parsers.rst.directives.misc.Include 34 | if not self.state.document.settings.file_insertion_enabled: 35 | raise self.warning('"%s" directive disabled.' % self.name) 36 | source = self.state_machine.input_lines.source( 37 | self.lineno - self.state_machine.input_offset - 1) 38 | source_dir = os.path.dirname(os.path.abspath(source)) 39 | path = directives.path(self.arguments[0]) 40 | if path.startswith('<') and path.endswith('>'): 41 | path = os.path.join(self.standard_include_path, path[1:-1]) 42 | path = os.path.normpath(os.path.join(source_dir, path)) 43 | path = utils.relative_path(None, path) 44 | path = nodes.reprunicode(path) 45 | encoding = self.options.get( 46 | 'encoding', self.state.document.settings.input_encoding) 47 | e_handler=self.state.document.settings.input_encoding_error_handler 48 | try: 49 | self.state.document.settings.record_dependencies.add(path) 50 | include_file = io.FileInput(source_path=path, 51 | encoding=encoding, 52 | error_handler=e_handler) 53 | except UnicodeEncodeError as error: 54 | raise self.severe(u'Problems with "%s" directive path:\n' 55 | 'Cannot encode input file path "%s" ' 56 | '(wrong locale?).' % 57 | (self.name, SafeString(path))) 58 | except IOError as error: 59 | raise self.severe(u'Problems with "%s" directive path:\n%s.' % 60 | (self.name, ErrorString(error))) 61 | startline = self.options.get('start-line', None) 62 | endline = self.options.get('end-line', None) 63 | try: 64 | if startline or (endline is not None): 65 | lines = include_file.readlines() 66 | rawtext = ''.join(lines[startline:endline]) 67 | else: 68 | rawtext = include_file.read() 69 | except UnicodeError as error: 70 | raise self.severe(u'Problem with "%s" directive:\n%s' % 71 | (self.name, ErrorString(error))) 72 | # start-after/end-before: no restrictions on newlines in match-text, 73 | # and no restrictions on matching inside lines vs. line boundaries 74 | after_text = self.options.get('start-after', None) 75 | if after_text: 76 | # skip content in rawtext before *and incl.* a matching text 77 | after_index = rawtext.find(after_text) 78 | if after_index < 0: 79 | raise self.severe('Problem with "start-after" option of "%s" ' 80 | 'directive:\nText not found.' % self.name) 81 | rawtext = rawtext[after_index + len(after_text):] 82 | before_text = self.options.get('end-before', None) 83 | if before_text: 84 | # skip content in rawtext after *and incl.* a matching text 85 | before_index = rawtext.find(before_text) 86 | if before_index < 0: 87 | raise self.severe('Problem with "end-before" option of "%s" ' 88 | 'directive:\nText not found.' % self.name) 89 | rawtext = rawtext[:before_index] 90 | 91 | # copied code ends 92 | parser = CommonMarkParser() 93 | md_document = utils.new_document(path, self.state.document.settings) 94 | parser.parse(rawtext, md_document) 95 | return md_document.children 96 | 97 | 98 | def setup(app): 99 | directives.register_directive('mdinclude', MdInclude) 100 | -------------------------------------------------------------------------------- /doc/_sphinxext/releases_hack.py: -------------------------------------------------------------------------------- 1 | """ 2 | Workaround for https://github.com/bitprophet/releases/issues/65 3 | 4 | This has to be in its own file, as for some reason classes in conf.py cannot 5 | be pickled. 6 | """ 7 | 8 | class release_uri: 9 | def __init__(self, releases_github_path): 10 | self._path = releases_github_path 11 | 12 | def __contains__(self, item): 13 | return "%s" in "https://github.com/%s/tree/%s" 14 | 15 | def __mod__(self, release): 16 | if release[0].isdigit(): 17 | release = "v" + release 18 | return 'https://github.com/%s/tree/%s' % (self._path, release) 19 | 20 | def format(self, /, number): 21 | return self.__mod__(number) 22 | -------------------------------------------------------------------------------- /doc/_static/theme_overrides.css: -------------------------------------------------------------------------------- 1 | /* https://rackerlabs.github.io/docs-rackspace/tools/rtd-tables.html */ 2 | /* override table width restrictions */ 3 | @media screen and (min-width: 767px) { 4 | 5 | .wy-table-responsive table td { 6 | /* !important prevents the common CSS stylesheets from overriding 7 | this as on RTD they are loaded after this stylesheet */ 8 | white-space: normal !important; 9 | } 10 | 11 | .wy-table-responsive { 12 | overflow: visible !important; 13 | } 14 | } -------------------------------------------------------------------------------- /doc/_templates/autosummary/module.rst: -------------------------------------------------------------------------------- 1 | {{ fullname }} 2 | {{ underline }} 3 | 4 | .. automodule:: {{fullname}} 5 | 6 | Members 7 | ======= -------------------------------------------------------------------------------- /doc/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | {% block sidebartitle %} 3 | 4 | {% if logo and theme_logo_only %} 5 | 6 | {% else %} 7 | {{ project }} 8 | {% endif %} 9 | 10 | {# this div is instead of the usual logo. The height is picked to avoid a jump 11 | when mathjax renders #} 12 |
13 | \[\color{white}{\huge\mathcal{G\!A}\hspace{0.01in}\mathbf{lgebra}}\] 14 |
15 | 16 |
17 | 18 | {% if theme_display_version %} 19 | {%- set nav_version = version %} 20 | {% if READTHEDOCS and current_version %} 21 | {%- set nav_version = current_version %} 22 | {% endif %} 23 | {% if nav_version %} 24 |
25 | {{ nav_version }} 26 |
27 | {% endif %} 28 | {% endif %} 29 | 30 | {% include "searchbox.html" %} 31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /doc/api.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: galgebra -------------------------------------------------------------------------------- /doc/bibliography.rst: -------------------------------------------------------------------------------- 1 | Bibliography 2 | ------------ 3 | 4 | .. bibliography:: refs.bib 5 | :all: 6 | -------------------------------------------------------------------------------- /doc/books/Macdonald/Conformal Model.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/books/Macdonald/Conformal Model.pdf -------------------------------------------------------------------------------- /doc/books/Macdonald/GAlgebraPrimer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/books/Macdonald/GAlgebraPrimer.pdf -------------------------------------------------------------------------------- /doc/books/Macdonald/README.md: -------------------------------------------------------------------------------- 1 | Bundled Supplementary Materials for LAGA and VAGC 2 | ======================================================= 3 | 4 | This directory constains bundled supplementary materials for [Linear and Geometric Algebra](http://www.faculty.luther.edu/~macdonal/laga/index.html) and [Vector and Geometric Calculus](http://www.faculty.luther.edu/~macdonal/vagc/index.html) by Alan Macdonald: 5 | 6 | GAlgebraPrimer.pdf (Last update: 1/24/18) 7 | -------------------------------------------- 8 | 9 | From http://www.faculty.luther.edu/~macdonal/laga/index.html: 10 | 11 | > [GAlgebraPrimer.pdf](http://www.faculty.luther.edu/~macdonal/laga/GAlgebraPrimer.pdf) contains instructions for installing and using GAlgebra. The primer also downloads with GAlgebra. 12 | 13 | 14 | Conformal Model.pdf (Last update: 11/6/18) 15 | -------------------------------------------- 16 | 17 | From http://www.faculty.luther.edu/~macdonal/laga/index.html: 18 | 19 | > As of the fourth printing (of _Linear and Geometric Algebra_) there is a new Chapter 10 on the magical conformal model. The latest version of the chapter is also available [here](http://www.faculty.luther.edu/~macdonal/laga/Conformal%20Model.pdf). 20 | 21 | 22 | -------------------------------------------------------------------------------- /doc/books/bookGA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/books/bookGA.pdf -------------------------------------------------------------------------------- /doc/books/galgebra.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/books/galgebra.pdf -------------------------------------------------------------------------------- /doc/images/basic_op.tex: -------------------------------------------------------------------------------- 1 | \begin{split}\begin{aligned} 2 | A+B &= \texttt{A+B} \\ 3 | A-B &= \texttt{A-B} \\ 4 | AB &= \texttt{A*B} \\ 5 | A \wedge B &= \texttt{A^B} \\ 6 | A \cdot B &= \texttt{A|B} \\ 7 | A \rfloor B &= \texttt{AB} \\ 9 | A/B &= \texttt{A/B} \\ 10 | \end{aligned}\end{split} -------------------------------------------------------------------------------- /doc/images/dhestenes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/images/dhestenes.jpg -------------------------------------------------------------------------------- /doc/images/grad.tex: -------------------------------------------------------------------------------- 1 | \begin{aligned} 2 | \nabla F &= \texttt{grad*F} \\ 3 | F \bar{\nabla} &= \texttt{F*rgrad} \\ 4 | \nabla {\wedge}F &= \texttt{grad^F} \\ 5 | F {\wedge}\bar{\nabla} &= \texttt{F^rgrad} \\ 6 | \nabla \cdot F &= \texttt{grad|F} \\ 7 | F \cdot \bar{\nabla} &= \texttt{F|rgrad} \\ 8 | \nabla \rfloor F &= \texttt{gradF} \\ 11 | F \lfloor \bar{\nabla} &= \texttt{F>rgrad} 12 | \end{aligned} -------------------------------------------------------------------------------- /doc/images/grad_cmp.tex: -------------------------------------------------------------------------------- 1 | \begin{aligned} 2 | F \nabla &= \texttt{F*grad} \\ 3 | \bar{\nabla} F &= \texttt{rgrad*F} \\ 4 | F {\wedge}\nabla &= \texttt{F^grad} \\ 5 | \bar{\nabla} {\wedge}F &= \texttt{rgrad^F} \\ 6 | F \cdot \nabla &= \texttt{F|grad} \\ 7 | \bar{\nabla}\cdot F &= \texttt{rgrad|F} \\ 8 | F \rfloor \nabla &= \texttt{Fgrad} \\ 11 | \bar{\nabla} \lfloor F &= \texttt{rgrad>F} 12 | \end{aligned} -------------------------------------------------------------------------------- /doc/images/st4_M3.tex: -------------------------------------------------------------------------------- 1 | \begin{aligned} \langle \mathbf{M} \rangle _3 =& M^{txy} \boldsymbol{e}_{t}\wedge \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} \\ & + M^{txz} \boldsymbol{e}_{t}\wedge \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} \\ & + M^{tyz} \boldsymbol{e}_{t}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ & + M^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{aligned} -------------------------------------------------------------------------------- /doc/images/wkclifford.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/images/wkclifford.jpg -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. mdinclude:: ../README.md 2 | 3 | .. these are all hidden, because they render more clearly in the sidebar. 4 | 5 | .. toctree:: 6 | :caption: A guide to GAlgebra 7 | :hidden: 8 | 9 | galgebra_guide 10 | sympy-representation 11 | module-components 12 | 13 | .. toctree:: 14 | :caption: Tutorials 15 | :maxdepth: 2 16 | :hidden: 17 | 18 | tutorials/algebra 19 | tutorials/lt 20 | tutorials/gprint 21 | 22 | .. toctree:: 23 | :caption: API 24 | :maxdepth: 3 25 | :hidden: 26 | 27 | api 28 | 29 | .. toctree:: 30 | :caption: Other information 31 | :maxdepth: 2 32 | :hidden: 33 | 34 | changelog 35 | bibliography 36 | 37 | Indices and tables 38 | ================== 39 | 40 | * :ref:`genindex` 41 | * :ref:`modindex` 42 | * :ref:`search` 43 | -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | notedown >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'notedown' command was not found. 19 | echo. 20 | echo.If you don't have notedown installed, grab it from 21 | echo.https://github.com/aaren/notedown or install it by 22 | echo. 23 | echo. pip install notedown 24 | exit /b 1 25 | ) 26 | 27 | %SPHINXBUILD% >NUL 2>NUL 28 | if errorlevel 9009 ( 29 | echo. 30 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 31 | echo.installed, then set the SPHINXBUILD environment variable to point 32 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 33 | echo.may add the Sphinx directory to PATH. 34 | echo. 35 | echo.If you don't have Sphinx installed, grab it from 36 | echo.http://sphinx-doc.org/ 37 | exit /b 1 38 | ) 39 | 40 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 41 | goto end 42 | 43 | :help 44 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 45 | 46 | :end 47 | popd 48 | -------------------------------------------------------------------------------- /doc/old_introduction.md: -------------------------------------------------------------------------------- 1 | | D. Hestenes | William Kindom Clifford | 2 | |:-:|:-:| 3 | |![image](images/dhestenes.jpg) |![image](images/wkclifford.jpg)| 4 | 5 | This document describes the implementation, installation and use of a geometric algebra module written in python that utilizes the *sympy* symbolic algebra library. The python module ga has been developed for coordinate free calculations using the operations (geometric, outer, and inner products etc.) of geometric algebra. The operations can be defined using a completely arbitrary metric defined by the inner products of a set of arbitrary vectors or the metric can be restricted to enforce orthogonality and signature constraints on the set of vectors. Additionally, a metric that is a function of a coordinate set can be defined so that a geometric algebra over a manifold can be implemented. Geometric algebras over submanifolds of the base manifold are also supported as well as linear multivector differential operators and linear transformations. In addition the module includes the geometric, outer (curl) and inner (div) derivatives. The module requires the *sympy* module and the numpy module for numerical linear algebra calculations. For LaTeX output a LaTeX distribution and pdf viewer must be installed. If the user is interested in using geometric algebra for strictly numerical purposes I would recommend using the *glucat* C++ templates which have a python wrapper for python users (). -------------------------------------------------------------------------------- /doc/old_migration_guide.md: -------------------------------------------------------------------------------- 1 | # Migration Guide (Old) 2 | 3 | > Note: The APIs have changed since the era of `sympy.galgebra` and `brombo/galgebra`, some properties and methods are deprecated, the supported versions of Python and SymPy have also changed, please check [Changelog](https://galgebra.readthedocs.io/en/latest/changelog.html) and further update your scripts accordingly besides the following. If you encounter any problems, feel free to [open an issue](https://github.com/pygae/galgebra/issues/new)! 4 | 5 | # Migrating from [sympy.galgebra](https://docs.sympy.org/0.7.6.1/modules/galgebra/) 6 | 7 | GAlgebra is no longer part of SymPy since 1.0.0, if you have an import like this in your source: 8 | 9 | ```python 10 | from sympy.galgebra.ga import * 11 | ``` 12 | 13 | Simply remove the `sympy.` prefix before `galgebra` then you are good to go: 14 | 15 | ```python 16 | from galgebra.ga import * 17 | ``` 18 | 19 | # Migrating from [brombo/galgebra](https://github.com/brombo/galgebra) 20 | 21 | The `setgapth.py` way to install is now deprecated by `pip install galgebra` and all modules in GAlgebra should be imported from `galgebra`, for example: 22 | 23 | ```python 24 | from galgebra.printer import Format, Eprint, latex, GaPrinter 25 | from galgebra.ga import Ga 26 | from galgebra.mv import Mv, Nga 27 | ``` -------------------------------------------------------------------------------- /doc/python/BACCAB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/BACCAB.pdf -------------------------------------------------------------------------------- /doc/python/BACCAB.py: -------------------------------------------------------------------------------- 1 | from galgebra.printer import Format, xpdf 2 | from galgebra.ga import Ga 3 | 4 | Format() 5 | g4d = Ga('a b c d') 6 | (a, b, c, d) = g4d.mv() 7 | 8 | print('g_{ij} =', g4d.g) 9 | print('\\bm{a|(b*c)} =', a | (b * c)) 10 | print('\\bm{a|(b^c)} =', a | (b ^ c)) 11 | print('\\bm{a|(b^c^d)} =', a | (b ^ c ^ d)) 12 | print('\\bm{a|(b^c)+c|(a^b)+b|(c^a)} =', 13 | (a | (b ^ c)) + (c | (a ^ b)) + (b | (c ^ a))) 14 | print('\\bm{a*(b^c)-b*(a^c)+c*(a^b)} =', 15 | a * (b ^ c) - b * (a ^ c) + c * (a ^ b)) 16 | print('\\bm{a*(b^c^d)-b*(a^c^d)+c*(a^b^d)-d*(a^b^c)} =', 17 | a * (b ^ c ^ d) - b * (a ^ c ^ d) + c * (a ^ b ^ d) - d * (a ^ b ^ c)) 18 | print('\\bm{(a^b)|(c^d)} =', (a ^ b) | (c ^ d)) 19 | print('\\bm{((a^b)|c)|d} =', ((a ^ b) | c) | d) 20 | print('\\bm{(a^b)\\times (c^d)} =', Ga.com(a ^ b, c ^ d)) 21 | xpdf(paper='letter', prog=True) 22 | -------------------------------------------------------------------------------- /doc/python/Dirac.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/Dirac.pdf -------------------------------------------------------------------------------- /doc/python/Dirac.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from sympy import symbols, sin, cos 3 | from galgebra.printer import Format, xpdf, Print_Function 4 | from galgebra.ga import Ga 5 | 6 | Format() 7 | coords = symbols('t x y z', real=True) 8 | (st4d, g0, g1, g2, g3) = Ga.build( 9 | 'gamma*t|x|y|z', g=[1, -1, -1, -1], coords=coords) 10 | I = st4d.i 11 | 12 | (m, e) = symbols('m e') 13 | 14 | psi = st4d.mv('psi', 'spinor', f=True) 15 | A = st4d.mv('A', 'vector', f=True) 16 | sig_z = g3 * g0 17 | 18 | print('\\text{4-Vector Potential\\;\\;}\\bm{A} =', A) 19 | print('\\text{8-component real spinor\\;\\;}\\bm{\\psi} =', psi) 20 | 21 | dirac_eq = (st4d.grad * psi) * I * sig_z - e * A * psi - m * psi * g0 22 | dirac_eq = dirac_eq.simplify() 23 | 24 | # FIXME terms of \psi^{ty} are not grouped together 25 | print(dirac_eq.Fmt(3, r'%\text{Dirac Equation\;\;}\nabla \bm{\psi}' + 26 | r' I \sigma_{z}-e\bm{A}\bm{\psi}-m\bm{\psi}\gamma_{t} = 0')) 27 | xpdf(paper='landscape', prog=True) 28 | -------------------------------------------------------------------------------- /doc/python/Dop.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/Dop.pdf -------------------------------------------------------------------------------- /doc/python/Dop.py: -------------------------------------------------------------------------------- 1 | from sympy import symbols, sin 2 | from galgebra.printer import Format, xpdf 3 | from galgebra.ga import Ga 4 | 5 | Format() 6 | coords = (x, y, z) = symbols('x y z', real=True) 7 | (o3d, ex, ey, ez) = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) 8 | X = x * ex + y * ey + z * ez 9 | I = o3d.i 10 | v = o3d.mv('v', 'vector') 11 | f = o3d.mv('f', 'scalar', f=True) 12 | A = o3d.mv('A', 'vector', f=True) 13 | dd = v | o3d.grad 14 | lap = o3d.grad * o3d.grad 15 | print(r'\bm{X} =', X) 16 | print(r'\bm{v} =', v) 17 | print(r'\bm{A} =', A) 18 | print(r'%\bm{v}\cdot\nabla =', dd) 19 | print(r'%\nabla^{2} =', lap) 20 | print(r'%\bm{v}\cdot\nabla f =', dd * f) 21 | print(r'%\nabla^{2} f =', lap * f) 22 | print(r'%\nabla^{2} \bm{A} =', lap * A) 23 | print(r'%\bar{\nabla}\cdot v =', o3d.rgrad | v) 24 | Xgrad = X | o3d.grad 25 | rgradX = o3d.rgrad | X 26 | print(r'%\bm{X}\cdot \nabla =', Xgrad) 27 | # FIXME This outputs incorrectly, the scalar part 3 is missing 28 | print(r'%\bar{\nabla}\cdot \bm{X} =', rgradX) 29 | # FIXME The following code complains: 30 | # ValueError: In Dop.Add complement flags have different values: False vs. True 31 | # com = Xgrad - rgradX 32 | # print(r'%\bm{X}\cdot \nabla - \bar{\nabla}\cdot \bm{X} =', com) 33 | sph_coords = (r, th, phi) = symbols('r theta phi', real=True) 34 | (sp3d, er, eth, ephi) = Ga.build('e', g=[1, r**2, r**2 * sin(th)**2], 35 | coords=sph_coords, norm=True) 36 | f = sp3d.mv('f', 'scalar', f=True) 37 | lap = sp3d.grad * sp3d.grad 38 | print(r'%\nabla^{2} = \nabla\cdot\nabla =', lap) 39 | print(r'%\lp\nabla^{2}\rp f =', lap * f) 40 | print(r'%\nabla\cdot\lp\nabla f\rp =', sp3d.grad | (sp3d.grad * f)) 41 | # FIXME crop didn't work, but pdf can be generated with TexLive 2017 installed 42 | xpdf(paper='landscape', crop=True) 43 | -------------------------------------------------------------------------------- /doc/python/EMWaves.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/EMWaves.pdf -------------------------------------------------------------------------------- /doc/python/EMWaves.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from sympy import symbols, exp, I, Matrix, solve, simplify 3 | from galgebra.printer import Format, xpdf, Print_Function 4 | from galgebra.ga import Ga 5 | from galgebra.metric import linear_expand 6 | 7 | Format() 8 | X = (t, x, y, z) = symbols('t x y z', real=True) 9 | (st4d, g0, g1, g2, g3) = Ga.build('gamma*t|x|y|z', g=[1, -1, -1, -1], coords=X) 10 | 11 | i = st4d.i 12 | 13 | B = st4d.mv('B', 'vector') 14 | E = st4d.mv('E', 'vector') 15 | B.set_coef(1, 0, 0) 16 | E.set_coef(1, 0, 0) 17 | B *= g0 18 | E *= g0 19 | F = E + i * B 20 | 21 | kx, ky, kz, w = symbols('k_x k_y k_z omega', real=True) 22 | kv = kx * g1 + ky * g2 + kz * g3 23 | xv = x * g1 + y * g2 + z * g3 24 | KX = ((w * g0 + kv) | (t * g0 + xv)).scalar() 25 | 26 | Ixyz = g1 * g2 * g3 27 | 28 | F = F * exp(I * KX) 29 | 30 | print(r'\text{Pseudo Scalar\;\;}I =', i) 31 | print(r'%I_{xyz} =', Ixyz) 32 | print(F.Fmt(3, '\\text{Electromagnetic Field Bi-Vector\\;\\;} F')) 33 | gradF = st4d.grad * F 34 | 35 | print('#Geom Derivative of Electomagnetic Field Bi-Vector') 36 | print(gradF.Fmt(3, 'grad*F = 0')) 37 | 38 | gradF = gradF / (I * exp(I * KX)) 39 | print(gradF.Fmt(3, r'%\lp\bm{\nabla}F\rp /\lp i e^{iK\cdot X}\rp = 0')) 40 | 41 | g = '1 # 0 0,# 1 0 0,0 0 1 0,0 0 0 -1' 42 | X = (xE, xB, xk, t) = symbols('x_E x_B x_k t', real=True) 43 | (EBkst, eE, eB, ek, et) = Ga.build('e_E e_B e_k t', g=g, coords=X) 44 | 45 | i = EBkst.i 46 | 47 | E, B, k, w = symbols('E B k omega', real=True) 48 | 49 | F = E * eE * et + i * B * eB * et 50 | kv = k * ek + w * et 51 | xv = xE * eE + xB * eB + xk * ek + t * et 52 | KX = (kv | xv).scalar() 53 | F = F * exp(I * KX) 54 | 55 | print(r'%\mbox{set } e_{E}\cdot e_{k} = e_{B}\cdot e_{k} = 0' + 56 | r'\mbox{ and } e_{E}\cdot e_{E} = e_{B}\cdot e_{B} = ' + 57 | r'e_{k}\cdot e_{k} = -e_{t}\cdot e_{t} = 1') 58 | 59 | print('g =', EBkst.g) 60 | 61 | print('K|X =', KX) 62 | print('F =', F) 63 | (EBkst.grad * F).Fmt(3, 'grad*F = 0') 64 | 65 | gradF_reduced = (EBkst.grad * F) / (I * exp(I * KX)) 66 | 67 | print(gradF_reduced.Fmt(3, r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0')) 68 | 69 | print(r'%\mbox{Previous equation requires that: }e_{E}\cdot e_{B} = 0' + 70 | r'\mbox{ if }B\ne 0\mbox{ and }k\ne 0') 71 | 72 | gradF_reduced = gradF_reduced.subs({EBkst.g[0, 1]: 0}) 73 | print(gradF_reduced.Fmt(3, r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0')) 74 | 75 | (coefs, bases) = linear_expand(gradF_reduced.obj) 76 | 77 | eq1 = coefs[0] 78 | eq2 = coefs[1] 79 | 80 | B1 = solve(eq1, B)[0] 81 | B2 = solve(eq2, B)[0] 82 | 83 | print(r'\mbox{eq1: }B =', B1) 84 | print(r'\mbox{eq2: }B =', B2) 85 | 86 | eq3 = B1 - B2 87 | 88 | print(r'\mbox{eq3 = eq1-eq2: }0 =', eq3) 89 | eq3 = simplify(eq3 / E) 90 | print(r'\mbox{eq3 = (eq1-eq2)/E: }0 =', eq3) 91 | print(r'#Solutions for $k$ and $B$ in terms of $\omega$ and $E$:') 92 | print('k =', Matrix(solve(eq3, k))) 93 | print('B =', Matrix([B1.subs(w, k), B1.subs(-w, k)])) 94 | xpdf(paper='landscape', prog=True) 95 | -------------------------------------------------------------------------------- /doc/python/LinearTrans.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/LinearTrans.pdf -------------------------------------------------------------------------------- /doc/python/LinearTrans.py: -------------------------------------------------------------------------------- 1 | from sympy import symbols, sin, cos 2 | from galgebra.ga import Ga 3 | from galgebra.printer import Format, xpdf 4 | 5 | Format() 6 | 7 | (u, v) = uv = symbols('u,v', real=True) 8 | (g2d, eu, ev) = Ga.build('e_u e_v', coords=uv) 9 | 10 | print('#$A$ is a general 2D linear transformation') 11 | 12 | A2d = g2d.lt('A') 13 | 14 | print('A =', A2d) 15 | print('\\f{\\det}{A} =', A2d.det()) 16 | print('\\f{\\Tr}{A} =', A2d.tr()) 17 | 18 | B2d = g2d.lt('B') 19 | 20 | print('B =', B2d) 21 | print('A + B =', A2d + B2d) 22 | print('AB =', A2d * B2d) 23 | print('A - B =', A2d - B2d) 24 | 25 | a = g2d.mv('a', 'vector') 26 | b = g2d.mv('b', 'vector') 27 | 28 | print(r'a|\f{\overline{A}}{b}-b|\f{\underline{A}}{a} =', 29 | ((a | A2d.adj()(b)) - (b | A2d(a))).simplify()) 30 | 31 | # FIXME All above prints incorrect result 32 | # (more complicated and not equivalent ) 33 | 34 | m4d = Ga('e_t e_x e_y e_z', g=[1, -1, -1, -1], 35 | coords=symbols('t,x,y,z', real=True)) 36 | 37 | T = m4d.lt('T') 38 | 39 | print('#$T$ is a linear transformation in Minkowski space') 40 | print(r'\underline{T} =', T) 41 | print(r'\overline{T} =', T.adj()) 42 | print(r'\f{\mbox{tr}}{\underline{T}} =', T.tr()) 43 | 44 | a = m4d.mv('a', 'vector') 45 | b = m4d.mv('b', 'vector') 46 | 47 | print(r'a|\f{\overline{T}}{b}-b|\f{\underline{T}}{a} =', 48 | ((a | T.adj()(b)) - (b | T(a))).simplify()) 49 | 50 | xpdf(paper='landscape', crop=True) 51 | -------------------------------------------------------------------------------- /doc/python/Ltrans.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/Ltrans.pdf -------------------------------------------------------------------------------- /doc/python/Ltrans.py: -------------------------------------------------------------------------------- 1 | from sympy import symbols, sin, cos, latex 2 | from galgebra.ga import Ga 3 | from galgebra.printer import Format, xpdf 4 | 5 | Format() 6 | (x, y, z) = xyz = symbols('x,y,z', real=True) 7 | (o3d, ex, ey, ez) = Ga.build('e_x e_y e_z', g=[1, 1, 1], coords=xyz) 8 | grad = o3d.grad 9 | (u, v) = uv = symbols('u,v', real=True) 10 | (g2d, eu, ev) = Ga.build('e_u e_v', coords=uv) 11 | grad_uv = g2d.grad 12 | A = o3d.lt('A') 13 | print('#3d orthogonal ($A,\\;B$ are linear transformations)') 14 | print('A =', A) 15 | print(r'\f{\operatorname{mat}}{A} =', latex(A.matrix())) 16 | print('\\f{\\det}{A} =', A.det()) 17 | print('\\overline{A} =', A.adj()) 18 | print('\\f{\\Tr}{A} =', A.tr()) 19 | print('\\f{A}{e_x^e_y} =', A(ex ^ ey)) 20 | print('\\f{A}{e_x}^\\f{A}{e_y} =', A(ex) ^ A(ey)) 21 | B = o3d.lt('B') 22 | print('A + B =', A + B) 23 | print('AB =', A * B) 24 | print('A - B =', A - B) 25 | 26 | # FIXME linear transformations fail to simplify 27 | # using dot products of bases 28 | 29 | print('#2d general ($A,\\;B$ are linear transformations)') 30 | A2d = g2d.lt('A') 31 | print('A =', A2d) 32 | print('\\f{\\det}{A} =', A2d.det()) 33 | # A2d.adj().Fmt(4,'\\overline{A}') 34 | print('\\f{\\Tr}{A} =', A2d.tr()) 35 | print('\\f{A}{e_u^e_v} =', A2d(eu ^ ev)) 36 | print('\\f{A}{e_u}^\\f{A}{e_v} =', A2d(eu) ^ A2d(ev)) 37 | B2d = g2d.lt('B') 38 | print('B =', B2d) 39 | print('A + B =', A2d + B2d) 40 | print('AB =', A2d * B2d) 41 | print('A - B =', A2d - B2d) 42 | a = g2d.mv('a', 'vector') 43 | b = g2d.mv('b', 'vector') 44 | print(r'a|\f{\overline{A}}{b}-b|\f{\underline{A}}{a} =', 45 | ((a | A2d.adj()(b)) - (b | A2d(a))).simplify()) 46 | 47 | print('#4d Minkowski spaqce (Space Time)') 48 | m4d = Ga('e_t e_x e_y e_z', g=[1, -1, -1, -1], 49 | coords=symbols('t,x,y,z', real=True)) 50 | T = m4d.lt('T') 51 | print('g =', m4d.g) 52 | # FIXME incorrect sign for T and T.adj() 53 | print(r'\underline{T} =', T) 54 | print(r'\overline{T} =', T.adj()) 55 | # m4d.mv(T.det()).Fmt(4,r'\f{\det}{\underline{T}}') 56 | print(r'\f{\mbox{tr}}{\underline{T}} =', T.tr()) 57 | a = m4d.mv('a', 'vector') 58 | b = m4d.mv('b', 'vector') 59 | print(r'a|\f{\overline{T}}{b}-b|\f{\underline{T}}{a} =', 60 | ((a | T.adj()(b)) - (b | T(a))).simplify()) 61 | xpdf(paper=(10, 12), debug=True) 62 | -------------------------------------------------------------------------------- /doc/python/LtransInst.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/LtransInst.pdf -------------------------------------------------------------------------------- /doc/python/LtransInst.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | from __future__ import print_function 3 | from sympy import symbols, sin, cos, latex, Matrix 4 | from galgebra.ga import Ga 5 | from galgebra.printer import Format, xpdf 6 | 7 | Format() 8 | (x, y, z) = xyz = symbols('x,y,z', real=True) 9 | (o3d, ex, ey, ez) = Ga.build('e_x e_y e_z', g=[1, 1, 1], coords=xyz) 10 | 11 | A = o3d.lt('A') 12 | print(r'\mbox{General Instantiation: }A =', A) 13 | th = symbols('theta', real=True) 14 | R = cos(th / 2) + (ex ^ ey) * sin(th / 2) 15 | B = o3d.lt(R) 16 | print(r'\mbox{Rotor: }R =', R) 17 | print(r'\mbox{Rotor Instantiation: }B =', B) 18 | dict1 = {ex: ey + ez, ez: ey + ez, ey: ex + ez} 19 | C = o3d.lt(dict1) 20 | print(r'\mbox{Dictionary} =', latex(dict1)) 21 | print(r'\mbox{Dictionary Instantiation: }C =', C) 22 | lst1 = [[1, 0, 1], [0, 1, 0], [1, 0, 1]] 23 | D = o3d.lt(lst1) 24 | print(r'\mbox{List} =', latex(lst1)) 25 | print(r'\mbox{List Instantiation: }D =', D) 26 | lst2 = [ey + ez, ex + ez, ex + ey] 27 | E = o3d.lt(lst2) 28 | print(r'\mbox{List} =', latex(lst2)) 29 | print(r'\mbox{List Instantiation: }E =', E) 30 | xpdf(paper=(10, 12), crop=True) 31 | -------------------------------------------------------------------------------- /doc/python/ReciprocalBasis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/ReciprocalBasis.pdf -------------------------------------------------------------------------------- /doc/python/ReciprocalBasis.py: -------------------------------------------------------------------------------- 1 | from sympy import expand, simplify 2 | from galgebra.printer import Format, xpdf 3 | from galgebra.ga import Ga 4 | 5 | g = '1 # #,' + \ 6 | '# 1 #,' + \ 7 | '# # 1' 8 | 9 | Format() 10 | 11 | ng3d = Ga('e1 e2 e3', g=g) 12 | (e1, e2, e3) = ng3d.mv() 13 | print('g_{ij} =', ng3d.g) 14 | E = e1 ^ e2 ^ e3 15 | Esq = (E * E).scalar() 16 | print('E =', E) 17 | print('%E^{2} =', Esq) 18 | Esq_inv = 1 / Esq 19 | E1 = (e2 ^ e3) * E 20 | E2 = (-1) * (e1 ^ e3) * E 21 | E3 = (e1 ^ e2) * E 22 | print('E1 = (e2^e3)*E =', E1) 23 | print('E2 =-(e1^e3)*E =', E2) 24 | print('E3 = (e1^e2)*E =', E3) 25 | w = (E1 | e2) 26 | w = w.expand() 27 | print('E1|e2 =', w) 28 | w = (E1 | e3) 29 | w = w.expand() 30 | print('E1|e3 =', w) 31 | w = (E2 | e1) 32 | w = w.expand() 33 | print('E2|e1 =', w) 34 | w = (E2 | e3) 35 | w = w.expand() 36 | print('E2|e3 =', w) 37 | w = (E3 | e1) 38 | w = w.expand() 39 | print('E3|e1 =', w) 40 | w = (E3 | e2) 41 | w = w.expand() 42 | print('E3|e2 =', w) 43 | w = (E1 | e1) 44 | w = (w.expand()).scalar() 45 | Esq = expand(Esq) 46 | print('%(E1\\cdot e1)/E^{2} =', simplify(w / Esq)) 47 | w = (E2 | e2) 48 | w = (w.expand()).scalar() 49 | print('%(E2\\cdot e2)/E^{2} =', simplify(w / Esq)) 50 | w = (E3 | e3) 51 | w = (w.expand()).scalar() 52 | print('%(E3\\cdot e3)/E^{2} =', simplify(w / Esq)) 53 | xpdf(paper='letter', prog=True) 54 | -------------------------------------------------------------------------------- /doc/python/SphericalCoordinates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/SphericalCoordinates.pdf -------------------------------------------------------------------------------- /doc/python/SphericalCoordinates.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from sympy import symbols, sin 3 | from galgebra.printer import Format, xpdf 4 | from galgebra.ga import Ga 5 | 6 | Format() 7 | X = (r, th, phi) = symbols('r theta phi') 8 | s3d = Ga( 9 | 'e_r e_theta e_phi', g=[ 10 | 1, r**2, r**2 * sin(th)**2], coords=X, norm=True) 11 | (er, eth, ephi) = s3d.mv() 12 | grad = s3d.grad 13 | 14 | f = s3d.mv('f', 'scalar', f=True) 15 | A = s3d.mv('A', 'vector', f=True) 16 | B = s3d.mv('B', 'bivector', f=True) 17 | 18 | print('f =', f) 19 | print('A =', A) 20 | print('B =', B) 21 | 22 | # FIXME xxxx/r printed as \frac{xxxx}{r} instead of \frac{1}{r} xxxx 23 | print('grad*f =', grad * f) 24 | print('grad|A =', grad | A) 25 | print('-I*(grad^A) =', (-s3d.i * (grad ^ A)).simplify()) 26 | print('grad^B =', grad ^ B) 27 | print(r'%\nabla\cdot\lp\nabla f\rp =', s3d.grad | (s3d.grad * f)) 28 | xpdf(paper='letter', prog=True) 29 | -------------------------------------------------------------------------------- /doc/python/TensorDef.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | from sympy import symbols, sin, cos 4 | from galgebra.printer import Format, xpdf, Print_Function 5 | from galgebra.ga import Ga 6 | from galgebra.lt import Mlt 7 | 8 | coords = symbols('t x y z', real=True) 9 | (st4d, g0, g1, g2, g3) = Ga.build('gamma*t|x|y|z', g=[1, -1, -1, -1], 10 | coords=coords) 11 | 12 | A = st4d.mv('T', 'bivector') 13 | 14 | 15 | def TA(a1, a2): 16 | return A | (a1 ^ a2) 17 | 18 | 19 | T = Mlt(TA, st4d) # Define multi-linear function 20 | -------------------------------------------------------------------------------- /doc/python/diffops.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/diffops.pdf -------------------------------------------------------------------------------- /doc/python/submanifold.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/submanifold.pdf -------------------------------------------------------------------------------- /doc/python/submanifold.py: -------------------------------------------------------------------------------- 1 | from sympy import symbols, sin, pi, latex 2 | from galgebra.ga import Ga 3 | from galgebra.printer import Format, xpdf 4 | 5 | Format() 6 | coords = (r, th, phi) = symbols('r,theta,phi', real=True) 7 | sp3d = Ga('e_r e_th e_ph', g=[1, r**2, r**2 * sin(th)**2], 8 | coords=coords, norm=True) 9 | 10 | sph_uv = (u, v) = symbols('u,v', real=True) 11 | sph_map = [1, u, v] # Coordinate map for sphere of r = 1 12 | sph2d = sp3d.sm(sph_map, sph_uv) 13 | 14 | print(r'(u,v)\rightarrow (r,\theta,\phi) = ', latex(sph_map)) 15 | # FIXME submanifold basis vectors are not normalized, g is incorrect 16 | print('g =', latex(sph2d.g)) 17 | F = sph2d.mv('F', 'vector', f=True) # scalar function 18 | f = sph2d.mv('f', 'scalar', f=True) # vector function 19 | print(r'\nabla f =', sph2d.grad * f) 20 | print('F =', F) 21 | print(r'\nabla F = ', sph2d.grad * F) 22 | 23 | cir_s = s = symbols('s', real=True) 24 | cir_map = [pi / 8, s] 25 | cir1d = sph2d.sm(cir_map, (cir_s,)) 26 | 27 | print('g =', latex(cir1d.g)) 28 | h = cir1d.mv('h', 'scalar', f=True) 29 | H = cir1d.mv('H', 'vector', f=True) 30 | print(r'(s)\rightarrow (u,v) = ', latex(cir_map)) 31 | print('H =', H) 32 | print(latex(H)) 33 | print(r'\nabla h =', cir1d.grad * h) 34 | print(r'\nabla H =', cir1d.grad * H) 35 | xpdf(filename='submanifold.tex', paper=(6, 5), crop=True) 36 | -------------------------------------------------------------------------------- /doc/python/submanifold1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/doc/python/submanifold1.pdf -------------------------------------------------------------------------------- /doc/readthedocs-pip-requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | ipython 3 | matplotlib 4 | scipy 5 | 6 | ## an unreleased commit that will eventually make the 3.1.0 release, with 7 | ## type annotations which work on cached_property 8 | #-e git+https://git@github.com/sphinx-doc/sphinx.git@5460ad6925199b57b27b7d059825d3560872edbb#egg=sphinx 9 | 10 | ipykernel 11 | nbsphinx 12 | numba 13 | sphinx-rtd-theme==2.0.0 14 | sphinx_mdinclude 15 | 16 | sphinx-markdown-tables 17 | notedown 18 | semantic-version 19 | releases 20 | sphinxcontrib-bibtex 21 | nbsphinx-link 22 | 23 | # the first release to support f-strings 24 | pygments 25 | 26 | # previous releases did not render our README badges correctly 27 | recommonmark 28 | -------------------------------------------------------------------------------- /doc/refs.bib: -------------------------------------------------------------------------------- 1 | @book{Doran, 2 | title = {Geometric {Algebra} for {Physicists}}, 3 | publisher = {Cambridge University Press}, 4 | author = {Doran, Chris and Lasenby, Anthony}, 5 | year = {2003}, 6 | url = {http://www.mrao.cam.ac.uk/~clifford} 7 | } 8 | 9 | @book{Hestenes, 10 | title = {Clifford algebra to geometric calculus: a unified language for mathematics and physics}, 11 | shorttitle = {Clifford algebra to geometric calculus}, 12 | publisher = {Kluwer Academic Publishers}, 13 | author = {Hestenes, David and Sobczyk, Garret}, 14 | year = {1984}, 15 | url = {http://geocalc.clas.asu.edu/html/CA_to_GC.html} 16 | } 17 | 18 | @book{HestenesMech, 19 | title = {New {Foundations} for {Classical} {Mechanics}}, 20 | publisher = {Kluwer Academic Publishers}, 21 | author = {Hestenes, David}, 22 | year = {1999}, 23 | url = {http://geocalc.clas.asu.edu/html/NFCM.html} 24 | } 25 | 26 | @book{Macdonald1, 27 | title = {Linear and {Geometric} {Algebra}}, 28 | publisher = {CreateSpace Independent Publishing Platform}, 29 | author = {{Alan Macdonald}}, 30 | year = {2010}, 31 | url = {http://www.faculty.luther.edu/~macdonal/laga} 32 | } 33 | 34 | @book{Macdonald2, 35 | title = {Vector and {Geometric} {Calculus}}, 36 | publisher = {CreateSpace Independent Publishing Platform}, 37 | author = {{Alan Macdonald}}, 38 | year = {2012}, 39 | url = {http://www.faculty.luther.edu/~macdonal/vagc/}, 40 | } 41 | 42 | @book{Dorst, 43 | title = {Geometric algebra for computer science: an object-oriented approach to geometry}, 44 | shorttitle = {Geometric algebra for computer science}, 45 | publisher = {Morgan Kaufmann}, 46 | author = {Dorst, Leo and Fontijne, Daniel and Mann, Stephen}, 47 | year = {2009}, 48 | note = {2nd printing}, 49 | url = {http://www.geometricalgebra.net/} 50 | } 51 | 52 | @book{Perwass, 53 | title = {Geometric {Algebra} with {Applications} in {Engineering}}, 54 | publisher = {Springer}, 55 | author = {Perwass, Christian}, 56 | year = {2008} 57 | } 58 | 59 | @book{Arthur, 60 | title = {Understanding {Geometric} {Algebra} for {Electromagnetic} {Theory}}, 61 | publisher = {Wiley-IEEE Press}, 62 | author = {{John W. Arthur}}, 63 | year = {2011} 64 | } 65 | -------------------------------------------------------------------------------- /doc/tutorials/algebra.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/ipython/tutorial_algebra.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/cm3.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/cm3.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/g2.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/g2.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/g3.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/g3.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/g4.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/g4.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/gprint.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/gprint.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/h3.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/h3.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/lt.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/ipython/lt.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/sp2.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/sp2.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/sp2g3.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/sp2g3.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/sp2sp3.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/sp2sp3.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/sp3.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/sp3.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/tutorials/spacetime.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../examples/primer/spacetime.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /doc/used_by.md: -------------------------------------------------------------------------------- 1 | # Used by 2 | 3 | Here is a list of projects that use GAlgebra, divided into two parts: 4 | 5 | 1. research: used to facilitate or verify research 6 | 2. functional: used as a dependency in their major functionality 7 | 3. explorational: used as an optional dependency in their examples, exercises, or tutorials 8 | 9 | They are roughly ordered by relevance, stars and last updated time. 10 | 11 | This data is manually mined from [forks](https://github.com/pygae/galgebra/forks) and [dependents](https://github.com/pygae/galgebra/network/dependents), as ["Used by" button is not shown](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/exploring-the-dependencies-of-a-repository#changing-the-used-by-package). All usages are manually reviewed to rule out false positives (e.g. the dependency maybe added, but is not actually used), some usages are manually added to our knowledge. 12 | 13 | ## Research 14 | 15 | (in recent years, non-exhaustive) 16 | 17 | - [Geometric Product of Two Oriented Points in Conformal Geometric Algebra (2024)](https://link.springer.com/article/10.1007/s00006-024-01363-6) 18 | - two anonymous expert reviewers, who either used the python symbolic geometric algebra implementation GAlgebra or the Clifford python library to independently verify the results of this paper 19 | - [Machine Learning Clifford invariants of ADE Coxeter elements (2024)](https://arxiv.org/abs/2310.00041) 20 | - uses GAlgebra for ADE invariant generation [code](https://github.com/DimaDroid/ML_Clifford_Invariants/blob/main/InvariantData/ADE8_InvariantGeneration.py) 21 | - [Clifford spinors and root system induction: H4 and the Grand Antiprism (2021)](https://arxiv.org/abs/2103.07817) 22 | - perform practical computations in group theory via versors in Clifford algebra framework 23 | - LaTeX output of GAlgebra is used in paper [code](https://github.com/ppd22/galgebra-in-action) 24 | 25 | ## Functional 26 | 27 | - Prof. Alan Macdonald's books: [Linear and Geometric Algebra](http://www.faculty.luther.edu/~macdonal/laga/index.html) and [Vector and Geometric Calculus](http://www.faculty.luther.edu/~macdonal/vagc/index.html) 28 | - GAlgebra is the books' companion library, see [GAlgebraPrimer](http://www.faculty.luther.edu/~macdonal/GAlgebraPrimer.pdf) 29 | - [micahscopes/alglbraic](https://github.com/micahscopes/alglbraic): A python library and CLI utility for generating libraries of algebraic GLSL functions, including Clifford algebras 30 | - [russellgoyder/sundial](https://github.com/russellgoyder/sundial): The sundial problem from a new angle 31 | - released as package `analemma` on PyPI 32 | - contains [a cheat sheet for GAlgebra](https://github.com/russellgoyder/geometric-algebra-cheat-sheet) 33 | - see also https://github.com/pygae/galgebra/issues/506 34 | - [jdekozak/dirac5d](https://github.com/jdekozak/dirac5d): Five dimensional Dirac equation over the reals 35 | - see also https://github.com/jdekozak/dirac5d/issues/4 36 | - [pygae/GAlgebra.jl](https://github.com/pygae/GAlgebra.jl): Julia interface to GAlgebra 37 | - contains test cases for [Eric Chisolm's Geometric Algebra](https://arxiv.org/abs/1205.5935) 38 | 39 | ## Explorational 40 | 41 | - Dr. Eric Wieser's PhD thesis *Formalizing Clifford algebras and related constructions in the Lean theorem prover* 42 | - in section 3.3. Symbolic, the approach of GAlgebra is demonstrated and discussed 43 | - [appliedgeometry/poissongeometry](https://github.com/appliedgeometry/poissongeometry): A Python module for (local) Poisson-Nijenhuis calculus on Poisson manifolds, with the following functions 44 | - used in notebook tutorials: https://github.com/appliedgeometry/poissongeometry/blob/master/docs/Tutorial_Ingles.ipynb 45 | - [meuns/galgebra: GA4CS examples, PGA, code-generation, and more](https://github.com/meuns/galgebra) 46 | - see also https://github.com/pygae/galgebra/pull/68 47 | - [hugohadfield/sym_scratch](https://github.com/hugohadfield/sym_scratch) 48 | - used in notebooks for CGA 49 | -------------------------------------------------------------------------------- /examples/LaTeX/4Derr.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/LaTeX/4Derr.pdf -------------------------------------------------------------------------------- /examples/LaTeX/4Derr.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import * 3 | from galgebra.printer import Format,xpdf,xdvi 4 | from galgebra.ga import Ga 5 | 6 | def main(): 7 | Format() 8 | snr=1 9 | g = '0 0 1 0 ,0 0 0 1 ,1 0 0 0 ,0 1 0 0' 10 | sk4coords = (e1,e2,e3,e4) = symbols('e1 e2 e3 e4') 11 | sk4 = Ga('e_1 e_2 e_3 e_4', g=g, coords=sk4coords) 12 | (e1,e2,e3,e4) = sk4.mv() 13 | print('g_{ii} =',sk4.g) 14 | 15 | v = symbols('v', real=True) 16 | x1=(e1+e3)/sqrt(2) 17 | x2=(e2+e4)/sqrt(2) 18 | print('x_1 '+yi[1]+' =',xi[0]>yi[0]) 37 | 38 | fs = o3d.mv('s','scalar',f=True) 39 | fv = o3d.mv('v','vector',f=True) 40 | fb = o3d.mv('b','bivector',f=True) 41 | 42 | print('#Multivector Functions:') 43 | 44 | print('s(X) =',fs) 45 | print('v(X) =',fv) 46 | print('b(X) =',fb) 47 | 48 | print('#Products:') 49 | 50 | fX = ((o3d.grad,'grad'),(fs,'s'),(fv,'v'),(fb,'b')) 51 | 52 | for xi in fX: 53 | print('') 54 | for yi in fX: 55 | if xi[1] == 'grad' and yi[1] == 'grad': 56 | pass 57 | else: 58 | print(xi[1]+' * '+yi[1]+' =',xi[0]*yi[0]) 59 | print(xi[1]+' ^ '+yi[1]+' =',xi[0]^yi[0]) 60 | if xi[1] != 's' and yi[1] != 's': 61 | print(xi[1]+' | '+yi[1]+' =',xi[0]|yi[0]) 62 | print(xi[1]+' < '+yi[1]+' =' ,xi[0] '+yi[1]+' =' ,xi[0]>yi[0]) 64 | 65 | 66 | (g2d,ex,ey) = Ga.build('e',coords=(x,y)) 67 | 68 | print(r'#General 2D Metric\newline') 69 | print('#Multivector Functions:') 70 | 71 | s = g2d.mv('s','scalar',f=True) 72 | v = g2d.mv('v','vector',f=True) 73 | b = g2d.mv('v','bivector',f=True) 74 | 75 | print('s(X) =',s) 76 | print('v(X) =',v) 77 | print('b(X) =',b) 78 | 79 | X = ((g2d.grad,'grad'),(s,'s'),(v,'v')) 80 | 81 | print('#Products:') 82 | 83 | for xi in X: 84 | print('') 85 | for yi in X: 86 | if xi[1] == 'grad' and yi[1] == 'grad': 87 | pass 88 | else: 89 | print(xi[1]+' * '+yi[1]+' =',xi[0]*yi[0]) 90 | print(xi[1]+' ^ '+yi[1]+' =',xi[0]^yi[0]) 91 | if xi[1] != 's' and yi[1] != 's': 92 | print(xi[1]+' | '+yi[1]+' =',xi[0]|yi[0]) 93 | else: 94 | print(xi[1]+' | '+yi[1]+' = Not Allowed') 95 | print(xi[1]+' < '+yi[1]+' =',xi[0] '+yi[1]+' =' ,xi[0]>yi[0]) 97 | 98 | # xpdf(paper='letter') 99 | xpdf(pdfprog=None, paper='letter') 100 | return 101 | 102 | if __name__ == "__main__": 103 | main() 104 | -------------------------------------------------------------------------------- /examples/LaTeX/second_derivative.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/LaTeX/second_derivative.pdf -------------------------------------------------------------------------------- /examples/LaTeX/simple_check_latex.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from galgebra.printer import xpdf,Print_Function,Format 3 | from galgebra.ga import Ga 4 | 5 | def basic_multivector_operations_3D(): 6 | (g3d,ex,ey,ez) = Ga.build('e*x|y|z') 7 | 8 | print('g_{ij} =',g3d.g) 9 | 10 | A = g3d.mv('A','mv') 11 | 12 | print(A.Fmt(1,'A')) 13 | print(A.Fmt(2,'A')) 14 | print(A.Fmt(3,'A')) 15 | 16 | print(A.even().Fmt(1,'%A_{+}')) 17 | print(A.odd().Fmt(1,'%A_{-}')) 18 | 19 | X = g3d.mv('X','vector') 20 | Y = g3d.mv('Y','vector') 21 | 22 | print(X.Fmt(1,'X')) 23 | print(Y.Fmt(1,'Y')) 24 | 25 | print((X*Y).Fmt(2,'X*Y')) 26 | print((X^Y).Fmt(2,'X^Y')) 27 | print((X|Y).Fmt(2,'X|Y')) 28 | return 29 | 30 | def basic_multivector_operations_2D(): 31 | (g2d,ex,ey) = Ga.build('e*x|y') 32 | 33 | print('g_{ij} =',g2d.g) 34 | 35 | X = g2d.mv('X','vector') 36 | A = g2d.mv('A','spinor') 37 | 38 | print(X.Fmt(1,'X')) 39 | print(A.Fmt(1,'A')) 40 | 41 | print((X|A).Fmt(2,'X|A')) 42 | print((XX).Fmt(2,'A>X')) 44 | return 45 | 46 | def main(): 47 | Format() 48 | 49 | basic_multivector_operations_3D() 50 | basic_multivector_operations_2D() 51 | 52 | # xpdf('simple_test_latex.tex') 53 | xpdf('simple_check_latex.tex', pdfprog=None) 54 | return 55 | 56 | if __name__ == "__main__": 57 | main() 58 | -------------------------------------------------------------------------------- /examples/LaTeX/simple_test_latex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/LaTeX/simple_test_latex.pdf -------------------------------------------------------------------------------- /examples/LaTeX/slow.py: -------------------------------------------------------------------------------- 1 | from sympy import * 2 | 3 | expr_srepr = "Add(Derivative(Function('B__uv')(Symbol('u', real=True), Symbol('v', real=True), Symbol('z', real=True)), Tuple(Symbol('z', real=True), Integer(1))), Mul(Integer(-1), Pow(Add(Mul(Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2)), Abs(Symbol('a', real=True))), Mul(Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)), Abs(Symbol('a', real=True)))), Integer(-1)), Function('B__uz')(Symbol('u', real=True), Symbol('v', real=True), Symbol('z', real=True)), sin(Mul(Integer(2), Symbol('v', real=True)))), Mul(Pow(Add(Mul(Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2)), Abs(Symbol('a', real=True))), Mul(Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)), Abs(Symbol('a', real=True)))), Integer(-1)), Function('B__vz')(Symbol('u', real=True), Symbol('v', real=True), Symbol('z', real=True)), sinh(Mul(Integer(2), Symbol('u', real=True)))), Mul(Integer(-1), Pow(Add(Mul(Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), cos(Mul(Integer(2), Symbol('v', real=True))), Abs(Symbol('a', real=True))), Mul(Integer(-1), Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), cosh(Mul(Integer(2), Symbol('u', real=True))), Abs(Symbol('a', real=True)))), Integer(-1)), Function('B__uz')(Symbol('u', real=True), Symbol('v', real=True), Symbol('z', real=True)), sin(Mul(Integer(2), Symbol('v', real=True)))), Mul(Pow(Add(Mul(Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), cos(Mul(Integer(2), Symbol('v', real=True))), Abs(Symbol('a', real=True))), Mul(Integer(-1), Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(1, 2)), cosh(Mul(Integer(2), Symbol('u', real=True))), Abs(Symbol('a', real=True)))), Integer(-1)), Function('B__vz')(Symbol('u', real=True), Symbol('v', real=True), Symbol('z', real=True)), sinh(Mul(Integer(2), Symbol('u', real=True)))), Mul(Integer(-1), Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(-1, 2)), Pow(Abs(Symbol('a', real=True)), Integer(-1)), Derivative(Function('B__uz')(Symbol('u', real=True), Symbol('v', real=True), Symbol('z', real=True)), Tuple(Symbol('v', real=True), Integer(1)))), Mul(Pow(Add(Mul(Pow(sin(Symbol('v', real=True)), Integer(2)), Pow(cosh(Symbol('u', real=True)), Integer(2))), Mul(Pow(cos(Symbol('v', real=True)), Integer(2)), Pow(sinh(Symbol('u', real=True)), Integer(2)))), Rational(-1, 2)), Pow(Abs(Symbol('a', real=True)), Integer(-1)), Derivative(Function('B__vz')(Symbol('u', real=True), Symbol('v', real=True), Symbol('z', real=True)), Tuple(Symbol('u', real=True), Integer(1)))))" 4 | 5 | expr = eval(expr_srepr) 6 | 7 | trigsimp(simplify(expr)) 8 | 9 | -------------------------------------------------------------------------------- /examples/Macdonald/Algebras.py: -------------------------------------------------------------------------------- 1 | # Provided by Alan Macdonald http://faculty.luther.edu macdonal@luther.edu 2 | 3 | from sympy import * 4 | from galgebra.ga import * 5 | 6 | # g2: Standard 2D Model 7 | g2coords = (x,y) = symbols('x y', real=True) 8 | g2 = Ga('e_x e_y', g=[1,1], coords=g2coords) 9 | (ex, ey) = g2.mv() 10 | 11 | # g3: Standard 3D Model 12 | g3coords = (x,y,z) = symbols('x y z', real=True) 13 | g3 = Ga('e_x e_y e_z', g=[1,1,1], coords=g3coords) 14 | (ex, ey, ez) = g3.mv() 15 | 16 | # g4: Standard 4D Model 17 | g4coords = (w,x,y,z) = symbols('w x y z', real=True) 18 | g4 = Ga('e_w e_x e_y e_z', g=[1,1,1,1], coords=g4coords) 19 | (ew, ex, ey, ez) = g4.mv() 20 | 21 | # h3: Homogeneous Coordinates 22 | h3coords = (x,y,z,e) = symbols('x y z e', real=True) 23 | h3 = Ga('e_x e_y e_z e_e', g=[1,1,1,1], coords=h3coords) 24 | (ex,ey,ez,ee) = h3.mv() 25 | 26 | # sp3: Spherical Coordinates I 27 | sp3coords = (r, ph, th) = symbols('r phi theta', real=True) 28 | sp3 = Ga('e_r e_phi e_theta', g=None, coords=sp3coords, \ 29 | X=[r, r*sin(ph)*cos(th), r*sin(ph)*sin(th), r*cos(ph)], norm=True) 30 | (er, eph, eth) = sp3.mv() 31 | # Mathematics naming convention: $\phi$ colatitude, $\theta$ longitude. 32 | # (r phi theta) is a right-handed system 33 | 34 | # sp3: Spherical Coordinates II 35 | sp3coords = (r, ph, th) = symbols('r phi theta', real=True, norm=True) 36 | sp3 = Ga('e_r e_phi e_theta', g=[1, r**2, r**2*sin(ph)**2], coords=sp3coords) 37 | (er, eph, eth) = sp3.mv() 38 | # Mathematics naming convention: $\phi$ colatitude, $\theta$ longitude. 39 | # (r phi theta) is a right-handed system 40 | 41 | # st4: Spacetime Algebra I 42 | st4coords = (t,x,y,z) = symbols('t x y z', real=True) 43 | st4 = Ga('e_t e_x e_y e_z', g=[1,-1,-1,-1], coords=st4coords) 44 | (et, ex, ey, ez) = st4.mv() 45 | 46 | # st4: Spacetime Algebra II 47 | st4coords = (t,x,y,z) = symbols('t x y z', real=True) 48 | st4 = Ga('e_t e_x e_y e_z', g=[-1,1,1,1], coords=st4coords) 49 | (et, ex, ey, ez) = st4.mv() 50 | 51 | # cf3: Conformal Model I (Doran/Lasenby p. 363) 52 | cf3coords = (n,x,y,z,nbar) = symbols('n x y z nbar', real=True) 53 | cf3g = '0 0 0 0 2, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 1 0, 2 0 0 0 0' 54 | cf3 = Ga('e_n e_x e_y e_z e_nbar', g = cf3g, coords = cf3coords) 55 | (en, ex, ey, ez, enbar) = cf3.mv() 56 | 57 | # sp2: Unit Sphere in $\RE^3$ I (submanifold of g3) 58 | sp2coords = (ph,th) = symbols('phi theta', real=True) 59 | sp2param = [sin(ph)*cos(th), sin(ph)*sin(th), cos(ph)] 60 | sp2 = g3.sm(sp2param, sp2coords, norm=True) 61 | (eph, eth) = sp2.mv() 62 | 63 | # sp2: Unit Sphere in $\RE^3$ II (submanifold of sp3) 64 | sp2coords = (p,t) = symbols('phi theta', real=True) # p for phi, t for theta 65 | sp2param = [1, p, t] # Parameterization of unit sphere 66 | sp2 = sp3.sm(sp2param, sp2coords, norm=True) 67 | (ep, et) = sp2.mv() 68 | -------------------------------------------------------------------------------- /examples/Macdonald/README.md: -------------------------------------------------------------------------------- 1 | Bundled Code for LAGA and VAGC 2 | ======================================================= 3 | 4 | This directory constains bundled code for [Linear and Geometric Algebra](http://www.faculty.luther.edu/~macdonal/laga/index.html) and [Vector and Geometric Calculus](http://www.faculty.luther.edu/~macdonal/vagc/index.html) by Alan Macdonald: 5 | 6 | Algebras.py 7 | -------------------------------------------- 8 | 9 | From [GAlgebraPrimer.pdf](http://www.faculty.luther.edu/~macdonal/laga/GAlgebraPrimer.pdf): 10 | 11 | > Algebras.py. This fi le is distributed with GAlgebra. It contains code to create many different geometric algebras, including g3 and all others used in this document, as well as others not covered here: homogeneous, spacetime, and conformal algebras. 12 | 13 | cm3.ipynb 14 | -------------------------------------------- 15 | 16 | From http://www.faculty.luther.edu/~macdonal/laga/index.html: 17 | 18 | > Notebooks. GAlgebra works in Jupyter (formerly IPython) and Jupyter Lab notebooks. Output is typeset in beautiful LaTeX. A Jupyter notebook to accompany the new Chapter 10 is available [here](http://www.faculty.luther.edu/~macdonal/laga/cm3.ipynb). (If the file opens in your browser, save it under the name cm3.ipynb".) 19 | 20 | Note 21 | -------------------------------------------- 22 | 23 | The code included in GAlgebra has some small adjustments to the original code by Alan Macdonald, for compatibility with Python 3 and installation from pip. 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/Old Format/bad_example.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import S 3 | from galgebra.printer import xdvi,Print_Function,Format 4 | from galgebra.deprecated import MV 5 | 6 | (ex,ey,ez) = MV.setup('e_x e_y e_z',metric='[1,1,1]') 7 | 8 | v = S(3)*ex+S(4)*ey 9 | 10 | print(v) 11 | print(v.norm()) 12 | print(v.norm2()) 13 | print(v/v.norm()) 14 | print(v/(v.norm()**2)) 15 | print(v*(v/v.norm2())) 16 | print(v.inv()) 17 | -------------------------------------------------------------------------------- /examples/Old Format/eval_check.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | #test_latest.py 3 | 4 | from sympy import symbols 5 | from galgebra.deprecated import MV,ReciprocalFrame 6 | from galgebra.printer import enhance_print,def_prec,GAeval,oprint 7 | 8 | def main(): 9 | enhance_print() 10 | 11 | coords = symbols('x y z') 12 | (ex,ey,ez,grad) = MV.setup('ex ey ez',metric='[1,1,1]',coords=coords) 13 | 14 | mfvar = (u,v) = symbols('u v') 15 | 16 | eu = ex+ey 17 | ev = ex-ey 18 | 19 | (eu_r,ev_r) = ReciprocalFrame([eu,ev]) 20 | 21 | oprint('Frame',(eu,ev),'Reciprocal Frame',(eu_r,ev_r)) 22 | 23 | print('eu.eu_r =',eu|eu_r) 24 | print('eu.ev_r =',eu|ev_r) 25 | print('ev.eu_r =',ev|eu_r) 26 | print('ev.ev_r =',ev|ev_r) 27 | 28 | eu = ex+ey+ez 29 | ev = ex-ey 30 | 31 | (eu_r,ev_r) = ReciprocalFrame([eu,ev]) 32 | 33 | oprint('Frame',(eu,ev),'Reciprocal Frame',(eu_r,ev_r)) 34 | 35 | print('eu.eu_r =',eu|eu_r) 36 | print('eu.ev_r =',eu|ev_r) 37 | print('ev.eu_r =',ev|eu_r) 38 | print('ev.ev_r =',ev|ev_r) 39 | 40 | print('eu =',eu) 41 | print('ev =',ev) 42 | 43 | def_prec(locals()) 44 | 45 | print(GAeval('eu^ev|ex',True)) 46 | print(GAeval('eu^ev|ex*eu',True)) 47 | return 48 | 49 | if __name__ == "__main__": 50 | main() 51 | -------------------------------------------------------------------------------- /examples/Old Format/exp_check.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | from sympy import symbols,sin,cos 5 | from galgebra.deprecated import MV 6 | from galgebra.printer import enhance_print 7 | 8 | def main(): 9 | enhance_print() 10 | (ex,ey,ez) = MV.setup('e*x|y|z',metric='[1,1,1]') 11 | 12 | u = MV('u','vector') 13 | v = MV('v','vector') 14 | w = MV('w','vector') 15 | print(u) 16 | print(v) 17 | 18 | uv = u^v 19 | print(uv) 20 | print(uv.is_blade()) 21 | 22 | exp_uv = uv.exp() 23 | exp_uv.Fmt(2,'exp(uv)') 24 | 25 | return 26 | 27 | if __name__ == "__main__": 28 | main() 29 | -------------------------------------------------------------------------------- /examples/Old Format/latex_check.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/Old Format/latex_check.pdf -------------------------------------------------------------------------------- /examples/Old Format/matrix_latex.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import symbols, Matrix 3 | from galgebra.printer import xpdf, Format 4 | 5 | def main(): 6 | Format() 7 | a = Matrix ( 2, 2, ( 1, 2, 3, 4 ) ) 8 | b = Matrix ( 2, 1, ( 5, 6 ) ) 9 | c = a * b 10 | print(a,b,'=',c) 11 | 12 | x, y = symbols ( 'x, y' ) 13 | 14 | d = Matrix ( 1, 2, ( x ** 3, y ** 3 )) 15 | e = Matrix ( 2, 2, ( x ** 2, 2 * x * y, 2 * x * y, y ** 2 ) ) 16 | f = d * e 17 | 18 | print('%',d,e,'=',f) 19 | 20 | # xpdf() 21 | xpdf(pdfprog=None) 22 | return 23 | 24 | if __name__ == "__main__": 25 | main() 26 | -------------------------------------------------------------------------------- /examples/Old Format/mv_setup_options.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import symbols 3 | from galgebra.deprecated import MV 4 | from galgebra.printer import enhance_print,Print_Function 5 | 6 | def MV_setup_options(): 7 | (e1,e2,e3) = MV.setup('e_1 e_2 e_3','[1,1,1]') 8 | v = MV('v', 'vector') 9 | print(v) 10 | 11 | (e1,e2,e3) = MV.setup('e*1|2|3','[1,1,1]') 12 | v = MV('v', 'vector') 13 | print(v) 14 | 15 | (e1,e2,e3) = MV.setup('e*x|y|z','[1,1,1]') 16 | v = MV('v', 'vector') 17 | print(v) 18 | 19 | coords = symbols('x y z') 20 | (e1,e2,e3,grad) = MV.setup('e','[1,1,1]',coords=coords) 21 | v = MV('v', 'vector') 22 | print(v) 23 | 24 | return 25 | 26 | def main(): 27 | enhance_print() 28 | MV_setup_options() 29 | return 30 | 31 | if __name__ == "__main__": 32 | main() 33 | -------------------------------------------------------------------------------- /examples/Old Format/outdated/manifold_check.py: -------------------------------------------------------------------------------- 1 | 2 | from sympy.ga.ga import MV,ReciprocalFrame,ga_print_on,ga_print_off 3 | from sympy.ga.ga_debug import oprint 4 | from sympy.ga.ga_print import enhance_print 5 | from sympy import symbols,log,simplify,diff,cos,sin 6 | from sympy.ga.manifold import Manifold 7 | 8 | def Test_Reciprocal_Frame(): 9 | coords = symbols('x y z') 10 | (ex,ey,ez,grad) = MV.setup('ex ey ez',metric='[1,1,1]',coords=coords) 11 | 12 | mfvar = (u,v) = symbols('u v') 13 | 14 | eu = ex+ey 15 | ev = ex-ey 16 | 17 | (eu_r,ev_r) = ReciprocalFrame([eu,ev]) 18 | 19 | oprint('Frame',(eu,ev),'Reciprocal Frame',(eu_r,ev_r)) 20 | 21 | print 'eu.eu_r =',eu|eu_r 22 | print 'eu.ev_r =',eu|ev_r 23 | print 'ev.eu_r =',ev|eu_r 24 | print 'ev.ev_r =',ev|ev_r 25 | 26 | eu = ex+ey+ez 27 | ev = ex-ey 28 | 29 | (eu_r,ev_r) = ReciprocalFrame([eu,ev]) 30 | 31 | oprint('Frame',(eu,ev),'Reciprocal Frame',(eu_r,ev_r)) 32 | 33 | print 'eu.eu_r =',eu|eu_r 34 | print 'eu.ev_r =',eu|ev_r 35 | print 'ev.eu_r =',ev|eu_r 36 | print 'ev.ev_r =',ev|ev_r 37 | return 38 | 39 | def Plot_Mobius_Strip_Manifold(): 40 | coords = symbols('x y z') 41 | (ex,ey,ez,grad) = MV.setup('ex ey ez',metric='[1,1,1]',coords=coords) 42 | mfvar = (u,v) = symbols('u v') 43 | X = (cos(u)+v*cos(u/2)*cos(u))*ex+(sin(u)+v*cos(u/2)*sin(u))*ey+v*sin(u/2)*ez 44 | MF = Manifold(X,mfvar,True,I=MV.I) 45 | MF.Plot2DSurface([0.0,6.28,48],[-0.3,0.3,12],surf=False,skip=[4,4],tan=0.15) 46 | return 47 | 48 | def Distorted_manifold_with_scalar_function(): 49 | coords = symbols('x y z') 50 | (ex,ey,ez,grad) = MV.setup('ex ey ez',metric='[1,1,1]',coords=coords) 51 | mfvar = (u,v) = symbols('u v') 52 | X = 2*u*ex+2*v*ey+(u**3+v**3/2)*ez 53 | MF = Manifold(X,mfvar,I=MV.I) 54 | 55 | (eu,ev) = MF.Basis() 56 | 57 | g = (v+1)*log(u) 58 | dg = MF.Grad(g) 59 | print 'g =',g 60 | print 'dg =',dg 61 | print 'dg(1,0) =',dg.subs({u:1,v:0}) 62 | G = u*eu+v*ev 63 | dG = MF.Grad(G) 64 | print 'G =',G 65 | print 'P(G) =',MF.Proj(G) 66 | print 'zcoef =',simplify(2*(u**2 + v**2)*(-4*u**2 - 4*v**2 - 1)) 67 | print 'dG =',dG 68 | print 'P(dG) =',MF.Proj(dG) 69 | PS = u*v*eu^ev 70 | print 'PS =',PS 71 | print 'dPS =',MF.Grad(PS) 72 | print 'P(dPS) =',MF.Proj(MF.Grad(PS)) 73 | return 74 | 75 | def Simple_manifold_with_scalar_function_derivative(): 76 | coords = (x,y,z) = symbols('x y z') 77 | basis = (e1, e2, e3, grad) = MV.setup('e_1 e_2 e_3',metric='[1,1,1]',coords=coords) 78 | # Define surface 79 | mfvar = (u,v) = symbols('u v') 80 | X = u*e1+v*e2+(u**2+v**2)*e3 81 | print X 82 | MF = Manifold(X,mfvar) 83 | 84 | # Define field on the surface. 85 | g = (v+1)*log(u) 86 | 87 | # Method 1: Using old Manifold routines. 88 | VectorDerivative = (MF.rbasis[0]/MF.E_sq)*diff(g,u) + (MF.rbasis[1]/MF.E_sq)*diff(g,v) 89 | print 'Vector derivative =', VectorDerivative.subs({u:1,v:0}) 90 | 91 | # Method 2: Using new Manifold routines. 92 | dg = MF.Grad(g) 93 | print 'Vector derivative =', dg.subs({u:1,v:0}) 94 | return 95 | 96 | def main(): 97 | ga_print_on() 98 | enhance_print() 99 | Test_Reciprocal_Frame() 100 | Distorted_manifold_with_scalar_function() 101 | Simple_manifold_with_scalar_function_derivative() 102 | #Plot_Mobius_Strip_Manifold() 103 | ga_print_off() 104 | return 105 | 106 | if __name__ == "__main__": 107 | main() 108 | -------------------------------------------------------------------------------- /examples/Old Format/physics_check_latex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/Old Format/physics_check_latex.pdf -------------------------------------------------------------------------------- /examples/Old Format/physics_check_latex.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import sys 4 | from sympy import symbols,sin,cos 5 | from galgebra.printer import xpdf,Print_Function,Format 6 | from galgebra.deprecated import MV 7 | 8 | def Maxwells_Equations_in_Geometric_Calculus(): 9 | Print_Function() 10 | X = symbols('t x y z') 11 | (g0,g1,g2,g3,grad) = MV.setup('gamma*t|x|y|z',metric='[1,-1,-1,-1]',coords=X) 12 | I = MV.I 13 | 14 | B = MV('B','vector',fct=True) 15 | E = MV('E','vector',fct=True) 16 | B.set_coef(1,0,0) 17 | E.set_coef(1,0,0) 18 | B *= g0 19 | E *= g0 20 | J = MV('J','vector',fct=True) 21 | F = E+I*B 22 | 23 | print(r'\text{Pseudo Scalar\;\;}I =',I) 24 | print('\\text{Magnetic Field Bi-Vector\\;\\;} B = \\bm{B\\gamma_{t}} =',B) 25 | print('\\text{Electric Field Bi-Vector\\;\\;} E = \\bm{E\\gamma_{t}} =',E) 26 | print('\\text{Electromagnetic Field Bi-Vector\\;\\;} F = E+IB =',F) 27 | print('%\\text{Four Current Density\\;\\;} J =',J) 28 | gradF = grad*F 29 | print('#Geometric Derivative of Electomagnetic Field Bi-Vector') 30 | gradF.Fmt(3,'grad*F') 31 | 32 | print('#Maxwell Equations') 33 | print('grad*F = J') 34 | print('#Div $E$ and Curl $H$ Equations') 35 | (gradF.grade(1)-J).Fmt(3,'%\\grade{\\nabla F}_{1} -J = 0') 36 | print('#Curl $E$ and Div $B$ equations') 37 | (gradF.grade(3)).Fmt(3,'%\\grade{\\nabla F}_{3} = 0') 38 | return 39 | 40 | def Dirac_Equation_in_Geometric_Calculus(): 41 | Print_Function() 42 | vars = symbols('t x y z') 43 | (g0,g1,g2,g3,grad) = MV.setup('gamma*t|x|y|z',metric='[1,-1,-1,-1]',coords=vars) 44 | I = MV.I 45 | 46 | (m,e) = symbols('m e') 47 | 48 | psi = MV('psi','spinor',fct=True) 49 | A = MV('A','vector',fct=True) 50 | sig_z = g3*g0 51 | 52 | print('\\text{4-Vector Potential\\;\\;}\\bm{A} =',A) 53 | print('\\text{8-component real spinor\\;\\;}\\bm{\\psi} =',psi) 54 | 55 | dirac_eq = (grad*psi)*I*sig_z-e*A*psi-m*psi*g0 56 | dirac_eq.simplify() 57 | 58 | dirac_eq.Fmt(3,r'%\text{Dirac Equation\;\;}\nabla \bm{\psi} I \sigma_{z}-e\bm{A}\bm{\psi}-m\bm{\psi}\gamma_{t} = 0') 59 | 60 | return 61 | 62 | def Lorentz_Tranformation_in_Geometric_Algebra(): 63 | Print_Function() 64 | (alpha,beta,gamma) = symbols('alpha beta gamma') 65 | (x,t,xp,tp) = symbols("x t x' t'") 66 | (g0,g1) = MV.setup('gamma*t|x',metric='[1,-1]') 67 | 68 | from sympy import sinh,cosh 69 | 70 | R = cosh(alpha/2)+sinh(alpha/2)*(g0^g1) 71 | X = t*g0+x*g1 72 | Xp = tp*g0+xp*g1 73 | print('R =',R) 74 | 75 | print(r"#%t\bm{\gamma_{t}}+x\bm{\gamma_{x}} = t'\bm{\gamma'_{t}}+x'\bm{\gamma'_{x}} = R\lp t'\bm{\gamma_{t}}+x'\bm{\gamma_{x}}\rp R^{\dagger}") 76 | 77 | Xpp = R*Xp*R.rev() 78 | Xpp = Xpp.collect() 79 | Xpp = Xpp.subs({2*sinh(alpha/2)*cosh(alpha/2):sinh(alpha),sinh(alpha/2)**2+cosh(alpha/2)**2:cosh(alpha)}) 80 | print(r"%t\bm{\gamma_{t}}+x\bm{\gamma_{x}} =",Xpp) 81 | Xpp = Xpp.subs({sinh(alpha):gamma*beta,cosh(alpha):gamma}) 82 | 83 | print(r'%\f{\sinh}{\alpha} = \gamma\beta') 84 | print(r'%\f{\cosh}{\alpha} = \gamma') 85 | 86 | print(r"%t\bm{\gamma_{t}}+x\bm{\gamma_{x}} =",Xpp.collect()) 87 | return 88 | 89 | def main(): 90 | Format() 91 | 92 | Maxwells_Equations_in_Geometric_Calculus() 93 | Dirac_Equation_in_Geometric_Calculus() 94 | Lorentz_Tranformation_in_Geometric_Algebra() 95 | 96 | # xpdf() 97 | xpdf(pdfprog=None) 98 | return 99 | 100 | if __name__ == "__main__": 101 | main() 102 | -------------------------------------------------------------------------------- /examples/Old Format/print_check_latex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/Old Format/print_check_latex.pdf -------------------------------------------------------------------------------- /examples/Old Format/prob_not_solenoidal.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from sympy import symbols,sin,cos,factor_terms,simplify 4 | from galgebra.printer import enhance_print 5 | from galgebra.deprecated import MV 6 | 7 | def main(): 8 | enhance_print() 9 | 10 | X = (x,y,z) = symbols('x y z') 11 | (ex,ey,ez,grad) = MV.setup('e_x e_y e_z',metric='[1,1,1]',coords=(x,y,z)) 12 | 13 | A = x*(ey^ez) + y*(ez^ex) + z*(ex^ey) 14 | print('A =', A) 15 | print('grad^A =',(grad^A).simplify()) 16 | print() 17 | 18 | f = MV('f','scalar',fct=True) 19 | f = (x**2 + y**2 + z**2)**(-1.5) 20 | print('f =', f) 21 | print('grad*f =',(grad*f).expand()) 22 | print() 23 | 24 | B = f*A 25 | print('B =', B) 26 | print() 27 | 28 | Curl_B = grad^B 29 | 30 | print('grad^B =', Curl_B.simplify()) 31 | 32 | def Symplify(A): 33 | return(factor_terms(simplify(A))) 34 | 35 | print(Curl_B.func(Symplify)) 36 | return 37 | 38 | if __name__ == "__main__": 39 | main() 40 | -------------------------------------------------------------------------------- /examples/Old Format/products_latex.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import symbols 3 | from galgebra.deprecated import MV 4 | from galgebra.printer import xdvi,Format 5 | 6 | def main(): 7 | #Format() 8 | 9 | coords = (x,y,z) = symbols('x y z') 10 | 11 | (ex,ey,ez,grad) = MV.setup('e*x|y|z','[1,1,1]',coords=coords) 12 | 13 | s = MV('s','scalar') 14 | v = MV('v','vector') 15 | b = MV('b','bivector') 16 | 17 | print(r'#3D Orthogonal Metric\newline') 18 | 19 | print('#Multvectors:') 20 | print('s =',s) 21 | print('v =',v) 22 | print('b =',b) 23 | 24 | print('#Products:') 25 | 26 | X = ((s,'s'),(v,'v'),(b,'b')) 27 | 28 | for xi in X: 29 | print('') 30 | for yi in X: 31 | print(xi[1]+'*'+yi[1]+' =',xi[0]*yi[0]) 32 | print(xi[1]+'^'+yi[1]+' =',xi[0]^yi[0]) 33 | if xi[1] != 's' and yi[1] != 's': 34 | print(xi[1]+'|'+yi[1]+' =',xi[0]|yi[0]) 35 | print(xi[1]+'<'+yi[1]+' =',xi[0]'+yi[1]+' =',xi[0]>yi[0]) 37 | 38 | fs = MV('s','scalar',fct=True) 39 | fv = MV('v','vector',fct=True) 40 | fb = MV('b','bivector',fct=True) 41 | 42 | print('#Multivector Functions:') 43 | 44 | print('s(X) =',fs) 45 | print('v(X) =',fv) 46 | print('b(X) =',fb) 47 | 48 | print('#Products:') 49 | 50 | fX = ((grad,'grad'),(fs,'s'),(fv,'v'),(fb,'b')) 51 | 52 | for xi in fX: 53 | print('') 54 | for yi in fX: 55 | if xi[1] == 'grad' and yi[1] == 'grad': 56 | pass 57 | else: 58 | print(xi[1]+'*'+yi[1]+' =',xi[0]*yi[0]) 59 | print(xi[1]+'^'+yi[1]+' =',xi[0]^yi[0]) 60 | if xi[1] != 's' and yi[1] != 's': 61 | print(xi[1]+'|'+yi[1]+' =',xi[0]|yi[0]) 62 | print(xi[1]+'<'+yi[1]+' =',xi[0]'+yi[1]+' =',xi[0]>yi[0]) 64 | 65 | 66 | (ex,ey,grad) = MV.setup('e',coords=(x,y)) 67 | 68 | print(r'#General 2D Metric\newline') 69 | print('#Multivector Functions:') 70 | 71 | s = MV('s','scalar',fct=True) 72 | v = MV('v','vector',fct=True) 73 | b = MV('v','bivector',fct=True) 74 | 75 | print('s(X) =',s) 76 | print('v(X) =',v) 77 | print('b(X) =',b) 78 | 79 | X = ((grad,'grad'),(s,'s'),(v,'v')) 80 | 81 | print('#Products:') 82 | 83 | for xi in X: 84 | print('') 85 | for yi in X: 86 | if xi[1] == 'grad' and yi[1] == 'grad': 87 | pass 88 | else: 89 | print(xi[1]+'*'+yi[1]+' =',xi[0]*yi[0]) 90 | print(xi[1]+'^'+yi[1]+' =',xi[0]^yi[0]) 91 | if xi[1] != 's' and yi[1] != 's': 92 | print(xi[1]+'|'+yi[1]+' =',xi[0]|yi[0]) 93 | print(xi[1]+'<'+yi[1]+' =',xi[0]'+yi[1]+' =',xi[0]>yi[0]) 95 | 96 | #xdvi(paper='letter') 97 | return 98 | 99 | if __name__ == "__main__": 100 | main() 101 | -------------------------------------------------------------------------------- /examples/Old Format/reflect_test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/Old Format/reflect_test.pdf -------------------------------------------------------------------------------- /examples/Old Format/reflect_test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import * 3 | from galgebra.ga import Ga 4 | from galgebra.deprecated import MV 5 | from galgebra.printer import Format, xpdf, Fmt 6 | Format() 7 | 8 | ew,ex,ey,ez = MV.setup('e_w e_x e_y e_z',metric=[1,1,1,1]) 9 | 10 | a = MV('a','vector') 11 | a.set_coef(1,0,0) 12 | b = ex+ey+ez 13 | c = MV('c','vector') 14 | print('a =',a) 15 | print('b =',b) 16 | print('c =',c) 17 | 18 | print(a.reflect_in_blade(ex^ey).Fmt(1,'a\\mbox{ reflect in }xy')) 19 | print(a.reflect_in_blade(ey^ez).Fmt(1,'a\\mbox{ reflect in }yz')) 20 | print(a.reflect_in_blade(ez^ex).Fmt(1,'a\\mbox{ reflect in }zx')) 21 | print(a.reflect_in_blade(ez^(ex+ey)).Fmt(1,'a\\mbox{ reflect in plane }(x=y)')) 22 | print(b.reflect_in_blade((ez-ey)^(ex-ey)).Fmt(1,'b\\mbox{ reflect in plane }(x+y+z=0)')) 23 | 24 | print(a.reflect_in_blade(ex).Fmt(1,'\\mbox{Reflect in }\\bm{e}_{x}')) 25 | print(a.reflect_in_blade(ey).Fmt(1,'\\mbox{Reflect in }\\bm{e}_{y}')) 26 | print(a.reflect_in_blade(ez).Fmt(1,'\\mbox{Reflect in }\\bm{e}_{z}')) 27 | 28 | print(c.reflect_in_blade(ex^ey).Fmt(1,'c\\mbox{ reflect in }xy')) 29 | print(c.reflect_in_blade(ex^ey^ez).Fmt(1,'c\\mbox{ reflect in }xyz')) 30 | print((ew^ex).reflect_in_blade(ey^ez).Fmt(1,'wx\\mbox{ reflect in }yz')) 31 | print((ew^ex).reflect_in_blade(ex^ey).Fmt(1,'wx\\mbox{ reflect in }xy')) 32 | 33 | # xpdf() 34 | xpdf(pdfprog=None) 35 | -------------------------------------------------------------------------------- /examples/Old Format/simple_check.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | from sympy import symbols,sin,cos,simplify 5 | from galgebra.deprecated import MV 6 | from galgebra.printer import enhance_print 7 | 8 | def main(): 9 | enhance_print() 10 | 11 | (ex,ey,ez) = MV.setup('e*x|y|z',metric='[1,1,1]') 12 | 13 | u = MV('u','vector') 14 | v = MV('v','vector') 15 | w = MV('w','vector') 16 | print(u) 17 | print(v) 18 | print(w) 19 | 20 | uv = u^v 21 | print(uv) 22 | print(uv.is_blade()) 23 | uvw = u^v^w 24 | print(uvw) 25 | print(uvw.is_blade()) 26 | 27 | print(simplify((uv*uv).scalar())) 28 | return 29 | 30 | if __name__ == "__main__": 31 | main() 32 | -------------------------------------------------------------------------------- /examples/Old Format/simple_check_latex.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from galgebra.printer import xpdf,Format 3 | from galgebra.deprecated import MV 4 | 5 | def basic_multivector_operations_3D(): 6 | (ex,ey,ez) = MV.setup('e*x|y|z') 7 | 8 | print('g_{ij} =',MV.metric) 9 | 10 | A = MV('A','mv') 11 | 12 | A.Fmt(1,'A') 13 | A.Fmt(2,'A') 14 | A.Fmt(3,'A') 15 | 16 | A.even().Fmt(1,'%A_{+}') 17 | A.odd().Fmt(1,'%A_{-}') 18 | 19 | X = MV('X','vector') 20 | Y = MV('Y','vector') 21 | 22 | X.Fmt(1,'X') 23 | Y.Fmt(1,'Y') 24 | 25 | (X*Y).Fmt(2,'X*Y') 26 | (X^Y).Fmt(2,'X^Y') 27 | (X|Y).Fmt(2,'X|Y') 28 | return 29 | 30 | def basic_multivector_operations_2D(): 31 | (ex,ey) = MV.setup('e*x|y') 32 | 33 | print('g_{ij} =',MV.metric) 34 | 35 | X = MV('X','vector') 36 | A = MV('A','spinor') 37 | 38 | X.Fmt(1,'X') 39 | A.Fmt(1,'A') 40 | 41 | (X|A).Fmt(2,'X|A') 42 | (XX).Fmt(2,'A>X') 44 | return 45 | 46 | def main(): 47 | Format() 48 | 49 | basic_multivector_operations_3D() 50 | basic_multivector_operations_2D() 51 | 52 | # xpdf() 53 | xpdf(pdfprog=None) 54 | return 55 | 56 | if __name__ == "__main__": 57 | main() 58 | -------------------------------------------------------------------------------- /examples/Old Format/simple_test_latex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/Old Format/simple_test_latex.pdf -------------------------------------------------------------------------------- /examples/Old Format/spherical_latex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/examples/Old Format/spherical_latex.pdf -------------------------------------------------------------------------------- /examples/Old Format/spherical_latex.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | from sympy import symbols,sin,cos 5 | from galgebra.deprecated import MV 6 | from galgebra.printer import xpdf,Print_Function,Format 7 | 8 | def derivatives_in_spherical_coordinates(): 9 | Print_Function() 10 | X = (r,th,phi) = symbols('r theta phi') 11 | curv = [[r*cos(phi)*sin(th),r*sin(phi)*sin(th),r*cos(th)],[1,r,r*sin(th)]] 12 | (er,eth,ephi,grad) = MV.setup('e_r e_theta e_phi',metric='[1,1,1]',coords=X,curv=curv) 13 | 14 | f = MV('f','scalar',fct=True) 15 | A = MV('A','vector',fct=True) 16 | B = MV('B','grade2',fct=True) 17 | 18 | print('f =',f) 19 | print('A =',A) 20 | print('B =',B) 21 | 22 | print('grad*f =',grad*f) 23 | print('grad|A =',grad|A) 24 | print('-I*(grad^A) =',-MV.I*(grad^A)) 25 | print('grad^B =',grad^B) 26 | return 27 | def main(): 28 | Format() 29 | derivatives_in_spherical_coordinates() 30 | # xpdf() 31 | xpdf(pdfprog=None) 32 | return 33 | 34 | if __name__ == "__main__": 35 | main() 36 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples for GAlgebra 2 | 3 | Note: These examples are verified as tests in CI, see [README.md for test](../test/README.md). Especially please read section _How to maintain the examples_. 4 | 5 | - `ipython`: 6 | - These examples demonstrate GAlgebra in [Jupyter Notebooks](https://nbviewer.jupyter.org/github/pygae/galgebra/tree/master/examples/) 7 | - The notebooks that are named after the following directories, serve the purpose of recording outputs of the examples in the respective directories 8 | - other notebooks are to demonstrate individual scenarios of interest 9 | - please see section _Test purposes of each Jupyter Notebook_ in [README.md for test](../test/README.md) 10 | - `Terminal`: 11 | - These examples demonstrate various functionalities of GAlgebra 12 | - output format: color ANSI console output 13 | - `LaTeX` 14 | - Same as the above 15 | - output format: complete and compileable LaTeX source files 16 | - `Old Format` 17 | - These examples calls deprecated interfaces of GAlgebra -------------------------------------------------------------------------------- /examples/Terminal/1d_grad.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import * 3 | 4 | s = symbols('s',real=True) 5 | 6 | x = s**2 7 | 8 | f = Function('f')(x) 9 | 10 | print(x) 11 | print(f) 12 | D_s_f = diff(f,s,evaluate=False) 13 | 14 | print(D_s_f) 15 | print(latex(D_s_f)) 16 | 17 | -------------------------------------------------------------------------------- /examples/Terminal/ConformalConsole.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from sympy import Symbol, symbols, sin, cos, Rational, expand, simplify, collect 4 | from sympy import Rational as Rat 5 | from galgebra.printer import Format, Eprint 6 | from galgebra.ga import Ga 7 | from math import sqrt 8 | 9 | global n,nbar,I 10 | 11 | def radius(T): 12 | ''' 13 | This retrieves the radius from a trivector representing a circle 14 | ''' 15 | a=(T*T).scalar() 16 | b=((T^n)*(T^n)).scalar() 17 | return (-1*a/b)**0.5 18 | 19 | def center(T): 20 | global n 21 | '''returns the center of a given circle trivector''' 22 | return T*n*T 23 | 24 | def split_bivector(B): 25 | global ebar 26 | '''Implements the algorithm described in Doran and Lasenby to recover null vectors wedging to B''' 27 | print('B =',B) 28 | print('B**2 =',B*B) 29 | NB = B.norm() 30 | print('NB =',NB) 31 | Bh = B/NB 32 | ap = ebar - ((ebar^Bh)*Bh) 33 | a1 = ap + (ap*Bh) 34 | a2 = ap - (ap*Bh) 35 | #print '#a1 = ',a1 36 | #print '#a2 = ',a2 37 | return [a1,a2] 38 | 39 | def norm(X): 40 | Y=sqrt((X*X).scalar()) 41 | return Y 42 | 43 | Eprint() 44 | 45 | g='1 0 0 0, \ 46 | 0 1 0 0, \ 47 | 0 0 0 2, \ 48 | 0 0 2 0' 49 | 50 | c2d = Ga('e_1 e_2 n \\bar{n}',g=g) 51 | (e1,e2,n,nbar) = c2d.mv() 52 | 53 | def F(x): 54 | global n,nbar 55 | Fx = ((x*x)*n+2*x-nbar) / 2 56 | return(Fx) 57 | 58 | e = (n+nbar)/2 59 | ebar = n - e 60 | I=e1*e2*e*ebar 61 | 62 | def intersect_lines(L1,L2): 63 | global I 64 | ''' 65 | Computes the intersection bivector of two conformal lines L1, L2 66 | ''' 67 | C = I*((I*L1)^(I*L2)) 68 | return C 69 | 70 | 71 | A=F(Rat(1,2)*e1) 72 | B=F(2*e1) 73 | C=F(Rat(4,5)*e1+Rat(3,5)*e2) 74 | D=F(Rat(4,5)*e1-Rat(3,5)*e2) 75 | 76 | print('A =',A) 77 | print('B =',B) 78 | print('C =',C) 79 | print('D =',D) 80 | 81 | T=A^B^C 82 | print('T =',T) 83 | U=F(e1)^(F(e2))^F(-1*e1) 84 | print('U =',U) 85 | inter=intersect_lines(U,T) 86 | print('inter =',inter) 87 | 88 | x,y = split_bivector(inter) 89 | 90 | bases = (e1,e2) 91 | print(x.proj(bases)) 92 | print(y.proj(bases)) 93 | 94 | 95 | print('One intersection point x = ',x) 96 | print('The other intersection point y = ',y) 97 | print('x**2 = ',x*x) 98 | print('y**2 = ',y*y) 99 | print('T^x = ',T^x) 100 | print('T^y = ',T^y) 101 | print('U^x = ',U^x) 102 | print('U^y = ',U^y) 103 | -------------------------------------------------------------------------------- /examples/Terminal/coefs_test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import symbols,S 3 | from galgebra.ga import Ga 4 | from galgebra.printer import Eprint, Print_Function 5 | 6 | def coefs_test(): 7 | Print_Function() 8 | 9 | (o3d,e1,e2,e3) = Ga.build('e_1 e_2 e_3',g=[1,1,1]) 10 | print(o3d.blades.flat) 11 | print(o3d.mv_blades.flat) 12 | v = o3d.mv('v', 'vector') 13 | print(v) 14 | print(v.blade_coefs([e3,e1])) 15 | A = o3d.mv('A', 'mv') 16 | print(A) 17 | print(A.blade_coefs([e1^e3,e3,e1^e2,e1^e2^e3])) 18 | print(A.blade_coefs()) 19 | return 20 | 21 | def main(): 22 | Eprint() 23 | coefs_test() 24 | return 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /examples/Terminal/exp_check.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | from sympy import symbols,sin,cos 5 | from galgebra.ga import Ga 6 | from galgebra.printer import Eprint 7 | 8 | def main(): 9 | Eprint() 10 | (o3d,ex,ey,ez) = Ga.build('e*x|y|z',g=[1,1,1]) 11 | 12 | u = o3d.mv('u','vector') 13 | v = o3d.mv('v','vector') 14 | w = o3d.mv('w','vector') 15 | print(u) 16 | print(v) 17 | 18 | uv = u^v 19 | print(uv) 20 | print(uv.is_blade()) 21 | 22 | exp_uv = uv.exp() 23 | print('exp(uv) =', exp_uv) 24 | 25 | return 26 | 27 | if __name__ == "__main__": 28 | main() 29 | -------------------------------------------------------------------------------- /examples/Terminal/lt_check.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sympy 3 | from galgebra import ga 4 | 5 | base=ga.Ga('e0 e1',g=[1,1],coords=sympy.symbols('x,y',real=True)) 6 | e0,e1 = base.mv() 7 | M=[[1,2],[3,4]] 8 | Mvec = [e0+2*e1,3*e0+4*e1] 9 | #print M[0][0],M[0][1] 10 | #print M[1][0],M[1][1] 11 | print(base.lt(Mvec)) 12 | print(base.lt(M)) 13 | print(sympy.Matrix(M)) 14 | -------------------------------------------------------------------------------- /examples/Terminal/lt_test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import sympy 4 | from galgebra import ga 5 | 6 | coords=sympy.symbols('x,y,z',real=True) 7 | base=ga.Ga('e0 e1 e2',g=[1,1,1],coords=coords) 8 | M=[[1,2,3],[4,5,6],[7,8,9]] 9 | A=base.lt(M) 10 | print(A) 11 | e0,e1,e2=base.basis 12 | print('A.lt_dict[e0]=', A.lt_dict[e0]) 13 | print('A.lt_dict[e1]=', A.lt_dict[e1]) 14 | print('A.lt_dict[e2]=', A.lt_dict[e2]) 15 | print(A.matrix()) 16 | v = base.mv('v','vector') 17 | print(v) 18 | print(A(v)) 19 | -------------------------------------------------------------------------------- /examples/Terminal/mv_setup_options.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sympy import symbols 3 | from galgebra.ga import Ga 4 | from galgebra.printer import Eprint, Print_Function 5 | 6 | def Mv_setup_options(): 7 | Print_Function() 8 | 9 | (o3d,e1,e2,e3) = Ga.build('e_1 e_2 e_3',g=[1,1,1]) 10 | v = o3d.mv('v', 'vector') 11 | print(v) 12 | 13 | (o3d,e1,e2,e3) = Ga.build('e*1|2|3',g=[1,1,1]) 14 | v = o3d.mv('v', 'vector') 15 | print(v) 16 | 17 | (o3d,e1,e2,e3) = Ga.build('e*x|y|z',g=[1,1,1]) 18 | v = o3d.mv('v', 'vector') 19 | print(v) 20 | 21 | coords = symbols('x y z',real=True) 22 | (o3d,e1,e2,e3) = Ga.build('e',g=[1,1,1],coords=coords) 23 | v = o3d.mv('v', 'vector') 24 | print(v) 25 | 26 | print(v.grade(2)) 27 | print(v.i_grade) 28 | 29 | return 30 | 31 | def main(): 32 | Eprint() 33 | Mv_setup_options() 34 | return 35 | 36 | if __name__ == "__main__": 37 | main() 38 | -------------------------------------------------------------------------------- /examples/Terminal/prob_not_solenoidal.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from sympy import symbols,sqrt 4 | from galgebra.printer import Eprint 5 | from galgebra.ga import Ga 6 | 7 | def main(): 8 | Eprint() 9 | 10 | X = (x,y,z) = symbols('x y z',real=True) 11 | (o3d,ex,ey,ez) = Ga.build('e_x e_y e_z',g=[1,1,1],coords=(x,y,z)) 12 | 13 | A = x*(ey^ez) + y*(ez^ex) + z*(ex^ey) 14 | print('A =', A) 15 | print('grad^A =',(o3d.grad^A).simplify()) 16 | print() 17 | 18 | f = o3d.mv(1/sqrt(x**2 + y**2 + z**2)) 19 | print('f =', f) 20 | print('grad*f =',(o3d.grad*f).simplify()) 21 | print() 22 | 23 | B = f*A 24 | print('B =', B) 25 | print() 26 | 27 | Curl_B = o3d.grad^B 28 | 29 | print('grad^B =', Curl_B.simplify()) 30 | 31 | return 32 | 33 | if __name__ == "__main__": 34 | main() 35 | -------------------------------------------------------------------------------- /examples/Terminal/reciprocal.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sympy 3 | from galgebra import ga 4 | 5 | coords = u,v = sympy.symbols('u,v',real=True) 6 | #x,y,z=sympy.symbols('x,y,z',Function=True) 7 | 8 | x = sympy.Function('x')(*coords) 9 | y = sympy.Function('y')(*coords) 10 | z = sympy.Function('z')(*coords) 11 | 12 | #surface=ga.Ga('e1 e2',coords=(u,v),X=[x(u,v),y(u,v),z(u,v)]) 13 | surface=ga.Ga('e1 e2',coords=(u,v),X=[x,y,z]) 14 | print(surface.g) 15 | eu,ev = surface.mv() 16 | eur,evr = surface.mvr() 17 | print((eu|eur).simplify()) 18 | print((eu|evr).simplify()) 19 | print((ev|eur).simplify()) 20 | print((ev|evr).simplify()) 21 | -------------------------------------------------------------------------------- /examples/Terminal/rotations.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | from sympy import symbols,sin,cos,sqrt 5 | from galgebra.ga import Ga 6 | from galgebra.printer import Eprint 7 | 8 | def main(): 9 | Eprint() 10 | (o3d,ex,ey,ez) = Ga.build('e*x|y|z',g=[1,1,1]) 11 | 12 | (r,th,phi,alpha,beta,gamma) = symbols('r theta phi alpha beta gamma',real=True) 13 | (x_a,y_a,z_a,x_b,y_b,z_b,ab_mag,th_ab) = symbols('x_a y_a z_a x_b y_b z_b ab_mag theta_ab',real=True) 14 | 15 | I = ex^ey^ez 16 | 17 | a = o3d.mv('a','vector') 18 | b = o3d.mv('b','vector') 19 | c = o3d.mv('c','vector') 20 | ab = a-b 21 | 22 | print('a =', a) 23 | print('b =', b) 24 | print('c =', c) 25 | print('ab =', ab) 26 | 27 | ab_norm = ab/ab_mag 28 | 29 | print('ab/|ab| =', ab_norm) 30 | 31 | R_ab = cos(th_ab/2) +I*ab_norm*cos(th_ab/2) 32 | R_ab_rev = R_ab.rev() 33 | print('R_ab =', R_ab) 34 | print('R_ab_rev =', R_ab_rev) 35 | 36 | e__ab_x = R_ab * ex * R_ab_rev 37 | e__ab_y = R_ab * ey * R_ab_rev 38 | e__ab_z = R_ab * ez * R_ab_rev 39 | 40 | print('e_ab_x =', e__ab_x) 41 | print('e_ab_y =', e__ab_y) 42 | print('e_ab_z =', e__ab_z) 43 | 44 | R_phi = cos(phi/2)-(ex^ey)*sin(phi/2) 45 | R_phi_rev = R_phi.rev() 46 | 47 | print(R_phi) 48 | print(R_phi_rev) 49 | 50 | e_phi = (R_phi * ey * R_phi.rev()) 51 | 52 | print(e_phi) 53 | 54 | R_th = cos(th/2)+I*e_phi*sin(th/2) 55 | R_th_rev = R_th.rev() 56 | print(R_th.trigsimp()) 57 | print(R_th_rev.trigsimp()) 58 | 59 | e_r = (R_th*R_phi*ex*R_phi_rev*R_th_rev).trigsimp() 60 | 61 | e_th = (R_th*R_phi*ez*R_phi_rev*R_th_rev).trigsimp() 62 | 63 | e_phi = e_phi.trigsimp() 64 | 65 | print('e_r =', e_r) 66 | print('e_th =', e_th) 67 | print('e_phi =', e_phi) 68 | 69 | return 70 | 71 | if __name__ == "__main__": 72 | main() 73 | -------------------------------------------------------------------------------- /examples/ipython/conftest.py: -------------------------------------------------------------------------------- 1 | # https://nbval.readthedocs.io/en/latest/#Skipping-certain-output-types 2 | def pytest_collectstart(collector): 3 | if collector.fspath and collector.fspath.ext == '.ipynb': 4 | collector.skip_compare += 'text/html', 'application/javascript', 'stderr', -------------------------------------------------------------------------------- /examples/ipython/galgebra_ipython_helpers.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | import os 4 | from IPython.display import display_pretty 5 | 6 | 7 | def check(name): 8 | run(name) 9 | 10 | with open(name + '.tex', 'r') as f: 11 | # can't use display.Latex here, it would result in CSS comparisons in the output. 12 | # using `display` forces this to be a separate output to any stdout from above. 13 | display_pretty(f.read(), raw=True) 14 | 15 | 16 | def run(name): 17 | # this makes Python < 3.9 behave like 3.9 18 | abs_name = os.path.abspath(name) 19 | # stdout and stderr do not seem to go the right place in jupyter 20 | p = subprocess.run( 21 | [sys.executable, '-Wdefault', abs_name + '.py'], 22 | stdout=subprocess.PIPE, stderr=subprocess.PIPE, 23 | universal_newlines=True) 24 | sys.stdout.write(p.stdout) 25 | sys.stdout.flush() 26 | # remove the absolute paths from deprecation warnings 27 | sys.stderr.write(p.stderr.replace(abs_name, name)) 28 | sys.stderr.flush() 29 | 30 | # this makes the error easier to read in nbval 31 | if p.returncode: 32 | raise RuntimeError("The script raised an exception:\n\n" + p.stderr) 33 | -------------------------------------------------------------------------------- /examples/ipython/issue-511.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "c037437a-5863-4af2-82fb-3f715a984ad0", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "data": { 11 | "text/plain": [ 12 | "(e_0, e_0)" 13 | ] 14 | }, 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "output_type": "execute_result" 18 | } 19 | ], 20 | "source": [ 21 | "from galgebra.ga import Ga\n", 22 | "import sympy as S\n", 23 | "\n", 24 | "ga = Ga('e', g=[1,1,1], coords=S.symbols(f\"0:{3}\", real=True), wedge=False)\n", 25 | "ex,ey,ez = ga.mv()\n", 26 | "ex**-1, ga.mv(1)/ex" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 2, 32 | "id": "ea2d702a-dd04-4f5c-8794-1efefc8e7ee9", 33 | "metadata": {}, 34 | "outputs": [ 35 | { 36 | "data": { 37 | "text/latex": [ 38 | "$\\displaystyle \\frac{1}{8} \\mathbf{e}_{0}$" 39 | ], 40 | "text/plain": [ 41 | "e_0/8" 42 | ] 43 | }, 44 | "execution_count": 2, 45 | "metadata": {}, 46 | "output_type": "execute_result" 47 | } 48 | ], 49 | "source": [ 50 | "(2*ex)**-3" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 3, 56 | "id": "09faf76e-f43c-4023-be91-3f2460de0456", 57 | "metadata": {}, 58 | "outputs": [ 59 | { 60 | "data": { 61 | "text/latex": [ 62 | "$\\displaystyle \\frac{1}{65536}$" 63 | ], 64 | "text/plain": [ 65 | "1/65536" 66 | ] 67 | }, 68 | "execution_count": 3, 69 | "metadata": {}, 70 | "output_type": "execute_result" 71 | } 72 | ], 73 | "source": [ 74 | "(2*ex)**-16" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 4, 80 | "id": "91e20a05-ba7d-48cd-8916-d7460fb99e87", 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "data": { 85 | "text/plain": [ 86 | "(2*e_0/29 + 3*e_1/29 + 4*e_2/29, 2*e_0/841 + 3*e_1/841 + 4*e_2/841)" 87 | ] 88 | }, 89 | "execution_count": 4, 90 | "metadata": {}, 91 | "output_type": "execute_result" 92 | } 93 | ], 94 | "source": [ 95 | "((2*ex + 3*ey + 4*ez).inv(), (2*ex + 3*ey + 4*ez)**-3)" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 5, 101 | "id": "bdf6ce81-ab58-4e3b-aa72-6cd320e6062d", 102 | "metadata": {}, 103 | "outputs": [ 104 | { 105 | "data": { 106 | "text/latex": [ 107 | "$\\displaystyle \\frac{1}{841}$" 108 | ], 109 | "text/plain": [ 110 | "1/841" 111 | ] 112 | }, 113 | "execution_count": 5, 114 | "metadata": {}, 115 | "output_type": "execute_result" 116 | } 117 | ], 118 | "source": [ 119 | "(2*ex + 3*ey + 4*ez).inv() * (2*ex + 3*ey + 4*ez)**-3" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 6, 125 | "id": "2a557448-ac80-4b1c-87a0-0d25d731953c", 126 | "metadata": {}, 127 | "outputs": [ 128 | { 129 | "data": { 130 | "text/latex": [ 131 | "$\\displaystyle 1$" 132 | ], 133 | "text/plain": [ 134 | "1" 135 | ] 136 | }, 137 | "execution_count": 6, 138 | "metadata": {}, 139 | "output_type": "execute_result" 140 | } 141 | ], 142 | "source": [ 143 | "((2*ex + 3*ey + 4*ez)**3) * (2*ex + 3*ey + 4*ez)**-3" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 7, 149 | "id": "fd88f171-7f74-4112-9123-e986d8d92d76", 150 | "metadata": {}, 151 | "outputs": [ 152 | { 153 | "data": { 154 | "text/latex": [ 155 | "$\\displaystyle 1$" 156 | ], 157 | "text/plain": [ 158 | "1" 159 | ] 160 | }, 161 | "execution_count": 7, 162 | "metadata": {}, 163 | "output_type": "execute_result" 164 | } 165 | ], 166 | "source": [ 167 | "(2*ex + 3*ey + 4*ez)**-3 * ((2*ex + 3*ey + 4*ez)**3)" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": null, 173 | "id": "47ca185d-a790-4ba9-9c45-265572e6675d", 174 | "metadata": {}, 175 | "outputs": [], 176 | "source": [] 177 | } 178 | ], 179 | "metadata": { 180 | "kernelspec": { 181 | "display_name": "Python 3 (ipykernel)", 182 | "language": "python", 183 | "name": "python3" 184 | }, 185 | "language_info": { 186 | "codemirror_mode": { 187 | "name": "ipython", 188 | "version": 3 189 | }, 190 | "file_extension": ".py", 191 | "mimetype": "text/x-python", 192 | "name": "python", 193 | "nbconvert_exporter": "python", 194 | "pygments_lexer": "ipython3", 195 | "version": "3.9.18" 196 | } 197 | }, 198 | "nbformat": 4, 199 | "nbformat_minor": 5 200 | } 201 | -------------------------------------------------------------------------------- /examples/ipython/issue-513.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "26c91d51-9f62-4c3e-9d02-2ca3a0977913", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "from galgebra.ga import Ga\n", 11 | "import sympy as S\n", 12 | "\n", 13 | "x,y,z = coords = S.symbols('x y z', real=True)\n", 14 | "ga = Ga('e', g=[1,1,1], coords=coords, wedge=False)\n", 15 | "ex,ey,ez = ga.mv()" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 2, 21 | "id": "5d541f6c-f9f8-4adb-a4b5-5ab27a9293dc", 22 | "metadata": {}, 23 | "outputs": [ 24 | { 25 | "data": { 26 | "text/latex": [ 27 | "$\\displaystyle \\mathbf{e}_{x} \\frac{\\partial}{\\partial x} + \\mathbf{e}_{y} \\frac{\\partial}{\\partial y} + \\mathbf{e}_{z} \\frac{\\partial}{\\partial z}$" 28 | ], 29 | "text/plain": [ 30 | "e_x*D{x} + e_y*D{y} + e_z*D{z}" 31 | ] 32 | }, 33 | "execution_count": 2, 34 | "metadata": {}, 35 | "output_type": "execute_result" 36 | } 37 | ], 38 | "source": [ 39 | "ga.grad" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 3, 45 | "id": "d07a0e79-b467-4cef-9ea6-3b49e925bf0e", 46 | "metadata": {}, 47 | "outputs": [ 48 | { 49 | "data": { 50 | "text/latex": [ 51 | "$\\displaystyle 1$" 52 | ], 53 | "text/plain": [ 54 | "1" 55 | ] 56 | }, 57 | "execution_count": 3, 58 | "metadata": {}, 59 | "output_type": "execute_result" 60 | } 61 | ], 62 | "source": [ 63 | "ga.grad * (x*ex)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 4, 69 | "id": "417d322c-30f5-4353-9f32-cc39cb7b2d8e", 70 | "metadata": {}, 71 | "outputs": [ 72 | { 73 | "data": { 74 | "text/latex": [ 75 | "$\\displaystyle \\mathbf{e}_{x}$" 76 | ], 77 | "text/plain": [ 78 | "e_x" 79 | ] 80 | }, 81 | "execution_count": 4, 82 | "metadata": {}, 83 | "output_type": "execute_result" 84 | } 85 | ], 86 | "source": [ 87 | "(x*ex).diff(x)" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 5, 93 | "id": "7d66fe00-5011-4946-ad4f-9ae6f38c315d", 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "x,y,z = coords = S.symbols('x y z', real=True)\n", 98 | "ga = Ga('e', g=[1,1,1], coords=coords, wedge=False)\n", 99 | "ex,ey,ez = ga.mv()" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 6, 105 | "id": "7bac45e6-985f-497d-b13e-b40f9150dfd5", 106 | "metadata": {}, 107 | "outputs": [ 108 | { 109 | "data": { 110 | "text/latex": [ 111 | "$\\displaystyle \\mathbf{e}_{x} \\frac{\\partial}{\\partial x} + \\mathbf{e}_{y} \\frac{\\partial}{\\partial y} + \\mathbf{e}_{z} \\frac{\\partial}{\\partial z}$" 112 | ], 113 | "text/plain": [ 114 | "e_x*D{x} + e_y*D{y} + e_z*D{z}" 115 | ] 116 | }, 117 | "execution_count": 6, 118 | "metadata": {}, 119 | "output_type": "execute_result" 120 | } 121 | ], 122 | "source": [ 123 | "ga.grad" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 7, 129 | "id": "2f8161af-c147-4fcf-adfa-53613b24210f", 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "data": { 134 | "text/latex": [ 135 | "$\\displaystyle 1$" 136 | ], 137 | "text/plain": [ 138 | "1" 139 | ] 140 | }, 141 | "execution_count": 7, 142 | "metadata": {}, 143 | "output_type": "execute_result" 144 | } 145 | ], 146 | "source": [ 147 | "ga.grad * (x*ex)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 8, 153 | "id": "231177c9-3422-4e33-9ace-d914502ba060", 154 | "metadata": {}, 155 | "outputs": [ 156 | { 157 | "data": { 158 | "text/latex": [ 159 | "$\\displaystyle \\mathbf{e}_{x}$" 160 | ], 161 | "text/plain": [ 162 | "e_x" 163 | ] 164 | }, 165 | "execution_count": 8, 166 | "metadata": {}, 167 | "output_type": "execute_result" 168 | } 169 | ], 170 | "source": [ 171 | "(x*ex).pdiff(x) # notice this is pdiff() not diff() this tim" 172 | ] 173 | } 174 | ], 175 | "metadata": { 176 | "kernelspec": { 177 | "display_name": "Python 3 (ipykernel)", 178 | "language": "python", 179 | "name": "python3" 180 | }, 181 | "language_info": { 182 | "codemirror_mode": { 183 | "name": "ipython", 184 | "version": 3 185 | }, 186 | "file_extension": ".py", 187 | "mimetype": "text/x-python", 188 | "name": "python", 189 | "nbconvert_exporter": "python", 190 | "pygments_lexer": "ipython3", 191 | "version": "3.9.18" 192 | } 193 | }, 194 | "nbformat": 4, 195 | "nbformat_minor": 5 196 | } 197 | -------------------------------------------------------------------------------- /examples/ipython/issue-514.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "c98f4750-3af1-4749-b2a6-8a17764511bd", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "data": { 11 | "text/plain": [ 12 | "(e_xyz, e_xyz, 'Iinv+')" 13 | ] 14 | }, 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "output_type": "execute_result" 18 | } 19 | ], 20 | "source": [ 21 | "from galgebra.ga import Ga\n", 22 | "import sympy as S\n", 23 | "\n", 24 | "Ga.dual_mode('Iinv+')\n", 25 | "\n", 26 | "ga = Ga('e', g=[1,1,1], coords=S.symbols('x y z', real=True), wedge=False)\n", 27 | "ex,ey,ez = ga.mv()\n", 28 | "I = ga.i\n", 29 | "(ex*I) * (ex*I).dual(), (ex*I).dual() * (ex*I), ga.dual_mode_value" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "id": "95c6f201-9f55-4e5d-9996-6a19b0f915ff", 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "data": { 40 | "text/plain": [ 41 | "True" 42 | ] 43 | }, 44 | "execution_count": 2, 45 | "metadata": {}, 46 | "output_type": "execute_result" 47 | } 48 | ], 49 | "source": [ 50 | "(ex*I).dual().undual() == (ex*I)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "id": "f8d2ce01-aae9-46ff-be2d-225138fa30cf", 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [] 60 | } 61 | ], 62 | "metadata": { 63 | "kernelspec": { 64 | "display_name": "Python 3 (ipykernel)", 65 | "language": "python", 66 | "name": "python3" 67 | }, 68 | "language_info": { 69 | "codemirror_mode": { 70 | "name": "ipython", 71 | "version": 3 72 | }, 73 | "file_extension": ".py", 74 | "mimetype": "text/x-python", 75 | "name": "python", 76 | "nbconvert_exporter": "python", 77 | "pygments_lexer": "ipython3", 78 | "version": "3.9.18" 79 | } 80 | }, 81 | "nbformat": 4, 82 | "nbformat_minor": 5 83 | } 84 | -------------------------------------------------------------------------------- /examples/ipython/issue-516.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "ee7c8882-7356-441a-920e-3603d081002b", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "[1]\n", 14 | "[1]\n" 15 | ] 16 | } 17 | ], 18 | "source": [ 19 | "from galgebra.ga import Ga\n", 20 | "import sympy as S\n", 21 | "\n", 22 | "ga = Ga('e', g=[1,1,1], coords=S.symbols(f\"0:3\", real=True), wedge=False)\n", 23 | "x,y,z = ga.mv()\n", 24 | "a = ga.mv('A','mv')\n", 25 | "print((a.grade(0)*x).grades)\n", 26 | "print((a.grade(0)^x).grades)" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "id": "8920d631-eb4f-4955-9558-9dc158b5171e", 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [] 36 | } 37 | ], 38 | "metadata": { 39 | "kernelspec": { 40 | "display_name": "Python 3 (ipykernel)", 41 | "language": "python", 42 | "name": "python3" 43 | }, 44 | "language_info": { 45 | "codemirror_mode": { 46 | "name": "ipython", 47 | "version": 3 48 | }, 49 | "file_extension": ".py", 50 | "mimetype": "text/x-python", 51 | "name": "python", 52 | "nbconvert_exporter": "python", 53 | "pygments_lexer": "ipython3", 54 | "version": "3.9.18" 55 | } 56 | }, 57 | "nbformat": 4, 58 | "nbformat_minor": 5 59 | } 60 | -------------------------------------------------------------------------------- /examples/ipython/issue-518.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "2956314d-53f6-4150-ab15-90eaa84e8815", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "data": { 11 | "text/latex": [ 12 | "$\\displaystyle 1$" 13 | ], 14 | "text/plain": [ 15 | "1" 16 | ] 17 | }, 18 | "execution_count": 2, 19 | "metadata": {}, 20 | "output_type": "execute_result" 21 | } 22 | ], 23 | "source": [ 24 | "from galgebra.ga import Ga\n", 25 | "import sympy as S\n", 26 | "\n", 27 | "ga = Ga('e', g=[1,1,1], coords=S.symbols(f\"0:{3}\", real=True), wedge=False)\n", 28 | "x,y,z = ga.mv()\n", 29 | "(x**0).grade()" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 3, 35 | "id": "2fa9ab19-eb44-4eb8-b369-453cd779a249", 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "data": { 40 | "text/latex": [ 41 | "$\\displaystyle 1$" 42 | ], 43 | "text/plain": [ 44 | "1" 45 | ] 46 | }, 47 | "execution_count": 3, 48 | "metadata": {}, 49 | "output_type": "execute_result" 50 | } 51 | ], 52 | "source": [ 53 | "(x**2).grade()" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "id": "9b287705-2c5a-4a6b-88f4-ba7c7c336947", 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [] 63 | } 64 | ], 65 | "metadata": { 66 | "kernelspec": { 67 | "display_name": "Python 3 (ipykernel)", 68 | "language": "python", 69 | "name": "python3" 70 | }, 71 | "language_info": { 72 | "codemirror_mode": { 73 | "name": "ipython", 74 | "version": 3 75 | }, 76 | "file_extension": ".py", 77 | "mimetype": "text/x-python", 78 | "name": "python", 79 | "nbconvert_exporter": "python", 80 | "pygments_lexer": "ipython3", 81 | "version": "3.9.18" 82 | } 83 | }, 84 | "nbformat": 4, 85 | "nbformat_minor": 5 86 | } 87 | -------------------------------------------------------------------------------- /examples/primer/g2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/latex": [ 11 | "$\\displaystyle \\DeclareMathOperator{\\Tr}{Tr}$$\n", 12 | "$$\\DeclareMathOperator{\\Adj}{Adj}$$\n", 13 | "$$\\newcommand{\\bfrac}[2]{\\displaystyle\\frac{#1}{#2}}$$\n", 14 | "$$\\newcommand{\\lp}{\\left (}$$\n", 15 | "$$\\newcommand{\\rp}{\\right )}$$\n", 16 | "$$\\newcommand{\\paren}[1]{\\lp {#1} \\rp}$$\n", 17 | "$$\\newcommand{\\half}{\\frac{1}{2}}$$\n", 18 | "$$\\newcommand{\\llt}{\\left <}$$\n", 19 | "$$\\newcommand{\\rgt}{\\right >}$$\n", 20 | "$$\\newcommand{\\abs}[1]{\\left |{#1}\\right | }$$\n", 21 | "$$\\newcommand{\\pdiff}[2]{\\bfrac{\\partial {#1}}{\\partial {#2}}}$$\n", 22 | "$$\\newcommand{\\npdiff}[3]{\\bfrac{\\partial^{#3} {#1}}{\\partial {#2}^{#3}}}$$\n", 23 | "$$\\newcommand{\\lbrc}{\\left \\{}$$\n", 24 | "$$\\newcommand{\\rbrc}{\\right \\}}$$\n", 25 | "$$\\newcommand{\\W}{\\wedge}$$\n", 26 | "$$\\newcommand{\\prm}[1]{{#1}^{\\prime}}$$\n", 27 | "$$\\newcommand{\\ddt}[1]{\\bfrac{d{#1}}{dt}}$$\n", 28 | "$$\\newcommand{\\R}{\\dagger}$$\n", 29 | "$$\\newcommand{\\deriv}[3]{\\bfrac{d^{#3}#1}{d{#2}^{#3}}}$$\n", 30 | "$$\\newcommand{\\grade}[2]{\\left < {#1} \\right >_{#2}}$$\n", 31 | "$$\\newcommand{\\f}[2]{{#1}\\lp {#2} \\rp}$$\n", 32 | "$$\\newcommand{\\eval}[2]{\\left . {#1} \\right |_{#2}}$$\n", 33 | "$$\\newcommand{\\bs}[1]{\\boldsymbol{#1}}$$\n", 34 | "$$\\newcommand{\\grad}{\\bs{\\nabla}}$" 35 | ], 36 | "text/plain": [ 37 | "" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "# G2: Standard 2D Model\n", 46 | "\n", 47 | "# Make SymPy available to this program:\n", 48 | "import sympy \n", 49 | "from sympy import *\n", 50 | "\n", 51 | "# Make GAlgebra available to this program:\n", 52 | "from galgebra.ga import * \n", 53 | "from galgebra.mv import *\n", 54 | "from galgebra.printer import Fmt, GaPrinter, Format\n", 55 | " # Fmt: sets the way that a multivector's basis expansion is output.\n", 56 | " # GaPrinter: makes GA output a little more readable.\n", 57 | " # Format: turns on latex printer.\n", 58 | "from galgebra.gprinter import gFormat, gprint\n", 59 | "gFormat()" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 2, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# g2: The geometric algebra G^2.\n", 69 | "g2coords = (x,y) = symbols('x y', real=True)\n", 70 | "g2 = Ga('e', g=[1,1,1], coords=g2coords)\n", 71 | "(ex, ey) = g2.mv()\n", 72 | "\n", 73 | "grad = g2.grad\n", 74 | "from galgebra.dop import *\n", 75 | "pdx = Pdop(x)\n", 76 | "pdy = Pdop(y)" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [] 85 | } 86 | ], 87 | "metadata": { 88 | "kernelspec": { 89 | "display_name": "Python 3 (ipykernel)", 90 | "language": "python", 91 | "name": "python3" 92 | }, 93 | "language_info": { 94 | "codemirror_mode": { 95 | "name": "ipython", 96 | "version": 3 97 | }, 98 | "file_extension": ".py", 99 | "mimetype": "text/x-python", 100 | "name": "python", 101 | "nbconvert_exporter": "python", 102 | "pygments_lexer": "ipython3", 103 | "version": "3.11.8" 104 | } 105 | }, 106 | "nbformat": 4, 107 | "nbformat_minor": 4 108 | } 109 | -------------------------------------------------------------------------------- /examples/primer/g3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/latex": [ 11 | "$\\displaystyle \\DeclareMathOperator{\\Tr}{Tr}$$\n", 12 | "$$\\DeclareMathOperator{\\Adj}{Adj}$$\n", 13 | "$$\\newcommand{\\bfrac}[2]{\\displaystyle\\frac{#1}{#2}}$$\n", 14 | "$$\\newcommand{\\lp}{\\left (}$$\n", 15 | "$$\\newcommand{\\rp}{\\right )}$$\n", 16 | "$$\\newcommand{\\paren}[1]{\\lp {#1} \\rp}$$\n", 17 | "$$\\newcommand{\\half}{\\frac{1}{2}}$$\n", 18 | "$$\\newcommand{\\llt}{\\left <}$$\n", 19 | "$$\\newcommand{\\rgt}{\\right >}$$\n", 20 | "$$\\newcommand{\\abs}[1]{\\left |{#1}\\right | }$$\n", 21 | "$$\\newcommand{\\pdiff}[2]{\\bfrac{\\partial {#1}}{\\partial {#2}}}$$\n", 22 | "$$\\newcommand{\\npdiff}[3]{\\bfrac{\\partial^{#3} {#1}}{\\partial {#2}^{#3}}}$$\n", 23 | "$$\\newcommand{\\lbrc}{\\left \\{}$$\n", 24 | "$$\\newcommand{\\rbrc}{\\right \\}}$$\n", 25 | "$$\\newcommand{\\W}{\\wedge}$$\n", 26 | "$$\\newcommand{\\prm}[1]{{#1}^{\\prime}}$$\n", 27 | "$$\\newcommand{\\ddt}[1]{\\bfrac{d{#1}}{dt}}$$\n", 28 | "$$\\newcommand{\\R}{\\dagger}$$\n", 29 | "$$\\newcommand{\\deriv}[3]{\\bfrac{d^{#3}#1}{d{#2}^{#3}}}$$\n", 30 | "$$\\newcommand{\\grade}[2]{\\left < {#1} \\right >_{#2}}$$\n", 31 | "$$\\newcommand{\\f}[2]{{#1}\\lp {#2} \\rp}$$\n", 32 | "$$\\newcommand{\\eval}[2]{\\left . {#1} \\right |_{#2}}$$\n", 33 | "$$\\newcommand{\\bs}[1]{\\boldsymbol{#1}}$$\n", 34 | "$$\\newcommand{\\grad}{\\bs{\\nabla}}$" 35 | ], 36 | "text/plain": [ 37 | "" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "# G3: Standard 3D Model\n", 46 | "\n", 47 | "# Make SymPy available to this program:\n", 48 | "import sympy \n", 49 | "from sympy import *\n", 50 | "\n", 51 | "# Make GAlgebra available to this program:\n", 52 | "from galgebra.ga import * \n", 53 | "from galgebra.mv import *\n", 54 | "from galgebra.printer import Fmt, GaPrinter, Format\n", 55 | " # Fmt: sets the way that a multivector's basis expansion is output.\n", 56 | " # GaPrinter: makes GA output a little more readable.\n", 57 | " # Format: turns on latex printer.\n", 58 | "from galgebra.gprinter import gFormat, gprint\n", 59 | "gFormat()" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 2, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# g3: The geometric algebra G^3.\n", 69 | "g3coords = (x,y,z) = symbols('x y z', real=True)\n", 70 | "g3 = Ga('e', g=[1,1,1], coords=g3coords)\n", 71 | "(ex, ey, ez) = g3.mv()\n", 72 | "\n", 73 | "grad = g3.grad\n", 74 | "from galgebra.dop import *\n", 75 | "pdx = Pdop(x)\n", 76 | "pdy = Pdop(y)\n", 77 | "pdz = Pdop(z)" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [] 86 | } 87 | ], 88 | "metadata": { 89 | "kernelspec": { 90 | "display_name": "Python 3 (ipykernel)", 91 | "language": "python", 92 | "name": "python3" 93 | }, 94 | "language_info": { 95 | "codemirror_mode": { 96 | "name": "ipython", 97 | "version": 3 98 | }, 99 | "file_extension": ".py", 100 | "mimetype": "text/x-python", 101 | "name": "python", 102 | "nbconvert_exporter": "python", 103 | "pygments_lexer": "ipython3", 104 | "version": "3.11.8" 105 | } 106 | }, 107 | "nbformat": 4, 108 | "nbformat_minor": 4 109 | } 110 | -------------------------------------------------------------------------------- /examples/primer/g4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/latex": [ 11 | "$\\displaystyle \\DeclareMathOperator{\\Tr}{Tr}$$\n", 12 | "$$\\DeclareMathOperator{\\Adj}{Adj}$$\n", 13 | "$$\\newcommand{\\bfrac}[2]{\\displaystyle\\frac{#1}{#2}}$$\n", 14 | "$$\\newcommand{\\lp}{\\left (}$$\n", 15 | "$$\\newcommand{\\rp}{\\right )}$$\n", 16 | "$$\\newcommand{\\paren}[1]{\\lp {#1} \\rp}$$\n", 17 | "$$\\newcommand{\\half}{\\frac{1}{2}}$$\n", 18 | "$$\\newcommand{\\llt}{\\left <}$$\n", 19 | "$$\\newcommand{\\rgt}{\\right >}$$\n", 20 | "$$\\newcommand{\\abs}[1]{\\left |{#1}\\right | }$$\n", 21 | "$$\\newcommand{\\pdiff}[2]{\\bfrac{\\partial {#1}}{\\partial {#2}}}$$\n", 22 | "$$\\newcommand{\\npdiff}[3]{\\bfrac{\\partial^{#3} {#1}}{\\partial {#2}^{#3}}}$$\n", 23 | "$$\\newcommand{\\lbrc}{\\left \\{}$$\n", 24 | "$$\\newcommand{\\rbrc}{\\right \\}}$$\n", 25 | "$$\\newcommand{\\W}{\\wedge}$$\n", 26 | "$$\\newcommand{\\prm}[1]{{#1}^{\\prime}}$$\n", 27 | "$$\\newcommand{\\ddt}[1]{\\bfrac{d{#1}}{dt}}$$\n", 28 | "$$\\newcommand{\\R}{\\dagger}$$\n", 29 | "$$\\newcommand{\\deriv}[3]{\\bfrac{d^{#3}#1}{d{#2}^{#3}}}$$\n", 30 | "$$\\newcommand{\\grade}[2]{\\left < {#1} \\right >_{#2}}$$\n", 31 | "$$\\newcommand{\\f}[2]{{#1}\\lp {#2} \\rp}$$\n", 32 | "$$\\newcommand{\\eval}[2]{\\left . {#1} \\right |_{#2}}$$\n", 33 | "$$\\newcommand{\\bs}[1]{\\boldsymbol{#1}}$$\n", 34 | "$$\\newcommand{\\grad}{\\bs{\\nabla}}$" 35 | ], 36 | "text/plain": [ 37 | "" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "# G4: Standard 4D Model\n", 46 | "\n", 47 | "# Make SymPy available to this program:\n", 48 | "import sympy \n", 49 | "from sympy import *\n", 50 | "\n", 51 | "# Make GAlgebra available to this program:\n", 52 | "from galgebra.ga import * \n", 53 | "from galgebra.mv import *\n", 54 | "from galgebra.printer import Fmt, GaPrinter, Format\n", 55 | " # Fmt: sets the way that a multivector's basis expansion is output.\n", 56 | " # GaPrinter: makes GA output a little more readable.\n", 57 | " # Format: turns on latex printer.\n", 58 | "from galgebra.gprinter import gFormat, gprint\n", 59 | "gFormat()" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 2, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# g4: R^4 using cartesian coordiantes\n", 69 | "g4coords = (x,y,z,w) = symbols('x y z w', real=True)\n", 70 | "g4 = Ga('e', g=[1,1,1,1], coords=g4coords)\n", 71 | "(ex, ey, ez, ew) = g4.mv()" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [] 80 | } 81 | ], 82 | "metadata": { 83 | "kernelspec": { 84 | "display_name": "Python 3 (ipykernel)", 85 | "language": "python", 86 | "name": "python3" 87 | }, 88 | "language_info": { 89 | "codemirror_mode": { 90 | "name": "ipython", 91 | "version": 3 92 | }, 93 | "file_extension": ".py", 94 | "mimetype": "text/x-python", 95 | "name": "python", 96 | "nbconvert_exporter": "python", 97 | "pygments_lexer": "ipython3", 98 | "version": "3.11.8" 99 | } 100 | }, 101 | "nbformat": 4, 102 | "nbformat_minor": 4 103 | } 104 | -------------------------------------------------------------------------------- /examples/primer/h3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/latex": [ 11 | "$\\displaystyle \\DeclareMathOperator{\\Tr}{Tr}$$\n", 12 | "$$\\DeclareMathOperator{\\Adj}{Adj}$$\n", 13 | "$$\\newcommand{\\bfrac}[2]{\\displaystyle\\frac{#1}{#2}}$$\n", 14 | "$$\\newcommand{\\lp}{\\left (}$$\n", 15 | "$$\\newcommand{\\rp}{\\right )}$$\n", 16 | "$$\\newcommand{\\paren}[1]{\\lp {#1} \\rp}$$\n", 17 | "$$\\newcommand{\\half}{\\frac{1}{2}}$$\n", 18 | "$$\\newcommand{\\llt}{\\left <}$$\n", 19 | "$$\\newcommand{\\rgt}{\\right >}$$\n", 20 | "$$\\newcommand{\\abs}[1]{\\left |{#1}\\right | }$$\n", 21 | "$$\\newcommand{\\pdiff}[2]{\\bfrac{\\partial {#1}}{\\partial {#2}}}$$\n", 22 | "$$\\newcommand{\\npdiff}[3]{\\bfrac{\\partial^{#3} {#1}}{\\partial {#2}^{#3}}}$$\n", 23 | "$$\\newcommand{\\lbrc}{\\left \\{}$$\n", 24 | "$$\\newcommand{\\rbrc}{\\right \\}}$$\n", 25 | "$$\\newcommand{\\W}{\\wedge}$$\n", 26 | "$$\\newcommand{\\prm}[1]{{#1}^{\\prime}}$$\n", 27 | "$$\\newcommand{\\ddt}[1]{\\bfrac{d{#1}}{dt}}$$\n", 28 | "$$\\newcommand{\\R}{\\dagger}$$\n", 29 | "$$\\newcommand{\\deriv}[3]{\\bfrac{d^{#3}#1}{d{#2}^{#3}}}$$\n", 30 | "$$\\newcommand{\\grade}[2]{\\left < {#1} \\right >_{#2}}$$\n", 31 | "$$\\newcommand{\\f}[2]{{#1}\\lp {#2} \\rp}$$\n", 32 | "$$\\newcommand{\\eval}[2]{\\left . {#1} \\right |_{#2}}$$\n", 33 | "$$\\newcommand{\\bs}[1]{\\boldsymbol{#1}}$$\n", 34 | "$$\\newcommand{\\grad}{\\bs{\\nabla}}$" 35 | ], 36 | "text/plain": [ 37 | "" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "# h3: 3D Homogeneous Coordinates\n", 46 | "\n", 47 | "import sympy \n", 48 | "from sympy import * # Make SymPy available to this program\n", 49 | "sympy.init_printing() \n", 50 | "\n", 51 | "from galgebra.printer import Fmt, GaPrinter # Need all these parameters\n", 52 | "from galgebra.gprinter import gFormat, gprint\n", 53 | "gFormat()\n", 54 | "\n", 55 | "from galgebra.ga import * # Make GAlgebra available to this program.\n", 56 | "from galgebra.mv import *\n", 57 | "from galgebra.printer import Fmt, GaPrinter, Format\n", 58 | " # Fmt: sets the way that a multivector's basis expansion is output.\n", 59 | " # GaPrinter: makes GA output a little more readable.\n", 60 | " # Format: turns on latex printer.\n", 61 | "\n", 62 | "from galgebra.gprinter import gFormat, gprint\n", 63 | "gFormat()" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 2, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "h3coords = (x,y,z,e) = symbols('x y z e', real=True)\n", 73 | "# h3 = Ga('e_x e_y e_z e_e', g=[1,1,1,1], coords=h3coords)\n", 74 | "h3 = Ga('\\mathbf{e}', g=[1,1,1,1], coords=h3coords)\n", 75 | "(ex,ey,ez,ee) = h3.mv()" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [] 84 | } 85 | ], 86 | "metadata": { 87 | "kernelspec": { 88 | "display_name": "Python 3 (ipykernel)", 89 | "language": "python", 90 | "name": "python3" 91 | }, 92 | "language_info": { 93 | "codemirror_mode": { 94 | "name": "ipython", 95 | "version": 3 96 | }, 97 | "file_extension": ".py", 98 | "mimetype": "text/x-python", 99 | "name": "python", 100 | "nbconvert_exporter": "python", 101 | "pygments_lexer": "ipython3", 102 | "version": "3.11.8" 103 | } 104 | }, 105 | "nbformat": 4, 106 | "nbformat_minor": 4 107 | } 108 | -------------------------------------------------------------------------------- /examples/primer/sp2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# sp2: Geometric algebra for unit sphere in R^3 using spherical coordinates.\n", 10 | "# Mathematics coordinate order: (phi,theta)\n", 11 | "\n", 12 | "# Make SymPy available to this program:\n", 13 | "import sympy \n", 14 | "from sympy import *\n", 15 | "\n", 16 | "# Make GAlgebra available to this program:\n", 17 | "from galgebra.ga import * \n", 18 | "from galgebra.mv import *\n", 19 | "from galgebra.printer import Fmt, GaPrinter, Format\n", 20 | " # Fmt: sets the way that a multivector's basis expansion is output.\n", 21 | " # GaPrinter: makes GA output a little more readable.\n", 22 | " # Format: turns on latex printer.\n", 23 | "from galgebra.gprinter import gFormat, gprint\n", 24 | "gFormat()" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "# sp2: Geometric algebra for unit sphere in R^3 using spherical coordinates.\n", 34 | "# Mathematics coordinate order: (phi,theta)\n", 35 | "\n", 36 | "# Set up sp2\n", 37 | "basis = 'e_phi e_theta'\n", 38 | "coords = (phi,th) = symbols('phi theta', real=True)\n", 39 | "g = [sin(phi)*cos(th), sin(phi)*sin(th), cos(phi)]\n", 40 | "sp2 = Ga('\\mathbf{e}', g=None , coords=coords, \\\n", 41 | " X=[sin(phi)*cos(th), sin(phi)*sin(th), cos(phi)], norm=True)\n", 42 | "\n", 43 | "(ephi, eth) = sp2.mv()\n", 44 | "(rphi, rth) = sp2.mvr()\n", 45 | "\n", 46 | "# Derivatives\n", 47 | "grad = sp2.grad\n", 48 | "# from galgebra.dop import *\n", 49 | "# pdphi = Pdop(phi)\n", 50 | "# pdth = Pdop(th)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "grad" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [] 68 | } 69 | ], 70 | "metadata": { 71 | "kernelspec": { 72 | "display_name": "Python 3 (ipykernel)", 73 | "language": "python", 74 | "name": "python3" 75 | }, 76 | "language_info": { 77 | "codemirror_mode": { 78 | "name": "ipython", 79 | "version": 3 80 | }, 81 | "file_extension": ".py", 82 | "mimetype": "text/x-python", 83 | "name": "python", 84 | "nbconvert_exporter": "python", 85 | "pygments_lexer": "ipython3", 86 | "version": "3.11.8" 87 | } 88 | }, 89 | "nbformat": 4, 90 | "nbformat_minor": 4 91 | } 92 | -------------------------------------------------------------------------------- /examples/primer/sp3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/latex": [ 11 | "$\\displaystyle \\DeclareMathOperator{\\Tr}{Tr}$$\n", 12 | "$$\\DeclareMathOperator{\\Adj}{Adj}$$\n", 13 | "$$\\newcommand{\\bfrac}[2]{\\displaystyle\\frac{#1}{#2}}$$\n", 14 | "$$\\newcommand{\\lp}{\\left (}$$\n", 15 | "$$\\newcommand{\\rp}{\\right )}$$\n", 16 | "$$\\newcommand{\\paren}[1]{\\lp {#1} \\rp}$$\n", 17 | "$$\\newcommand{\\half}{\\frac{1}{2}}$$\n", 18 | "$$\\newcommand{\\llt}{\\left <}$$\n", 19 | "$$\\newcommand{\\rgt}{\\right >}$$\n", 20 | "$$\\newcommand{\\abs}[1]{\\left |{#1}\\right | }$$\n", 21 | "$$\\newcommand{\\pdiff}[2]{\\bfrac{\\partial {#1}}{\\partial {#2}}}$$\n", 22 | "$$\\newcommand{\\npdiff}[3]{\\bfrac{\\partial^{#3} {#1}}{\\partial {#2}^{#3}}}$$\n", 23 | "$$\\newcommand{\\lbrc}{\\left \\{}$$\n", 24 | "$$\\newcommand{\\rbrc}{\\right \\}}$$\n", 25 | "$$\\newcommand{\\W}{\\wedge}$$\n", 26 | "$$\\newcommand{\\prm}[1]{{#1}^{\\prime}}$$\n", 27 | "$$\\newcommand{\\ddt}[1]{\\bfrac{d{#1}}{dt}}$$\n", 28 | "$$\\newcommand{\\R}{\\dagger}$$\n", 29 | "$$\\newcommand{\\deriv}[3]{\\bfrac{d^{#3}#1}{d{#2}^{#3}}}$$\n", 30 | "$$\\newcommand{\\grade}[2]{\\left < {#1} \\right >_{#2}}$$\n", 31 | "$$\\newcommand{\\f}[2]{{#1}\\lp {#2} \\rp}$$\n", 32 | "$$\\newcommand{\\eval}[2]{\\left . {#1} \\right |_{#2}}$$\n", 33 | "$$\\newcommand{\\bs}[1]{\\boldsymbol{#1}}$$\n", 34 | "$$\\newcommand{\\grad}{\\bs{\\nabla}}$" 35 | ], 36 | "text/plain": [ 37 | "" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "# sp3: Spherical Coordinates in R^3\n", 46 | "\n", 47 | "# Make SymPy available to this program:\n", 48 | "import sympy \n", 49 | "from sympy import *\n", 50 | "\n", 51 | "# Make GAlgebra available to this program:\n", 52 | "from galgebra.ga import * \n", 53 | "from galgebra.mv import *\n", 54 | "from galgebra.printer import Fmt, GaPrinter, Format\n", 55 | " # Fmt: sets the way that a multivector's basis expansion is output.\n", 56 | " # GaPrinter: makes GA output a little more readable.\n", 57 | " # Format: turns on latex printer.\n", 58 | "from galgebra.gprinter import gFormat, gprint\n", 59 | "gFormat()" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 2, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# sp3: Geometric algebra for R^3 using spherical coordinates \n", 69 | "# Mathematics convention: r, phi (colatitude), theta (longitude), in right handed order. \n", 70 | "\n", 71 | "sp3coords = (r, phi, theta) = symbols('r phi theta') \n", 72 | "sp3 = Ga('e', g=None, coords=sp3coords, \\\n", 73 | " X=[r*sin(phi)*cos(theta), r*sin(phi)*sin(theta),r*cos(phi)], norm=True)\n", 74 | " # g = None. Instead, the spherical coordinate parameterization X is used.\n", 75 | " # \"\\\" is Python's line continuation character\n", 76 | "(er, ephi, etheta) = sp3.mv()\n", 77 | "\n", 78 | "grad = sp3.grad\n", 79 | "from galgebra.dop import *\n", 80 | "pdr = Pdop(r)\n", 81 | "pdphi = Pdop(phi)\n", 82 | "pdtheta = Pdop(theta)" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 3, 88 | "metadata": {}, 89 | "outputs": [ 90 | { 91 | "data": { 92 | "text/latex": [ 93 | "$\\displaystyle \\mathbf{e}_{r} \\frac{\\partial}{\\partial r} + \\mathbf{e}_{\\phi} \\frac{1}{r} \\frac{\\partial}{\\partial \\phi} + \\mathbf{e}_{\\theta} \\frac{1}{r \\sin{\\left(\\phi \\right)}} \\frac{\\partial}{\\partial \\theta}$" 94 | ], 95 | "text/plain": [ 96 | "e_r*D{r} + e_phi*1/r*D{phi} + e_theta*1/(r*sin(phi))*D{theta}" 97 | ] 98 | }, 99 | "execution_count": 3, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "sp3.grad" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": null, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [] 114 | } 115 | ], 116 | "metadata": { 117 | "kernelspec": { 118 | "display_name": "Python 3 (ipykernel)", 119 | "language": "python", 120 | "name": "python3" 121 | }, 122 | "language_info": { 123 | "codemirror_mode": { 124 | "name": "ipython", 125 | "version": 3 126 | }, 127 | "file_extension": ".py", 128 | "mimetype": "text/x-python", 129 | "name": "python", 130 | "nbconvert_exporter": "python", 131 | "pygments_lexer": "ipython3", 132 | "version": "3.11.8" 133 | } 134 | }, 135 | "nbformat": 4, 136 | "nbformat_minor": 4 137 | } 138 | -------------------------------------------------------------------------------- /examples/primer/spacetime.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/latex": [ 11 | "$\\displaystyle \\DeclareMathOperator{\\Tr}{Tr}$$\n", 12 | "$$\\DeclareMathOperator{\\Adj}{Adj}$$\n", 13 | "$$\\newcommand{\\bfrac}[2]{\\displaystyle\\frac{#1}{#2}}$$\n", 14 | "$$\\newcommand{\\lp}{\\left (}$$\n", 15 | "$$\\newcommand{\\rp}{\\right )}$$\n", 16 | "$$\\newcommand{\\paren}[1]{\\lp {#1} \\rp}$$\n", 17 | "$$\\newcommand{\\half}{\\frac{1}{2}}$$\n", 18 | "$$\\newcommand{\\llt}{\\left <}$$\n", 19 | "$$\\newcommand{\\rgt}{\\right >}$$\n", 20 | "$$\\newcommand{\\abs}[1]{\\left |{#1}\\right | }$$\n", 21 | "$$\\newcommand{\\pdiff}[2]{\\bfrac{\\partial {#1}}{\\partial {#2}}}$$\n", 22 | "$$\\newcommand{\\npdiff}[3]{\\bfrac{\\partial^{#3} {#1}}{\\partial {#2}^{#3}}}$$\n", 23 | "$$\\newcommand{\\lbrc}{\\left \\{}$$\n", 24 | "$$\\newcommand{\\rbrc}{\\right \\}}$$\n", 25 | "$$\\newcommand{\\W}{\\wedge}$$\n", 26 | "$$\\newcommand{\\prm}[1]{{#1}^{\\prime}}$$\n", 27 | "$$\\newcommand{\\ddt}[1]{\\bfrac{d{#1}}{dt}}$$\n", 28 | "$$\\newcommand{\\R}{\\dagger}$$\n", 29 | "$$\\newcommand{\\deriv}[3]{\\bfrac{d^{#3}#1}{d{#2}^{#3}}}$$\n", 30 | "$$\\newcommand{\\grade}[2]{\\left < {#1} \\right >_{#2}}$$\n", 31 | "$$\\newcommand{\\f}[2]{{#1}\\lp {#2} \\rp}$$\n", 32 | "$$\\newcommand{\\eval}[2]{\\left . {#1} \\right |_{#2}}$$\n", 33 | "$$\\newcommand{\\bs}[1]{\\boldsymbol{#1}}$$\n", 34 | "$$\\newcommand{\\grad}{\\bs{\\nabla}}$" 35 | ], 36 | "text/plain": [ 37 | "" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "# Spacetime algebra. [1, -1, -1, -1] signature\n", 46 | "\n", 47 | "# Make SymPy available to this program:\n", 48 | "import sympy \n", 49 | "from sympy import *\n", 50 | "\n", 51 | "# Make GAlgebra available to this program:\n", 52 | "from galgebra.ga import * \n", 53 | "from galgebra.mv import *\n", 54 | "from galgebra.printer import Fmt, GaPrinter, Format\n", 55 | " # Fmt: sets the way that a multivector's basis expansion is output.\n", 56 | " # GaPrinter: makes GA output a little more readable.\n", 57 | " # Format: turns on latex printer.\n", 58 | "from galgebra.gprinter import gFormat, gprint\n", 59 | "gFormat()" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 2, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "txyz = (t, x, y, z) = symbols('t x y z', real=True)\n", 69 | "stcoords = (t,x,y,z) = symbols('t x y z')\n", 70 | "st = Ga('\\mathbf{e}', g=[1, -1, -1, -1], coords=stcoords)\n", 71 | "(et, ex, ey, ez) = st.mv()" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 3, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "data": { 81 | "text/latex": [ 82 | "$\\displaystyle X = X^{t} \\mathbf{\\mathbf{e}_t} + X^{x} \\mathbf{\\mathbf{e}_x} + X^{y} \\mathbf{\\mathbf{e}_y} + X^{z} \\mathbf{\\mathbf{e}_z}$" 83 | ], 84 | "text/plain": [ 85 | "X__t*\\mathbf{e}_t + X__x*\\mathbf{e}_x + X__y*\\mathbf{e}_y + X__z*\\mathbf{e}_z" 86 | ] 87 | }, 88 | "execution_count": 3, 89 | "metadata": {}, 90 | "output_type": "execute_result" 91 | } 92 | ], 93 | "source": [ 94 | "st.mv('X', 'vector')" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [] 103 | } 104 | ], 105 | "metadata": { 106 | "kernelspec": { 107 | "display_name": "Python 3 (ipykernel)", 108 | "language": "python", 109 | "name": "python3" 110 | }, 111 | "language_info": { 112 | "codemirror_mode": { 113 | "name": "ipython", 114 | "version": 3 115 | }, 116 | "file_extension": ".py", 117 | "mimetype": "text/x-python", 118 | "name": "python", 119 | "nbconvert_exporter": "python", 120 | "pygments_lexer": "ipython3", 121 | "version": "3.11.8" 122 | } 123 | }, 124 | "nbformat": 4, 125 | "nbformat_minor": 4 126 | } 127 | -------------------------------------------------------------------------------- /galgebra/__init__.py: -------------------------------------------------------------------------------- 1 | r""" 2 | .. currentmodule:: galgebra 3 | 4 | ======================================== 5 | galgebra (:mod:`galgebra`) 6 | ======================================== 7 | 8 | A module for geometric algebra. 9 | 10 | Submodules 11 | ========== 12 | 13 | .. autosummary:: 14 | :toctree: generated 15 | 16 | metric 17 | ga 18 | mv 19 | lt 20 | dop 21 | atoms 22 | printer 23 | gprinter 24 | utils 25 | 26 | .. note:: 27 | 28 | Some functions may be better documented by the original non-generated docs 29 | on the :doc:`module-components` page, but there is a risk the descriptions 30 | there are outdated. 31 | 32 | If you would like to help with merging the descriptions here with a 33 | description on that page, please head over to :issue:`300` on GitHub, where 34 | there's an explanation of how to do so. Even merging just one function 35 | explanation helps! 36 | """ 37 | 38 | from ._version import __version__ # noqa: F401 39 | -------------------------------------------------------------------------------- /galgebra/_backports/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Backports of library components from newer python versions. 3 | 4 | For internal use only. 5 | """ 6 | -------------------------------------------------------------------------------- /galgebra/_backports/typing.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | # shim for typing.OrderedDict 4 | if sys.version_info >= (3, 7, 2): 5 | from typing import OrderedDict 6 | else: 7 | from typing import TypeVar, Mapping 8 | import collections 9 | 10 | K = TypeVar('K') 11 | V = TypeVar('V') 12 | 13 | class OrderedDict(collections.OrderedDict, Mapping[K, V]): 14 | pass 15 | 16 | del K, V, TypeVar, Mapping, collections 17 | -------------------------------------------------------------------------------- /galgebra/_utils/__init__.py: -------------------------------------------------------------------------------- 1 | """ Internal helpers for use in galgebra """ 2 | 3 | from .cached_property import cached_property 4 | from .kwarg_parser import KwargParser 5 | 6 | __all__ = [ 7 | 'cached_property', 8 | 'KwargParser', 9 | ] 10 | -------------------------------------------------------------------------------- /galgebra/_utils/cached_property.py: -------------------------------------------------------------------------------- 1 | class cached_property: 2 | """ A property that is only computed once """ 3 | def __init__(self, getter): 4 | self.fget = getter 5 | self.__name__ = getter.__name__ 6 | self.__doc__ = getter.__doc__ 7 | 8 | def __set_name__(self, owner, name): 9 | self.__name__ = name 10 | # copy across the annotation for sphinx 11 | try: 12 | prop_ann = self.fget.__annotations__['return'] 13 | except KeyError: 14 | return 15 | 16 | try: 17 | owner_anns = owner.__annotations__ 18 | except AttributeError: 19 | owner_anns = owner.__annotations__ = {} 20 | owner_anns[name] = prop_ann 21 | 22 | def __get__(self, obj, cls): 23 | if obj is None: 24 | return self 25 | val = self.fget(obj) 26 | # this entry hides the _cached_property 27 | setattr(obj, self.__name__, val) 28 | return val 29 | -------------------------------------------------------------------------------- /galgebra/_utils/kwarg_parser.py: -------------------------------------------------------------------------------- 1 | class KwargParser: 2 | """ 3 | Helper function to emulate Python 3 keyword-only arguments. 4 | 5 | Use as:: 6 | 7 | def func(x1, **kwargs): 8 | kw = KwargParser('func', kwargs) 9 | a = kw.pop('a') 10 | b = kw.pop('b', 2) 11 | kw.reject_remaining() 12 | ... 13 | 14 | To emulate the Python 3 syntax:: 15 | 16 | def func(x1, *, a, b=2): 17 | ... 18 | 19 | This is also useful for functions with overloaded signatures, for which 20 | a single Python 3 signature cannot be written. 21 | """ 22 | def __init__(self, func_name, kwargs): 23 | self._func_name = func_name 24 | self._kwargs = kwargs 25 | 26 | def pop(self, arg_name, *default): 27 | try: 28 | return self._kwargs.pop(arg_name, *default) 29 | except KeyError: 30 | pass 31 | raise TypeError( 32 | '{}() missing required keyword-only argument {!r}' 33 | .format(self._func_name, arg_name) 34 | ) 35 | 36 | def reject_remaining(self): 37 | if self._kwargs: 38 | # match the error message to what Python 3 produces 39 | bad_arg = next(iter(self._kwargs)) 40 | raise TypeError( 41 | '{}() got an unexpected keyword argument {!r}' 42 | .format(self._func_name, bad_arg) 43 | ) 44 | -------------------------------------------------------------------------------- /galgebra/_utils/printable.py: -------------------------------------------------------------------------------- 1 | __all__ = ['Printable'] 2 | 3 | try: 4 | from sympy.printing.defaults import Printable 5 | except ImportError: 6 | # sympy < 1.7 7 | from sympy import Basic 8 | 9 | class _Trick_can_print_latex(set): 10 | """ 11 | A class that tricks the `_can_print_latex` function in sympy < 1.7 into 12 | returning True for our types, by subclassing a supported type. 13 | 14 | In sympy >= 1.7, it already returns True for our types. 15 | """ 16 | def __init__(self, value): 17 | self.value = value 18 | 19 | def __iter__(self): 20 | return iter([]) 21 | 22 | def _latex(self, printer): 23 | return printer._print(self.value) 24 | 25 | class Printable: 26 | """ Backport of `sympy.printing.defaults.Printable` """ 27 | def __str__(self): 28 | from sympy.printing.str import sstr 29 | return sstr(self, order=None) 30 | 31 | __repr__ = __str__ 32 | 33 | def _repr_latex_(self): 34 | f = None 35 | try: 36 | # This isn't perfect, in principle there could be multiple 37 | # active IPython's with different configurations. 38 | ip = get_ipython() 39 | except NameError: 40 | # Not in IPython 41 | pass 42 | else: 43 | # Reuse the printer that was customized by init_printing, if 44 | # present. 45 | f = ip.display_formatter.formatters['text/latex'].type_printers.get(Basic) 46 | 47 | if f is None: 48 | # no customizations present or ipython not running 49 | f = Basic._repr_latex_ 50 | 51 | if f is None: 52 | # latex printing disabled 53 | return None 54 | 55 | return f(_Trick_can_print_latex(self)) 56 | -------------------------------------------------------------------------------- /galgebra/_version.py: -------------------------------------------------------------------------------- 1 | # Package versioning solution originally found here: 2 | # http://stackoverflow.com/q/458550 3 | 4 | # Store the version here so: 5 | # 1) we don't load dependencies by storing it in __init__.py 6 | # 2) we can import it in setup.py for the same reason 7 | # 3) we can import it into your module 8 | __version__ = '0.6.0-dev' 9 | -------------------------------------------------------------------------------- /galgebra/deprecated.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | from . import ga 4 | from .mv import Mv 5 | 6 | # galgebra 0.5.0 7 | warnings.warn( 8 | "The `galgebra.deprecated` module is deprecated", 9 | DeprecationWarning, stacklevel=2) 10 | 11 | ################################# MV class for backward compatibility ################### 12 | 13 | 14 | class MV(Mv): 15 | """ A deprecated version of :class:`galgebra.mv.Mv`. """ 16 | 17 | @staticmethod 18 | def convert_metric(gstr): 19 | if gstr[0] == '[' and gstr[-1] == ']': 20 | gstr_lst = gstr[1:-1].split(',') 21 | g = [] 22 | for x in gstr_lst: 23 | g.append(int(x)) 24 | return g 25 | else: 26 | return gstr 27 | 28 | @staticmethod 29 | def setup(basis, metric=None, coords=None, rframe=False, debug=False, curv=(None, None)) -> list: 30 | """ 31 | This function allows a single geometric algebra to be created. 32 | 33 | If the function is called more than once the old geometric algebra is 34 | overwritten by the new geometric algebra. The named input ``metric`` 35 | is the same as the named input ``g`` in the current version of 36 | *galgebra*. Likewise, ``basis``, ``coords``, and ``debug`` are the same 37 | in the old and current versions of *galgebra* [17]_. 38 | Due to improvements in *sympy* the inputs ``rframe`` and ``curv[1]`` are 39 | no longer required. ``curv[0]`` is the vector function (list or tuple of 40 | scalar functions) of the coordinates required to define a vector manifold. 41 | For compatibility with the old version of *galgebra* if ``curv`` is used 42 | ``metric`` should be a orthonormal Euclidean metric of the same 43 | dimension as ``curv[0]``. 44 | 45 | It is strongly suggested that one use the new methods of defining a 46 | geometric algebra on a manifold. 47 | 48 | .. [17] 49 | If the metric is input as a list or list or lists the object is no 50 | longer quoted (input as a string). For example the old 51 | ``metric='[1,1,1]'`` becomes ``metric=[1,1,1]``. 52 | """ 53 | 54 | if isinstance(metric, str): 55 | metric = MV.convert_metric(metric) 56 | if curv != (None, None): 57 | MV.GA = ga.Ga(basis, g=None, coords=coords, X=curv[0], debug=debug) 58 | else: 59 | MV.GA = ga.Ga(basis, g=metric, coords=coords, X=curv[0], debug=debug) 60 | MV.I = MV.GA.i 61 | MV.metric = MV.GA.g 62 | if coords is not None: 63 | MV.grad, MV.rgrad = MV.GA.grads() 64 | return list(MV.GA.mv()) + [MV.grad] 65 | else: 66 | return list(MV.GA.mv()) 67 | 68 | def __init__(self, base, mvtype, fct=None, blade_rep=True): 69 | # galgebra 0.5.0 70 | warnings.warn( 71 | "The `galgebra.deprecated.MV` class is deprecated in favor of " 72 | "`galgebra.mv.Mv`.", 73 | DeprecationWarning, stacklevel=2) 74 | kwargs = {} 75 | if fct is not None: 76 | kwargs['f'] = fct # only forward this argument if we received it 77 | Mv.__init__(self, base, mvtype, ga=MV.GA, **kwargs) 78 | 79 | def Fmt(self, fmt=1, title=None) -> None: 80 | """ 81 | ``Fmt`` in ``MV`` has inputs identical to ``Fmt`` in ``Mv`` except that 82 | if ``A`` is a multivector then ``A.Fmt(2,'A')`` executes a print 83 | statement from ``MV`` and returns ``None``, while from ``Mv``, 84 | ``A.Fmt(2,'A')`` returns a string so that the function is compatible 85 | with use in *ipython notebook*. 86 | """ 87 | print(Mv.Fmt(self, fmt=fmt, title=title)) 88 | 89 | 90 | def ReciprocalFrame(basis, mode='norm'): 91 | # galgebra 0.5.0 92 | warnings.warn( 93 | "The `galgebra.deprecated.ReciprocalFrame` function is deprecated in " 94 | "favor of the `ReciprocalFrame` method of `Ga` objects.", 95 | DeprecationWarning, stacklevel=2) 96 | GA = basis[0].Ga 97 | return GA.ReciprocalFrame(basis, mode=mode) 98 | -------------------------------------------------------------------------------- /galgebra/primer.py: -------------------------------------------------------------------------------- 1 | # Author: Greg Grunberg 2 | # Last revised: 2023-01-13 3 | 4 | # INSTRUCTIONS: 5 | # 6 | # To invoke this program within a Jupyter notebok, write the command 7 | # 8 | # from galgebra.primer import * 9 | # 10 | # in the notebook's first In[ ] cell and execute that cell. 11 | 12 | from sys import version 13 | 14 | # Make SymPy available to this program 15 | import sympy 16 | from sympy import * 17 | 18 | # Make GAlgebra available to this program. 19 | import galgebra 20 | from galgebra.ga import * 21 | from galgebra.mv import * 22 | from galgebra.lt import * 23 | from galgebra.dop import * 24 | from galgebra.printer import Fmt, GaPrinter, Format 25 | # Fmt: sets display mode of a multivector's basis expansion. 26 | # GaPrinter: makes GA output a little more readable. 27 | # Format: turns on latex printer. 28 | from galgebra.gprinter import gFormat, gprint 29 | gFormat() 30 | # Default `Fmode=True` suppresses display of the arguments of 31 | # multivector fields. 32 | # Default `Dmode=True` causes partial differentiation 33 | # operators to be displayed in shortened form. 34 | Ga.dual_mode('Iinv+') 35 | # Sets multivector dualization to be right multiplication by the 36 | # by the inverse unit pseudoscalar (the convention used in the 37 | # textbooks LAGA, VAGC, and GACS). 38 | initializations_list = r"""\textsf{The following initialization commands were executed:}\\ 39 | \quad\texttt{from sys import version}\\ 40 | \quad\texttt{import sympy}\\ 41 | \quad\texttt{from sympy import *}\\ 42 | \quad\texttt{import galgebra}\\ 43 | \quad\texttt{from galgebra.ga import *}\\ 44 | \quad\texttt{from galgebra.mv import *}\\ 45 | \quad\texttt{from galgebra.lt import *}\\ 46 | \quad\texttt{from galgebra.dop import *}\\ 47 | \quad\texttt{from galgebra.printer import Fmt, GaPrinter, Format}\\ 48 | \quad\texttt{from galgebra.gprinter import gFormat, gprint}\\ 49 | \quad\texttt{gFormat()}\\~~~~~~~~ 50 | \quad\textsf{# default 'Fmode=True' suppresses arguments of multivector fields}\\~~~~~~~~ 51 | \quad\textsf{# default 'Dmode=True' displays partial differentiation operators in short form}\\ 52 | \quad\texttt{Ga.dual_mode('Iinv+')}\\~~~~~~~~ 53 | \quad\textsf{# dual and undual defined by }\mathbf{M}^\star = \mathbf{M}\mathbf{I}^{-1} \textsf{ and } \mathbf{M}^{-\star} = \mathbf{M}\mathbf{I}\\""" 54 | gprint(initializations_list) 55 | 56 | # Display versions of softwared being used. 57 | gprint(r'\textsf{This notebook is now using} \\', 58 | r'\qquad\bullet~ \textsf{Python }', version[:5], 59 | r'\qquad\bullet~ \textsf{SymPy }', sympy.__version__[:8], 60 | r'\qquad\bullet~ \textsf{GAlgebra }', galgebra.__version__[:], r'.') 61 | -------------------------------------------------------------------------------- /galgebra/utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utility Classes 3 | """ 4 | 5 | import sys 6 | import collections 7 | import warnings 8 | 9 | from io import StringIO # noqa: F401 10 | 11 | # galgebra 0.5.0 12 | warnings.warn( 13 | "galgebra.utils is deprecated and will be removed. " 14 | "If you need python 2 compatibility helpers, use a decdicated module like " 15 | "`six`.", DeprecationWarning, stacklevel=2) 16 | 17 | # From https://github.com/benjaminp/six/blob/master/six.py 18 | PY2 = sys.version_info[0] == 2 19 | PY3 = sys.version_info[0] == 3 20 | 21 | string_types = str 22 | 23 | # https://stackoverflow.com/questions/16176742/python-3-replacement-for-deprecated-compiler-ast-flatten-function 24 | 25 | 26 | def flatten(x): 27 | result = [] 28 | 29 | for el in x: 30 | if isinstance(x, collections.Iterable) and not isstr(el): 31 | result.extend(flatten(el)) 32 | else: 33 | result.append(el) 34 | return result 35 | 36 | 37 | def isstr(s): 38 | return isinstance(s, str) 39 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [test] 2 | test_suite = test 3 | 4 | [tool:pytest] 5 | # The default also includes *_test.py. This matches some example scripts, which are 6 | # not tests at all, and perform unwanted work and global configuration when 7 | # pytest scans them for tests. 8 | python_files = test_*.py 9 | 10 | [flake8] 11 | 12 | # for now, just check the main code 13 | filename = 14 | ./setup.py 15 | ./galgebra/*.py 16 | 17 | ignore = 18 | # flake8 defaults 19 | E121 20 | E123 21 | E126 22 | E226 23 | E24 24 | E704 25 | W503 26 | W504 27 | 28 | # long lines 29 | E501 30 | 31 | # allow the use of `I` and `i` as variable names 32 | E741 33 | E743 34 | 35 | per-file-ignores = 36 | # E266 too many leading '#' for block comment 37 | ./galgebra/deprecated.py:E266 38 | 39 | # E266 too many leading '#' for block comment 40 | ./galgebra/dop.py:E266 41 | 42 | # E266 too many leading '#' for block comment 43 | ./galgebra/ga.py:E266 44 | 45 | # F821 undefined name 'Mv' 46 | ./galgebra/metric.py:F821 47 | 48 | # E266 too many leading '#' for block comment 49 | ./galgebra/mv.py:E266 50 | 51 | # E122 continuation line missing indentation or outdented 52 | # E127 continuation line over-indented for visual indent 53 | # E128 continuation line under-indented for visual indent 54 | # E262 inline comment should start with '# ' 55 | # E265 block comment should start with '# ' 56 | # E402 module level import not at top of file 57 | # F401 'IPython.display.Latex' imported but unused 58 | # F401 'IPython.display.Math' imported but unused 59 | # F401 'IPython.display.display' imported but unused 60 | # F401 'IPython.display.display_latex' imported but unused 61 | # F401 'inspect.currentframe' imported but unused 62 | # F401 'inspect.getouterframes' imported but unused 63 | # F401 'sympy.core.function._coeff_isneg' imported but unused 64 | # F401 'sympy.interactive.printing' imported but unused 65 | ./galgebra/printer.py: E122,E127,E128,E262,E265,E402,F401 66 | 67 | # F401 '.printer.Format_cnt' imported but unused 68 | ./galgebra/gprinter.py: F401 69 | 70 | # F403 'from sympy import *' used; unable to detect undefined names 71 | # F403 'from galgebra.ga import *' used; unable to detect undefined names 72 | # F403 'from galgebra.mv import *' used; unable to detect undefined names 73 | # F403 'from galgebra.lt import *' used; unable to detect undefined names 74 | # F403 'from galgebra.dop import *' used; unable to detect undefined names 75 | # F401 'galgebra.printer.Fmt' imported but unused 76 | # F401 'galgebra.printer.GaPrinter' imported but unused 77 | # F401 'galgebra.printer.Format' imported but unused 78 | # F405 'Ga' may be undefined, or defined from star imports: galgebra.dop, galgebra.ga, galgebra.lt, galgebra.mv, sympy 79 | ./galgebra/primer.py: F403,F401,F405 80 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from setuptools import setup, find_packages 3 | from os import path 4 | 5 | this_directory = path.abspath(path.dirname(__file__)) 6 | 7 | with open(path.join(this_directory, 'galgebra', '_version.py'), encoding='utf-8') as f: 8 | exec(f.read()) 9 | 10 | with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: 11 | long_description = f.read() 12 | 13 | setup( 14 | name='galgebra', 15 | version=__version__, # noqa: F821 16 | description='Symbolic Geometric Algebra/Calculus package for SymPy.', 17 | author='Alan Bromborsky', 18 | maintainer='Hugo Hadfield', 19 | maintainer_email='hadfield.hugo@gmail.com', 20 | url='https://github.com/pygae/galgebra', 21 | license='BSD', 22 | packages=find_packages(), 23 | package_dir={'galgebra': 'galgebra'}, 24 | # Sympy 1.4 is needed for printing tests to pass, but 1.3 will still work 25 | install_requires=['sympy'], 26 | python_requires='>=3.6', 27 | long_description=long_description, 28 | long_description_content_type='text/markdown', 29 | classifiers=[ 30 | 'Development Status :: 4 - Beta', 31 | 'Environment :: Console', 32 | 'Intended Audience :: Science/Research', 33 | 'License :: OSI Approved :: BSD License', 34 | 'Natural Language :: English', 35 | 'Operating System :: OS Independent', 36 | 'Programming Language :: Python :: 3.8', 37 | 'Programming Language :: Python :: 3.9', 38 | 'Programming Language :: Python :: 3.10', 39 | 'Programming Language :: Python :: 3.11', 40 | 'Topic :: Scientific/Engineering :: Mathematics', 41 | 'Topic :: Scientific/Engineering :: Physics', 42 | ], 43 | project_urls={ 44 | 'Documentation': 'http://galgebra.readthedocs.io', 45 | 'Bug Tracker': 'https://github.com/pygae/galgebra/issues', 46 | 'Source Code': 'https://github.com/pygae/galgebra', 47 | }, 48 | ) 49 | -------------------------------------------------------------------------------- /test/.nbval_sanitize.cfg: -------------------------------------------------------------------------------- 1 | [Line endings] 2 | regex: \r\n 3 | replace: \n 4 | [Displaystyle] 5 | regex: \\displaystyle 6 | replace: 7 | [Math modes] 8 | regex: \$\$ 9 | replace: $ 10 | 11 | regex: \s*\$\s* 12 | replace: $ 13 | 14 | [sympy printing changes] 15 | regex: \\left \( 16 | replace: \\left( 17 | regex: \\right \) 18 | replace: \\right) 19 | regex: \\left \[ 20 | replace: \\left[ 21 | regex: \\right \] 22 | replace: \\right] 23 | 24 | # note hacks to avoid trailing spaces which editors may trim 25 | regex: , \\quad( ) 26 | replace: , \ \1 27 | 28 | # sympy 1.5 seems to reorder a few additions compared to 1.3 29 | regex: \\begin\{array}\{c}- \\frac\{\\sqrt\{2}}\{4} \+ \\frac\{1}\{2}\\end\{array} 30 | replace: \\begin{array}{c}\\frac{1}{2} - \\frac{\\sqrt{2}}{4}\\end{array} 31 | regex: =( +)- \\frac\{\\sqrt\{2}}\{4} \+ \\frac\{1}\{2}(?=\$| \\end\{equation\*}) 32 | replace: =\1\\frac{1}{2} - \\frac{\\sqrt{2}}{4} 33 | 34 | regex: \{- \\left\(\\boldsymbol\{e}_\{E}\\cdot \\boldsymbol\{e}_\{B}\\right\) \^\{2} \+ 1\} 35 | replace: {1 - \\left(\\boldsymbol{e}_{E}\\cdot \\boldsymbol{e}_{B}\\right) ^{2}} 36 | 37 | # To cope with sympy master `parenthesize_super()` for dop.ipynb, see #289 38 | regex: \\left\(\\operatorname\{F\^\{(\\phi|r|\\theta)\}\}\\right\)\^\{2\} 39 | replace: \\operatorname{F^{\1}}^{2} 40 | 41 | # sympy master does not bold subscripts of bold symbols 42 | regex: \\mathbf\{(\w+)_\{(\w+)}} 43 | replace: \\mathbf{\1}_{\2} 44 | 45 | # sympy master shows trailing commas on 1-tuples. This replacement is easier to do in reverse. 46 | regex: ,\\right\) 47 | replace: \\right) 48 | 49 | # ignore versions 50 | # \text{Python }3.8.5 51 | regex: \{Python \}(\d+\.\d+(\.\d+)?) 52 | replace: {Python } 53 | # \text{SymPy }1.8.dev 54 | regex: \{SymPy \}(\d+\.\d+(\.\d+)?(\.dev)?) 55 | replace: {SymPy } 56 | # \text{GAlgebra }0.5.0 57 | regex: \{GAlgebra \}(\d+\.\d+(\.\d+)?(-dev)?) 58 | replace: {GAlgebra } 59 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function -------------------------------------------------------------------------------- /test/fixtures/test_gprinter.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/test/fixtures/test_gprinter.pdf -------------------------------------------------------------------------------- /test/fixtures/test_lt_pdf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pygae/galgebra/8f661e31b27c453dc86ec6e56310e2ba5705e156/test/fixtures/test_lt_pdf.pdf -------------------------------------------------------------------------------- /test/test_misc.py: -------------------------------------------------------------------------------- 1 | import re 2 | import string 3 | import sys 4 | import textwrap 5 | 6 | import pytest 7 | from IPython.lib.pretty import pretty 8 | 9 | from galgebra.ga import lazy_dict, OrderedBiMap, GradedTuple 10 | from galgebra._utils import cached_property 11 | 12 | 13 | class TestOrderedBiMap: 14 | 15 | def test_inverse(self): 16 | d = OrderedBiMap([('one', 1), ('two', 2)]) 17 | assert d.inverse == OrderedBiMap([(1, 'one'), (2, 'two')]) 18 | assert d.inverse.inverse is d 19 | 20 | def test_annotation(self): 21 | # check that we can use this like a generic type 22 | def foo() -> OrderedBiMap[str, int]: 23 | pass 24 | 25 | 26 | class TestCachedProperty: 27 | 28 | def test_cache(self): 29 | 30 | class X: 31 | _val = 0 32 | @cached_property 33 | def val(self): 34 | try: 35 | return self._val 36 | finally: 37 | self._val += 1 38 | 39 | # property is computed only when the cache is clear 40 | x = X() 41 | assert x.val == 0 42 | assert x.val == 0 43 | del x.val 44 | assert x.val == 1 45 | assert x.val == 1 46 | del x.val 47 | assert x.val == 2 48 | assert x.val == 2 49 | 50 | @pytest.mark.skipif( 51 | sys.version_info < (3, 6), 52 | reason='__set_name__ was not added until Python 3.6' 53 | ) 54 | def test_annotation(self): 55 | class X: 56 | @cached_property 57 | def val(self) -> 'int': 58 | pass 59 | 60 | assert X.__annotations__['val'] == 'int' 61 | 62 | 63 | class TestLazyDict: 64 | 65 | def test_caching(self): 66 | seen = [] 67 | def f_value(k): 68 | seen.append(k) 69 | return len(seen) 70 | 71 | l = lazy_dict({'a': 0}, f_value) 72 | assert l['a'] == 0 73 | assert len(seen) == 0 74 | 75 | # should not call the function twice 76 | assert l['b'] == 1 77 | assert l['b'] == 1 78 | 79 | assert l['c'] == 2 80 | 81 | def test_repr(self): 82 | l = lazy_dict({'1': 1}, int) 83 | assert repr(l) == "lazy_dict({'1': 1}, f_value=)" 84 | 85 | # needs to be long enough to wrap 86 | l = lazy_dict({string.ascii_lowercase: string.ascii_lowercase }, int) 87 | assert pretty(l) == textwrap.dedent("""\ 88 | lazy_dict({'abcdefghijklmnopqrstuvwxyz': 'abcdefghijklmnopqrstuvwxyz'}, 89 | f_value=)""") 90 | 91 | 92 | class TestGradedTuple: 93 | 94 | def test_basic(self): 95 | t = GradedTuple(( 96 | ([0],), 97 | ([1], [1]), 98 | ([2],), 99 | )) 100 | assert isinstance(t, tuple) 101 | 102 | assert t.flat == ([0], [1], [1], [2]) 103 | with pytest.raises(AttributeError): 104 | t.flat = () 105 | -------------------------------------------------------------------------------- /test/test_printer.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import io 3 | import textwrap 4 | import sys 5 | 6 | import pytest 7 | from sympy import Symbol, Derivative 8 | 9 | from galgebra.printer import GaPrinter, GaLatexPrinter, oprint, _texify, Get_Program 10 | from galgebra.ga import Ga 11 | 12 | 13 | has_ordered_dictionaries = sys.version_info >= (3, 6) 14 | 15 | 16 | def test_latex_flg_GaPrinter(): 17 | g3d, e_1, e_2, e_3 = Ga.build('e*1|2|3') 18 | t = Symbol('theta') 19 | 20 | mv = t + 0*e_1 21 | 22 | # it shouldn't matter whether the latex printer is enabled, if we call 23 | # the non-latex one we should get a non latex result. 24 | assert GaPrinter().doprint(mv) == 'theta' 25 | GaLatexPrinter.redirect() 26 | try: 27 | assert GaPrinter().doprint(mv) == 'theta' 28 | finally: 29 | GaLatexPrinter.restore() 30 | 31 | 32 | def test_latex_flg_Symbol_sortkey(): 33 | """ 34 | Symbol.sort_key should not be affected by whether latex printing is enabled. 35 | 36 | `sort_key` affects the order of expressions returned by `sympy.simplify`. 37 | """ 38 | t = Symbol('theta') 39 | 40 | t_sort = t.sort_key() 41 | 42 | # sort key is cached, and we want to compare the behavior between the cache 43 | # being populated from within a latex context to it being populated from 44 | # outside it 45 | t.sort_key.cache_clear() 46 | 47 | GaLatexPrinter.redirect() 48 | try: 49 | t_latex_sort = t.sort_key() 50 | finally: 51 | GaLatexPrinter.restore() 52 | 53 | assert t_sort == t_latex_sort 54 | 55 | 56 | def test_deprecated_get_program(): 57 | with pytest.warns(DeprecationWarning): 58 | # returns nothing and does very little 59 | assert Get_Program() is None 60 | 61 | 62 | def test_oprint(): 63 | s = io.StringIO() 64 | with contextlib.redirect_stdout(s): 65 | oprint( 66 | 'int', 1, 67 | 'dictionary', dict(a=1, b=2), 68 | 'set', {1}, 69 | 'tuple', (1, 2), 70 | 'list', [1, 2, 3], 71 | 'str', 'a quote: "', 72 | 'deriv', Derivative(Symbol('x'), Symbol('x'), evaluate=False), 73 | ) 74 | 75 | if has_ordered_dictionaries: 76 | assert s.getvalue() == textwrap.dedent("""\ 77 | int = 1 78 | dictionary = {a: 1, b: 2} 79 | set = {1} 80 | tuple = (1, 2) 81 | list = [1, 2, 3] 82 | str = a quote: " 83 | deriv = D{x}x 84 | """) 85 | 86 | 87 | def test_oprint_dict_mode(): 88 | s = io.StringIO() 89 | with contextlib.redirect_stdout(s): 90 | oprint( 91 | 'int', 1, 92 | 'dictionary', dict(a=1, b=2), 93 | 'set', {1}, 94 | 'tuple', (1, 2), 95 | 'list', [1, 2, 3], 96 | 'str', 'a quote: "', 97 | dict_mode=True 98 | ) 99 | 100 | if has_ordered_dictionaries: 101 | assert s.getvalue() == textwrap.dedent("""\ 102 | int = 1 103 | dictionary: 104 | a -> 1 105 | b -> 2 106 | set = {1} 107 | tuple = (1, 2) 108 | list = [1, 2, 3] 109 | str = a quote: " 110 | """) 111 | 112 | 113 | def test_texify(): 114 | # operators 115 | assert _texify('a|b') == r'a\cdot b' 116 | assert _texify('a^b') == r'a\W b' 117 | assert _texify('a*b') == r'a b' 118 | assert _texify('ab') == r'a\lfloor b' 120 | assert _texify('a>>b') == r'a \times b' 121 | assert _texify('a<= '3.6' 10 | pytest >= 4.4.0; python_version >= '3.6' 11 | 12 | # our CI run disables tests on 3.5 using -k syntax that does not work in pytest 6 13 | pytest < 6; python_version < '3.6' 14 | --------------------------------------------------------------------------------