Wrapper for applying unary functions to fields in grid space. This can be used with arbitrary user-defined functions, but symbolic differentiation is only implemented for some scipy/numpy universal functions. Parameters ---------- func : function Unary function
| 503 | |
| 504 | |
| 505 | class UnaryGridFunction(NonlinearOperator, FutureField): |
| 506 | """ |
| 507 | Wrapper for applying unary functions to fields in grid space. |
| 508 | This can be used with arbitrary user-defined functions, but |
| 509 | symbolic differentiation is only implemented for some scipy/numpy |
| 510 | universal functions. |
| 511 | |
| 512 | Parameters |
| 513 | ---------- |
| 514 | func : function |
| 515 | Unary function acting on grid data. Must be vectorized |
| 516 | and include an output array argument, e.g. func(x, out). |
| 517 | arg : dedalus operand |
| 518 | Argument field or operator. |
| 519 | deriv : function, optional |
| 520 | Symbolic derivative of func. Defaults are provided |
| 521 | for some common numpy/scipy ufuncs (default: None). |
| 522 | out : field, optional |
| 523 | Output field (default: new field). |
| 524 | |
| 525 | Notes |
| 526 | ----- |
| 527 | The supplied function must support an output argument called 'out' |
| 528 | and act in a vectorized fashion. The action is essentially: |
| 529 | |
| 530 | func(arg['g'], out=out['g']) |
| 531 | |
| 532 | """ |
| 533 | |
| 534 | ufunc_derivatives = { |
| 535 | np.absolute: lambda x: np.sign(x), |
| 536 | np.sign: lambda x: 0, |
| 537 | np.exp: lambda x: np.exp(x), |
| 538 | np.exp2: lambda x: np.exp2(x) * np.log(2), |
| 539 | np.log: lambda x: x**(-1), |
| 540 | np.log2: lambda x: (x * np.log(2))**(-1), |
| 541 | np.log10: lambda x: (x * np.log(10))**(-1), |
| 542 | np.sqrt: lambda x: (1/2) * x**(-1/2), |
| 543 | np.square: lambda x: 2*x, |
| 544 | np.sin: lambda x: np.cos(x), |
| 545 | np.cos: lambda x: -np.sin(x), |
| 546 | np.tan: lambda x: np.cos(x)**(-2), |
| 547 | np.arcsin: lambda x: (1 - x**2)**(-1/2), |
| 548 | np.arccos: lambda x: -(1 - x**2)**(-1/2), |
| 549 | np.arctan: lambda x: (1 + x**2)**(-1), |
| 550 | np.sinh: lambda x: np.cosh(x), |
| 551 | np.cosh: lambda x: np.sinh(x), |
| 552 | np.tanh: lambda x: 1-np.tanh(x)**2, |
| 553 | np.arcsinh: lambda x: (x**2 + 1)**(-1/2), |
| 554 | np.arccosh: lambda x: (x**2 - 1)**(-1/2), |
| 555 | np.arctanh: lambda x: (1 - x**2)**(-1), |
| 556 | scp.erf: lambda x: 2*(np.pi)**(-1/2)*np.exp(-x**2)} |
| 557 | |
| 558 | # Add ufuncs and shortcuts to aliases |
| 559 | aliases.update({ufunc.__name__: ufunc for ufunc in ufunc_derivatives}) |
| 560 | aliases.update({'abs': np.absolute, 'conj': np.conjugate}) |
| 561 | |
| 562 | def __init__(self, func, arg, deriv=None, out=None): |
no test coverage detected