Skip to main content

Runge-Kutta ODE Integrator Implemented in Cython and Numba.

Project description

CyRK

DOI Python Version 3.8-3.12 Code Coverage
Windows Tests MacOS Tests Ubuntu Tests

CyRK Version 0.11.0 Alpha

Runge-Kutta ODE Integrator Implemented in Cython and Numba

CyRK provides fast integration tools to solve systems of ODEs using an adaptive time stepping scheme. CyRK can accept differential equations that are written in pure Python, njited numba, or cython-based cdef functions. These kinds of functions are generally easier to implement than pure c functions and can be used in existing Python software. Using CyRK can speed up development time while avoiding the slow performance that comes with using pure Python-based solvers like SciPy's solve_ivp.

The purpose of this package is to provide some functionality of scipy's solve_ivp with greatly improved performance.

Currently, CyRK's numba-based (njit-safe) implementation is 10-140x faster than scipy's solve_ivp function. The cython-based pysolve_ivp function that works with python (or njit'd) functions is 20-50x faster than scipy. The cython-based cysolver_ivp function that works with cython-based cdef functions is 50-700+x faster than scipy.

An additional benefit of the two cython implementations is that they are pre-compiled. This avoids most of the start-up performance hit experienced by just-in-time compilers like numba.

CyRK Performance Graphic

Installation

CyRK has been tested on Python 3.8--3.12; Windows, Ubuntu, and MacOS.

To install simply open a terminal and call:

pip install CyRK

If not installing from a wheel, CyRK will attempt to install Cython and Numpy in order to compile the source code. A "C++ 14" compatible compiler is required. Compiling CyRK has been tested on the latest versions of Windows, Ubuntu, and MacOS. Your milage may vary if you are using a older or different operating system. After everything has been compiled, cython will be uninstalled and CyRK's runtime dependencies (see the pyproject.toml file for the latest list) will be installed instead.

A new installation of CyRK can be tested quickly by running the following from a python console.

from CyRK import test_pysolver, test_cysolver, test_nbrk
test_pysolver()
# Should see "CyRK's PySolver was tested successfully."
test_cysolver()
# Should see "CyRK's CySolver was tested successfully."
test_nbrk()
# Should see "CyRK's nbrk_ode was tested successfully."

Troubleshooting Installation and Runtime Problems

Please report installation issues. We will work on a fix and/or add workaround information here.

  • If you see a "Can not load module: CyRK.cy" or similar error then the cython extensions likely did not compile during installation. Try running pip install CyRK --no-binary="CyRK" to force python to recompile the cython extensions locally (rather than via a prebuilt wheel).
  • On MacOS: If you run into problems installing CyRK then reinstall using the verbose flag (pip install -v .) to look at the installation log. If you see an error that looks like "clang: error: unsupported option '-fopenmp'" then you may have a problem with your llvm or libomp libraries. It is recommended that you install CyRK in an Anaconda environment with the following packages conda install numpy scipy cython llvm-openmp. See more discussion here and the steps taken here.
  • CyRK has a number of runtime status codes which can be used to help determine what failed during integration. Learn more about these codes https://github.com/jrenaud90/CyRK/blob/main/Documentation/Status%20and%20Error%20Codes.md.

Development and Testing Dependencies

If you intend to work on CyRK's code base you will want to install the following dependencies in order to run CyRK's test suite and experimental notebooks.

conda install pytest scipy matplotlib jupyter

conda install can be replaced with pip install if you prefer.

Using CyRK

The following code can be found in a Jupyter Notebook called "Getting Started.ipynb" in the "Demos" folder.

Note: some older CyRK functions like cyrk_ode and CySolver class-based method have been deprecated and removed. Read more in "Documentation/Deprecations.md". CyRK's API is similar to SciPy's solve_ivp function. A differential equation can be defined in python such as:

# For even more speed up you can use numba's njit to compile the diffeq
from numba import njit
@njit
def diffeq_nb(t, y):
    dy = np.empty_like(y)
    dy[0] = (1. - 0.01 * y[1]) * y[0]
    dy[1] = (0.02 * y[0] - 1.) * y[1]
    return dy

Numba-based nbsolve_ivp

Future Development Note: The numba-based solver is currently in a feature-locked state and will not receive new features (as of CyRK v0.9.0). The reason for this is because it uses a different backend than the rest of CyRK and is not as flexible or easy to expand without significant code duplication. Please see GitHub Issue: TBD to see the status of this new numba-based solver or share your interest in continued development.

The system of ODEs can then be solved using CyRK's numba solver by,

import numpy as np
from CyRK import nbsolve_ivp

initial_conds = np.asarray((20., 20.), dtype=np.float64, order='C')
time_span = (0., 50.)
rtol = 1.0e-7
atol = 1.0e-8

result = \
    nbsolve_ivp(diffeq_nb, time_span, initial_conds, rk_method=1, rtol=rtol, atol=atol)

print("Was Integration was successful?", result.success)
print(result.message)
print("Size of solution: ", result.size)
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(result.t, result.y[0], c='r')
ax.plot(result.t, result.y[1], c='b')

nbsolve_ivp Arguments

nbsolve_ivp(
    diffeq: callable,                  # Differential equation defined as a numba.njit'd python function
    t_span: Tuple[float, float],       # Python tuple of floats defining the start and stop points for integration
    y0: np.ndarray,                    # Numpy array defining initial y0 conditions.
    args: tuple = tuple(),             # Python Tuple of additional args passed to the differential equation. These can be any njit-safe object.
    rtol: float = 1.e-3,               # Relative tolerance used to control integration error.
    atol: float = 1.e-6,               # Absolute tolerance (near 0) used to control integration error.
    rtols: np.ndarray = EMPTY_ARR,     # Overrides rtol if provided. Array of floats of rtols if you'd like a different rtol for each y.
    atols: np.ndarray = EMPTY_ARR,     # Overrides atol if provided. Array of floats of atols if you'd like a different atol for each y.
    max_step: float = np.inf,          # Maximum allowed step size.
    first_step: float = None,          # Initial step size. If set to 0.0 then CyRK will guess a good step size.
    rk_method: int = 1,                # Integration method. Current options: 0 == RK23, 1 == RK45, 2 == DOP853
    t_eval: np.ndarray = EMPTY_ARR,    # `nbsolve_ivp` uses an adaptive time stepping protocol based on the recent error at each step. This results in a final non-uniform time domain of variable size. If the user would like the results at specific time steps then they can provide a np.ndarray array at the desired steps via `t_eval`. The solver will then interpolate the results to fit this 
    capture_extra: bool = False,       # Set to True if the diffeq is designed to provide extra outputs.
    interpolate_extra: bool = False,   # See "Documentation/Extra Output.md" for details.
    max_num_steps: int = 0             # Maximum number of steps allowed. If exceeded then integration will fail. 0 (the default) turns this off.
    )

Python wrapped pysolve_ivp

CyRK's main integration functions utilize a C++ backend system which is then wrapped and accessible to Python via Cython. The easiest way to interface with this system is through CyRK's pysolve_ivp function. It follows a very similar format to both nbsolve_ivp and Scipy's solve_ivp. First you must build a function in Python. This could look the same as the function described above for nbsolve_ivp (see diffeq_nb). However, there are a few advantages that pysolve_ivp provides over nbsolve_ivp:

  1. It accepts both functions that use numba's njit wrapper (as diffeq_nb did above) or pure Python functions (nbsolve_ivp only accepts njit'd functions).
  2. You can provide the resultant dy/dt as an argument which can provide a significant performance boost.

Utilizing point 2, we can re-write the differential equation function as,

# Note if using this format, `dy` must be the first argument. Additionally, a special flag must be set to True when calling pysolve_ivp, see below.
def cy_diffeq(dy, t, y):
    dy[0] = (1. - 0.01 * y[1]) * y[0]
    dy[1] = (0.02 * y[0] - 1.) * y[1]

Since this function is not using any special functions we could easily wrap it with njit for additional performance boost: cy_diffeq = njit(cy_diffeq).

Once you have built your function the procedure to solve it is:

import numpy as np
from CyRK import pysolve_ivp

initial_conds = np.asarray((20., 20.), dtype=np.complex128, order='C')
time_span = (0., 50.)
rtol = 1.0e-7
atol = 1.0e-8

result = \
    pysolve_ivp(cy_diffeq, time_span, initial_conds, method="RK45", rtol=rtol, atol=atol,
                # Note if you did build a differential equation that has `dy` as the first argument then you must pass the following flag as `True`.
                # You could easily pass the `diffeq_nb` example which returns dy. You would just set this flag to False (and experience a hit to your performance).
                pass_dy_as_arg=True)

print("Was Integration was successful?", result.success)
print(result.message)
print("Size of solution: ", result.size)
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(result.t, result.y[0], c='r')
ax.plot(result.t, result.y[1], c='b')

pysolve_ivp Arguments

def pysolve_ivp(
        object py_diffeq,            # Differential equation defined as a python function
        tuple time_span,             # Python tuple of floats defining the start and stop points for integration
        double[::1] y0,              # Numpy array defining initial y0 conditions.
        str method = 'RK45',         # Integration method. Current options are: RK23, RK45, DOP853
        double[::1] t_eval = None,   # Array of time steps at which to save data. If not provided then all adaptive time steps will be saved. There is a slight performance hit using this feature.
        bint dense_output = False,   # If True, then dense interpolators will be saved to the solution. This allows a user to call solution as if a function (in time).
        tuple args = None,           # Python Tuple of additional args passed to the differential equation. These can be any python object.
        size_t expected_size = 0,    # Expected size of the solution. There is a slight performance improvement if selecting the the exact or slightly more time steps than the adaptive stepper will require (if you happen to know this ahead of time).
        unsigned int num_extra = 0,  # Number of extra outputs you want to capture during integration. There is a performance hit if this is used in conjunction with t_eval or dense_output.
        double first_step = 0.0,     # Initial step size. If set to 0.0 then CyRK will guess a good step size.
        double max_step = INF,       # Maximum allowed step size.
        rtol = 1.0e-3,               # Relative tolerance used to control integration error. This can be provided as a numpy array if you'd like a different rtol for each y.
        atol = 1.0e-6,               # Absolute tolerance (near 0) used to control integration error. This can be provided as a numpy array if you'd like a different atol for each y.
        size_t max_num_steps = 0,    # Maximum number of steps allowed. If exceeded then integration will fail. 0 (the default) turns this off.
        size_t max_ram_MB = 2000,    # Maximum amount of system memory the integrator is allowed to use. If this is exceeded then integration will fail.
        bint pass_dy_as_arg = False  # Flag if differential equation returns dy (False) or is passed dy as the _first_ argument (True).
        ):

Pure Cython cysolve_ivp

A final method is provided to users in the form of cysolve_ivp. This function can only be accessed and used by code written in Cython. Details about how to setup and use Cython can be found on the project's website. The below code examples assume you are running the code in a Jupyter Notebook.

cysolve_ivp has a slightly different interface than nbsolve_ivp and pysolve_ivp as it only accepts C types. For that reason, python functions will not work with cysolve_ivp. While developing in Cython is more challenging than Python, there is a huge performance advantage (cysolve_ivp is roughly 5x faster than pysolve_ivp and 700x faster than scipy's solve_ivp). Below is a demonstration of how it can be used.

First a pure Cython file (written as a Jupyter notebook).

%%cython --force 
# distutils: language = c++
# cython: boundscheck=False, wraparound=False, nonecheck=False, cdivision=True, initializedcheck=False

import numpy as np
cimport numpy as np
np.import_array()

# Note the "distutils" and "cython" headers above are functional. They tell cython how to compile the code. In this case we want to use C++ and to turn off several safety checks (which improve performance).

# The cython diffeq is much less flexible than the others described above. It must follow this format, including the type information. 
# Currently, CyRK only allows additional arguments to be passed in as a double array pointer (they all must be of type double). Mixed type args will be explored in the future if there is demand for it (make a GitHub issue if you'd like to see this feature!).
# The "noexcept nogil" tells cython that the Python Global Interpretor Lock is not required, and that no exceptions should be raised by the code within this function (both improve performance).
# If you do need the gil for your differential equation then you must use the `cysolve_ivp_gil` function instead of `cysolve_ivp`

# Import the required functions from CyRK
from CyRK cimport cysolve_ivp, DiffeqFuncType, WrapCySolverResult, CySolveOutput, PreEvalFunc

# Note that currently you must provide the "const void* args, PreEvalFunc pre_eval_func" as inputs even if they are unused.
# See "Advanced CySolver.md" in the documentation for information about these parameters.
cdef void cython_diffeq(double* dy, double t, double* y, const void* args, PreEvalFunc pre_eval_func) noexcept nogil:
    
    # Unpack args
    # CySolver assumes an arbitrary data type for additional arguments. So we must cast them to the array of 
    # doubles that we want to use for this equation
    cdef double* args_as_dbls = <double*>args
    cdef double a = args_as_dbls[0]
    cdef double b = args_as_dbls[1]
    
    # Build Coeffs
    cdef double coeff_1 = (1. - a * y[1])
    cdef double coeff_2 = (b * y[0] - 1.)
    
    # Store results
    dy[0] = coeff_1 * y[0]
    dy[1] = coeff_2 * y[1]
    # We can also capture additional output with cysolve_ivp.
    dy[2] = coeff_1
    dy[3] = coeff_2

# Import the required functions from CyRK
from CyRK cimport cysolve_ivp, DiffeqFuncType, WrapCySolverResult, CySolveOutput

# Let's get the integration number for the RK45 method
from CyRK cimport RK45_METHOD_INT

# Now let's import cysolve_ivp and build a function that runs it. We will not make this function `cdef` like the diffeq was. That way we can run it from python (this is not a requirement. If you want you can do everything within Cython).
# Since this function is not `cdef` we can use Python types for its input. We just need to clean them up and convert them to pure C before we call cysolve_ivp.
def run_cysolver(tuple t_span, double[::1] y0):
    
    # Cast our diffeq to the accepted format
    cdef DiffeqFuncType diffeq = cython_diffeq
    
    # Convert the python user input to pure C types
    cdef double* y0_ptr       = &y0[0]
    cdef unsigned int num_y   = len(y0)
    cdef double[2] t_span_arr = [t_span[0], t_span[1]]
    cdef double* t_span_ptr   = &t_span_arr[0]

    # Assume constant args
    cdef double[2] args   = [0.01, 0.02]
    cdef double* args_dbl_ptr = &args[0]
    # Need to cast the arg double pointer to void
    cdef void* args_ptr = <void*>args_dbl_ptr

    # Run the integrator!
    cdef CySolveOutput result = cysolve_ivp(
        diffeq,
        t_span_ptr,
        y0_ptr,
        num_y,
        method = RK45_METHOD_INT, # Integration method
        rtol = 1.0e-7,
        atol = 1.0e-8,
        args_ptr = args_ptr,
        num_extra = 2
    )

    # The CySolveOutput is not accesible via Python. We need to wrap it first
    cdef WrapCySolverResult pysafe_result = WrapCySolverResult()
    pysafe_result.set_cyresult_pointer(result)

    return pysafe_result

Now we can make a python script that calls our new cythonized wrapper function. Everything below is in pure Python.

# Assume we are working in a Jupyter notebook so we don't need to import `run_cysolver` if it was defined in an earlier cell.
# from my_cython_code import run_cysolver

import numpy as np
initial_conds = np.asarray((20., 20.), dtype=np.float64, order='C')
time_span = (0., 50.)

result = run_cysolver(time_span, initial_conds)

print("Was Integration was successful?", result.success)
print(result.message)
print("Size of solution: ", result.size)
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(result.t, result.y[0], c='r')
ax.plot(result.t, result.y[1], c='b')

# Can also plot the extra output. They are small for this example so scaling them up by 100
ax.plot(result.t, 100*result.y[2], c='green', ls=':')
ax.plot(result.t, 100*result.y[3], c='purple', ls=':')

There is a lot more you can do to interface with CyRK's C++ backend and fully optimize the integrators to your needs. These details will be documented in "Documentation/Advanced CySolver.md".

cysolve_ivp and cysolve_ivp_gil Arguments

cdef shared_ptr[CySolverResult] cysolve_ivp(
    DiffeqFuncType diffeq_ptr,        # Differential equation defined as a cython function
    double* t_span_ptr,               # Pointer to array (size 2) of floats defining the start and stop points for integration
    double* y0_ptr,                   # Pointer to array defining initial y0 conditions.
    unsigned int num_y,               # Size of y0_ptr array.
    unsigned int method = 1,          # Integration method. Current options: 0 == RK23, 1 == RK45, 2 == DOP853
    double rtol = 1.0e-3,             # Relative tolerance used to control integration error.
    double atol = 1.0e-6,             # Absolute tolerance (near 0) used to control integration error.
    void* args_ptr = NULL,            # Pointer to array of additional arguments passed to the diffeq. See "Advanced CySolver.md" for more details.
    unsigned int num_extra = 0,       # Number of extra outputs you want to capture during integration. There is a performance hit if this is used in conjunction with t_eval or dense_output.
    size_t max_num_steps = 0,         # Maximum number of steps allowed. If exceeded then integration will fail. 0 (the default) turns this off.
    size_t max_ram_MB = 2000,         # Maximum amount of system memory the integrator is allowed to use. If this is exceeded then integration will fail.
    bint dense_output = False,        # If True, then dense interpolators will be saved to the solution. This allows a user to call solution as if a function (in time).
    double* t_eval = NULL,            # Pointer to an array of time steps at which to save data. If not provided then all adaptive time steps will be saved. There is a slight performance hit using this feature.
    size_t len_t_eval = 0,            # Size of t_eval.
    PreEvalFunc pre_eval_func = NULL  # Optional additional function that is called within `diffeq_ptr` using current `t` and `y`. See "Advanced CySolver.md" for more details.
    double* rtols_ptr = NULL,         # Overrides rtol if provided. Pointer to array of floats of rtols if you'd like a different rtol for each y.
    double* atols_ptr = NULL,         # Overrides atol if provided. Pointer to array of floats of atols if you'd like a different atol for each y.
    double max_step = MAX_STEP,       # Maximum allowed step size.
    double first_step = 0.0           # Initial step size. If set to 0.0 then CyRK will guess a good step size.
    size_t expected_size = 0,         # Expected size of the solution. There is a slight performance improvement if selecting the the exact or slightly more time steps than the adaptive stepper will require (if you happen to know this ahead of time).
    )

Limitations and Known Issues

  • Issue 30: CyRK's cysolve_ivp and pysolve_ivp does not allow for complex-valued dependent variables.

Citing CyRK

It is great to see CyRK used in other software or in scientific studies. We ask that you cite back to CyRK's GitHub website so interested parties can learn about this package. It would also be great to hear about the work being done with CyRK, so get in touch!

Renaud, Joe P. (2022). CyRK - ODE Integrator Implemented in Cython and Numba. Zenodo. https://doi.org/10.5281/zenodo.7093266

In addition to citing CyRK, please consider citing SciPy and its references for the specific Runge-Kutta model that was used in your work. CyRK is largely an adaptation of SciPy's functionality. Find more details here.

Pauli Virtanen, Ralf Gommers, Travis E. Oliphant, Matt Haberland, Tyler Reddy, David Cournapeau, Evgeni Burovski, Pearu Peterson, Warren Weckesser, Jonathan Bright, Stéfan J. van der Walt, Matthew Brett, Joshua Wilson, K. Jarrod Millman, Nikolay Mayorov, Andrew R. J. Nelson, Eric Jones, Robert Kern, Eric Larson, CJ Carey, İlhan Polat, Yu Feng, Eric W. Moore, Jake VanderPlas, Denis Laxalde, Josef Perktold, Robert Cimrman, Ian Henriksen, E.A. Quintero, Charles R Harris, Anne M. Archibald, Antônio H. Ribeiro, Fabian Pedregosa, Paul van Mulbregt, and SciPy 1.0 Contributors. (2020) SciPy 1.0: Fundamental Algorithms for Scientific Computing in Python. Nature Methods, 17(3), 261-272.

Contribute to CyRK

Please look here for an up-to-date list of contributors to the CyRK package.

CyRK is open-source and is distributed under the Creative Commons Attribution-ShareAlike 4.0 International license. You are welcome to fork this repository and make any edits with attribution back to this project (please see the Citing CyRK section).

  • We encourage users to report bugs or feature requests using GitHub Issues.
  • If you would like to contribute but don't know where to start, check out the good first issue tag on GitHub.
  • Users are welcome to submit pull requests and should feel free to create them before the final code is completed so that feedback and suggestions can be given early on.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cyrk-0.11.1.tar.gz (970.6 kB view details)

Uploaded Source

Built Distributions

CyRK-0.11.1-cp312-cp312-win_amd64.whl (1.5 MB view details)

Uploaded CPython 3.12 Windows x86-64

CyRK-0.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

CyRK-0.11.1-cp312-cp312-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

CyRK-0.11.1-cp312-cp312-macosx_10_15_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.12 macOS 10.15+ x86-64

CyRK-0.11.1-cp311-cp311-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.11 Windows x86-64

CyRK-0.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

CyRK-0.11.1-cp311-cp311-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

CyRK-0.11.1-cp311-cp311-macosx_10_15_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.11 macOS 10.15+ x86-64

CyRK-0.11.1-cp310-cp310-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.10 Windows x86-64

CyRK-0.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

CyRK-0.11.1-cp310-cp310-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

CyRK-0.11.1-cp310-cp310-macosx_10_15_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.10 macOS 10.15+ x86-64

CyRK-0.11.1-cp39-cp39-win_amd64.whl (1.5 MB view details)

Uploaded CPython 3.9 Windows x86-64

CyRK-0.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

CyRK-0.11.1-cp39-cp39-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

CyRK-0.11.1-cp39-cp39-macosx_10_15_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.9 macOS 10.15+ x86-64

CyRK-0.11.1-cp38-cp38-win_amd64.whl (1.5 MB view details)

Uploaded CPython 3.8 Windows x86-64

CyRK-0.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

CyRK-0.11.1-cp38-cp38-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

CyRK-0.11.1-cp38-cp38-macosx_10_15_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.8 macOS 10.15+ x86-64

File details

Details for the file cyrk-0.11.1.tar.gz.

File metadata

  • Download URL: cyrk-0.11.1.tar.gz
  • Upload date:
  • Size: 970.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for cyrk-0.11.1.tar.gz
Algorithm Hash digest
SHA256 a17cf267264e25db31600d580a3df705718556c6377e8f9795d335ba22ecbe99
MD5 121e09ad3fd2dbc6e9617cf88a9884c9
BLAKE2b-256 e2b213e1321e4ddf16a17aa2cfbdff94c96ef153c7125abc4c04e43d80379fed

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: CyRK-0.11.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for CyRK-0.11.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 681b1cd5d131a8459e17ee41a089408c2d38a8aafef4cb5b5b73e66294d3bfcd
MD5 e12b6dcac6ee557edffa31280f7cde9b
BLAKE2b-256 48ff620d1fdedd5adeb8065b31dc4b6af511f40bd7ca4b12e4b2a9b2cd7d7ed7

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 79ba0d50bd75cafe2a0aac9fab829fb03253d4e26e2445339ecfa5922205c8a3
MD5 140a3ec125edac2587f0c42d27436ff6
BLAKE2b-256 bde27fce5a0d70c9a9cb385c10d7039d07dea9e9273da58690a17b3fd72afb7d

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 550637cd424f4f8baf94e98bb29701c19f2e90ce03ac8f3d1d4cfc8084bd9aa8
MD5 78cce236cdf7d2fb23b7355edb2cd3ac
BLAKE2b-256 91b9e2114a4c7a68b79a5582ed5b5ff02d45cd9807812665695d31fe665fc99b

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp312-cp312-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp312-cp312-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 22f0f672d37a1d9d3935cf9ca3dd4b170696101b1d6a0aa0316e13e87df7cc4f
MD5 502bd4418d397b7aa55a810104947e16
BLAKE2b-256 0e59394ea1fc28a24987c8ed19a4f183d8a3a1f31ff5981121c4ba2ab07390aa

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: CyRK-0.11.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for CyRK-0.11.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 7934603c60b4182a620650552fc41fcd47b3bc06750ab60dc3fc7e85e84fcf07
MD5 b532a8dadb789e33c95004481cd179fe
BLAKE2b-256 4be8a46f8fdf9387d25c018344f46d27b4e15c357fd2b9b6cea9857dbd9c9087

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c00e4e01cbcee6d722489683a37d3d89dfbe34ac553fa3198e7175d57b2bbd3d
MD5 f0005c303987fd3b760fd3e9f1cbc19e
BLAKE2b-256 02f7cfa6dc852a2266be9bc8f176ea9895cbc6e50a37d363e67f72de025b0861

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5887452e0e95f3755c77cf056bf0a25295852ab3618a86a980792c6337f7c237
MD5 c76e3eb1e8aac7a5080fc100eff60d06
BLAKE2b-256 fd58c5536afec30667a50ba0aea2b0d76e286e87b86a92da440ad4cf60958147

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp311-cp311-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp311-cp311-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 80f8c69ceb317b532ab1cebb4222f84eaf2073215a54b746c5797a52399a3a94
MD5 770609a54414fcad4165b7ab2db5633b
BLAKE2b-256 e69fcf028114dc54a36395fbd0ab031ffdb6382572f62931f73d923b79995ac2

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: CyRK-0.11.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for CyRK-0.11.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 31f3ce03cd75f4aceac157348ad07fd7094c111f2c9db95fcaf5bafc188edc52
MD5 ee31b2d1617253a13ad8bd6e421042a0
BLAKE2b-256 5d54824a5b734c79527eb42981b26d599379fef0713c96a0250f9e548ff5a880

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 10d6c0eef2ab6d565c301703fac45bb8af3327d90abf5c679b9355d1862486a9
MD5 eb121b851d1b4906b2dd46572b9320de
BLAKE2b-256 bec9c87f4437bd0397014f02e6f321692fd8459cca5adb268da07029e1fba246

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cece8073afbc0d20e46f82aaf06c58f4084f3d7b0391d951de89de0af79c3bc6
MD5 f59caaf1be7e8d4cd71968621cffdf13
BLAKE2b-256 524c3ea7ca93759fceadd04e0506a9dc6428cee08d35d1cf61cb6fde6be86e9d

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp310-cp310-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp310-cp310-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 ca02b5e2ea7ce704b80ae01f674724b38ea49068a338f9006a7386ba995212bd
MD5 b23e53205e5d054a9f5e5c1ca6061d12
BLAKE2b-256 57e81d6ac069fdaf32c5f21c2acefb2b464584d841303bb653295b147ae6a8aa

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: CyRK-0.11.1-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for CyRK-0.11.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 bb681b476f8ecb3bd8b533843d32c1879487725b47ba67baaf35fef194ae3b49
MD5 3237b125f615d48d5e8d8c6d6e59174f
BLAKE2b-256 4cda8ba9681608bf31000aae10c136b47fd1c54ee57fbdbbae02df29bd554a5a

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0cead2a0e3cb99b5626cb2532430c193d0eb590725e9ee8450e40489fda7ad06
MD5 37db13f5d587adf3e67c12dc6b1d3707
BLAKE2b-256 7246c4a0d48d11fff2d8a942bdba9872e3ee0b2a5f3e968dabe4f56ab60790dd

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7fb1d34c2bde6228040ab1c6641f06752aafe1d6dcfaf1db3a016173e4df99a4
MD5 c1add528b7aa07fe1ea39485bad18093
BLAKE2b-256 8da5c0fefcef38f246b0575f747c4307a932c46af8fa7abdc8eb80e561897964

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp39-cp39-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp39-cp39-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 7cf1d9b81cbe4e67281a85542afdb1810516d650bbce524a6cf03e3408bfa60c
MD5 08a1c21a20c0e939687619f107c69fcd
BLAKE2b-256 ee2291107e9bcd02c62dc91ad5bc5044128bd6f19d484f7985e39977c1f7e124

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: CyRK-0.11.1-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for CyRK-0.11.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 e1e0347571fc3cc60b045692fedcf5aa4b63f4da95797cc00ce53ff1a0bd02c2
MD5 dffc74137b43b39b13aa6acf50ca13fd
BLAKE2b-256 77505be7043577b3129cd2f45127acb0f43f1b9ed035665894fee2b5550a10a7

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d275f54fac79ac93518d6ae1d27d008bdb7dd800ec286498c00bfd00e1fbb909
MD5 f0766cf071fd11b3f0d71f4985fd2a7d
BLAKE2b-256 f3a642a6c00c3da2491fbdc34ab4c95062ca94c953e1ae630c4e3f4e229129f2

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 210b21a5fb2ae72a02dca9dddd37fb541a8f611ca386e20e395bc40d010d8699
MD5 a5bc4e2ab0200219d92a13fcdb384254
BLAKE2b-256 0936c1262d639dd4125307055c9a7ac114c13daa31d7ac6625a966445c66491a

See more details on using hashes here.

File details

Details for the file CyRK-0.11.1-cp38-cp38-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for CyRK-0.11.1-cp38-cp38-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 e2165bdc41fae8c30c9beb71435a4b8f6725f2ace5ca98bb79fe73586b0c4c46
MD5 ec7b7ad1cf8f54c9a1f8d4ded499e65a
BLAKE2b-256 e4801afa8a0b03a54c390dbb4f1935aa41b38b78891ccaa2dcef5a066e5937e9

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page