Skip to content

Commit 15a9a50

Browse files
committed
Updating modsim
1 parent 0de9c93 commit 15a9a50

1 file changed

Lines changed: 89 additions & 6 deletions

File tree

code/modsim.py

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import pint
2727
UNITS = pint.UnitRegistry()
28+
Quantity = UNITS.Quantity
2829

2930
from numpy import sqrt, array, linspace, pi
3031

@@ -37,6 +38,7 @@
3738
from scipy.interpolate import interp1d
3839
from scipy.integrate import odeint
3940
from scipy.optimize import leastsq
41+
from scipy.optimize import minimize_scalar
4042

4143
from time import sleep
4244

@@ -62,7 +64,7 @@ def linspace(start, stop, num=50, **kwargs):
6264
return array
6365

6466

65-
def linrange(start, stop=None, step=1, **kwargs):
67+
def linrange(start=0, stop=None, step=1, **kwargs):
6668
"""Returns evenly spaced samples over the interval [start, stop].
6769
6870
start: number or Quantity
@@ -158,6 +160,67 @@ def units_on():
158160
UNITS._get_dimensionality = SAVED_PINT_METHOD
159161

160162

163+
164+
def min_bounded(min_func, bounds, *args, **options):
165+
"""Finds the input value that minimizes `min_func`.
166+
167+
min_func: computes the function to be minimized
168+
bounds: sequence of two values, lower and upper bounds of the
169+
range to be searched
170+
args: any additional positional arguments are passed to min_func
171+
options: any keyword arguments are passed as options to minimize_scalar
172+
173+
returns: OptimizeResult object
174+
(see https://docs.scipy.org/doc/scipy/
175+
reference/generated/scipy.optimize.minimize_scalar.html)
176+
"""
177+
try:
178+
midpoint = np.mean(bounds)
179+
min_func(midpoint, *args)
180+
except Exception as e:
181+
msg = """Before running scipy.integrate.odeint, I tried
182+
running the slope function you provided with the
183+
initial conditions in system and t=0, and I got
184+
the following error:"""
185+
logger.error(msg)
186+
raise(e)
187+
188+
underride(options, xatol=1e-3)
189+
190+
res = minimize_scalar(min_func,
191+
bracket=bounds,
192+
bounds=bounds,
193+
args=args,
194+
method='bounded',
195+
options=options)
196+
197+
if not res.success:
198+
msg = """scipy.optimize.minimize_scalar did not succeed.
199+
The message it returns is %s""" % res.message
200+
raise Exception(msg)
201+
202+
return res
203+
204+
205+
def max_bounded(max_func, bounds, *args, **options):
206+
"""Finds the input value that maximizes `max_func`.
207+
208+
min_func: computes the function to be maximized
209+
bounds: sequence of two values, lower and upper bounds of the
210+
range to be searched
211+
args: any additional positional arguments are passed to max_func
212+
options: any keyword arguments are passed as options to minimize_scalar
213+
214+
returns: OptimizeResult object
215+
(see https://docs.scipy.org/doc/scipy/
216+
reference/generated/scipy.optimize.minimize_scalar.html)
217+
"""
218+
def min_func(*args):
219+
return -max_func(*args)
220+
221+
return min_bounded(min_func, bounds, *args, **options)
222+
223+
161224
def run_odeint(system, slope_func, **kwargs):
162225
"""Runs a simulation of the system.
163226
@@ -229,8 +292,25 @@ def interpolate(series, **options):
229292
return interp1d(series.index, series.values, **options)
230293

231294

232-
def unpack(series, names=None):
295+
def interp_inverse(series, **options):
296+
"""Interpolate the inverse function of a Series.
297+
298+
series: Series object, represents a mapping from `a` to `b`
299+
kind: string, which kind of iterpolation
300+
options: keyword arguments passed to interpolate
301+
302+
returns: interpolation object, can be used as a function
303+
from `b` to `a`
233304
"""
305+
inverse = Series(series.index, index=series.values)
306+
T = interpolate(inverse, **options)
307+
return T
308+
309+
310+
def unpack(series):
311+
"""Make the names in `series` available as globals.
312+
313+
series: Series with variables names in the index
234314
"""
235315
frame = inspect.currentframe()
236316
caller = frame.f_back
@@ -710,7 +790,7 @@ class SweepFrame(MyDataFrame):
710790
pass
711791

712792

713-
class _Vector(UNITS.Quantity):
793+
class _Vector(Quantity):
714794
"""Represented as a Pint Quantity with a NumPy array
715795
716796
x, y, z, mag, mag2, and angle are accessible as attributes.
@@ -788,10 +868,13 @@ def dist(self, other):
788868
return diff.mag
789869

790870
def diff_angle(self, other):
871+
"""Angular difference between two vectors, in radians.
791872
"""
792-
"""
793-
#TODO: see http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/
794-
raise NotImplementedError()
873+
if len(self) == 2:
874+
return self.angle - other.angle
875+
else:
876+
#TODO: see http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/
877+
raise NotImplementedError()
795878

796879

797880
def Vector(*args, units=None):

0 commit comments

Comments
 (0)