VAMPyR introduction#

1 Prologue#

Import the packages like so

from vampyr import vampyr3d as vp
import matplotlib.pyplot as plt
import numpy as np

If you want to find out how to use a function, or what we have in the package use the function below

help(vp.ScalingProjector)

In case the help was not enough, ask us for help. For this you need only your voice.

2 Math in VAMPyR#

The following exercises are introductions in working with functions, application of operators and some equation solving.

2.1 Projecting a function#

In this task you will create a function, project it at different precisions and basis orders, and plot it against its projection. This is meant to give you understanding in how one can approach completeness in multiwavelets.

First we start by initializing the multiresolution analysis (mra) by using the following command

mra = vp.MultiResolutionAnalysis(box=[-20,20], order=7)

Here you will change the order value later. This defines the polynomial order of the basis.

An allowed function for projection in vampyr needs to have a single coordinate argument and it has to output a float value. You will construct a gaussian function defined by $\( f(\mathbf{r}) = \beta \exp(-\alpha[r_x^2 + r_y^2 + r_z^2]) \)$ the alpha value is a measure of how sharp the gaussian function is, and the beta is just a normalization factor, for this exercise you can set it to anything. Fill out the following python function for this (hint: you can use np.exp).

def f(r):
    # implement your function here (x,y,z is accessed as r[0],r[1],r[2])
    return

You should then be able to plot this function by running the next cell

r_x = np.linspace(-0.99, 0.99, 1000) # create an evenly spaced set of points between -0.99 and 0.99
r_y = np.zeros(1000)
r_z = np.zeros(1000)
r = [r_x, r_y, r_z]

plt.plot(r_x, f(r))

Now we want to project this function, the way we do that is by creating a projection operator vp.ScalingProjector and apply it on the function. We apply this operator by using the function as a function argument of it, P(f) for example.

Try creating one and project the function you created earlier.

hint: use the help function to fill out the blanks)

### write your code here
P_eps = 

f_tree =    # <-- here is where you will put the projected function

when you are done you can run the following cell to plot your projected function.

f_plt = [ f_tree([x, 0.0, 0.0]) for x in r_x ]
plt.plot(r_x, f(r), "tab:blue") # your function
plt.plot(r_x, f_plt, "tab:red") # your projected function
plt.show()

Now that you have projected the function, try changing three values, the alpha value of your original function, the order of the basis and the precision (prec) at which you project the function. What you should see is that the sharper the function, the higher order and precision you need to represent it properly.

One last thing I need to point out before we go to the next exercise is that it is convention to call our projected functions trees, as they all are vp.FunctionTree type.

2.2 Arithmethic#

Arithmethic in vampyr is mostly the same as in normal python. Lets work with the previous function you created.

First you can normalize your projected function by calling the function normalize() of f_tree. Try it in the next cell

# normalize your function here

Before we go on into the rest of the exercise, it is important to note that whenever a function is shown, and it doesn’t start with vp., it is assumed that it must be called as a member function of the tree, that is f_tree.normalize(), otherwise all functions must be called by using the vp. prefix.

Start by multiplying it by a factor of \(2\) and assigning it to a new tree g_tree

g_tree =  # <--- assign your rescaled function to this

You should be able to compare it against f_tree by runnning the following cell

g_plt = [ g_tree([x, 0.0, 0.0]) for x in r_x ]
plt.plot(r_x, g_plt, "tab:red")
plt.plot(r_x, f_plt, "tab:blue")
plt.show()

try adding f_tree and g_tree together

h_tree =  # <--- assign your added functions to this

again, you can test this by plotting it against the two other functions by running the following cell

h_plt = [ h_tree([x, 0.0, 0.0]) for x in r_x ]

plt.plot(r_x, h_plt, "tab:orange")
plt.plot(r_x, g_plt, "tab:red")
plt.plot(r_x, f_plt, "tab:blue")
plt.show()

You can also check that the norm of the different trees makes sense. This is done by calling the norm() value of your tree, try printing it below using the print function. The f_tree should be normalized, so its norm should be about \(1.0\)

print() # print the norm of your functions

Try multiplying your trees with the * operator, it should return a new tree which is the product of both, and you can check its norm again.

i_tree =  # <----- assign you multiplied functions to this

Finally, you can take the dot product, also called inner product, between two trees by using the vp.dot function. You can try this in the cell below. print out the norm of the product as shown above, is it what you would expect?

# take the dot product of f_tree and g_tree

2.3 Operators#

You have already worked with the vp.ScalingProjector and will work with the vp.HelmholtzOperator. In this part we will work with the Derivative operator, defined as vp.ABGVDerivative (named after the authors of the paper: Alpert, Beylkin, Gines and Vozovoi). Try constructing (with the help of help()) and applying the operator to your f_tree

D =  # <--- initialize the ABGVDerivative operator here
df_tree =  #  <-- set your differentiated f_tree here

Run the cell below to plot your differentiated function

df_plt = [ df_tree([x, 0.0, 0.0]) for x in r_x ]
plt.plot(r_x, df_plt, "tab:blue") # your differentiated function
plt.plot(r_x, f_plt, "tab:red") # your function tree
plt.show()