Skip to main content

npsolve

Many numerical solvers (like those in scipy) provide candidate solutions as a numpy array. They often also require a numpy array as a return value (e.g. an array of derivatives) during the solution. These requirements can make it difficult to use an object oriented approach to performing the calculations.

The npsolve package is a small, simple package built on numpy and fastwire to make it easy to use object-oriented code for the calculation step for numerical solvers.

Basic usage tutorial

First, setup some classes that you want to do calculations with. We do this by using the add_var method to setup variables and their initial values.

import numpy as np
import npsolve

class Component1(npsolve.Partial):
    def __init__(self):
        super().__init__()
        self.add_var('position', init=0.1)
        self.add_var('velocity', init=0.3)
    
class Component2(npsolve.Partial):
    def __init__(self):
        super().__init__()
        self.add_var('force', init=-0.1)

Next override the set_vectors method to store views you might want. In this case, we'll just save the variables as attributes. Note that these are actually views, that are automatically updated by the solver. We'll do it differently with Component2.

class Component1(npsolve.Partial):
    def __init__(self):
        super().__init__()
        self.add_var('position', init=0.1)
        self.add_var('velocity', init=0.3)
    
    def set_vectors(self, state_dct, ret_dct):
        ''' Set some state views for use during calculations '''
        self.position = state_dct['position']
        self.velocity = state_dct['velocity']
        self.force = state_dct['force']
    

class Component2(npsolve.Partial):
    def __init__(self):
        super().__init__()
        self.add_var('force', init=-0.1)

Note that variables are made available to all Partial instances automatically.

Then, we'll tell them how to do the calculations. The step method is called automatically and expects a dictionary of return values (e.g. derivatives). A dictionary of the current state values is provided (again), but we're going to use the views we set in the set_vectors method.

class Component1(npsolve.Partial):
    def __init__(self):
        super().__init__()
        self.add_var('position', init=0.1)
        self.add_var('velocity', init=0.3)
    
    def set_vectors(self, state_dct, ret_dct):
        ''' Set some state views for use during calculations '''
        self.position = state_dct['position']
        self.velocity = state_dct['velocity']
        self.force = state_dct['force']
    
    def step(self, state_dct, *args):
        ''' Called by the solver at each time step 
        Calculate acceleration based on the 
        '''
        acceleration = 1.0 * self.force
        derivatives = {'position': self.velocity,
                       'velocity': acceleration}
        return derivatives
		

class Component2(npsolve.Partial):
    def __init__(self):
        super().__init__()
        self.add_var('force', init=-0.1)

    def calculate(self, state_dct, t):
        ''' Some arbitrary calculations based on current time t
        and the position at that time calculated in Component1.
        This returns a derivative for variable 'c'
        '''
        dc = 1.0 * np.cos(2*t) * state_dct['position']
        derivatives = {'force': dc}
        return derivatives
    
    def step(self, state_dct, t, *args):
        ''' Called by the solver at each time step '''
        return self.calculate(state_dct, t)
        
		

Now, we'll set up the solver. By default, Solvers have a step method that's ready to use, and after initialisation, the initial values set by the Partial classes are captured in the npsolve_initial_values attribute. By default, the Solver's step method returns a vector of all the return values, the same size as the Solver's npsolve_initial_values array.

from scipy.integrate import odeint

class Solver(npsolve.Solver):
    def solve(self):
        self.t_vec = np.linspace(0, 5, 1001)
        result = odeint(self.step, self.npsolve_initial_values, self.t_vec)
        return result

To run, we just have to instantiate the Solver before the Partials that use it, then call the npsolve_init method. It doesn't matter where in the code we create the Solver and Partial instances - they'll link up automatically through fastwire.

def run():
    s = Solver()
    c1 = Component1()
    c2 = Component2()
    s.npsolve_init()
    # Now we can run!
    res = s.solve()
    return res, s

Let's set up a plot to see the results. Use the npsolve_slices attribute of the Solver to get the right columns.

def plot(res, s):
    slices = s.npsolve_slices
    
    plt.plot(s.t_vec, res[:,slices['position']], label='position')
    plt.plot(s.t_vec, res[:,slices['velocity']], label='velocity')
    plt.plot(s.t_vec, res[:,slices['force']], label='force')
    plt.legend()

Run it and see what happens!

res, s = run()
plot(res, s)

Metadata

Release files for npsolve 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for npsolve 0.0.1
File Size Uploaded
npsolve-0.0.1.tar.gz 8.1 kB Details

Release files / npsolve-0.0.1.tar.gz

Download URL npsolve-0.0.1.tar.gz
Size 8.1 kB
Tags Source
SHA-256 checksum
How to use checksums
7bfea301fb57f62a3f26764acfec5cee7429b0a6d754dfed7b2bc4704131a1e9
BLAKE2b-256 checksum
How to use checksums
2e300dc69d9c7b0cf1ead4e7aec7ef00c7e7d87f26a90e1765a157bc26ddf122
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.4

Release history Release notifications | RSS feed

1.0.4

2 release files

1.0.3

2 release files

1.0.0

1 release file

0.3.1

1 release file

0.2.1

2 release files

0.2.0

1 release file

0.1.2

1 release file

0.1.1

1 release file

0.1.0

1 release file

0.0.9

1 release file

0.0.8

1 release file

0.0.7

1 release file

0.0.6

1 release file

0.0.5

1 release file

0.0.4

1 release file

0.0.2

1 release file

This release

0.0.1 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page