|
| 1 | +# --- import -------------------------------------------------------------------------------------- |
| 2 | + |
| 3 | + |
| 4 | +import numpy as np |
| 5 | + |
| 6 | + |
| 7 | +# --- define -------------------------------------------------------------------------------------- |
| 8 | + |
| 9 | + |
| 10 | +wn_to_omega = 2 * np.pi * 3e-5 # omega is radians / fs |
| 11 | + |
| 12 | + |
| 13 | +# factor used to convert FWHM to stdev for function definition |
| 14 | +# gaussian defined such that FWHM,intensity scale = sigma * 2 * sqrt(ln(2)) |
| 15 | +# (i.e. FWHM, intensity scale ~ 1.67 * sigma, amplitude scale) |
| 16 | +FWHM_to_sigma = 1. / (2 * np.sqrt(np.log(2))) |
| 17 | + |
| 18 | + |
| 19 | +# TODO: these should probably not be hard-coded |
| 20 | +timestep = 4.0 |
| 21 | +early_buffer = 100.0 |
| 22 | +late_buffer = 400.0 |
| 23 | + |
| 24 | +# --- functions ----------------------------------------------------------------------------------- |
| 25 | + |
| 26 | + |
| 27 | +def _get_t(obj, d): |
| 28 | + """ |
| 29 | + returns the t array that is appropriate for the given pulse |
| 30 | + parameters; needs the appropriate buffers/timestep as well |
| 31 | + """ |
| 32 | + if obj.fixed_bounds: |
| 33 | + t_min = obj.fixed_bounds_min |
| 34 | + t_max = obj.fixed_bounds_max |
| 35 | + else: |
| 36 | + t_min = d.min() - obj.early_buffer |
| 37 | + t_max = d.max() + obj.late_buffer |
| 38 | + # span up to and including t_max now |
| 39 | + t = np.arange(t_min, t_max + obj.timestep, obj.timestep) |
| 40 | + # alternate form: |
| 41 | + return t |
| 42 | + |
| 43 | + |
| 44 | +# --- class --------------------------------------------------------------------------------------- |
| 45 | + |
| 46 | + |
| 47 | +class GaussRWA: |
| 48 | + """ |
| 49 | + returns an array of gaussian values with arguments of |
| 50 | + input array vec, |
| 51 | + mean mu, |
| 52 | + standard deviation sigma |
| 53 | + amplitude amp |
| 54 | + frequency freq |
| 55 | + phase offset p |
| 56 | +
|
| 57 | + we are in rw approx, so if interaction is supposed to be negative, give |
| 58 | + frequency a negative sign |
| 59 | + """ |
| 60 | + # dictionary to associate array position to pulse attribute |
| 61 | + cols = ['A', # amplitude, a.u. |
| 62 | + 's', # pulse FWHM (fs), |
| 63 | + 'd', # pulse center delay (fs), |
| 64 | + 'w', # frequency (wn), |
| 65 | + 'p'] # phase shift (radians) |
| 66 | + # initial vars come from misc module, just as with scan module |
| 67 | + timestep = timestep |
| 68 | + early_buffer = early_buffer |
| 69 | + late_buffer = late_buffer |
| 70 | + # fixed bounds set to true if you want fixed time indices for the pulses |
| 71 | + fixed_bounds = False |
| 72 | + fixed_bounds_min = None |
| 73 | + fixed_bounds_max = None |
| 74 | + |
| 75 | + @classmethod |
| 76 | + def pulse(cls, eparams, pm=None): |
| 77 | + """Get efields for each pulse. |
| 78 | +
|
| 79 | + Parameters |
| 80 | + ---------- |
| 81 | + eparams : 2D numpy ndarray |
| 82 | + Array in (pulse, parameter). Refer to cols attribute for list |
| 83 | + of parameters. |
| 84 | + pm : iterable of integers |
| 85 | + Phase matching. If None, fully positive phase matching is |
| 86 | + assumed. |
| 87 | +
|
| 88 | + Returns |
| 89 | + ------- |
| 90 | + (1D array, 1D array) |
| 91 | + Tuple of 1D numpy ndarray time (fs) and complex efield (a.u.). |
| 92 | + """ |
| 93 | + # import if the size is right |
| 94 | + area = eparams[:, 0].copy().astype(float) |
| 95 | + sigma = eparams[:, 1].copy().astype(float) |
| 96 | + mu = eparams[:, 2].copy().astype(float) |
| 97 | + freq = eparams[:, 3].copy().astype(float) |
| 98 | + p = eparams[:, 4].copy().astype(float) |
| 99 | + # proper unit conversions |
| 100 | + sigma *= FWHM_to_sigma |
| 101 | + freq *= wn_to_omega |
| 102 | + # redefine delays s.t. always relative to the first pulse listed |
| 103 | + offset = mu[0] |
| 104 | + # subtract off the value |
| 105 | + mu -= offset |
| 106 | + # normalize amplitdue to stdev |
| 107 | + y = area / (sigma * np.sqrt(2 * np.pi)) |
| 108 | + #print y, sigma, mu, freq, p |
| 109 | + # calculate t |
| 110 | + t = cls.get_t(mu) |
| 111 | + # incorporate complex conjugates if necessary |
| 112 | + if pm is None: |
| 113 | + cc = np.ones((eparams.shape[-1])) |
| 114 | + else: |
| 115 | + cc = np.sign(pm) |
| 116 | + x = np.exp(-1j*(cc[:,None]*(freq[:,None]*(t[None,:] - mu[:,None])+p[:,None]))) |
| 117 | + x*= y[:,None] * np.exp(-(t[None,:] - mu[:,None])**2 / (2*sigma[:,None]**2) ) |
| 118 | + return t, x |
| 119 | + |
| 120 | + @classmethod |
| 121 | + def get_t(cls, d): |
| 122 | + return _get_t(cls, d) |
0 commit comments