Skip to content

Commit

Permalink
Merge pull request #87 from maroba/v0.11.0
Browse files Browse the repository at this point in the history
v0.11.0
  • Loading branch information
maroba authored Dec 11, 2024
2 parents f199bc0 + 71e40a6 commit 2c5fab2
Show file tree
Hide file tree
Showing 33 changed files with 2,050 additions and 1,399 deletions.
1 change: 0 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ name: Checks

on:
push:
branches: [ master ]

jobs:
build:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,4 @@ ENV/

# Visual Studio Code
.vscode
venv2
12 changes: 12 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Change Log

## Version 0.11.x

- More comfortable API. (Old API still available)

## Version 0.10.x

- Create symbolic representations of finite difference schemes

## Version 0.9.x

- Generate differential operators for generic stencils

## Version 0.8.x

- Formulate and solve partial differential equations
Expand Down
92 changes: 47 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,76 +32,67 @@ You can find the documentation of the code including examples of application at

## Taking Derivatives

*findiff* allows to easily define derivative operators that you can apply to *numpy* arrays of any dimension.
The syntax for a simple derivative operator is
*findiff* allows to easily define derivative operators that you can apply to *numpy* arrays of
any dimension.

```python
FinDiff(axis, spacing, degree)
```

where `spacing` is the separation of grid points between neighboring grid points. Consider the 1D case
Consider the simple 1D case of a equidistant grid
with a first derivative $\displaystyle \frac{\partial}{\partial x}$ along the only axis (0):

```python
import numpy as np
from findiff import FinDiff
from findiff import Diff

# define the grid:
x = np.linspace(0, 1, 100)
f = np.sin(x) # as an example

# time step dx
dx = x[1] - x[0]
# the array to differentiate:
f = np.sin(x) # as an example

# Define the derivative:
d_dx = FinDiff(0, dx, 1)
d_dx = Diff(0, x[1] - x[0])

# Apply it:
df_dx = d_dx(f)
```

Similary, you can define partial derivative operators along different axes or of higher degree, for example:

| Math | *findiff* | |
| :---------------------------------------------------------: | ----------------------------------- | --------------------------------------- |
| $\displaystyle \frac{\partial}{\partial y}$ | ``FinDiff(1, dy, 1)`` | same as `` FinDiff(1, dy)`` |
| $\displaystyle \frac{\partial^4}{\partial y^4}$ | ``FinDiff(1, dy, 4)`` | any degree is possible |
| $\displaystyle \frac{\partial^3}{\partial x^2\partial z}$ | ``FinDiff((0, dx, 2), (2, dz, 1))`` | mixed also possible, one tuple per axis |
| $\displaystyle \frac{\partial}{\partial x_{10}}$ | ``FinDiff(10, dx10, 1)`` | number of axes not limited |
Similarly, you can define partial derivatives along other axes, for example, if $z$ is the 2-axis, we can write
$\frac{\partial}{\partial z}$ as:

We can also take linear combinations of derivative operators, for example:

$$
2x \frac{\partial^3}{\partial x^2 \partial z} + 3 \sin(y)z^2 \frac{\partial^3}{\partial x \partial y^2}
$$
```python
Diff(2, dz)
```

is
`Diff` always creates a first derivative. For higher derivatives, you simply exponentiate them, for example for $\frac{\partial^2}{\partial_x^2}$

```python
Coef(2*X) * FinDiff((0, dz, 2), (2, dz, 1)) + Coef(3*sin(Y)*Z**2) * FinDiff((0, dx, 1), (1, dy, 2))
```
d2_dx2 = Diff(0, dx)**2
```

where `X, Y, Z` are *numpy* arrays with meshed grid points.
and apply it as before.

Chaining differential operators is also possible, e.g.
You can also define more general differential operators intuitively, like

$$
\left( \frac{\partial}{\partial x} - \frac{\partial}{\partial y} \right)
\cdot \left( \frac{\partial}{\partial x} + \frac{\partial}{\partial y} \right)
= \frac{\partial^2}{\partial x^2} - \frac{\partial^2}{\partial y^2}
2x \frac{\partial^3}{\partial x^2 \partial z} + 3 \sin(y)z^2 \frac{\partial^3}{\partial x \partial y^2}
$$

can be written as

which can be written as

```python
(FinDiff(0, dx) - FinDiff(1, dy)) * (FinDiff(0, dx) + FinDiff(1, dy))
```
# define the operator
diff_op = 2 * X * Diff(0)**2 * Diff(2) + 3 * sin(Y) * Z**2 * Diff(0) * Diff(1)

and
# set the grid you use (equidistant here)
diff_op.set_grid({0: dx, 1: dy, 2: dz})

```python
FinDiff(0, dx, 2) - FinDiff(1, dy, 2)
# apply the operator
result = diff_op(f)
```

where `X, Y, Z` are *numpy* arrays with meshed grid points. Here you see that you can also define your grid
lazily.

Of course, standard operators from vector calculus like gradient, divergence and curl are also available
as shortcuts.

Expand All @@ -113,10 +104,21 @@ When constructing an instance of `FinDiff`, you can request the desired accuracy
order by setting the keyword argument `acc`. For example:

```python
d2_dx2 = findiff.FinDiff(0, dy, 2, acc=4)
d2f_dx2 = d2_dx2(f)
d_dx = Diff(0, dy, acc=4)
df_dx = d2_dx2(f)
```

Alternatively, you can also split operator definition and configuration:

```python
d_dx = Diff(0, dx)
d_dx.set_accuracy(2)
df_dx = d2_dx2(f)
```

which comes in handy if you have a complicated expression of differential operators, because then you
can specify it on the whole expression and it will be passed down to all basic operators.

If not specified, second order accuracy will be taken by default.

## Finite Difference Coefficients
Expand Down Expand Up @@ -164,7 +166,7 @@ For a given _FinDiff_ differential operator, you can get the matrix representati
using the `matrix(shape)` method, e.g. for a small 1D grid of 10 points:

```python
d2_dx2 = FinDiff(0, dx, 2)
d2_dx2 = Diff(0, dx)**2
mat = d2_dx2.matrix((10,)) # this method returns a scipy sparse matrix
print(mat.toarray())
```
Expand Down Expand Up @@ -276,13 +278,13 @@ u(0) = 0, \hspace{1em} u(10) = 1
$$

```python
from findiff import FinDiff, Id, PDE
from findiff import Diff, Id, PDE

shape = (300, )
t = numpy.linspace(0, 10, shape[0])
dt = t[1]-t[0]

L = FinDiff(0, dt, 2) - FinDiff(0, dt, 1) + Coef(5) * Id()
L = Diff(0, dt)**2 - Diff(0, dt) + 5 * Id()
f = numpy.cos(2*t)

bc = BoundaryConditions(shape)
Expand Down Expand Up @@ -387,5 +389,5 @@ python setup.py develop
From the console:

```
python -m unittest discover test
python -m unittest discover tests
```
17 changes: 9 additions & 8 deletions examples/examples-basic.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
"collapsed": false,
"jupyter": {
"is_executing": true
}
},
"outputs": [],
"source": [
"import numpy as np\n",
"from findiff import FinDiff, coefficients, Coefficient"
]
"from findiff import Diff"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -79,9 +82,7 @@
"collapsed": true
},
"outputs": [],
"source": [
"d2_dx2 = FinDiff(0, dx, 2)"
]
"source": "d2_dx2 = Diff(0, dx=dx, acc=2)"
},
{
"cell_type": "markdown",
Expand Down
11 changes: 7 additions & 4 deletions findiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
- New in version 0.8: Solve partial differential equations with Dirichlet or Neumann boundary conditions
- New in version 0.9: Generate differential operators for generic stencils
- New in version 0.10: Create symbolic representations of finite difference schemes
- Version 1.0: Completely remodeled API (backward compatibility is maintained, though)
"""

__version__ = "0.10.2"
__version__ = "0.11.0"

from .coefs import coefficients
from .operators import FinDiff, Coef, Identity, Coefficient

from .legacy import *
from .operators import Diff, Identity
from .pde import PDE, BoundaryConditions
from .symbolic import SymbolicMesh, SymbolicDiff
from .compatible import Coef, Coefficient, FinDiff, Id
from .coefs import coefficients
from .vector import Gradient, Divergence, Curl, Laplacian
34 changes: 34 additions & 0 deletions findiff/compatible.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Provides an interface to obsolete classes for backward compatibility."""

from findiff import Diff
from findiff.operators import FieldOperator, Identity


def FinDiff(*args, **kwargs):

if len(args) > 3:
raise ValueError("FinDiff accepts not more than 3 positional arguments.")

def diff_from_tuple(tpl):
if len(tpl) == 3:
axis, h, order = tpl
return Diff(axis, h, **kwargs) ** order
elif len(tpl) == 2:
axis, h = tpl
return Diff(axis, h, **kwargs)

if isinstance(args[0], (list, tuple)):
diffs = []
for tpl in args:
diffs.append(diff_from_tuple(tpl))
fd = diffs[0]
for diff in diffs[1:]:
fd = fd * diff
return fd

return diff_from_tuple(args)


# Define aliasses for backward compatibility
Coefficient = Coef = FieldOperator
Id = Identity
Loading

0 comments on commit 2c5fab2

Please sign in to comment.