Just like for the vibration equation there are several options. If you have an analytical solution that is time-dependent you can specify one wave as:
un[:] = sp.lambdify(x, u0.subs(t, dt))(xj)
If you do not have , then what?
How to fix , option 1
Use a forward difference
Only first order accurate, but still a possibility.
Use a second order forward difference
Second order accurate, but implicit. And you get two waves!
How to implement , option 2
Use a second order central differece
and the PDE at
Insert for to obtain
Second order accurate and explicit
How to fix boundary conditions?
We will consider 4 different types of boundary conditions
Dirichlet
and
Neumann
and
Open
and
Periodic
Note
Accounting for boundary conditions very often takes more than 50 % of the lines of code in a PDE solver!
Dirichlet boundary conditions
We need to fix and and start by fixing this at
Next, we compute
Here, if the first and last rows of are set to zero, then and .
Next, for
Again, if the first and last rows of are zero, then and for all . The boundary values remain as initially set at .
Dirichlet boundary conditions summary
Set and define a modified differentiation matrix
Now boundary conditions will be ok at all time steps simply by:
Initialize and compute . Set
for n in range():
Update to next iteration:
Dirichlet boundary conditions summary
Note
It is also possible to do nothing with and simply fix the boundary conditions after updating all the internal points
Initialize and compute .
Set and .
for n in range():
Set and
Update to next iteration:
Note
Regular, unmodified , where the first and last rows are completely irrelevant.
Neumann boundary conditions
We need to fix and . We already have .
A second order central scheme at is using ghost cell at
Use the ghost cell and the PDE to fix the Neumann condition
The PDE at the left hand side using ghost cell:
Insert for and obtain
Note
Second order accurate and explicit. Can be implemented by modifying !
Neumann at is the same
The PDE at the right hand side using ghost cell:
Insert for and obtain
And for we similarly get
Neumann summary
Set and define a modified differentiation matrix
Now boundary conditions will be ok at all time steps simply by:
Initialize and compute . Set
for n in range():
Update to next iteration:
Open boundary
The wave simply disappears through the boundary
As for Neumann there are several ways to implement these boundary conditions. The simplest option is to solve the first order accurate
such that
Second order option
Solve for the boundary node
Nice option, but difficult to incorporate in the matrix, since there is no way to modify the first and last rows of such that
Second second order option
Use central, second order scheme
and isolate the ghost node :
Use regular PDE at the boundary that includes the ghost node:
This gives an equation for that fixes the open boundary condition:
Open boundary conditions
Left boundary:
Right boundary:
Both explicit and second order. But not possible to implement into the matrix such that
Implementation open boundaries
Initialize and compute . Set
for n in range():
Update to next iteration:
Note
There is no need to use a modified . The two updates of and will overwrite anything computed in the first step.
Periodic boundary conditions
A periodic solution is a solution that is repeating itself indefinitely. For example :
We solve the problem for example for , but the actual solution will be like above, with no boundaries.
Note
A periodic domain is also referred to as a domain with no boundaries.
A periodic mesh in time
Note
There are only unknowns for a mesh with nodes.
Consider the discretization of
At the left hand side of the domain, the point to the left of is
At the right hand side of the domain the point to the right of is
Periodic boundary conditions can be implemented in the matrix
Note that the matrix expects , even though . The last row in is thus irrelevant, because we wil set manually.
Implementation periodic boundaries
Initialize and compute . Set
for n in range(1, ):
Update to next iteration:
Periodic wave
Properties of the wave equation
If the initial condition is and , then the solution at is
These are two waves - one traveling to the left and the other traveling to the right
If the initial condition , then
is a solution
Representation of waves as complex exponentials
If the initial condition is a sum of waves (superposition, each wave is a solution of the wave equation)
for some , then the solution is
We will analyze one component , where is the frequency in time. This is very similar to the investigation we did for the numerical frequency for the vibration equation.
Assume that the numerical solution is a complex wave
How accurate is compared to the exact ?
What can be concluded about stability?
Note that the solution is a recurrence relation
with an amplification factor such that
Numerical dispersion relation
We can find by inserting for in the discretized wave equation
This is a lot of work, just like it was for the vibration equation. In the end we should get
where the CFL number is
is the numerical dispersion relation
is the exact dispersion relation
We can compare the two to investigate numerical accuracy and stability
Stability
A simpler approach is to insert for directly in
and solve for . We get
Divide by , multiply by and use to get
continue on next slide
Stability
Use to obtain
This is a quadratic equation to solve for A. Using we get that
We see that for any real numbers .
For all real numbers
since
For and stability we need and thus
Rearrange to get that
Since can at worst be we get that the positive real CFL number must be smaller than 1
Hence (since ) for stability we require that
Test Dirichlet solver using CFL=1.01 vs CFL=1.0
unm1[:] = sp.lambdify(x, u0.subs(t, 0))(xj)un[:] = sp.lambdify(x, u0.subs(t, dt))(xj) plotdata = {0: unm1.copy()}CFL =1.01for n inrange(Nt): unp1[:] =2*un - unm1 + CFL**2* D2 @ un unp1[0] =0 unp1[-1] =0 unm1[:] = un un[:] = unp1if n %10==0: plotdata[n] = unp1.copy()