Path: blob/master/material/numerical-calculus.ipynb
934 views
Numerical Calculus
Throughout this section and the next ones, we shall cover the topic of numerical calculus. Calculus has been identified since ancient times as a powerful toolkit for analysing and handling geometrical problems. Since differential calculus was developed by Newton and Leibniz (in its actual notation), many different applications have been found, at the point that most of the current science is founded on it (e.g. differential and integral equations). Due to the ever increasing complexity of analytical expressions used in physics and astronomy, their usage becomes more and more impractical, and numerical approaches are more than necessary when one wants to go deeper. This issue has been identified since long ago and many numerical techniques have been developed. We shall cover only the most basic schemes, but also providing a basis for more formal approaches.
Bibliography
Thomas J. Sargent John Stachurski, Python Programming for Quantitative Economics GitHub
Numerical Differentiation
According to the formal definition of differentiation, given a function such that , the first order derivative is given by
However, when exhibits a complex form or is a numerical function (only a discrete set of points are known), this expression becomes unfeasible. In spite of this, this formula gives us a very first rough way to calculate numerical derivatives by taking a finite interval , i.e.
where the function must be known at least in and , and should be small enough.
Example 1
Evaluate the first derivative of the next function using the previous numerical scheme at the point and using
Compare with the real function and plot the tangent line using the found values of the slope.
It is used as:
Parameters
func
: function → Input function.
x0
: float → The point at which n
-th derivative is found.
dx
: float, optional → Spacing.
n
: int, optional → Order of the derivative. Default is 1.
args
: tuple, optional → Arguments
order
: int, optional → Number of points to use, must be odd.
Activity: We now check for the impact of the change of the spacing dx
. Try from dx=0.5
and then small values
{"name":"stdin","output_type":"stream","text":"dx= 1\n"}
{"name":"stdin","output_type":"stream","text":"dx= 0.1\n"}
{"name":"stdin","output_type":"stream","text":"dx= 0.01\n"}
{"name":"stdin","output_type":"stream","text":"dx= 1e-3\n"}
{"name":"stdin","output_type":"stream","text":"dx= 1e-6\n"}
Compare with:
Implementation of the derivate of the function inside a full range
We now generalize the derivative
function to allow the evaluation of the derivate in a full range of values. It will be designed such that the evaluation in just one point can be still possible. In this way, the new function can be used as a full replacement of derivative
function.
To implement this function we need three keys ingredients of python
:
try
andexcept
python progamming sctructureFunction definition with generic mandatory and optional arguments
Conversion of a float function into a vectorized fuction
try
and except
python progamming sctructure
First we introduce the try
and except
python progamming sctructure, wich is used to bypass one python error. For example a zero dimension array has not a shape attribute, so that the following error, of type IndexError
, is generated:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Input In [20], in <cell line: 1>()
----> 1 (1,)[1]
IndexError: tuple index out of range
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Input In [33], in <cell line: 1>()
----> 1 nn=np.array(3).shape[0]
2 nn
IndexError: tuple index out of range
To bypass that error we use the following code:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_57720/4138546388.py in <module>
1 x=3
----> 2 len(3)
TypeError: object of type 'int' has no len()
so that nn
takes the values assigned in the except
part:
Activity: A float has the method is_integer()
to check if the decimal part is zero. Creates a function is_integer(x)
which works even in the case that the number is already an integer
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Input In [50], in <cell line: 2>()
1 x=2
----> 2 x.is_integer()
AttributeError: 'int' object has no attribute 'is_integer'
Objetos:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [58], in <cell line: 1>()
----> 1 eval('hola')
, in <module>
NameError: name 'hola' is not defined
Traceback (most recent call last):
File ~/anaconda3/lib/python3.9/site-packages/IPython/core/interactiveshell.py:3369 in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
Input In [59] in <cell line: 1>
eval('hola mundo')
File <string>:1
hola mundo
^
SyntaxError: unexpected EOF while parsing
Testing
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Input In [61], in <cell line: 1>()
----> 1 assert False
AssertionError:
assert
is trivial for True
assert
generates an error for False
Function parameters
In python the function can be defined with mandatory and optional arguments
a
,b
: is like a tuple of mandatory arguments →(a,b)
c=2
,d=3
: is like a dictionary of optional arguments →{'c':2,'d':3}
Function definition with generic mandatory and optional arguments
We need to introduce another important concept about functions. There is a powerfull way to define a function with generic arguments:
Instead of the mandatory arguments we can use the generic list pointer:
*args
Instead of the optional arguments we can use the generic dictionary pointer:
**kwargs
Activity; Check the function with any type of mandatory or optional argument
Check the function without arguments
Check the function with a mandatory argument
Check the function with several mandatory arguments
Check the function with several optional arguments
Check the function with one of the optional arguments equal to some list
Check the function with one string as mandatory argument, and with one of the optional arguments equal to some list
Conversion of a float function into a vectorized function
An important numpy
function is:
Which convert a function which takes a float as an argument into a new function which que takes numpy arrays
as an argument. The problem is that the converted function does not longer return a float when the argument is a float:
It is used as:
Parameters: pyfunc
: A python function or method.
...
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [80], in <cell line: 1>()
----> 1 m.sin([0.5,0.7])
TypeError: must be real number, not list
Vectorization of Scipy method derivative
The problem is that derivative
only works for one a point
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [84], in <cell line: 1>()
----> 1 misc.derivative(np.sin,[1,1.2],dx=1E-6)
, in derivative(func, x0, dx, n, args, order)
142 ho = order >> 1
143 for k in range(order):
--> 144 val += weights[k]*func(x0+(k-ho)*dx,*args)
145 return val / prod((dx,)*n,axis=0)
TypeError: can only concatenate list (not "float") to list
This is easily fixed with np.vectorize
Code for the derivate of the function inside a full range
To recover the evaluation of a float into a float we can force the IndexError
in order to use of the pure scipy
derivative
function when a float is given as input. The full implemention combine the three previos ingredients into a very compact pythonic-way function definition as shwon below
which behaves exactly as the scipy
derivative
function when a float argument is used:
and as a vectorized function when an array argument is used:
Let see now the implementation of the derivate
function as full replacement of the derivative
function:
Test
Let us check the implementation with the previous function
but now evaluated for a list of values
For the prevous X
array:
We have:
Example
Finally we check the function in the range
Activity: Implement the full derivative function by using isinstance()
instead of try
and except
Example: Heat transfer in a 1D bar
Fourier's Law of thermal conduction describes the diffusion of heat. Situations in which there are gradients of heat, a flux that tends to homogenise the temperature arises as a consequence of collisions of particles within a body. The Fourier's Law is giving by
where T is the temperature, its gradient and k is the material's conductivity. In the next example it is shown the magnitud of the heat flux in a 1D bar(wire).
Activity
Construct a density map of the magnitud of the heat flux of a 2D bar. Consider the temperature profile as
Activity
The Poisson's equation relates the matter content of a body with the gravitational potential through the next equation
where is the potential, the density and the gravitational constant.
Taking these data and using the three-point Midpoint formula, find the density field from the potential (seventh column in the file) and plot it against the radial coordinate. (Tip: Use )
Activity
The radar stations A and B, separated by the distance a = 500 m, track the plane C by recording the angles and at 1-second intervals. The successive readings are
calculate the speed v using the 3 point approximantion at t = 10 ,12 and 14 s. Calculate the x component of the acceleration of the plane at = 12 s. The coordinates of the plane can be shown to be
Appendix
One implementation of derivative
algorithm
n+1-point formula
A generalization of the previous formula is given by the (n+1)-point formula, where first-order derivatives are calculated using more than one point, what makes it a much better approximation for many problems. it is controled by the order
option of the derivative
function of scipy.misc
Theorem
For a function such that , the next expression is always satisfied
where is a set of point where the function is mapped, is some function of such that , and is the associated Lagrange interpolant polynomial.
As becomes higher, the approximation should be better as the error term becomes neglectable.
Taking the previous expression, and differenciating, we obtain
where is the -th Lagrange basis functions for points, is its first derivative.
Note that the last expressions is evaluated in rather than a general value, the cause of this is because this expression is not longer valid for another value not within the set , however this is not an inconvenient when handling real applications.
This formula constitutes the (n+1)-point approximation and it comprises a generalization of almost all the existing schemes to differentiate numerically. Next, we shall derive some very used formulas.
For example, the form that takes this derivative polynomial for 3 points is the following
Endpoint formulas
Endpoint formulas are based on evaluating the derivative at the first of a set of points, i.e., if we want to evaluate at , we then need , , , . For the sake of simplicity, it is usually assumed that the set is equally spaced such that .
Three-point Endpoint Formula
with
Five-point Endpoint Formula
with
Endpoint formulas are especially useful near to the end of a set of points, where no further points exist.
Midpoint formulas
On the other hand, Midpoint formulas are based on evaluating the derivative at the middle of a set of points, i.e., if we want to evaluate at , we then need , , , , , , .
Three-point Midpoint Formula
with
Five-point Midpoint Formula
with
As Midpoint formulas required one iteration less than Endpoint ones, they are more often used for numerical applications. Furthermore, the round-off error is smaller as well. However, near to the end of a set of points, they are no longer useful as no further points exists, and Endpoint formulas are preferable.
Example with custom implementation