I am relatively new to coding and am trying to code a subroutine that takes in a grid spacing h and a polynomial degree n and returns the n + 1 numbers that correspond to the symmetric finite difference stencil/filter for the operator d2/dx2, i.e write some code that returns the finite difference coefficients found on wikipedia. I am close but not getting the correct values for 4th, 6th and 8th degree accuracy. Any help would be greatly appreciated!
I've coded this Lagrange polynomial, but it doesnt seem to work (Edit: The code doesn't return any errors, but does not return the correct coefficients for the second order central finite difference found here https://en.wikipedia.org/wiki/Finite_difference_coefficient. Thanks for the help!)
Edit: The formula i am trying to implement is
which i understand is a Lagrange polynomial that works as a 'filter', however i do not know why it produces the finite central difference coefficients.
:
def central_difference_coefficients(order, n):
coefficients = []
for j in range(n+1):
coefficient = 0.0
for i in range(n+1):
if i != j:
term1 = 1.0 / (j - i)
product = 1.0
for m in range(n+1):
if m != j and m != i:
denominator = j - m
if denominator != 0:
product *= 1.0 / denominator
for l in range(n+1):
if l != j and l != i and l != m:
denominator = j - l
if denominator != 0:
product *= (n / 2 - l) /denominator
term2 = term1 * product
coefficient += term2
if j != 0:
coefficient *= 1.0 / (order**2)
coefficients.append(coefficient)
return coefficients
# Example usage:
order = 2
n = 4
coefficients_2nd_order = central_difference_coefficients(order, n)
print(f"Central Difference Coefficients (2nd order) for n={n}:\n{coefficients_2nd_order}")
For an example of the answer it gives for n=2 is [1.0, -0.5, 0.0625], which should be [1,-2,1] Let me know where I've gone wrong!
I spotted at least one bug in your code: the resetting line
product = 1.0should be inside the loop indexed bym, because there is a different product for everym. Instead you have put this line just outside the loop overm, so that subsequent terms of themsum will be affected by previous products.In fact, you could remove line
product = 1.0completely, and replaceproduct *= 1.0 / denominatorbyproduct = 1.0 / denominator, which would also reset the product correctly.To avoid these kinds of bugs, python conveniently offers a
sumand aprodfunction which you can use to calculate a sum or a product with a for-loop without manually writingproduct = 1.0andproduct *= ....Here are two ways to rewrite your function using
sumandprod:sumandprodare particularly convenient when implementing formula; you can compare directly the code with the formula and don't have to worry about maintaining variables and resetting them correctly.These kinds of "inline for-loops" differ from usual for-loops and are called "generator-expressions" in python, and you can use them with
sum,prod,max,min, or even with[ ]to create a list like I did with the loop indexed byj(an expression to create a list like this is called a "list comprehension").You can test that
C(1, 2) == K(1, 2) == [1.0, -2.0, 1.0]as expected.