 Contents of /trunk/doc/cookbook/example07.tex

Revision 4821 - (show annotations)
Tue Apr 1 04:58:33 2014 UTC (5 years, 2 months ago) by sshaw
File MIME type: application/x-tex
File size: 15745 byte(s)
moved SolverOptions to c++, split into SolverOptions for the options and SolverBuddy as the state as a precursor to per-pde solving... does break some use cases (e.g. pde.getSolverOptions().DIRECT will now fail, new value access is with SolverOptions.DIRECT), examples and documentation updated to match

 1 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % Copyright (c) 2003-2014 by University of Queensland 4 5 % 6 % Primary Business: Queensland, Australia 7 % Licensed under the Open Software License version 3.0 8 9 % 10 % Development until 2012 by Earth Systems Science Computational Center (ESSCC) 11 % Development 2012-2013 by School of Earth Sciences 12 % Development from 2014 by Centre for Geoscience Computing (GeoComp) 13 % 14 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 16 The acoustic wave equation governs the propagation of pressure waves. Wave 17 types that obey this law tend to travel in liquids or gases where shear waves 18 or longitudinal style wave motion is not possible. An obvious example is sound 19 waves. 20 21 The acoustic wave equation is defined as; 22 \begin{equation} 23 \nabla ^2 p - \frac{1}{c^2} \frac{\partial ^2 p}{\partial t^2} = 0 24 \label{eqn:acswave} 25 \end{equation} 26 where $p$ is the pressure, $t$ is the time and $c$ is the wave velocity. In this 27 chapter the acoustic wave equation is demonstrated. Important steps include the 28 translation of the Laplacian $\nabla^2$ to the \esc general form, the stiff 29 equation stability criterion and solving for the displacement or acceleration solution. 30 31 \section{The Laplacian in \esc} 32 The Laplacian operator which can be written as $\Delta$ or $\nabla^2$, is 33 calculated via the divergence of the gradient of the object, which in this 34 example is the scalar $p$. Thus we can write; 35 \begin{equation} 36 \nabla^2 p = \nabla \cdot \nabla p = 37 \sum_{i}^n 38 \frac{\partial^2 p}{\partial x^2_{i}} 39 \label{eqn:laplacian} 40 \end{equation} 41 For the two dimensional case in Cartesian coordinates \autoref{eqn:laplacian} 42 becomes; 43 \begin{equation} 44 \nabla^2 p = \frac{\partial^2 p}{\partial x^2} 45 + \frac{\partial^2 p}{\partial y^2} 46 \end{equation} 47 48 In \esc the Laplacian is calculated using the divergence representation and the 49 intrinsic functions \textit{grad()} and \textit{trace()}. The function 50 \textit{grad{}} will return the spatial gradients of an object. 51 For a rank 0 solution, this is of the form; 52 \begin{equation} 53 \nabla p = \left[ 54 \frac{\partial p}{\partial x _{0}}, 55 \frac{\partial p}{\partial x _{1}} 56 \right] 57 \label{eqn:grad} 58 \end{equation} 59 Larger ranked solution objects will return gradient tensors. For example, a 60 pressure field which acts in the directions $p _{0}$ and $p 61 _{1}$ would return; 62 \begin{equation} 63 \nabla p = \begin{bmatrix} 64 \frac{\partial p _{0}}{\partial x _{0}} & 65 \frac{\partial p _{1}}{\partial x _{0}} \\ 66 \frac{\partial p _{0}}{\partial x _{1}} & 67 \frac{\partial p _{1}}{\partial x _{1}} 68 \end{bmatrix} 69 \label{eqn:gradrank1} 70 \end{equation} 71 72 \autoref{eqn:grad} corresponds to the Linear PDE general form value 73 $X$. Notice however, that the general form contains the term $X 74 _{i,j}$\footnote{This is the first derivative in the $j^{th}$ 75 direction for the $i^{th}$ component of the solution.}, 76 hence for a rank 0 object there is no need to do more then calculate the 77 gradient and submit it to the solver. In the case of the rank 1 or greater 78 object, it is also necessary to calculate the trace. This is the sum of the 79 diagonal in \autoref{eqn:gradrank1}. 80 81 Thus when solving for equations containing the Laplacian one of two things must 82 be completed. If the object \verb!p! is less than rank 1 the gradient is 83 calculated via; 84 \begin{python} 85 gradient=grad(p) 86 \end{python} 87 and if the object is greater then or equal to a rank 1 tensor, the trace of 88 the gradient is calculated. 89 \begin{python} 90 gradient=trace(grad(p)) 91 \end{python} 92 These values can then be submitted to the PDE solver via the general form term 93 $X$. The Laplacian is then computed in the solution process by taking the 94 divergence of $X$. 95 96 Note, if you are unsure about the rank of your tensor, the \textit{getRank} 97 command will return the rank of the PDE object. 98 \begin{python} 99 rank = p.getRank() 100 \end{python} 101 102 103 \section{Numerical Solution Stability} \label{sec:nsstab} 104 Unfortunately, the wave equation belongs to a class of equations called 105 \textbf{stiff} PDEs. These types of equations can be difficult to solve 106 numerically as they tend to oscillate about the exact solution, which can 107 eventually lead to a catastrophic failure. To counter this problem, explicitly 108 stable schemes like the backwards Euler method, and correct parameterisation of 109 the problem are required. 110 111 There are two variables which must be considered for 112 stability when numerically trying to solve the wave equation. For linear media, 113 the two variables are related via; 114 \begin{equation} \label{eqn:freqvel} 115 f=\frac{v}{\lambda} 116 \end{equation} 117 The velocity $v$ that a wave travels in a medium is an important variable. For 118 stability the analytical wave must not propagate faster then the numerical wave 119 is able to, and in general, needs to be much slower then the numerical wave. 120 For example, a line 100m long is discretised into 1m intervals or 101 nodes. If 121 a wave enters with a propagation velocity of 100m/s then the travel time for 122 the wave between each node will be 0.01 seconds. The time step, must therefore 123 be significantly less than this. Of the order $10E-4$ would be appropriate. 124 This stability criterion is known as the Courant\textendash 125 Friedrichs\textendash Lewy condition given by 126 \begin{equation} 127 dt=f\cdot \frac{dx}{v} 128 \end{equation} 129 where $dx$ is the mesh size and $f$ is a safety factor. To obtain a time step of 130 $10E-4$, a safety factor of $f=0.1$ was used. 131 132 The wave frequency content also plays a part in numerical stability. The 133 Nyquist-sampling theorem states that a signals bandwidth content will be 134 accurately represented when an equispaced sampling rate $f _{n}$ is 135 equal to or greater then twice the maximum frequency of the signal 136 $f_{s}$, or; 137 \begin{equation} \label{eqn:samptheorem} 138 f_{n} \geqslant f_{s} 139 \end{equation} 140 For example, a 50Hz signal will require a sampling rate greater then 100Hz or 141 one sample every 0.01 seconds. The wave equation relies on a spatial frequency, 142 thus the sampling theorem in this case applies to the solution mesh spacing. 143 This relationship confirms that the frequency content of the input signal 144 directly affects the time discretisation of the problem. 145 146 To accurately model the wave equation with high resolutions and velocities 147 means that very fine spatial and time discretisation is necessary for most 148 problems. This requirement makes the wave equation arduous to 149 solve numerically due to the large number of time iterations required in each 150 solution. Models with very high velocities and frequencies will be the worst 151 affected by this problem. 152 153 \section{Displacement Solution} 154 \sslist{example07a.py} 155 156 We begin the solution to this PDE with the centred difference formula for the 157 second derivative; 158 \begin{equation} 159 f''(x) \approx \frac{f(x+h - 2f(x) + f(x-h)}{h^2} 160 \label{eqn:centdiff} 161 \end{equation} 162 substituting \autoref{eqn:centdiff} for $\frac{\partial ^2 p }{\partial t ^2}$ 163 in \autoref{eqn:acswave}; 164 \begin{equation} 165 \nabla ^2 p - \frac{1}{c^2h^2} \left[p_{(t+1)} - 2p_{(t)} + 166 p_{(t-1)} \right] 167 = 0 168 \label{eqn:waveu} 169 \end{equation} 170 Rearranging for $p_{(t+1)}$; 171 \begin{equation} 172 p_{(t+1)} = c^2 h^2 \nabla ^2 p_{(t)} +2p_{(t)} - 173 p_{(t-1)} 174 \end{equation} 175 this can be compared with the general form of the \modLPDE module and it 176 becomes clear that $D=1$, $X_{i,j}=-c^2 h^2 \nabla ^2 p_{(t)}$ and 177 $Y=2p_{(t)} - p_{(t-1)}$. 178 179 The solution script is similar to others that we have created in previous 180 chapters. The general steps are; 181 \begin{enumerate} 182 \item The necessary libraries must be imported. 183 \item The domain needs to be defined. 184 \item The time iteration and control parameters need to be defined. 185 \item The PDE is initialised with source and boundary conditions. 186 \item The time loop is started and the PDE is solved at consecutive time steps. 187 \item All or select solutions are saved to file for visualisation later on. 188 \end{enumerate} 189 190 Parts of the script which warrant more attention are the definition of the 191 source, visualising the source, the solution time loop and the VTK data export. 192 193 \subsection{Pressure Sources} 194 As the pressure is a scalar, one need only define the pressure for two 195 time steps prior to the start of the solution loop. Two known solutions are 196 required because the wave equation contains a double partial derivative with 197 respect to time. This is often a good opportunity to introduce a source to the 198 solution. This model has the source located at it's centre. The source should 199 be smooth and cover a number of samples to satisfy the frequency stability 200 criterion. Small sources will generate high frequency signals. Here, when using 201 a rectangular domain, the source is defined by a cosine function. 202 \begin{python} 203 U0=0.01 # amplitude of point source 204 xc=[500,500] #location of point source 205 # define small radius around point xc 206 src_radius = 30 207 # for first two time steps 208 u=U0*(cos(length(x-xc)*3.1415/src_radius)+1)*\ 209 whereNegative(length(x-xc)-src_radius) 210 u_m1=u 211 \end{python} 212 213 \subsection{Visualising the Source} 214 There are two options for visualising the source. The first is to export the 215 initial conditions of the model to VTK, which can be interpreted as a scalar 216 surface in Mayavi2. The second is to take a cross section of the model which 217 will require the \textit{Locator} function. 218 First \verb!Locator! must be imported; 219 \begin{python} 220 from esys.escript.pdetools import Locator 221 \end{python} 222 The function can then be used on the domain to locate the nearest domain node 223 to the point or points of interest. 224 225 It is now necessary to build a list of $(x,y)$ locations that specify where are 226 model slice will go. This is easily implemented with a loop; 227 \begin{python} 228 cut_loc=[] 229 src_cut=[] 230 for i in range(ndx/2-ndx/10,ndx/2+ndx/10): 231 cut_loc.append(xstep*i) 232 src_cut.append([xstep*i,xc]) 233 \end{python} 234 We then submit the output to \verb!Locator! and finally return the appropriate 235 values using the \verb!getValue! function. 236 \begin{python} 237 src=Locator(mydomain,src_cut) 238 src_cut=src.getValue(u) 239 \end{python} 240 It is then a trivial task to plot and save the output using \mpl 241 (\autoref{fig:cxsource}). 242 \begin{python} 243 pl.plot(cut_loc,src_cut) 244 pl.axis([xc-src_radius*3,xc+src_radius*3,0.,2*U0]) 245 pl.savefig(os.path.join(savepath,"source_line.png")) 246 \end{python} 247 \begin{figure}[h] 248 \centering 249 \includegraphics[width=6in]{figures/sourceline.png} 250 \caption{Cross section of the source function.} 251 \label{fig:cxsource} 252 \end{figure} 253 254 255 \subsection{Point Monitoring} 256 In the more general case where the solution mesh is irregular or specific 257 locations need to be monitored, it is simple enough to use the \textit{Locator} 258 function. 259 \begin{python} 260 rec=Locator(mydomain,[250.,250.]) 261 \end{python} 262 When the solution \verb u is updated we can extract the value at that point 263 via; 264 \begin{python} 265 u_rec=rec.getValue(u) 266 \end{python} 267 For consecutive time steps one can record the values from \verb!u_rec! in an 268 array initialised as \verb!u_rec0=[]! with; 269 \begin{python} 270 u_rec0.append(rec.getValue(u)) 271 \end{python} 272 273 It can be useful to monitor the value at a single or multiple individual points 274 in the model during the modelling process. This is done using 275 the \verb!Locator! function. 276 277 278 \section{Acceleration Solution} 279 \sslist{example07b.py} 280 281 An alternative method to the displacement solution, is to solve for the 282 acceleration $\frac{\partial ^2 p}{\partial t^2}$ directly. The displacement can 283 then be derived from the acceleration after a solution has been calculated 284 The acceleration is given by a modified form of \autoref{eqn:waveu}; 285 \begin{equation} 286 \nabla ^2 p - \frac{1}{c^2} a = 0 287 \label{eqn:wavea} 288 \end{equation} 289 and can be solved directly with $Y=0$ and $X=-c^2 \nabla ^2 p_{(t)}$. 290 After each iteration the displacement is re-evaluated via; 291 \begin{equation} 292 p_{(t+1)}=2p_{(t)} - p_{(t-1)} + h^2a 293 \end{equation} 294 295 \subsection{Lumping} 296 For \esc, the acceleration solution is preferred as it allows the use of matrix 297 lumping. Lumping or mass lumping as it is sometimes known, is the process of 298 aggressively approximating the density elements of a mass matrix into the main 299 diagonal. The use of Lumping is motivated by the simplicity of diagonal matrix 300 inversion. As a result, Lumping can significantly reduce the computational 301 requirements of a problem. Care should be taken however, as this 302 function can only be used when the $A$, $B$ and $C$ coefficients of the 303 general form are zero. 304 305 More information about the lumping implementation used in \esc and its accuracy 306 can be found in the user guide. 307 308 To turn lumping on in \esc one can use the command; 309 \begin{python} 310 mypde.getSolverOptions().setSolverMethod(SolverOptions.HRZ_LUMPING) 311 \end{python} 312 It is also possible to check if lumping is set using; 313 \begin{python} 314 print mypde.isUsingLumping() 315 \end{python} 316 317 \section{Stability Investigation} 318 It is now prudent to investigate the stability limitations of this problem. 319 First, we let the frequency content of the source be very small. If we define 320 the source as a cosine input, then the wavlength of the input is equal to the 321 radius of the source. Let this value be 5 meters. Now, if the maximum velocity 322 of the model is $c=380.0ms^{-1}$, then the source 323 frequency is $f_{r} = \frac{380.0}{5} = 76.0 Hz$. This is a worst case 324 scenario with a small source and the models maximum velocity. 325 326 Furthermore, we know from \autoref{sec:nsstab}, that the spatial sampling 327 frequency must be at least twice this value to ensure stability. If we assume 328 the model mesh is a square equispaced grid, 329 then the sampling interval is the side length divided by the number of samples, 330 given by $\Delta x = \frac{1000.0m}{400} = 2.5m$ and the maximum sampling 331 frequency capable at this interval is 332 $f_{s}=\frac{380.0ms^{-1}}{2.5m}=152Hz$ this is just equal to the 333 required rate satisfying \autoref{eqn:samptheorem}. 334 335 \autoref{fig:ex07sampth} depicts three examples where the grid has been 336 undersampled, sampled correctly, and over sampled. The grids used had 337 200, 400 and 800 nodes per side respectively. Obviously, the oversampled grid 338 retains the best resolution of the modelled wave. 339 340 The time step required for each of these examples is simply calculated from 341 the propagation requirement. For a maximum velocity of $380.0ms^{-1}$, 342 \begin{subequations} 343 \begin{equation} 344 \Delta t \leq \frac{1000.0m}{200} \frac{1}{380.0} = 0.013s 345 \end{equation} 346 \begin{equation} 347 \Delta t \leq \frac{1000.0m}{400} \frac{1}{380.0} = 0.0065s 348 \end{equation} 349 \begin{equation} 350 \Delta t \leq \frac{1000.0m}{800} \frac{1}{380.0} = 0.0032s 351 \end{equation} 352 \end{subequations} 353 Observe that for each doubling of the number of nodes in the mesh, we halve 354 the time step. To illustrate the impact this has, consider our model. If the 355 source is placed at the center, it is $500m$ from the nearest boundary. With a 356 velocity of $380.0ms^{-1}$ it will take $\approx1.3s$ for the wavefront to 357 reach that boundary. In each case, this equates to $100$, $200$ and $400$ time 358 steps. This is again, only a best case scenario, for true stability these time 359 values may need to be halved and possibly halved again. 360 361 \begin{figure}[ht] 362 \centering 363 \subfigure[Undersampled Example]{ 364 \includegraphics[width=0.45\textwidth,trim=0cm 6cm 5cm 6cm,clip]{figures/ex07usamp.png} 365 \label{fig:ex07usamp} 366 } 367 \subfigure[Just sampled Example]{ 368 \includegraphics[width=0.45\textwidth,trim=0cm 6cm 5cm 6cm,clip]{figures/ex07jsamp.png} 369 \label{fig:ex07jsamp} 370 } 371 \subfigure[Over sampled Example]{ 372 \includegraphics[width=0.45\textwidth,trim=0cm 6cm 5cm 6cm,clip]{figures/ex07nsamp.png} 373 \label{fig:ex07nsamp} 374 } 375 \caption{Sampling Theorem example for stability investigation} 376 \label{fig:ex07sampth} 377 \end{figure} 378