$$
\newcommand{\uex}{{u_{\small\mbox{e}}}}
\newcommand{\half}{\frac{1}{2}}
\newcommand{\halfi}{{1/2}}
\newcommand{\xpoint}{\boldsymbol{x}}
\newcommand{\normalvec}{\boldsymbol{n}}
\newcommand{\Oof}[1]{\mathcal{O}(#1)}
\newcommand{\Ix}{\mathcal{I}_x}
\newcommand{\Iy}{\mathcal{I}_y}
\newcommand{\It}{\mathcal{I}_t}
\newcommand{\setb}[1]{#1^0} % set begin
\newcommand{\sete}[1]{#1^{-1}} % set end
\newcommand{\setl}[1]{#1^-}
\newcommand{\setr}[1]{#1^+}
\newcommand{\seti}[1]{#1^i}
\newcommand{\Real}{\mathbb{R}}
$$
Building a general 1D wave equation solver
The program wave1D_dn_vc.py
solves a fairly general 1D wave equation:
$$
\begin{align}
u_t &= (c^2(x)u_x)_x + f(x,t),\quad &x\in (0,L),\ t\in (0,T]
\tag{34}\\
u(x,0) &= I(x),\quad &x\in [0,L]
\tag{35}\\
u_t(x,0) &= V(t),\quad &x\in [0,L]
\tag{36}\\
u(0,t) &= U_0(t)\hbox{ or } u_x(0,t)=0,\quad &t\in (0,T]
\tag{37}\\
u(L,t) &= U_L(t)\hbox{ or } u_x(L,t)=0,\quad &t\in (0,T]
\tag{38}
\end{align}
$$
Can be adapted to many needs.