Source code for flash.analysis

"""Analysis functions for common FLASH problems."""

import numpy as np
import scipy.optimize


[docs]def fit_power_law(t, r, **kwargs): """Given a shock with radius r over time t, returns the parameters of best fit to the following power-law: .. math:: R = R_0 t^\\alpha Parameters ---------- t : iterable Time values. r : iterable Corresponding radius values. kwargs : optional Other parameters to pass down to scipy.optimize.curve_fit() Returns ------- r_o : float Radius scaling factor. alpha : float The power-law index. """ power_law = lambda s, r0, a: r0 * (s**a) popt, pcov = scipy.optimize.curve_fit(power_law, t, r, p0=(r[0], 0.5), **kwargs) return popt
[docs]def shock_detect(r, v, threshold=1e-6, min_threshold=1e-36): """Given radius (r) and data (v) arrays, finds the outer most shock. Currently this assumes that the radius is montonically increasing. Parameters ---------- r : ndarray Positional data for values. v : ndarray Data values which determine the presnece of a shock. This is typically done with density or pressure fields. threshold : float, optional The value above which gradients must exceed to be considered a shock. Required for ignoring low-level noise. min_threshold : float, optional If a shock is not found at a given threshold level, the threshold value is reduced by an order of magnitude until a shock is found. This continues until a minimum threshold is reached. Returns ------- shock_r : r.dtype Shock position. shock_v : v.dtype Shock peak value. shock_i : int Shock index in r and v arrays """ dvdr = np.gradient(v) / np.gradient(r) abs_v = np.abs(v[:-1]) sign_dvdr = np.sign(dvdr) mask = np.array([]) while 0 == mask.sum() and min_threshold <= threshold: mask = (threshold < np.abs(v[:-1])) mask = mask & (sign_dvdr[1:] != sign_dvdr[:-1]) threshold *= 0.1 if threshold < min_threshold: raise ValueError("minimum threshold reached, shock not found.") shock_i = np.where(mask)[0][-1] shock_r = r[shock_i] shock_v = v[shock_i] return shock_r, shock_v, shock_i