Skip to content

Commit d5c59fd

Browse files
authored
Merge pull request #236 from nep-pack/call_from_python
Call from python tutorial
2 parents 545f62c + ca77423 commit d5c59fd

File tree

5 files changed

+123
-16
lines changed

5 files changed

+123
-16
lines changed

docs/make.jl

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ makedocs(
2424
"Tutorial 2 (Contour)" => "tutorial_contour.md",
2525
"Tutorial 3 (BEM)" => "bemtutorial.md",
2626
"Tutorial 4 (Deflation)" => "deflate_tutorial.md",
27-
"Tutorial 5 (Python)" => "tutorial_call_python.md",
28-
"Tutorial 6 (MATLAB)" => "tutorial_matlab1.md",
29-
"Tutorial 7 (FORTRAN)" => "tutorial_fortran1.md",
30-
"Tutorial 8 (gmsh + nanophotonics)" => "tutorial_nano1.md",
31-
"Tutorial 9 (New solver)" => "tutorial_newmethod.md",
32-
"Tutorial 10 (Linear solvers)" => "tutorial_linsolve.md",
33-
"Tutorial 11 (Orr--Somerfeld)" => "hydrotutorial.md"
27+
"Tutorial 5 (Python 1)" => "tutorial_call_python.md",
28+
"Tutorial 6 (Python 2)" => "tutorial_python_call.md",
29+
"Tutorial 7 (MATLAB)" => "tutorial_matlab1.md",
30+
"Tutorial 8 (FORTRAN)" => "tutorial_fortran1.md",
31+
"Tutorial 9 (gmsh + nanophotonics)" => "tutorial_nano1.md",
32+
"Tutorial 10 (New solver)" => "tutorial_newmethod.md",
33+
"Tutorial 11 (Linear solvers)" => "tutorial_linsolve.md",
34+
"Tutorial 12 (Orr--Somerfeld)" => "hydrotutorial.md"
3435
]
3536
]
3637
)

docs/src/compute_functions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ advised if needed for efficiency reasons.
2626

2727
!!! tip
2828
Examples of usage of `Mder_NEP` and/or `Mder_Mlincomb_NEP` are available in
29-
tutorials [3](bemtutorial.md), [5](tutorial_call_python.md),
30-
[6](tutorial_matlab1.md), and [7](tutorial_fortran1.md).
29+
tutorials on [boundary element method](bemtutorial.md), [python](tutorial_call_python.md),
30+
[matlab](tutorial_matlab1.md), and [fortran](tutorial_fortran1.md).
3131

3232
As a NEP-solver developer,
3333
`compute_Mlincomb`-calls are preferred over

docs/src/tutorial_python_call.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Tutorial: Using NEP-PACK from python
2+
3+
## PyJulia
4+
5+
The previous tutorial illustrated how a NEP defined
6+
in python code can be solved with NEP-PACK.
7+
Python is currently a more mature language than Julia,
8+
and there are considerable packages and features
9+
in python not present in Julia. If you need these features,
10+
it may be more convenient to call NEP-PACK
11+
from python, rather than calling python code from julia.
12+
13+
The python package [PyJulia](https://github.com/JuliaPy/pyjulia)
14+
gives us that possibility. The installation of PyJulia on Ubuntu linux is simple:
15+
```
16+
$ python3 -m pip install julia # Only necessary first time you run it
17+
...
18+
$ python3
19+
>>> import julia
20+
>>> jl = Julia(compiled_modules=False) # compilation flag necessary on ubuntu
21+
>>> julia.install() # Only necessary first time you run it
22+
>>> from julia import Base
23+
>>> Base.MathConstants.golden # Julia's definition of golden ratio
24+
1.618033988749895
25+
```
26+
27+
28+
## Using PyJulia and NEP-PACK
29+
30+
The [`Mder_NEP`](@ref)-function provides a convenient
31+
way to define NEPs by only
32+
using a function that computes the matrix ``M(λ)``
33+
and its derivatives.
34+
Let us first define a function which does that in python. We consider
35+
the problem
36+
```math
37+
M(λ)=\begin{bmatrix}3&2\newline3&-1\end{bmatrix}+
38+
λ\begin{bmatrix}0&2\newline0&1\end{bmatrix}+
39+
e^{0.5 λ}\begin{bmatrix}1&1\newline1&1\end{bmatrix}
40+
```
41+
and implement it with this python code:
42+
```python
43+
import numpy as np;
44+
import cmath as m;
45+
def my_compute_M(s,der):
46+
"""Compute the matrix M^{(k)}(s) for a given eigenvalue approximation and derivative k"""
47+
A=np.matrix('3 2; 3 -1'); B=np.matrix('0 2; 0 1'); C=np.matrix('1 1; 1 1');
48+
tau=0.5;
49+
M=pow(tau,der)*m.exp(tau*s)*C
50+
if (der==0):
51+
M=M+A+s*B;
52+
elif (der==1):
53+
M=M+B;
54+
return M
55+
```
56+
An evaluation of the matrix function can be done by the call:
57+
```
58+
>>> my_compute_M(0.3,0)
59+
matrix([[ 6.76183424+0.j, 3.16183424+0.j],
60+
[ 4.16183424+0.j, -3.7 +0.j]])
61+
```
62+
We instantiate a new NEP based with `Mder_NEP` which first must be imported
63+
```
64+
>>> from julia.NonlinearEigenproblems import Mder_NEP
65+
>>> n=2; # Size of the problem
66+
>>> nep=Mder_NEP(2,my_compute_M);
67+
```
68+
and we can apply most of our solvers to this problem by first importing the corresponding function, in this case we use [`contour_beyn`](@ref).
69+
```
70+
>>> from julia.NonlinearEigenproblems import contour_beyn;
71+
>>> sol=contour_beyn(nep,logger=1,neigs=1,radius=3)
72+
Computing integrals
73+
NonlinearEigenproblems.NEPSolver.MatrixTrapezoidal: computing G...
74+
NonlinearEigenproblems.NEPSolver.MatrixTrapezoidal: summing terms........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
75+
Computing SVD prepare for eigenvalue extraction p=1
76+
Computing eigenvalues
77+
Computing eigenvectors
78+
>>>
79+
```
80+
We can verify that we computed a solution as follows
81+
```
82+
>>> s=sol[0][0]; v=sol[1]
83+
>>> my_compute_M(s,0)*v
84+
matrix([[1.71634841e-17-1.59872116e-14j],
85+
[9.55210099e-17-3.99680289e-15j]])
86+
>>> from numpy.linalg import norm
87+
>>> norm(my_compute_M(s,0)*v)
88+
1.6479526251408437e-14
89+
```
90+
Note that in order to obtain better efficiency for
91+
large-scale problems, and reduce overhead,
92+
you may want to use [`Mder_Mlincomb_NEP`](@ref),
93+
as described in the [previous tutorial](tutorial_call_python.md).
94+
95+
96+
![To the top](http://jarlebring.se/onepixel.png?NEPPACKDOC_PYTHON2)

src/nep_type_helpers.jl

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ julia> norm(compute_Mder(nep,λ)*v)
4747
5.551115123125783e-17
4848
```
4949
"""
50-
function Mder_NEP(n,Mder_fun::Function; maxder=typemax(Int))
50+
function Mder_NEP(n,Mder_fun; maxder=typemax(Int))
5151
maxder_Mlincomb=-1; # This means we delegate every Mlincomb_call
5252
Mlincomb_fun=s->s; # Dummy function
5353
return Mder_Mlincomb_NEP(n,
@@ -104,12 +104,23 @@ julia> norm(compute_Mder(nep,λ)*v)
104104
```
105105
"""
106106
function Mder_Mlincomb_NEP(n,
107-
Mder_fun::Function, maxder_Mder,
108-
Mlincomb_fun::Function, maxder_Mlincomb::Int=typemax(Int))
109-
return Mder_Mlincomb_NEP(n,Mder_fun,maxder,
110-
Mlincomb_fun,maxder_Mlincomb);
107+
Mder_fun, maxder_Mder,
108+
Mlincomb_fun, maxder_Mlincomb::Int=typemax(Int))
109+
# Wrap the two functions to Function unless they are already Function
110+
if !isa(Mder_fun,Function)
111+
new_Mder_fun = (λ,der) -> Mder_fun(λ,der);
112+
else
113+
new_Mder_fun = Mder_fun;
114+
end
115+
if !isa(Mlincomb_fun,Function)
116+
new_Mlincomb_fun = (λ,X) -> Mlincomb_fun(λ,X);
117+
else
118+
new_Mlincomb_fun = Mlincomb_fun;
119+
end
120+
return Mder_Mlincomb_NEP(n,new_Mder_fun,maxder_Mder,
121+
new_Mlincomb_fun,maxder_Mlincomb);
111122
end
112-
Mder_Mlincomb_NEP(n,Mder_fun::Function,Mlincomb_fun::Function) = Mder_Mlincomb_NEP(n,Mder_fun,typemax(Int),Mlincomb_fun);
123+
Mder_Mlincomb_NEP(n,Mder_fun,Mlincomb_fun) = Mder_Mlincomb_NEP(n,Mder_fun,typemax(Int),Mlincomb_fun);
113124

114125

115126

test/interpolation.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pep = interpolate(nep, intpoints)
1919
λ2,x2 = newton(pep,logger=displaylevel,maxit=40, λ=-0.75, v=ones(size(nep,1)));
2020
@test compute_resnorm(pep,λ2,x2) < eps()*100
2121
@test abs(λ1-λ2)/abs(λ1) < eps()*1000
22-
println("λ1",λ1,"λ2",λ2)
2322

2423
# Newton on interpolated dep (interpolating pep of degree 8)
2524
intpoints = [λ1-5, λ1-1, λ1, λ1+5, λ1+1, λ1+5im, λ1+1im, λ1-5im, λ1-1im]

0 commit comments

Comments
 (0)