Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
599b513b8b |
@@ -1,10 +0,0 @@
|
||||
This folder currently holds ``durations.json`` and ``blacklisted.json`` which are used in our pytest configuration.
|
||||
``durations.json`` allows the two options ``--quickcheck`` and ``--veryquickcheck`` to be passed to ``pytest``.
|
||||
Currently, the list of slow tests is updated intermittently by running::
|
||||
|
||||
$ ./.ci/generate_durations_log.sh
|
||||
$ ./.ci/parse_durations_log.py
|
||||
$ git commit -am "pytest: Updated .ci/durations.json"
|
||||
|
||||
make sure you have a C compiler, a Fortran compiler, numpy, scipy, cython, matplotlib & sage installed (the latter can
|
||||
be tricky, in which case just make sure that no sage tests are removed in the git diff).
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash -e
|
||||
#!/bin/bash
|
||||
ABS_REPO_PATH=$(unset CDPATH && cd "$(dirname "$0")/.." && echo $PWD)
|
||||
cat <<EOF >${ABS_REPO_PATH}/.ci/blacklisted.json
|
||||
{
|
||||
@@ -10,4 +10,4 @@ cat <<EOF >${ABS_REPO_PATH}/.ci/blacklisted.json
|
||||
]
|
||||
}
|
||||
EOF
|
||||
${PYTHON:-python} -m pytest -ra --durations 0 --verbose | tee $ABS_REPO_PATH/.ci/durations.log
|
||||
python3 -m pytest -ra --durations 0 --verbose | tee $ABS_REPO_PATH/.ci/durations.log
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
custom: ['https://numfocus.salsalabs.org/donate-to-sympy/index.html']
|
||||
@@ -7,12 +7,9 @@
|
||||
# track a file that is ignored for some reason, you have to use
|
||||
# "git add -f". See "git help gitignore" for more information.
|
||||
|
||||
# Virtualenv
|
||||
/.venv/
|
||||
|
||||
# Regular Python bytecode file
|
||||
*.pyc
|
||||
__pycache__/
|
||||
|
||||
# Optimized Python bytecode file
|
||||
*.pyo
|
||||
@@ -20,12 +17,6 @@ __pycache__/
|
||||
# Vim's swap files
|
||||
*.sw[op]
|
||||
|
||||
# VSCode settings file
|
||||
.vscode/
|
||||
|
||||
# PyCharm settings file
|
||||
/.idea/
|
||||
|
||||
# Generated files from Jython
|
||||
*$py.class
|
||||
|
||||
@@ -79,7 +70,7 @@ sample.tex
|
||||
.ipynb_checkpoints/
|
||||
|
||||
# pytest cache folder
|
||||
.*cache
|
||||
.cache
|
||||
|
||||
# pytest related data file for slow tests
|
||||
.ci/durations.log
|
||||
|
||||
@@ -355,7 +355,6 @@ Peter Enenkel <peter.enenkel+git@gmail.com> <peter.enenkel+github@gmail.com>
|
||||
Jithin D. George <jithindgeorge93@gmail.com>
|
||||
Lev Chelyadinov <leva181777@gmail.com>
|
||||
Sourav Ghosh <souravghosh2197@gmail.com>
|
||||
Ethan Ward <etkewa@gmail.com> etkewa@gmail.com <qsRf9sGKy9rV>
|
||||
Ethan Ward <etkewa@gmail.com>
|
||||
Ethan Ward <etkewa@gmail.com> <ethanward@email.arizona.edu>
|
||||
Nilabja Bhattacharya <nilabja10201992@gmail.com>
|
||||
@@ -383,38 +382,3 @@ Ravi charan <ravicharan.vsp@gmail.com>
|
||||
Nityananda Gohain <nityanandagohain@gmail.com>
|
||||
Nicholas Bollweg <nick.bollweg@gmail.com> <nbollweg@continuum.io>
|
||||
Johan Blåbäck <johan_bluecreek@riseup.net> <johan.blaback@cea.fr>
|
||||
Adwait Baokar <adwaitbaokar18@gmail.com> abaokar-07 <adwaitbaokar18@gmail.com>
|
||||
Rahil Hastu <rahilhastu@gmail.com> rahil hastu <rahilhastu@gmail.com>
|
||||
Sidhant Nagpal <sidhantnagpal97@gmail.com> sidhantnagpal <sidhantnagpal97@gmail.com>
|
||||
Sidhant Nagpal <sidhantnagpal97@gmail.com> “sidhantnagpal” <sidhantnagpal97@gmail.com>
|
||||
Sidhant Nagpal <sidhantnagpal97@gmail.com> Sidhant Nagpal <36465988+sidhantnagpal@users.noreply.github.com>
|
||||
Nikoleta Glynatsi <GlynatsiNE@cardiff.ac.uk> Nikoleta Glynatsi <glynatsine@cardiff.ac.uk>
|
||||
Samyak Jain <samyak.jain2016a@vitstudent.ac.in> Samyak Jain <samtan106@gmail.com>
|
||||
Avi Shrivastava <shrivastavaavi123@gmail.com> avi <shrivastavaavi123@gmail.com>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in> czgdp1807 <gdp.1807@gmail.com>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in> czgdp1807 <36567889+czgdp1807@users.noreply.github.com>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in> czgdp1807 <czgdp1807@gmail.com>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in> MathLover <36567889+czgdp1807@users.noreply.github.com>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in> czgdp1807 <singh.23@iitj.ac.in>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in> Gagandeep Singh <36567889+czgdp1807@users.noreply.github.com>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in> Gagandeep Singh <czgdp1807@gmail.com>
|
||||
S.Y. Lee <sylee957@gmail.com> sylee957 <sylee957@gmail.com>
|
||||
Yatna Verma <yatnavermaa@gmail.com> yatna <yatnavermaa@gmail.com>
|
||||
Jared Lumpe <mjlumpe@gmail.com> Michael Jared Lumpe <mjlumpe@gmail.com>
|
||||
Austin Palmer <ap4000@nyu.edu> austin <ap4000@nyu.edu>
|
||||
Marduk Bolaños <mardukbp@mac.com> mardukbp <mardukbp@mac.com>
|
||||
amsuhane <ayushsuhane99@iitkgp.ac.in> amsuhane <“ayushsuhane99@iitkgp.ac.in”>
|
||||
Ritu Raj Singh <RituRajSingh878@gmail.com> Ritu Raj Singh <37741324+RituRajSingh878@users.noreply.github.com>
|
||||
Ritu Raj Singh <RituRajSingh878@gmail.com> RituRajSingh878 <RituRajSingh878@gmail.com>
|
||||
rationa-kunal <kunalgk1999@gmail.com> kunal <kunalgk1999@protonmail.com>
|
||||
shiksha11 <shiksharawat01@gmail.com> shiksha11 <33157995+shiksha11@users.noreply.github.com>
|
||||
Jogi Miglani <jmig5776@gmail.com> jmig5776 <jmig5776@gmail.com>
|
||||
Supreet Agrawal <supreet11agrawal@gmail.com> stm <supreet11agrawal@gmail.com>
|
||||
Bavish Kulur <bavishkulur@gmail.com> bavish2201 <bavishkulur@gmail.com>
|
||||
Divyanshu Thakur <divyanshu@iiitmanipur.ac.in> Divyanshu <divyanshu@iiitmanipur.ac.in>
|
||||
Shubham Kumar Jha <skjha832@gmail.com> ShubhamKJha <skjha832@gmail.com>
|
||||
Frédéric Chapoton <fchapoton2@gmail.com> fchapoton <fchapoton2@gmail.com>
|
||||
Salmista-94 <alejandrogroso@hotmail.com> alejandrogroso@hotmail.com <Salmista-94>
|
||||
Jack <ivanenko@ucu.edu.ua> LilJohny <ivanenko@ucu.edu.ua>
|
||||
Nabanita Dash <dashnabanita@gmail.com> Nabanita Dash <31562743+Naba7@users.noreply.github.com>
|
||||
Rajiv Ranjan Singh <rajivperfect007@gmail.com> Rajiv Ranjan Singh <42106787+iamrajiv@users.noreply.github.com>
|
||||
|
||||
@@ -1,69 +1,30 @@
|
||||
language: python
|
||||
sudo: false
|
||||
stages:
|
||||
- quality
|
||||
- baseline
|
||||
- test
|
||||
env:
|
||||
matrix:
|
||||
- SPLIT="1/2" TEST_SYMPY="true"
|
||||
- SPLIT="2/2" TEST_SYMPY="true"
|
||||
- TEST_DOCTESTS="true" FASTCACHE="false" TEST_SETUP="true" TEST_EXAMPLES="true"
|
||||
- TEST_DOCTESTS="true" FASTCACHE="false" TEST_SETUP="true"
|
||||
- SPLIT="1/4" TEST_SYMPY="true"
|
||||
- SPLIT="2/4" TEST_SYMPY="true"
|
||||
- SPLIT="3/4" TEST_SYMPY="true"
|
||||
- SPLIT="4/4" TEST_SYMPY="true"
|
||||
global:
|
||||
- secure: "YIEZal9EBTL+fg2YmoZoS8Bvt3eAVUOZjb38CtqpzR2CCSXWoUk35KG23m2NknlY1iKfYJyt7XWBszT/VKOQEbWQq7PIakV4vIByrWacgBxy1x3WC+rZoW7TX+JJiL+y942qIYbMoNMMB8xFpE5RDLSjSecMpFhJJXoafVTvju8="
|
||||
dist: trusty
|
||||
|
||||
python:
|
||||
- 2.7
|
||||
- 3.4
|
||||
- 3.5
|
||||
- 3.6
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- stage: quality
|
||||
python: 3.7
|
||||
dist: xenial
|
||||
sudo: true
|
||||
script: bin/test quality
|
||||
env:
|
||||
|
||||
- stage: baseline
|
||||
python: 3.7
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- TEST_DOCTESTS="true" FASTCACHE="false" TEST_SETUP="true" TEST_EXAMPLES="true"
|
||||
- python: 3.7
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- SPLIT="1/2" TEST_SYMPY="true"
|
||||
- python: 3.7
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- SPLIT="2/2" TEST_SYMPY="true"
|
||||
|
||||
- stage: test
|
||||
python: 3.8-dev
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- TEST_DOCTESTS="true" FASTCACHE="false" TEST_SETUP="true" TEST_EXAMPLES="true"
|
||||
- python: 3.8-dev
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- SPLIT="1/2" TEST_SYMPY="true"
|
||||
- python: 3.8-dev
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- SPLIT="2/2" TEST_SYMPY="true"
|
||||
- python: 2.7
|
||||
env:
|
||||
- TEST_ASCII="true"
|
||||
# space separated list of optional dependencies(conda packages) to install and test
|
||||
- TEST_OPT_DEPENDENCY="numpy scipy gmpy2 matplotlib>=2.2 theano llvmlite autowrap cython wurlitzer python-symengine=0.3.* tensorflow numexpr ipython antlr-python-runtime>=4.7,<4.8 antlr>=4.7,<4.8 cloudpickle python=2.7 pyglet pycosat python-clang"
|
||||
# autowrap installs libgfortran libgcc gcc cython
|
||||
- TEST_OPT_DEPENDENCY="numpy scipy gmpy2 matplotlib theano llvmlite autowrap python-symengine=0.3.* tensorflow numexpr ipython antlr-python-runtime>=4.7,<4.8 antlr>=4.7,<4.8"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -73,13 +34,9 @@ matrix:
|
||||
- liblapack-dev
|
||||
- gfortran
|
||||
- python: 3.6
|
||||
# This is actually 3.7 (once all the dependencies support it). We use
|
||||
# python: 3.6 here because 3.7 requires the slower xenial/sudo: true container,
|
||||
# and we aren't actually using the Travis Python anyway.
|
||||
env:
|
||||
- TEST_ASCII="true"
|
||||
- TEST_OPT_DEPENDENCY="numpy scipy gmpy2 matplotlib theano llvmlite autowrap cython wurlitzer python-symengine=0.3.* tensorflow numexpr ipython antlr-python-runtime>=4.7,<4.8 antlr>=4.7,<4.8 cloudpickle pyglet pycosat lfortran python-clang"
|
||||
- TEST_SAGE="true"
|
||||
- TEST_OPT_DEPENDENCY="numpy scipy gmpy2 matplotlib theano llvmlite autowrap python-symengine=0.3.* tensorflow numexpr ipython antlr-python-runtime>=4.7,<4.8 antlr>=4.7,<4.8"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -90,9 +47,7 @@ matrix:
|
||||
- gfortran
|
||||
- python-scipy
|
||||
|
||||
- python: 3.7
|
||||
dist: xenial
|
||||
sudo: true
|
||||
- python: 3.6
|
||||
env:
|
||||
- TEST_SPHINX="true"
|
||||
- FASTCACHE="false"
|
||||
@@ -114,97 +69,105 @@ matrix:
|
||||
- python: 2.7
|
||||
env:
|
||||
- TEST_SLOW="true"
|
||||
- SPLIT="1/2"
|
||||
- SPLIT="1/3"
|
||||
- python: 2.7
|
||||
env:
|
||||
- TEST_SLOW="true"
|
||||
- SPLIT="2/2"
|
||||
- python: 3.7
|
||||
dist: xenial
|
||||
sudo: true
|
||||
- SPLIT="2/3"
|
||||
- python: 2.7
|
||||
env:
|
||||
- TEST_SLOW="true"
|
||||
- SPLIT="1/2"
|
||||
- python: 3.7
|
||||
dist: xenial
|
||||
sudo: true
|
||||
- SPLIT="3/3"
|
||||
- python: 3.6
|
||||
env:
|
||||
- TEST_SLOW="true"
|
||||
- SPLIT="2/2"
|
||||
|
||||
# Code coverage tests
|
||||
- SPLIT="1/3"
|
||||
- python: 3.6
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- TEST_COVERAGE="true"
|
||||
- SPLIT="1/4"
|
||||
- TEST_SLOW="true"
|
||||
- SPLIT="2/3"
|
||||
- python: 3.6
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- TEST_COVERAGE="true"
|
||||
- SPLIT="2/4"
|
||||
- python: 3.6
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- TEST_COVERAGE="true"
|
||||
- SPLIT="3/4"
|
||||
- python: 3.6
|
||||
dist: xenial
|
||||
sudo: true
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- TEST_COVERAGE="true"
|
||||
- SPLIT="4/4"
|
||||
- TEST_SLOW="true"
|
||||
- SPLIT="3/3"
|
||||
|
||||
# Everything here and below is in the allow_failures. The need to be
|
||||
# duplicated here and in that section below.
|
||||
- python: "pypy"
|
||||
- python: 3.5 # Dummy value
|
||||
env:
|
||||
- TEST_DOCTESTS="true" TEST_EXAMPLES="true"
|
||||
- TEST_SAGE="true"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="1/2"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="2/2"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
sudo: true
|
||||
|
||||
fast_finish: true
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_DOCTESTS="true"
|
||||
- FASTCACHE="false"
|
||||
- TEST_SETUP="true"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="1/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="2/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="3/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="4/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
|
||||
allow_failures:
|
||||
# The apt installation of sage fails sometimes
|
||||
- python: 3.5 # Dummy value
|
||||
env:
|
||||
- TEST_SAGE="true"
|
||||
- FASTCACHE="false"
|
||||
sudo: true
|
||||
# PyPy randomly fails because of some PyPy bugs (Fatal RPython error: AssertionError)
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_DOCTESTS="true"
|
||||
- FASTCACHE="false"
|
||||
- TEST_SETUP="true"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -214,7 +177,7 @@ matrix:
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="1/2"
|
||||
- SPLIT="1/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
@@ -225,7 +188,29 @@ matrix:
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="2/2"
|
||||
- SPLIT="2/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="3/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pypy
|
||||
packages:
|
||||
- pypy
|
||||
- python: "pypy"
|
||||
env:
|
||||
- TEST_SYMPY="true"
|
||||
- SPLIT="4/4"
|
||||
- FASTCACHE="false"
|
||||
addons:
|
||||
apt:
|
||||
@@ -235,25 +220,19 @@ matrix:
|
||||
- pypy
|
||||
|
||||
before_install:
|
||||
- set -e
|
||||
- python -c "import fcntl; fcntl.fcntl(1, fcntl.F_SETFL, 0)"
|
||||
- if [[ "${FASTCACHE}" != "false" ]]; then
|
||||
pip install fastcache;
|
||||
fi
|
||||
- if [[ "${TEST_COVERAGE}" == "true" ]]; then
|
||||
pip install coverage;
|
||||
coverage debug sys;
|
||||
fi
|
||||
- if [ "$TRAVIS_PYTHON_VERSION" == "3.8-dev" ]; then
|
||||
pip uninstall -y Cython;
|
||||
- if [[ "${TEST_SPHINX}" == "true" ]]; then
|
||||
pip install "sphinx" "docutils" doctr;
|
||||
fi
|
||||
- |
|
||||
if [[ -n "${TEST_OPT_DEPENDENCY}" ]]; then
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" ]]; then
|
||||
# We do this conditionally because it saves us some downloading if the
|
||||
# version is the same.
|
||||
deactivate; # Deactivate the Travis virtualenv
|
||||
if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
||||
wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -q -O miniconda.sh;
|
||||
wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -q -O miniconda.sh;
|
||||
else
|
||||
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -q -O miniconda.sh;
|
||||
fi
|
||||
@@ -265,28 +244,19 @@ before_install:
|
||||
conda config --prepend channels conda-forge --prepend channels symengine/label/dev;
|
||||
|
||||
conda info -a;
|
||||
conda create -q -n test-environment ${TEST_OPT_DEPENDENCY};
|
||||
conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION pip ${TEST_OPT_DEPENDENCY/autowrap/libgfortran libgcc gcc cython};
|
||||
source activate test-environment;
|
||||
export CPATH=$CONDA_PREFIX/include;
|
||||
export LIBRARY_PATH=$CONDA_PREFIX/lib;
|
||||
export LD_LIBRARY_PATH=$CONDA_PREFIX/lib;
|
||||
export SYMPY_STRICT_COMPILER_CHECKS=1;
|
||||
conda clean --all;
|
||||
if [[ "$TEST_SAGE" == "true" ]]; then
|
||||
# Use a separate environment because sage downgrades matplotlib
|
||||
conda create -c conda-forge/label/cf201901 -n sage sagelib mpmath "ipython>=5.5.0,<6";
|
||||
conda clean --all;
|
||||
fi
|
||||
if [[ "$TRAVIS_PYTHON_VERSION" == "3.6" ]]; then
|
||||
conda install matchpy;
|
||||
fi
|
||||
elif [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then
|
||||
pip list | grep "numpy" && pip uninstall -y numpy;
|
||||
pip list --format=legacy | grep "numpy" && pip uninstall -y numpy;
|
||||
fi
|
||||
- if [[ "${TEST_SPHINX}" == "true" ]]; then
|
||||
pip install "sphinx" "docutils" doctr matplotlib sphinx-math-dollar;
|
||||
- if [[ "${TEST_SAGE}" == "true" ]]; then
|
||||
sudo apt-add-repository -y ppa:aims/sagemath;
|
||||
sudo apt-get update;
|
||||
sudo apt-get install -y sagemath-upstream-binary;
|
||||
fi
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" == "3.6" ]]; then
|
||||
pip install matchpy;
|
||||
fi
|
||||
|
||||
install:
|
||||
# If a command fails, fail the build.
|
||||
- set -e
|
||||
@@ -294,27 +264,22 @@ install:
|
||||
then virtualenv -p /usr/bin/pypy ~/.venv;
|
||||
. ~/.venv/bin/activate;
|
||||
fi
|
||||
# Once https://github.com/fredrik-johansson/mpmath/pull/403 is in a released
|
||||
# version of mpmath remove this line.
|
||||
- pip install mpmath
|
||||
# -We:invalid makes invalid escape sequences error in Python 3.6. See
|
||||
# -#12028.
|
||||
# SyntaxWarning flag for catching errors in Python3.8
|
||||
# Issue - #16973. -We:invalid can be dropped from 3.8 onwards, but
|
||||
# it needs to be there for earlier versions.
|
||||
- |
|
||||
if [[ "${TEST_SETUP}" == "true" ]]; then
|
||||
# The install cycle below is to test installation on systems without
|
||||
# setuptools.
|
||||
virtualenv ~/.venv-no-setuptools;
|
||||
~/.venv-no-setuptools/bin/pip install mpmath;
|
||||
~/.venv-no-setuptools/bin/pip uninstall -y setuptools;
|
||||
~/.venv-no-setuptools/bin/python -We:invalid setup.py -q install;
|
||||
if [[ "${TEST_SAGE}" != "true" ]]; then
|
||||
pip install mpmath;
|
||||
if [[ "${TEST_SETUP}" == "true" ]]; then
|
||||
# The install cycle below is to test installation on systems without setuptools.
|
||||
pip uninstall -y setuptools;
|
||||
python -We:invalid setup.py install;
|
||||
pip uninstall -y sympy;
|
||||
pip install --upgrade setuptools;
|
||||
fi
|
||||
python -We:invalid -m compileall -f sympy/;
|
||||
python -We:invalid setup.py install;
|
||||
pip list --format=columns;
|
||||
fi
|
||||
python -We:invalid -We::SyntaxWarning -m compileall -f -q sympy/;
|
||||
python -We:invalid setup.py -q install;
|
||||
pip list --format=columns;
|
||||
|
||||
script:
|
||||
# Don't run doctr if the build fails
|
||||
- set -e
|
||||
@@ -322,8 +287,5 @@ script:
|
||||
- if [[ "${TEST_SPHINX}" == "true" ]]; then
|
||||
doctr deploy dev --deploy-repo sympy/sympy_doc --command './generate_indexes.py';
|
||||
fi
|
||||
- if [[ "${TEST_COVERAGE}" == "true" ]]; then
|
||||
bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports";
|
||||
fi
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
@@ -4,7 +4,7 @@ those who explicitly didn't want to be mentioned. People with a * next
|
||||
to their names are not found in the metadata of the git history. This
|
||||
file is generated automatically by running `./bin/authors_update.py`.
|
||||
|
||||
There are a total of 822 authors.
|
||||
There are a total of 704 authors.
|
||||
|
||||
Ondřej Čertík <ondrej@certik.cz>
|
||||
Fabian Pedregosa <fabian@fseoane.net>
|
||||
@@ -710,121 +710,3 @@ Nityananda Gohain <nityanandagohain@gmail.com>
|
||||
Cédric Travelletti <cedrictravelletti@gmail.com>
|
||||
Nicholas Bollweg <nick.bollweg@gmail.com>
|
||||
Himanshu Ladia <hladia199811@gmail.com>
|
||||
eward <eward@sunbelt-medical.com>
|
||||
Adwait Baokar <adwaitbaokar18@gmail.com>
|
||||
Mihail Tarigradschi <m.tarigradschi@gmail.com>
|
||||
Saketh <alurusaisaketh@gmail.com>
|
||||
rushyam <rushyamsonu@gmail.com>
|
||||
sfoo <sfoohei@gmail.com>
|
||||
Rahil Hastu <rahilhastu@gmail.com>
|
||||
Zach Raines <raineszm@gmail.com>
|
||||
Sidhant Nagpal <sidhantnagpal97@gmail.com>
|
||||
Gagandeep Singh <singh.23@iitj.ac.in>
|
||||
Rishav Chakraborty <annonymousxyz@outlook.com>
|
||||
Malkhan Singh <malkhansinghrathaur@gmail.com>
|
||||
Joaquim Monserrat <qmonserrat@mailoo.org>
|
||||
Mayank Singh <mayank.singh081997@gmail.com>
|
||||
Rémy Léone <rleone@online.net>
|
||||
Maxence Mayrand <35958639+maxencemayrand@users.noreply.github.com>
|
||||
Nikoleta Glynatsi <GlynatsiNE@cardiff.ac.uk>
|
||||
helo9 <helo9@users.noreply.github.com>
|
||||
Ken Wakita <wakita@is.titech.ac.jp>
|
||||
Carl Sandrock <carl.sandrock@up.ac.za>
|
||||
Fredrik Eriksson <freeriks@student.chalmers.se>
|
||||
Ian Swire <oversizedpenguin@gmail.com>
|
||||
Bulat <daianovich@mail.ru>
|
||||
Ehren Metcalfe <ehren.m@gmail.com>
|
||||
Dmitry Savransky <dsavransky@gmail.com>
|
||||
Kiyohito Yamazaki <kyamaz@openql.org>
|
||||
Caley Finn <caleyreuben@gmail.com>
|
||||
zhouzq-thu <zzq_890709@hotmail.com>
|
||||
Alexander Pozdneev <pozdneev@users.noreply.github.com>
|
||||
Wes Turner <50891+westurner@users.noreply.github.com>
|
||||
JMSS-Unknown <31131631+JMSS-Unknown@users.noreply.github.com>
|
||||
Arshdeep Singh <singh.arshdeep1999@gmail.com>
|
||||
cym1 <16437732+cym1@users.noreply.github.com>
|
||||
Stewart Wadsworth <stewart.wadsworth@gmail.com>
|
||||
Jared Lumpe <mjlumpe@gmail.com>
|
||||
Avi Shrivastava <shrivastavaavi123@gmail.com>
|
||||
ramvenkat98 <ramvenkat98@gmail.com>
|
||||
Bilal Ahmed <b.ahmed0918@gmail.com>
|
||||
Dimas Abreu Archanjo Dutra <dimasad@ufmg.br>
|
||||
Yatna Verma <yatnavermaa@gmail.com>
|
||||
S.Y. Lee <sylee957@gmail.com>
|
||||
Miro Hrončok <miro@hroncok.cz>
|
||||
Sudarshan Kamath <sudarshan.kamath97@gmail.com>
|
||||
Ayushman Koul <ayushmankoul4570@gmail.com>
|
||||
Robert Dougherty-Bliss <robert.w.bliss@gmail.com>
|
||||
Andrey Grozin <A.G.Grozin@inp.nsk.su>
|
||||
Bavish Kulur <bavishkulur@gmail.com>
|
||||
Arun Singh <arunsin997@gmail.com>
|
||||
sirnicolaf <43586954+sirnicolaf@users.noreply.github.com>
|
||||
Zachariah Etienne <zachetie@gmail.com>
|
||||
Prayush Dawda <35144226+iamprayush@users.noreply.github.com>
|
||||
2torus <boris.ettinger@gmail.com>
|
||||
Faisal Riyaz <faisalriyaz011@gmail.com>
|
||||
Martin Roelfs <u0114255@kuleuven.be>
|
||||
SirJohnFranklin <sirjfu@googlemail.com>
|
||||
Anthony Sottile <asottile@umich.edu>
|
||||
ViacheslavP <public.viacheslav@gmail.com>
|
||||
Safiya03 <safiyanesar@gmail.com>
|
||||
Alexander Dunlap <alexander.dunlap@gmail.com>
|
||||
Rohit Sharma <31184621+rohitx007@users.noreply.github.com>
|
||||
Jonathan Warner <warnerjon12@gmail.com>
|
||||
Mohitbalwani26 <44258119+Mohitbalwani26@users.noreply.github.com>
|
||||
Marduk Bolaños <mardukbp@mac.com>
|
||||
amsuhane <ayushsuhane99@iitkgp.ac.in>
|
||||
Matthias Geier <Matthias.Geier@gmail.com>
|
||||
klaasvanaarsen <44929042+klaasvanaarsen@users.noreply.github.com>
|
||||
Shubham Kumar Jha <skjha832@gmail.com>
|
||||
rationa-kunal <kunalgk1999@gmail.com>
|
||||
Animesh Sinha <animeshsinha1309@gmail.com>
|
||||
Gaurang Tandon <1gaurangtandon@gmail.com>
|
||||
Matthew Craven <clyring@users.noreply.github.com>
|
||||
Daniel Ingram <ingramds@appstate.edu>
|
||||
Jogi Miglani <jmig5776@gmail.com>
|
||||
Takumasa Nakamura <n.takumasa@gmail.com>
|
||||
Ritu Raj Singh <RituRajSingh878@gmail.com>
|
||||
Rajiv Ranjan Singh <rajivperfect007@gmail.com>
|
||||
Vera Lozhkina <veralozhkina@gmail.com>
|
||||
adhoc-king <46354827+adhoc-king@users.noreply.github.com>
|
||||
Mikel Rouco <mikel.mrm@gmail.com>
|
||||
Oscar Gustafsson <oscar.gustafsson@gmail.com>
|
||||
damianos <damianos@semmle.com>
|
||||
Supreet Agrawal <supreet11agrawal@gmail.com>
|
||||
shiksha11 <shiksharawat01@gmail.com>
|
||||
Martin Ueding <dev@martin-ueding.de>
|
||||
sharma-kunal <kunalsharma6914@gmail.com>
|
||||
Divyanshu Thakur <divyanshu@iiitmanipur.ac.in>
|
||||
Susumu Ishizuka <susumu.ishizuka@kii.com>
|
||||
Samnan Rahee <namanush.rsr.16@gmail.com>
|
||||
Fredrik Andersson <fredrik.andersson@fcc.chalmers.se>
|
||||
Bhavya Srivastava <bhavya17037@iiitd.ac.in>
|
||||
Alpesh Jamgade <alpeshjamgade21@gmail.com>
|
||||
Shubham Abhang <shubhamabhang77@gmail.com>
|
||||
Vishesh Mangla <manglavishesh64@gmail.com>
|
||||
Nicko van Someren <nicko@nicko.org>
|
||||
dandiez <47832466+dandiez@users.noreply.github.com>
|
||||
Frédéric Chapoton <fchapoton2@gmail.com>
|
||||
jhanwar <f2015463@pilani.bits-pilani.ac.in>
|
||||
Noumbissi valere Gille Geovan <noumbissivalere@gmail.com>
|
||||
Salmista-94 <alejandrogroso@hotmail.com>
|
||||
Shivani Kohli <shivanikohli.09@gmail.com>
|
||||
Parker Berry <parker.berry@marquette.edu>
|
||||
Pragyan Mehrotra <pragyan18168@iiitd.ac.in>
|
||||
Nabanita Dash <dashnabanita@gmail.com>
|
||||
Gaetano Guerriero <x.guerriero@tin.it>
|
||||
Ankit Pandey <pandeyan@grinnell.edu>
|
||||
Ritesh Kumar <ritesh99rakesh@gmail.com>
|
||||
kkkkx <709563092@qq.com>
|
||||
wate123 <junlin0604@gmail.com>
|
||||
Corwinpro <corwinat@gmail.com>
|
||||
Anway De <anway1756@gmail.com>
|
||||
znxftw <vishnu2101@gmail.com>
|
||||
Jack <ivanenko@ucu.edu.ua>
|
||||
OrestisVaggelis <orestis22000@gmail.com>
|
||||
Nikhil Maan <nikhilmaan22@gmail.com>
|
||||
Abhinav Anand <abhinav.anand2807@gmail.com>
|
||||
sqs <googol.sqs@gmail.com>
|
||||
Juan Barbosa <js.barbosa10@uniandes.edu.co>
|
||||
Prionti Nasir <pdn3628@rit.edu>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to make participation in our project and
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
@@ -48,13 +48,13 @@ threatening, offensive, or harmful.
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account or acting as an appointed
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing or otherwise unacceptable behavior may be
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting one of the project maintainers at asmeurer@gmail.com or
|
||||
ondrej.certik@gmail.com. All complaints will be reviewed and investigated and
|
||||
will result in a response that is deemed necessary and appropriate to the
|
||||
@@ -69,7 +69,7 @@ members of the project's leadership.
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [https://contributor-covenant.org/version/1/4][version]
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: https://contributor-covenant.org
|
||||
[version]: https://contributor-covenant.org/version/1/4/
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2006-2019 SymPy Development Team
|
||||
Copyright (c) 2006-2018 SymPy Development Team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
@@ -29,7 +29,7 @@ DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Patches that were taken from the Diofant project (https://github.com/diofant/diofant)
|
||||
Patches taken from the Diofant project (https://github.com/diofant/diofant)
|
||||
are licensed as:
|
||||
|
||||
Copyright (c) 2006-2017 SymPy Development Team,
|
||||
@@ -45,7 +45,7 @@ modification, are permitted provided that the following conditions are met:
|
||||
b. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
c. Neither the name of Diofant or SymPy nor the names of its contributors
|
||||
c. Neither the name of Diofant, or SymPy nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
@@ -64,7 +64,7 @@ DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Submodules taken from the multipledispatch project (https://github.com/mrocklin/multipledispatch)
|
||||
Submodule taken from the multipledispatch project (https://github.com/mrocklin/multipledispatch)
|
||||
are licensed as:
|
||||
|
||||
Copyright (c) 2014 Matthew Rocklin
|
||||
|
||||
@@ -5,11 +5,9 @@ recursive-include examples *.py README
|
||||
|
||||
include sympy/utilities/mathml/data/*.xsl
|
||||
|
||||
recursive-include sympy/parsing/latex *.g4 *.txt
|
||||
recursive-include sympy/parsing/autolev *.g4 *.al
|
||||
recursive-include sympy/parsing/latex *.g4 *.tokens *.interp *.txt
|
||||
|
||||
include LICENSE
|
||||
include TODO
|
||||
include AUTHORS
|
||||
include README.rst
|
||||
include bin/isympy
|
||||
|
||||
@@ -4,24 +4,10 @@ was changed. Do not include the issue number in the title. -->
|
||||
#### References to other Issues or PRs
|
||||
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
|
||||
format, e.g. "Fixes #1234". See
|
||||
https://github.com/blog/1506-closing-issues-via-pull-requests . Please also
|
||||
write a comment on that issue linking back to this pull request once it is
|
||||
open. -->
|
||||
https://github.com/blog/1506-closing-issues-via-pull-requests .-->
|
||||
|
||||
|
||||
#### Brief description of what is fixed or changed
|
||||
|
||||
|
||||
#### Other comments
|
||||
|
||||
|
||||
#### Release Notes
|
||||
|
||||
<!-- Write the release notes for this release below. See
|
||||
https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more information
|
||||
on how to write release notes. The bot will check your release notes
|
||||
automatically to see if they are formatted correctly. -->
|
||||
|
||||
<!-- BEGIN RELEASE NOTES -->
|
||||
|
||||
<!-- END RELEASE NOTES -->
|
||||
|
||||
@@ -6,7 +6,7 @@ SymPy
|
||||
.. |pypi version| image:: https://img.shields.io/pypi/v/sympy.svg
|
||||
:target: https://pypi.python.org/pypi/sympy
|
||||
.. |Build status| image:: https://secure.travis-ci.org/sympy/sympy.svg?branch=master
|
||||
:target: https://travis-ci.org/sympy/sympy
|
||||
:target: http://travis-ci.org/sympy/sympy
|
||||
.. |Gitter Badge| image:: https://badges.gitter.im/Join%20Chat.svg
|
||||
:alt: Join the chat at https://gitter.im/sympy/sympy
|
||||
:target: https://gitter.im/sympy/sympy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
@@ -15,7 +15,7 @@ SymPy
|
||||
|
||||
A Python library for symbolic mathematics.
|
||||
|
||||
https://sympy.org/
|
||||
http://sympy.org/
|
||||
|
||||
See the AUTHORS file for the list of authors.
|
||||
|
||||
@@ -36,10 +36,7 @@ to ask us anything there. We have a very welcoming and helpful community.
|
||||
Download
|
||||
--------
|
||||
|
||||
The recommended installation method is through Anaconda,
|
||||
https://www.anaconda.com/download/
|
||||
|
||||
You can also get the latest version of SymPy from
|
||||
Get the latest version of SymPy from
|
||||
https://pypi.python.org/pypi/sympy/
|
||||
|
||||
To get the git version do
|
||||
@@ -49,14 +46,14 @@ To get the git version do
|
||||
$ git clone git://github.com/sympy/sympy.git
|
||||
|
||||
For other options (tarballs, debs, etc.), see
|
||||
https://docs.sympy.org/dev/install.html.
|
||||
http://docs.sympy.org/dev/install.html.
|
||||
|
||||
Documentation and usage
|
||||
-----------------------
|
||||
|
||||
Everything is at:
|
||||
|
||||
https://docs.sympy.org/
|
||||
http://docs.sympy.org/
|
||||
|
||||
You can generate everything at the above site in your local copy of SymPy by::
|
||||
|
||||
@@ -82,7 +79,7 @@ To start it, issue::
|
||||
|
||||
$ bin/isympy
|
||||
|
||||
from this directory, if SymPy is not installed or simply::
|
||||
from this directory if SymPy is not installed or simply::
|
||||
|
||||
$ isympy
|
||||
|
||||
@@ -91,7 +88,7 @@ if SymPy is installed.
|
||||
Installation
|
||||
------------
|
||||
|
||||
SymPy has a hard dependency on the `mpmath <http://mpmath.org/>`_
|
||||
SymPy has a hard dependency on the `mpmath <http://mpmath.org/>`
|
||||
library (version >= 0.19). You should install it first, please refer to
|
||||
the mpmath installation guide:
|
||||
|
||||
@@ -105,7 +102,7 @@ If you install it system-wide, you may need to prefix the previous command with
|
||||
|
||||
$ sudo python setup.py install
|
||||
|
||||
See https://docs.sympy.org/dev/install.html for more information.
|
||||
See http://docs.sympy.org/dev/install.html for more information.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
@@ -138,8 +135,7 @@ To test pull requests, use `sympy-bot <https://github.com/sympy/sympy-bot>`_.
|
||||
|
||||
Regenerate Experimental `\LaTeX` Parser/Lexer
|
||||
---------------------------------------------
|
||||
|
||||
The parser and lexer generated with the `ANTLR4 <http://antlr4.org>`_ toolchain
|
||||
The parser and lexer generated with the `ANTLR4 <http://antlr4.org`_ toolchain
|
||||
in `sympy/parsing/latex/_antlr` and checked into the repo. Presently, most
|
||||
users should not need to regenerate these files, but if you plan to work on
|
||||
this feature, you will need the `antlr4` command line tool available. One way
|
||||
@@ -151,6 +147,16 @@ After making changes to `sympy/parsing/latex/LaTeX.g4`, run::
|
||||
|
||||
$ ./setup.py antlr
|
||||
|
||||
Usage in Python 3
|
||||
-----------------
|
||||
|
||||
SymPy also supports Python 3. If you want to install the latest version in
|
||||
Python 3, get the Python 3 tarball from
|
||||
https://pypi.python.org/pypi/sympy/
|
||||
|
||||
To install the SymPy for Python 3, simply run the above commands with a Python
|
||||
3 interpreter.
|
||||
|
||||
Clean
|
||||
-----
|
||||
|
||||
@@ -188,11 +194,11 @@ Brief History
|
||||
-------------
|
||||
|
||||
SymPy was started by Ondřej Čertík in 2005, he wrote some code during the
|
||||
summer, then he wrote some more code during summer 2006. In February 2007,
|
||||
summer, then he wrote some more code during the summer 2006. In February 2007,
|
||||
Fabian Pedregosa joined the project and helped fixed many things, contributed
|
||||
documentation and made it alive again. 5 students (Mateusz Paprocki, Brian
|
||||
Jorgensen, Jason Gedge, Robert Schwarz, and Chris Wu) improved SymPy incredibly
|
||||
during summer 2007 as part of the Google Summer of Code. Pearu Peterson
|
||||
Jorgensen, Jason Gedge, Robert Schwarz and Chris Wu) improved SymPy incredibly
|
||||
during the summer 2007 as part of the Google Summer of Code. Pearu Peterson
|
||||
joined the development during the summer 2007 and he has made SymPy much more
|
||||
competitive by rewriting the core from scratch, that has made it from 10x to
|
||||
100x faster. Jurjen N.E. Bos has contributed pretty printing and other patches.
|
||||
@@ -205,16 +211,16 @@ from Google Summer of Code students.
|
||||
|
||||
In 2011, Ondřej Čertík stepped down as lead developer, with Aaron Meurer, who
|
||||
also started as a Google Summer of Code student, taking his place. Ondřej
|
||||
Čertík is still active in the community but is too busy with work and family
|
||||
Čertík is still active in the community, but is too busy with work and family
|
||||
to play a lead development role.
|
||||
|
||||
Since then, a lot more people have joined the development and some people have
|
||||
also left. You can see the full list in doc/src/aboutus.rst, or online at:
|
||||
|
||||
https://docs.sympy.org/dev/aboutus.html#sympy-development-team
|
||||
http://docs.sympy.org/dev/aboutus.html#sympy-development-team
|
||||
|
||||
The git history goes back to 2007 when development moved from svn to hg. To
|
||||
see the history before that point, look at https://github.com/sympy/sympy-old.
|
||||
The git history goes back to 2007, when development moved from svn to hg. To
|
||||
see the history before that point, look at http://github.com/sympy/sympy-old.
|
||||
|
||||
You can use git to see the biggest developers. The command::
|
||||
|
||||
@@ -244,12 +250,12 @@ A BibTeX entry for LaTeX users is
|
||||
|
||||
@article{10.7717/peerj-cs.103,
|
||||
title = {SymPy: symbolic computing in Python},
|
||||
author = {Meurer, Aaron and Smith, Christopher P. and Paprocki, Mateusz and \v{C}ert\'{i}k, Ond\v{r}ej and Kirpichev, Sergey B. and Rocklin, Matthew and Kumar, Amit and Ivanov, Sergiu and Moore, Jason K. and Singh, Sartaj and Rathnayake, Thilina and Vig, Sean and Granger, Brian E. and Muller, Richard P. and Bonazzi, Francesco and Gupta, Harsh and Vats, Shivam and Johansson, Fredrik and Pedregosa, Fabian and Curry, Matthew J. and Terrel, Andy R. and Rou\v{c}ka, \v{S}t\v{e}p\'{a}n and Saboo, Ashutosh and Fernando, Isuru and Kulal, Sumith and Cimrman, Robert and Scopatz, Anthony},
|
||||
author = {Meurer, Aaron and Smith, Christopher P. and Paprocki, Mateusz and \v{C}ert\'{i}k, Ond\v{r}ej and Kirpichev, Sergey B. and Rocklin, Matthew and Kumar, AMiT and Ivanov, Sergiu and Moore, Jason K. and Singh, Sartaj and Rathnayake, Thilina and Vig, Sean and Granger, Brian E. and Muller, Richard P. and Bonazzi, Francesco and Gupta, Harsh and Vats, Shivam and Johansson, Fredrik and Pedregosa, Fabian and Curry, Matthew J. and Terrel, Andy R. and Rou\v{c}ka, \v{S}t\v{e}p\'{a}n and Saboo, Ashutosh and Fernando, Isuru and Kulal, Sumith and Cimrman, Robert and Scopatz, Anthony},
|
||||
year = 2017,
|
||||
month = jan,
|
||||
keywords = {Python, Computer algebra system, Symbolics},
|
||||
abstract = {
|
||||
SymPy is an open source computer algebra system written in pure Python. It is built with a focus on extensibility and ease of use, through both interactive and programmatic applications. These characteristics have led SymPy to become a popular symbolic library for the scientific Python ecosystem. This paper presents the architecture of SymPy, a description of its features, and a discussion of select submodules. The supplementary material provides additional examples and further outline details of the architecture and features of SymPy.
|
||||
SymPy is an open source computer algebra system written in pure Python. It is built with a focus on extensibility and ease of use, through both interactive and programmatic applications. These characteristics have led SymPy to become a popular symbolic library for the scientific Python ecosystem. This paper presents the architecture of SymPy, a description of its features, and a discussion of select submodules. The supplementary material provide additional examples and further outline details of the architecture and features of SymPy.
|
||||
},
|
||||
volume = 3,
|
||||
pages = {e103},
|
||||
|
||||
@@ -20,7 +20,7 @@ if sys.version_info < (3, 6):
|
||||
|
||||
from subprocess import run, PIPE
|
||||
from distutils.version import LooseVersion
|
||||
from collections import OrderedDict
|
||||
from collections import defaultdict, OrderedDict
|
||||
|
||||
def red(text):
|
||||
return "\033[31m%s\033[0m" % text
|
||||
@@ -47,6 +47,8 @@ git_ver = run(['git', '--version'], stdout=PIPE, encoding='utf-8').stdout[12:]
|
||||
if LooseVersion(git_ver) < LooseVersion(minimal):
|
||||
print(yellow("Please use a git version >= %s" % minimal))
|
||||
|
||||
from sympy.utilities.misc import filldedent
|
||||
|
||||
def author_name(line):
|
||||
assert line.count("<") == line.count(">") == 1
|
||||
assert line.endswith(">")
|
||||
@@ -90,10 +92,6 @@ try:
|
||||
# this will fail if the .mailmap is not right
|
||||
assert 'Sergey B Kirpichev' == author_name(git_people.pop(226)
|
||||
), 'Sergey B Kirpichev was not found at line 226.'
|
||||
assert 'azure-pipelines[bot]' == \
|
||||
author_name(git_people.pop(751)), 'azure-pipelines[bot] was not found at line 751'
|
||||
assert 'whitesource-bolt-for-github[bot]' == \
|
||||
author_name(git_people.pop(792)), 'whitesource-bolt-for-github[bot] not found at line 792'
|
||||
except AssertionError as msg:
|
||||
print(red(msg))
|
||||
sys.exit(1)
|
||||
@@ -152,5 +150,3 @@ if new_authors:
|
||||
print()
|
||||
for i in sorted(new_authors, key=lambda x: x.lower()):
|
||||
print('\t%s' % i)
|
||||
else:
|
||||
print(yellow("The AUTHORS file was updated."))
|
||||
|
||||
@@ -30,9 +30,6 @@ except ImportError:
|
||||
# It's html.parser in Python 3
|
||||
from html.parser import HTMLParser
|
||||
|
||||
from sympy.utilities.misc import filldedent
|
||||
|
||||
|
||||
# Load color templates, used from sympy/utilities/runtests.py
|
||||
color_templates = (
|
||||
("Black", "0;30"),
|
||||
@@ -313,21 +310,14 @@ def process_function(name, c_name, b_obj, mod_path, f_sk, f_md, f_mdt, f_idt,
|
||||
if name.startswith('_'):
|
||||
f_sk.append(full_name)
|
||||
else:
|
||||
doc = obj.__doc__
|
||||
if type(doc) is str:
|
||||
if not doc:
|
||||
add_md = True
|
||||
elif not '>>>' in doc:
|
||||
add_mdt = True
|
||||
elif _is_indirect(name, doc):
|
||||
add_idt = True
|
||||
else:
|
||||
f_doctest = True
|
||||
elif doc is None:
|
||||
# this was a function defined in the docstring
|
||||
f_doctest = True
|
||||
if not obj.__doc__:
|
||||
add_md = True
|
||||
elif not '>>>' in obj.__doc__:
|
||||
add_mdt = True
|
||||
elif _is_indirect(name, obj.__doc__):
|
||||
add_idt = True
|
||||
else:
|
||||
assert None, type(doc)
|
||||
f_doctest = True
|
||||
|
||||
function = True
|
||||
|
||||
@@ -380,23 +370,15 @@ def process_class(c_name, obj, c_sk, c_md, c_mdt, c_idt, c_has_doctest,
|
||||
|
||||
c = True
|
||||
full_name = "LINE %d: %s" % (line_no, c_name)
|
||||
doc = obj.__doc__
|
||||
if type(doc) is str:
|
||||
if not doc:
|
||||
c_md.append(full_name)
|
||||
elif not '>>>' in doc:
|
||||
c_mdt.append(full_name)
|
||||
elif _is_indirect(c_name, doc):
|
||||
c_idt.append(full_name)
|
||||
else:
|
||||
c_dt = True
|
||||
c_has_doctest.append(full_name)
|
||||
elif doc is None:
|
||||
# this was a class defined in the docstring
|
||||
if not obj.__doc__:
|
||||
c_md.append(full_name)
|
||||
elif not '>>>' in obj.__doc__:
|
||||
c_mdt.append(full_name)
|
||||
elif _is_indirect(c_name, obj.__doc__):
|
||||
c_idt.append(full_name)
|
||||
else:
|
||||
c_dt = True
|
||||
c_has_doctest.append(full_name)
|
||||
else:
|
||||
assert None, type(doc)
|
||||
|
||||
in_sphinx = False
|
||||
if sphinx:
|
||||
@@ -453,7 +435,7 @@ def coverage(module_path, verbose=False, no_color=False, sphinx=True):
|
||||
if member in skip_members:
|
||||
continue
|
||||
|
||||
# Identify if the member (class/def) is a part of this module
|
||||
# Identify if the member (class/def) a part of this module
|
||||
obj = getattr(m, member)
|
||||
obj_mod = inspect.getmodule(obj)
|
||||
|
||||
@@ -552,10 +534,6 @@ def coverage(module_path, verbose=False, no_color=False, sphinx=True):
|
||||
|
||||
|
||||
def go(sympy_top, file, verbose=False, no_color=False, exact=True, sphinx=True):
|
||||
|
||||
# file names containing any string in skip_paths will be skipped,
|
||||
skip_paths = []
|
||||
|
||||
if os.path.isdir(file):
|
||||
doctests, total_sphinx, num_functions = 0, 0, 0
|
||||
for F in os.listdir(file):
|
||||
@@ -606,11 +584,10 @@ if __name__ == "__main__":
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.sphinx and not os.path.exists(os.path.join(sympy_top, 'doc', '_build', 'html')):
|
||||
print(filldedent("""
|
||||
Cannot check Sphinx coverage without a documentation build.
|
||||
To build the docs, run "cd doc; make html". To skip
|
||||
checking Sphinx coverage, pass --no-sphinx.
|
||||
"""))
|
||||
print("""
|
||||
Cannot check Sphinx coverage without a documentation build. To build the
|
||||
docs, run "cd doc; make html". To skip checking Sphinx coverage, pass --no-sphinx.
|
||||
""")
|
||||
sys.exit(1)
|
||||
|
||||
full_coverage = True
|
||||
|
||||
@@ -27,7 +27,7 @@ from __future__ import print_function
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from argparse import ArgumentParser
|
||||
from optparse import OptionParser
|
||||
|
||||
minver = '3.4'
|
||||
try:
|
||||
@@ -37,10 +37,12 @@ try:
|
||||
except ImportError:
|
||||
print(
|
||||
"You need to install module coverage (version %s or newer required).\n"
|
||||
"See https://coverage.readthedocs.io/en/latest/ or \n"
|
||||
"See http://nedbatchelder.com/code/coverage/ or \n"
|
||||
"https://launchpad.net/ubuntu/+source/python-coverage/" % minver)
|
||||
sys.exit(-1)
|
||||
|
||||
REPORT_DIR = "covhtml"
|
||||
REFRESH = False
|
||||
|
||||
omit_dir_patterns = ['.*tests', 'benchmark', 'examples',
|
||||
'pyglet', 'test_external']
|
||||
@@ -58,13 +60,13 @@ def generate_covered_files(top_dir):
|
||||
yield os.path.join(dirpath, filename)
|
||||
|
||||
|
||||
def make_report(
|
||||
test_args, source_dir='sympy/', report_dir='covhtml', use_cache=False,
|
||||
slow=False
|
||||
):
|
||||
def make_report(source_dir, report_dir, use_cache=False, slow=False):
|
||||
# code adapted from /bin/test
|
||||
from get_sympy import path_hack
|
||||
sympy_top = path_hack()
|
||||
bin_dir = os.path.abspath(os.path.dirname(__file__)) # bin/
|
||||
sympy_top = os.path.split(bin_dir)[0] # ../
|
||||
sympy_dir = os.path.join(sympy_top, 'sympy') # ../sympy/
|
||||
if os.path.isdir(sympy_dir):
|
||||
sys.path.insert(0, sympy_top)
|
||||
os.chdir(sympy_top)
|
||||
|
||||
cov = coverage.coverage()
|
||||
@@ -77,43 +79,40 @@ def make_report(
|
||||
cov.erase()
|
||||
cov.start()
|
||||
import sympy
|
||||
sympy.test(*test_args, subprocess=False, slow=slow)
|
||||
sympy.test(source_dir, subprocess=False)
|
||||
if slow:
|
||||
sympy.test(source_dir, subprocess=False, slow=slow)
|
||||
#sympy.doctest() # coverage doesn't play well with doctests
|
||||
cov.stop()
|
||||
try:
|
||||
cov.save()
|
||||
except PermissionError:
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"PermissionError has been raised while saving the " \
|
||||
"coverage result.",
|
||||
RuntimeWarning
|
||||
)
|
||||
cov.save()
|
||||
|
||||
covered_files = list(generate_covered_files(source_dir))
|
||||
|
||||
if report_dir in os.listdir(os.curdir):
|
||||
for f in os.listdir(report_dir):
|
||||
if f.split('.')[-1] in ['html', 'css', 'js']:
|
||||
os.remove(os.path.join(report_dir, f))
|
||||
|
||||
cov.html_report(morfs=covered_files, directory=report_dir)
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument(
|
||||
'-c', '--use-cache', action='store_true', default=False,
|
||||
help='Use cached data.')
|
||||
parser.add_argument(
|
||||
'-d', '--report-dir', default='covhtml',
|
||||
help='Directory to put the generated report in.')
|
||||
parser.add_argument(
|
||||
"--slow", action="store_true", dest="slow", default=False,
|
||||
help="Run slow functions also.")
|
||||
options, args = parser.parse_known_args()
|
||||
|
||||
if __name__ == '__main__':
|
||||
report_dir = options.report_dir
|
||||
use_cache = options.use_cache
|
||||
slow = options.slow
|
||||
make_report(
|
||||
args, report_dir=report_dir, use_cache=use_cache, slow=slow)
|
||||
parser = OptionParser()
|
||||
parser.add_option('-c', '--use-cache', action='store_true', default=False,
|
||||
help='Use cached data.')
|
||||
parser.add_option('-d', '--report-dir', default='covhtml',
|
||||
help='Directory to put the generated report in.')
|
||||
parser.add_option("--slow", action="store_true", dest="slow",
|
||||
default=False, help="Run slow functions also.")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if args:
|
||||
source_dir = args[0]
|
||||
else:
|
||||
source_dir = 'sympy/'
|
||||
|
||||
make_report(source_dir, **options.__dict__)
|
||||
|
||||
print("The generated coverage report is in covhtml directory.")
|
||||
print(
|
||||
"Open %s in your web browser to view the report" %
|
||||
os.sep.join([report_dir, 'index.html'])
|
||||
)
|
||||
print("Open %s in your web browser to view the report" % os.sep.join(
|
||||
'sympy covhtml index.html'.split()))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Program to execute doctests using the py.test like interface.
|
||||
|
||||
The advantage over py.test is that it only depends on sympy and should just
|
||||
work in any circumstances. See "sympy.doctest?" for documentation.
|
||||
work in any circumstances. See "sympy.dotest?" for documentation.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
A tool to help keep .mailmap up-to-date with the
|
||||
current git authors.
|
||||
@@ -49,11 +50,6 @@ def author_name(line):
|
||||
assert line.endswith(">")
|
||||
return line.split("<", 1)[0].strip()
|
||||
|
||||
def author_email(line):
|
||||
assert line.count("<") == line.count(">") == 1
|
||||
assert line.endswith(">")
|
||||
return line.split("<", 1)[1][:-1].strip()
|
||||
|
||||
sysexit = 0
|
||||
print(blue("checking git authors..."))
|
||||
|
||||
@@ -120,41 +116,6 @@ if multi:
|
||||
for e in sorted(dups[k]):
|
||||
print('\t%s' % e)
|
||||
|
||||
bad_names = []
|
||||
bad_emails = []
|
||||
for i in git_people:
|
||||
name = author_name(i)
|
||||
email = author_email(i)
|
||||
if '@' in name:
|
||||
bad_names.append(i)
|
||||
elif '@' not in email:
|
||||
bad_emails.append(i)
|
||||
if bad_names:
|
||||
print()
|
||||
print(yellow(filldedent("""
|
||||
The following people appear to have an email address
|
||||
listed for their name. Entries should be added to
|
||||
.mailmap so that names are formatted like
|
||||
"Name <email address>".
|
||||
""")))
|
||||
for i in bad_names:
|
||||
print("\t%s" % i)
|
||||
|
||||
# TODO: Should we check for bad emails as well? Some people have empty email
|
||||
# addresses. The above check seems to catch people who get the name and email
|
||||
# backwards, so let's leave this alone for now.
|
||||
|
||||
# if bad_emails:
|
||||
# print()
|
||||
# print(yellow(filldedent("""
|
||||
# The following names do not appear to have valid
|
||||
# emails. Entries should be added to .mailmap that
|
||||
# use a proper email address. If there is no email
|
||||
# address for a person, use "none@example.com".
|
||||
# """)))
|
||||
# for i in bad_emails:
|
||||
# print("\t%s" % i)
|
||||
|
||||
print()
|
||||
print(blue("checking .mailmap..."))
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from __future__ import print_function
|
||||
from sympy.core.compatibility import string_types
|
||||
|
||||
import time
|
||||
import timeit
|
||||
@@ -64,7 +63,7 @@ class TreeNode(object):
|
||||
self.print_generic(n, method="exclusive_time")
|
||||
|
||||
def write_cachegrind(self, f):
|
||||
if isinstance(f, string_types):
|
||||
if isinstance(f, str):
|
||||
f = open(f, "w")
|
||||
f.write("events: Microseconds\n")
|
||||
f.write("fl=sympyallimport\n")
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Test that only executable files have an executable bit set
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from get_sympy import path_hack
|
||||
base_dir = path_hack()
|
||||
|
||||
def test_executable(path):
|
||||
if not os.path.isdir(path):
|
||||
if os.access(path, os.X_OK):
|
||||
with open(path, 'r') as f:
|
||||
if f.readline()[:2] != "#!":
|
||||
exn_msg = "File at " + path + " either should not be executable or should have a shebang line"
|
||||
raise SystemError(exn_msg)
|
||||
else:
|
||||
for file in os.listdir(path):
|
||||
test_executable(os.path.join(path, file))
|
||||
|
||||
test_executable(base_dir)
|
||||
@@ -1,88 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Test that
|
||||
|
||||
from sympy import *
|
||||
|
||||
Doesn't import anything other than SymPy, it's hard dependencies (mpmath), and
|
||||
hard optional dependencies (gmpy2, fastcache). Importing unnecessary libraries
|
||||
can accidentally add hard dependencies to SymPy in the worst case, or at best
|
||||
slow down the SymPy import time when they are installed.
|
||||
|
||||
Note, for this test to be effective, every external library that could
|
||||
potentially be imported by SymPy must be installed.
|
||||
|
||||
TODO: Monkeypatch the importer to detect non-standard library imports even
|
||||
when they aren't installed.
|
||||
|
||||
Based on code from
|
||||
https://stackoverflow.com/questions/22195382/how-to-check-if-a-module-library-package-is-part-of-the-python-standard-library.
|
||||
"""
|
||||
|
||||
# These libraries will always be imported with SymPy
|
||||
hard_dependencies = ['mpmath']
|
||||
|
||||
# These libraries are optional, but are always imported at SymPy import time
|
||||
# when they are installed. External libraries should only be added to this
|
||||
# list if they are required for core SymPy functionality.
|
||||
hard_optional_dependencies = ['gmpy', 'gmpy2', 'fastcache', 'pycosat']
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
stdlib = {p for p in sys.path if p.startswith(sys.prefix) and
|
||||
'site-packages' not in p}
|
||||
|
||||
existing_modules = list(sys.modules.keys())
|
||||
|
||||
|
||||
# hook in-tree SymPy into Python path, if possible
|
||||
|
||||
this_path = os.path.abspath(__file__)
|
||||
this_dir = os.path.dirname(this_path)
|
||||
sympy_top = os.path.split(this_dir)[0]
|
||||
sympy_dir = os.path.join(sympy_top, 'sympy')
|
||||
|
||||
if os.path.isdir(sympy_dir):
|
||||
sys.path.insert(0, sympy_top)
|
||||
|
||||
def test_external_imports():
|
||||
exec("from sympy import *", {})
|
||||
|
||||
bad = []
|
||||
for mod in sys.modules:
|
||||
if '.' in mod and mod.split('.')[0] in sys.modules:
|
||||
# Only worry about the top-level modules
|
||||
continue
|
||||
|
||||
if mod in existing_modules:
|
||||
continue
|
||||
|
||||
if any(mod == i or mod.startswith(i + '.') for i in ['sympy'] +
|
||||
hard_dependencies + hard_optional_dependencies):
|
||||
continue
|
||||
|
||||
if mod in sys.builtin_module_names:
|
||||
continue
|
||||
|
||||
fname = getattr(sys.modules[mod], "__file__", None)
|
||||
if fname is None:
|
||||
bad.append(mod)
|
||||
continue
|
||||
|
||||
if fname.endswith(('__init__.py', '__init__.pyc', '__init__.pyo')):
|
||||
fname = os.path.dirname(fname)
|
||||
|
||||
if os.path.dirname(fname) in stdlib:
|
||||
continue
|
||||
|
||||
bad.append(mod)
|
||||
|
||||
if bad:
|
||||
raise RuntimeError("""Unexpected external modules found when running 'from sympy import *':
|
||||
""" + '\n '.join(bad))
|
||||
|
||||
print("No unexpected external modules were imported with 'from sympy import *'!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_external_imports()
|
||||
@@ -22,19 +22,9 @@ fi
|
||||
|
||||
if [[ "${TEST_SAGE}" == "true" ]]; then
|
||||
echo "Testing SAGE"
|
||||
source deactivate
|
||||
source activate sage
|
||||
sage -v
|
||||
sage -python bin/test sympy/external/tests/test_sage.py
|
||||
PYTHONPATH=. sage -t sympy/external/tests/test_sage.py
|
||||
export MPMATH_NOSAGE=1
|
||||
source deactivate
|
||||
source activate test-environment
|
||||
fi
|
||||
|
||||
if [[ -n "${TEST_OPT_DEPENDENCY}" ]]; then
|
||||
python bin/test_external_imports.py
|
||||
python bin/test_executable.py
|
||||
sage -t sympy/external/tests/test_sage.py
|
||||
fi
|
||||
|
||||
# We change directories to make sure that we test the installed version of
|
||||
@@ -42,30 +32,9 @@ fi
|
||||
mkdir empty
|
||||
cd empty
|
||||
|
||||
if [[ "${TEST_COVERAGE}" == "true" ]]; then
|
||||
rm -f $TRAVIS_BUILD_DIR/.coverage.* $TRAVIS_BUILD_DIR/.coverage
|
||||
cat << EOF | python
|
||||
import distutils.sysconfig
|
||||
import os
|
||||
|
||||
with open(os.path.join(distutils.sysconfig.get_python_lib(), 'coverage.pth'), 'w') as pth:
|
||||
pth.write('import sys; exec(%r)\n' % '''\
|
||||
try:
|
||||
import coverage
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
coverage.process_startup()
|
||||
''')
|
||||
EOF
|
||||
export COVERAGE_PROCESS_START=$TRAVIS_BUILD_DIR/coveragerc_travis
|
||||
fi
|
||||
|
||||
if [[ "${TEST_ASCII}" == "true" ]]; then
|
||||
# Force Python to act like pre-3.7 where LC_ALL=C causes
|
||||
# UnicodeEncodeErrors. Once the lowest Python version we support is 3.7,
|
||||
# we can consider dropping this test entirely. See PEP 538.
|
||||
export PYTHONIOENCODING=ascii:strict
|
||||
export OLD_LC_ALL=$LC_ALL
|
||||
export LC_ALL=C
|
||||
cat <<EOF | python
|
||||
print('Testing ASCII')
|
||||
try:
|
||||
@@ -78,6 +47,7 @@ import sympy
|
||||
if not (sympy.test('print') and sympy.doctest()):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
export LC_ALL=$OLD_LC_ALL
|
||||
fi
|
||||
|
||||
if [[ "${TEST_DOCTESTS}" == "true" ]]; then
|
||||
@@ -103,110 +73,58 @@ EOF
|
||||
fi
|
||||
|
||||
# lambdify with tensorflow and numexpr is tested here
|
||||
|
||||
# TODO: Generate these tests automatically
|
||||
if [[ -n "${TEST_OPT_DEPENDENCY}" ]]; then
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"numpy"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing optional dependencies')
|
||||
|
||||
print('Testing NUMPY')
|
||||
import sympy
|
||||
test_list = [
|
||||
# numpy
|
||||
'*numpy*',
|
||||
'sympy/core/tests/test_numbers.py',
|
||||
'sympy/matrices/',
|
||||
'sympy/physics/quantum/',
|
||||
'sympy/core/tests/test_sympify.py',
|
||||
'sympy/utilities/tests/test_lambdify.py',
|
||||
|
||||
# scipy
|
||||
'*scipy*',
|
||||
|
||||
# llvmlite
|
||||
'*llvm*',
|
||||
|
||||
# theano
|
||||
'*theano*',
|
||||
|
||||
# gmpy
|
||||
'polys',
|
||||
|
||||
# autowrap
|
||||
'*autowrap*',
|
||||
|
||||
# ipython
|
||||
'*ipython*',
|
||||
|
||||
# antlr, lfortran, clang
|
||||
'sympy/parsing/',
|
||||
|
||||
# matchpy
|
||||
'*rubi*',
|
||||
|
||||
# codegen
|
||||
'sympy/codegen/',
|
||||
'sympy/utilities/tests/test_codegen',
|
||||
'sympy/utilities/_compilation/tests/test_compilation',
|
||||
|
||||
# cloudpickle
|
||||
'pickling',
|
||||
|
||||
# pycosat
|
||||
'sympy/logic',
|
||||
'sympy/assumptions',
|
||||
|
||||
]
|
||||
|
||||
blacklist = [
|
||||
'sympy/physics/quantum/tests/test_circuitplot.py',
|
||||
]
|
||||
|
||||
doctest_list = [
|
||||
# numpy
|
||||
'sympy/matrices/',
|
||||
'sympy/utilities/lambdify.py',
|
||||
|
||||
# scipy
|
||||
'*scipy*',
|
||||
|
||||
# llvmlite
|
||||
'*llvm*',
|
||||
|
||||
# theano
|
||||
'*theano*',
|
||||
|
||||
# gmpy
|
||||
'polys',
|
||||
|
||||
# autowrap
|
||||
'*autowrap*',
|
||||
|
||||
# ipython
|
||||
'*ipython*',
|
||||
|
||||
# antlr, lfortran, clang
|
||||
'sympy/parsing/',
|
||||
|
||||
# matchpy
|
||||
'*rubi*',
|
||||
|
||||
# codegen
|
||||
'sympy/codegen/',
|
||||
|
||||
# pycosat
|
||||
'sympy/logic',
|
||||
'sympy/assumptions',
|
||||
|
||||
]
|
||||
|
||||
if not (sympy.test(*test_list, blacklist=blacklist) and sympy.doctest(*doctest_list)):
|
||||
if not (sympy.test('*numpy*', 'sympy/core/tests/test_numbers.py',
|
||||
'sympy/matrices/', 'sympy/physics/quantum/',
|
||||
'sympy/core/tests/test_sympify.py',
|
||||
'sympy/utilities/tests/test_lambdify.py',
|
||||
blacklist=['sympy/physics/quantum/tests/test_circuitplot.py'])
|
||||
and sympy.doctest('sympy/matrices/', 'sympy/utilities/lambdify.py')):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"scipy"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing SCIPY')
|
||||
import sympy
|
||||
# scipy matrices are tested in numpy testing
|
||||
if not sympy.test('sympy/external/tests/test_scipy.py'):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"llvmlite"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing LLVMJIT')
|
||||
import sympy
|
||||
if not (sympy.test('sympy/printing/tests/test_llvmjit.py')
|
||||
and sympy.doctest('sympy/printing/llvmjitcode.py')):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"theano"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing THEANO')
|
||||
import sympy
|
||||
if not sympy.test('*theano*'):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"gmpy"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing GMPY')
|
||||
import sympy
|
||||
if not (sympy.test('sympy/polys/') and sympy.doctest('sympy/polys/')):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
cd ..
|
||||
bin/doctest doc/src/modules/numeric-computation.rst
|
||||
fi
|
||||
|
||||
# This is separate because it needs to be run with subprocess=False
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"matplotlib"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing MATPLOTLIB')
|
||||
@@ -224,6 +142,37 @@ if not (sympy.test('sympy/plotting', 'sympy/physics/quantum/tests/test_circuitpl
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"autowrap"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing AUTOWRAP')
|
||||
import sympy
|
||||
if not (sympy.test('sympy/external/tests/test_autowrap.py')
|
||||
and sympy.doctest('sympy/utilities/autowrap.py')):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"ipython"* ]]; then
|
||||
cat << EOF | python
|
||||
print('Testing IPYTHON')
|
||||
import sympy
|
||||
if not sympy.test('*ipython*'):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "${TEST_SYMPY}" == "true" ]]; then
|
||||
# -We:invalid makes invalid escape sequences error in Python 3.6. See
|
||||
# -#12028.
|
||||
cat << EOF | python -We:invalid
|
||||
print('Testing SYMPY, split ${SPLIT}')
|
||||
import sympy
|
||||
if not sympy.test(split='${SPLIT}'):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"symengine"* ]]; then
|
||||
export USE_SYMENGINE=1
|
||||
cat << EOF | python
|
||||
@@ -237,21 +186,11 @@ EOF
|
||||
unset USE_SYMENGINE
|
||||
fi
|
||||
|
||||
if [[ "${TEST_SYMPY}" == "true" ]]; then
|
||||
# -We:invalid makes invalid escape sequences error in Python 3.6. See
|
||||
# -#12028.
|
||||
if [[ "${TEST_OPT_DEPENDENCY}" == *"antlr"* ]]; then
|
||||
cat << EOF | python -We:invalid
|
||||
print('Testing SYMPY, split ${SPLIT}')
|
||||
print('Testing ANTLR')
|
||||
import sympy
|
||||
if not sympy.test(split='${SPLIT}'):
|
||||
raise Exception('Tests failed')
|
||||
if not sympy.test('sympy/parsing/tests/test_latex'):
|
||||
raise Exception('Tests failed')
|
||||
EOF
|
||||
fi
|
||||
if [[ "${TEST_COVERAGE}" == "true" ]]; then
|
||||
unset COVERAGE_PROCESS_START
|
||||
fi
|
||||
|
||||
if [[ "${TEST_EXAMPLES}" == "true" ]]; then
|
||||
# No need to change directory if executed after the rst doctest
|
||||
examples/all.py -q
|
||||
fi
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 0%
|
||||
threshold: 100%
|
||||
|
||||
patch: false
|
||||
|
||||
precision: 3
|
||||
|
||||
comment:
|
||||
layout: "diff"
|
||||
behavior: default
|
||||
require_changes: true
|
||||
@@ -8,24 +8,10 @@ import json
|
||||
import sys
|
||||
import warnings
|
||||
import pytest
|
||||
from sympy.utilities.runtests import setup_pprint, _get_doctest_blacklist
|
||||
|
||||
durations_path = os.path.join(os.path.dirname(__file__), '.ci', 'durations.json')
|
||||
blacklist_path = os.path.join(os.path.dirname(__file__), '.ci', 'blacklisted.json')
|
||||
|
||||
# Collecting tests from rubi_tests under pytest leads to errors even if the
|
||||
# tests will be skipped.
|
||||
collect_ignore = ["sympy/integrals/rubi"] + _get_doctest_blacklist()
|
||||
if sys.version_info < (3,):
|
||||
collect_ignore.append('doc/src/gotchas.rst')
|
||||
|
||||
# Set up printing for doctests
|
||||
setup_pprint()
|
||||
sys.__displayhook__ = sys.displayhook
|
||||
#from sympy import pprint_use_unicode
|
||||
#pprint_use_unicode(False)
|
||||
|
||||
|
||||
def _mk_group(group_dict):
|
||||
return list(chain(*[[k+'::'+v for v in files] for k, files in group_dict.items()]))
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
[run]
|
||||
parallel = True
|
||||
branch = True
|
||||
source = sympy
|
||||
omit =
|
||||
*/tests/*
|
||||
*/benchmarks/*
|
||||
*/sympy/integrals/rubi/rules/*
|
||||
*/sympy/plotting/pygletplot/*
|
||||
*/conftest.py
|
||||
data_file = $TRAVIS_BUILD_DIR/.coverage
|
||||
|
||||
[report]
|
||||
exclude_lines =
|
||||
\#.*pragma:\s*no.?cover
|
||||
^\s*if SYMPY_DEBUG:
|
||||
show_missing = True
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# TeXmacs interface for SymPy
|
||||
#
|
||||
@@ -11,7 +11,7 @@
|
||||
# heuristics to know where a multi-line expression is
|
||||
# broken. As a result you can't use more than one space
|
||||
# in a sequence. However you can and must indent your
|
||||
# expression using standard Python rules.
|
||||
# expression using standard Pyhon rules.
|
||||
#
|
||||
# You can retrieve the last output using '_' built-in
|
||||
# symbol. If the previous command did not generate
|
||||
@@ -65,7 +65,7 @@ f = Function('f')
|
||||
Gamma, Zeta = gamma, zeta
|
||||
|
||||
_greek = 'alpha beta gamma delta epsilon zeta eta ' \
|
||||
'theta iota kappa mu nu xi omicron rho ' \
|
||||
'theta iota kappa mu nu xi omicron pi rho ' \
|
||||
'sigma tau upsilon phi chi psi omega'
|
||||
|
||||
for _symbol in _greek.split(' '):
|
||||
|
||||
@@ -6,32 +6,22 @@ Debian/Ubuntu
|
||||
|
||||
To make the html documentation, install the prerequisites::
|
||||
|
||||
apt-get install python-sphinx texlive-latex-recommended dvipng librsvg2-bin imagemagick docbook2x graphviz
|
||||
python -m pip install sphinx-math-dollar
|
||||
apt-get install python-sphinx texlive-latex-recommended dvipng librsvg2-bin imagemagick docbook2x
|
||||
|
||||
and do::
|
||||
|
||||
make html
|
||||
|
||||
If you get **mpmath** error, install python-mpmath package::
|
||||
|
||||
apt-get install python-mpmath
|
||||
|
||||
If you get **matplotlib** error, install python-matplotlib package::
|
||||
|
||||
apt-get install python-matplotlib
|
||||
|
||||
and to view it, do::
|
||||
|
||||
firefox _build/html/index.html
|
||||
epiphany _build/html/index.html
|
||||
|
||||
Fedora
|
||||
------
|
||||
|
||||
Fedora (and maybe other RPM based distributions), install the prerequisites::
|
||||
|
||||
dnf install python3-sphinx librsvg2 ImageMagick docbook2X texlive-dvipng-bin texlive-scheme-medium librsvg2-tools
|
||||
python -m pip install sphinx-math-dollar
|
||||
dnf install python3-sphinx librsvg2 ImageMagick docbook2X texlive-dvipng-bin texlive-scheme-medium librsvg2-tools
|
||||
|
||||
After that, run::
|
||||
|
||||
@@ -41,62 +31,6 @@ If you get **mpmath** error, install python3-mpmath package::
|
||||
|
||||
dnf install python3-mpmath
|
||||
|
||||
If you get **matplotlib** error, install python3-matplotlib package::
|
||||
|
||||
dnf install python3-matplotlib
|
||||
|
||||
And view it at::
|
||||
|
||||
_build/html/index.html
|
||||
|
||||
Mac
|
||||
---
|
||||
|
||||
- Install MacTex: http://www.tug.org/mactex/
|
||||
- Install homebrew: https://brew.sh/
|
||||
|
||||
Install these packages with homebrew:
|
||||
|
||||
```bash
|
||||
brew install imagemagick graphviz docbook librsvg
|
||||
```
|
||||
|
||||
Install these packages with either pip or conda:
|
||||
|
||||
```bash
|
||||
python -m pip install mpmath matplotlib sphinx sphinx-math-dollar
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
conda install -c conda-forge mpmpath matplotlib sphinx sphinx-math-dollar
|
||||
```
|
||||
|
||||
Windows 10
|
||||
----------
|
||||
|
||||
Making your sphinx build successful on the Windows system is tricky because of
|
||||
some dependencies like dvipng or docbook2x not available.
|
||||
|
||||
For Windows 10, however, the Windows Subsystem for Linux can be a possible
|
||||
workaround solution, and you can install Ubuntu shell on your Windows system
|
||||
after following up the tutorial below
|
||||
|
||||
https://github.com/MicrosoftDocs/WSL/blob/live/WSL/install-win10.md
|
||||
|
||||
In your command prompt, simply run 'ubuntu' to transfer to linux terminal,
|
||||
and follow up the Debian/Ubuntu tutorial above to install all the dependencies,
|
||||
and then you can run 'make html' to build.
|
||||
(Note that you would also have to install 'make' via 'apt-get install make')
|
||||
|
||||
If you want to change directory in your prompt to your working folder of sympy
|
||||
in windows file system, you can prepend 'cd /mnt/' to your file path in windows,
|
||||
and run in your shell to navigate to the folder.
|
||||
(Also note that linux uses '/' instead of '\\' for path)
|
||||
|
||||
This method would provide better compatibility than cygwin or msys2,
|
||||
and more convenience than a virtual machine, if you partially need linux
|
||||
environment for your workflow.
|
||||
|
||||
However this method is only viable for Windows 10 64-bit users.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[epydoc]
|
||||
|
||||
name : SymPy
|
||||
url: https://code.google.com/p/sympy
|
||||
url: http://code.google.com/p/sympy
|
||||
|
||||
modules : sympy, sympy.core, sympy.modules
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
\usetikzlibrary{shapes,snakes}
|
||||
\usepackage{amsmath,amssymb}
|
||||
\begin{document}
|
||||
\begin{center}\huge{\textbf{SymPy Cheatsheet (https://sympy.org)}}\end{center}
|
||||
\begin{center}\huge{\textbf{SymPy Cheatsheet (http://sympy.org)}}\end{center}
|
||||
\begin{multicols*}{3}
|
||||
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ Test if permutation \verb!g! belong to self.
|
||||
|
||||
|
||||
\verb!coset_factor(g, af=False)!\\
|
||||
Return G's (self's) coset factorization, \verb!f,! of \verb!g!.
|
||||
Return GÔs (selfÕs) coset factorization, \verb!f,! of \verb!g!.
|
||||
|
||||
|
||||
|
||||
@@ -458,7 +458,7 @@ Return iterator to generate the elements of the group
|
||||
|
||||
|
||||
\verb!generate_dimino(af=False)!\\
|
||||
Yield group elements using Dimino's algorithm
|
||||
Yield group elements using DiminoÕs algorithm
|
||||
|
||||
|
||||
\verb!generate_schreier_sims(af=False)!\\
|
||||
@@ -1014,7 +1014,7 @@ Verify the centralizer of a group/set/element inside another group.
|
||||
|
||||
\rule{0.3\linewidth}{0.25pt}
|
||||
\scriptsize\\
|
||||
https://www.sympy.org/cheatsheets
|
||||
http://www.sympy.org/cheatsheets
|
||||
|
||||
|
||||
\end{multicols}
|
||||
|
||||
@@ -7,10 +7,7 @@ import inspect
|
||||
import textwrap
|
||||
import re
|
||||
import pydoc
|
||||
try:
|
||||
from collections.abc import Mapping
|
||||
except ImportError: # Python 2
|
||||
from collections import Mapping
|
||||
import collections
|
||||
import sys
|
||||
|
||||
|
||||
@@ -90,7 +87,7 @@ class Reader(object):
|
||||
return not ''.join(self._str).strip()
|
||||
|
||||
|
||||
class NumpyDocString(Mapping):
|
||||
class NumpyDocString(collections.Mapping):
|
||||
def __init__(self, docstring, config={}):
|
||||
docstring = textwrap.dedent(docstring).split('\n')
|
||||
|
||||
@@ -108,10 +105,10 @@ class NumpyDocString(Mapping):
|
||||
'Attributes': [],
|
||||
'Methods': [],
|
||||
'See Also': [],
|
||||
# 'Notes': [],
|
||||
'Notes': [],
|
||||
'Warnings': [],
|
||||
'References': '',
|
||||
# 'Examples': '',
|
||||
'Examples': '',
|
||||
'index': {}
|
||||
}
|
||||
self._other_keys = []
|
||||
@@ -538,17 +535,18 @@ class ClassDoc(NumpyDocString):
|
||||
if not self[field]:
|
||||
doc_list = []
|
||||
for name in sorted(items):
|
||||
clsname = getattr(self._cls, name, None)
|
||||
if clsname is not None:
|
||||
doc_item = pydoc.getdoc(clsname)
|
||||
try:
|
||||
doc_item = pydoc.getdoc(getattr(self._cls, name))
|
||||
doc_list.append((name, '', splitlines_x(doc_item)))
|
||||
except AttributeError:
|
||||
pass # method doesn't exist
|
||||
self[field] = doc_list
|
||||
|
||||
@property
|
||||
def methods(self):
|
||||
if self._cls is None:
|
||||
return []
|
||||
return [name for name, func in inspect.getmembers(self._cls)
|
||||
return [name for name, func in inspect_getmembers(self._cls)
|
||||
if ((not name.startswith('_')
|
||||
or name in self.extra_public_methods)
|
||||
and callable(func))]
|
||||
@@ -557,5 +555,33 @@ class ClassDoc(NumpyDocString):
|
||||
def properties(self):
|
||||
if self._cls is None:
|
||||
return []
|
||||
return [name for name, func in inspect.getmembers(self._cls)
|
||||
return [name for name, func in inspect_getmembers(self._cls)
|
||||
if not name.startswith('_') and func is None]
|
||||
|
||||
|
||||
# This function was taken verbatim from Python 2.7 inspect.getmembers() from
|
||||
# the standard library. The difference from Python < 2.7 is that there is the
|
||||
# try/except AttributeError clause added, which catches exceptions like this
|
||||
# one: https://gist.github.com/1471949
|
||||
def inspect_getmembers(object, predicate=None):
|
||||
"""
|
||||
Return all members of an object as (name, value) pairs sorted by name.
|
||||
Optionally, only return members that satisfy a given predicate.
|
||||
"""
|
||||
results = []
|
||||
for key in dir(object):
|
||||
try:
|
||||
value = getattr(object, key)
|
||||
except AttributeError:
|
||||
continue
|
||||
if not predicate or predicate(value):
|
||||
results.append((key, value))
|
||||
results.sort()
|
||||
return results
|
||||
|
||||
def _is_show_member(self, name):
|
||||
if self.show_inherited_members:
|
||||
return True # show all class members
|
||||
if name not in self._cls.__dict__:
|
||||
return False # class member is inherited, we do not show it
|
||||
return True
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
from sympy.core.compatibility import string_types
|
||||
|
||||
import sys
|
||||
import re
|
||||
@@ -195,7 +194,7 @@ class SphinxDocString(NumpyDocString):
|
||||
out = []
|
||||
if self['References']:
|
||||
out += self._str_header('References')
|
||||
if isinstance(self['References'], string_types):
|
||||
if isinstance(self['References'], str):
|
||||
self['References'] = [self['References']]
|
||||
out.extend(self['References'])
|
||||
out += ['']
|
||||
@@ -239,10 +238,12 @@ class SphinxDocString(NumpyDocString):
|
||||
for param_list in ('Other Parameters', 'Raises', 'Warns'):
|
||||
out += self._str_param_list(param_list)
|
||||
out += self._str_warnings()
|
||||
out += self._str_see_also(func_role)
|
||||
out += self._str_section('Notes')
|
||||
out += self._str_references()
|
||||
out += self._str_examples()
|
||||
for s in self._other_keys:
|
||||
out += self._str_section(s)
|
||||
out += self._str_see_also(func_role)
|
||||
out += self._str_references()
|
||||
out += self._str_member_list('Attributes')
|
||||
out = self._str_indent(out, indent)
|
||||
return '\n'.join(out)
|
||||
|
||||
@@ -23,10 +23,7 @@ import re
|
||||
import pydoc
|
||||
import sphinx
|
||||
import inspect
|
||||
try:
|
||||
from collections.abc import Callable
|
||||
except ImportError: # Python 2
|
||||
from collections import Callable
|
||||
import collections
|
||||
|
||||
if sphinx.__version__ < '1.0.1':
|
||||
raise RuntimeError("Sphinx 1.0.1 or newer is required")
|
||||
@@ -104,7 +101,7 @@ def mangle_signature(app, what, name, obj, options, sig, retann):
|
||||
'initializes x; see ' in pydoc.getdoc(obj.__init__))):
|
||||
return '', ''
|
||||
|
||||
if not (isinstance(obj, Callable) or
|
||||
if not (isinstance(obj, collections.Callable) or
|
||||
hasattr(obj, '__argspec_is_invalid_')):
|
||||
return
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
sympylive
|
||||
~~~~~~~~~
|
||||
|
||||
Allow `SymPy Live <https://live.sympy.org/>`_ to be used for interactive
|
||||
Allow `SymPy Live <http://live.sympy.org/>`_ to be used for interactive
|
||||
evaluation of SymPy's code examples.
|
||||
|
||||
:copyright: Copyright 2014 by the SymPy Development Team, see AUTHORS.
|
||||
@@ -30,5 +30,5 @@ def builder_inited(app):
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('sympylive_url', 'https://live.sympy.org', False)
|
||||
app.add_config_value('sympylive_url', 'http://live.sympy.org', False)
|
||||
app.connect('builder-inited', builder_inited)
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
This script creates logos of different formats from the source "sympy.svg"
|
||||
|
||||
Requirements:
|
||||
rsvg-convert - for converting to *.png format
|
||||
(librsvg2-bin deb package)
|
||||
rsvg-convert - for converting to *.png format (librsvg2-bin deb package)
|
||||
imagemagick - for converting to *.ico favicon format
|
||||
"""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from optparse import OptionParser
|
||||
import xml.dom.minidom
|
||||
import os.path
|
||||
import logging
|
||||
@@ -23,69 +22,61 @@ default_output_dir = os.path.join(os.path.dirname(__file__), "_build/logo")
|
||||
|
||||
# those are the options for resizing versions without tail or text
|
||||
svg_sizes = {}
|
||||
svg_sizes['notail'] = {
|
||||
"prefix":"notail", "dx":-70, "dy":-20, "size":690,
|
||||
"title":"SymPy Logo, with no tail"}
|
||||
svg_sizes['notail-notext'] = {
|
||||
"prefix":"notailtext", "dx":-70, "dy":60, "size":690,
|
||||
"title":"SymPy Logo, with no tail, no text"}
|
||||
svg_sizes['notext'] = {
|
||||
"prefix":"notext", "dx":-7, "dy":90, "size":750,
|
||||
"title":"SymPy Logo, with no text"}
|
||||
svg_sizes['notail'] = {"prefix":"notail", "dx":-70, "dy":-20, "size":690, "title":"SymPy Logo, with no tail"}
|
||||
svg_sizes['notail-notext'] = {"prefix":"notailtext", "dx":-70, "dy":60, "size":690, "title":"SymPy Logo, with no tail, no text"}
|
||||
svg_sizes['notext'] = {"prefix":"notext", "dx":-7, "dy":90, "size":750, "title":"SymPy Logo, with no text"}
|
||||
|
||||
# The list of identifiers of various versions
|
||||
versions = ['notail', 'notail-notext', 'notext']
|
||||
|
||||
parser = ArgumentParser(usage="%(prog)s [options ...]")
|
||||
parser = OptionParser()
|
||||
parser.set_usage("%s [options ...]")
|
||||
|
||||
parser.add_argument("--source-dir", type=str, dest="source_dir",
|
||||
help="Directory of the source *.svg file [default: %(default)s]",
|
||||
parser.add_option("--source-dir", type="string", dest="source_dir",
|
||||
help="Directory of the source *.svg file [default: %default]",
|
||||
default=default_source_dir)
|
||||
|
||||
parser.add_argument("--source-svg", type=str, dest="source_svg",
|
||||
help="File name of the source *.svg file [default: %(default)s]",
|
||||
parser.add_option("--source-svg", type="string", dest="source_svg",
|
||||
help="File name of the source *.svg file [default: %default]",
|
||||
default=default_source_svg)
|
||||
|
||||
parser.add_argument("--svg", action="store_true", dest="generate_svg",
|
||||
help="Generate *.svg versions without tails " \
|
||||
"and without text 'SymPy' [default: %(default)s]",
|
||||
parser.add_option("--svg", action="store_true", dest="generate_svg",
|
||||
help="Generate *.svg versions without tails and without text 'SymPy' [default: %default]",
|
||||
default=False)
|
||||
|
||||
parser.add_argument("--png", action="store_true", dest="generate_png",
|
||||
help="Generate *.png versions [default: %(default)s]",
|
||||
parser.add_option("--png", action="store_true", dest="generate_png",
|
||||
help="Generate *.png versions [default: %default]",
|
||||
default=False)
|
||||
|
||||
parser.add_argument("--ico", action="store_true", dest="generate_ico",
|
||||
help="Generate *.ico versions [default: %(default)s]",
|
||||
parser.add_option("--ico", action="store_true", dest="generate_ico",
|
||||
help="Generate *.ico versions [default: %default]",
|
||||
default=False)
|
||||
|
||||
parser.add_argument("--clear", action="store_true", dest="clear",
|
||||
help="Remove temporary files [default: %(default)s]",
|
||||
parser.add_option("--clear", action="store_true", dest="clear",
|
||||
help="Remove temporary files [default: %default]",
|
||||
default=False)
|
||||
|
||||
parser.add_argument("-a", "--all", action="store_true", dest="generate_all",
|
||||
help="Shorthand for '--svg --png --ico --clear' options " \
|
||||
"[default: %(default)s]",
|
||||
parser.add_option("-a", "--all", action="store_true", dest="generate_all",
|
||||
help="Shorthand for '--svg --png --ico --clear' options [default: %default]",
|
||||
default=True)
|
||||
|
||||
parser.add_argument("-s", "--sizes", type=str, dest="sizes",
|
||||
help="Sizes of png pictures [default: %(default)s]",
|
||||
parser.add_option("-s", "--sizes", type="string", dest="sizes",
|
||||
help="Sizes of png pictures [default: %default]",
|
||||
default="160,500")
|
||||
|
||||
parser.add_argument("--icon-sizes", type=str, dest="icon_sizes",
|
||||
help="Sizes of icons embedded in favicon file [default: %(default)s]",
|
||||
parser.add_option("--icon-sizes", type="string", dest="icon_sizes",
|
||||
help="Sizes of icons embedded in favicon file [default: %default]",
|
||||
default="16,32,48,64")
|
||||
|
||||
parser.add_argument("--output-dir", type=str, dest="output_dir",
|
||||
help="Output dir [default: %(default)s]",
|
||||
parser.add_option("--output-dir", type="string", dest="output_dir",
|
||||
help="Outpu dir [default: %default]",
|
||||
default=default_output_dir)
|
||||
|
||||
parser.add_argument("-d", "--debug", action="store_true", dest="debug",
|
||||
help="Print debug log [default: %(default)s]",
|
||||
parser.add_option("-d", "--debug", action="store_true", dest="debug",
|
||||
default=False)
|
||||
|
||||
def main():
|
||||
options, args = parser.parse_known_args()
|
||||
options, args = parser.parse_args()
|
||||
if options.debug:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
@@ -135,9 +126,7 @@ def generate_notail_notext_versions(fn_source, output_dir):
|
||||
title.firstChild.data = properties["title"]
|
||||
|
||||
desc = svg.getElementsByTagName("desc")[0]
|
||||
desc.appendChild(
|
||||
doc.createTextNode(
|
||||
"\n\nThis file is generated from %s !" % fn_source))
|
||||
desc.appendChild(doc.createTextNode("\n\nThis file is generated from %s !" % fn_source))
|
||||
|
||||
fn_out = get_svg_filename_from_versionkey(fn_source, ver)
|
||||
fn_out = os.path.join(output_dir, fn_out)
|
||||
@@ -153,8 +142,7 @@ def convert_to_png(fn_source, output_dir, sizes):
|
||||
stderr=subprocess.STDOUT)
|
||||
p.communicate()
|
||||
if p.returncode == 127:
|
||||
logging.error(
|
||||
"%s: command not found. Install librsvg" % cmd)
|
||||
logging.error("%s: command not found" % cmd)
|
||||
sys.exit(p.returncode)
|
||||
|
||||
for ver in svgs:
|
||||
@@ -199,7 +187,7 @@ def convert_to_ico(fn_source, output_dir, sizes):
|
||||
stderr=subprocess.STDOUT)
|
||||
p.communicate()
|
||||
if p.returncode == 127:
|
||||
logging.error("%s: command not found. Install imagemagick" % cmd)
|
||||
logging.error("%s: command not found" % cmd)
|
||||
sys.exit(p.returncode)
|
||||
|
||||
for ver in svgs:
|
||||
|
||||
@@ -23,7 +23,7 @@ this will generate isympy.1 in the current directory. -->
|
||||
|
||||
<!-- TITLE should be something like "User commands", -->
|
||||
<!-- "&dhpackage; command-line reference" or similar (see e.g. -->
|
||||
<!-- https://www.tldp.org/HOWTO/Man-Page/q2.html). But limit -->
|
||||
<!-- http://www.tldp.org/HOWTO/Man-Page/q2.html). But limit -->
|
||||
<!-- the length to 30 chars. -->
|
||||
<!ENTITY dhtitle "&dhpackage; command-line reference">
|
||||
|
||||
@@ -36,7 +36,7 @@ this will generate isympy.1 in the current directory. -->
|
||||
|
||||
<!-- SECTION should be 1-8, maybe w/ subsection other -->
|
||||
<!-- parameters are allowed: see man(7), man(1) and -->
|
||||
<!-- https://www.tldp.org/HOWTO/Man-Page/q2.html. -->
|
||||
<!-- http://www.tldp.org/HOWTO/Man-Page/q2.html. -->
|
||||
<!ENTITY dhsection "1">
|
||||
|
||||
]>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
@import url("classic.css");
|
||||
@import url(https://fonts.googleapis.com/css?family=Open+Sans);
|
||||
@import url("basic.css");
|
||||
@import url(http://fonts.googleapis.com/css?family=Open+Sans);
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
@@ -290,8 +290,6 @@ p.admonition-title:after {
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: DejaVu Sans Mono, monospace;
|
||||
font-size: 100%;
|
||||
padding: 5px;
|
||||
background-color: {{ theme_codebgcolor }};
|
||||
color: {{ theme_codetextcolor }};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends '!layout.html' %}
|
||||
|
||||
{%- block linktags %}
|
||||
<link href="https://docs.sympy.org/latest/{{ pagename }}.html" rel="canonical" />
|
||||
<link href="http://docs.sympy.org/latest/{{ pagename }}.html" rel="canonical" />
|
||||
{{ super() }}
|
||||
{%- endblock %}
|
||||
|
||||
@@ -12,9 +12,9 @@ You can find a brief history of SymPy in the `README <https://github.com/sympy/s
|
||||
Financial and Infrastructure Support
|
||||
------------------------------------
|
||||
|
||||
* `Google <https://www.google.com/about/company/>`_: SymPy has received generous
|
||||
* `Google <http://www.google.com/about/company/>`_: SymPy has received generous
|
||||
financial support from Google in various years through the `Google Summer of
|
||||
Code <https://g.co/gsoc>`_ program by providing stipends:
|
||||
Code <http://g.co/gsoc>`_ program by providing stipends:
|
||||
|
||||
* in 2007 for 5 students (`GSoC 2007 <https://github.com/sympy/sympy/wiki/GSoC-2007-Report>`_)
|
||||
* in 2008 for 1 student (`GSoC 2008 <https://github.com/sympy/sympy/wiki/GSoC-2008-report>`_)
|
||||
@@ -40,14 +40,14 @@ Financial and Infrastructure Support
|
||||
* 6 GSoC 2015 students
|
||||
* 1 GSoC 2016 student (James)
|
||||
|
||||
* `Portland State University (PSU) <https://www.pdx.edu/>`_ has hosted following
|
||||
* `Portland State University (PSU) <http://www.pdx.edu/>`_ has hosted following
|
||||
GSoC students:
|
||||
|
||||
* 1 student (Chris) in 2007
|
||||
* 3 students (Aaron, Dale and Fabian) in 2009
|
||||
* 1 student (Addison) in 2010
|
||||
|
||||
* `The Space Telescope Science Institute <http://www.stsci.edu/>`_: STScI hosted 1 GSoC 2007 student (Mateusz)
|
||||
* `The Space Telescope Science Institute <http://www.stsci.edu/portal/>`_: STScI hosted 1 GSoC 2007 student (Mateusz)
|
||||
|
||||
* `The Ruby Science Foundation <http://www.sciruby.com/>`_ has hosted following
|
||||
GSoC students:
|
||||
@@ -57,8 +57,8 @@ Financial and Infrastructure Support
|
||||
|
||||
* Several 13-17 year old pre-university students contributed as part of
|
||||
Google's `Code-In
|
||||
<https://www.google-melange.com/gci/homepage/google/gci2011>`_ 2011. (`GCI
|
||||
2011 <https://www.google-melange.com/gci/org/google/gci2011/sympy>`_)
|
||||
<http://www.google-melange.com/gci/homepage/google/gci2011>`_ 2011. (`GCI
|
||||
2011 <http://www.google-melange.com/gci/org/google/gci2011/sympy>`_)
|
||||
|
||||
* `Simula Research Laboratory <https://www.simula.no/>`_: supports Pearu Peterson work in SymPy/SymPy Core projects
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
# serve to show the default value.
|
||||
|
||||
import sys
|
||||
import inspect
|
||||
import os
|
||||
import subprocess
|
||||
import sympy
|
||||
|
||||
# If your extensions are in another directory, add it here.
|
||||
@@ -25,9 +22,8 @@ sys.path = ['ext'] + sys.path
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.linkcode', 'sphinx_math_dollar',
|
||||
'sphinx.ext.mathjax', 'numpydoc', 'sympylive',
|
||||
'sphinx.ext.graphviz', 'matplotlib.sphinxext.plot_directive']
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.mathjax',
|
||||
'numpydoc', 'sympylive', 'sphinx.ext.graphviz', ]
|
||||
|
||||
# Use this to use pngmath instead
|
||||
#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.pngmath', ]
|
||||
@@ -35,10 +31,8 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.linkcode', 'sphinx_math_dollar',
|
||||
# To stop docstrings inheritance.
|
||||
autodoc_inherit_docstrings = False
|
||||
|
||||
# MathJax file, which is free to use. See https://www.mathjax.org/#gettingstarted
|
||||
# As explained in the link using latest.js will get the latest version even
|
||||
# though it says 2.7.5.
|
||||
mathjax_path = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS_HTML-full'
|
||||
# MathJax file, which is free to use. See http://www.mathjax.org/docs/2.0/start.html
|
||||
mathjax_path = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML-full'
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -53,7 +47,7 @@ suppress_warnings = ['ref.citation', 'ref.footnote']
|
||||
|
||||
# General substitutions.
|
||||
project = 'SymPy'
|
||||
copyright = '2019 SymPy Development Team'
|
||||
copyright = '2018 SymPy Development Team'
|
||||
|
||||
# The default replacements for |version| and |release|, also used in various
|
||||
# other places throughout the built documents.
|
||||
@@ -86,8 +80,6 @@ today_fmt = '%B %d, %Y'
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# Don't show the source code hyperlinks when using matplotlib plot directive.
|
||||
plot_html_show_source_link = False
|
||||
|
||||
# Options for HTML output
|
||||
# -----------------------
|
||||
@@ -110,7 +102,7 @@ html_theme = 'classic'
|
||||
|
||||
html_logo = '_static/sympylogo.png'
|
||||
html_favicon = '../_build/logo/sympy-notailtext-favicon.ico'
|
||||
# See http://www.sphinx-doc.org/en/master/theming.html#builtin-themes
|
||||
# See http://sphinx-doc.org/theming.html#builtin-themes.
|
||||
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
@@ -207,83 +199,5 @@ texinfo_documents = [
|
||||
]
|
||||
|
||||
# Use svg for graphviz
|
||||
|
||||
graphviz_output_format = 'svg'
|
||||
|
||||
|
||||
# Requried for linkcode extension.
|
||||
# Get commit hash from the external file.
|
||||
commit_hash_filepath = '../commit_hash.txt'
|
||||
commit_hash = None
|
||||
if os.path.isfile(commit_hash_filepath):
|
||||
with open(commit_hash_filepath, 'r') as f:
|
||||
commit_hash = f.readline()
|
||||
|
||||
# Get commit hash from the external file.
|
||||
if not commit_hash:
|
||||
try:
|
||||
commit_hash = subprocess.check_output(['git', 'rev-parse', 'HEAD'])
|
||||
commit_hash = commit_hash.decode('ascii')
|
||||
commit_hash = commit_hash.rstrip()
|
||||
except:
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"Failed to get the git commit hash as the command " \
|
||||
"'git rev-parse HEAD' is not working. The commit hash will be " \
|
||||
"assumed as the SymPy master, but the lines may be misleading " \
|
||||
"or nonexistent as it is not the correct branch the doc is " \
|
||||
"built with. Check your installation of 'git' if you want to " \
|
||||
"resolve this warning.")
|
||||
commit_hash = 'master'
|
||||
|
||||
fork = 'sympy'
|
||||
blobpath = \
|
||||
"https://github.com/{}/sympy/blob/{}/sympy/".format(fork, commit_hash)
|
||||
|
||||
|
||||
def linkcode_resolve(domain, info):
|
||||
"""Determine the URL corresponding to Python object."""
|
||||
if domain != 'py':
|
||||
return
|
||||
|
||||
modname = info['module']
|
||||
fullname = info['fullname']
|
||||
|
||||
submod = sys.modules.get(modname)
|
||||
if submod is None:
|
||||
return
|
||||
|
||||
obj = submod
|
||||
for part in fullname.split('.'):
|
||||
try:
|
||||
obj = getattr(obj, part)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
# strip decorators, which would resolve to the source of the decorator
|
||||
# possibly an upstream bug in getsourcefile, bpo-1764286
|
||||
try:
|
||||
unwrap = inspect.unwrap
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
obj = unwrap(obj)
|
||||
|
||||
try:
|
||||
fn = inspect.getsourcefile(obj)
|
||||
except Exception:
|
||||
fn = None
|
||||
if not fn:
|
||||
return
|
||||
|
||||
try:
|
||||
source, lineno = inspect.getsourcelines(obj)
|
||||
except Exception:
|
||||
lineno = None
|
||||
|
||||
if lineno:
|
||||
linespec = "#L%d-L%d" % (lineno, lineno + len(source) - 1)
|
||||
else:
|
||||
linespec = ""
|
||||
|
||||
fn = os.path.relpath(fn, start=os.path.dirname(sympy.__file__))
|
||||
return blobpath + fn + linespec
|
||||
|
||||
@@ -20,7 +20,7 @@ remainder of the SymPy Docs, and the `official Python Tutorial <https://docs.pyt
|
||||
|
||||
If you are already familiar with C or Java, you might also want to look
|
||||
at this `4 minute Python tutorial
|
||||
<https://nerdparadise.com/programming/python4minutes/>`_.
|
||||
<http://www.nerdparadise.com/tech/python/4minutecrashcourse/>`_.
|
||||
|
||||
Ignore ``#doctest: +SKIP`` in the examples. That has to do with
|
||||
internal testing of the examples.
|
||||
@@ -230,7 +230,7 @@ are used for the imaginary unit (:math:`i`), the base of the natural
|
||||
logarithm (:math:`e`), the :func:`sympify` function (see :ref:`Symbolic
|
||||
Expressions<symbolic-expressions>` below), numeric evaluation (:func:`N`
|
||||
is equivalent to :ref:`evalf()<evalf-label>` ),
|
||||
the `big O <https://en.wikipedia.org/wiki/Big_O_notation>`_ order symbol
|
||||
the `big O <http://en.wikipedia.org/wiki/Big_O_notation>`_ order symbol
|
||||
(as in :math:`O(n\log{n})`), and the assumptions object that holds a list of
|
||||
supported ask keys (such as :obj:`Q.real`), respectively. You can use the
|
||||
mnemonic ``OSINEQ`` to remember what Symbols are defined by default in SymPy.
|
||||
@@ -258,10 +258,10 @@ To get a full list of all default names in SymPy do:
|
||||
# A big list of all default sympy names and functions follows.
|
||||
# Ignore everything that starts and ends with __.
|
||||
|
||||
If you have `IPython <https://ipython.org/>`_ installed and
|
||||
If you have `IPython <http://ipython.org/>`_ installed and
|
||||
use :command:`isympy`, you can also press the TAB key to get a list of
|
||||
all built-in names and to autocomplete. Also, see `this page
|
||||
<https://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks>`_ for a
|
||||
<http://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks>`_ for a
|
||||
trick for getting tab completion in the regular Python console.
|
||||
|
||||
.. note::
|
||||
@@ -334,9 +334,9 @@ you don't have to worry about this problem:
|
||||
3.142857142857143
|
||||
>>> # One solution is to just assign the expression to a variable
|
||||
>>> # if we need to use it again.
|
||||
>>> a = solve(7*x - 22, x)[0]
|
||||
>>> a = solve(7*x - 22, x)
|
||||
>>> a
|
||||
22/7
|
||||
[22/7]
|
||||
|
||||
The other solution is to put quotes around the expression
|
||||
and run it through S() (i.e., sympify it):
|
||||
@@ -346,7 +346,7 @@ you don't have to worry about this problem:
|
||||
|
||||
Also, if you do not use :command:`isympy`, you could use ``from
|
||||
__future__ import division`` to prevent the ``/`` sign from performing
|
||||
`integer division <https://en.wikipedia.org/wiki/Integer_division>`_.
|
||||
`integer division <http://en.wikipedia.org/wiki/Integer_division>`_.
|
||||
|
||||
>>> from __future__ import division
|
||||
>>> 1/2 # With division imported it evaluates to a python float
|
||||
@@ -740,8 +740,8 @@ Getting help from within SymPy
|
||||
help()
|
||||
------
|
||||
|
||||
Although all docs are available at `docs.sympy.org <https://docs.sympy.org/>`_ or on the
|
||||
`SymPy Wiki <https://wiki.sympy.org/>`_, you can also get info on functions from within the
|
||||
Although all docs are available at `docs.sympy.org <http://docs.sympy.org/>`_ or on the
|
||||
`SymPy Wiki <http://wiki.sympy.org/>`_, you can also get info on functions from within the
|
||||
Python interpreter that runs SymPy. The easiest way to do this is to do
|
||||
``help(function)``, or ``function?`` if you are using :command:`ipython`::
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ For easier use, there is a syntactic sugar for expressions.
|
||||
For example, ``cos(x) + 1`` is equal to ``cos(x).__add__(1)`` is equal to
|
||||
``Add(cos(x), Integer(1))``
|
||||
|
||||
This works because Python allows you to override the behavior of built-in
|
||||
This works becauses Python allows you to override the behavior of built-in
|
||||
operations ``+, *, -, /`` etc., by defining methods with names ``__add__``,
|
||||
``__mul__`` etc., so ``cos(x) + 1`` is evaluated as ``cos(x).__add__(1)``.
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
.. _documentation:
|
||||
|
||||
.. SymPy documentation master file, created by sphinx-quickstart.py on Sat Mar 22 19:34:32 2008.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
@@ -9,7 +7,7 @@ Welcome to SymPy's documentation!
|
||||
|
||||
A PDF version of these docs can be found `here <https://github.com/sympy/sympy/releases>`_.
|
||||
|
||||
`SymPy <https://sympy.org>`_ is a Python library for symbolic mathematics.
|
||||
`SymPy <http://sympy.org>`_ is a Python library for symbolic mathematics.
|
||||
If you are new to SymPy, start with the :ref:`Tutorial <tutorial>`.
|
||||
|
||||
This is the central page for all of SymPy's documentation.
|
||||
@@ -26,6 +24,7 @@ Contents:
|
||||
guide.rst
|
||||
modules/index.rst
|
||||
special_topics/index.rst
|
||||
python-comparisons.rst
|
||||
wiki.rst
|
||||
outreach.rst
|
||||
aboutus.rst
|
||||
|
||||
@@ -5,16 +5,17 @@ Installation
|
||||
|
||||
The SymPy CAS can be installed on virtually any computer with Python 2.7 or
|
||||
above. SymPy does require `mpmath`_ Python library to be installed first. The
|
||||
recommended method of installation is through Anaconda, which includes
|
||||
mpmath, as well as several other useful libraries. Alternatively, some Linux
|
||||
distributions have SymPy packages available.
|
||||
current recommended method of installation is through Anaconda, which includes
|
||||
mpmath, as well as several other useful libraries. Alternatively, executables
|
||||
are available for Windows, and some Linux distributions have SymPy packages
|
||||
available.
|
||||
|
||||
SymPy officially supports Python 2.7, 3.5, 3.6, 3.7, and PyPy.
|
||||
SymPy officially supports Python 2.7, 3.4, 3.5, 3.6 and PyPy.
|
||||
|
||||
Anaconda
|
||||
========
|
||||
|
||||
`Anaconda <https://www.anaconda.com/download/>`_ is a free Python distribution from
|
||||
`Anaconda <http://continuum.io/downloads>`_ is a free Python distribution from
|
||||
Continuum Analytics that includes SymPy, Matplotlib, IPython, NumPy, and many
|
||||
more useful packages for scientific computing. This is recommended because
|
||||
many nice features of SymPy are only enabled when certain libraries are
|
||||
@@ -34,7 +35,7 @@ If you wish to contribute to SymPy or like to get the latest updates as they
|
||||
come, install SymPy from git. To download the repository, execute the
|
||||
following from the command line::
|
||||
|
||||
git clone https://github.com/sympy/sympy.git
|
||||
git clone git://github.com/sympy/sympy.git
|
||||
|
||||
To update to the latest version, go into your repository and execute::
|
||||
|
||||
@@ -43,7 +44,7 @@ To update to the latest version, go into your repository and execute::
|
||||
If you want to install SymPy, but still want to use the git version, you can run
|
||||
from your repository::
|
||||
|
||||
python setupegg.py develop
|
||||
setupegg.py develop
|
||||
|
||||
This will cause the installed version to always point to the version in the git
|
||||
directory.
|
||||
@@ -51,14 +52,9 @@ directory.
|
||||
Other Methods
|
||||
=============
|
||||
|
||||
You may also install SymPy using pip or from source. In addition, most Linux
|
||||
and Python distributions have some SymPy version available to install using
|
||||
their package manager. Here is a list of several such Python distributions:
|
||||
|
||||
* `Anaconda <https://www.anaconda.com/download/>`_
|
||||
* `Enthought Canopy <https://www.enthought.com/product/canopy/>`_
|
||||
* `ActivePython <https://www.activestate.com/activepython>`_
|
||||
* `Spack <https://spack.io/>`_
|
||||
An installation executable (.exe) is available for Windows users at the
|
||||
`downloads site`_. In addition, various Linux distributions have SymPy
|
||||
available as a package. You may also install SymPy from source or using pip.
|
||||
|
||||
Run SymPy
|
||||
=========
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (https://www.inkscape.org/) -->
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (https://www.inkscape.org/) -->
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
|
||||
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
@@ -1,19 +0,0 @@
|
||||
========
|
||||
Algebras
|
||||
========
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The Algebras module for SymPy provides support
|
||||
for basic algebraic operations on Quaternions.
|
||||
|
||||
Quaternion Reference
|
||||
--------------------
|
||||
|
||||
.. automodule:: sympy.algebras
|
||||
|
||||
This section lists the classes implemented by the Algebras module.
|
||||
|
||||
.. autoclass:: Quaternion
|
||||
:members:
|
||||
@@ -1,6 +0,0 @@
|
||||
======
|
||||
Common
|
||||
======
|
||||
|
||||
.. automodule:: sympy.assumptions.handlers.common
|
||||
:members:
|
||||
@@ -11,8 +11,6 @@ Contents
|
||||
:maxdepth: 3
|
||||
|
||||
calculus.rst
|
||||
common.rst
|
||||
matrices.rst
|
||||
ntheory.rst
|
||||
order.rst
|
||||
sets.rst
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
========
|
||||
Matrices
|
||||
========
|
||||
|
||||
.. automodule:: sympy.assumptions.handlers.matrices
|
||||
:members:
|
||||
@@ -1,8 +1,6 @@
|
||||
.. _assumptions_module:
|
||||
|
||||
===========
|
||||
Assumptions
|
||||
===========
|
||||
==================
|
||||
Assumptions module
|
||||
==================
|
||||
|
||||
.. automodule:: sympy.assumptions
|
||||
|
||||
@@ -123,7 +121,7 @@ in notable speed improvements.
|
||||
|
||||
Logic inference used in one ask could be used to speed up further queries, and
|
||||
current system does not take advantage of this. For example, a truth maintenance
|
||||
system (https://en.wikipedia.org/wiki/Truth_maintenance_system) could be implemented.
|
||||
system (http://en.wikipedia.org/wiki/Truth_maintenance_system) could be implemented.
|
||||
|
||||
Misc
|
||||
====
|
||||
|
||||
@@ -10,10 +10,5 @@ Calculus
|
||||
.. automodule:: sympy.calculus.singularities
|
||||
:members:
|
||||
|
||||
.. _finite_diff:
|
||||
|
||||
.. automodule:: sympy.calculus.finite_diff
|
||||
:members:
|
||||
|
||||
.. automodule:: sympy.calculus.util
|
||||
.. automodule :: sympy.calculus.finite_diff
|
||||
:members:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
===============
|
||||
Category Theory
|
||||
===============
|
||||
Category Theory Module
|
||||
======================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.. _codegen_prose:
|
||||
|
||||
===============
|
||||
Code Generation
|
||||
===============
|
||||
================================================
|
||||
Structural Details of Code Generation with SymPy
|
||||
================================================
|
||||
|
||||
Several submodules in SymPy allow one to generate directly compilable and
|
||||
executable code in a variety of different programming languages from SymPy
|
||||
@@ -56,23 +56,37 @@ Code printers (sympy.printing)
|
||||
------------------------------
|
||||
|
||||
This is where the meat of code generation is; the translation of SymPy
|
||||
expressions to specific languages. Supported languages are C
|
||||
(:py:func:`sympy.printing.ccode.ccode`), R
|
||||
(:py:func:`sympy.printing.rcode.rcode`), Fortran 95
|
||||
(:py:func:`sympy.printing.fcode.fcode`), JavaScript
|
||||
(:py:func:`sympy.printing.jscode.jscode`), Julia
|
||||
(:py:func:`sympy.printing.julia.julia_code`), Mathematica
|
||||
(:py:func:`sympy.printing.mathematica.mathematica_code`), Octave/Matlab
|
||||
(:py:func:`sympy.printing.octave.octave_code`), Rust
|
||||
(:py:func:`sympy.printing.rust.rust_code`), Python (print_python, which is
|
||||
actually more like a lightweight version of codegen for Python, and
|
||||
Python (:py:func:`sympy.printing.pycode.pycode`), and
|
||||
:py:func:`sympy.printing.lambdarepr.lambdarepr`, which supports many libraries
|
||||
(like NumPy), and theano
|
||||
(:py:func:`sympy.printing.theanocode.theano_function`). The code printers are
|
||||
special cases of the other prints in SymPy (str printer, pretty printer, etc.).
|
||||
|
||||
An important distinction is that the code printer has to deal with assignments
|
||||
(using the :class:`sympy.codegen.ast.Assignment` object). This serves as
|
||||
(using the :class:`sympy.printing.codeprinter.Assignment` object).This serves as
|
||||
building blocks for the code printers and hence the ``codegen`` module. An
|
||||
example that shows the use of ``Assignment`` in C code::
|
||||
example that shows the use of ``Assignment``::
|
||||
|
||||
>>> from sympy.codegen.ast import Assignment
|
||||
>>> print(ccode(Assignment(x, y + 1)))
|
||||
x = y + 1;
|
||||
>>> mat = Matrix([x, y, z]).T
|
||||
>>> known_mat = MatrixSymbol('K', 1, 3)
|
||||
>>> Assignment(known_mat, mat)
|
||||
K := [x y z]
|
||||
>>> Assignment(known_mat, mat).lhs
|
||||
K
|
||||
>>> Assignment(known_mat, mat).rhs
|
||||
[x y z]
|
||||
|
||||
Here is another simple example of printing a C version of a SymPy expression::
|
||||
Here is a simple example of printing a C version of a SymPy expression::
|
||||
|
||||
>>> expr = (Rational(-1, 2) * Z * k * (e**2) / r)
|
||||
>>> expr
|
||||
@@ -164,8 +178,8 @@ An example of Mathematica code printer::
|
||||
|
||||
>>> expr = summation(expr, (n, -1, 1))
|
||||
>>> mathematica_code(expr)
|
||||
T*(x[-T]*Sin[(T + t)/T]/(T + t) + x[T]*Sin[(-T + t)/T]/(-T + t) + x[0]*Sin[t/T
|
||||
]/t)
|
||||
T*x[-T]*Sin[(T + t)/T]/(T + t) + T*x[T]*Sin[(-T + t)/T]/(-T + t) + T*x[0]*Sin[
|
||||
t/T]/t
|
||||
|
||||
We can go through a common expression in different languages we support and see
|
||||
how it works::
|
||||
@@ -289,12 +303,12 @@ For example::
|
||||
>>> [arg.result_var for arg in routine.results] # doctest: +SKIP
|
||||
[result₅₁₄₂₃₄₁₆₈₁₃₉₇₇₁₉₄₂₈]
|
||||
>>> [arg.expr for arg in routine.results]
|
||||
⎡ __________ ⎤
|
||||
⎢ y ╱ (2 - y)! -2⋅x ⎥
|
||||
⎢4⋅√6⋅(4⋅x) ⋅ ╱ ──────── ⋅ℯ ⋅assoc_laguerre(2 - y, 2⋅y + 1, 4⋅x)⎥
|
||||
⎢ ╲╱ (y + 3)! ⎥
|
||||
⎢────────────────────────────────────────────────────────────────────⎥
|
||||
⎣ 3 ⎦
|
||||
⎡ ___________ ⎤
|
||||
⎢ y ╱ (-y + 2)! -2⋅x ⎥
|
||||
⎢4⋅√6⋅(4⋅x) ⋅ ╱ ───────── ⋅ℯ ⋅assoc_laguerre(-y + 2, 2⋅y + 1, 4⋅x)⎥
|
||||
⎢ ╲╱ (y + 3)! ⎥
|
||||
⎢──────────────────────────────────────────────────────────────────────⎥
|
||||
⎣ 3 ⎦
|
||||
>>> [arg.name for arg in routine.arguments]
|
||||
[x, y]
|
||||
|
||||
@@ -486,7 +500,7 @@ implies 'Universal functions' and follows an ideology set by NumPy. The main
|
||||
point of ufuncify as compared to autowrap is that it allows arrays as arguments
|
||||
and can operate in an element-by-element fashion. The core operation done
|
||||
element-wise is in accordance to Numpy's array broadcasting rules. See `this
|
||||
<https://docs.scipy.org/doc/numpy/reference/ufuncs.html>`_ for more.
|
||||
<http://docs.scipy.org/doc/numpy/reference/ufuncs.html>`_ for more.
|
||||
|
||||
>>> from sympy import *
|
||||
>>> from sympy.abc import x
|
||||
@@ -498,16 +512,16 @@ element-wise is in accordance to Numpy's array broadcasting rules. See `this
|
||||
This function ``f`` consumes and returns a NumPy array. Generally ``ufuncify``
|
||||
performs at least as well as ``lambdify``. If the expression is complicated
|
||||
then ``ufuncify`` often significantly outperforms the NumPy backed solution.
|
||||
Jensen has a good `blog post <https://ojensen.wordpress.com/2010/08/10/fast-ufunc-ish-hydrogen-solutions/>`_ on this topic.
|
||||
Jensen has a good `blog post <http://ojensen.wordpress.com/2010/08/10/fast-ufunc-ish-hydrogen-solutions/>`_ on this topic.
|
||||
|
||||
Let us see an example for some quantitative analysis::
|
||||
|
||||
>>> from sympy.physics.hydrogen import R_nl
|
||||
>>> expr = R_nl(3, 1, x, 6)
|
||||
>>> expr
|
||||
-2⋅x
|
||||
8⋅x⋅(4 - 4⋅x)⋅ℯ
|
||||
───────────────────
|
||||
-2⋅x
|
||||
8⋅x⋅(-4⋅x + 4)⋅ℯ
|
||||
────────────────────
|
||||
3
|
||||
|
||||
The lambdify function translates SymPy expressions into Python functions,
|
||||
@@ -542,19 +556,17 @@ There are other facilities available with SymPy to do efficient numeric
|
||||
computation. See :ref:`this<numeric_computation>` page for a comparison among them.
|
||||
|
||||
|
||||
Classes and functions for rewriting expressions (sympy.codegen.rewriting)
|
||||
-------------------------------------------------------------------------
|
||||
Special (finite precision arithmetic) math functions
|
||||
----------------------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.rewriting
|
||||
.. automodule:: sympy.codegen.cfunctions
|
||||
:members:
|
||||
|
||||
.. automodule:: sympy.codegen.matrix_nodes
|
||||
:members:
|
||||
|
||||
Tools for simplifying expressions using approximations (sympy.codegen.approximations)
|
||||
-------------------------------------------------------------------------------------
|
||||
Fortran specific functions
|
||||
--------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.approximations
|
||||
.. automodule:: sympy.codegen.ffunctions
|
||||
:members:
|
||||
|
||||
Classes for abstract syntax trees (sympy.codegen.ast)
|
||||
@@ -562,63 +574,3 @@ Classes for abstract syntax trees (sympy.codegen.ast)
|
||||
|
||||
.. automodule:: sympy.codegen.ast
|
||||
:members:
|
||||
|
||||
Special C math functions (sympy.codegen.cfunctions)
|
||||
---------------------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.cfunctions
|
||||
:members:
|
||||
|
||||
C specific AST nodes (sympy.codegen.cnodes)
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.cnodes
|
||||
:members:
|
||||
|
||||
|
||||
C++ specific AST nodes (sympy.codegen.cxxnodes)
|
||||
-----------------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.cxxnodes
|
||||
:members:
|
||||
|
||||
Fortran specific AST nodes (sympy.codegen.fnodes)
|
||||
-------------------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.fnodes
|
||||
:members:
|
||||
|
||||
|
||||
Algorithms (sympy.codegen.algorithms)
|
||||
-------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.algorithms
|
||||
:members:
|
||||
|
||||
|
||||
Python utilities (sympy.codegen.pyutils)
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.pyutils
|
||||
:members:
|
||||
|
||||
|
||||
C utilities (sympy.codegen.cutils)
|
||||
----------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.cutils
|
||||
:members:
|
||||
|
||||
|
||||
Fortran utilities (sympy.codegen.futils)
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.futils
|
||||
:members:
|
||||
|
||||
|
||||
Array utilities (sympy.codegen.array_utils)
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: sympy.codegen.array_utils
|
||||
:members:
|
||||
|
||||
@@ -42,7 +42,7 @@ returned.
|
||||
|
||||
Example of construction of a finitely-presented group.
|
||||
The symmetric group of degree 4 may be represented as a two generator group
|
||||
with presentation `\left\langle a, b \mid a^2, b^3, (ab)^4 \right\rangle`. Giving the relations as a
|
||||
with presentation `\langle a, b \mid a^2, b^3, (ab)^4 \rangle`. Giving the relations as a
|
||||
list of relators, group in SymPy would be specified as:
|
||||
|
||||
>>> F, a, b = free_group("a, b")
|
||||
@@ -51,7 +51,7 @@ list of relators, group in SymPy would be specified as:
|
||||
<fp group on the generators (a, b)>
|
||||
|
||||
Currently groups with relators having presentation like
|
||||
`\left\langle r, s, t \mid r^2, s^2, t^2, rst = str = trs \right\rangle` will have to be specified as:
|
||||
`\langle r, s, t \mid r^2, s^2, t^2, rst = str = trs \rangle` will have to be specified as:
|
||||
|
||||
>>> F, r, s, t = free_group("r, s, t")
|
||||
>>> G = FpGroup(F, [r**2, s**2, t**2, r*s*t*r**-1*t**-1*s**-1, s*t*r*s**-1*r**-1*t**-1])
|
||||
@@ -174,12 +174,12 @@ manipulate the algorithm, like
|
||||
have finite index, and even if it has it may take many more intermediate
|
||||
cosets than the actual index of the subgroup is. To avoid a coset enumeration
|
||||
"running away" therefore SymPy has a "safety stop" built-in. This is
|
||||
controlled by this variable. To change it, use `max_cosets` keyword.
|
||||
For example:
|
||||
controlled by this variable. For example:
|
||||
|
||||
>>> CosetTable.coset_table_max_limit = 50
|
||||
>>> F, a, b = free_group("a, b")
|
||||
>>> Cox = FpGroup(F, [a**6, b**6, (a*b)**2, (a**2*b**2)**2, (a**3*b**3)**5])
|
||||
>>> C_r = coset_enumeration_r(Cox, [a], max_cosets=50)
|
||||
>>> C_r = coset_enumeration_r(Cox, [a])
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: the coset enumeration has defined more than 50 cosets
|
||||
@@ -209,12 +209,12 @@ whose index does not exceed some (modest) integer bound.
|
||||
Low Index Subgroups
|
||||
```````````````````
|
||||
|
||||
``low_index_subgroups(G, N)``: Given a finitely presented group `G = \left\langle X \mid R \right\rangle`
|
||||
``low_index_subgroups(G, N)``: Given a finitely presented group `G = \langle X \mid R \rangle`
|
||||
(can be a free group), and ``N`` a positive integer, determine the conjugacy classes of
|
||||
subgroups of ``G`` whose indices is less than or equal to ``N``.
|
||||
|
||||
For example to find all subgroups of `G = \left\langle a, b \mid a^2 = b^3 = (ab)^4 = 1 \right\rangle`
|
||||
having index `\le` 4, can be found as follows:
|
||||
For example to find all subgroups of `G = \langle a, b \mid a^2 = b^3 = (ab)^4 = 1 \rangle`
|
||||
having index <= 4, can be found as follows:
|
||||
|
||||
>>> from sympy.combinatorics.fp_groups import low_index_subgroups
|
||||
>>> F, a, b = free_group("a, b")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.. _combinatiorics-docs:
|
||||
|
||||
=============
|
||||
Combinatorics
|
||||
=============
|
||||
====================
|
||||
Combinatorics Module
|
||||
====================
|
||||
|
||||
Contents
|
||||
========
|
||||
@@ -23,4 +23,3 @@ Contents
|
||||
testutil.rst
|
||||
tensor_can.rst
|
||||
fp_groups.rst
|
||||
pc_groups.rst
|
||||
|
||||
@@ -1,307 +0,0 @@
|
||||
Polycyclic Groups
|
||||
=================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This module presents the functionality designed for computing with
|
||||
polycyclic groups(PcGroup for short). The name of the corresponding
|
||||
SymPy object is ``PolycyclicGroup``. The functions or classes described
|
||||
here are studied under **Computational Group Theory**.
|
||||
|
||||
Overview of functionalities
|
||||
```````````````````````````
|
||||
|
||||
* The construction of PolycyclicGroup from a given PermutationGroup.
|
||||
|
||||
* Computation of polycyclic generating sequence(pcgs for short) and
|
||||
polycyclic series(pc_series).
|
||||
|
||||
* Computation of relative order for polycyclic series.
|
||||
|
||||
* Implementation of class Collector which can be treated as a base for polycylic groups.
|
||||
|
||||
* Implementation of polycyclic group presentation(pc_presentation for short).
|
||||
|
||||
* Computation of exponent vector, depth and leading exponent for a given element
|
||||
of a polycyclic group.
|
||||
|
||||
For a description of fundamental algorithms of polycyclic groups, we
|
||||
often make use of *Handbook of Computational Group Theory*.
|
||||
|
||||
|
||||
The Construction of Polycyclic Groups
|
||||
-------------------------------------
|
||||
|
||||
Given a Permutation Group, A Polycyclic Group is constructed by computing the
|
||||
corresponding polycylic generating sequence, polycyclic series and it's
|
||||
relative order.
|
||||
|
||||
Attributes of PolycyclicGroup
|
||||
`````````````````````````````
|
||||
|
||||
* ``pc_sequence`` : Polycyclic sequence is formed by collecting all the missing
|
||||
generators between the adjacent groups in the derived series of given
|
||||
permutation group.
|
||||
|
||||
* ``pc_series`` : Polycyclic series is formed by adding all the missing generators
|
||||
of ``der[i+1]`` in ``der[i]``, where ``der`` represents derived series.
|
||||
|
||||
* ``relative_order`` : A list, computed by the ratio of adjacent groups in pc_series.
|
||||
|
||||
* ``collector`` : By default, it is None. Collector class provides the polycyclic presentation.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> G = SymmetricGroup(4)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> len(PcGroup.pcgs)
|
||||
4
|
||||
>>> pc_series = PcGroup.pc_series
|
||||
>>> pc_series[0]==G
|
||||
True
|
||||
>>> gen = pc_series[len(pc_series)-1].generators[0]
|
||||
>>> gen.is_identity
|
||||
True
|
||||
>>> PcGroup.relative_order
|
||||
[2, 3, 2, 2]
|
||||
|
||||
|
||||
The Construction of Collector
|
||||
-----------------------------
|
||||
|
||||
Collector is one of the attributes of class PolycyclicGroup.
|
||||
|
||||
Attributes of Collector
|
||||
```````````````````````
|
||||
|
||||
Collector posses all the attributes of PolycyclicGroup, In addition there are
|
||||
few more attributes which are defined below:
|
||||
|
||||
* ``free_group`` : free_group provides the mapping of polycyclic generating sequence with
|
||||
the free group elements.
|
||||
|
||||
* ``pc_presentation`` : Provides the presentation of polycyclic groups with the
|
||||
help of power and conjugate relators.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> G = SymmetricGroup(3)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> Collector = PcGroup.collector
|
||||
>>> Collector.free_group
|
||||
<free group on the generators (x0, x1)>
|
||||
>>> Collector.pc_presentation
|
||||
{x0**2: (), x1**3: (), x0**-1*x1*x0: x1**2}
|
||||
|
||||
|
||||
Computation of Minimal Uncollected Subword
|
||||
``````````````````````````````````````````
|
||||
|
||||
A word ``V`` defined on generators in the free_group of pc_group is a minimal
|
||||
uncollected subword of the word ``W`` if ``V`` is a subword of ``W`` and it has one of
|
||||
the following form:
|
||||
|
||||
* `v = {x_{i+1}}^{a_j}x_i`
|
||||
* `v = {x_{i+1}}^{a_j}{x_i}^{-1}`
|
||||
* `v = {x_i}^{a_j}`
|
||||
|
||||
`a_j \notin \{0, \ldots \mathrm{relative\_order}[j]-1\}`.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> from sympy.combinatorics.free_groups import free_group
|
||||
>>> G = SymmetricGroup(4)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> collector = PcGroup.collector
|
||||
>>> F, x1, x2 = free_group("x1, x2")
|
||||
>>> word = x2**2*x1**7
|
||||
>>> collector.minimal_uncollected_subword(word)
|
||||
((x2, 2),)
|
||||
|
||||
|
||||
Computation of Subword Index
|
||||
````````````````````````````
|
||||
|
||||
For a given word and it's subword, subword_index computes the
|
||||
starting and ending index of the subword in the word.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> from sympy.combinatorics.free_groups import free_group
|
||||
>>> G = SymmetricGroup(4)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> collector = PcGroup.collector
|
||||
>>> F, x1, x2 = free_group("x1, x2")
|
||||
>>> word = x2**2*x1**7
|
||||
>>> w = x2**2*x1
|
||||
>>> collector.subword_index(word, w)
|
||||
(0, 3)
|
||||
>>> w = x1**7
|
||||
>>> collector.subword_index(word, w)
|
||||
(2, 9)
|
||||
|
||||
|
||||
Computation of Collected Word
|
||||
`````````````````````````````
|
||||
|
||||
A word ``W`` is called collected, if ``W`` `= {x_{i_1}}^{a_1} \ldots {x_{i_r}}^{a_r}`
|
||||
with `i_1 < i_2< \ldots < i_r` and `a_j` is in `\{1 \ldots s_{j-1}\}`, where `s_j`
|
||||
represents the respective relative order.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> from sympy.combinatorics.perm_groups import PermutationGroup
|
||||
>>> from sympy.combinatorics.free_groups import free_group
|
||||
>>> G = SymmetricGroup(4)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> collector = PcGroup.collector
|
||||
>>> F, x0, x1, x2, x3 = free_group("x0, x1, x2, x3")
|
||||
>>> word = x3*x2*x1*x0
|
||||
>>> collected_word = collector.collected_word(word)
|
||||
>>> free_to_perm = {}
|
||||
>>> free_group = collector.free_group
|
||||
>>> for sym, gen in zip(free_group.symbols, collector.pcgs):
|
||||
... free_to_perm[sym] = gen
|
||||
>>> G1 = PermutationGroup()
|
||||
>>> for w in word:
|
||||
... sym = w[0]
|
||||
... perm = free_to_perm[sym]
|
||||
... G1 = PermutationGroup([perm] + G1.generators)
|
||||
>>> G2 = PermutationGroup()
|
||||
>>> for w in collected_word:
|
||||
... sym = w[0]
|
||||
... perm = free_to_perm[sym]
|
||||
... G2 = PermutationGroup([perm] + G2.generators)
|
||||
>>> G1 == G2
|
||||
True
|
||||
|
||||
|
||||
Computation of Polycyclic Presentation
|
||||
--------------------------------------
|
||||
|
||||
The computation of presentation starts from the bottom of the pcgs and polycyclic series.
|
||||
Storing all the previous generators from pcgs and then taking the last generator
|
||||
as the generator which acts as a conjugator and conjugates all the previous
|
||||
generators in the list.
|
||||
|
||||
To get a clear picture, start with an example of SymmetricGroup(4). For S(4) there are 4
|
||||
generators in pcgs say `[x_0, x_1, x_2, x_3]` and the relative_order vector is [2, 3, 2, 2].
|
||||
Starting from bottom of this sequence the presentation is computed in order as below.
|
||||
|
||||
using only `[x_3]` from ``pcgs`` and ``pc_series[4]`` compute:
|
||||
|
||||
* `x_3^2`
|
||||
|
||||
using only `[x_3]` from ``pcgs`` and ``pc_series[3]`` compute:
|
||||
|
||||
* `x_2^2`
|
||||
* `x_2^{-1}x_3x_2`
|
||||
|
||||
using `[x_3, x_2]` from ``pcgs`` and ``pc_series[2]`` compute:
|
||||
|
||||
* `x_1^3`
|
||||
* `x_1^{-1}x_3x_1`
|
||||
* `x_1^{-1}x_2x_1`
|
||||
|
||||
using `[x_3, x_2, x_1]` from ``pcgs`` and ``pc_series[1]`` compute:
|
||||
|
||||
* `x_0^2`
|
||||
* `x_0^{-1}x_3x_0`
|
||||
* `x_0^{-1}x_2x_0`
|
||||
* `x_0^{-1}x_1x_0`
|
||||
|
||||
|
||||
One thing to note is same group can have different pcgs due to variying derived_series which,
|
||||
results in different polycyclic presentations.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> from sympy.combinatorics.permutations import Permutation
|
||||
>>> G = SymmetricGroup(4)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> collector = PcGroup.collector
|
||||
>>> pcgs = PcGroup.pcgs
|
||||
>>> len(pcgs)
|
||||
4
|
||||
>>> free_group = collector.free_group
|
||||
>>> pc_resentation = collector.pc_presentation
|
||||
>>> free_to_perm = {}
|
||||
>>> for s, g in zip(free_group.symbols, pcgs):
|
||||
... free_to_perm[s] = g
|
||||
>>> for k, v in pc_resentation.items():
|
||||
... k_array = k.array_form
|
||||
... if v != ():
|
||||
... v_array = v.array_form
|
||||
... lhs = Permutation()
|
||||
... for gen in k_array:
|
||||
... s = gen[0]
|
||||
... e = gen[1]
|
||||
... lhs = lhs*free_to_perm[s]**e
|
||||
... if v == ():
|
||||
... assert lhs.is_identity
|
||||
... continue
|
||||
... rhs = Permutation()
|
||||
... for gen in v_array:
|
||||
... s = gen[0]
|
||||
... e = gen[1]
|
||||
... rhs = rhs*free_to_perm[s]**e
|
||||
... assert lhs == rhs
|
||||
|
||||
|
||||
Computation of Exponent Vector
|
||||
------------------------------
|
||||
|
||||
Any generator of the polycyclic group can be represented with the help of it's
|
||||
polycyclic generating sequence. Hence, the length of exponent vector is equal to
|
||||
the length of the pcgs.
|
||||
|
||||
A given generator ``g`` of the polycyclic group, can be represented as
|
||||
`g = x_1^{e_1} \ldots x_n^{e_n}`, where `x_i` represents polycyclic generators
|
||||
and ``n`` is the number of generators in the free_group equal to the length of pcgs.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> from sympy.combinatorics.permutations import Permutation
|
||||
>>> G = SymmetricGroup(4)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> collector = PcGroup.collector
|
||||
>>> pcgs = PcGroup.pcgs
|
||||
>>> collector.exponent_vector(G[0])
|
||||
[1, 0, 0, 0]
|
||||
>>> exp = collector.exponent_vector(G[1])
|
||||
>>> g = Permutation()
|
||||
>>> for i in range(len(exp)):
|
||||
... g = g*pcgs[i]**exp[i] if exp[i] else g
|
||||
>>> assert g == G[1]
|
||||
|
||||
|
||||
Depth of Polycyclic generator
|
||||
`````````````````````````````
|
||||
|
||||
Depth of a given polycyclic generator is defined as the index of the first
|
||||
non-zero entry in the exponent vector.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> G = SymmetricGroup(3)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> collector = PcGroup.collector
|
||||
>>> collector.depth(G[0])
|
||||
2
|
||||
>>> collector.depth(G[1])
|
||||
1
|
||||
|
||||
|
||||
Computation of Leading Exponent
|
||||
```````````````````````````````
|
||||
|
||||
Leading exponent represents the exponent of polycyclic generator at the above depth.
|
||||
|
||||
>>> from sympy.combinatorics.named_groups import SymmetricGroup
|
||||
>>> G = SymmetricGroup(3)
|
||||
>>> PcGroup = G.polycyclic_group()
|
||||
>>> collector = PcGroup.collector
|
||||
>>> collector.leading_exponent(G[1])
|
||||
1
|
||||
|
||||
|
||||
Bibliography
|
||||
------------
|
||||
|
||||
.. [Ho05] Derek F. Holt,
|
||||
Handbook of Computational Group Theory.
|
||||
In the series 'Discrete Mathematics and its Applications',
|
||||
`Chapman & Hall/CRC 2005, xvi + 514 p <https://www.crcpress.com/Handbook-of-Computational-Group-Theory/Holt-Eick-OBrien/p/book/9781584883722>`_.
|
||||
@@ -1,6 +1,5 @@
|
||||
========
|
||||
Concrete
|
||||
========
|
||||
Concrete Mathematics
|
||||
====================
|
||||
|
||||
Hypergeometric terms
|
||||
--------------------
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
====
|
||||
Core
|
||||
====
|
||||
SymPy Core
|
||||
==========
|
||||
|
||||
sympify
|
||||
-------
|
||||
@@ -16,7 +15,7 @@ assumptions
|
||||
.. automodule:: sympy.core.assumptions
|
||||
|
||||
cache
|
||||
-----
|
||||
-------
|
||||
.. module:: sympy.core.cache
|
||||
|
||||
cacheit
|
||||
@@ -226,12 +225,6 @@ GoldenRatio
|
||||
.. autoclass:: GoldenRatio
|
||||
:members:
|
||||
|
||||
TribonacciConstant
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: TribonacciConstant
|
||||
:members:
|
||||
|
||||
power
|
||||
-----
|
||||
.. module:: sympy.core.power
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
============
|
||||
Cryptography
|
||||
============
|
||||
Basic Cryptography Module
|
||||
=========================
|
||||
|
||||
.. warning::
|
||||
|
||||
@@ -51,18 +50,10 @@ substitutions at different times in the message.
|
||||
|
||||
.. autofunction:: decipher_shift
|
||||
|
||||
.. autofunction:: encipher_rot13
|
||||
|
||||
.. autofunction:: decipher_rot13
|
||||
|
||||
.. autofunction:: encipher_affine
|
||||
|
||||
.. autofunction:: decipher_affine
|
||||
|
||||
.. autofunction:: encipher_atbash
|
||||
|
||||
.. autofunction:: decipher_atbash
|
||||
|
||||
.. autofunction:: encipher_substitution
|
||||
|
||||
.. autofunction:: encipher_vigenere
|
||||
@@ -141,8 +132,4 @@ substitutions at different times in the message.
|
||||
|
||||
.. autofunction:: encipher_gm
|
||||
|
||||
.. autofunction:: decipher_gm
|
||||
|
||||
.. autofunction:: encipher_railfence
|
||||
|
||||
.. autofunction:: decipher_railfence
|
||||
.. autofunction:: decipher_gm
|
||||
@@ -1,6 +1,5 @@
|
||||
=====================
|
||||
Differential Geometry
|
||||
=====================
|
||||
Differential Geometry Module
|
||||
============================
|
||||
|
||||
.. module:: sympy.diffgeom
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
========
|
||||
Discrete
|
||||
========
|
||||
|
||||
The ``discrete`` module in SymPy implements methods to compute discrete
|
||||
transforms and convolutions of finite sequences.
|
||||
|
||||
.. automodule:: sympy.discrete
|
||||
|
||||
Since the discrete transforms can be used to reduce the computational complexity
|
||||
of the discrete convolutions, the ``convolutions`` module makes use of the
|
||||
``transforms`` module for efficient computation (notable for long input sequences).
|
||||
|
||||
Transforms
|
||||
----------
|
||||
|
||||
.. module:: sympy.discrete.transforms
|
||||
|
||||
This section lists the methods which implement the basic transforms
|
||||
for discrete sequences.
|
||||
|
||||
Fast Fourier Transform
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: fft
|
||||
|
||||
.. autofunction:: ifft
|
||||
|
||||
Number Theoretic Transform
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: ntt
|
||||
|
||||
.. autofunction:: intt
|
||||
|
||||
Fast Walsh Hadamard Transform
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: fwht
|
||||
|
||||
.. autofunction:: ifwht
|
||||
|
||||
Möbius Transform
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: mobius_transform
|
||||
|
||||
.. autofunction:: inverse_mobius_transform
|
||||
|
||||
|
||||
Convolutions
|
||||
------------
|
||||
|
||||
.. module:: sympy.discrete.convolutions
|
||||
|
||||
This section lists the methods which implement the basic convolutions
|
||||
for discrete sequences.
|
||||
|
||||
Convolution
|
||||
^^^^^^^^^^^
|
||||
|
||||
This is a general method for calculating the convolution of discrete
|
||||
sequences, which internally calls one of the methods ``convolution_fft``,
|
||||
``convolution_ntt``, ``convolution_fwht``, or ``convolution_subset``.
|
||||
|
||||
.. autofunction:: convolution
|
||||
|
||||
Convolution using Fast Fourier Transform
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: convolution_fft
|
||||
|
||||
Convolution using Number Theoretic Transform
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: convolution_ntt
|
||||
|
||||
Convolution using Fast Walsh Hadamard Transform
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: convolution_fwht
|
||||
|
||||
Subset Convolution
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: convolution_subset
|
||||
|
||||
Covering Product
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: covering_product
|
||||
|
||||
Intersecting Product
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autofunction:: intersecting_product
|
||||
@@ -1,7 +1,6 @@
|
||||
.. _evalf-label:
|
||||
|
||||
====================
|
||||
Numerical Evaluation
|
||||
Numerical evaluation
|
||||
====================
|
||||
|
||||
Basics
|
||||
@@ -70,7 +69,7 @@ This shows digits 999,951 through 1,000,000 of pi:
|
||||
|
||||
|
||||
High-precision calculations can be slow. It is recommended (but entirely
|
||||
optional) to install gmpy (https://code.google.com/p/gmpy/), which will
|
||||
optional) to install gmpy (http://code.google.com/p/gmpy/), which will
|
||||
significantly speed up computations such as the one above.
|
||||
|
||||
Floating-point numbers
|
||||
@@ -287,7 +286,7 @@ Oscillatory quadrature requires an integrand containing a factor cos(ax+b) or
|
||||
sin(ax+b). Note that many other oscillatory integrals can be transformed to
|
||||
this form with a change of variables:
|
||||
|
||||
>>> init_printing(use_unicode=False, wrap_line=False)
|
||||
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
|
||||
>>> intgrl = Integral(sin(1/x), (x, 0, 1)).transform(x, 1/x)
|
||||
>>> intgrl
|
||||
oo
|
||||
|
||||
@@ -66,36 +66,19 @@ fibonacci
|
||||
.. autoclass:: sympy.functions.combinatorial.numbers.fibonacci
|
||||
:members:
|
||||
|
||||
tribonacci
|
||||
----------
|
||||
|
||||
.. autoclass:: sympy.functions.combinatorial.numbers.tribonacci
|
||||
:members:
|
||||
|
||||
|
||||
harmonic
|
||||
--------
|
||||
|
||||
.. autoclass:: sympy.functions.combinatorial.numbers.harmonic
|
||||
:members:
|
||||
|
||||
|
||||
lucas
|
||||
-----
|
||||
|
||||
.. autoclass:: sympy.functions.combinatorial.numbers.lucas
|
||||
:members:
|
||||
|
||||
genocchi
|
||||
--------
|
||||
|
||||
.. autoclass:: sympy.functions.combinatorial.numbers.genocchi
|
||||
:members:
|
||||
|
||||
partition
|
||||
---------
|
||||
|
||||
.. autoclass:: sympy.functions.combinatorial.numbers.partition
|
||||
:members:
|
||||
|
||||
MultiFactorial
|
||||
--------------
|
||||
|
||||
@@ -66,11 +66,8 @@ principal_branch
|
||||
sympy.functions.elementary.trigonometric
|
||||
========================================
|
||||
|
||||
|
||||
.. _trionometric functions:
|
||||
|
||||
Trigonometric Functions
|
||||
========================
|
||||
Trionometric Functions
|
||||
======================
|
||||
|
||||
sin
|
||||
---
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
.. _functions:
|
||||
|
||||
=========
|
||||
Functions
|
||||
=========
|
||||
Functions Module
|
||||
****************
|
||||
|
||||
.. module:: sympy.functions
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
========
|
||||
Geometry
|
||||
========
|
||||
===============
|
||||
Geometry Module
|
||||
===============
|
||||
|
||||
|
||||
Introduction
|
||||
@@ -140,7 +140,7 @@ References
|
||||
|
||||
.. [WikiPappus] "Pappus's Hexagon Theorem" Wikipedia, the Free Encyclopedia.
|
||||
Web. 26 Apr. 2013.
|
||||
<https://en.wikipedia.org/wiki/Pappus's_hexagon_theorem>
|
||||
<http://en.wikipedia.org/wiki/Pappus's_hexagon_theorem>
|
||||
|
||||
Miscellaneous Notes
|
||||
-------------------
|
||||
|
||||
@@ -36,7 +36,7 @@ Here `D` is the Differential Operator and `L` is called the annihilator
|
||||
of the function.
|
||||
|
||||
A unique holonomic function can be defined from the annihilator and a set of
|
||||
initial conditions.
|
||||
initial conditons.
|
||||
For instance:
|
||||
|
||||
.. math::
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Converting other representations to holonomic
|
||||
=============================================
|
||||
|
||||
.. currentmodule:: sympy.holonomic.holonomic
|
||||
.. module:: sympy.holonomic.holonomic
|
||||
|
||||
Converting hypergeometric functions
|
||||
-----------------------------------
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.. _holonomic-docs:
|
||||
|
||||
=========
|
||||
Holonomic
|
||||
=========
|
||||
===================
|
||||
Holonomic Functions
|
||||
===================
|
||||
|
||||
.. automodule:: sympy.holonomic
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ a holonomic functions.
|
||||
>>> p * q
|
||||
HolonomicFunction((2) + (-2)*Dx + (1)*Dx**2, x, 0, [0, 1])
|
||||
|
||||
.. currentmodule:: sympy.holonomic.holonomic
|
||||
.. module:: sympy.holonomic.holonomic
|
||||
|
||||
Integration and Differentiation
|
||||
-------------------------------
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Representation of holonomic functions in SymPy
|
||||
==============================================
|
||||
|
||||
.. currentmodule:: sympy.holonomic.holonomic
|
||||
.. module:: sympy.holonomic.holonomic
|
||||
|
||||
Class :class:`DifferentialOperator` is used to represent the annihilator
|
||||
but we create differential operators easily using the function
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.. currentmodule:: sympy.holonomic.holonomic
|
||||
.. module:: sympy.holonomic.holonomic
|
||||
|
||||
Uses and Current limitations
|
||||
============================
|
||||
@@ -44,10 +44,10 @@ which initial conditions for the integrand are stored. Sometimes this gives an a
|
||||
For instance:
|
||||
|
||||
>>> expr_to_holonomic(sin(x)).integrate(x).to_expr()
|
||||
1 - cos(x)
|
||||
-cos(x) + 1
|
||||
>>> sin(x).integrate(x)
|
||||
-cos(x)
|
||||
|
||||
The indefinite integral of `\sin(x)` is `-\cos(x)`. But the output is `-\cos(x) + 1`
|
||||
which is `\int_{0}^{x} sin(x)dx`. Although both are considered correct but `-\cos(x)`
|
||||
is simpler.
|
||||
is simpler.
|
||||
@@ -16,49 +16,47 @@ access any SymPy module, or use the list below:
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
algebras.rst
|
||||
assumptions/index.rst
|
||||
calculus/index.rst
|
||||
categories.rst
|
||||
codegen.rst
|
||||
combinatorics/index.rst
|
||||
concrete.rst
|
||||
core.rst
|
||||
combinatorics/index.rst
|
||||
ntheory.rst
|
||||
crypto.rst
|
||||
diffgeom.rst
|
||||
solvers/diophantine.rst
|
||||
discrete.rst
|
||||
concrete.rst
|
||||
evalf.rst
|
||||
codegen.rst
|
||||
numeric-computation.rst
|
||||
functions/index.rst
|
||||
geometry/index.rst
|
||||
holonomic/index.rst
|
||||
simplify/hyperexpand.rst
|
||||
solvers/inequalities.rst
|
||||
integrals/integrals.rst
|
||||
liealgebras/index.rst
|
||||
logic.rst
|
||||
matrices/index.rst
|
||||
ntheory.rst
|
||||
numeric-computation.rst
|
||||
evalf.rst
|
||||
solvers/ode.rst
|
||||
parsing.rst
|
||||
solvers/pde.rst
|
||||
physics/index.rst
|
||||
plotting.rst
|
||||
polys/index.rst
|
||||
printing.rst
|
||||
plotting.rst
|
||||
assumptions/index.rst
|
||||
rewriting.rst
|
||||
series/index.rst
|
||||
sets.rst
|
||||
simplify/simplify.rst
|
||||
solvers/solvers.rst
|
||||
solvers/solveset.rst
|
||||
simplify/hyperexpand.rst
|
||||
stats.rst
|
||||
solvers/ode.rst
|
||||
solvers/pde.rst
|
||||
solvers/solvers.rst
|
||||
solvers/diophantine.rst
|
||||
solvers/inequalities.rst
|
||||
solvers/solveset.rst
|
||||
tensor/index.rst
|
||||
rewriting.rst
|
||||
utilities/index.rst
|
||||
parsing.rst
|
||||
calculus/index.rst
|
||||
physics/index.rst
|
||||
categories.rst
|
||||
diffgeom.rst
|
||||
vector/index.rst
|
||||
|
||||
Contributions to Docs
|
||||
Contributions to docs
|
||||
---------------------
|
||||
|
||||
All contributions are welcome. If you'd like to improve something, look into
|
||||
|
||||
@@ -161,7 +161,7 @@ is satisfies `G(\operatorname{Exp}(2 \pi i)z) = G(z)` for all `z \in \mathcal{S}
|
||||
be used to exploit the information. This is done transparently by the
|
||||
integration code.
|
||||
|
||||
.. [BlogPost] https://nessgrh.wordpress.com/2011/07/07/tricky-branch-cuts/
|
||||
.. [BlogPost] http://nessgrh.wordpress.com/2011/07/07/tricky-branch-cuts/
|
||||
|
||||
The G-Function Integration Theorems
|
||||
***********************************
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
=========
|
||||
Integrals
|
||||
=========
|
||||
Symbolic Integrals
|
||||
==================
|
||||
|
||||
.. module:: sympy.integrals
|
||||
|
||||
@@ -16,7 +15,7 @@ Examples
|
||||
SymPy can integrate a vast array of functions. It can integrate polynomial functions::
|
||||
|
||||
>>> from sympy import *
|
||||
>>> init_printing(use_unicode=False, wrap_line=False)
|
||||
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
|
||||
>>> x = Symbol('x')
|
||||
>>> integrate(x**2 + x + 1, x)
|
||||
3 2
|
||||
@@ -26,10 +25,10 @@ SymPy can integrate a vast array of functions. It can integrate polynomial funct
|
||||
|
||||
Rational functions::
|
||||
|
||||
>>> integrate(x/(x**2+2*x+1), x)
|
||||
1
|
||||
log(x + 1) + -----
|
||||
x + 1
|
||||
>>> integrate(x/(x**2+2*x+1), x)
|
||||
1
|
||||
log(x + 1) + -----
|
||||
x + 1
|
||||
|
||||
|
||||
Exponential-polynomial functions. These multiplicative combinations of polynomials and the functions ``exp``, ``cos`` and ``sin`` can be integrated by hand using repeated integration by parts, which is an extremely tedious process. Happily, SymPy will deal with these integrals.
|
||||
@@ -128,8 +127,6 @@ any order and any precision:
|
||||
|
||||
.. autofunction:: sympy.integrals.quadrature.gauss_jacobi
|
||||
|
||||
.. autofunction:: sympy.integrals.quadrature.gauss_lobatto
|
||||
|
||||
Integration over Polytopes
|
||||
==========================
|
||||
|
||||
@@ -173,7 +170,7 @@ For 2D Polygons
|
||||
Single Polynomial::
|
||||
|
||||
>>> from sympy.integrals.intpoly import *
|
||||
>>> init_printing(use_unicode=False, wrap_line=False)
|
||||
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
|
||||
>>> polytope_integrate(Polygon((0, 0), (0, 1), (1, 0)), x)
|
||||
1/6
|
||||
>>> polytope_integrate(Polygon((0, 0), (0, 1), (1, 0)), x + x*y + y**2)
|
||||
@@ -232,3 +229,4 @@ API reference
|
||||
-------------
|
||||
|
||||
.. autofunction:: sympy.integrals.intpoly.polytope_integrate
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
===========
|
||||
Lie Algebra
|
||||
===========
|
||||
==================
|
||||
Lie Algebra Module
|
||||
==================
|
||||
|
||||
.. automodule:: sympy.liealgebras
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
=====
|
||||
Logic
|
||||
=====
|
||||
Logic Module
|
||||
===============
|
||||
|
||||
.. module:: sympy.logic
|
||||
|
||||
@@ -47,7 +46,7 @@ from their truth tables-
|
||||
.. autofunction:: sympy.logic.boolalg.POSform
|
||||
|
||||
Boolean functions
|
||||
-----------------
|
||||
-----------------------
|
||||
|
||||
.. autoclass:: sympy.logic.boolalg.BooleanTrue
|
||||
|
||||
@@ -95,7 +94,7 @@ simplest forms.
|
||||
Inference
|
||||
---------
|
||||
|
||||
.. module:: sympy.logic.inference
|
||||
.. module: sympy.logic.inference
|
||||
|
||||
This module implements some inference routines in propositional logic.
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
Common Matrices
|
||||
===============
|
||||
|
||||
.. module:: sympy.matrices.common
|
||||
|
||||
MatrixCommon Class Reference
|
||||
----------------------------
|
||||
.. autoclass:: MatrixCommon
|
||||
:members:
|
||||
:inherited-members:
|
||||
@@ -9,7 +9,7 @@ The Matrix expression module allows users to write down statements like
|
||||
>>> X = MatrixSymbol('X', 3, 3)
|
||||
>>> Y = MatrixSymbol('Y', 3, 3)
|
||||
>>> (X.T*X).I*Y
|
||||
X**(-1)*X.T**(-1)*Y
|
||||
X^-1*X.T^-1*Y
|
||||
|
||||
>>> Matrix(X)
|
||||
Matrix([
|
||||
@@ -34,10 +34,6 @@ Matrix Expressions Core Reference
|
||||
:members:
|
||||
.. autoclass:: MatPow
|
||||
:members:
|
||||
.. autoclass:: HadamardProduct
|
||||
:members:
|
||||
.. autoclass:: HadamardPower
|
||||
:members:
|
||||
.. autoclass:: Inverse
|
||||
:members:
|
||||
.. autoclass:: Transpose
|
||||
|
||||
@@ -12,7 +12,6 @@ Contents:
|
||||
:maxdepth: 2
|
||||
|
||||
matrices.rst
|
||||
common.rst
|
||||
dense.rst
|
||||
sparse.rst
|
||||
immutablematrices.rst
|
||||
|
||||
@@ -10,7 +10,7 @@ The linear algebra module is designed to be as simple as possible. First, we
|
||||
import and declare our first ``Matrix`` object:
|
||||
|
||||
>>> from sympy.interactive.printing import init_printing
|
||||
>>> init_printing(use_unicode=False, wrap_line=False)
|
||||
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
|
||||
>>> from sympy.matrices import Matrix, eye, zeros, ones, diag, GramSchmidt
|
||||
>>> M = Matrix([[1,0,0], [0,0,0]]); M
|
||||
[1 0 0]
|
||||
@@ -325,31 +325,6 @@ but we can also apply functions to our matrix entries using ``applyfunc()``. Her
|
||||
[ ]
|
||||
[0 0 2]
|
||||
|
||||
If you want to extract a common factor from a matrix you can do so by
|
||||
applying ``gcd`` to the data of the matrix:
|
||||
|
||||
>>> from sympy.abc import x, y
|
||||
>>> from sympy import gcd
|
||||
>>> m = Matrix([[x, y], [1, x*y]]).inv(); m
|
||||
[ -x*y y ]
|
||||
[---------- ----------]
|
||||
[ 2 2 ]
|
||||
[- x *y + y - x *y + y]
|
||||
[ ]
|
||||
[ 1 -x ]
|
||||
[---------- ----------]
|
||||
[ 2 2 ]
|
||||
[- x *y + y - x *y + y]
|
||||
>>> gcd(tuple(_))
|
||||
1
|
||||
----------
|
||||
2
|
||||
- x *y + y
|
||||
>>> m/_
|
||||
[-x*y y ]
|
||||
[ ]
|
||||
[ 1 -x]
|
||||
|
||||
One more useful matrix-wide entry application function is the substitution function. Let's declare a matrix with symbolic entries then substitute a value. Remember we can substitute anything - even another symbol!:
|
||||
|
||||
>>> from sympy import Symbol
|
||||
@@ -523,31 +498,6 @@ So there is quite a bit that can be done with the module including eigenvalues,
|
||||
eigenvectors, nullspace calculation, cofactor expansion tools, and so on. From
|
||||
here one might want to look over the ``matrices.py`` file for all functionality.
|
||||
|
||||
MatrixDeterminant Class Reference
|
||||
---------------------------------
|
||||
.. autoclass:: MatrixDeterminant
|
||||
:members:
|
||||
|
||||
MatrixReductions Class Reference
|
||||
--------------------------------
|
||||
.. autoclass:: MatrixReductions
|
||||
:members:
|
||||
|
||||
MatrixSubspaces Class Reference
|
||||
-------------------------------
|
||||
.. autoclass:: MatrixSubspaces
|
||||
:members:
|
||||
|
||||
MatrixEigen Class Reference
|
||||
---------------------------
|
||||
.. autoclass:: MatrixEigen
|
||||
:members:
|
||||
|
||||
MatrixCalculus Class Reference
|
||||
------------------------------
|
||||
.. autoclass:: MatrixCalculus
|
||||
:members:
|
||||
|
||||
MatrixBase Class Reference
|
||||
--------------------------
|
||||
.. autoclass:: MatrixBase
|
||||
@@ -566,6 +516,8 @@ Matrix Exceptions Reference
|
||||
Matrix Functions Reference
|
||||
--------------------------
|
||||
|
||||
.. autofunction:: classof
|
||||
|
||||
.. autofunction:: sympy.matrices.dense.matrix_multiply_elementwise
|
||||
|
||||
.. autofunction:: sympy.matrices.dense.zeros
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
=============
|
||||
Number Theory
|
||||
=============
|
||||
====================
|
||||
|
||||
.. module:: sympy.ntheory.generate
|
||||
|
||||
@@ -50,8 +49,6 @@ Ntheory Functions Reference
|
||||
|
||||
.. autofunction:: factorint
|
||||
|
||||
.. autofunction:: factorrat
|
||||
|
||||
.. autofunction:: primefactors
|
||||
|
||||
.. autofunction:: divisors
|
||||
@@ -66,41 +63,21 @@ Ntheory Functions Reference
|
||||
|
||||
.. autofunction:: antidivisor_count
|
||||
|
||||
.. autoclass:: totient
|
||||
:members:
|
||||
.. autofunction:: totient
|
||||
|
||||
.. autoclass:: reduced_totient
|
||||
:members:
|
||||
.. autofunction:: reduced_totient
|
||||
|
||||
.. autoclass:: divisor_sigma
|
||||
:members:
|
||||
.. autofunction:: divisor_sigma
|
||||
|
||||
.. autoclass:: udivisor_sigma
|
||||
:members:
|
||||
.. autofunction:: udivisor_sigma
|
||||
|
||||
.. autofunction:: core
|
||||
|
||||
.. autofunction:: digits
|
||||
|
||||
.. autoclass:: primenu
|
||||
:members:
|
||||
.. autofunction:: primenu
|
||||
|
||||
.. autoclass:: primeomega
|
||||
:members:
|
||||
|
||||
.. autofunction:: mersenne_prime_exponent
|
||||
|
||||
.. autofunction:: is_perfect
|
||||
|
||||
.. autofunction:: is_mersenne_prime
|
||||
|
||||
.. autofunction:: abundance
|
||||
|
||||
.. autofunction:: is_abundant
|
||||
|
||||
.. autofunction:: is_deficient
|
||||
|
||||
.. autofunction:: is_amicable
|
||||
.. autofunction:: primeomega
|
||||
|
||||
.. module:: sympy.ntheory.modular
|
||||
|
||||
@@ -130,18 +107,8 @@ Ntheory Functions Reference
|
||||
|
||||
.. module:: sympy.ntheory.primetest
|
||||
|
||||
.. autofunction:: is_euler_pseudoprime
|
||||
|
||||
.. autofunction:: is_square
|
||||
|
||||
.. autofunction:: mr
|
||||
|
||||
.. autofunction:: is_lucas_prp
|
||||
|
||||
.. autofunction:: is_strong_lucas_prp
|
||||
|
||||
.. autofunction:: is_extra_strong_lucas_prp
|
||||
|
||||
.. autofunction:: isprime
|
||||
|
||||
.. module:: sympy.ntheory.residue_ntheory
|
||||
@@ -154,8 +121,6 @@ Ntheory Functions Reference
|
||||
|
||||
.. autofunction:: sqrt_mod
|
||||
|
||||
.. autofunction:: sqrt_mod_iter
|
||||
|
||||
.. autofunction:: quadratic_residues
|
||||
|
||||
.. autofunction:: nthroot_mod
|
||||
@@ -179,7 +144,3 @@ Ntheory Functions Reference
|
||||
.. module:: sympy.ntheory.egyptian_fraction
|
||||
|
||||
.. autofunction:: egyptian_fraction
|
||||
|
||||
.. module:: sympy.ntheory.bbp_pi
|
||||
|
||||
.. autofunction:: pi_hex_digits
|
||||
|
||||
@@ -66,8 +66,8 @@ powerful vectorized ufuncs that are backed by compiled C code.
|
||||
>>> import numpy
|
||||
>>> data = numpy.linspace(1, 10, 10000)
|
||||
>>> f(data)
|
||||
[ 0.84147098 0.84119981 0.84092844 ... -0.05426074 -0.05433146
|
||||
-0.05440211]
|
||||
[ 0.84147098 0.84119981 0.84092844 ..., -0.05426074 -0.05433146
|
||||
-0.05440211]
|
||||
|
||||
If you have array-based data this can confer a considerable speedup, on the
|
||||
order of 10 nano-seconds per element. Unfortunately numpy incurs some start-up
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
=======
|
||||
Parsing
|
||||
=======
|
||||
Parsing input
|
||||
=============
|
||||
|
||||
Parsing Functions Reference
|
||||
---------------------------
|
||||
@@ -91,27 +90,6 @@ change between releases, and become stricter, more relaxed, or some mix.
|
||||
|
||||
.. autoclass:: sympy.parsing.latex.LaTeXParsingError
|
||||
|
||||
|
||||
SymPy Expression Reference
|
||||
--------------------------
|
||||
|
||||
.. module:: sympy.parsing.sym_expr
|
||||
|
||||
.. autoclass:: SymPyExpression
|
||||
:members:
|
||||
|
||||
`Fortran` Parsing Reference
|
||||
---------------------------------
|
||||
|
||||
.. module:: sympy.parsing.fortran.fortran_parser
|
||||
|
||||
.. autoclass:: ASR2PyVisitor
|
||||
:members:
|
||||
|
||||
.. autofunction:: call_visitor
|
||||
|
||||
.. autofunction:: src_to_sympy
|
||||
|
||||
Runtime Installation
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -2,268 +2,113 @@
|
||||
Solving Beam Bending Problems using Singularity Functions
|
||||
===========================================================
|
||||
|
||||
To make this document easier to read, enable pretty printing:
|
||||
To make this document easier to read, we are going to enable pretty printing.
|
||||
|
||||
.. plot::
|
||||
:context: reset
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> from sympy import *
|
||||
>>> x, y, z = symbols('x y z')
|
||||
>>> init_printing(use_unicode=True, wrap_line=False)
|
||||
>>> from sympy import *
|
||||
>>> x, y, z = symbols('x y z')
|
||||
>>> init_printing(use_unicode=True, wrap_line=False)
|
||||
|
||||
Beam
|
||||
====
|
||||
|
||||
A planar beam is a structural element that is capable of withstanding load
|
||||
through resistance to internal shear and bending. Beams are characterized by
|
||||
their length, constraints, cross-sectional second moment of area, and elastic
|
||||
modulus. In SymPy, 2D beam objects are constructed by specifying the following
|
||||
properties:
|
||||
A Beam is a structural element that is capable of withstanding load
|
||||
primarily by resisting against bending. Beams are characterized by
|
||||
their second moment of area, their length and their elastic modulus.
|
||||
|
||||
In Sympy, we can construct a 2D beam objects with the following properties :
|
||||
|
||||
- Length
|
||||
- Elastic Modulus
|
||||
- Second Moment of Area
|
||||
- Variable : A symbol representing the location along the beam's length. By
|
||||
default, this is set to ``Symbol(x)``.
|
||||
- Variable : A symbol that can be used as a variable along the length. By default,
|
||||
this is set to ``Symbol(x)``.
|
||||
- Boundary Conditions
|
||||
- bc_slope : Boundary conditions for slope.
|
||||
- bc_deflection : Boundary conditions for deflection.
|
||||
- bc_slope : Boundary conditions for slope.
|
||||
- bc_deflection : Boundary conditions for deflection.
|
||||
- Load Distribution
|
||||
|
||||
Once the above are specified, the following methods are used to compute useful
|
||||
information about the loaded beam:
|
||||
We have following methods under the beam class:
|
||||
|
||||
- apply_load
|
||||
- solve_for_reaction_loads
|
||||
- shear_force
|
||||
- bending_moment
|
||||
- slope
|
||||
- deflection
|
||||
|
||||
- ``solve_for_reaction_loads()``
|
||||
- ``shear_force()``
|
||||
- ``bending_moment()``
|
||||
- ``slope()``
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Below are examples of a variety two dimensional beam bending problems.
|
||||
Let us solve some beam bending problems using this module :
|
||||
|
||||
Example 1
|
||||
---------
|
||||
|
||||
A cantilever beam 9 meters in length has a distributed constant load of 8 kN/m
|
||||
applied downward from the fixed end over a 5 meter distance. A counterclockwise
|
||||
moment of 50 kN-m is applied 5 meters from the fixed end. Lastly, a downward
|
||||
point load of 12 kN is applied at the free end of the beam.
|
||||
|
||||
::
|
||||
|
||||
y
|
||||
^
|
||||
|
|
||||
\\\\|
|
||||
\\\\| 8 kN/m
|
||||
\\\\|_________________
|
||||
\\\\|| | | | | | | | | 12 kN
|
||||
\\\\|V V V V V V V V V |
|
||||
\\\\|________________|_______________V
|
||||
\\\\| | |
|
||||
\\\\o - - - - - - - -⭯ 50 kN-m - - - | - - -> x
|
||||
\\\\|________________|_______________|
|
||||
\\\\| :
|
||||
\\\\|----------------|---------------|
|
||||
5.0 m 4.0 m
|
||||
A beam of length 9 meters is having a fixed support at the start.
|
||||
A distributed constant load of 8 kN/m is applied downward from the starting
|
||||
point till 5 meters away from the start. A clockwise moment of 50 kN-m is
|
||||
applied at 5 meters away from the start of the beam. A downward point load
|
||||
of 12 kN is applied at the end.
|
||||
|
||||
.. note::
|
||||
|
||||
The user is free to choose their own sign convention. In this case the
|
||||
upward forces and counterclockwise bending moment being positive.
|
||||
Since a user is free to choose its own sign convention we are considering
|
||||
the upward forces and clockwise bending moment being positive.
|
||||
|
||||
The beam must be initialized with the length, modulus of elasticity, and the
|
||||
second moment of area. These quantities can be symbols or numbers.
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> E, I = symbols('E, I')
|
||||
>>> b = Beam(9, E, I)
|
||||
|
||||
The three loads are applied to the beam using the ``apply_load()`` method. This
|
||||
method supports point forces, point moments, and polynomial distributed loads
|
||||
of any order, i.e. :math:`c, cx, cx^2, cx^3, \ldots``.
|
||||
|
||||
The 12 kN point load is in the negative direction, at the location of 9 meters,
|
||||
and the polynomial order is specified as -1:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.apply_load(-12, 9, -1)
|
||||
|
||||
The ``load`` attribute can then be used to access the loading function in
|
||||
singularity function form:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.load
|
||||
-1
|
||||
-12⋅<x - 9>
|
||||
|
||||
Similarly, the positive moment can be applied with a polynomial order -2:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.apply_load(50, 5, -2)
|
||||
|
||||
The distributed load is of order 0 and spans x=0 to x=5:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.apply_load(-8, 0, 0, end=5)
|
||||
|
||||
The fixed end imposes two boundary conditions: 1) no vertical deflection and 2)
|
||||
no rotation. These are specified by appending tuples of x values and the
|
||||
corresponding deflection or slope values:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.bc_deflection.append((0, 0))
|
||||
>>> b.bc_slope.append((0, 0))
|
||||
|
||||
These boundary conditions introduce an unknown reaction force and moment which
|
||||
need to be applied to the beam to maintain static equilibrium:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> R, M = symbols('R, M')
|
||||
>>> b.apply_load(R, 0, -1)
|
||||
>>> b.apply_load(M, 0, -2)
|
||||
>>> b.load
|
||||
-2 -1 0 -2 0 -1
|
||||
M⋅<x> + R⋅<x> - 8⋅<x> + 50⋅<x - 5> + 8⋅<x - 5> - 12⋅<x - 9>
|
||||
|
||||
These two variables can be solved for in terms of the applied loads and the
|
||||
final loading can be displayed:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.solve_for_reaction_loads(R, M)
|
||||
>>> b.reaction_loads
|
||||
{M: -258, R: 52}
|
||||
>>> b.load
|
||||
-2 -1 0 -2 0 -1
|
||||
- 258⋅<x> + 52⋅<x> - 8⋅<x> + 50⋅<x - 5> + 8⋅<x - 5> - 12⋅<x - 9>
|
||||
|
||||
At this point, the beam is fully defined and the internal shear and bending
|
||||
moments are calculated:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.shear_force()
|
||||
-1 0 1 -1 1 0
|
||||
- 258⋅<x> + 52⋅<x> - 8⋅<x> + 50⋅<x - 5> + 8⋅<x - 5> - 12⋅<x - 9>
|
||||
>>> b.bending_moment()
|
||||
0 1 2 0 2 1
|
||||
- 258⋅<x> + 52⋅<x> - 4⋅<x> + 50⋅<x - 5> + 4⋅<x - 5> - 12⋅<x - 9>
|
||||
|
||||
These can be visualized by calling the respective plot methods:
|
||||
|
||||
.. plot::
|
||||
:context:
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.plot_shear_force() # doctest: +SKIP
|
||||
>>> b.plot_bending_moment() # doctest: +SKIP
|
||||
|
||||
The beam will deform under load and the slope and deflection can be determined
|
||||
with:
|
||||
|
||||
.. plot::
|
||||
:context: close-figs
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.slope()
|
||||
3 3
|
||||
1 2 4⋅<x> 1 4⋅<x - 5> 2
|
||||
- 258⋅<x> + 26⋅<x> - ────── + 50⋅<x - 5> + ────────── - 6⋅<x - 9>
|
||||
3 3
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
>>> b.deflection()
|
||||
3 4 4
|
||||
2 26⋅<x> <x> 2 <x - 5> 3
|
||||
- 129⋅<x> + ─────── - ──── + 25⋅<x - 5> + ──────── - 2⋅<x - 9>
|
||||
3 3 3
|
||||
─────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
The slope and deflection of the beam can be plotted so long as numbers are
|
||||
provided for the modulus and second moment:
|
||||
|
||||
.. plot::
|
||||
:context: close-figs
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.plot_slope(subs={E: 20E9, I: 3.25E-6}) # doctest: +SKIP
|
||||
>>> b.plot_deflection(subs={E: 20E9, I: 3.25E-6}) # doctest: +SKIP
|
||||
|
||||
All of the plots can be shown in one figure with:
|
||||
|
||||
.. plot::
|
||||
:context: close-figs
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> b.plot_loading_results(subs={E: 20E9, I: 3.25E-6}) # doctest: +SKIP
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> from sympy import symbols
|
||||
>>> E, I = symbols('E, I')
|
||||
>>> R1, M1 = symbols('R1, M1')
|
||||
>>> b = Beam(9, E, I)
|
||||
>>> b.apply_load(R1, 0, -1)
|
||||
>>> b.apply_load(M1, 0, -2)
|
||||
>>> b.apply_load(-8, 0, 0, end=5)
|
||||
>>> b.apply_load(50, 5, -2)
|
||||
>>> b.apply_load(-12, 9, -1)
|
||||
>>> b.bc_slope.append((0, 0))
|
||||
>>> b.bc_deflection.append((0, 0))
|
||||
>>> b.solve_for_reaction_loads(R1, M1)
|
||||
>>> b.reaction_loads
|
||||
{M₁: -258, R₁: 52}
|
||||
>>> b.load
|
||||
-2 -1 0 -2 0 -1
|
||||
- 258⋅<x> + 52⋅<x> - 8⋅<x> + 50⋅<x - 5> + 8⋅<x - 5> - 12⋅<x - 9>
|
||||
>>> b.shear_force()
|
||||
-1 0 1 -1 1 0
|
||||
- 258⋅<x> + 52⋅<x> - 8⋅<x> + 50⋅<x - 5> + 8⋅<x - 5> - 12⋅<x - 9>
|
||||
>>> b.bending_moment()
|
||||
0 1 2 0 2 1
|
||||
- 258⋅<x> + 52⋅<x> - 4⋅<x> + 50⋅<x - 5> + 4⋅<x - 5> - 12⋅<x - 9>
|
||||
>>> b.slope()
|
||||
3 3
|
||||
1 2 4⋅<x> 1 4⋅<x - 5> 2
|
||||
- 258⋅<x> + 26⋅<x> - ────── + 50⋅<x - 5> + ────────── - 6⋅<x - 9>
|
||||
3 3
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
>>> b.deflection()
|
||||
3 4 4
|
||||
2 26⋅<x> <x> 2 <x - 5> 3
|
||||
- 129⋅<x> + ─────── - ──── + 25⋅<x - 5> + ──────── - 2⋅<x - 9>
|
||||
3 3 3
|
||||
─────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
Example 2
|
||||
---------
|
||||
|
||||
There is a beam of length 30 meters. A moment of magnitude 120 Nm is
|
||||
applied in the clockwise direction at the end of the beam. A point load
|
||||
applied in the clockwise direction at the end of the beam. A pointload
|
||||
of magnitude 8 N is applied from the top of the beam at the starting
|
||||
point. There are two simple supports below the beam. One at the end
|
||||
and another one at a distance of 10 meters from the start. The
|
||||
deflection is restricted at both the supports.
|
||||
|
||||
::
|
||||
|
||||
|| 8 N ⭯ 120 Nm
|
||||
\/______________________________________________|
|
||||
|_______________________________________________|
|
||||
/\ /\
|
||||
|------------|---------------------------------|
|
||||
10 m 20 m
|
||||
|
||||
.. note::
|
||||
|
||||
Using the sign convention of upward forces and counterclockwise moment
|
||||
Using the sign convention of upward forces and clockwise moment
|
||||
being positive.
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
@@ -282,50 +127,38 @@ deflection is restricted at both the supports.
|
||||
{R₁: 6, R₂: 2}
|
||||
>>> b.load
|
||||
-1 -1 -2 -1
|
||||
- 8⋅<x> + 6⋅<x - 10> + 120⋅<x - 30> + 2⋅<x - 30>
|
||||
- 8⋅<x> + 6⋅<x - 10> + 120⋅<x - 30> + 2⋅<x - 30>
|
||||
>>> b.shear_force()
|
||||
0 0 -1 0
|
||||
- 8⋅<x> + 6⋅<x - 10> + 120⋅<x - 30> + 2⋅<x - 30>
|
||||
- 8⋅<x> + 6⋅<x - 10> + 120⋅<x - 30> + 2⋅<x - 30>
|
||||
>>> b.bending_moment()
|
||||
1 1 0 1
|
||||
- 8⋅<x> + 6⋅<x - 10> + 120⋅<x - 30> + 2⋅<x - 30>
|
||||
- 8⋅<x> + 6⋅<x - 10> + 120⋅<x - 30> + 2⋅<x - 30>
|
||||
>>> b.slope()
|
||||
2 2 1 2 4000
|
||||
- 4⋅<x> + 3⋅<x - 10> + 120⋅<x - 30> + <x - 30> + ────
|
||||
3
|
||||
3
|
||||
─────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
E⋅I
|
||||
>>> b.deflection()
|
||||
3 3
|
||||
4000⋅x 4⋅<x> 3 2 <x - 30>
|
||||
3 3
|
||||
4000⋅x 4⋅<x> 3 2 <x - 30>
|
||||
────── - ────── + <x - 10> + 60⋅<x - 30> + ───────── - 12000
|
||||
3 3 3
|
||||
3 3 3
|
||||
──────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
E⋅I
|
||||
|
||||
Example 3
|
||||
---------
|
||||
|
||||
A beam of length 6 meters is having a roller support at the start and a hinged
|
||||
support at the end. A counterclockwise moment of 1.5 kN-m is applied at the mid
|
||||
of the beam. A constant distributed load of 3 kN/m and a ramp load of 1 kN/m is
|
||||
applied from the mid till the end of the beam.
|
||||
|
||||
::
|
||||
|
||||
ramp load = 1 KN/m
|
||||
constant load = 3 KN/m
|
||||
|------------------------|
|
||||
⭯ 1.5 KN-m
|
||||
______________________|________________________
|
||||
|_______________________________________________|
|
||||
o | /\
|
||||
|----------------------|-----------------------|
|
||||
3.0 m 3.0 m
|
||||
A beam of length 6 meters is having a roller support at the start and a
|
||||
hinged support at the end. A clockwise moment of 1.5 kN-m is applied at the mid
|
||||
of the beam. A constant distributed load of 3 kN/m and a ramp load of 1 kN/m
|
||||
is applied from the mid til the end of the beam.
|
||||
|
||||
.. note::
|
||||
|
||||
Using the sign convention of upward forces and counterclockwise moment
|
||||
Using the sign convention of upward forces and clockwise moment
|
||||
being positive.
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
@@ -345,540 +178,28 @@ applied from the mid till the end of the beam.
|
||||
{R₁: 2.75, R₂: 10.75}
|
||||
>>> b.load
|
||||
-1 -2 0 1 -1
|
||||
2.75⋅<x> + 1.5⋅<x - 3> - 3⋅<x - 3> - <x - 3> + 10.75⋅<x - 6>
|
||||
2.75⋅<x> + 1.5⋅<x - 3> - 3⋅<x - 3> - <x - 3> + 10.75⋅<x - 6>
|
||||
>>> b.shear_force()
|
||||
2
|
||||
2
|
||||
0 -1 1 <x - 3> 0
|
||||
2.75⋅<x> + 1.5⋅<x - 3> - 3⋅<x - 3> - ──────── + 10.75⋅<x - 6>
|
||||
2
|
||||
2.75⋅<x> + 1.5⋅<x - 3> - 3⋅<x - 3> - ──────── + 10.75⋅<x - 6>
|
||||
2
|
||||
>>> b.bending_moment()
|
||||
2 3
|
||||
2 3
|
||||
1 0 3⋅<x - 3> <x - 3> 1
|
||||
2.75⋅<x> + 1.5⋅<x - 3> - ────────── - ──────── + 10.75⋅<x - 6>
|
||||
2 6
|
||||
2.75⋅<x> + 1.5⋅<x - 3> - ────────── - ──────── + 10.75⋅<x - 6>
|
||||
2 6
|
||||
>>> b.slope()
|
||||
3 4
|
||||
2 1 <x - 3> <x - 3> 2
|
||||
3 4
|
||||
2 1 <x - 3> <x - 3> 2
|
||||
1.375⋅<x> + 1.5⋅<x - 3> - ──────── - ──────── + 5.375⋅<x - 6> - 15.6
|
||||
2 24
|
||||
2 24
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
E⋅I
|
||||
>>> b.deflection()
|
||||
4 5
|
||||
4 5
|
||||
3 2 <x - 3> <x - 3> 3
|
||||
-15.6⋅x + 0.458333333333333⋅<x> + 0.75⋅<x - 3> - ──────── - ──────── + 1.79166666666667⋅<x - 6>
|
||||
8 120
|
||||
-15.6⋅x + 0.458333333333333⋅<x> + 0.75⋅<x - 3> - ──────── - ──────── + 1.79166666666667⋅<x - 6>
|
||||
8 120
|
||||
──────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
Example 4
|
||||
---------
|
||||
|
||||
An overhanging beam of length 8 meters is pinned at 1 meter from starting point
|
||||
and supported by a roller 1 meter before the other end. It is subjected
|
||||
to a distributed constant load of 10 KN/m from the starting point till
|
||||
2 meters away from it. Two point loads of 20KN and 8KN are applied at
|
||||
5 meters and 7.5 meters away from the starting point respectively.
|
||||
|
||||
::
|
||||
|
||||
---> x
|
||||
|
|
||||
v y
|
||||
10 KN/m
|
||||
_____________ 20 KN 8 KN
|
||||
| | | | | | | | |
|
||||
V V V V V V V V V
|
||||
_______________________________________________
|
||||
|_______________________________________________|
|
||||
/\ O
|
||||
|-----|------|-----------------|----------|--|--|
|
||||
1m 1m 3m 2m .5m .5m
|
||||
|
||||
.. code:: pycon
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> from sympy import symbols
|
||||
>>> E,I,M,V = symbols('E I M V')
|
||||
>>> b = Beam(8, E, I)
|
||||
>>> E,I,R1,R2 = symbols('E I R1 R2')
|
||||
>>> b.apply_load(R1, 1, -1)
|
||||
>>> b.apply_load(R2, 7, -1)
|
||||
>>> b.apply_load(10, 0, 0, end=2)
|
||||
>>> b.apply_load(20, 5, -1)
|
||||
>>> b.apply_load(8, 7.5, -1)
|
||||
>>> b.solve_for_reaction_loads(R1, R2)
|
||||
>>> b.reaction_loads
|
||||
{R₁: -26.0, R₂: -22.0}
|
||||
>>> b.load
|
||||
0 -1 0 -1 -1 -1
|
||||
10⋅<x> - 26.0⋅<x - 1> - 10⋅<x - 2> + 20⋅<x - 5> - 22.0⋅<x - 7> + 8⋅<x - 7.5>
|
||||
|
||||
>>> b.shear_force()
|
||||
1 0 1 0 0 0
|
||||
10⋅<x> - 26.0⋅<x - 1> - 10⋅<x - 2> + 20⋅<x - 5> - 22.0⋅<x - 7> + 8⋅<x - 7.5>
|
||||
|
||||
>>> b.bending_moment()
|
||||
2 1 2 1 1 1
|
||||
5⋅<x> - 26.0⋅<x - 1> - 5⋅<x - 2> + 20⋅<x - 5> - 22.0⋅<x - 7> + 8⋅<x - 7.5>
|
||||
|
||||
>>> b.bc_deflection = [(1, 0), (7, 0)]
|
||||
>>> b.slope()
|
||||
3 3
|
||||
5⋅<x> 2 5⋅<x - 2> 2 2 2
|
||||
────── - 13.0⋅<x - 1> - ────────── + 10⋅<x - 5> - 11.0⋅<x - 7> + 4⋅<x - 7.5> + 28.2916666666667
|
||||
3 3
|
||||
───────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
>>> b.deflection()
|
||||
4 4 3 3
|
||||
5⋅<x> 3 5⋅<x - 2> 10⋅<x - 5> 3 4⋅<x - 7.5>
|
||||
28.2916666666667⋅x + ────── - 4.33333333333333⋅<x - 1> - ────────── + ─────────── - 3.66666666666667⋅<x - 7> + ──────────── - 28.7083333333333
|
||||
12 12 3 3
|
||||
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
Example 5
|
||||
---------
|
||||
|
||||
A cantilever beam of length 6 meters is under downward distributed constant
|
||||
load with magnitude of 4.0 KN/m from starting point till 2 meters away
|
||||
from it. A ramp load of 1 kN/m applied from the mid till the end of
|
||||
the beam. A point load of 12KN is also applied in same direction 4 meters
|
||||
away from start.
|
||||
|
||||
::
|
||||
|
||||
---> x .
|
||||
| . |
|
||||
v y 12 KN . | |
|
||||
| . | | |
|
||||
V . | | | |
|
||||
\\\\| 4 KN/m . | | | | |
|
||||
\\\\|___________ . 1 KN/m | |
|
||||
\\\\|| | | | | | . V V V V V V V
|
||||
\\\\|V V V V V V |---------------|
|
||||
\\\\|________________________________
|
||||
\\\\|________________________________|
|
||||
\\\\| : : :
|
||||
\\\\|----------|-----|----|----------|
|
||||
2.0 m 1m 1m 2.0 m
|
||||
|
||||
.. code:: pycon
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> from sympy import symbols
|
||||
>>> E,I,M,V = symbols('E I M V')
|
||||
>>> b = Beam(6, E, I)
|
||||
>>> b.apply_load(V, 0, -1)
|
||||
>>> b.apply_load(M, 0, -2)
|
||||
>>> b.apply_load(4, 0, 0, end=2)
|
||||
>>> b.apply_load(12, 4, -1)
|
||||
>>> b.apply_load(1, 3, 1, end=6)
|
||||
>>> b.solve_for_reaction_loads(V, M)
|
||||
>>> b.reaction_loads
|
||||
{M: 157/2, V: -49/2}
|
||||
>>> b.load
|
||||
-2 -1
|
||||
157⋅<x> 49⋅<x> 0 0 1 -1 0 1
|
||||
───────── - ──────── + 4⋅<x> - 4⋅<x - 2> + <x - 3> + 12⋅<x - 4> - 3⋅<x - 6> - <x - 6>
|
||||
2 2
|
||||
>>> b.shear_force()
|
||||
-1 0 2 2
|
||||
157⋅<x> 49⋅<x> 1 1 <x - 3> 0 1 <x - 6>
|
||||
───────── - ─────── + 4⋅<x> - 4⋅<x - 2> + ──────── + 12⋅<x - 4> - 3⋅<x - 6> - ────────
|
||||
2 2 2 2
|
||||
>>> b.bending_moment()
|
||||
0 1 3 2 3
|
||||
157⋅<x> 49⋅<x> 2 2 <x - 3> 1 3⋅<x - 6> <x - 6>
|
||||
──────── - ─────── + 2⋅<x> - 2⋅<x - 2> + ──────── + 12⋅<x - 4> - ────────── - ────────
|
||||
2 2 6 2 6
|
||||
>>> b.bc_deflection = [(0, 0)]
|
||||
>>> b.bc_slope = [(0, 0)]
|
||||
>>> b.slope()
|
||||
1 2 3 3 4 3 4
|
||||
157⋅<x> 49⋅<x> 2⋅<x> 2⋅<x - 2> <x - 3> 2 <x - 6> <x - 6>
|
||||
──────── - ─────── + ────── - ────────── + ──────── + 6⋅<x - 4> - ──────── - ────────
|
||||
2 4 3 3 24 2 24
|
||||
──────────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
>>> b.deflection()
|
||||
2 3 4 4 5 4 5
|
||||
157⋅<x> 49⋅<x> <x> <x - 2> <x - 3> 3 <x - 6> <x - 6>
|
||||
──────── - ─────── + ──── - ──────── + ──────── + 2⋅<x - 4> - ──────── - ────────
|
||||
4 12 6 6 120 8 120
|
||||
──────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
Example 6
|
||||
---------
|
||||
|
||||
An overhanging beam of length 11 meters is subjected to a distributed constant
|
||||
load of 2 KN/m from 2 meters away from the starting point till 6 meters away
|
||||
from it. It is pinned at the starting point and is resting over a roller 8 meters
|
||||
away from that end. Also a counterclockwise moment of 5 KN-m is applied at the
|
||||
overhanging end.
|
||||
|
||||
::
|
||||
|
||||
2 KN/m ---> x
|
||||
_________________ |
|
||||
| | | | | | | | | v y
|
||||
V V V V V V V V V ⭯ 5 KN-m
|
||||
____________________________________________________|
|
||||
O____________________________________________________|
|
||||
/ \ /\
|
||||
|--------|----------------|----------|---------------|
|
||||
2m 4m 2m 3m
|
||||
|
||||
.. code:: pycon
|
||||
|
||||
>>> R1, R2 = symbols('R1, R2')
|
||||
>>> E, I = symbols('E, I')
|
||||
>>> b = Beam(11, E, I)
|
||||
>>> b.apply_load(R1, 0, -1)
|
||||
>>> b.apply_load(2, 2, 0, end=6)
|
||||
>>> b.apply_load(R2, 8, -1)
|
||||
>>> b.apply_load(5, 11, -2)
|
||||
>>> b.solve_for_reaction_loads(R1, R2)
|
||||
>>> b.reaction_loads
|
||||
{R₁: -37/8, R₂: -27/8}
|
||||
>>> b.load
|
||||
-1 -1
|
||||
37⋅<x> 0 0 27⋅<x - 8> -2
|
||||
- ──────── + 2⋅<x - 2> - 2⋅<x - 6> - ──────────── + 5⋅<x - 11>
|
||||
8 8
|
||||
>>> b.shear_force()
|
||||
0 0
|
||||
37⋅<x> 1 1 27⋅<x - 8> -1
|
||||
- ─────── + 2⋅<x - 2> - 2⋅<x - 6> - ─────────── + 5⋅<x - 11>
|
||||
8 8
|
||||
>>> b.bending_moment()
|
||||
1 1
|
||||
37⋅<x> 2 2 27⋅<x - 8> 0
|
||||
- ─────── + <x - 2> - <x - 6> - ─────────── + 5⋅<x - 11>
|
||||
8 8
|
||||
>>> b.bc_deflection = [(0, 0), (8, 0)]
|
||||
>>> b.slope()
|
||||
2 3 3 2
|
||||
37⋅<x> <x - 2> <x - 6> 27⋅<x - 8> 1
|
||||
- ─────── + ──────── - ──────── - ─────────── + 5⋅<x - 11> + 36
|
||||
16 3 3 16
|
||||
────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
>>> b.deflection()
|
||||
3 4 4 3 2
|
||||
37⋅<x> <x - 2> <x - 6> 9⋅<x - 8> 5⋅<x - 11>
|
||||
36⋅x - ─────── + ──────── - ──────── - ────────── + ───────────
|
||||
48 12 12 16 2
|
||||
───────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
Example 7
|
||||
---------
|
||||
|
||||
There is a beam of length ``l``, fixed at both ends. A concentrated point load
|
||||
of magnitude ``F`` is applied in downward direction at mid-point of the
|
||||
beam.
|
||||
|
||||
::
|
||||
|
||||
^ y
|
||||
|
|
||||
---> x
|
||||
\\\\| F |\\\\
|
||||
\\\\| | |\\\\
|
||||
\\\\| V |\\\\
|
||||
\\\\|_____________________________________|\\\\
|
||||
\\\\|_____________________________________|\\\\
|
||||
\\\\| : |\\\\
|
||||
\\\\| : |\\\\
|
||||
\\\\|------------------|------------------|\\\\
|
||||
l/2 l/2
|
||||
|
||||
.. code:: pycon
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> from sympy import symbols
|
||||
>>> E, I, F = symbols('E I F')
|
||||
>>> l = symbols('l', positive=True)
|
||||
>>> b = Beam(l, E, I)
|
||||
>>> R1,R2 = symbols('R1 R2')
|
||||
>>> M1, M2 = symbols('M1, M2')
|
||||
>>> b.apply_load(R1, 0, -1)
|
||||
>>> b.apply_load(M1, 0, -2)
|
||||
>>> b.apply_load(R2, l, -1)
|
||||
>>> b.apply_load(M2, l, -2)
|
||||
>>> b.apply_load(-F, l/2, -1)
|
||||
>>> b.bc_deflection = [(0, 0),(l, 0)]
|
||||
>>> b.bc_slope = [(0, 0),(l, 0)]
|
||||
>>> b.solve_for_reaction_loads(R1, R2, M1, M2)
|
||||
>>> b.reaction_loads
|
||||
⎧ -F⋅l F⋅l F F⎫
|
||||
⎨M₁: ─────, M₂: ───, R₁: ─, R₂: ─⎬
|
||||
⎩ 8 8 2 2⎭
|
||||
|
||||
>>> b.load
|
||||
-2 -2 -1 -1 -1
|
||||
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> l F⋅<-l + x>
|
||||
- ───────── + ────────────── + ─────── - F⋅<- ─ + x> + ────────────
|
||||
8 8 2 2 2
|
||||
|
||||
>>> b.shear_force()
|
||||
-1 -1 0 0 0
|
||||
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> l F⋅<-l + x>
|
||||
- ───────── + ────────────── + ────── - F⋅<- ─ + x> + ───────────
|
||||
8 8 2 2 2
|
||||
|
||||
>>> b.bending_moment()
|
||||
0 0 1 1 1
|
||||
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> l F⋅<-l + x>
|
||||
- ──────── + ───────────── + ────── - F⋅<- ─ + x> + ───────────
|
||||
8 8 2 2 2
|
||||
|
||||
>>> b.slope()
|
||||
2
|
||||
l
|
||||
1 1 2 F⋅<- ─ + x> 2
|
||||
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> 2 F⋅<-l + x>
|
||||
- ──────── + ───────────── + ────── - ──────────── + ───────────
|
||||
8 8 4 2 4
|
||||
────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
>>> b.deflection()
|
||||
3
|
||||
l
|
||||
2 2 3 F⋅<- ─ + x> 3
|
||||
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> 2 F⋅<-l + x>
|
||||
- ──────── + ───────────── + ────── - ──────────── + ───────────
|
||||
16 16 12 6 12
|
||||
────────────────────────────────────────────────────────────────
|
||||
E⋅I
|
||||
|
||||
|
||||
Example 8
|
||||
---------
|
||||
|
||||
There is a beam of length ``4*l``, having a hinge connector at the middle. It
|
||||
is having a fixed support at the start and also has two rollers at a distance
|
||||
of ``l`` and ``4*l`` from the starting point. A concentrated point load ``P`` is also
|
||||
applied at a distance of ``3*l`` from the starting point.
|
||||
|
||||
::
|
||||
|
||||
---> x
|
||||
\\\\| P |
|
||||
\\\\| | v y
|
||||
\\\\| V
|
||||
\\\\|_____________________ _______________________
|
||||
\\\\|_____________________O_______________________|
|
||||
\\\\| /\ : /\
|
||||
\\\\| oooo : oooo
|
||||
\\\\|----------|-----------|----------|-----------|
|
||||
l l l l
|
||||
|
||||
.. code:: pycon
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> from sympy import symbols
|
||||
>>> E, I = symbols('E I')
|
||||
>>> l = symbols('l', positive=True)
|
||||
>>> R1, M1, R2, R3, P = symbols('R1 M1 R2 R3 P')
|
||||
>>> b1 = Beam(2*l, E, I)
|
||||
>>> b2 = Beam(2*l, E, I)
|
||||
>>> b = b1.join(b2, "hinge")
|
||||
>>> b.apply_load(M1, 0, -2)
|
||||
>>> b.apply_load(R1, 0, -1)
|
||||
>>> b.apply_load(R2, l, -1)
|
||||
>>> b.apply_load(R3, 4*l, -1)
|
||||
>>> b.apply_load(P, 3*l, -1)
|
||||
>>> b.bc_slope = [(0, 0)]
|
||||
>>> b.bc_deflection = [(0, 0), (l, 0), (4*l, 0)]
|
||||
>>> b.solve_for_reaction_loads(M1, R1, R2, R3)
|
||||
>>> b.reaction_loads
|
||||
⎧ -P⋅l 3⋅P -5⋅P -P ⎫
|
||||
⎨M₁: ─────, R₁: ───, R₂: ─────, R₃: ───⎬
|
||||
⎩ 4 4 4 2 ⎭
|
||||
|
||||
>>> b.load
|
||||
-2 -1 -1 -1
|
||||
P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> -1 P⋅<-4⋅l + x>
|
||||
- ───────── + ───────── - ────────────── + P⋅<-3⋅l + x> - ──────────────
|
||||
4 4 4 2
|
||||
|
||||
>>> b.shear_force()
|
||||
-1 0 0 0
|
||||
P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> 0 P⋅<-4⋅l + x>
|
||||
- ───────── + ──────── - ───────────── + P⋅<-3⋅l + x> - ─────────────
|
||||
4 4 4 2
|
||||
|
||||
>>> b.bending_moment()
|
||||
0 1 1 1
|
||||
P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> 1 P⋅<-4⋅l + x>
|
||||
- ──────── + ──────── - ───────────── + P⋅<-3⋅l + x> - ─────────────
|
||||
4 4 4 2
|
||||
|
||||
>>> b.slope()
|
||||
⎛ 2 2 2 2⎞ ⎛ 1 2 2 2⎞ ⎛ 1 2 2 2⎞
|
||||
⎜5⋅P⋅l P⋅<-2⋅l + x> P⋅<-3⋅l + x> P⋅<-4⋅l + x> ⎟ 0 ⎜ P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0 ⎜ P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0
|
||||
⎜────── - ───────────── + ───────────── - ─────────────⎟⋅<-2⋅l + x> ⎜- ──────── + ──────── - ───────────── + ─────────────⎟⋅<x> ⎜- ──────── + ──────── - ───────────── + ─────────────⎟⋅<-2⋅l + x>
|
||||
⎝ 48 4 2 4 ⎠ ⎝ 4 8 8 4 ⎠ ⎝ 4 8 8 4 ⎠
|
||||
──────────────────────────────────────────────────────────────────── + ──────────────────────────────────────────────────────────── - ───────────────────────────────────────────────────────────────────
|
||||
E⋅I E⋅I E⋅I
|
||||
>>> b.deflection()
|
||||
⎛ 2 3 3 3⎞ ⎛ 2 3 3 3⎞ ⎛ 3 2 3 3 3⎞
|
||||
⎜ P⋅l⋅<x> P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0 ⎜ P⋅l⋅<x> P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0 ⎜7⋅P⋅l 5⋅P⋅l ⋅(-2⋅l + x) P⋅<-2⋅l + x> P⋅<-3⋅l + x> P⋅<-4⋅l + x> ⎟ 0
|
||||
⎜- ──────── + ────── - ───────────── + ─────────────⎟⋅<x> ⎜- ──────── + ────── - ───────────── + ─────────────⎟⋅<-2⋅l + x> ⎜────── + ───────────────── - ───────────── + ───────────── - ─────────────⎟⋅<-2⋅l + x>
|
||||
⎝ 8 8 24 12 ⎠ ⎝ 8 8 24 12 ⎠ ⎝ 24 48 12 6 12 ⎠
|
||||
────────────────────────────────────────────────────────── - ───────────────────────────────────────────────────────────────── + ────────────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I E⋅I E⋅I
|
||||
|
||||
Example 9
|
||||
---------
|
||||
|
||||
There is a cantilever beam of length 4 meters. For first 2 meters
|
||||
its moment of inertia is ``1.5*I`` and ``I`` for the rest.
|
||||
A pointload of magnitude 20 N is applied from the top at its free end.
|
||||
|
||||
::
|
||||
|
||||
---> x
|
||||
\\\\| |
|
||||
\\\\| 20 N v y
|
||||
\\\\|________________ |
|
||||
\\\\| |_______________V
|
||||
\\\\| 1.5*I _______I_______|
|
||||
\\\\|________________|
|
||||
\\\\| :
|
||||
\\\\|----------------|---------------|
|
||||
2.0 m 2.0 m
|
||||
|
||||
.. code:: pycon
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> from sympy import symbols
|
||||
>>> E, I = symbols('E, I')
|
||||
>>> R1, R2 = symbols('R1, R2')
|
||||
>>> b1 = Beam(2, E, 1.5*I)
|
||||
>>> b2 = Beam(2, E, I)
|
||||
>>> b = b1.join(b2, "fixed")
|
||||
>>> b.apply_load(20, 4, -1)
|
||||
>>> b.apply_load(R1, 0, -1)
|
||||
>>> b.apply_load(R2, 0, -2)
|
||||
>>> b.bc_slope = [(0, 0)]
|
||||
>>> b.bc_deflection = [(0, 0)]
|
||||
>>> b.solve_for_reaction_loads(R1, R2)
|
||||
>>> b.load
|
||||
-2 -1 -1
|
||||
80⋅<x> - 20⋅<x> + 20⋅<x - 4>
|
||||
>>> b.shear_force()
|
||||
-1 0 0
|
||||
80⋅<x> - 20⋅<x> + 20⋅<x - 4>
|
||||
>>> b.bending_moment()
|
||||
0 1 1
|
||||
80⋅<x> - 20⋅<x> + 20⋅<x - 4>
|
||||
>>> b.slope()
|
||||
⎛ 1 2 2 ⎞
|
||||
⎜80⋅<x> - 10⋅<x> + 10⋅<x - 4> 120 ⎟
|
||||
⎜─────────────────────────────── - ─── ⎟ ⎛ 1 2 2⎞ 0 ⎛ 1 2 2⎞ 0
|
||||
⎜ I I 80.0⎟ 0 0.666666666666667⋅⎝80⋅<x> - 10⋅<x> + 10⋅<x - 4> ⎠⋅<x> 0.666666666666667⋅⎝80⋅<x> - 10⋅<x> + 10⋅<x - 4> ⎠⋅<x - 2>
|
||||
⎜───────────────────────────────────── + ────⎟⋅<x - 2> + ──────────────────────────────────────────────────────── - ────────────────────────────────────────────────────────────
|
||||
⎝ E E⋅I ⎠ E⋅I E⋅I
|
||||
|
||||
Example 10
|
||||
----------
|
||||
|
||||
A combined beam, with constant flexural rigidity ``E*I``, is formed by joining
|
||||
a Beam of length ``2*l`` to the right of another Beam of length ``l``. The whole beam
|
||||
is fixed at both of its ends. A point load of magnitude ``P`` is also applied
|
||||
from the top at a distance of ``2*l`` from starting point.
|
||||
|
||||
::
|
||||
|
||||
---> x
|
||||
|
|
||||
\\\\| P v y |\\\\
|
||||
\\\\| | |\\\\
|
||||
\\\\| V |\\\\
|
||||
\\\\|____________ ________________________|\\\\
|
||||
\\\\|____________O________________________|\\\\
|
||||
\\\\| : : |\\\\
|
||||
\\\\| : : |\\\\
|
||||
\\\\|------------|------------|-----------|\\\\
|
||||
l l l
|
||||
|
||||
.. code:: pycon
|
||||
|
||||
>>> from sympy.physics.continuum_mechanics.beam import Beam
|
||||
>>> from sympy import symbols
|
||||
>>> E, I = symbols('E, I')
|
||||
>>> l = symbols('l', positive=True)
|
||||
>>> b1 = Beam(l ,E,I)
|
||||
>>> b2 = Beam(2*l ,E,I)
|
||||
>>> b = b1.join(b2,"hinge")
|
||||
>>> M1, A1, M2, A2, P = symbols('M1 A1 M2 A2 P')
|
||||
>>> b.apply_load(A1, 0, -1)
|
||||
>>> b.apply_load(M1, 0 ,-2)
|
||||
>>> b.apply_load(P, 2*l, -1)
|
||||
>>> b.apply_load(A2, 3*l, -1)
|
||||
>>> b.apply_load(M2, 3*l, -2)
|
||||
>>> b.bc_slope=[(0, 0), (3*l, 0)]
|
||||
>>> b.bc_deflection=[(0, 0), (3*l, 0)]
|
||||
>>> b.solve_for_reaction_loads(M1, A1, M2, A2)
|
||||
>>> b.reaction_loads
|
||||
⎧ -5⋅P -13⋅P 5⋅P⋅l -4⋅P⋅l ⎫
|
||||
⎨A₁: ─────, A₂: ──────, M₁: ─────, M₂: ───────⎬
|
||||
⎩ 18 18 18 9 ⎭
|
||||
|
||||
>>> b.load
|
||||
-2 -2 -1 -1
|
||||
5⋅P⋅l⋅<x> 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<x> -1 13⋅P⋅<-3⋅l + x>
|
||||
─────────── - ────────────────── - ───────── + P⋅<-2⋅l + x> - ─────────────────
|
||||
18 9 18 18
|
||||
|
||||
>>> b.shear_force()
|
||||
-1 -1 0 0
|
||||
5⋅P⋅l⋅<x> 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<x> 0 13⋅P⋅<-3⋅l + x>
|
||||
─────────── - ────────────────── - ──────── + P⋅<-2⋅l + x> - ────────────────
|
||||
18 9 18 18
|
||||
|
||||
>>> b.bending_moment()
|
||||
0 0 1 1
|
||||
5⋅P⋅l⋅<x> 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<x> 1 13⋅P⋅<-3⋅l + x>
|
||||
────────── - ───────────────── - ──────── + P⋅<-2⋅l + x> - ────────────────
|
||||
18 9 18 18
|
||||
|
||||
>>> b.slope()
|
||||
⎛ 1 2 2⎞ ⎛ 1 2 2⎞ ⎛ 2 1 2 2 2⎞
|
||||
⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜P⋅l 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> 13⋅P⋅<-3⋅l + x> ⎟ 0
|
||||
⎜────────── - ──────── + ─────────────⎟⋅<x> ⎜────────── - ──────── + ─────────────⎟⋅<-l + x> ⎜──── - ───────────────── - ───────────── + ───────────── - ────────────────⎟⋅<-l + x>
|
||||
⎝ 18 36 36 ⎠ ⎝ 18 36 36 ⎠ ⎝ 18 9 36 2 36 ⎠
|
||||
──────────────────────────────────────────── - ───────────────────────────────────────────────── + ───────────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I E⋅I E⋅I
|
||||
|
||||
>>> b.deflection()
|
||||
⎛ 2 3 3⎞ ⎛ 2 3 3⎞ ⎛ 3 2 2 3 3 3⎞
|
||||
⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜5⋅P⋅l P⋅l ⋅(-l + x) 2⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> 13⋅P⋅<-3⋅l + x> ⎟ 0
|
||||
⎜────────── - ──────── + ─────────────⎟⋅<x> ⎜────────── - ──────── + ─────────────⎟⋅<-l + x> ⎜────── + ───────────── - ───────────────── - ───────────── + ───────────── - ────────────────⎟⋅<-l + x>
|
||||
⎝ 36 108 108 ⎠ ⎝ 36 108 108 ⎠ ⎝ 54 18 9 108 6 108 ⎠
|
||||
──────────────────────────────────────────── - ───────────────────────────────────────────────── + ─────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
E⋅I E⋅I E⋅I
|
||||
|
||||
Example 11
|
||||
----------
|
||||
|
||||
Any type of load defined by a polynomial can be applied to the beam. This
|
||||
allows approximation of arbitrary load distributions. The following example
|
||||
shows six truncated polynomial loads across the surface of a beam.
|
||||
|
||||
.. plot::
|
||||
:context: close-figs
|
||||
:format: doctest
|
||||
:include-source: True
|
||||
|
||||
>>> n = 6
|
||||
>>> b = Beam(10*n, E, I)
|
||||
>>> for i in range(n):
|
||||
... b.apply_load(1 / (5**i), 10*i + 5, i, end=10*i + 10)
|
||||
>>> plot(b.load, (x, 0, 10*n)) # doctest: +SKIP
|
||||
E⋅I
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.. _physics-docs:
|
||||
|
||||
=======
|
||||
Physics
|
||||
=======
|
||||
==============
|
||||
Physics Module
|
||||
==============
|
||||
|
||||
.. automodule:: sympy.physics
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
.. _kane_lagrange:
|
||||
|
||||
==============================================
|
||||
Kane's Method & Lagrange's Method (Docstrings)
|
||||
==============================================
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
.. _part_bod:
|
||||
|
||||
=====================================================
|
||||
Masses, Inertias & Particles, RigidBodys (Docstrings)
|
||||
=====================================================
|
||||
|
||||
@@ -1,596 +0,0 @@
|
||||
.. _autolev_parser:
|
||||
|
||||
==============
|
||||
Autolev Parser
|
||||
==============
|
||||
|
||||
.. role:: input(strong)
|
||||
|
||||
Introduction
|
||||
============
|
||||
Autolev (now superseded by MotionGenesis) is a domain specific language
|
||||
used for symbolic multibody dynamics. The SymPy mechanics module now has
|
||||
enough power and functionality to be a fully featured symbolic dynamics
|
||||
module. This parser parses Autolev (version 4.1) code to SymPy code by making
|
||||
use of SymPy's math libraries and the mechanics module.
|
||||
|
||||
The parser has been built using the `ANTLR <http://www.antlr.org/>`_ framework and its main purpose
|
||||
is to help former users of Autolev to get familiarized with multibody dynamics
|
||||
in SymPy.
|
||||
|
||||
The sections below shall discuss details of the parser like usage, gotchas,
|
||||
issues and future improvements.
|
||||
For a detailed comparison of Autolev and SymPy Mechanics you might want to look at
|
||||
the :ref:`SymPy Mechanics for Autolev Users guide <sympy_mechanics_for_autolev_users>`.
|
||||
|
||||
.. _usage:
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
We first start with an Autolev code file.
|
||||
|
||||
Let us take this example
|
||||
(Comments ``%`` have been included to show the Autolev responses):
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
% double_pendulum.al
|
||||
%-------------------
|
||||
MOTIONVARIABLES' Q{2}', U{2}'
|
||||
CONSTANTS L,M,G
|
||||
NEWTONIAN N
|
||||
FRAMES A,B
|
||||
SIMPROT(N, A, 3, Q1)
|
||||
% -> N_A = [COS(Q1), -SIN(Q1), 0; SIN(Q1), COS(Q1), 0; 0, 0, 1]
|
||||
SIMPROT(N, B, 3, Q2)
|
||||
% -> N_B = [COS(Q2), -SIN(Q2), 0; SIN(Q2), COS(Q2), 0; 0, 0, 1]
|
||||
W_A_N>=U1*N3>
|
||||
% -> W_A_N> = U1*N3>
|
||||
W_B_N>=U2*N3>
|
||||
% -> W_B_N> = U2*N3>
|
||||
POINT O
|
||||
PARTICLES P,R
|
||||
P_O_P> = L*A1>
|
||||
% -> P_O_P> = L*A1>
|
||||
P_P_R> = L*B1>
|
||||
% -> P_P_R> = L*B1>
|
||||
V_O_N> = 0>
|
||||
% -> V_O_N> = 0>
|
||||
V2PTS(N, A, O, P)
|
||||
% -> V_P_N> = L*U1*A2>
|
||||
V2PTS(N, B, P, R)
|
||||
% -> V_R_N> = L*U1*A2> + L*U2*B2>
|
||||
MASS P=M, R=M
|
||||
Q1' = U1
|
||||
Q2' = U2
|
||||
GRAVITY(G*N1>)
|
||||
% -> FORCE_P> = G*M*N1>
|
||||
% -> FORCE_R> = G*M*N1>
|
||||
ZERO = FR() + FRSTAR()
|
||||
% -> ZERO[1] = -L*M*(2*G*SIN(Q1)+L*(U2^2*SIN(Q1-Q2)+2*U1'+COS(Q1-Q2)*U2'))
|
||||
% -> ZERO[2] = -L*M*(G*SIN(Q2)-L*(U1^2*SIN(Q1-Q2)-U2'-COS(Q1-Q2)*U1'))
|
||||
KANE()
|
||||
INPUT M=1,G=9.81,L=1
|
||||
INPUT Q1=.1,Q2=.2,U1=0,U2=0
|
||||
INPUT TFINAL=10, INTEGSTP=.01
|
||||
CODE DYNAMICS() some_filename.c
|
||||
|
||||
The parser can be used as follows::
|
||||
|
||||
>>> from sympy.parsing.autolev import parse_autolev
|
||||
>>> sympy_code = parse_autolev(open('double_pendulum.al'), include_numeric=True)
|
||||
|
||||
# The include_pydy flag is False by default. Setting it to True will
|
||||
# enable PyDy simulation code to be outputted if applicable.
|
||||
|
||||
>>> print(sympy_code)
|
||||
import sympy.physics.mechanics as me
|
||||
import sympy as sm
|
||||
import math as m
|
||||
import numpy as np
|
||||
|
||||
q1, q2, u1, u2 = me.dynamicsymbols('q1 q2 u1 u2')
|
||||
q1d, q2d, u1d, u2d = me.dynamicsymbols('q1 q2 u1 u2', 1)
|
||||
l, m, g=sm.symbols('l m g', real=True)
|
||||
frame_n=me.ReferenceFrame('n')
|
||||
frame_a=me.ReferenceFrame('a')
|
||||
frame_b=me.ReferenceFrame('b')
|
||||
frame_a.orient(frame_n, 'Axis', [q1, frame_n.z])
|
||||
# print(frame_n.dcm(frame_a))
|
||||
frame_b.orient(frame_n, 'Axis', [q2, frame_n.z])
|
||||
# print(frame_n.dcm(frame_b))
|
||||
frame_a.set_ang_vel(frame_n, u1*frame_n.z)
|
||||
# print(frame_a.ang_vel_in(frame_n))
|
||||
frame_b.set_ang_vel(frame_n, u2*frame_n.z)
|
||||
# print(frame_b.ang_vel_in(frame_n))
|
||||
point_o=me.Point('o')
|
||||
particle_p=me.Particle('p', me.Point('p_pt'), sm.Symbol('m'))
|
||||
particle_r=me.Particle('r', me.Point('r_pt'), sm.Symbol('m'))
|
||||
particle_p.point.set_pos(point_o, l*frame_a.x)
|
||||
# print(particle_p.point.pos_from(point_o))
|
||||
particle_r.point.set_pos(particle_p.point, l*frame_b.x)
|
||||
# print(particle_p.point.pos_from(particle_r.point))
|
||||
point_o.set_vel(frame_n, 0)
|
||||
# print(point_o.vel(frame_n))
|
||||
particle_p.point.v2pt_theory(point_o,frame_n,frame_a)
|
||||
# print(particle_p.point.vel(frame_n))
|
||||
particle_r.point.v2pt_theory(particle_p.point,frame_n,frame_b)
|
||||
# print(particle_r.point.vel(frame_n))
|
||||
particle_p.mass = m
|
||||
particle_r.mass = m
|
||||
force_p = particle_p.mass*(g*frame_n.x)
|
||||
# print(force_p)
|
||||
force_r = particle_r.mass*(g*frame_n.x)
|
||||
# print(force_r)
|
||||
kd_eqs = [q1d - u1, q2d - u2]
|
||||
forceList = [(particle_p.point,particle_p.mass*(g*frame_n.x)), (particle_r.point,particle_r.mass*(g*frame_n.x))]
|
||||
kane = me.KanesMethod(frame_n, q_ind=[q1,q2], u_ind=[u1, u2], kd_eqs = kd_eqs)
|
||||
fr, frstar = kane.kanes_equations([particle_p, particle_r], forceList)
|
||||
zero = fr+frstar
|
||||
# print(zero)
|
||||
#---------PyDy code for integration----------
|
||||
from pydy.system import System
|
||||
sys = System(kane, constants = {l:1, m:1, g:9.81},
|
||||
specifieds={},
|
||||
initial_conditions={q1:.1, q2:.2, u1:0, u2:0},
|
||||
times = np.linspace(0.0, 10, 10/.01))
|
||||
|
||||
y=sys.integrate()
|
||||
|
||||
|
||||
The commented code is not part of the output code. The print
|
||||
statements demonstrate how to get responses similar to the ones in the
|
||||
Autolev file.
|
||||
Note that we need to use SymPy functions like ``.ang_vel_in()``, ``.dcm()``
|
||||
etc in many cases unlike directly printing out the variables like ``zero``.
|
||||
If you are completely new to SymPy mechanics, the :ref:`SymPy Mechanics for Autolev Users guide <sympy_mechanics_for_autolev_users>`
|
||||
guide should help. You might also have to use basic SymPy simplifications
|
||||
and manipulations like ``trigsimp()``, ``expand()``, ``evalf()`` etc for
|
||||
getting outputs similar to Autolev.
|
||||
Refer to the `SymPy Tutorial <https://docs.sympy.org/latest/tutorial/index.html>`_
|
||||
to know more about these.
|
||||
|
||||
.. _gotchas_autolev:
|
||||
|
||||
Gotchas
|
||||
=======
|
||||
|
||||
- Don't use variable names that conflict with Python's reserved words.
|
||||
This is one example where this is violated:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
LAMBDA = EIG(M)
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#SymPy Code
|
||||
#----------
|
||||
lambda = sm.Matrix([i.evalf() for i in (m).eigenvals().keys()])
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- Make sure that the names of vectors and scalars are different.
|
||||
Autolev treats these differently but these will get overwritten in Python.
|
||||
The parser currently allows the names of bodies and scalars/vectors to
|
||||
coincide but doesn't do this between scalars and vectors.
|
||||
This should probably be changed in the future.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
VARIABLES X,Y
|
||||
FRAMES A
|
||||
A> = X*A1> + Y*A2>
|
||||
A = X+Y
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#SymPy Code
|
||||
#----------
|
||||
x, y = me.dynamicsymbols('x y')
|
||||
frame_a = me.ReferenceFrame('a')
|
||||
a = x*frame_a.x + y*frame_a.y
|
||||
a = x + y
|
||||
# Note how frame_a is named differently so it doesn't cause a problem.
|
||||
# On the other hand, 'a' gets rewritten from a scalar to a vector.
|
||||
# This should be changed in the future.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- When dealing with Matrices returned by functions, one must check the
|
||||
order of the values as they may not be the same as in Autolev. This is
|
||||
especially the case for eigenvalues and eigenvectors.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
EIG(M, E1, E2)
|
||||
% -> [5; 14; 13]
|
||||
E2ROW = ROWS(E2, 1)
|
||||
EIGVEC> = VECTOR(A, E2ROW)
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#SymPy Code
|
||||
#----------
|
||||
e1 = sm.Matrix([i.evalf() for i in m.eigenvals().keys()])
|
||||
# sm.Matrix([5;13;14]) different order
|
||||
e2 = sm.Matrix([i[2][0].evalf() for i in m.eigenvects()]).reshape(m.shape[0], m.shape[1])
|
||||
e2row = e2.row(0)
|
||||
# This result depends on the order of the vectors in the eigenvecs.
|
||||
eigenvec = e2row[0]*a.x + e2row[1]*a.y + e2row[2]*a.y
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- When using ``EVALUATE``, use something like ``90*UNITS(deg,rad)`` for
|
||||
angle substitutions as radians are the default in SymPy.
|
||||
You could also add ``np.deg2rad()`` directly in the SymPy code.
|
||||
|
||||
This need not be done for the output code (generated on parsing the
|
||||
``CODE`` commands) as the parser takes care of this when ``deg`` units
|
||||
are given in the ``INPUT`` declarations.
|
||||
|
||||
The ``DEGREES`` setting, on the other hand, works only in some cases like
|
||||
in ``SIMPROT`` where an angle is expected.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
A> = Q1*A1> + Q2*A2>
|
||||
B> = EVALUATE(A>, Q1:30*UNITS(DEG,RAD))
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#SymPy Code
|
||||
#----------
|
||||
a = q1*a.frame_a.x + q2*frame_a.y
|
||||
b = a.subs({q1:30*0.0174533})
|
||||
# b = a.subs({q1:np.deg2rad(30)}
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- Most of the Autolev settings have not been parsed and have no effect on the parser.
|
||||
The only ones that work somewhat are ``COMPLEX`` and ``DEGREES``.
|
||||
It is advised to look into alternatives to these in SymPy and Python.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- The ``REPRESENT`` command is not supported.
|
||||
Use the ``MATRIX``, ``VECTOR`` or ``DYADIC`` commands instead.
|
||||
Autolev 4.1 suggests these over ``REPRESENT`` as well while still allowing
|
||||
it but the parser doesn't parse it.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- Do not use variables declarations of the type ``WO{3}RD{2,4}``.
|
||||
The parser can only handle one variable name followed by one pair
|
||||
of curly braces and any number of ``'`` s.
|
||||
You would have to declare all the cases manually if you want to achieve
|
||||
something like ``WO{3}RD{2,4}``.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- The parser can handle normal versions of most commands but it may not
|
||||
parse functions with Matrix arguments properly in most cases.
|
||||
Eg:
|
||||
|
||||
``M=COEF([E1;E2],[U1,U2,U3])``
|
||||
|
||||
This would compute the coefficients of ``U1``, ``U2`` and ``U3`` in ``E1``
|
||||
and ``E2``. It is preferable to manually construct a Matrix using the
|
||||
regular versions of these commands.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
% COEF([E1;E2],[U1,U2,U3])
|
||||
M = [COEF(E1,U1),COEF(E1,U2),COEF(E1,U3) &
|
||||
;COEF(E2,U1),COEF(E2,U2),COEF(E2,U3)]
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- ``MOTIONVARIABLE`` declarations must be used for the generalized coordinates
|
||||
and speeds and all other variables must be declared in regular
|
||||
``VARIABLE`` declarations.
|
||||
The parser requires this to distinguish between them to pass the correct
|
||||
parameters to the Kane's method object.
|
||||
|
||||
It is also preferred to always declare the speeds corresponding to the
|
||||
coordinates and to pass in the kinematic differential equations.
|
||||
The parser is able to handle some cases where this isn't the case by
|
||||
introducing some dummy variables of its own but SymPy on its own
|
||||
does require them.
|
||||
|
||||
Also note that older Autolev declarations like ``VARIABLES U{3}'`` are not
|
||||
supported either.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
MOTIONVARIABLES' Q{2}', U{2}'
|
||||
% ----- OTHER LINES ----
|
||||
Q1' = U1
|
||||
Q2' = U2
|
||||
----- OTHER LINES ----
|
||||
ZERO = FR() + FRSTAR()
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#SymPy Code
|
||||
#----------
|
||||
q1, q2, u1, u2 = me.dynamicsymbols('q1 q2 u1 u2')
|
||||
q1d, q2d, u1d, u2d = me.dynamicsymbols('q1 q2 u1 u2', 1)
|
||||
|
||||
# ------- other lines -------
|
||||
|
||||
kd_eqs = [q1d - u1, q2d - u2]
|
||||
kane = me.KanesMethod(frame_n, q_ind=[q1,q2], u_ind=[u1, u2], kd_eqs = kd_eqs)
|
||||
fr, frstar = kane.kanes_equations([particle_p, particle_r], forceList)
|
||||
zero = fr+frstar
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- Need to change ``me.dynamicsymbols._t`` to ``me.dynamicsymbols('t')`` for
|
||||
all occurrences of it in the Kane's equations. For example have a look at
|
||||
line 10 of this `spring damper example <https://github.com/sympy/sympy/blob/master/sympy/parsing/autolev/test_examples/mass_spring_damper.py>`_.
|
||||
This equation is used in forming the Kane's equations so we need to
|
||||
change ``me.dynamicsymbols._t`` to ``me.dynamicsymbols('t')`` in this case.
|
||||
|
||||
The main reason that this needs to be done is because PyDy
|
||||
requires time dependent specifieds to be explicitly laid out while
|
||||
Autolev simply takes care of the stray time variables in the equations
|
||||
by itself.
|
||||
|
||||
The problem is that PyDy's System class does not accept
|
||||
``dynamicsymbols._t`` as a specified. Refer to issue `#396 <https://github.com/pydy/pydy/issues/396>`_.
|
||||
This change is not actually ideal so a better solution should be figured
|
||||
out in the future.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- The parser creates SymPy ``symbols`` and ``dynamicsymbols`` by parsing
|
||||
variable declarations in the Autolev Code.
|
||||
|
||||
For intermediate expressions which are directly initialized the parser
|
||||
does not create SymPy symbols. It just assigns them to the expression.
|
||||
|
||||
On the other hand, when a declared variable is assigned to an expression,
|
||||
the parser stores the expression against the variable in a dictionary so
|
||||
as to not reassign it to a completely different entity. This constraint
|
||||
is due to the inherent nature of Python and how it differs from a language
|
||||
like Autolev.
|
||||
|
||||
Also, Autolev seems to be able to assume whether to use a variable or the
|
||||
rhs expression that variable has been assigned to in equations even
|
||||
without an explicit ``RHS()`` call in some cases.
|
||||
For the parser to work correctly however, it is better to use ``RHS()``
|
||||
wherever a variable's rhs expression is meant to be used.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
VARIABLES X, Y
|
||||
E = X + Y
|
||||
X = 2*Y
|
||||
|
||||
RHS_X = RHS(X)
|
||||
|
||||
I1 = X
|
||||
I2 = Y
|
||||
I3 = X + Y
|
||||
|
||||
INERTIA B,I1,I2,I3
|
||||
% -> I_B_BO>> = I1*B1>*B1> + I2*B2>*B2> + I3*B3>*B3>
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#SymPy Code
|
||||
#----------
|
||||
x,y = me.dynamicsymbols('x y')
|
||||
e = x + y # No symbol is made out of 'e'
|
||||
|
||||
# an entry like {x:2*y} is stored in an rhs dictionary
|
||||
|
||||
rhs_x = 2*y
|
||||
|
||||
i1 = x # again these are not made into SymPy symbols
|
||||
i2 = y
|
||||
i3 = x + y
|
||||
|
||||
body_b.inertia = (me.inertia(body_b_f, i1, i2, i3), b_cm)
|
||||
# This prints as:
|
||||
# x*b_f.x*b_f.x + y*b_f.y*b_f.y + (x+y)*b_f.z*b_f.z
|
||||
# while Autolev's output has I1,I2 and I3 in it.
|
||||
# Autolev however seems to know when to use the RHS of I1,I2 and I3
|
||||
# based on the context.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- This is how the ``SOLVE`` command is parsed:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
SOLVE(ZERO,X,Y)
|
||||
A = RHS(X)*2 + RHS(Y)
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#SymPy Code
|
||||
#----------
|
||||
print(sm.solve(zero,x,y))
|
||||
# Behind the scenes the rhs of x
|
||||
# is set to sm.solve(zero,x,y)[x].
|
||||
a = sm.solve(zero,x,y)[x]*2 + sm.solve(zero,x,y)[y]
|
||||
|
||||
The indexing like ``[x]`` and ``[y]`` doesn't always work so you might want to
|
||||
look at the underlying dictionary that solve returns and index it correctly.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- Inertia declarations and Inertia functions work somewhat differently in
|
||||
the context of the parser. This might be hard to understand at first
|
||||
but this had to be done to bridge the gap due to the differences in
|
||||
SymPy and Autolev. Here are some points about them:
|
||||
|
||||
1. Inertia declarations (``INERTIA B,I1,I2,I3``) set the inertias of rigid
|
||||
bodies.
|
||||
|
||||
2. Inertia setters of the form ``I_C_D>> = expr`` however, set the inertias
|
||||
only when C is a body. If C is a particle then ``I_C_D>> = expr``
|
||||
simply parses to ``i_c_d = expr`` and ``i_c_d`` acts like a regular variable.
|
||||
|
||||
3. When it comes to inertia getters (``I_C_D>>`` used in an expression or
|
||||
``INERTIA`` commands), these MUST be used with the ``EXPRESS`` command
|
||||
to specify the frame as SymPy needs this information to compute the
|
||||
inertia dyadic.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
INERTIA B,I1,I2,I3
|
||||
I_B_BO>> = X*A1>*A1> + Y*A2>*A2> % Parser will set the inertia of B
|
||||
I_P_Q>> = X*A1>*A1> + Y^2*A2>*A2> % Parser just parses it as i_p_q = expr
|
||||
|
||||
E1 = 2*EXPRESS(I_B_O>>,A)
|
||||
E2 = I_P_Q>>
|
||||
E3 = EXPRESS(I_P_O>>,A)
|
||||
E4 = EXPRESS(INERTIA(O),A)
|
||||
|
||||
% In E1 we are using the EXPRESS command with I_B_O>> which makes
|
||||
% the parser and SymPy compute the inertia of Body B about point O.
|
||||
|
||||
% In E2 we are just using the dyadic object I_P_Q>> (as I_P_Q>> = expr
|
||||
% doesn't act as a setter) defined above and not asking the parser
|
||||
% or SymPy to compute anything.
|
||||
|
||||
% E3 asks the parser to compute the inertia of P about point O.
|
||||
|
||||
% E4 asks the parser to compute the inertias of all bodies wrt about O.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- In an inertia declaration of a body, if the inertia is being set about
|
||||
a point other than the center of mass, one needs to make sure that
|
||||
the position vector setter for that point and the center of mass appears
|
||||
before the inertia declaration as SymPy will throw an error otherwise.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
%Autolev Code
|
||||
%------------
|
||||
P_SO_O> = X*A1>
|
||||
INERTIA S_(O) I1,I2,I3
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
- Note that all Autolev commands have not been implemented. The parser
|
||||
now covers the important ones in their basic forms. If you are doubtful
|
||||
whether a command is included or not, please have a look at `this file <https://github.com/sympy/sympy/blob/master/sympy/parsing/autolev/_listener_autolev_antlr.py>`_
|
||||
in the source code. Search for "<command>" to verify this. Looking at the
|
||||
code for the specific command will also give an idea about what form it
|
||||
is expected to work in.
|
||||
|
||||
.. _issues:
|
||||
|
||||
Limitations and Issues
|
||||
======================
|
||||
|
||||
- A lot of the issues have already been discussed in the Gotchas section.
|
||||
Some of these are:
|
||||
|
||||
- Vector names coinciding with scalar names are overwritten in Python.
|
||||
- Some convenient variable declarations aren't parsed.
|
||||
- Some convenient forms of functions to return matrices aren't parsed.
|
||||
- Settings aren't parsed.
|
||||
- symbols and rhs expressions work very differently in Python which might
|
||||
cause undesirable results.
|
||||
- Dictionary indexing for the parsed code of the ``SOLVE`` command is
|
||||
not proper in many cases.
|
||||
- Need to change ``dynamicsymbols._t`` to ``dynamicsymbols('t')`` for the
|
||||
PyDy simulation code to work properly.
|
||||
|
||||
Here are some other ones:
|
||||
|
||||
- Eigenvectors do not seem to work as expected. The values in Autolev and SymPy
|
||||
are not the same in many cases.
|
||||
|
||||
- Block matrices aren't parsed by the parser. It would actually be easier
|
||||
to make a change in SymPy to allow matrices to accept other matrices for
|
||||
arguments.
|
||||
|
||||
- The SymPy equivalent of the ``TAYLOR`` command ``.series()`` does not work
|
||||
with ``dynamicsymbols()``.
|
||||
|
||||
- Only ``DEPENDENT`` constraints are currently parsed. Need to parse
|
||||
``AUXILIARY`` constraints as well. This should be done soon as it isn't
|
||||
very difficult.
|
||||
|
||||
- None of the energy and momentum functions are parsed right now. It would
|
||||
be nice to get these working as well. Some changes should probably be made
|
||||
to SymPy. For instance, SymPy doesn't have a function equivalent to ``NICHECK()``.
|
||||
|
||||
- The numerical integration parts work properly only in the case of the
|
||||
``KANE`` command with no arguments. Things like ``KANE(F1,F2)`` do not currently
|
||||
work.
|
||||
|
||||
- Also, the PyDy numerical simulation code works only for cases where the
|
||||
matrix say ``ZERO = FR() + FRSTAR()`` is solved for. It doesn't work well when the
|
||||
matrix has some other equations plugged in as well. One hurdle
|
||||
faced in achieving this was that PyDy's System class automatically takes
|
||||
in the ``forcing_full`` and ``mass_matrix_full`` and solves them without giving the
|
||||
user the flexibility to specify the equations. It would be nice to add
|
||||
this functionality to the System class.
|
||||
|
||||
|
||||
.. _future_improvements:
|
||||
|
||||
Future Improvements
|
||||
===================
|
||||
|
||||
1. Completing Dynamics Online
|
||||
-----------------------------
|
||||
The parser has been built by referring to and parsing codes from the
|
||||
`Autolev Tutorial <http://web.mae.ufl.edu/~fregly/PDFs/autolev_tutorial.pdf>`_
|
||||
and the book *Dynamics Online: Theory and Implementation Using Autolev*.
|
||||
Basically, the process involved going through each of these codes,
|
||||
validating the parser results and improving the rules if required
|
||||
to make sure the codes parsed well.
|
||||
|
||||
The parsed codes of these are available on GitLab `here <https://gitlab.com/sympy/autolev-test-examples>`_.
|
||||
The repo is private so access needs to be requested.
|
||||
As of now, most codes till Chapter 4 of *Dynamics Online* have been parsed.
|
||||
|
||||
Completing all the remaining codes of the book (namely, *2-10*, *2-11*, *rest
|
||||
of Ch4*, *Ch5* and *Ch6* (less important) ) would make the parser more complete.
|
||||
|
||||
|
||||
2. Fixing Issues
|
||||
----------------
|
||||
The second thing to do would be to go about fixing the problems described
|
||||
above in the :ref:`Gotchas <gotchas_autolev>` and :ref:`Limitations and Issues <issues>`
|
||||
sections in order of priority and ease. Many of these require changes
|
||||
in the parser code while some of these are better fixed by adding some
|
||||
functionality to SymPy.
|
||||
|
||||
|
||||
3. Switching to an AST
|
||||
----------------------
|
||||
The parser is currently built using a kind of Concrete Syntax Tree (CST)
|
||||
using the `ANTLR <http://www.antlr.org/>`_ framework. It would be ideal to switch from a CST to an
|
||||
Abstract Syntax Tree (AST). This way, the parser code will be independent
|
||||
of the ANTLR grammar which makes it a lot more flexible. It would also be
|
||||
easier to make changes to the grammar and the rules of the parser.
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (https://www.inkscape.org/) -->
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
@@ -9,7 +9,7 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="https://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="378.90466"
|
||||
height="456.13843"
|
||||
id="svg2"
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (https://www.inkscape.org/) -->
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
@@ -8,7 +8,7 @@
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="https://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="550"
|
||||
height="550"
|
||||
id="svg2"
|
||||
|
||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
@@ -56,12 +56,14 @@ accelerations(q double dots) with the ``rhs`` method. ::
|
||||
>>> q = [q1, q2, q3]
|
||||
>>> l = LagrangesMethod(Lag, q)
|
||||
>>> le = l.form_lagranges_equations()
|
||||
>>> le.simplify(); le
|
||||
>>> le = le.simplify()
|
||||
>>> le
|
||||
Matrix([
|
||||
[m*r**2*(6*sin(q2)*q3'' + 5*sin(2*q2)*q1'*q2' + 6*cos(q2)*q2'*q3' - 5*cos(2*q2)*q1''/2 + 7*q1''/2)/4],
|
||||
[ m*r*(4*g*sin(q2) - 5*r*sin(2*q2)*q1'**2/2 - 6*r*cos(q2)*q1'*q3' + 5*r*q2'')/4],
|
||||
[ 3*m*r**2*(sin(q2)*q1'' + cos(q2)*q1'*q2' + q3'')/2]])
|
||||
>>> lrhs = l.rhs(); lrhs.simplify(); lrhs
|
||||
>>> lrhs = l.rhs().simplify()
|
||||
>>> lrhs
|
||||
Matrix([
|
||||
[ q1'],
|
||||
[ q2'],
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
.. _classical_mechanics:
|
||||
|
||||
===================
|
||||
Classical Mechanics
|
||||
===================
|
||||
@@ -83,8 +81,6 @@ Guide to Mechanics
|
||||
examples.rst
|
||||
advanced.rst
|
||||
reference.rst
|
||||
autolev_parser.rst
|
||||
sympy_mechanics_for_autolev_users.rst
|
||||
|
||||
Mechanics API
|
||||
=============
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
.. _kane_method:
|
||||
|
||||
==================================
|
||||
Kane's Method in Physics/Mechanics
|
||||
==================================
|
||||
|
||||
@@ -3,7 +3,7 @@ Lagrange's Method in Physics/Mechanics
|
||||
======================================
|
||||
|
||||
:mod:`mechanics` provides functionality for deriving equations of motion
|
||||
using `Lagrange's method <https://en.wikipedia.org/wiki/Lagrangian_mechanics>`_.
|
||||
using `Lagrange's method <http://en.wikipedia.org/wiki/Lagrangian_mechanics>`_.
|
||||
This document will describe Lagrange's method as used in this module, but not
|
||||
how the equations are actually derived.
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
.. _masses:
|
||||
|
||||
=================================================================
|
||||
Masses, Inertias, Particles and Rigid Bodies in Physics/Mechanics
|
||||
=================================================================
|
||||
@@ -223,42 +221,40 @@ The following example shows how to use the momenta functions in
|
||||
One begins by creating the requisite symbols to describe the system. Then
|
||||
the reference frame is created and the kinematics are done. ::
|
||||
|
||||
>>> from sympy import symbols
|
||||
>>> from sympy.physics.mechanics import dynamicsymbols, ReferenceFrame
|
||||
>>> from sympy.physics.mechanics import RigidBody, Particle, Point, outer
|
||||
>>> from sympy.physics.mechanics import linear_momentum, angular_momentum
|
||||
>>> m, M, l1 = symbols('m M l1')
|
||||
>>> q1d = dynamicsymbols('q1d')
|
||||
>>> N = ReferenceFrame('N')
|
||||
>>> O = Point('O')
|
||||
>>> O.set_vel(N, 0 * N.x)
|
||||
>>> Ac = O.locatenew('Ac', l1 * N.x)
|
||||
>>> P = Ac.locatenew('P', l1 * N.x)
|
||||
>>> a = ReferenceFrame('a')
|
||||
>>> a.set_ang_vel(N, q1d * N.z)
|
||||
>>> Ac.v2pt_theory(O, N, a)
|
||||
l1*q1d*N.y
|
||||
>>> P.v2pt_theory(O, N, a)
|
||||
2*l1*q1d*N.y
|
||||
>> from sympy import symbols
|
||||
>> from sympy.physics.mechanics import dynamicsymbols, ReferenceFrame
|
||||
>> from sympy.physics.mechanics import RigidBody, Particle, Point, outer
|
||||
>> from sympy.physics.mechanics import linear_momentum, angular_momentum
|
||||
>> m, M, l1 = symbols('m M l1')
|
||||
>> q1d = dynamicsymbols('q1d')
|
||||
>> N = ReferenceFrame('N')
|
||||
>> O = Point('O')
|
||||
>> O.set_vel(N, 0 * N.x)
|
||||
>> Ac = O.locatenew('Ac', l1 * N.x)
|
||||
>> P = Ac.locatenew('P', l1 * N.x)
|
||||
>> a = ReferenceFrame('a')
|
||||
>> a.set_ang_vel(N, q1d * N.z)
|
||||
>> Ac.v2pt_theory(O, N, a)
|
||||
>> P.v2pt_theory(O, N, a)
|
||||
|
||||
Finally, the bodies that make up the system are created. In this case the
|
||||
system consists of a particle Pa and a RigidBody A. ::
|
||||
|
||||
>>> Pa = Particle('Pa', P, m)
|
||||
>>> I = outer(N.z, N.z)
|
||||
>>> A = RigidBody('A', Ac, a, M, (I, Ac))
|
||||
>> Pa = Particle('Pa', P, m)
|
||||
>> I = outer(N.z, N.z)
|
||||
>> A = RigidBody('A', Ac, a, M, (I, Ac))
|
||||
|
||||
Then one can either choose to evaluate the momenta of individual components
|
||||
of the system or of the entire system itself. ::
|
||||
|
||||
>>> linear_momentum(N,A)
|
||||
>> linear_momentum(N,A)
|
||||
M*l1*q1d*N.y
|
||||
>>> angular_momentum(O, N, Pa)
|
||||
>> angular_momentum(O, N, Pa)
|
||||
4*l1**2*m*q1d*N.z
|
||||
>>> linear_momentum(N, A, Pa)
|
||||
>> linear_momentum(N, A, Pa)
|
||||
(M*l1*q1d + 2*l1*m*q1d)*N.y
|
||||
>>> angular_momentum(O, N, A, Pa)
|
||||
(M*l1**2*q1d + 4*l1**2*m*q1d + q1d)*N.z
|
||||
>> angular_momentum(O, N, A, Pa)
|
||||
(4*l1**2*m*q1d + q1d)*N.z
|
||||
|
||||
It should be noted that the user can determine either momenta in any frame
|
||||
in :mod:`mechanics` as the user is allowed to specify the reference frame when
|
||||
@@ -327,34 +323,33 @@ The following example shows how to use the energy functions in
|
||||
As was discussed above in the momenta functions, one first creates the system
|
||||
by going through an identical procedure. ::
|
||||
|
||||
>>> from sympy import symbols
|
||||
>>> from sympy.physics.mechanics import dynamicsymbols, ReferenceFrame, outer
|
||||
>>> from sympy.physics.mechanics import RigidBody, Particle
|
||||
>>> from sympy.physics.mechanics import kinetic_energy, potential_energy, Point
|
||||
>>> m, M, l1, g, h, H = symbols('m M l1 g h H')
|
||||
>>> omega = dynamicsymbols('omega')
|
||||
>>> N = ReferenceFrame('N')
|
||||
>>> O = Point('O')
|
||||
>>> O.set_vel(N, 0 * N.x)
|
||||
>>> Ac = O.locatenew('Ac', l1 * N.x)
|
||||
>>> P = Ac.locatenew('P', l1 * N.x)
|
||||
>>> a = ReferenceFrame('a')
|
||||
>>> a.set_ang_vel(N, omega * N.z)
|
||||
>>> Ac.v2pt_theory(O, N, a)
|
||||
l1*omega*N.y
|
||||
>>> P.v2pt_theory(O, N, a)
|
||||
2*l1*omega*N.y
|
||||
>>> Pa = Particle('Pa', P, m)
|
||||
>>> I = outer(N.z, N.z)
|
||||
>>> A = RigidBody('A', Ac, a, M, (I, Ac))
|
||||
>> from sympy import symbols
|
||||
>> from sympy.physics.mechanics import dynamicsymbols, ReferenceFrame, outer
|
||||
>> from sympy.physics.mechanics import RigidBody, Particle, mechanics_printing
|
||||
>> from symp.physics.mechanics import kinetic_energy, potential_energy, Point
|
||||
>> mechanics_printing()
|
||||
>> m, M, l1, g, h, H = symbols('m M l1 g h H')
|
||||
>> omega = dynamicsymbols('omega')
|
||||
>> N = ReferenceFrame('N')
|
||||
>> O = Point('O')
|
||||
>> O.set_vel(N, 0 * N.x)
|
||||
>> Ac = O.locatenew('Ac', l1 * N.x)
|
||||
>> P = Ac.locatenew('P', l1 * N.x)
|
||||
>> a = ReferenceFrame('a')
|
||||
>> a.set_ang_vel(N, omega * N.z)
|
||||
>> Ac.v2pt_theory(O, N, a)
|
||||
>> P.v2pt_theory(O, N, a)
|
||||
>> Pa = Particle('Pa', P, m)
|
||||
>> I = outer(N.z, N.z)
|
||||
>> A = RigidBody('A', Ac, a, M, (I, Ac))
|
||||
|
||||
The user can then determine the kinetic energy of any number of entities of the
|
||||
system: ::
|
||||
|
||||
>>> kinetic_energy(N, Pa)
|
||||
2*l1**2*m*omega(t)**2
|
||||
>>> kinetic_energy(N, Pa, A)
|
||||
M*l1**2*omega(t)**2/2 + 2*l1**2*m*omega(t)**2 + omega(t)**2/2
|
||||
>> kinetic_energy(N, Pa)
|
||||
2*l1**2*m*q1d**2
|
||||
>> kinetic_energy(N, Pa, A)
|
||||
M*l1**2*q1d**2/2 + 2*l1**2*m*q1d**2 + q1d**2/2
|
||||
|
||||
It should be noted that the user can determine either kinetic energy relative
|
||||
to any frame in :mod:`mechanics` as the user is allowed to specify the
|
||||
@@ -366,15 +361,14 @@ every entity of the system using the :mod:`potential_energy` property. The
|
||||
potential energy of any number of entities comprising the system can then be
|
||||
determined: ::
|
||||
|
||||
>>> Pa.potential_energy = m * g * h
|
||||
>>> A.potential_energy = M * g * H
|
||||
>>> potential_energy(A, Pa)
|
||||
>> Pa.potential_energy = m * g * h
|
||||
>> A.potential_energy = M * g * H
|
||||
>> potential_energy(A, Pa)
|
||||
H*M*g + g*h*m
|
||||
|
||||
One can also determine the Lagrangian for this system: ::
|
||||
|
||||
>>> from sympy.physics.mechanics import Lagrangian
|
||||
>>> Lagrangian(N, Pa, A)
|
||||
-H*M*g + M*l1**2*omega(t)**2/2 - g*h*m + 2*l1**2*m*omega(t)**2 + omega(t)**2/2
|
||||
>> Lagrangian(Pa, A)
|
||||
-H*M*g + M*l1**2*q1d**2/2 - g*h*m + 2*l1**2*m*q1d**2 + q1d**2/2
|
||||
|
||||
Please refer to the docstrings to learn more about each function.
|
||||
|
||||
@@ -1,717 +0,0 @@
|
||||
.. _sympy_mechanics_for_autolev_users:
|
||||
|
||||
=================================
|
||||
SymPy Mechanics for Autolev Users
|
||||
=================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Autolev (now superseded by MotionGenesis) is a domain specific programming
|
||||
language which is used for symbolic multibody dynamics. The SymPy mechanics
|
||||
module now has enough power and functionality to be a fully featured symbolic
|
||||
dynamics module. The PyDy package extends the SymPy output to the numerical
|
||||
domain for simulation, analyses and visualization. Autolev and SymPy Mechanics have
|
||||
a lot in common but there are also many differences between them.
|
||||
This page shall expand upon their differences. It is meant to be a go-to
|
||||
reference for Autolev users who want to transition to SymPy Mechanics.
|
||||
|
||||
It would be nice to have a basic understanding of SymPy and SymPy Mechanics before
|
||||
going over this page.
|
||||
If you are completely new to Python, you can check out the official
|
||||
`Python Tutorial <https://docs.python.org/3/tutorial/>`_.
|
||||
Check out the :ref:`SymPy Documentation <documentation>`, especially
|
||||
the tutorial to get a feel for SymPy.
|
||||
For an introduction to Multibody dynamics in Python, `this <https://www.youtube.com/watch?v=mdo2NYtA-xY&t=6950s>`_
|
||||
lecture is very helpful.
|
||||
|
||||
You might also find the :ref:`Autolev Parser <autolev_parser>` which is
|
||||
a part of SymPy to be helpful.
|
||||
|
||||
Some Key Differences
|
||||
------------------------
|
||||
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| **Autolev** | **SymPy Mechanics** |
|
||||
+===================================+===================================+
|
||||
|| || |
|
||||
| Autolev is a domain specific | SymPy is a library written in the |
|
||||
| programming language designed to | general purpose language Python. |
|
||||
| perform multibody dynamics. Since | Although Autolev's code is more |
|
||||
| it is a language of its own, it | compact, SymPy (by virtue of being|
|
||||
| has a very rigid language | an add on to Python) is more |
|
||||
| specification. It predefines, | flexible. The users have more |
|
||||
| assumes and computes | control over what they can do. For|
|
||||
| many things based on the | example, one can create a class in|
|
||||
| input code. Its code is a lot | their code for let's say a type of|
|
||||
| cleaner and concise as a result of| rigibodies with common |
|
||||
| this. | properties. |
|
||||
| | The wide array of scientific |
|
||||
| | Python libraries available is also|
|
||||
| | a big plus. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|| || |
|
||||
| Autolev generates Matlab, C, or | SymPy generates numerical Python, |
|
||||
| Fortran code from a small set of | C or Octave/Matlab code from a |
|
||||
| symbolic mathematics. | large set of symbolic mathematics |
|
||||
| | created with SymPy. It also builds|
|
||||
| | on the popular scientific Python |
|
||||
| | stack such as NumPy, SciPy, |
|
||||
| | IPython, matplotlib, Cython and |
|
||||
| | Theano. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|| || |
|
||||
| Autolev uses 1 (one) based | Python uses 0 (zero) based |
|
||||
| indexing. The initial element of | indexing. The initial element of |
|
||||
| a sequence is found using a[1]. | a sequence is found using a[0]. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|| || |
|
||||
| Autolev is case insensitive. | SymPy code being Python code is |
|
||||
| | case sensitive. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|| || |
|
||||
| One can define their own commands | SymPy code is Python code, so one |
|
||||
| in Autolev by making .R and .A | can define functions in their |
|
||||
| files which can be used in their | code. This is a lot more |
|
||||
| programs. | convenient. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|| || |
|
||||
| Autolev is proprietary. | SymPy is open source. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|
||||
Rough Autolev-SymPy Equivalents
|
||||
----------------------------------
|
||||
|
||||
The tables below give rough equivalents for some common Autolev
|
||||
expressions. **These are not exact equivalents**, but rather should be
|
||||
taken as hints to get you going in the right direction. For more detail
|
||||
read the built-in documentation on :ref:`SymPy vectors <physics_vector>`,
|
||||
:ref:`SymPy mechanics <classical_mechanics>` and
|
||||
`PyDy <https://www.pydy.org/documentation.html>`_ .
|
||||
|
||||
In the tables below, it is assumed that you have executed the following
|
||||
commands in Python:
|
||||
::
|
||||
|
||||
import sympy.physics.mechanics as me
|
||||
import sympy as sm
|
||||
|
||||
Mathematical Equivalents
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| **Autolev** | **SymPy** | **Notes** |
|
||||
+=======================+=======================+=======================+
|
||||
|| || || |
|
||||
| ``Constants A, B`` | ``a, b = | Note that the names |
|
||||
| | sm.symbols(‘a | of the symbols can be |
|
||||
| | b’, real=True)`` | different from the |
|
||||
| | | names of the |
|
||||
| | | variables they are |
|
||||
| | | assigned to. We can |
|
||||
| | | define ``a, b = |
|
||||
| | | symbols(‘b a’)`` but |
|
||||
| | | its good practice to |
|
||||
| | | follow the |
|
||||
| | | convention. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``Constants C+`` | ``c = sm.symbols(‘c’, | Refer to SymPy |
|
||||
| | real=True, | :ref:`assumptions |
|
||||
| | nonnegative=True)`` | <assumptions_module>` |
|
||||
| | | for more information. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``Constants D-`` | ``d = sm.symbols(‘d’, | |
|
||||
| | real=True, | |
|
||||
| | nonpositive=True)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``Constants K{4}`` | ``k1, k2, k3, k4 = | |
|
||||
| | sm.symbols('k1 k2 k3 | |
|
||||
| | k4', real=True)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``Constants a{2:4}`` | ``a2, a3, a4 = | |
|
||||
| | sm.symbols('a2 a3 a4',| |
|
||||
| | real=True)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``Constants | ``b11, b12, b21, b22 =| |
|
||||
| b{1:2, 1:2}`` | sm.symbols('b11 b12 | |
|
||||
| | b21 b22', real=True)``| |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``Specified Phi`` | ``phi = | |
|
||||
| | me.dynamicsymbols(‘phi| |
|
||||
| | ')`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``Variables q, s`` | ``q, s = | |
|
||||
| | me.dynamicsymbols(q, | |
|
||||
| | s)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Variables x’’`` | ``x = | |
|
||||
| | me.dynamicsymbols(‘x’ | |
|
||||
| | )`` | |
|
||||
| | | |
|
||||
| | ``xd = | |
|
||||
| | me.dynamicsymbols(‘x’ | |
|
||||
| | , 1)`` | |
|
||||
| | | |
|
||||
| | ``xd2 = | |
|
||||
| | me.dynamicsymbols(‘x’ | |
|
||||
| | , 2)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Variables y{2}’`` | ``y1 = | |
|
||||
| | me.dynamicsymbols(‘y1’| |
|
||||
| | )`` | |
|
||||
| | | |
|
||||
| | ``y2 = | |
|
||||
| | me.dynamicsymbols(‘y2’| |
|
||||
| | )`` | |
|
||||
| | | |
|
||||
| | ``y1d = | |
|
||||
| | me.dynamicsymbols(‘y1’| |
|
||||
| | , 1)`` | |
|
||||
| | | |
|
||||
| | ``y2d = | |
|
||||
| | me.dynamicsymbols(‘y2'| |
|
||||
| | , 1)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``MotionVariables | ``u1 = | SymPy doesn’t |
|
||||
| u{2}`` | me.dynamicsymbols(‘u1’| differentiate between |
|
||||
| | )`` | variables, |
|
||||
| | | motionvariables and |
|
||||
| | ``u2 = | specifieds during |
|
||||
| | me.dynamicsymbols('u2'| declaration. Instead, |
|
||||
| | )`` | it takes different |
|
||||
| | | lists of these as |
|
||||
| | | parameters in objects |
|
||||
| | | like the KanesMethod. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Imaginary j`` | ``j = sm.I`` | I is a sympy object |
|
||||
| | | which stands for the |
|
||||
| | | imaginary unit. One |
|
||||
| | | can define complex |
|
||||
| | | numbers using it. |
|
||||
| | | |
|
||||
| | | ``z = x + I*y`` |
|
||||
| | | |
|
||||
| | | where x, y and z are |
|
||||
| | | symbols. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Tina = 2*pi`` | ``tina = 2*sm.pi`` | Using ``.evalf()`` |
|
||||
| | | will result in the |
|
||||
| | ``tina = | numeric value. |
|
||||
| | tina.evalf()`` | |
|
||||
| | | |
|
||||
| ``s = u*t + a*t^2/2`` | ``t = | |
|
||||
| | me.dynamicsymbols._t``| |
|
||||
| | | |
|
||||
| | ``s = u*t + a*t**2/2``| |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|| || || |
|
||||
| ``abs(x)^3 + sin(x)^2 | ``sm.abs(x)**3 | |
|
||||
| + acos(x)`` | + sm.sin(x)**2 + | |
|
||||
| | sm.acos(x)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``E = (x+2*y)^2 + | ``E = (x+2*y)**2 + | For more information |
|
||||
| 3*(7+x)*(x+y)`` | 3*(7+x)*(x+y)`` | refer to |
|
||||
| | | :ref:`simplification. |
|
||||
| ``Expand(E)`` | ``sm.expand(E)`` | <tutorial-simplify>` |
|
||||
| | | |
|
||||
| ``Factor(E, x)`` | ``sm.horner(E, | |
|
||||
| | wrt=x)`` | |
|
||||
| | | |
|
||||
| ``Coef(y, x)`` | ``y.coeff(x)`` | These SymPy functions |
|
||||
| | | do not work in place. |
|
||||
| ``Replace(y, | ``y.subs({sm.sin(x): | They just return |
|
||||
| sin(x)=3)`` | 3})`` | expressions. If you |
|
||||
| | | want to overwrite the |
|
||||
| ``Exclude(E,x)`` | ``e.collect(x).coeff( | original expression |
|
||||
| | x, 0)`` | you would have to do |
|
||||
| | | something like: |
|
||||
| ``Include(E,x)`` | ``e.collect(x).coeff( | |
|
||||
| | x, 1)`` | ``y = |
|
||||
| | | y.subs({sm.sin(x): |
|
||||
| ``Arrange(E,2,y)`` | ``e.collect(y)`` | 3})`` |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Dy = D(E, y)`` | ``E.diff(y)`` | For more information |
|
||||
| | | refer to |
|
||||
| ``Dt = Dt(E)`` | ``E.diff( | :ref:`calculus. |
|
||||
| | me.dynamicsymbols._t | <calculus>` |
|
||||
| | )`` | |
|
||||
| | | |
|
||||
| | Works if the | |
|
||||
| | expression is made up | |
|
||||
| | of dynamicsymbols. | |
|
||||
| ``Dt2 = Dt(V, A)`` | | |
|
||||
| where V is a vector | ``dt2 = v.dt(A)`` | |
|
||||
| and A is a frame | | |
|
||||
| | | |
|
||||
| ``Dy2 = D(V, y, A)`` | ``dy2 = v.diff(y, A)``| |
|
||||
| | | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``E = COS(X*Y)`` | ``e = sm.cos(x*y)`` | For more information |
|
||||
| | | refer to :ref:`series.|
|
||||
| ``TY = Taylor(E, | ``b = e.series(x, 0, | <series_expansions>` |
|
||||
| 0:2, x=0, y=0)`` | 2).removeO().series(y,| |
|
||||
| | 0, 2).removeO()`` | |
|
||||
| | | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``F = Evaluate(E, | ``E.subs([(x, a), (y, | |
|
||||
| x=a, y=2)`` | 2)])`` | |
|
||||
| | | |
|
||||
| | To get floating point | |
|
||||
| | numbers from numerical| |
|
||||
| | expressions use | |
|
||||
| | ``.evalf()`` | |
|
||||
| | | |
|
||||
| | ``E.evalf((a + | |
|
||||
| | sm.pi).subs({a: 3}))``| |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``P = Polynomial([a, | ``p = | For more information |
|
||||
| b, c], x)`` | sm.Poly(sm.Matrix([a, | refer to |
|
||||
| | b, c]).reshape(1, 3), | :ref:`polys. |
|
||||
| | x)`` | <polys-reference>` |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Roots(Polynomial( | ``sm.solve( | For more information |
|
||||
| a*x^2 + b*x + c, x, | sm.Poly(a*x**2 + | refer to |
|
||||
| 2)`` | b*x + c))`` | :ref:`solvers`. |
|
||||
| | | |
|
||||
| ``Roots([1;2;3])`` | ``sm.solve(sm.Poly( | For numerical |
|
||||
| | sm.Matrix([1,2,3]). | computation related |
|
||||
| | reshape(3, 1), x), | to polynomials and |
|
||||
| | x)`` | roots refer to |
|
||||
| | | `mpmath/calculus. <htt|
|
||||
| | | p://docs.s |
|
||||
| | | ympy.org/0.7.6/module |
|
||||
| | | s/mpmath/calculus/pol |
|
||||
| | | ynomials.html>`_ |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Solve(A, x1, x2)`` | ``sm.linsolve(A, | For more information |
|
||||
| | (x1, x2))`` | refer to |
|
||||
| | | :ref:` |
|
||||
| where A is an | where A is an | solvers/solveset. |
|
||||
| augmented matrix that | augmented matrix | <solveset>` |
|
||||
| represents the linear | | |
|
||||
| equations and x1, x2 | | |
|
||||
| are the variables to | | For non linear solvers|
|
||||
| solve for. | | refer to |
|
||||
| | | ``nonlinsolve`` and |
|
||||
| | | ``nsolve`` in |
|
||||
| | | :ref:`solvers. |
|
||||
| | | <solvers>` |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``RowMatrix = [1, 2, | ``row_matrix = | For more information |
|
||||
| 3, 4]`` | sm.Matrix([[1],[2], | refer to |
|
||||
| | [3],[4]])`` | :ref:`matrices. |
|
||||
| | | <matrices>` |
|
||||
| ``ColMatrix = [1; 2; | ``col_matrix = | |
|
||||
| 3; 4]`` | sm.Matrix([1, 2, 3, | |
|
||||
| | 4])`` | |
|
||||
| | | |
|
||||
| ``MO = [a, b; c, 0]`` | ``MO = sm.Matrix([[a, | |
|
||||
| | b], [c, 0]])`` | |
|
||||
| | | |
|
||||
| ``MO[2, 2] := d`` | ``MO[1, 1] = d`` | |
|
||||
| | | |
|
||||
| ``A + B*C`` | ``A + B*C`` | |
|
||||
| | | |
|
||||
| ``Cols(A)`` | ``A.cols`` | |
|
||||
| | | |
|
||||
| ``Cols(A, 1)`` | ``A.col(0)`` | |
|
||||
| | | |
|
||||
| ``Rows(A)`` | ``A.rows`` | |
|
||||
| | | |
|
||||
| ``Rows(A, 1)`` | ``A.row(0)`` | |
|
||||
| | | |
|
||||
| ``Det(A)`` | ``M.det()`` | |
|
||||
| | | |
|
||||
| ``Element(A, 2, 3)`` | ``M[2, 3]`` | |
|
||||
| | | |
|
||||
| ``Inv(A)`` | ``M**-1`` | |
|
||||
| | | |
|
||||
| ``Trace(A)`` | ``sm.trace(A)`` | |
|
||||
| | | |
|
||||
| ``Transpose(A)`` | ``A.T`` | |
|
||||
| | | |
|
||||
| ``Diagmat(4, 1)`` | ``sm.diag(1,1,1,1)`` | |
|
||||
| | | |
|
||||
| ``Eig(A)`` | ``A.eigenvals()`` | |
|
||||
| | | |
|
||||
| ``Eig(A, EigVal, | ``eigval = | |
|
||||
| EigVec)`` | A.eigenvals()`` | |
|
||||
| | | |
|
||||
| | ``eigvec = | |
|
||||
| | A.eigenvects()`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|
||||
|
||||
Physical Equivalents
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| **Autolev** | **SymPy** | **Notes** |
|
||||
+=======================+=======================+=======================+
|
||||
| ``Bodies A`` | ``m =sm.symbols(‘m’)``| The 4th and 5th |
|
||||
| | | arguments are for the |
|
||||
| Declares A, its | ``Ao = | mass and inertia. |
|
||||
| masscenter Ao, and | sm.symbols(‘Ao’)`` | These are specified |
|
||||
| orthonormal vectors | | after the declaration |
|
||||
| A1>, A2> and A3> | ``Af = | in Autolev. |
|
||||
| fixed in A. | me.ReferenceFrame(‘Af’| |
|
||||
| | )`` | |
|
||||
| | | |
|
||||
| | ``I = | One can pass a dummy |
|
||||
| | me.outer(Af.x,Af.x)`` | for the parameters |
|
||||
| | | and use setters |
|
||||
| | ``P = me.Point(‘P’)`` | ``A.mass = \_`` and |
|
||||
| | | ``A.inertia = \_`` to |
|
||||
| | ``A =me.RigidBody(‘A’,| set them later. |
|
||||
| | Ao, Af, m, (I, P))`` | |
|
||||
| | | |
|
||||
| | Af.x, Af.y and Af.z | For more information |
|
||||
| | are equivalent to | refer to |
|
||||
| | A1>, A2> and A3>. | :ref:`mechanics/masses|
|
||||
| | | .<masses>` |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Frames A`` | ``A = | For more information |
|
||||
| | me.ReferenceFrame(‘A’ | refer to |
|
||||
| ``V1> = | )`` | :ref:`physics/vectors.|
|
||||
| X1*A1> + X2*A2>`` | | <matrices>` |
|
||||
| | ``v1 = | |
|
||||
| | x1*A.x + x2*A.y`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Newtonian N`` | ``N = | SymPy doesn’t specify |
|
||||
| | me.ReferenceFrame(‘N’ | that a frame is |
|
||||
| | )`` | inertial during |
|
||||
| | | declaration. Many |
|
||||
| | | functions such as |
|
||||
| | | ``set_ang_vel()`` take|
|
||||
| | | the inertial |
|
||||
| | | reference frame as a |
|
||||
| | | parameter. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Particles C`` | ``m = | The 2nd and 3rd |
|
||||
| | sm.symbols(‘m’)`` | arguments are for the |
|
||||
| | | point and mass. In |
|
||||
| | ``Po = | Autolev, these are |
|
||||
| | me.Point(‘Po’)`` | specified after the |
|
||||
| | | declaration. |
|
||||
| | ``C = me.Particle(‘C’,| |
|
||||
| | Po, m)`` | One can pass a dummy |
|
||||
| | | and use setters |
|
||||
| | | (``A.point = \_`` and |
|
||||
| | | ``A.mass = \_``) to |
|
||||
| | | set them later. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Points P, Q`` | ``P = me.Point(‘P’)`` | |
|
||||
| | | |
|
||||
| | ``Q = me.Point(‘Q’)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Mass B=mB`` | ``mB = symbols(‘mB’)``| |
|
||||
| | | |
|
||||
| | ``B.mass = mB`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Inertia B, I1, I2, | ``I = me.inertia(Bf, | For more information |
|
||||
| I3, I12, I23, I31`` | i1, i2, i3, i12, i23, | refer to the |
|
||||
| | i31)`` | :ref:`mechanics api. |
|
||||
| | | <part_bod>` |
|
||||
| | ``B.inertia = (I, P)``| |
|
||||
| | where B is a | |
|
||||
| | rigidbody, Bf is the | |
|
||||
| | related frame and P is| |
|
||||
| | the center of mass of | |
|
||||
| | B. | |
|
||||
| | | |
|
||||
| | Inertia dyadics can | |
|
||||
| | also be formed using | |
|
||||
| | vector outer products.| |
|
||||
| | | |
|
||||
| | ``I = | |
|
||||
| | me.outer(N.x, N.x)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``vec> = P_O_Q>/L`` | ``vec = | For more information |
|
||||
| | (Qo.pos_from(O))/L`` | refer to |
|
||||
| ``vec> = | | :ref:`physics/vectors.|
|
||||
| u1*N1> + u2*N2>`` | ``vec = | <physics_vector>` |
|
||||
| | u1*N.x + u2*N.y`` | |
|
||||
| ``Cross(a>, b>)`` | | |
|
||||
| | ``cross(a, b)`` | |
|
||||
| ``Dot(a>, b>)`` | | |
|
||||
| | ``dot(a, b)`` | |
|
||||
| ``Mag(v>)`` | | |
|
||||
| | ``v.magnitude()`` | |
|
||||
| ``Unitvec(v>)`` | | |
|
||||
| | ``v.normalize()`` | |
|
||||
| | | |
|
||||
| ``DYAD>> = 3*A1>*A1> +| ``dyad = | |
|
||||
| A2>*A2> + 2*A3>*A3>`` | 3*me.outer(a.x | |
|
||||
| | ,a.x) + me.outer(a.y, | |
|
||||
| | a.y) + 2*me.outer(a.z | |
|
||||
| | ,a.z)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``P_O_Q> = LA*A1>`` | ``Q.point = | For more information |
|
||||
| | O.locatenew(‘Qo’, | refer to the |
|
||||
| | LA*A.x)`` | :ref:`kinematics api. |
|
||||
| | | <kinematics>` |
|
||||
| ``P_P_Q> = LA*A1>`` | where A is a | |
|
||||
| | reference frame. | |
|
||||
| | | |
|
||||
| | ``Q.point = | |
|
||||
| | P.point.locatenew(‘Qo | All these vector and |
|
||||
| | ’, | kinematic functions |
|
||||
| | LA*A.x)`` | are to be used on |
|
||||
| | | ``Point`` objects and |
|
||||
| | | not ``Particle`` |
|
||||
| | | objects so ``.point`` |
|
||||
| | | must be used for |
|
||||
| | | particles. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``V_O_N> = u3*N.1> + | ``O.set_vel(N, u1*N.x | The getter would be |
|
||||
| u4*N.2>`` | + u2*N.y)`` | ``O.vel(N)``. |
|
||||
| | | |
|
||||
| ``Partials(V_O_N>, | ``O.partial_velocity(N| |
|
||||
| u3)`` | , u3)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``A_O_N> = 0>`` | ``O.set_acc(N, 0)`` | The getter would be |
|
||||
| | | ``O.acc(N)``. |
|
||||
| Acceleration of point | | |
|
||||
| O in reference frame | | |
|
||||
| N. | | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``W_B_N> = qB’*B3>`` | ``B.set_ang_vel(N, | The getter would be |
|
||||
| | qBd*Bf.z)`` | ``B.ang_vel_in(N)``. |
|
||||
| Angular velocity of | | |
|
||||
| body B in reference | where Bf is the frame | |
|
||||
| frame F. | associated with the | |
|
||||
| | body B. | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``ALF_B_N> =Dt(W_B_N>,| ``B.set_ang_acc(N, | The getter would be |
|
||||
| N)`` | diff(B.ang_vel_in(N) | ``B.ang_acc_in(N)``. |
|
||||
| | )`` | |
|
||||
| Angular acceleration | | |
|
||||
| of body B in | | |
|
||||
| reference frame N. | | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Force_O> = F1*N1> + | In SymPy one should | |
|
||||
| F2*N2>`` | have a list which | |
|
||||
| | contains all the | |
|
||||
| ``Torque_A> = | forces and torques. | |
|
||||
| -c*qA’*A3>`` | | |
|
||||
| | ``fL.append((O, f1*N.x| |
|
||||
| | + f2*N.y))`` | |
|
||||
| | | |
|
||||
| | where fL is the force | |
|
||||
| | list. | |
|
||||
| | | |
|
||||
| | ``fl.append((A, | |
|
||||
| | -c*qAd*A.z))`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``A_B = M`` | ``B.orient(A, 'DCM', | |
|
||||
| where M is a matrix | M)`` where M is a | |
|
||||
| and A, B are frames. | SymPy Matrix. | |
|
||||
| | | |
|
||||
| ``D = A_B*2 + 1`` | ``D = A.dcm(B)*2 + 1``| |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``CM(B)`` | ``B.masscenter`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Mass(A,B,C)`` | ``A.mass + B.mass + | |
|
||||
| | C.mass`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``V1pt(A,B,P,Q)`` | ``Q.v1pt_theory(P, A, | P and Q are assumed to|
|
||||
| | B)`` | be ``Point`` objects |
|
||||
| | | here. Remember to use |
|
||||
| | | ``.point`` for |
|
||||
| | | particles. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``V2pts(A,B,P,Q)`` | ``Q.v2pt_theory(P, A, | |
|
||||
| | B)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``A1pt(A,B,P,Q)`` | ``Q.a1pt_theory(P, A, | |
|
||||
| | B)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``A2pts(A,B,P,Q)`` | ``Q.a2pt_theory(P, A, | |
|
||||
| | B)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Angvel(A,B)`` | ``B.ang_vel_in(A)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Simprot(A, B, 1, | ``B.orient(A, ‘Axis’, | |
|
||||
| qA)`` | qA, A.x)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Gravity(G*N1>)`` | ``fL.extend(gravity( | In SymPy we must use a|
|
||||
| | g*N.x, P1, P2, ...))``| forceList (here fL) |
|
||||
| | | which contains tuples |
|
||||
| | | of the form ``(point, |
|
||||
| | | force_vector)``. This |
|
||||
| | | is passed to the |
|
||||
| | | ``kanes_equations()`` |
|
||||
| | | method of the |
|
||||
| | | KanesMethod object. |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``CM(O,P1,R)`` | ``me.functions. | |
|
||||
| | center_of_mass(o, p1, | |
|
||||
| | r)`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Force(P/Q, v>)`` | ``fL.append((P, -1*v),| |
|
||||
| | (Q, v))`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Torque(A/B, v>)`` | ``fL.append((A, -1*v),| |
|
||||
| | (B, v))`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Kindiffs(A, B ...)``| ``KM.kindiffdict()`` | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Momentum(option)`` | ``linear_momentum(N, | |
|
||||
| | B1, B2 ...)`` | |
|
||||
| | | |
|
||||
| | reference frame | |
|
||||
| | followed by one or | |
|
||||
| | more bodies | |
|
||||
| | | |
|
||||
| | ``angular_momentum(O, | |
|
||||
| | N, B1, B2 ...)`` | |
|
||||
| | | |
|
||||
| | point, reference | |
|
||||
| | frame followed by one | |
|
||||
| | or more bodies | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``KE()`` | ``kinetic_energy(N, | |
|
||||
| | B1, B2 ...)`` | |
|
||||
| | | |
|
||||
| | reference frame | |
|
||||
| | followed by one or | |
|
||||
| | more bodies | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Constrain(...)`` | ``velocity_constraints| For more details |
|
||||
| | = [...]`` | refer to |
|
||||
| | | :ref:`mechanics/kane |
|
||||
| | ``u_dependent = | <kane_method>` and |
|
||||
| | [...]`` | the :ref:`kane api. |
|
||||
| | | <kane_lagrange>` |
|
||||
| | ``u_auxiliary = | |
|
||||
| | [...]`` | |
|
||||
| | | |
|
||||
| | These lists are | |
|
||||
| | passed to the | |
|
||||
| | KanesMethod object. | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
| ``Fr()`` | ``KM = KanesMethod(f, | For more details |
|
||||
| ``FrStar()`` | q_ind, u_ind, kd_eqs, | refer to |
|
||||
| | q_dependent, configura| :ref:`mechanics/kane |
|
||||
| | tion_constraints, u_de| <kane_method>` and |
|
||||
| | pendent, velocity_cons| the :ref:`kane api. |
|
||||
| | traints, acceleration_| <kane_lagrange>` |
|
||||
| | constraints, u_auxilia| |
|
||||
| | ry)`` | |
|
||||
| | | |
|
||||
| | The KanesMethod | |
|
||||
| | object takes a | |
|
||||
| | reference frame | |
|
||||
| | followed by multiple | |
|
||||
| | lists as arguments. | |
|
||||
| | | |
|
||||
| | ``(fr, frstar) = | |
|
||||
| | KM.kanes_equations(fL,| |
|
||||
| | bL)`` where fL and bL | |
|
||||
| | are lists of forces | |
|
||||
| | and bodies | |
|
||||
| | respectively. | |
|
||||
+-----------------------+-----------------------+-----------------------+
|
||||
|
||||
Numerical Evaluation and Visualization
|
||||
----------------------------------------
|
||||
|
||||
Autolev’s CODE Option() command allows one to generate Matlab, C, or
|
||||
Fortran code for numerical evaluation and visualization. Option can be
|
||||
Dynamics, ODE, Nonlinear or Algebraic.
|
||||
|
||||
Numerical evaluation for dynamics can be achieved using PyDy. One can
|
||||
pass in the KanesMethod object to the System class along with the values
|
||||
for the constants, specifieds, initial conditions and time steps. The
|
||||
equations of motion can then be integrated. The plotting is achieved
|
||||
using matlplotlib. Here is an example from the `PyDy Documentation <https://www.pydy.org/documentation.html>`_
|
||||
on how it is done::
|
||||
|
||||
from numpy import array, linspace, sin
|
||||
from pydy.system import System
|
||||
|
||||
sys = System(kane,
|
||||
constants = {mass: 1.0, stiffness: 1.0,
|
||||
damping: 0.2, gravity: 9.8},
|
||||
specifieds = {force: lambda x, t: sin(t)},
|
||||
initial_conditions = {position: 0.1, speed:-1.0},
|
||||
times = linspace(0.0, 10.0, 1000))
|
||||
|
||||
y = sys.integrate()
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
plt.plot(sys.times, y)
|
||||
plt.legend((str(position), str(speed)))
|
||||
plt.show()
|
||||
|
||||
For information on all the things PyDy can accomplish refer to the
|
||||
`PyDy Documentation <https://www.pydy.org/documentation.html>`_.
|
||||
|
||||
The tools in the PyDy workflow are :
|
||||
|
||||
- `SymPy <https://sympy.org>`_: SymPy is a Python library for
|
||||
symbolic computation. It provides computer algebra capabilities
|
||||
either as a standalone application, as a library to other
|
||||
applications, or live on the web as SymPy Live or SymPy Gamma.
|
||||
|
||||
- `NumPy <https://www.numpy.org/>`_: NumPy is a library for the
|
||||
Python programming language, adding support for large,
|
||||
multi-dimensional arrays and matrices, along with a large
|
||||
collection of high-level mathematical functions to operate on
|
||||
these arrays.
|
||||
|
||||
- `SciPy <https://www.scipy.org/>`_: SciPy is an open source
|
||||
Python library used for scientific computing and technical
|
||||
computing. SciPy contains modules for optimization, linear
|
||||
algebra, integration, interpolation, special functions, FFT,
|
||||
signal and image processing, ODE solvers and other tasks common
|
||||
in science and engineering.
|
||||
|
||||
- `IPython <https://ipython.org/>`_: IPython is a command shell
|
||||
for interactive computing in multiple programming languages,
|
||||
originally developed for the Python programming language, that
|
||||
offers introspection, rich media, shell syntax, tab completion,
|
||||
and history.
|
||||
|
||||
- `Theano <http://deeplearning.net/software/theano/>`_: Theano is
|
||||
a numerical computation library for Python. In Theano,
|
||||
computations are expressed using a NumPy-esque syntax and
|
||||
compiled to run efficiently on either CPU or GPU architectures
|
||||
|
||||
- `Cython <http://cython.org/>`_: Cython is a superset of the
|
||||
Python programming language, designed to give C-like performance
|
||||
with code that is mostly written in Python. Cython is a compiled
|
||||
language that generates CPython extension modules.
|
||||
|
||||
- `matplotlib <https://matplotlib.org/>`_: matplotlib is a
|
||||
plotting library for the Python programming language and its
|
||||
numerical mathematics extension NumPy.
|
||||
|
||||
One will be able to write code equivalent to the Matlab, C or Fortran
|
||||
code generated by Autolev using these scientific computing tools. It is
|
||||
recommended to go over these modules to gain an understanding of
|
||||
scientific computing with Python.
|
||||
|
||||
Links
|
||||
----------
|
||||
|
||||
:ref:`SymPy Tutorial <tutorial>`
|
||||
|
||||
:ref:`SymPy Documentation <documentation>`
|
||||
|
||||
:ref:`SymPy Physics Vector
|
||||
Documentation <physics_vector>`
|
||||
|
||||
:ref:`SymPy Mechanics
|
||||
Documentation <classical_mechanics>`
|
||||
|
||||
`PyDy Documentation <https://www.pydy.org/documentation.html>`_
|
||||
|
||||
`MultiBody Dynamics with Python <https://www.youtube.com/watch?v=mdo2NYtA-xY>`_
|
||||
@@ -2,14 +2,14 @@
|
||||
Examples
|
||||
========
|
||||
|
||||
In the following sections we give few examples of what can be done with this
|
||||
In the following sections we give few examples of what can be do with this
|
||||
module.
|
||||
|
||||
|
||||
Dimensional analysis
|
||||
====================
|
||||
|
||||
We will start from Newton's second law
|
||||
We will start from the second Newton's law
|
||||
|
||||
.. math::
|
||||
m a = F
|
||||
@@ -81,39 +81,26 @@ variables (taken from Wikipedia). The result should be 224.701 days.
|
||||
>>> from sympy.physics.units import day, gravitational_constant as G
|
||||
>>> from sympy.physics.units import meter, kilogram
|
||||
>>> T = symbols("T")
|
||||
>>> a = Quantity("venus_a")
|
||||
|
||||
Specify the dimension and scale in SI units:
|
||||
|
||||
>>> a.set_dimension(length, "SI")
|
||||
>>> a.set_scale_factor(108208000e3*meter, "SI")
|
||||
|
||||
Add the solar mass as quantity:
|
||||
|
||||
>>> M = Quantity("solar_mass")
|
||||
>>> M.set_dimension(mass, "SI")
|
||||
>>> M.set_scale_factor(1.9891e30*kilogram, "SI")
|
||||
|
||||
Now Kepler's law:
|
||||
|
||||
>>> a = Quantity("venus_a", length, 108208000e3*meter)
|
||||
>>> M = Quantity("solar_mass", mass, 1.9891e30*kilogram)
|
||||
>>> eq = Eq(T**2 / a**3, 4*pi**2 / G / M)
|
||||
>>> eq
|
||||
Eq(T**2/venus_a**3, 4*pi**2/(gravitational_constant*solar_mass))
|
||||
>>> q = solve(eq, T)[1]
|
||||
>>> q
|
||||
2*pi*venus_a**(3/2)/(sqrt(gravitational_constant)*sqrt(solar_mass))
|
||||
6.28318530717959*venus_a**(3/2)/(sqrt(gravitational_constant)*sqrt(solar_mass))
|
||||
|
||||
To convert to days, use the ``convert_to`` function (and possibly approximate
|
||||
the outcoming result):
|
||||
the outcoming result:
|
||||
|
||||
>>> from sympy.physics.units import convert_to
|
||||
>>> convert_to(q, day)
|
||||
71.5112118495813*pi*day
|
||||
2.15992161980729e-7*sqrt(1081898088255574765)*day
|
||||
>>> convert_to(q, day).n()
|
||||
224.659097795948*day
|
||||
224.662800523082*day
|
||||
|
||||
We could also have the solar mass and the day as units coming from the
|
||||
astrophysical system, but we wanted to show how to create a unit that one needs.
|
||||
astrophysical system, but I wanted to show how to create a unit that one needs.
|
||||
|
||||
We can see in this example that intermediate dimensions can be ill-defined,
|
||||
such as sqrt(G), but one should check that the final result - when all
|
||||
|
||||