diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle deleted file mode 100644 index 1af79c1..0000000 Binary files a/docs/build/doctrees/environment.pickle and /dev/null differ diff --git a/docs/build/doctrees/frontend_API.doctree b/docs/build/doctrees/frontend_API.doctree deleted file mode 100644 index 9992435..0000000 Binary files a/docs/build/doctrees/frontend_API.doctree and /dev/null differ diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree deleted file mode 100644 index 433498c..0000000 Binary files a/docs/build/doctrees/index.doctree and /dev/null differ diff --git a/docs/build/doctrees/modules.doctree b/docs/build/doctrees/modules.doctree deleted file mode 100644 index 623e506..0000000 Binary files a/docs/build/doctrees/modules.doctree and /dev/null differ diff --git a/docs/build/doctrees/pytreegrav.doctree b/docs/build/doctrees/pytreegrav.doctree deleted file mode 100644 index 0e8b2f1..0000000 Binary files a/docs/build/doctrees/pytreegrav.doctree and /dev/null differ diff --git a/docs/build/doctrees/setup.doctree b/docs/build/doctrees/setup.doctree deleted file mode 100644 index 6f014b8..0000000 Binary files a/docs/build/doctrees/setup.doctree and /dev/null differ diff --git a/docs/build/doctrees/usage/installation.doctree b/docs/build/doctrees/usage/installation.doctree deleted file mode 100644 index 9fe0ba8..0000000 Binary files a/docs/build/doctrees/usage/installation.doctree and /dev/null differ diff --git a/docs/build/doctrees/usage/quickstart.doctree b/docs/build/doctrees/usage/quickstart.doctree deleted file mode 100644 index 1332cdd..0000000 Binary files a/docs/build/doctrees/usage/quickstart.doctree and /dev/null differ diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo deleted file mode 100644 index 3f06d14..0000000 --- a/docs/build/html/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: be6e11db1cd9fb46ff18e596837810f8 -tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/Nbody_simulation.html b/docs/build/html/Nbody_simulation.html deleted file mode 100644 index 5f6ad17..0000000 --- a/docs/build/html/Nbody_simulation.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - Example: N-body simulation — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Example: N-body simulation

-

Here we provide a simple example of an N-body integrator implemented -using force and potential evaluation routines from pytreegrav. If you -were writing a more serious simulation code you would want to adopt a -more modular, object-oriented approach, but this suffices to demonstrate -the use of pytreegrav.

-
-

Initial Conditions

-

We first make a function to initialize some particles in a Gaussian -blob. You can try modifying the IC generator and playing around with the -initial velocity and geometry for extra fun. We also write a function to -evaluate the total energy, which is conserved down to tree-force and -integration errors.

-
%pylab
-from pytreegrav import Accel, Potential
-
-def GenerateICs(N,seed=42):
-    np.random.seed(seed) # seed the RNG for reproducibility
-    pos = np.random.normal(size=(N,3)) # positions of particles
-    pos -= np.average(pos,axis=0) # put center of mass at the origin
-    vel = np.zeros_like(pos) # initialize at rest
-    vel -= np.average(vel,axis=0) # make average velocity 0
-    softening = np.repeat(0.1,N) # initialize softening to 0.1
-    masses = np.repeat(1./N,N) # make the system have unit mass
-    return pos, masses, vel, softening
-
-def TotalEnergy(pos, masses, vel, softening):
-    kinetic = 0.5 * np.sum(masses[:,None] * vel**2)
-    potential = 0.5 * np.sum(masses * Potential(pos,masses,softening,parallel=True))
-    return kinetic + potential
-
-
-
Using matplotlib backend: MacOSX
-Populating the interactive namespace from numpy and matplotlib
-
-
-
-
-

Stepper function

-

Now let’s define the basic timestep for a leapfrog integrator, put in -the Hamiltonian split kick-drift-kick form (e.g. Springel 2005).

-
def leapfrog_kdk_timestep(dt, pos, masses, softening, vel, accel):
-    # first a half-step kick
-    vel[:] = vel + 0.5 * dt * accel # note that you must slice arrays to modify them in place in the function!
-    # then full-step drift
-    pos[:] = pos + dt * vel
-    # then recompute accelerations
-    accel[:] = Accel(pos,masses,softening,parallel=True)
-    # then another half-step kick
-    vel[:] = vel + 0.5 * dt * accel
-
-
-
-
-

Main simulation loop

-
pos, masses, vel, softening = GenerateICs(10000) # initialize initial condition with 10k particles
-
-accel = Accel(pos,masses,softening,parallel=True) # initialize acceleration
-
-t = 0 # initial time
-Tmax = 50 # final/max time
-
-energies = [] #energies
-r50s = [] #half-mass radii
-ts = [] # times
-
-
-while t <= Tmax: # actual simulation loop - this may take a couple minutes to run
-    r50s.append(np.median(np.sum((pos - np.median(pos,axis=0))**2,axis=1)**0.5))
-    energies.append(TotalEnergy(pos,masses,vel,softening))
-    ts.append(t)
-
-    dt = 0.03 # adjust this to control integration error
-
-    leapfrog_kdk_timestep(dt, pos, masses, softening, vel, accel)
-    t += dt
-
-print("Simulation complete! Relative energy error: %g"%(np.abs((energies[0]-energies[-1])/energies[0])))
-
-
-
Simulation complete! Relative energy error: 0.00161328
-
-
-
-
-

Analysis

-

Now we can plot the half-mass radius (to get an idea of how the system -pulsates over time) and the total energy (to check for accuracy) as a -function of time

-
%matplotlib inline
-plt.figure(figsize=(4,4),dpi=300)
-plt.plot(ts,energies,label="Total Energy")
-plt.plot(ts,r50s,label="Half-mass Radius")
-plt.xlabel("Time")
-plt.legend()
-
-
-
<matplotlib.legend.Legend at 0x7fa6d7753820>
-
-
-_images/Nbody_simulation_9_1.png -
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/_images/CPU_Time_serial.png b/docs/build/html/_images/CPU_Time_serial.png deleted file mode 100644 index ab84a5b..0000000 Binary files a/docs/build/html/_images/CPU_Time_serial.png and /dev/null differ diff --git a/docs/build/html/_sources/frontend_API.rst.txt b/docs/build/html/_sources/frontend_API.rst.txt deleted file mode 100644 index f270334..0000000 --- a/docs/build/html/_sources/frontend_API.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -API Documentation -================= - -.. automodule:: pytreegrav.frontend - :noindex: - :members: diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt deleted file mode 100644 index 38e2fe6..0000000 --- a/docs/build/html/_sources/index.rst.txt +++ /dev/null @@ -1,25 +0,0 @@ -.. pytreegrav documentation master file, created by - sphinx-quickstart on Mon Nov 22 10:52:56 2021. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to pytreegrav's documentation! -====================================== -pytreegrav is a package for computing the gravitational potential and/or field of a set of particles. It includes methods for brute-force direction summation and for the fast, approximate Barnes-Hut treecode method. For the Barnes-Hut method we implement an oct-tree as a numba jitclass to achieve much higher peformance than the equivalent pure Python implementation, without writing a single line of C or Cython. - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - usage/installation - usage/quickstart - Nbody_simulation - frontend_API - community - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/build/html/_sources/modules.rst.txt b/docs/build/html/_sources/modules.rst.txt deleted file mode 100644 index 487cdb5..0000000 --- a/docs/build/html/_sources/modules.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -src -=== - -.. toctree:: - :maxdepth: 4 - - pytreegrav diff --git a/docs/build/html/_sources/pytreegrav.rst.txt b/docs/build/html/_sources/pytreegrav.rst.txt deleted file mode 100644 index 1cc98c2..0000000 --- a/docs/build/html/_sources/pytreegrav.rst.txt +++ /dev/null @@ -1,61 +0,0 @@ -pytreegrav package -================== - -Submodules ----------- - -pytreegrav.bruteforce module ----------------------------- - -.. automodule:: pytreegrav.bruteforce - :members: - :undoc-members: - :show-inheritance: - -pytreegrav.dynamic\_tree module -------------------------------- - -.. automodule:: pytreegrav.dynamic_tree - :members: - :undoc-members: - :show-inheritance: - -pytreegrav.frontend module --------------------------- - -.. automodule:: pytreegrav.frontend - :members: - :undoc-members: - :show-inheritance: - -pytreegrav.kernel module ------------------------- - -.. automodule:: pytreegrav.kernel - :members: - :undoc-members: - :show-inheritance: - -pytreegrav.octree module ------------------------- - -.. automodule:: pytreegrav.octree - :members: - :undoc-members: - :show-inheritance: - -pytreegrav.treewalk module --------------------------- - -.. automodule:: pytreegrav.treewalk - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: pytreegrav - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/setup.rst.txt b/docs/build/html/_sources/setup.rst.txt deleted file mode 100644 index 552eb49..0000000 --- a/docs/build/html/_sources/setup.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -setup module -============ - -.. automodule:: setup - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/usage/installation.rst.txt b/docs/build/html/_sources/usage/installation.rst.txt deleted file mode 100644 index ede64ce..0000000 --- a/docs/build/html/_sources/usage/installation.rst.txt +++ /dev/null @@ -1,81 +0,0 @@ -.. _install: - -Installation -============ - -The below will help you quickly install pytreegrav. - -Requirements ------------- - -You will need a working Python 3.x installation; we recommend installing `Anaconda `_ Python version 3.x. -You will also need to install the following packages: - - * numpy - - * numba - -Installing the latest stable release ------------------------------------- - -Install the latest stable release with - -.. code-block:: bash - - pip install pytreegrav - -This is the preferred way to install pytreegrav as it will -automatically install the necessary requirements and put Pytreegrav -into your :code:`${PYTHONPATH}` environment variable so you can -import it. - -Install from source -------------------- - -Alternatively, you can install the latest version directly from the most up-to-date version -of the source-code by cloning/forking the GitHub repository - -.. code-block:: bash - - git clone https://github.com/mikegrudic/pytreegrav.git - - -Once you have the source, you can build pytreegrav (and add it to your environment) -by executing - -.. code-block:: bash - - python setup.py install - -or - -.. code-block:: bash - - pip install -e . - -in the top level directory. The required Python packages will automatically be -installed as well. - -You can test your installation by looking for the pytreegrav -executable built by the installation - -.. code-block:: bash - - which pytreegrav - -and by importing the pytreegrav Python frontend in Python - -.. code-block:: python - - import pytreegrav - -Testing -------- - -To test that the tree solver is working correctly, run - -.. code-block:: bash - - pytest - -from the root directory of the package. This will run a basic test problem comparing the acceleration and potential from the tree and brute force solvers respectively, and check that the answers are within the expected tolerance. diff --git a/docs/build/html/_sources/usage/quickstart.rst.txt b/docs/build/html/_sources/usage/quickstart.rst.txt deleted file mode 100644 index 6c6a112..0000000 --- a/docs/build/html/_sources/usage/quickstart.rst.txt +++ /dev/null @@ -1,170 +0,0 @@ - -Quickstart -========== - -pytreegrav is a package for computing the gravitational potential and/or field of a set of particles. It includes methods for brute-force direction summation and for the fast, approximate Barnes-Hut treecode method. For the Barnes-Hut method we implement an oct-tree as a numba jitclass to achieve much higher peformance than the equivalent pure Python implementation. - -First let's import the stuff we want and generate some particle positions and masses - these would be your particle data for whatever your problem is. - -.. code-block:: python - - import numpy as np - from pytreegrav import Accel, Potential - -.. code-block:: python - - N = 10**5 # number of particles - x = np.random.rand(N,3) # positions randomly sampled in the unit cube - m = np.repeat(1./N,N) # masses - let the system have unit mass - h = np.repeat(0.01,N) # softening radii - these are optional, assumed 0 if not provided to the frontend functions - -Now we can use the ``Accel`` and ``Potential`` functions to compute the gravitational field and potential at each particle position: - -.. code-block:: python - - print(Accel(x,m,h)) - print(Potential(x,m,h)) - -.. code-block:: - - [[-0.1521787 0.2958852 -0.30109005] - [-0.50678204 -0.37489886 -1.0558666 ] - [-0.24650087 0.95423467 -0.175074 ] - ... - [ 0.87868472 -1.28332176 -0.22718531] - [-0.41962742 0.32372245 -1.31829084] - [ 2.45127054 0.38292881 0.05820412]] - [-2.35518057 -2.19299372 -2.28494218 ... -2.11783337 -2.1653377 - -1.80464695] - - - -By default, pytreegrav will try to make the optimal choice between brute-force and tree methods for speed, but we can also force it to use one method or another. Let's try both and compare their runtimes: - -.. code-block:: python - - from time import time - t = time() - # tree gravitational acceleration - accel_tree = Accel(x,m,h,method='tree') - print("Tree accel runtime: %gs"%(time() - t)); t = time() - - accel_bruteforce = Accel(x,m,h,method='bruteforce') - print("Brute force accel runtime: %gs"%(time() - t)); t = time() - - phi_tree = Potential(x,m,h,method='tree') - print("Tree potential runtime: %gs"%(time() - t)); t = time() - - phi_bruteforce = Potential(x,m,h,method='bruteforce') - print("Brute force potential runtime: %gs"%(time() - t)); t = time() - -.. code-block:: - - Tree accel runtime: 0.927745s - Brute force accel runtime: 44.1175s - Tree potential runtime: 0.802386s - Brute force potential runtime: 20.0234s - - - -As you can see, the tree-based methods can be much faster than the brute-force methods, especially for particle counts exceeding 10^4. Here's an example of how much faster the treecode is when run on a Plummer sphere with a variable number of particles, on a single core of an Intel i9 9900k workstation: - -.. image:: ./CPU_Time_serial.png - :target: ./CPU_Time_serial.png - :alt: Benchmark - - -But there's no free lunch here: the tree methods are approximate. Let's quantify the RMS errors of the stuff we just computed, compared to the exact brute-force solutions: - -.. code-block:: python - - acc_error = np.sqrt(np.mean(np.sum((accel_tree-accel_bruteforce)**2,axis=1))) # RMS force error - print("RMS force error: ", acc_error) - phi_error = np.std(phi_tree - phi_bruteforce) - print("RMS potential error: ", phi_error) - -.. code-block:: - - RMS force error: 0.006739311224338851 - RMS potential error: 0.0003888328578588027 - - - -The above errors are typical for default settings: ~1% force error and ~0.1\% potential error. The error in the tree approximation is controlled by the Barnes-Hut opening angle ``theta``\ , set to 0.7 by default. Smaller ``theta`` gives higher accuracy, but also runs slower: - -.. code-block:: python - - thetas = 0.1,0.2,0.4,0.8 # different thetas to try - for theta in thetas: - t = time() - accel_tree = Accel(x,m,h,method='tree',theta=theta) - acc_error = np.sqrt(np.mean(np.sum((accel_tree-accel_bruteforce)**2,axis=1))) - print("theta=%g Runtime: %gs RMS force error: %g"%(theta, time()-t, acc_error)) - -.. code-block:: - - theta=0.1 Runtime: 63.1738s RMS force error: 3.78978e-05 - theta=0.2 Runtime: 14.3356s RMS force error: 0.000258755 - theta=0.4 Runtime: 2.91292s RMS force error: 0.00148698 - theta=0.8 Runtime: 0.724668s RMS force error: 0.0105937 - - - -Both brute-force and tree-based calculations can be parallelized across all available logical cores via OpenMP, by specifying ``parallel=True``. This can speed things up considerably, with parallel scaling that will vary with your core and particle number: - -.. code-block:: python - - from time import time - t = time() - # tree gravitational acceleration - accel_tree = Accel(x,m,h,method='tree',parallel=True) - print("Tree accel runtime in parallel: %gs"%(time() - t)); t = time() - - accel_bruteforce = Accel(x,m,h,method='bruteforce',parallel=True) - print("Brute force accel runtime in parallel: %gs"%(time() - t)); t = time() - - phi_tree = Potential(x,m,h,method='tree',parallel=True) - print("Tree potential runtime in parallel: %gs"%(time() - t)); t = time() - - phi_bruteforce = Potential(x,m,h,method='bruteforce',parallel=True) - print("Brute force potential runtime in parallel: %gs"%(time() - t)); t = time() - -.. code-block:: - - Tree accel runtime in parallel: 0.222271s - Brute force accel runtime in parallel: 7.25576s - Tree potential runtime in parallel: 0.181393s - Brute force potential runtime in parallel: 5.72611s - - - -What if I want to evaluate the fields at different points than where the particles are? ---------------------------------------------------------------------------------------- - -We got you covered. The ``Target`` methods do exactly this: you specify separate sets of points for the particle positions and the field evaluation, and everything otherwise works exactly the same (including optional parallelization and choice of solver): - -.. code-block:: python - - from pytreegrav import AccelTarget, PotentialTarget - - # generate a separate set of "target" positions where we want to know the potential and field - N_target = 10**4 - x_target = np.random.rand(N_target,3) - h_target = np.repeat(0.01,N_target) # optional "target" softening: this sets a floor on the softening length of all forces/potentials computed - - accel_tree = AccelTarget(x_target, x,m, h_target=h_target, h_source=h,method='tree') # we provide the points/masses/softenings we generated before as the "source" particles - accel_bruteforce = AccelTarget(x_target,x,m,h_source=h,method='bruteforce') - - acc_error = np.sqrt(np.mean(np.sum((accel_tree-accel_bruteforce)**2,axis=1))) # RMS force error - print("RMS force error: ", acc_error) - - phi_tree = PotentialTarget(x_target, x,m, h_target=h_target, h_source=h,method='tree') # we provide the points/masses/softenings we generated before as the "source" particles - phi_bruteforce = PotentialTarget(x_target,x,m,h_target=h_target, h_source=h,method='bruteforce') - - phi_error = np.std(phi_tree - phi_bruteforce) - print("RMS potential error: ", phi_error) - -.. code-block:: - - RMS force error: 0.006719983300560105 - RMS potential error: 0.0003873676304955059 diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css deleted file mode 100644 index 30fee9d..0000000 --- a/docs/build/html/_static/basic.css +++ /dev/null @@ -1,925 +0,0 @@ -/* - * basic.css - * ~~~~~~~~~ - * - * Sphinx stylesheet -- basic theme. - * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -div.section::after { - display: block; - content: ''; - clear: left; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; - word-wrap: break-word; - overflow-wrap : break-word; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar #searchbox form.search { - overflow: hidden; -} - -div.sphinxsidebar #searchbox input[type="text"] { - float: left; - width: 80%; - padding: 0.25em; - box-sizing: border-box; -} - -div.sphinxsidebar #searchbox input[type="submit"] { - float: left; - width: 20%; - border-left: none; - padding: 0.25em; - box-sizing: border-box; -} - - -img { - border: 0; - max-width: 100%; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li p.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; - margin-left: auto; - margin-right: auto; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable ul { - margin-top: 0; - margin-bottom: 0; - list-style-type: none; -} - -table.indextable > tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body { - min-width: 360px; - max-width: 800px; -} - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -a:visited { - color: #551A8B; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, figure.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, figure.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, figure.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -img.align-default, figure.align-default, .figure.align-default { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-default { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar, -aside.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px; - background-color: #ffe; - width: 40%; - float: right; - clear: right; - overflow-x: auto; -} - -p.sidebar-title { - font-weight: bold; -} - -nav.contents, -aside.topic, -div.admonition, div.topic, blockquote { - clear: left; -} - -/* -- topics ---------------------------------------------------------------- */ - -nav.contents, -aside.topic, -div.topic { - border: 1px solid #ccc; - padding: 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- content of sidebars/topics/admonitions -------------------------------- */ - -div.sidebar > :last-child, -aside.sidebar > :last-child, -nav.contents > :last-child, -aside.topic > :last-child, -div.topic > :last-child, -div.admonition > :last-child { - margin-bottom: 0; -} - -div.sidebar::after, -aside.sidebar::after, -nav.contents::after, -aside.topic::after, -div.topic::after, -div.admonition::after, -blockquote::after { - display: block; - content: ''; - clear: both; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - margin-top: 10px; - margin-bottom: 10px; - border: 0; - border-collapse: collapse; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -table.align-default { - margin-left: auto; - margin-right: auto; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -th > :first-child, -td > :first-child { - margin-top: 0px; -} - -th > :last-child, -td > :last-child { - margin-bottom: 0px; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure, figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption, figcaption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number, -figcaption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text, -figcaption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -/* -- hlist styles ---------------------------------------------------------- */ - -table.hlist { - margin: 1em 0; -} - -table.hlist td { - vertical-align: top; -} - -/* -- object description styles --------------------------------------------- */ - -.sig { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; -} - -.sig-name, code.descname { - background-color: transparent; - font-weight: bold; -} - -.sig-name { - font-size: 1.1em; -} - -code.descname { - font-size: 1.2em; -} - -.sig-prename, code.descclassname { - background-color: transparent; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.sig-param.n { - font-style: italic; -} - -/* C++ specific styling */ - -.sig-inline.c-texpr, -.sig-inline.cpp-texpr { - font-family: unset; -} - -.sig.c .k, .sig.c .kt, -.sig.cpp .k, .sig.cpp .kt { - color: #0033B3; -} - -.sig.c .m, -.sig.cpp .m { - color: #1750EB; -} - -.sig.c .s, .sig.c .sc, -.sig.cpp .s, .sig.cpp .sc { - color: #067D17; -} - - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -:not(li) > ol > li:first-child > :first-child, -:not(li) > ul > li:first-child > :first-child { - margin-top: 0px; -} - -:not(li) > ol > li:last-child > :last-child, -:not(li) > ul > li:last-child > :last-child { - margin-bottom: 0px; -} - -ol.simple ol p, -ol.simple ul p, -ul.simple ol p, -ul.simple ul p { - margin-top: 0; -} - -ol.simple > li:not(:first-child) > p, -ul.simple > li:not(:first-child) > p { - margin-top: 0; -} - -ol.simple p, -ul.simple p { - margin-bottom: 0; -} - -aside.footnote > span, -div.citation > span { - float: left; -} -aside.footnote > span:last-of-type, -div.citation > span:last-of-type { - padding-right: 0.5em; -} -aside.footnote > p { - margin-left: 2em; -} -div.citation > p { - margin-left: 4em; -} -aside.footnote > p:last-of-type, -div.citation > p:last-of-type { - margin-bottom: 0em; -} -aside.footnote > p:last-of-type:after, -div.citation > p:last-of-type:after { - content: ""; - clear: both; -} - -dl.field-list { - display: grid; - grid-template-columns: fit-content(30%) auto; -} - -dl.field-list > dt { - font-weight: bold; - word-break: break-word; - padding-left: 0.5em; - padding-right: 5px; -} - -dl.field-list > dd { - padding-left: 0.5em; - margin-top: 0em; - margin-left: 0em; - margin-bottom: 0em; -} - -dl { - margin-bottom: 15px; -} - -dd > :first-child { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -.sig dd { - margin-top: 0px; - margin-bottom: 0px; -} - -.sig dl { - margin-top: 0px; - margin-bottom: 0px; -} - -dl > dd:last-child, -dl > dd:last-child > :last-child { - margin-bottom: 0; -} - -dt:target, span.highlighted { - background-color: #fbe54e; -} - -rect.highlighted { - fill: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -.classifier:before { - font-style: normal; - margin: 0 0.5em; - content: ":"; - display: inline-block; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -.translated { - background-color: rgba(207, 255, 207, 0.2) -} - -.untranslated { - background-color: rgba(255, 207, 207, 0.2) -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -pre, div[class*="highlight-"] { - clear: both; -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; - white-space: nowrap; -} - -div[class*="highlight-"] { - margin: 1em 0; -} - -td.linenos pre { - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - display: block; -} - -table.highlighttable tbody { - display: block; -} - -table.highlighttable tr { - display: flex; -} - -table.highlighttable td { - margin: 0; - padding: 0; -} - -table.highlighttable td.linenos { - padding-right: 0.5em; -} - -table.highlighttable td.code { - flex: 1; - overflow: hidden; -} - -.highlight .hll { - display: block; -} - -div.highlight pre, -table.highlighttable pre { - margin: 0; -} - -div.code-block-caption + div { - margin-top: 0; -} - -div.code-block-caption { - margin-top: 1em; - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -table.highlighttable td.linenos, -span.linenos, -div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; - -webkit-user-select: text; /* Safari fallback only */ - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - margin: 1em 0; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: absolute; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js deleted file mode 100644 index d06a71d..0000000 --- a/docs/build/html/_static/doctools.js +++ /dev/null @@ -1,156 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Base JavaScript utilities for all Sphinx HTML documentation. - * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ -"use strict"; - -const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ - "TEXTAREA", - "INPUT", - "SELECT", - "BUTTON", -]); - -const _ready = (callback) => { - if (document.readyState !== "loading") { - callback(); - } else { - document.addEventListener("DOMContentLoaded", callback); - } -}; - -/** - * Small JavaScript module for the documentation. - */ -const Documentation = { - init: () => { - Documentation.initDomainIndexTable(); - Documentation.initOnKeyListeners(); - }, - - /** - * i18n support - */ - TRANSLATIONS: {}, - PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), - LOCALE: "unknown", - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext: (string) => { - const translated = Documentation.TRANSLATIONS[string]; - switch (typeof translated) { - case "undefined": - return string; // no translation - case "string": - return translated; // translation exists - default: - return translated[0]; // (singular, plural) translation tuple exists - } - }, - - ngettext: (singular, plural, n) => { - const translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated !== "undefined") - return translated[Documentation.PLURAL_EXPR(n)]; - return n === 1 ? singular : plural; - }, - - addTranslations: (catalog) => { - Object.assign(Documentation.TRANSLATIONS, catalog.messages); - Documentation.PLURAL_EXPR = new Function( - "n", - `return (${catalog.plural_expr})` - ); - Documentation.LOCALE = catalog.locale; - }, - - /** - * helper function to focus on search bar - */ - focusSearchBar: () => { - document.querySelectorAll("input[name=q]")[0]?.focus(); - }, - - /** - * Initialise the domain index toggle buttons - */ - initDomainIndexTable: () => { - const toggler = (el) => { - const idNumber = el.id.substr(7); - const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); - if (el.src.substr(-9) === "minus.png") { - el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; - toggledRows.forEach((el) => (el.style.display = "none")); - } else { - el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; - toggledRows.forEach((el) => (el.style.display = "")); - } - }; - - const togglerElements = document.querySelectorAll("img.toggler"); - togglerElements.forEach((el) => - el.addEventListener("click", (event) => toggler(event.currentTarget)) - ); - togglerElements.forEach((el) => (el.style.display = "")); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); - }, - - initOnKeyListeners: () => { - // only install a listener if it is really needed - if ( - !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS - ) - return; - - document.addEventListener("keydown", (event) => { - // bail for input elements - if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; - // bail with special keys - if (event.altKey || event.ctrlKey || event.metaKey) return; - - if (!event.shiftKey) { - switch (event.key) { - case "ArrowLeft": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const prevLink = document.querySelector('link[rel="prev"]'); - if (prevLink && prevLink.href) { - window.location.href = prevLink.href; - event.preventDefault(); - } - break; - case "ArrowRight": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const nextLink = document.querySelector('link[rel="next"]'); - if (nextLink && nextLink.href) { - window.location.href = nextLink.href; - event.preventDefault(); - } - break; - } - } - - // some keyboard layouts may need Shift to get / - switch (event.key) { - case "/": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.focusSearchBar(); - event.preventDefault(); - } - }); - }, -}; - -// quick alias for translations -const _ = Documentation.gettext; - -_ready(Documentation.init); diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js deleted file mode 100644 index da41795..0000000 --- a/docs/build/html/_static/documentation_options.js +++ /dev/null @@ -1,13 +0,0 @@ -const DOCUMENTATION_OPTIONS = { - VERSION: '1.2.1', - LANGUAGE: 'en', - COLLAPSE_INDEX: false, - BUILDER: 'html', - FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', - HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false, - SHOW_SEARCH_SUMMARY: true, - ENABLE_SEARCH_SHORTCUTS: true, -}; \ No newline at end of file diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png deleted file mode 100644 index a858a41..0000000 Binary files a/docs/build/html/_static/file.png and /dev/null differ diff --git a/docs/build/html/_static/jquery.js b/docs/build/html/_static/jquery.js deleted file mode 100644 index c4c6022..0000000 --- a/docs/build/html/_static/jquery.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 00 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } -} - diff --git a/docs/build/html/_static/minus.png b/docs/build/html/_static/minus.png deleted file mode 100644 index d96755f..0000000 Binary files a/docs/build/html/_static/minus.png and /dev/null differ diff --git a/docs/build/html/_static/plus.png b/docs/build/html/_static/plus.png deleted file mode 100644 index 7107cec..0000000 Binary files a/docs/build/html/_static/plus.png and /dev/null differ diff --git a/docs/build/html/_static/pygments.css b/docs/build/html/_static/pygments.css deleted file mode 100644 index 84ab303..0000000 --- a/docs/build/html/_static/pygments.css +++ /dev/null @@ -1,75 +0,0 @@ -pre { line-height: 125%; } -td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -.highlight .hll { background-color: #ffffcc } -.highlight { background: #f8f8f8; } -.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ -.highlight .err { border: 1px solid #FF0000 } /* Error */ -.highlight .k { color: #008000; font-weight: bold } /* Keyword */ -.highlight .o { color: #666666 } /* Operator */ -.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ -.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #9C6500 } /* Comment.Preproc */ -.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ -.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ -.highlight .gd { color: #A00000 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ -.highlight .gr { color: #E40000 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #008400 } /* Generic.Inserted */ -.highlight .go { color: #717171 } /* Generic.Output */ -.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #0044DD } /* Generic.Traceback */ -.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #008000 } /* Keyword.Pseudo */ -.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #B00040 } /* Keyword.Type */ -.highlight .m { color: #666666 } /* Literal.Number */ -.highlight .s { color: #BA2121 } /* Literal.String */ -.highlight .na { color: #687822 } /* Name.Attribute */ -.highlight .nb { color: #008000 } /* Name.Builtin */ -.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -.highlight .no { color: #880000 } /* Name.Constant */ -.highlight .nd { color: #AA22FF } /* Name.Decorator */ -.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #0000FF } /* Name.Function */ -.highlight .nl { color: #767600 } /* Name.Label */ -.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #19177C } /* Name.Variable */ -.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mb { color: #666666 } /* Literal.Number.Bin */ -.highlight .mf { color: #666666 } /* Literal.Number.Float */ -.highlight .mh { color: #666666 } /* Literal.Number.Hex */ -.highlight .mi { color: #666666 } /* Literal.Number.Integer */ -.highlight .mo { color: #666666 } /* Literal.Number.Oct */ -.highlight .sa { color: #BA2121 } /* Literal.String.Affix */ -.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ -.highlight .sc { color: #BA2121 } /* Literal.String.Char */ -.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ -.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ -.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ -.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ -.highlight .sx { color: #008000 } /* Literal.String.Other */ -.highlight .sr { color: #A45A77 } /* Literal.String.Regex */ -.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ -.highlight .ss { color: #19177C } /* Literal.String.Symbol */ -.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ -.highlight .fm { color: #0000FF } /* Name.Function.Magic */ -.highlight .vc { color: #19177C } /* Name.Variable.Class */ -.highlight .vg { color: #19177C } /* Name.Variable.Global */ -.highlight .vi { color: #19177C } /* Name.Variable.Instance */ -.highlight .vm { color: #19177C } /* Name.Variable.Magic */ -.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/build/html/_static/searchtools.js b/docs/build/html/_static/searchtools.js deleted file mode 100644 index 7918c3f..0000000 --- a/docs/build/html/_static/searchtools.js +++ /dev/null @@ -1,574 +0,0 @@ -/* - * searchtools.js - * ~~~~~~~~~~~~~~~~ - * - * Sphinx JavaScript utilities for the full-text search. - * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ -"use strict"; - -/** - * Simple result scoring code. - */ -if (typeof Scorer === "undefined") { - var Scorer = { - // Implement the following function to further tweak the score for each result - // The function takes a result array [docname, title, anchor, descr, score, filename] - // and returns the new score. - /* - score: result => { - const [docname, title, anchor, descr, score, filename] = result - return score - }, - */ - - // query matches the full name of an object - objNameMatch: 11, - // or matches in the last dotted part of the object name - objPartialMatch: 6, - // Additive scores depending on the priority of the object - objPrio: { - 0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5, // used to be unimportantResults - }, - // Used when the priority is not in the mapping. - objPrioDefault: 0, - - // query found in title - title: 15, - partialTitle: 7, - // query found in terms - term: 5, - partialTerm: 2, - }; -} - -const _removeChildren = (element) => { - while (element && element.lastChild) element.removeChild(element.lastChild); -}; - -/** - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping - */ -const _escapeRegExp = (string) => - string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string - -const _displayItem = (item, searchTerms, highlightTerms) => { - const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; - const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; - const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; - const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; - const contentRoot = document.documentElement.dataset.content_root; - - const [docName, title, anchor, descr, score, _filename] = item; - - let listItem = document.createElement("li"); - let requestUrl; - let linkUrl; - if (docBuilder === "dirhtml") { - // dirhtml builder - let dirname = docName + "/"; - if (dirname.match(/\/index\/$/)) - dirname = dirname.substring(0, dirname.length - 6); - else if (dirname === "index/") dirname = ""; - requestUrl = contentRoot + dirname; - linkUrl = requestUrl; - } else { - // normal html builders - requestUrl = contentRoot + docName + docFileSuffix; - linkUrl = docName + docLinkSuffix; - } - let linkEl = listItem.appendChild(document.createElement("a")); - linkEl.href = linkUrl + anchor; - linkEl.dataset.score = score; - linkEl.innerHTML = title; - if (descr) { - listItem.appendChild(document.createElement("span")).innerHTML = - " (" + descr + ")"; - // highlight search terms in the description - if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js - highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); - } - else if (showSearchSummary) - fetch(requestUrl) - .then((responseData) => responseData.text()) - .then((data) => { - if (data) - listItem.appendChild( - Search.makeSearchSummary(data, searchTerms) - ); - // highlight search terms in the summary - if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js - highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); - }); - Search.output.appendChild(listItem); -}; -const _finishSearch = (resultCount) => { - Search.stopPulse(); - Search.title.innerText = _("Search Results"); - if (!resultCount) - Search.status.innerText = Documentation.gettext( - "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." - ); - else - Search.status.innerText = _( - `Search finished, found ${resultCount} page(s) matching the search query.` - ); -}; -const _displayNextItem = ( - results, - resultCount, - searchTerms, - highlightTerms, -) => { - // results left, load the summary and display it - // this is intended to be dynamic (don't sub resultsCount) - if (results.length) { - _displayItem(results.pop(), searchTerms, highlightTerms); - setTimeout( - () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), - 5 - ); - } - // search finished, update title and status message - else _finishSearch(resultCount); -}; - -/** - * Default splitQuery function. Can be overridden in ``sphinx.search`` with a - * custom function per language. - * - * The regular expression works by splitting the string on consecutive characters - * that are not Unicode letters, numbers, underscores, or emoji characters. - * This is the same as ``\W+`` in Python, preserving the surrogate pair area. - */ -if (typeof splitQuery === "undefined") { - var splitQuery = (query) => query - .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) - .filter(term => term) // remove remaining empty strings -} - -/** - * Search Module - */ -const Search = { - _index: null, - _queued_query: null, - _pulse_status: -1, - - htmlToText: (htmlString) => { - const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); - htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); - const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent !== undefined) return docContent.textContent; - console.warn( - "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." - ); - return ""; - }, - - init: () => { - const query = new URLSearchParams(window.location.search).get("q"); - document - .querySelectorAll('input[name="q"]') - .forEach((el) => (el.value = query)); - if (query) Search.performSearch(query); - }, - - loadIndex: (url) => - (document.body.appendChild(document.createElement("script")).src = url), - - setIndex: (index) => { - Search._index = index; - if (Search._queued_query !== null) { - const query = Search._queued_query; - Search._queued_query = null; - Search.query(query); - } - }, - - hasIndex: () => Search._index !== null, - - deferQuery: (query) => (Search._queued_query = query), - - stopPulse: () => (Search._pulse_status = -1), - - startPulse: () => { - if (Search._pulse_status >= 0) return; - - const pulse = () => { - Search._pulse_status = (Search._pulse_status + 1) % 4; - Search.dots.innerText = ".".repeat(Search._pulse_status); - if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); - }; - pulse(); - }, - - /** - * perform a search for something (or wait until index is loaded) - */ - performSearch: (query) => { - // create the required interface elements - const searchText = document.createElement("h2"); - searchText.textContent = _("Searching"); - const searchSummary = document.createElement("p"); - searchSummary.classList.add("search-summary"); - searchSummary.innerText = ""; - const searchList = document.createElement("ul"); - searchList.classList.add("search"); - - const out = document.getElementById("search-results"); - Search.title = out.appendChild(searchText); - Search.dots = Search.title.appendChild(document.createElement("span")); - Search.status = out.appendChild(searchSummary); - Search.output = out.appendChild(searchList); - - const searchProgress = document.getElementById("search-progress"); - // Some themes don't use the search progress node - if (searchProgress) { - searchProgress.innerText = _("Preparing search..."); - } - Search.startPulse(); - - // index already loaded, the browser was quick! - if (Search.hasIndex()) Search.query(query); - else Search.deferQuery(query); - }, - - /** - * execute search (requires search index to be loaded) - */ - query: (query) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - - // stem the search terms and add them to the correct list - const stemmer = new Stemmer(); - const searchTerms = new Set(); - const excludedTerms = new Set(); - const highlightTerms = new Set(); - const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); - splitQuery(query.trim()).forEach((queryTerm) => { - const queryTermLower = queryTerm.toLowerCase(); - - // maybe skip this "word" - // stopwords array is from language_data.js - if ( - stopwords.indexOf(queryTermLower) !== -1 || - queryTerm.match(/^\d+$/) - ) - return; - - // stem the word - let word = stemmer.stemWord(queryTermLower); - // select the correct list - if (word[0] === "-") excludedTerms.add(word.substr(1)); - else { - searchTerms.add(word); - highlightTerms.add(queryTermLower); - } - }); - - if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js - localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) - } - - // console.debug("SEARCH: searching for:"); - // console.info("required: ", [...searchTerms]); - // console.info("excluded: ", [...excludedTerms]); - - // array of [docname, title, anchor, descr, score, filename] - let results = []; - _removeChildren(document.getElementById("search-progress")); - - const queryLower = query.toLowerCase(); - for (const [title, foundTitles] of Object.entries(allTitles)) { - if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { - for (const [file, id] of foundTitles) { - let score = Math.round(100 * queryLower.length / title.length) - results.push([ - docNames[file], - titles[file] !== title ? `${titles[file]} > ${title}` : title, - id !== null ? "#" + id : "", - null, - score, - filenames[file], - ]); - } - } - } - - // search for explicit entries in index directives - for (const [entry, foundEntries] of Object.entries(indexEntries)) { - if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { - for (const [file, id] of foundEntries) { - let score = Math.round(100 * queryLower.length / entry.length) - results.push([ - docNames[file], - titles[file], - id ? "#" + id : "", - null, - score, - filenames[file], - ]); - } - } - } - - // lookup as object - objectTerms.forEach((term) => - results.push(...Search.performObjectSearch(term, objectTerms)) - ); - - // lookup as search terms in fulltext - results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); - - // let the scorer override scores with a custom scoring function - if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); - - // now sort the results by score (in opposite order of appearance, since the - // display function below uses pop() to retrieve items) and then - // alphabetically - results.sort((a, b) => { - const leftScore = a[4]; - const rightScore = b[4]; - if (leftScore === rightScore) { - // same score: sort alphabetically - const leftTitle = a[1].toLowerCase(); - const rightTitle = b[1].toLowerCase(); - if (leftTitle === rightTitle) return 0; - return leftTitle > rightTitle ? -1 : 1; // inverted is intentional - } - return leftScore > rightScore ? 1 : -1; - }); - - // remove duplicate search results - // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept - let seen = new Set(); - results = results.reverse().reduce((acc, result) => { - let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); - if (!seen.has(resultStr)) { - acc.push(result); - seen.add(resultStr); - } - return acc; - }, []); - - results = results.reverse(); - - // for debugging - //Search.lastresults = results.slice(); // a copy - // console.info("search results:", Search.lastresults); - - // print the results - _displayNextItem(results, results.length, searchTerms, highlightTerms); - }, - - /** - * search for object names - */ - performObjectSearch: (object, objectTerms) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const objects = Search._index.objects; - const objNames = Search._index.objnames; - const titles = Search._index.titles; - - const results = []; - - const objectSearchCallback = (prefix, match) => { - const name = match[4] - const fullname = (prefix ? prefix + "." : "") + name; - const fullnameLower = fullname.toLowerCase(); - if (fullnameLower.indexOf(object) < 0) return; - - let score = 0; - const parts = fullnameLower.split("."); - - // check for different match types: exact matches of full name or - // "last name" (i.e. last dotted part) - if (fullnameLower === object || parts.slice(-1)[0] === object) - score += Scorer.objNameMatch; - else if (parts.slice(-1)[0].indexOf(object) > -1) - score += Scorer.objPartialMatch; // matches in last name - - const objName = objNames[match[1]][2]; - const title = titles[match[0]]; - - // If more than one term searched for, we require other words to be - // found in the name/title/description - const otherTerms = new Set(objectTerms); - otherTerms.delete(object); - if (otherTerms.size > 0) { - const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); - if ( - [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) - ) - return; - } - - let anchor = match[3]; - if (anchor === "") anchor = fullname; - else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; - - const descr = objName + _(", in ") + title; - - // add custom score for some objects according to scorer - if (Scorer.objPrio.hasOwnProperty(match[2])) - score += Scorer.objPrio[match[2]]; - else score += Scorer.objPrioDefault; - - results.push([ - docNames[match[0]], - fullname, - "#" + anchor, - descr, - score, - filenames[match[0]], - ]); - }; - Object.keys(objects).forEach((prefix) => - objects[prefix].forEach((array) => - objectSearchCallback(prefix, array) - ) - ); - return results; - }, - - /** - * search for full-text terms in the index - */ - performTermsSearch: (searchTerms, excludedTerms) => { - // prepare search - const terms = Search._index.terms; - const titleTerms = Search._index.titleterms; - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - - const scoreMap = new Map(); - const fileMap = new Map(); - - // perform the search on the required terms - searchTerms.forEach((word) => { - const files = []; - const arr = [ - { files: terms[word], score: Scorer.term }, - { files: titleTerms[word], score: Scorer.title }, - ]; - // add support for partial matches - if (word.length > 2) { - const escapedWord = _escapeRegExp(word); - Object.keys(terms).forEach((term) => { - if (term.match(escapedWord) && !terms[word]) - arr.push({ files: terms[term], score: Scorer.partialTerm }); - }); - Object.keys(titleTerms).forEach((term) => { - if (term.match(escapedWord) && !titleTerms[word]) - arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); - }); - } - - // no match but word was a required one - if (arr.every((record) => record.files === undefined)) return; - - // found search word in contents - arr.forEach((record) => { - if (record.files === undefined) return; - - let recordFiles = record.files; - if (recordFiles.length === undefined) recordFiles = [recordFiles]; - files.push(...recordFiles); - - // set score for the word in each file - recordFiles.forEach((file) => { - if (!scoreMap.has(file)) scoreMap.set(file, {}); - scoreMap.get(file)[word] = record.score; - }); - }); - - // create the mapping - files.forEach((file) => { - if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) - fileMap.get(file).push(word); - else fileMap.set(file, [word]); - }); - }); - - // now check if the files don't contain excluded terms - const results = []; - for (const [file, wordList] of fileMap) { - // check if all requirements are matched - - // as search terms with length < 3 are discarded - const filteredTermCount = [...searchTerms].filter( - (term) => term.length > 2 - ).length; - if ( - wordList.length !== searchTerms.size && - wordList.length !== filteredTermCount - ) - continue; - - // ensure that none of the excluded terms is in the search result - if ( - [...excludedTerms].some( - (term) => - terms[term] === file || - titleTerms[term] === file || - (terms[term] || []).includes(file) || - (titleTerms[term] || []).includes(file) - ) - ) - break; - - // select one (max) score for the file. - const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); - // add result to the result list - results.push([ - docNames[file], - titles[file], - "", - null, - score, - filenames[file], - ]); - } - return results; - }, - - /** - * helper function to return a node containing the - * search summary for a given text. keywords is a list - * of stemmed words. - */ - makeSearchSummary: (htmlText, keywords) => { - const text = Search.htmlToText(htmlText); - if (text === "") return null; - - const textLower = text.toLowerCase(); - const actualStartPosition = [...keywords] - .map((k) => textLower.indexOf(k.toLowerCase())) - .filter((i) => i > -1) - .slice(-1)[0]; - const startWithContext = Math.max(actualStartPosition - 120, 0); - - const top = startWithContext === 0 ? "" : "..."; - const tail = startWithContext + 240 < text.length ? "..." : ""; - - let summary = document.createElement("p"); - summary.classList.add("context"); - summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; - - return summary; - }, -}; - -_ready(Search.init); diff --git a/docs/build/html/_static/underscore.js b/docs/build/html/_static/underscore.js deleted file mode 100644 index cf177d4..0000000 --- a/docs/build/html/_static/underscore.js +++ /dev/null @@ -1,6 +0,0 @@ -!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define("underscore",r):(n="undefined"!=typeof globalThis?globalThis:n||self,function(){var t=n._,e=n._=r();e.noConflict=function(){return n._=t,e}}())}(this,(function(){ -// Underscore.js 1.13.1 -// https://underscorejs.org -// (c) 2009-2021 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. -var n="1.13.1",r="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||Function("return this")()||{},t=Array.prototype,e=Object.prototype,u="undefined"!=typeof Symbol?Symbol.prototype:null,o=t.push,i=t.slice,a=e.toString,f=e.hasOwnProperty,c="undefined"!=typeof ArrayBuffer,l="undefined"!=typeof DataView,s=Array.isArray,p=Object.keys,v=Object.create,h=c&&ArrayBuffer.isView,y=isNaN,d=isFinite,g=!{toString:null}.propertyIsEnumerable("toString"),b=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"],m=Math.pow(2,53)-1;function j(n,r){return r=null==r?n.length-1:+r,function(){for(var t=Math.max(arguments.length-r,0),e=Array(t),u=0;u=0&&t<=m}}function J(n){return function(r){return null==r?void 0:r[n]}}var G=J("byteLength"),H=K(G),Q=/\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/;var X=c?function(n){return h?h(n)&&!q(n):H(n)&&Q.test(a.call(n))}:C(!1),Y=J("length");function Z(n,r){r=function(n){for(var r={},t=n.length,e=0;e":">",'"':""","'":"'","`":"`"},Cn=Ln($n),Kn=Ln(_n($n)),Jn=tn.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g},Gn=/(.)^/,Hn={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},Qn=/\\|'|\r|\n|\u2028|\u2029/g;function Xn(n){return"\\"+Hn[n]}var Yn=/^\s*(\w|\$)+\s*$/;var Zn=0;function nr(n,r,t,e,u){if(!(e instanceof r))return n.apply(t,u);var o=Mn(n.prototype),i=n.apply(o,u);return _(i)?i:o}var rr=j((function(n,r){var t=rr.placeholder,e=function(){for(var u=0,o=r.length,i=Array(o),a=0;a1)ur(a,r-1,t,e),u=e.length;else for(var f=0,c=a.length;f0&&(t=r.apply(this,arguments)),n<=1&&(r=null),t}}var lr=rr(cr,2);function sr(n,r,t){r=qn(r,t);for(var e,u=nn(n),o=0,i=u.length;o0?0:u-1;o>=0&&o0?a=o>=0?o:Math.max(o+f,a):f=o>=0?Math.min(o+1,f):o+f+1;else if(t&&o&&f)return e[o=t(e,u)]===u?o:-1;if(u!=u)return(o=r(i.call(e,a,f),$))>=0?o+a:-1;for(o=n>0?a:f-1;o>=0&&o0?0:i-1;for(u||(e=r[o?o[a]:a],a+=n);a>=0&&a=3;return r(n,Fn(t,u,4),e,o)}}var Ar=wr(1),xr=wr(-1);function Sr(n,r,t){var e=[];return r=qn(r,t),jr(n,(function(n,t,u){r(n,t,u)&&e.push(n)})),e}function Or(n,r,t){r=qn(r,t);for(var e=!er(n)&&nn(n),u=(e||n).length,o=0;o=0}var Br=j((function(n,r,t){var e,u;return D(r)?u=r:(r=Nn(r),e=r.slice(0,-1),r=r[r.length-1]),_r(n,(function(n){var o=u;if(!o){if(e&&e.length&&(n=In(n,e)),null==n)return;o=n[r]}return null==o?o:o.apply(n,t)}))}));function Nr(n,r){return _r(n,Rn(r))}function Ir(n,r,t){var e,u,o=-1/0,i=-1/0;if(null==r||"number"==typeof r&&"object"!=typeof n[0]&&null!=n)for(var a=0,f=(n=er(n)?n:jn(n)).length;ao&&(o=e);else r=qn(r,t),jr(n,(function(n,t,e){((u=r(n,t,e))>i||u===-1/0&&o===-1/0)&&(o=n,i=u)}));return o}function Tr(n,r,t){if(null==r||t)return er(n)||(n=jn(n)),n[Wn(n.length-1)];var e=er(n)?En(n):jn(n),u=Y(e);r=Math.max(Math.min(r,u),0);for(var o=u-1,i=0;i1&&(e=Fn(e,r[1])),r=an(n)):(e=qr,r=ur(r,!1,!1),n=Object(n));for(var u=0,o=r.length;u1&&(t=r[1])):(r=_r(ur(r,!1,!1),String),e=function(n,t){return!Er(r,t)}),Ur(n,e,t)}));function zr(n,r,t){return i.call(n,0,Math.max(0,n.length-(null==r||t?1:r)))}function Lr(n,r,t){return null==n||n.length<1?null==r||t?void 0:[]:null==r||t?n[0]:zr(n,n.length-r)}function $r(n,r,t){return i.call(n,null==r||t?1:r)}var Cr=j((function(n,r){return r=ur(r,!0,!0),Sr(n,(function(n){return!Er(r,n)}))})),Kr=j((function(n,r){return Cr(n,r)}));function Jr(n,r,t,e){A(r)||(e=t,t=r,r=!1),null!=t&&(t=qn(t,e));for(var u=[],o=[],i=0,a=Y(n);ir?(e&&(clearTimeout(e),e=null),a=c,i=n.apply(u,o),e||(u=o=null)):e||!1===t.trailing||(e=setTimeout(f,l)),i};return c.cancel=function(){clearTimeout(e),a=0,e=u=o=null},c},debounce:function(n,r,t){var e,u,o,i,a,f=function(){var c=zn()-u;r>c?e=setTimeout(f,r-c):(e=null,t||(i=n.apply(a,o)),e||(o=a=null))},c=j((function(c){return a=this,o=c,u=zn(),e||(e=setTimeout(f,r),t&&(i=n.apply(a,o))),i}));return c.cancel=function(){clearTimeout(e),e=o=a=null},c},wrap:function(n,r){return rr(r,n)},negate:fr,compose:function(){var n=arguments,r=n.length-1;return function(){for(var t=r,e=n[r].apply(this,arguments);t--;)e=n[t].call(this,e);return e}},after:function(n,r){return function(){if(--n<1)return r.apply(this,arguments)}},before:cr,once:lr,findKey:sr,findIndex:vr,findLastIndex:hr,sortedIndex:yr,indexOf:gr,lastIndexOf:br,find:mr,detect:mr,findWhere:function(n,r){return mr(n,Dn(r))},each:jr,forEach:jr,map:_r,collect:_r,reduce:Ar,foldl:Ar,inject:Ar,reduceRight:xr,foldr:xr,filter:Sr,select:Sr,reject:function(n,r,t){return Sr(n,fr(qn(r)),t)},every:Or,all:Or,some:Mr,any:Mr,contains:Er,includes:Er,include:Er,invoke:Br,pluck:Nr,where:function(n,r){return Sr(n,Dn(r))},max:Ir,min:function(n,r,t){var e,u,o=1/0,i=1/0;if(null==r||"number"==typeof r&&"object"!=typeof n[0]&&null!=n)for(var a=0,f=(n=er(n)?n:jn(n)).length;ae||void 0===t)return 1;if(t - - - - - - Feedback, Support, and Contributions — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Feedback, Support, and Contributions

-

To contribute to pytreegrav, report an issue, or seek support, please initiate a pull request or issue through the project project github

-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/frontend_API.html b/docs/build/html/frontend_API.html deleted file mode 100644 index 1588505..0000000 --- a/docs/build/html/frontend_API.html +++ /dev/null @@ -1,388 +0,0 @@ - - - - - - - API Documentation — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

API Documentation

-
-
-pytreegrav.frontend.Accel(pos, m, softening=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational acceleration calculation

-

Returns the gravitational acceleration for a set of particles with positions x and masses m, at the positions of those particles, using either brute force or tree-based methods depending on the number of particles.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • softening (None or array_like, optional) – shape (N,) array containing kernel support radii for gravitational softening - these give the radius of compact support of the M4 cubic spline mass distribution - set to 0 by default

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

g – shape (N,3) array of acceleration vectors at the particle positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.AccelTarget(pos_target, pos_source, m_source, softening_target=None, softening_source=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational acceleration calculation for general N+M body case

-

Returns the gravitational acceleration for a set of M particles with positions x_source and masses m_source, at the positions of a set of N particles that need not be the same.

-
-
Parameters:
-
    -
  • pos_target (array_like) – shape (N,3) array of target particle positions where you want to know the acceleration

  • -
  • pos_source (array_like) – shape (M,3) array of source particle positions (positions of particles sourcing the gravitational field)

  • -
  • m_source (array_like) – shape (M,) array of source particle masses

  • -
  • softening_target (array_like or None, optional) – shape (N,) array of target particle softening radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • softening_source (array_like or None, optional) – shape (M,) array of source particle radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

phi – shape (N,3) array of accelerations at the target positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.ColumnDensity(pos, m, radii, rays=None, randomize_rays=False, healpix=False, tree=None, theta=0.5, return_tree=False, parallel=False)
-

Ray-traced or angle-binned column density calculation.

-

Returns an estimate of the column density from the position of each particle -integrated to infinity, assuming the particles are represented by uniform spheres. Note -that optical depth can be obtained by supplying “sigma = opacity * mass” in -place of mass, useful in situations where opacity is highly variable.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • radii (array_like) – shape (N,) array containing particle radii of the uniform spheres that -we use to model the particles’ mass distribution

  • -
  • rays (optional) – Which ray directions to raytrace the columns. -None: use the angular-binned column density method with 6 bins on the sky -OPTION 2: Integer number: use this many rays, with 6 using the standard -6-ray grid and other numbers sampling random directions -OPTION 3: Give a (N_rays,3) array of vectors specifying the -directions, which will be automatically normalized.

  • -
  • healpix (int, optional) – Use healpix ray grid with specified resolution level NSIDE

  • -
  • randomize_rays (bool, optional) – Randomize the orientation of the ray-grid for each particle

  • -
  • parallel (bool, optional) – If True, will parallelize the column density over all available cores. -(default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, -not necessarily the target particles at pos (default None)

  • -
  • theta (float, optional) – Opening angle for beam-traced angular bin estimator

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
-
-
Returns:
-

columns – shape (N,N_rays) float array of column densities from particle -centers integrated along the rays

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.ConstructTree(pos, m=None, softening=None, quadrupole=False, vel=None, compute_moments=True, morton_order=True)
-

Builds a tree containing particle data, for subsequent potential/field evaluation

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like or None, optional) – shape (N,) array of particle masses - if None then zeros will be used (e.g. if all you need the tree for is spatial algorithms)

  • -
  • softening (array_like or None, optional) – shape (N,) array of particle softening lengths - these give the radius of compact support of the M4 cubic spline mass distribution of each particle

  • -
  • quadrupole (bool, optional) – Whether to store quadrupole moments (default False)

  • -
  • vel (bool, optional) – Whether to store node velocities in the tree (default False)

  • -
-
-
Returns:
-

tree – Octree instance built from particle data

-
-
Return type:
-

octree

-
-
-
- -
-
-pytreegrav.frontend.DensityCorrFunc(pos, m, rbins=None, max_bin_size_ratio=100, theta=1.0, tree=None, return_tree=False, parallel=False, boxsize=0, weighted_binning=False)
-

Computes the average amount of mass in radial bin [r,r+dr] around a point, provided a set of radial bins.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • rbins (array_like or None, optional) – 1D array of radial bin edges - if None will use heuristics to determine sensible bins. Otherwise MUST BE LOGARITHMICALLY SPACED (default None)

  • -
  • max_bin_size_ratio (float, optional) – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 100)

  • -
  • theta (float, optional) – cell opening angle used to control accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 1.0)

  • -
  • parallel (bool, optional) – If True, will parallelize the correlation function computation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – if True will return the generated or used tree for future use (default False)

  • -
  • boxsize (float, optional) – finite periodic box size, if periodic boundary conditions are to be used (default 0)

  • -
  • weighted_binning (bool, optional) – (experimental) if True will distribute mass among radial bings with a weighted kernel (default False)

  • -
-
-
Returns:
-

    -
  • rbins (array_like) – array containing radial bin edges

  • -
  • mbins (array_like) – array containing mean mass in radial bins, averaged over all points

  • -
-

-
-
-
- -
-
-pytreegrav.frontend.Potential(pos, m, softening=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational potential calculation

-

Returns the gravitational potential for a set of particles with positions x and masses m, at the positions of those particles, using either brute force or tree-based methods depending on the number of particles.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • softening (None or array_like, optional) – shape (N,) array containing kernel support radii for gravitational softening - - these give the radius of compact support of the M4 cubic spline mass distribution - set to 0 by default

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

phi – shape (N,) array of potentials at the particle positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.PotentialTarget(pos_target, pos_source, m_source, softening_target=None, softening_source=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational potential calculation for general N+M body case

-

Returns the gravitational potential for a set of M particles with positions x_source and masses m_source, at the positions of a set of N particles that need not be the same.

-
-
Parameters:
-
    -
  • pos_target (array_like) – shape (N,3) array of target particle positions where you want to know the potential

  • -
  • pos_source (array_like) – shape (M,3) array of source particle positions (positions of particles sourcing the gravitational field)

  • -
  • m_source (array_like) – shape (M,) array of source particle masses

  • -
  • softening_target (array_like or None, optional) – shape (N,) array of target particle softening radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • softening_source (array_like or None, optional) – shape (M,) array of source particle radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

phi – shape (N,) array of potentials at the target positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.VelocityCorrFunc(pos, m, v, rbins=None, max_bin_size_ratio=100, theta=1.0, tree=None, return_tree=False, parallel=False, boxsize=0, weighted_binning=False)
-

Computes the weighted average product v(x).v(x+r), for a vector field v, in radial bins

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • v (array_like) – shape (N,3) of vector quantity (e.g. velocity, magnetic field, etc)

  • -
  • rbins (array_like or None, optional) – 1D array of radial bin edges - if None will use heuristics to determine sensible bins. Otherwise MUST BE LOGARITHMICALLY SPACED (default None)

  • -
  • max_bin_size_ratio (float, optional) – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 100)

  • -
  • theta (float, optional) – cell opening angle used to control accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 1.0)

  • -
  • parallel (bool, optional) – If True, will parallelize the correlation function computation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – if True will return the generated or used tree for future use (default False)

  • -
  • boxsize (float, optional) – finite periodic box size, if periodic boundary conditions are to be used (default 0)

  • -
  • weighted_binning (bool, optional) – (experimental) if True will distribute mass among radial bings with a weighted kernel (default False)

  • -
-
-
Returns:
-

    -
  • rbins (array_like) – array containing radial bin edges

  • -
  • corr (array_like) – array containing correlation function values in radial bins

  • -
-

-
-
-
- -
-
-pytreegrav.frontend.VelocityStructFunc(pos, m, v, rbins=None, max_bin_size_ratio=100, theta=1.0, tree=None, return_tree=False, parallel=False, boxsize=0, weighted_binning=False)
-

Computes the structure function for a vector field: the average value of |v(x)-v(x+r)|^2, in radial bins for r

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • v (array_like) – shape (N,3) of vector quantity (e.g. velocity, magnetic field, etc)

  • -
  • rbins (array_like or None, optional) – 1D array of radial bin edges - if None will use heuristics to determine sensible bins. Otherwise MUST BE LOGARITHMICALLY SPACED (default None)

  • -
  • max_bin_size_ratio (float, optional) – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 100)

  • -
  • theta (float, optional) – cell opening angle used to control accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 1.0)

  • -
  • parallel (bool, optional) – If True, will parallelize the correlation function computation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – if True will return the generated or used tree for future use (default False)

  • -
  • boxsize (float, optional) – finite periodic box size, if periodic boundary conditions are to be used (default 0)

  • -
  • weighted_binning (bool, optional) – (experimental) if True will distribute mass among radial bings with a weighted kernel (default False)

  • -
-
-
Returns:
-

    -
  • rbins (array_like) – array containing radial bin edges

  • -
  • Sv (array_like) – array containing structure function values

  • -
-

-
-
-
- -
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html deleted file mode 100644 index 1d9fb91..0000000 --- a/docs/build/html/genindex.html +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - Index — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - -

Index

- -
- A - | C - | D - | F - | I - | M - | N - | O - | P - | S - | V - -
-

A

- - - -
- -

C

- - - -
- -

D

- - - -
- -

F

- - -
- -

I

- - -
- -

M

- - -
- -

N

- - -
- -

O

- - -
- -

P

- - - -
    -
  • - pytreegrav.bruteforce - -
  • -
  • - pytreegrav.dynamic_tree - -
  • -
  • - pytreegrav.frontend - -
  • -
  • - pytreegrav.kernel - -
  • -
  • - pytreegrav.octree - -
  • -
  • - pytreegrav.treewalk - -
  • -
- -

S

- - -
- -

V

- - - -
- - - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/index.html b/docs/build/html/index.html deleted file mode 100644 index 4debdbd..0000000 --- a/docs/build/html/index.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - Welcome to pytreegrav’s documentation! — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Welcome to pytreegrav’s documentation!

-

pytreegrav is a package for computing the gravitational potential and/or field of a set of particles. It includes methods for brute-force direction summation and for the fast, approximate Barnes-Hut treecode method. For the Barnes-Hut method we implement an oct-tree as a numba jitclass to achieve much higher peformance than the equivalent pure Python implementation, without writing a single line of C or Cython.

- -
-
-

Indices and tables

- -
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/modules.html b/docs/build/html/modules.html deleted file mode 100644 index 7a870b4..0000000 --- a/docs/build/html/modules.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - src — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

src

-
- -
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv deleted file mode 100644 index 32d26ff..0000000 Binary files a/docs/build/html/objects.inv and /dev/null differ diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html deleted file mode 100644 index eb58233..0000000 --- a/docs/build/html/py-modindex.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - Python Module Index — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - -

Python Module Index

- -
- p -
- - - - - - - - - - - - - - - - - - - - - - - - - -
 
- p
- pytreegrav -
    - pytreegrav.bruteforce -
    - pytreegrav.dynamic_tree -
    - pytreegrav.frontend -
    - pytreegrav.kernel -
    - pytreegrav.octree -
    - pytreegrav.treewalk -
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/pytreegrav.html b/docs/build/html/pytreegrav.html deleted file mode 100644 index 385484c..0000000 --- a/docs/build/html/pytreegrav.html +++ /dev/null @@ -1,937 +0,0 @@ - - - - - - - pytreegrav package — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

pytreegrav package

-
-

Submodules

-
-
-

pytreegrav.bruteforce module

-
-
-pytreegrav.bruteforce.AccelTarget_bruteforce(x_target, softening_target, x_source, m_source, softening_source, G=1.0)
-

Returns the gravitational acceleration at a set of target positions, due to a set of source particles.

-

Arguments: -x_target – shape (N,3) array of positions where the field is to be evaluated -softening_target – shape (N,) array of minimum softening lengths to be used -x_source – shape (M,3) array of positions of gravitating particles -m_source – shape (M,) array of particle masses -softening_source – shape (M,) array of softening lengths

-

Optional arguments: -G – gravitational constant (default 1.0)

-

Returns: -shape (N,3) array of gravitational accelerations

-
- -
-
-pytreegrav.bruteforce.AccelTarget_bruteforce_parallel(x_target, softening_target, x_source, m_source, softening_source, G=1.0)
-

Returns the gravitational acceleration at a set of target positions, due to a set of source particles.

-

Arguments: -x_target – shape (N,3) array of positions where the field is to be evaluated -softening_target – shape (N,) array of minimum softening lengths to be used -x_source – shape (M,3) array of positions of gravitating particles -m_source – shape (M,) array of particle masses -softening_source – shape (M,) array of softening lengths

-

Optional arguments: -G – gravitational constant (default 1.0)

-

Returns: -shape (N,3) array of gravitational accelerations

-
- -
-
-pytreegrav.bruteforce.Accel_bruteforce(x, m, softening, G=1.0)
-

Returns the exact mutually-interacting gravitational accelerations of a set of particles.

-

Arguments: -x – shape (N,3) array of positions where the potential is to be evaluated -m – shape (N,) array of particle masses -softening – shape (N,) array of softening lengths

-

Optional arguments: -G – gravitational constant (default 1.0)

-

Returns: -shape (N,3) array of gravitational accelerations

-
- -
-
-pytreegrav.bruteforce.Accel_bruteforce_parallel(x, m, softening, G=1.0)
-

Returns the exact mutually-interacting gravitational accelerations of a set of particles.

-

Arguments: -x – shape (N,3) array of positions where the potential is to be evaluated -m – shape (N,) array of particle masses -softening – shape (N,) array of softening lengths

-

Optional arguments: -G – gravitational constant (default 1.0)

-

Returns: -shape (N,3) array of gravitational accelerations

-
- -
-
-pytreegrav.bruteforce.PotentialTarget_bruteforce(x_target, softening_target, x_source, m_source, softening_source, G=1.0)
-

Returns the exact gravitational potential due to a set of particles, at a set of positions that need not be the same as the particle positions.

-

Arguments: -x_target – shape (N,3) array of positions where the potential is to be evaluated -softening_target – shape (N,) array of minimum softening lengths to be used -x_source – shape (M,3) array of positions of gravitating particles -m_source – shape (M,) array of particle masses -softening_source – shape (M,) array of softening lengths

-

Optional arguments: -G – gravitational constant (default 0.7)

-

Returns: -shape (N,) array of potential values

-
- -
-
-pytreegrav.bruteforce.PotentialTarget_bruteforce_parallel(x_target, softening_target, x_source, m_source, softening_source, G=1.0)
-

Returns the exact gravitational potential due to a set of particles, at a set of positions that need not be the same as the particle positions.

-

Arguments: -x_target – shape (N,3) array of positions where the potential is to be evaluated -softening_target – shape (N,) array of minimum softening lengths to be used -x_source – shape (M,3) array of positions of gravitating particles -m_source – shape (M,) array of particle masses -softening_source – shape (M,) array of softening lengths

-

Optional arguments: -G – gravitational constant (default 0.7)

-

Returns: -shape (N,) array of potential values

-
- -
-
-pytreegrav.bruteforce.Potential_bruteforce(x, m, softening, G=1.0)
-

Returns the exact mutually-interacting gravitational potential for a set of particles with positions x and masses m, evaluated by brute force.

-

Arguments: -x – shape (N,3) array of particle positions -m – shape (N,) array of particle masses -softening – shape (N,) array containing kernel support radii for gravitational softening

-

Optional arguments: -G – gravitational constant (default 1.0)

-

Returns: -shape (N,) array containing potential values

-
- -
-
-pytreegrav.bruteforce.Potential_bruteforce_parallel(x, m, softening, G=1.0)
-

Returns the exact mutually-interacting gravitational potential for a set of particles with positions x and masses m, evaluated by brute force.

-

Arguments: -x – shape (N,3) array of particle positions -m – shape (N,) array of particle masses -softening – shape (N,) array containing kernel support radii for gravitational softening

-

Optional arguments: -G – gravitational constant (default 1.0)

-

Returns: -shape (N,) array containing potential values

-
- -
-
-

pytreegrav.dynamic_tree module

-
-
-pytreegrav.dynamic_tree.ComputeMomentsDynamic(tree, no, children)
-
- -
-
-class pytreegrav.dynamic_tree.DynamicOctree(*args, **kwargs)
-

Bases: DynamicOctree

-

Octree implementation that stores node velocities for correlation functions and dynamic updates.

-
-
-class_type = jitclass.DynamicOctree#76beab8bbac0<Sizes:array(float64, 1d, A),Deltas:array(float64, 1d, A),Coordinates:array(float64, 2d, A),Velocities:array(float64, 2d, A),VelocityDisp:array(float64, 1d, A),Masses:array(float64, 1d, A),Quadrupoles:array(float64, 3d, A),HasQuads:bool,NumParticles:int64,NumNodes:int64,Softenings:array(float64, 1d, A),NextBranch:array(int64, 1d, A),FirstSubnode:array(int64, 1d, A),TreewalkIndices:array(int64, 1d, A)>
-
- -
- -
-
-pytreegrav.dynamic_tree.SetupTreewalk(tree, no, children)
-
- -
-
-

pytreegrav.frontend module

-
-
-pytreegrav.frontend.Accel(pos, m, softening=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational acceleration calculation

-

Returns the gravitational acceleration for a set of particles with positions x and masses m, at the positions of those particles, using either brute force or tree-based methods depending on the number of particles.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • softening (None or array_like, optional) – shape (N,) array containing kernel support radii for gravitational softening - these give the radius of compact support of the M4 cubic spline mass distribution - set to 0 by default

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

g – shape (N,3) array of acceleration vectors at the particle positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.AccelTarget(pos_target, pos_source, m_source, softening_target=None, softening_source=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational acceleration calculation for general N+M body case

-

Returns the gravitational acceleration for a set of M particles with positions x_source and masses m_source, at the positions of a set of N particles that need not be the same.

-
-
Parameters:
-
    -
  • pos_target (array_like) – shape (N,3) array of target particle positions where you want to know the acceleration

  • -
  • pos_source (array_like) – shape (M,3) array of source particle positions (positions of particles sourcing the gravitational field)

  • -
  • m_source (array_like) – shape (M,) array of source particle masses

  • -
  • softening_target (array_like or None, optional) – shape (N,) array of target particle softening radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • softening_source (array_like or None, optional) – shape (M,) array of source particle radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

phi – shape (N,3) array of accelerations at the target positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.ColumnDensity(pos, m, radii, rays=None, randomize_rays=False, healpix=False, tree=None, theta=0.5, return_tree=False, parallel=False)
-

Ray-traced or angle-binned column density calculation.

-

Returns an estimate of the column density from the position of each particle -integrated to infinity, assuming the particles are represented by uniform spheres. Note -that optical depth can be obtained by supplying “sigma = opacity * mass” in -place of mass, useful in situations where opacity is highly variable.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • radii (array_like) – shape (N,) array containing particle radii of the uniform spheres that -we use to model the particles’ mass distribution

  • -
  • rays (optional) – Which ray directions to raytrace the columns. -None: use the angular-binned column density method with 6 bins on the sky -OPTION 2: Integer number: use this many rays, with 6 using the standard -6-ray grid and other numbers sampling random directions -OPTION 3: Give a (N_rays,3) array of vectors specifying the -directions, which will be automatically normalized.

  • -
  • healpix (int, optional) – Use healpix ray grid with specified resolution level NSIDE

  • -
  • randomize_rays (bool, optional) – Randomize the orientation of the ray-grid for each particle

  • -
  • parallel (bool, optional) – If True, will parallelize the column density over all available cores. -(default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, -not necessarily the target particles at pos (default None)

  • -
  • theta (float, optional) – Opening angle for beam-traced angular bin estimator

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
-
-
Returns:
-

columns – shape (N,N_rays) float array of column densities from particle -centers integrated along the rays

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.ConstructTree(pos, m=None, softening=None, quadrupole=False, vel=None, compute_moments=True, morton_order=True)
-

Builds a tree containing particle data, for subsequent potential/field evaluation

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like or None, optional) – shape (N,) array of particle masses - if None then zeros will be used (e.g. if all you need the tree for is spatial algorithms)

  • -
  • softening (array_like or None, optional) – shape (N,) array of particle softening lengths - these give the radius of compact support of the M4 cubic spline mass distribution of each particle

  • -
  • quadrupole (bool, optional) – Whether to store quadrupole moments (default False)

  • -
  • vel (bool, optional) – Whether to store node velocities in the tree (default False)

  • -
-
-
Returns:
-

tree – Octree instance built from particle data

-
-
Return type:
-

octree

-
-
-
- -
-
-pytreegrav.frontend.DensityCorrFunc(pos, m, rbins=None, max_bin_size_ratio=100, theta=1.0, tree=None, return_tree=False, parallel=False, boxsize=0, weighted_binning=False)
-

Computes the average amount of mass in radial bin [r,r+dr] around a point, provided a set of radial bins.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • rbins (array_like or None, optional) – 1D array of radial bin edges - if None will use heuristics to determine sensible bins. Otherwise MUST BE LOGARITHMICALLY SPACED (default None)

  • -
  • max_bin_size_ratio (float, optional) – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 100)

  • -
  • theta (float, optional) – cell opening angle used to control accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 1.0)

  • -
  • parallel (bool, optional) – If True, will parallelize the correlation function computation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – if True will return the generated or used tree for future use (default False)

  • -
  • boxsize (float, optional) – finite periodic box size, if periodic boundary conditions are to be used (default 0)

  • -
  • weighted_binning (bool, optional) – (experimental) if True will distribute mass among radial bings with a weighted kernel (default False)

  • -
-
-
Returns:
-

    -
  • rbins (array_like) – array containing radial bin edges

  • -
  • mbins (array_like) – array containing mean mass in radial bins, averaged over all points

  • -
-

-
-
-
- -
-
-pytreegrav.frontend.Potential(pos, m, softening=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational potential calculation

-

Returns the gravitational potential for a set of particles with positions x and masses m, at the positions of those particles, using either brute force or tree-based methods depending on the number of particles.

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • softening (None or array_like, optional) – shape (N,) array containing kernel support radii for gravitational softening - - these give the radius of compact support of the M4 cubic spline mass distribution - set to 0 by default

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

phi – shape (N,) array of potentials at the particle positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.PotentialTarget(pos_target, pos_source, m_source, softening_target=None, softening_source=None, G=1.0, theta=0.7, tree=None, return_tree=False, parallel=False, method='adaptive', quadrupole=False)
-

Gravitational potential calculation for general N+M body case

-

Returns the gravitational potential for a set of M particles with positions x_source and masses m_source, at the positions of a set of N particles that need not be the same.

-
-
Parameters:
-
    -
  • pos_target (array_like) – shape (N,3) array of target particle positions where you want to know the potential

  • -
  • pos_source (array_like) – shape (M,3) array of source particle positions (positions of particles sourcing the gravitational field)

  • -
  • m_source (array_like) – shape (M,) array of source particle masses

  • -
  • softening_target (array_like or None, optional) – shape (N,) array of target particle softening radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • softening_source (array_like or None, optional) – shape (M,) array of source particle radii - these give the radius of compact support of the M4 cubic spline mass distribution

  • -
  • G (float, optional) – gravitational constant (default 1.0)

  • -
  • theta (float, optional) – cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7, gives ~1% accuracy)

  • -
  • parallel (bool, optional) – If True, will parallelize the force summation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – return the tree used for future use (default False)

  • -
  • method (str, optional) – Which summation method to use: ‘adaptive’, ‘tree’, or ‘bruteforce’ (default adaptive tries to pick the faster choice)

  • -
  • quadrupole (bool, optional) – Whether to use quadrupole moments in tree summation (default False)

  • -
-
-
Returns:
-

phi – shape (N,) array of potentials at the target positions

-
-
Return type:
-

array_like

-
-
-
- -
-
-pytreegrav.frontend.VelocityCorrFunc(pos, m, v, rbins=None, max_bin_size_ratio=100, theta=1.0, tree=None, return_tree=False, parallel=False, boxsize=0, weighted_binning=False)
-

Computes the weighted average product v(x).v(x+r), for a vector field v, in radial bins

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • v (array_like) – shape (N,3) of vector quantity (e.g. velocity, magnetic field, etc)

  • -
  • rbins (array_like or None, optional) – 1D array of radial bin edges - if None will use heuristics to determine sensible bins. Otherwise MUST BE LOGARITHMICALLY SPACED (default None)

  • -
  • max_bin_size_ratio (float, optional) – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 100)

  • -
  • theta (float, optional) – cell opening angle used to control accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 1.0)

  • -
  • parallel (bool, optional) – If True, will parallelize the correlation function computation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – if True will return the generated or used tree for future use (default False)

  • -
  • boxsize (float, optional) – finite periodic box size, if periodic boundary conditions are to be used (default 0)

  • -
  • weighted_binning (bool, optional) – (experimental) if True will distribute mass among radial bings with a weighted kernel (default False)

  • -
-
-
Returns:
-

    -
  • rbins (array_like) – array containing radial bin edges

  • -
  • corr (array_like) – array containing correlation function values in radial bins

  • -
-

-
-
-
- -
-
-pytreegrav.frontend.VelocityStructFunc(pos, m, v, rbins=None, max_bin_size_ratio=100, theta=1.0, tree=None, return_tree=False, parallel=False, boxsize=0, weighted_binning=False)
-

Computes the structure function for a vector field: the average value of |v(x)-v(x+r)|^2, in radial bins for r

-
-
Parameters:
-
    -
  • pos (array_like) – shape (N,3) array of particle positions

  • -
  • m (array_like) – shape (N,) array of particle masses

  • -
  • v (array_like) – shape (N,3) of vector quantity (e.g. velocity, magnetic field, etc)

  • -
  • rbins (array_like or None, optional) – 1D array of radial bin edges - if None will use heuristics to determine sensible bins. Otherwise MUST BE LOGARITHMICALLY SPACED (default None)

  • -
  • max_bin_size_ratio (float, optional) – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 100)

  • -
  • theta (float, optional) – cell opening angle used to control accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 1.0)

  • -
  • parallel (bool, optional) – If True, will parallelize the correlation function computation over all available cores. (default False)

  • -
  • tree (Octree, optional) – optional pre-generated Octree: this can contain any set of particles, not necessarily the target particles at pos (default None)

  • -
  • return_tree (bool, optional) – if True will return the generated or used tree for future use (default False)

  • -
  • boxsize (float, optional) – finite periodic box size, if periodic boundary conditions are to be used (default 0)

  • -
  • weighted_binning (bool, optional) – (experimental) if True will distribute mass among radial bings with a weighted kernel (default False)

  • -
-
-
Returns:
-

    -
  • rbins (array_like) – array containing radial bin edges

  • -
  • Sv (array_like) – array containing structure function values

  • -
-

-
-
-
- -
-
-pytreegrav.frontend.valueTestMethod(method)
-
- -
-
-

pytreegrav.kernel module

-
-
-pytreegrav.kernel.ForceKernel(r, h)
-

Returns the quantity equivalent to (fraction of mass enclosed)/ r^3 for a cubic-spline mass distribution of compact support radius h. Used to calculate the softened gravitational force.

-

Arguments: -r - radius -h - softening

-
- -
-
-pytreegrav.kernel.PotentialKernel(r, h)
-

Returns the equivalent of -1/r for a cubic-spline mass distribution of compact support radius h. Used to calculate the softened gravitational potential.

-

Arguments: -r - radius -h - softening

-
- -
-
-

pytreegrav.octree module

-
-
-pytreegrav.octree.ComputeMoments(tree, no, children)
-

Does a recursive pass through the tree and computes centers of mass, total mass, max softening, and distance between geometric center and COM

-
- -
-
-class pytreegrav.octree.Octree(*args, **kwargs)
-

Bases: Octree

-

Octree implementation.

-
-
-class_type = jitclass.Octree#76becaee2160<Sizes:array(float64, 1d, A),Deltas:array(float64, 1d, A),Coordinates:array(float64, 2d, A),Masses:array(float64, 1d, A),Quadrupoles:array(float64, 3d, A),HasQuads:bool,NumParticles:int64,NumNodes:int64,Softenings:array(float64, 1d, A),NextBranch:array(int64, 1d, A),FirstSubnode:array(int64, 1d, A),TreewalkIndices:array(int64, 1d, A)>
-
- -
- -
-
-pytreegrav.octree.SetupTreewalk(tree, no, children)
-
- -
-
-pytreegrav.octree.increase_tree_size(tree, fac=1.2)
-

Reallocate the tree data with storage increased by factor fac

-
- -
-
-

pytreegrav.treewalk module

-
-
-pytreegrav.treewalk.AccelTarget_tree(pos_target, softening_target, tree, G=1.0, theta=0.7, quadrupole=False)
-

Returns the gravitational acceleration at the specified points, given a tree containing the mass distribution -Arguments: -pos_target – shape (N,3) array of positions at which to evaluate the field -softening_target – shape (N,) array of minimum softening lengths to be used in all accel computations -tree – Octree instance containing the positions, masses, and softenings of the source particles -Optional arguments: -G – gravitational constant (default 1.0) -theta – accuracy parameter, smaller is more accurate, larger is faster (default 0.7) -Returns: -shape (N,3) array of acceleration values at each point in pos_target

-
- -
-
-pytreegrav.treewalk.AccelTarget_tree_parallel(pos_target, softening_target, tree, G=1.0, theta=0.7, quadrupole=False)
-

Returns the gravitational acceleration at the specified points, given a tree containing the mass distribution -Arguments: -pos_target – shape (N,3) array of positions at which to evaluate the field -softening_target – shape (N,) array of minimum softening lengths to be used in all accel computations -tree – Octree instance containing the positions, masses, and softenings of the source particles -Optional arguments: -G – gravitational constant (default 1.0) -theta – accuracy parameter, smaller is more accurate, larger is faster (default 0.7) -Returns: -shape (N,3) array of acceleration values at each point in pos_target

-
- -
-
-pytreegrav.treewalk.AccelWalk(pos, tree, softening=0, no=-1, theta=0.7)
-

Returns the gravitational acceleration field at position x by performing the Barnes-Hut treewalk using the provided octree instance -Arguments: -pos - (3,) array containing position of interest -tree - octree instance storing the tree structure -Keyword arguments: -softening - softening radius of the particle at which the force is being evaluated - we use the greater of the target and source softenings when evaluating the softened potential -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization -theta - cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7 gives ~1% accuracy)

-
- -
-
-pytreegrav.treewalk.AccelWalk_quad(pos, tree, softening=0, no=-1, theta=0.7)
-

Returns the gravitational acceleration field at position x by performing the Barnes-Hut treewalk using the provided octree instance. Uses the quadrupole expansion. -Arguments: -pos - (3,) array containing position of interest -tree - octree instance storing the tree structure -Keyword arguments: -softening - softening radius of the particle at which the force is being evaluated - we use the greater of the target and source softenings when evaluating the softened potential -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization -theta - cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7 gives ~1% accuracy)

-
- -
-
-pytreegrav.treewalk.ColumnDensityWalk_binned(pos, tree, theta=0.5, no=-1)
-

Returns the integrated column density to infinity from pos, in the directions given by the rays argument

-

Arguments: -pos - (3,) array containing position of interest -tree - octree object storing the tree structure

-

Returns: -columns - shape (6,) array of average column densities in the 6 equal bins on the sphere

-

Keyword arguments: -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization

-
- -
-
-pytreegrav.treewalk.ColumnDensityWalk_multiray(pos, rays, tree, no=-1)
-

Returns the integrated column density to infinity from pos, in the directions given by the rays argument

-

Arguments: -pos - (3,) array containing position of interest -rays - (N_rays, 3) array of unit vectors -tree - octree object storing the tree structure

-

Returns: -columns - (N_rays,) array of column densities along directions given by rays

-

Keyword arguments: -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization

-
- -
-
-pytreegrav.treewalk.ColumnDensityWalk_singleray(pos, ray, tree, no=-1)
-

Returns the integrated column density to infinity from pos, in the directions given by the rays argument

-

Arguments: -pos - (3,) array containing position of interest -ray - (3,) array with the unit vector of the ray -tree - octree object storing the tree structure

-

Returns: -columns - (N_rays,) array of column densities along directions given by rays

-

Keyword arguments: -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization

-
- -
-
-pytreegrav.treewalk.ColumnDensity_tree(pos_target, tree, rays=None, randomize_rays=False, theta=0.7)
-

Returns the column density integrated to infinity from pos_target along rays, given the mass distribution in an Octree

-
-
Parameters:
-
    -
  • pos_target (array_like) – shape (N,3) array of target particle positions where you want to know the potential.

  • -
  • tree (Octree) – Octree instance initialized with the positions, masses, and softenings of the source particles.

  • -
  • rays (array_like) – Shape (N_rays,3) array of ray direction unit vectors. If None then we instead compute average column densities in a 6-bin tesselation of the sphere.

  • -
  • randomize_rays (bool, optional) –

  • -
  • particle. (Randomly orients the raygrid for each) –

  • -
  • particle. – Randomly orients the raygrid for each particle.

  • -
-
-
-
- -
-
-pytreegrav.treewalk.ColumnDensity_tree_parallel(pos_target, tree, rays=None, randomize_rays=False, theta=0.7)
-

Returns the column density integrated to infinity from pos_target along rays, given the mass distribution in an Octree

-
-
Parameters:
-
    -
  • pos_target (array_like) – shape (N,3) array of target particle positions where you want to know the potential.

  • -
  • tree (Octree) – Octree instance initialized with the positions, masses, and softenings of the source particles.

  • -
  • rays (array_like) – Shape (N_rays,3) array of ray direction unit vectors. If None then we instead compute average column densities in a 6-bin tesselation of the sphere.

  • -
  • randomize_rays (bool, optional) –

  • -
  • particle. (Randomly orients the raygrid for each) –

  • -
  • particle. – Randomly orients the raygrid for each particle.

  • -
-
-
-
- -
-
-pytreegrav.treewalk.DensityCorrFunc_tree(pos, tree, rbins, max_bin_size_ratio=100, theta=0.7, boxsize=0, weighted_binning=False)
-

Returns the average mass in radial bins surrounding a point

-

Arguments: -pos – shape (N,3) array of particle positions -tree – Octree instance containing the positions, masses, and softenings of the source particles

-

Optional arguments: -rbins – 1D array of radial bin edges - if None will use heuristics to determine sensible bins -max_bin_size_ratio – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width

-

Returns: -mbins – arrays containing total mass in each bin

-
- -
-
-pytreegrav.treewalk.DensityCorrFunc_tree_parallel(pos, tree, rbins, max_bin_size_ratio=100, theta=0.7, boxsize=0, weighted_binning=False)
-

Returns the average mass in radial bins surrounding a point

-

Arguments: -pos – shape (N,3) array of particle positions -tree – Octree instance containing the positions, masses, and softenings of the source particles

-

Optional arguments: -rbins – 1D array of radial bin edges - if None will use heuristics to determine sensible bins -max_bin_size_ratio – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width

-

Returns: -mbins – arrays containing total mass in each bin

-
- -
-
-pytreegrav.treewalk.DensityCorrWalk(pos, tree, rbins, max_bin_size_ratio=100, theta=0.7, no=-1, boxsize=0, weighted_binning=False)
-

Returns the gravitational potential at position x by performing the Barnes-Hut treewalk using the provided octree instance

-

Arguments: -pos - (3,) array containing position of interest -tree - octree object storing the tree structure

-

Keyword arguments: -softening - softening radius of the particle at which the force is being evaluated - we use the greater of the target and source softenings when evaluating the softened potential -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization -theta - cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7 gives ~1% accuracy)

-
- -
-
-pytreegrav.treewalk.NearestImage(x, boxsize)
-
- -
-
-pytreegrav.treewalk.PotentialTarget_tree(pos_target, softening_target, tree, G=1.0, theta=0.7, quadrupole=False)
-

Returns the gravitational potential at the specified points, given a tree containing the mass distribution -Arguments: -pos_target – shape (N,3) array of positions at which to evaluate the potential -softening_target – shape (N,) array of minimum softening lengths to be used in all potential computations -tree – Octree instance containing the positions, masses, and softenings of the source particles -Optional arguments: -G – gravitational constant (default 1.0) -theta – accuracy parameter, smaller is more accurate, larger is faster (default 0.7) -Returns: -shape (N,) array of potential values at each point in pos

-
- -
-
-pytreegrav.treewalk.PotentialTarget_tree_parallel(pos_target, softening_target, tree, G=1.0, theta=0.7, quadrupole=False)
-

Returns the gravitational potential at the specified points, given a tree containing the mass distribution -Arguments: -pos_target – shape (N,3) array of positions at which to evaluate the potential -softening_target – shape (N,) array of minimum softening lengths to be used in all potential computations -tree – Octree instance containing the positions, masses, and softenings of the source particles -Optional arguments: -G – gravitational constant (default 1.0) -theta – accuracy parameter, smaller is more accurate, larger is faster (default 0.7) -Returns: -shape (N,) array of potential values at each point in pos

-
- -
-
-pytreegrav.treewalk.PotentialWalk(pos, tree, softening=0, no=-1, theta=0.7)
-

Returns the gravitational potential at position x by performing the Barnes-Hut treewalk using the provided octree instance -Arguments: -pos - (3,) array containing position of interest -tree - octree object storing the tree structure -Keyword arguments: -softening - softening radius of the particle at which the force is being evaluated - we use the greater of the target and source softenings when evaluating the softened potential -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization -theta - cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7 gives ~1% accuracy)

-
- -
-
-pytreegrav.treewalk.PotentialWalk_quad(pos, tree, softening=0, no=-1, theta=0.7)
-

Returns the gravitational potential at position x by performing the Barnes-Hut treewalk using the provided octree instance. Uses the quadrupole expansion. -Arguments: -pos - (3,) array containing position of interest -tree - octree object storing the tree structure -Keyword arguments: -softening - softening radius of the particle at which the force is being evaluated - we use the greater of the target and source softenings when evaluating the softened potential -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization -theta - cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7 gives ~1% accuracy)

-
- -
-
-pytreegrav.treewalk.VelocityCorrFunc_tree(pos, vel, weight, tree, rbins, max_bin_size_ratio=100, theta=0.7, boxsize=0, weighted_binning=False)
-

Returns the average mass in radial bins surrounding a point

-

Arguments: -pos – shape (N,3) array of particle positions -tree – Octree instance containing the positions, masses, and softenings of the source particles

-

Optional arguments: -rbins – 1D array of radial bin edges - if None will use heuristics to determine sensible bins -max_bin_size_ratio – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 0.5)

-

Returns: -mbins – arrays containing total mass in each bin

-
- -
-
-pytreegrav.treewalk.VelocityCorrFunc_tree_parallel(pos, vel, weight, tree, rbins, max_bin_size_ratio=100, theta=0.7, boxsize=0, weighted_binning=False)
-

Returns the average mass in radial bins surrounding a point

-

Arguments: -pos – shape (N,3) array of particle positions -tree – Octree instance containing the positions, masses, and softenings of the source particles

-

Optional arguments: -rbins – 1D array of radial bin edges - if None will use heuristics to determine sensible bins -max_bin_size_ratio – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 0.5)

-

Returns: -mbins – arrays containing total mass in each bin

-
- -
-
-pytreegrav.treewalk.VelocityCorrWalk(pos, vel, tree, rbins, max_bin_size_ratio=100, theta=0.7, no=-1, boxsize=0, weighted_binning=False)
-

Returns the gravitational potential at position x by performing the Barnes-Hut treewalk using the provided octree instance

-

Arguments: -pos - (3,) array containing position of interest -vel - (3,) array containing velocity of point of interest -tree - octree object storing the tree structure

-

Keyword arguments: -softening - softening radius of the particle at which the force is being evaluated - we use the greater of the target and source softenings when evaluating the softened potential -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization -theta - cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7 gives ~1% accuracy)

-
- -
-
-pytreegrav.treewalk.VelocityStructFunc_tree(pos, vel, weight, tree, rbins, max_bin_size_ratio=100, theta=0.7, boxsize=0, weighted_binning=False)
-

Returns the average mass in radial bins surrounding a point

-

Arguments: -pos – shape (N,3) array of particle positions -tree – Octree instance containing the positions, masses, and softenings of the source particles

-

Optional arguments: -rbins – 1D array of radial bin edges - if None will use heuristics to determine sensible bins -max_bin_size_ratio – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 0.5)

-

Returns: -mbins – arrays containing total mass in each bin

-
- -
-
-pytreegrav.treewalk.VelocityStructFunc_tree_parallel(pos, vel, weight, tree, rbins, max_bin_size_ratio=100, theta=0.7, boxsize=0, weighted_binning=False)
-

Returns the average mass in radial bins surrounding a point

-

Arguments: -pos – shape (N,3) array of particle positions -tree – Octree instance containing the positions, masses, and softenings of the source particles

-

Optional arguments: -rbins – 1D array of radial bin edges - if None will use heuristics to determine sensible bins -max_bin_size_ratio – controls the accuracy of the binning - tree nodes are subdivided until their side length is at most this factor * the radial bin width (default 0.5)

-

Returns: -mbins – arrays containing total mass in each bin

-
- -
-
-pytreegrav.treewalk.VelocityStructWalk(pos, vel, tree, rbins, max_bin_size_ratio=100, theta=0.7, no=-1, boxsize=0, weighted_binning=False)
-

Returns the gravitational potential at position x by performing the Barnes-Hut treewalk using the provided octree instance

-

Arguments: -pos - (3,) array containing position of interest -vel - (3,) array containing velocity of point of interest -tree - octree object storing the tree structure

-

Keyword arguments: -softening - softening radius of the particle at which the force is being evaluated - we use the greater of the target and source softenings when evaluating the softened potential -no - index of the top-level node whose field is being summed - defaults to the global top-level node, can use a subnode in principle for e.g. parallelization -theta - cell opening angle used to control force accuracy; smaller is slower (runtime ~ theta^-3) but more accurate. (default 0.7 gives ~1% accuracy)

-
- -
-
-pytreegrav.treewalk.acceptance_criterion(r: float, h: float, size: float, delta: float, theta: float) bool
-

Criterion for accepting the multipole approximation for summing the contribution of a node

-
- -
-
-pytreegrav.treewalk.angular_bin(dx)
-

Angular bin for binned column density estimator

-
- -
-
-pytreegrav.treewalk.do_weighted_binning(tree, no, rbins, mbin, r, r_idx, quantity)
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/search.html b/docs/build/html/search.html deleted file mode 100644 index 82fd38f..0000000 --- a/docs/build/html/search.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - Search — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - - - -
- -
- -
-
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js deleted file mode 100644 index 0744de7..0000000 --- a/docs/build/html/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({"docnames": ["Nbody_simulation", "community", "frontend_API", "index", "modules", "pytreegrav", "setup", "usage/installation", "usage/quickstart"], "filenames": ["Nbody_simulation.rst", "community.rst", "frontend_API.rst", "index.rst", "modules.rst", "pytreegrav.rst", "setup.rst", "usage/installation.rst", "usage/quickstart.rst"], "titles": ["Example: N-body simulation", "Feedback, Support, and Contributions", "API Documentation", "Welcome to pytreegrav\u2019s documentation!", "src", "pytreegrav package", "setup module", "Installation", "Quickstart"], "terms": {"here": [0, 8], "we": [0, 2, 3, 5, 7, 8], "provid": [0, 2, 5, 8], "simpl": 0, "an": [0, 1, 2, 3, 5, 8], "integr": [0, 2, 5], "implement": [0, 3, 5, 8], "us": [0, 2, 5, 8], "forc": [0, 2, 3, 5, 7, 8], "potenti": [0, 2, 3, 4, 5, 7, 8], "evalu": [0, 2, 3, 5], "routin": 0, "from": [0, 2, 3, 5, 8], "pytreegrav": [0, 1, 2, 4, 7, 8], "If": [0, 2, 5], "you": [0, 2, 5, 7, 8], "were": 0, "write": [0, 3], "more": [0, 2, 5], "seriou": 0, "code": [0, 7], "would": [0, 8], "want": [0, 2, 3, 5], "adopt": 0, "modular": 0, "object": [0, 5], "orient": [0, 2, 5], "approach": 0, "thi": [0, 2, 5, 7, 8], "suffic": 0, "demonstr": 0, "first": [0, 8], "make": [0, 8], "some": [0, 8], "particl": [0, 2, 3, 5], "gaussian": 0, "blob": 0, "can": [0, 2, 5, 7, 8], "try": [0, 8], "modifi": 0, "ic": 0, "gener": [0, 2, 5, 8], "plai": 0, "around": [0, 2, 5], "veloc": [0, 2, 5], "geometri": 0, "extra": 0, "fun": 0, "also": [0, 7, 8], "total": [0, 5], "energi": 0, "which": [0, 2, 5, 7], "i": [0, 2, 3, 5, 7], "conserv": 0, "down": 0, "tree": [0, 2, 3, 5, 7, 8], "error": [0, 8], "pylab": 0, "import": [0, 7, 8], "accel": [0, 2, 4, 5, 8], "def": 0, "generat": 0, "seed": 0, "42": 0, "np": [0, 8], "random": [0, 2, 5, 8], "rng": 0, "reproduc": 0, "po": [0, 2, 5], "normal": [0, 2, 5], "size": [0, 2, 5], "3": [0, 2, 5, 7, 8], "posit": [0, 2, 5, 8], "averag": [0, 2, 5], "axi": [0, 8], "0": [0, 2, 5, 8], "put": [0, 7], "center": [0, 2, 5], "mass": [0, 2, 5, 8], "origin": 0, "vel": [0, 2, 5], "zeros_lik": 0, "rest": 0, "soften": [0, 2, 5, 8], "repeat": [0, 8], "1": [0, 2, 5, 8], "system": [0, 8], "have": [0, 7, 8], "unit": [0, 5, 8], "return": [0, 2, 5], "totalenergi": 0, "kinet": 0, "5": [0, 2, 5, 8], "sum": [0, 5, 8], "none": [0, 2, 5], "2": [0, 2, 5, 8], "parallel": [0, 2, 5, 8], "true": [0, 2, 5, 8], "matplotlib": 0, "backend": 0, "macosx": 0, "popul": 0, "interact": [0, 5], "namespac": 0, "numpi": [0, 7, 8], "now": [0, 8], "let": [0, 8], "": [0, 8], "defin": 0, "basic": [0, 7], "timestep": 0, "leapfrog": 0, "hamiltonian": 0, "split": 0, "kick": 0, "drift": 0, "form": 0, "e": [0, 2, 5, 7], "g": [0, 2, 5, 8], "springel": 0, "2005": 0, "leapfrog_kdk_timestep": 0, "dt": 0, "half": 0, "step": 0, "note": [0, 2, 5], "must": [0, 2, 5], "slice": 0, "arrai": [0, 2, 5], "them": 0, "place": [0, 2, 5], "full": 0, "recomput": 0, "acceler": [0, 2, 5, 7, 8], "anoth": [0, 8], "10000": 0, "10k": 0, "t": [0, 8], "time": [0, 8], "tmax": 0, "50": 0, "final": 0, "max": [0, 5], "r50": 0, "radii": [0, 2, 5, 8], "while": 0, "actual": 0, "mai": 0, "take": 0, "coupl": 0, "minut": 0, "run": [0, 7, 8], "append": 0, "median": 0, "03": 0, "adjust": 0, "control": [0, 2, 5, 8], "print": [0, 8], "complet": 0, "rel": 0, "ab": 0, "00161328": 0, "plot": 0, "radiu": [0, 2, 5], "get": 0, "idea": 0, "how": [0, 8], "pulsat": 0, "over": [0, 2, 5], "check": [0, 7], "accuraci": [0, 2, 5, 8], "inlin": 0, "plt": 0, "figur": 0, "figsiz": 0, "4": [0, 8], "dpi": 0, "300": 0, "label": 0, "xlabel": 0, "legend": 0, "0x7fa6d7753820": 0, "To": [1, 7], "report": 1, "issu": 1, "seek": 1, "pleas": 1, "initi": [1, 3, 5], "pull": 1, "request": 1, "through": [1, 5], "project": 1, "github": [1, 7], "frontend": [2, 4, 7, 8], "m": [2, 5, 8], "theta": [2, 5, 8], "7": [2, 5, 8], "return_tre": [2, 5], "fals": [2, 5], "method": [2, 3, 5, 8], "adapt": [2, 5], "quadrupol": [2, 5], "gravit": [2, 3, 5, 8], "calcul": [2, 5, 8], "set": [2, 3, 5, 8], "x": [2, 5, 7, 8], "those": [2, 5], "either": [2, 5], "brute": [2, 3, 5, 7, 8], "base": [2, 5, 8], "depend": [2, 5], "number": [2, 5, 8], "paramet": [2, 5], "array_lik": [2, 5], "shape": [2, 5], "n": [2, 3, 5, 8], "float": [2, 5], "option": [2, 5, 8], "constant": [2, 5], "default": [2, 5, 8], "contain": [2, 5], "kernel": [2, 4], "support": [2, 3, 5], "give": [2, 5, 8], "compact": [2, 5], "m4": [2, 5], "cubic": [2, 5], "spline": [2, 5], "distribut": [2, 5], "cell": [2, 5], "open": [2, 5, 8], "angl": [2, 5, 8], "smaller": [2, 5, 8], "slower": [2, 5, 8], "runtim": [2, 5, 8], "accur": [2, 5], "bool": [2, 5], "summat": [2, 3, 5, 8], "all": [2, 5, 8], "avail": [2, 5, 8], "core": [2, 5, 8], "octre": [2, 4], "pre": [2, 5], "ani": [2, 5], "necessarili": [2, 5], "target": [2, 5, 8], "futur": [2, 5], "str": [2, 5], "bruteforc": [2, 4, 8], "tri": [2, 5], "pick": [2, 5], "faster": [2, 5, 8], "choic": [2, 5, 8], "whether": [2, 5], "moment": [2, 5], "vector": [2, 5], "type": [2, 5], "acceltarget": [2, 4, 5, 8], "pos_target": [2, 5], "pos_sourc": [2, 5], "m_sourc": [2, 5], "softening_target": [2, 5], "softening_sourc": [2, 5], "bodi": [2, 3, 5], "case": [2, 5], "x_sourc": [2, 5], "need": [2, 5, 7], "same": [2, 5, 8], "where": [2, 3, 5], "know": [2, 5, 8], "sourc": [2, 3, 5, 8], "field": [2, 3, 5], "phi": [2, 5], "columndens": [2, 4, 5], "rai": [2, 5], "randomize_rai": [2, 5], "healpix": [2, 5], "trace": [2, 5], "bin": [2, 5], "column": [2, 5], "densiti": [2, 5], "estim": [2, 5], "each": [2, 5, 8], "infin": [2, 5], "assum": [2, 5, 8], "ar": [2, 3, 5, 7], "repres": [2, 5], "uniform": [2, 5], "sphere": [2, 5, 8], "optic": [2, 5], "depth": [2, 5], "obtain": [2, 5], "suppli": [2, 5], "sigma": [2, 5], "opac": [2, 5], "situat": [2, 5], "highli": [2, 5], "variabl": [2, 5, 7, 8], "model": [2, 5], "direct": [2, 3, 5, 8], "raytrac": [2, 5], "angular": [2, 5], "6": [2, 5], "sky": [2, 5], "integ": [2, 5], "mani": [2, 5], "standard": [2, 5], "grid": [2, 5], "other": [2, 5], "sampl": [2, 5, 8], "n_rai": [2, 5], "specifi": [2, 5, 8], "automat": [2, 5, 7], "int": [2, 5], "resolut": [2, 5], "level": [2, 5, 7], "nside": [2, 5], "beam": [2, 5], "along": [2, 5], "constructtre": [2, 4, 5], "compute_mo": [2, 5], "morton_ord": [2, 5], "build": [2, 5, 7], "data": [2, 5, 8], "subsequ": [2, 5], "zero": [2, 5], "spatial": [2, 5], "algorithm": [2, 5], "length": [2, 5, 8], "store": [2, 5], "node": [2, 5], "instanc": [2, 5], "built": [2, 5, 7], "densitycorrfunc": [2, 4, 5], "rbin": [2, 5], "max_bin_size_ratio": [2, 5], "100": [2, 5], "boxsiz": [2, 5], "weighted_bin": [2, 5], "comput": [2, 3, 5, 8], "amount": [2, 5], "radial": [2, 5], "r": [2, 5], "dr": [2, 5], "point": [2, 3, 5], "1d": [2, 5], "edg": [2, 5], "heurist": [2, 5], "determin": [2, 5], "sensibl": [2, 5], "otherwis": [2, 5, 8], "BE": [2, 5], "logarithm": [2, 5], "space": [2, 5], "subdivid": [2, 5], "until": [2, 5], "side": [2, 5], "most": [2, 5, 7], "factor": [2, 5], "width": [2, 5], "correl": [2, 5], "function": [2, 3, 5, 8], "finit": [2, 5], "period": [2, 5], "box": [2, 5], "boundari": [2, 5], "condit": [2, 3, 5], "experiment": [2, 5], "among": [2, 5], "bing": [2, 5], "weight": [2, 5], "mbin": [2, 5], "mean": [2, 5, 8], "potentialtarget": [2, 4, 5, 8], "velocitycorrfunc": [2, 4, 5], "v": [2, 5], "product": [2, 5], "quantiti": [2, 5], "magnet": [2, 5], "etc": [2, 5], "corr": [2, 5], "valu": [2, 5], "velocitystructfunc": [2, 4, 5], "structur": [2, 5], "sv": [2, 5], "packag": [3, 4, 7, 8], "It": [3, 8], "includ": [3, 8], "fast": [3, 8], "approxim": [3, 5, 8], "barn": [3, 5, 8], "hut": [3, 5, 8], "treecod": [3, 8], "For": [3, 8], "oct": [3, 8], "numba": [3, 7, 8], "jitclass": [3, 5, 8], "achiev": [3, 8], "much": [3, 8], "higher": [3, 8], "peform": [3, 8], "than": 3, "equival": [3, 5, 8], "pure": [3, 8], "python": [3, 7, 8], "without": 3, "singl": [3, 8], "line": 3, "c": 3, "cython": 3, "instal": 3, "requir": 3, "latest": 3, "stabl": 3, "releas": 3, "test": 3, "quickstart": 3, "what": 3, "differ": 3, "exampl": [3, 8], "simul": 3, "stepper": 3, "main": 3, "loop": 3, "analysi": 3, "api": 3, "feedback": 3, "contribut": [3, 5], "index": [3, 5], "modul": [3, 4], "search": 3, "page": 3, "submodul": 4, "acceltarget_bruteforc": [4, 5], "acceltarget_bruteforce_parallel": [4, 5], "accel_bruteforc": [4, 5, 8], "accel_bruteforce_parallel": [4, 5], "potentialtarget_bruteforc": [4, 5], "potentialtarget_bruteforce_parallel": [4, 5], "potential_bruteforc": [4, 5], "potential_bruteforce_parallel": [4, 5], "dynamic_tre": 4, "computemomentsdynam": [4, 5], "dynamicoctre": [4, 5], "class_typ": [4, 5], "setuptreewalk": [4, 5], "valuetestmethod": [4, 5], "forcekernel": [4, 5], "potentialkernel": [4, 5], "computemo": [4, 5], "increase_tree_s": [4, 5], "treewalk": 4, "acceltarget_tre": [4, 5], "acceltarget_tree_parallel": [4, 5], "accelwalk": [4, 5], "accelwalk_quad": [4, 5], "columndensitywalk_bin": [4, 5], "columndensitywalk_multirai": [4, 5], "columndensitywalk_singlerai": [4, 5], "columndensity_tre": [4, 5], "columndensity_tree_parallel": [4, 5], "densitycorrfunc_tre": [4, 5], "densitycorrfunc_tree_parallel": [4, 5], "densitycorrwalk": [4, 5], "nearestimag": [4, 5], "potentialtarget_tre": [4, 5], "potentialtarget_tree_parallel": [4, 5], "potentialwalk": [4, 5], "potentialwalk_quad": [4, 5], "velocitycorrfunc_tre": [4, 5], "velocitycorrfunc_tree_parallel": [4, 5], "velocitycorrwalk": [4, 5], "velocitystructfunc_tre": [4, 5], "velocitystructfunc_tree_parallel": [4, 5], "velocitystructwalk": [4, 5], "acceptance_criterion": [4, 5], "angular_bin": [4, 5], "do_weighted_bin": [4, 5], "content": 4, "x_target": [5, 8], "due": 5, "argument": 5, "minimum": 5, "exact": [5, 8], "mutual": 5, "children": 5, "class": 5, "arg": 5, "kwarg": 5, "dynam": 5, "updat": 5, "76beab8bbac0": 5, "float64": 5, "A": 5, "delta": 5, "coordin": 5, "2d": 5, "velocitydisp": 5, "3d": 5, "hasquad": 5, "numparticl": 5, "int64": 5, "numnod": 5, "nextbranch": 5, "firstsubnod": 5, "treewalkindic": 5, "h": [5, 8], "fraction": 5, "enclos": 5, "doe": 5, "recurs": 5, "pass": 5, "distanc": 5, "between": [5, 8], "geometr": 5, "com": [5, 7], "76becaee2160": 5, "fac": 5, "realloc": 5, "storag": 5, "increas": 5, "given": 5, "larger": 5, "perform": 5, "interest": 5, "keyword": 5, "being": 5, "greater": 5, "when": [5, 8], "top": [5, 7], "whose": 5, "global": 5, "subnod": 5, "principl": 5, "expans": 5, "equal": 5, "instead": 5, "tessel": 5, "randomli": [5, 8], "raygrid": 5, "surround": 5, "criterion": 5, "accept": 5, "multipol": 5, "dx": 5, "r_idx": 5, "The": [7, 8], "below": 7, "help": 7, "quickli": 7, "work": [7, 8], "recommend": 7, "anaconda": 7, "version": 7, "follow": 7, "pip": 7, "prefer": 7, "wai": 7, "necessari": 7, "your": [7, 8], "pythonpath": 7, "environ": 7, "so": 7, "altern": 7, "directli": 7, "up": [7, 8], "date": 7, "clone": 7, "fork": 7, "repositori": 7, "git": 7, "http": 7, "mikegrud": 7, "onc": 7, "add": 7, "execut": 7, "setup": 7, "py": 7, "directori": 7, "well": 7, "look": 7, "solver": [7, 8], "correctli": 7, "pytest": 7, "root": 7, "problem": [7, 8], "compar": [7, 8], "respect": 7, "answer": 7, "within": 7, "expect": 7, "toler": 7, "stuff": 8, "whatev": 8, "10": 8, "rand": 8, "cube": 8, "01": 8, "1521787": 8, "2958852": 8, "30109005": 8, "50678204": 8, "37489886": 8, "0558666": 8, "24650087": 8, "95423467": 8, "175074": 8, "87868472": 8, "28332176": 8, "22718531": 8, "41962742": 8, "32372245": 8, "31829084": 8, "45127054": 8, "38292881": 8, "05820412": 8, "35518057": 8, "19299372": 8, "28494218": 8, "11783337": 8, "1653377": 8, "80464695": 8, "By": 8, "optim": 8, "speed": 8, "one": 8, "both": 8, "accel_tre": 8, "phi_tre": 8, "phi_bruteforc": 8, "927745": 8, "44": 8, "1175": 8, "802386": 8, "20": 8, "0234": 8, "As": 8, "see": 8, "especi": 8, "count": 8, "exceed": 8, "plummer": 8, "intel": 8, "i9": 8, "9900k": 8, "workstat": 8, "But": 8, "free": 8, "lunch": 8, "quantifi": 8, "rm": 8, "just": 8, "solut": 8, "acc_error": 8, "sqrt": 8, "phi_error": 8, "std": 8, "006739311224338851": 8, "0003888328578588027": 8, "abov": 8, "typic": 8, "8": 8, "63": 8, "1738": 8, "78978e": 8, "05": 8, "14": 8, "3356": 8, "000258755": 8, "91292": 8, "00148698": 8, "724668": 8, "0105937": 8, "across": 8, "logic": 8, "via": 8, "openmp": 8, "thing": 8, "consider": 8, "scale": 8, "vari": 8, "222271": 8, "25576": 8, "181393": 8, "72611": 8, "got": 8, "cover": 8, "do": 8, "exactli": 8, "separ": 8, "everyth": 8, "n_target": 8, "h_target": 8, "floor": 8, "h_sourc": 8, "befor": 8, "006719983300560105": 8, "0003873676304955059": 8}, "objects": {"": [[5, 0, 0, "-", "pytreegrav"]], "pytreegrav": [[5, 0, 0, "-", "bruteforce"], [5, 0, 0, "-", "dynamic_tree"], [5, 0, 0, "-", "frontend"], [5, 0, 0, "-", "kernel"], [5, 0, 0, "-", "octree"], [5, 0, 0, "-", "treewalk"]], "pytreegrav.bruteforce": [[5, 1, 1, "", "AccelTarget_bruteforce"], [5, 1, 1, "", "AccelTarget_bruteforce_parallel"], [5, 1, 1, "", "Accel_bruteforce"], [5, 1, 1, "", "Accel_bruteforce_parallel"], [5, 1, 1, "", "PotentialTarget_bruteforce"], [5, 1, 1, "", "PotentialTarget_bruteforce_parallel"], [5, 1, 1, "", "Potential_bruteforce"], [5, 1, 1, "", "Potential_bruteforce_parallel"]], "pytreegrav.dynamic_tree": [[5, 1, 1, "", "ComputeMomentsDynamic"], [5, 2, 1, "", "DynamicOctree"], [5, 1, 1, "", "SetupTreewalk"]], "pytreegrav.dynamic_tree.DynamicOctree": [[5, 3, 1, "", "class_type"]], "pytreegrav.frontend": [[5, 1, 1, "", "Accel"], [5, 1, 1, "", "AccelTarget"], [5, 1, 1, "", "ColumnDensity"], [5, 1, 1, "", "ConstructTree"], [5, 1, 1, "", "DensityCorrFunc"], [5, 1, 1, "", "Potential"], [5, 1, 1, "", "PotentialTarget"], [5, 1, 1, "", "VelocityCorrFunc"], [5, 1, 1, "", "VelocityStructFunc"], [5, 1, 1, "", "valueTestMethod"]], "pytreegrav.kernel": [[5, 1, 1, "", "ForceKernel"], [5, 1, 1, "", "PotentialKernel"]], "pytreegrav.octree": [[5, 1, 1, "", "ComputeMoments"], [5, 2, 1, "", "Octree"], [5, 1, 1, "", "SetupTreewalk"], [5, 1, 1, "", "increase_tree_size"]], "pytreegrav.octree.Octree": [[5, 3, 1, "", "class_type"]], "pytreegrav.treewalk": [[5, 1, 1, "", "AccelTarget_tree"], [5, 1, 1, "", "AccelTarget_tree_parallel"], [5, 1, 1, "", "AccelWalk"], [5, 1, 1, "", "AccelWalk_quad"], [5, 1, 1, "", "ColumnDensityWalk_binned"], [5, 1, 1, "", "ColumnDensityWalk_multiray"], [5, 1, 1, "", "ColumnDensityWalk_singleray"], [5, 1, 1, "", "ColumnDensity_tree"], [5, 1, 1, "", "ColumnDensity_tree_parallel"], [5, 1, 1, "", "DensityCorrFunc_tree"], [5, 1, 1, "", "DensityCorrFunc_tree_parallel"], [5, 1, 1, "", "DensityCorrWalk"], [5, 1, 1, "", "NearestImage"], [5, 1, 1, "", "PotentialTarget_tree"], [5, 1, 1, "", "PotentialTarget_tree_parallel"], [5, 1, 1, "", "PotentialWalk"], [5, 1, 1, "", "PotentialWalk_quad"], [5, 1, 1, "", "VelocityCorrFunc_tree"], [5, 1, 1, "", "VelocityCorrFunc_tree_parallel"], [5, 1, 1, "", "VelocityCorrWalk"], [5, 1, 1, "", "VelocityStructFunc_tree"], [5, 1, 1, "", "VelocityStructFunc_tree_parallel"], [5, 1, 1, "", "VelocityStructWalk"], [5, 1, 1, "", "acceptance_criterion"], [5, 1, 1, "", "angular_bin"], [5, 1, 1, "", "do_weighted_binning"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "attribute", "Python attribute"]}, "titleterms": {"exampl": 0, "n": 0, "bodi": 0, "simul": 0, "initi": 0, "condit": 0, "stepper": 0, "function": 0, "main": 0, "loop": 0, "analysi": 0, "feedback": 1, "support": 1, "contribut": 1, "api": 2, "document": [2, 3], "welcom": 3, "pytreegrav": [3, 5], "": 3, "content": [3, 5], "indic": 3, "tabl": 3, "src": 4, "packag": 5, "submodul": 5, "bruteforc": 5, "modul": [5, 6], "dynamic_tre": 5, "frontend": 5, "kernel": 5, "octre": 5, "treewalk": 5, "setup": 6, "instal": 7, "requir": 7, "latest": 7, "stabl": 7, "releas": 7, "from": 7, "sourc": 7, "test": 7, "quickstart": 8, "what": 8, "i": 8, "want": 8, "evalu": 8, "field": 8, "differ": 8, "point": 8, "than": 8, "where": 8, "particl": 8, "ar": 8}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"Example: N-body simulation": [[0, "example-n-body-simulation"]], "Initial Conditions": [[0, "initial-conditions"]], "Stepper function": [[0, "stepper-function"]], "Main simulation loop": [[0, "main-simulation-loop"]], "Analysis": [[0, "analysis"]], "Feedback, Support, and Contributions": [[1, "feedback-support-and-contributions"]], "API Documentation": [[2, "api-documentation"]], "Welcome to pytreegrav\u2019s documentation!": [[3, "welcome-to-pytreegrav-s-documentation"]], "Contents:": [[3, null]], "Indices and tables": [[3, "indices-and-tables"]], "src": [[4, "src"]], "pytreegrav package": [[5, "pytreegrav-package"]], "Submodules": [[5, "submodules"]], "pytreegrav.bruteforce module": [[5, "module-pytreegrav.bruteforce"]], "pytreegrav.dynamic_tree module": [[5, "module-pytreegrav.dynamic_tree"]], "pytreegrav.frontend module": [[5, "module-pytreegrav.frontend"]], "pytreegrav.kernel module": [[5, "module-pytreegrav.kernel"]], "pytreegrav.octree module": [[5, "module-pytreegrav.octree"]], "pytreegrav.treewalk module": [[5, "module-pytreegrav.treewalk"]], "Module contents": [[5, "module-pytreegrav"]], "Installation": [[7, "installation"]], "Requirements": [[7, "requirements"]], "Installing the latest stable release": [[7, "installing-the-latest-stable-release"]], "Install from source": [[7, "install-from-source"]], "Testing": [[7, "testing"]], "Quickstart": [[8, "quickstart"]], "What if I want to evaluate the fields at different points than where the particles are?": [[8, "what-if-i-want-to-evaluate-the-fields-at-different-points-than-where-the-particles-are"]], "setup module": [[6, "setup-module"]]}, "indexentries": {}}) \ No newline at end of file diff --git a/docs/build/html/setup.html b/docs/build/html/setup.html deleted file mode 100644 index 88c7480..0000000 --- a/docs/build/html/setup.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - setup module — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

setup module

-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/usage/installation.html b/docs/build/html/usage/installation.html deleted file mode 100644 index ce71c6d..0000000 --- a/docs/build/html/usage/installation.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - Installation — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Installation

-

The below will help you quickly install pytreegrav.

-
-

Requirements

-

You will need a working Python 3.x installation; we recommend installing Anaconda Python version 3.x. -You will also need to install the following packages:

-
-
    -
  • numpy

  • -
  • numba

  • -
-
-
-
-

Installing the latest stable release

-

Install the latest stable release with

-
pip install pytreegrav
-
-
-

This is the preferred way to install pytreegrav as it will -automatically install the necessary requirements and put Pytreegrav -into your ${PYTHONPATH} environment variable so you can -import it.

-
-
-

Install from source

-

Alternatively, you can install the latest version directly from the most up-to-date version -of the source-code by cloning/forking the GitHub repository

-
git clone https://github.com/mikegrudic/pytreegrav.git
-
-
-

Once you have the source, you can build pytreegrav (and add it to your environment) -by executing

-
python setup.py install
-
-
-

or

-
pip install -e .
-
-
-

in the top level directory. The required Python packages will automatically be -installed as well.

-

You can test your installation by looking for the pytreegrav -executable built by the installation

-
which pytreegrav
-
-
-

and by importing the pytreegrav Python frontend in Python

-
import pytreegrav
-
-
-
-
-

Testing

-

To test that the tree solver is working correctly, run

-
pytest
-
-
-

from the root directory of the package. This will run a basic test problem comparing the acceleration and potential from the tree and brute force solvers respectively, and check that the answers are within the expected tolerance.

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/usage/quickstart.html b/docs/build/html/usage/quickstart.html deleted file mode 100644 index 41b9802..0000000 --- a/docs/build/html/usage/quickstart.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - Quickstart — pytreegrav 1.2.1 documentation - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Quickstart

-

pytreegrav is a package for computing the gravitational potential and/or field of a set of particles. It includes methods for brute-force direction summation and for the fast, approximate Barnes-Hut treecode method. For the Barnes-Hut method we implement an oct-tree as a numba jitclass to achieve much higher peformance than the equivalent pure Python implementation.

-

First let’s import the stuff we want and generate some particle positions and masses - these would be your particle data for whatever your problem is.

-
import numpy as np
-from pytreegrav import Accel, Potential
-
-
-
N = 10**5 # number of particles
-x = np.random.rand(N,3) # positions randomly sampled in the unit cube
-m = np.repeat(1./N,N) # masses - let the system have unit mass
-h = np.repeat(0.01,N) # softening radii - these are optional, assumed 0 if not provided to the frontend functions
-
-
-

Now we can use the Accel and Potential functions to compute the gravitational field and potential at each particle position:

-
print(Accel(x,m,h))
-print(Potential(x,m,h))
-
-
-
[[-0.1521787   0.2958852  -0.30109005]
- [-0.50678204 -0.37489886 -1.0558666 ]
- [-0.24650087  0.95423467 -0.175074  ]
- ...
- [ 0.87868472 -1.28332176 -0.22718531]
- [-0.41962742  0.32372245 -1.31829084]
- [ 2.45127054  0.38292881  0.05820412]]
-[-2.35518057 -2.19299372 -2.28494218 ... -2.11783337 -2.1653377
- -1.80464695]
-
-
-

By default, pytreegrav will try to make the optimal choice between brute-force and tree methods for speed, but we can also force it to use one method or another. Let’s try both and compare their runtimes:

-
from time import time
-t = time()
-# tree gravitational acceleration
-accel_tree = Accel(x,m,h,method='tree')
-print("Tree accel runtime: %gs"%(time() - t)); t = time()
-
-accel_bruteforce = Accel(x,m,h,method='bruteforce')
-print("Brute force accel runtime: %gs"%(time() - t)); t = time()
-
-phi_tree = Potential(x,m,h,method='tree')
-print("Tree potential runtime: %gs"%(time() - t)); t = time()
-
-phi_bruteforce = Potential(x,m,h,method='bruteforce')
-print("Brute force potential runtime: %gs"%(time() - t)); t = time()
-
-
-
Tree accel runtime: 0.927745s
-Brute force accel runtime: 44.1175s
-Tree potential runtime: 0.802386s
-Brute force potential runtime: 20.0234s
-
-
-

As you can see, the tree-based methods can be much faster than the brute-force methods, especially for particle counts exceeding 10^4. Here’s an example of how much faster the treecode is when run on a Plummer sphere with a variable number of particles, on a single core of an Intel i9 9900k workstation:

-Benchmark -

But there’s no free lunch here: the tree methods are approximate. Let’s quantify the RMS errors of the stuff we just computed, compared to the exact brute-force solutions:

-
acc_error = np.sqrt(np.mean(np.sum((accel_tree-accel_bruteforce)**2,axis=1))) # RMS force error
-print("RMS force error: ", acc_error)
-phi_error = np.std(phi_tree - phi_bruteforce)
-print("RMS potential error: ", phi_error)
-
-
-
RMS force error:  0.006739311224338851
-RMS potential error:  0.0003888328578588027
-
-
-

The above errors are typical for default settings: ~1% force error and ~0.1% potential error. The error in the tree approximation is controlled by the Barnes-Hut opening angle theta, set to 0.7 by default. Smaller theta gives higher accuracy, but also runs slower:

-
thetas = 0.1,0.2,0.4,0.8 # different thetas to try
-for theta in thetas:
-    t = time()
-    accel_tree = Accel(x,m,h,method='tree',theta=theta)
-    acc_error = np.sqrt(np.mean(np.sum((accel_tree-accel_bruteforce)**2,axis=1)))
-    print("theta=%g Runtime: %gs RMS force error: %g"%(theta, time()-t, acc_error))
-
-
-
theta=0.1 Runtime: 63.1738s RMS force error: 3.78978e-05
-theta=0.2 Runtime: 14.3356s RMS force error: 0.000258755
-theta=0.4 Runtime: 2.91292s RMS force error: 0.00148698
-theta=0.8 Runtime: 0.724668s RMS force error: 0.0105937
-
-
-

Both brute-force and tree-based calculations can be parallelized across all available logical cores via OpenMP, by specifying parallel=True. This can speed things up considerably, with parallel scaling that will vary with your core and particle number:

-
from time import time
-t = time()
-# tree gravitational acceleration
-accel_tree = Accel(x,m,h,method='tree',parallel=True)
-print("Tree accel runtime in parallel: %gs"%(time() - t)); t = time()
-
-accel_bruteforce = Accel(x,m,h,method='bruteforce',parallel=True)
-print("Brute force accel runtime in parallel: %gs"%(time() - t)); t = time()
-
-phi_tree = Potential(x,m,h,method='tree',parallel=True)
-print("Tree potential runtime in parallel: %gs"%(time() - t)); t = time()
-
-phi_bruteforce = Potential(x,m,h,method='bruteforce',parallel=True)
-print("Brute force potential runtime in parallel: %gs"%(time() - t)); t = time()
-
-
-
Tree accel runtime in parallel: 0.222271s
-Brute force accel runtime in parallel: 7.25576s
-Tree potential runtime in parallel: 0.181393s
-Brute force potential runtime in parallel: 5.72611s
-
-
-
-

What if I want to evaluate the fields at different points than where the particles are?

-

We got you covered. The Target methods do exactly this: you specify separate sets of points for the particle positions and the field evaluation, and everything otherwise works exactly the same (including optional parallelization and choice of solver):

-
from pytreegrav import AccelTarget, PotentialTarget
-
-# generate a separate set of "target" positions where we want to know the potential and field
-N_target = 10**4
-x_target = np.random.rand(N_target,3)
-h_target = np.repeat(0.01,N_target) # optional "target" softening: this sets a floor on the softening length of all forces/potentials computed
-
-accel_tree = AccelTarget(x_target, x,m, h_target=h_target, h_source=h,method='tree') # we provide the points/masses/softenings we generated before as the "source" particles
-accel_bruteforce = AccelTarget(x_target,x,m,h_source=h,method='bruteforce')
-
-acc_error = np.sqrt(np.mean(np.sum((accel_tree-accel_bruteforce)**2,axis=1))) # RMS force error
-print("RMS force error: ", acc_error)
-
-phi_tree = PotentialTarget(x_target, x,m, h_target=h_target, h_source=h,method='tree') # we provide the points/masses/softenings we generated before as the "source" particles
-phi_bruteforce = PotentialTarget(x_target,x,m,h_target=h_target, h_source=h,method='bruteforce')
-
-phi_error = np.std(phi_tree - phi_bruteforce)
-print("RMS potential error: ", phi_error)
-
-
-
RMS force error:  0.006719983300560105
-RMS potential error:  0.0003873676304955059
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/src/pytreegrav/octree.py b/src/pytreegrav/octree.py index 298a930..a3e4c19 100644 --- a/src/pytreegrav/octree.py +++ b/src/pytreegrav/octree.py @@ -1,18 +1,9 @@ -from numba import ( - int32, - deferred_type, - optional, - float64, - boolean, - int64, - njit, - jit, - prange, - types, -) -from numba.experimental import jitclass +"""Implementation of the Octree jitclass""" + import numpy as np -from numpy import empty, empty_like, zeros, zeros_like, sqrt, ones, concatenate +from numpy import zeros, ones, concatenate +from numba import float64, boolean, int64, njit +from numba.experimental import jitclass spec = [ ("Sizes", float64[:]), # side length of tree nodes diff --git a/tests/tree_test.py b/tests/tree_test.py index 09fb771..79982c2 100644 --- a/tests/tree_test.py +++ b/tests/tree_test.py @@ -21,6 +21,6 @@ def test_answer(): print("RMS force error: ", acc_error) phi_error = np.std(phi_tree - phi_bruteforce) print("RMS potential error: ", phi_error) - + np.save("phi_error.npy",phi_tree-phi_bruteforce) assert acc_error < 0.02 assert phi_error < 0.02