To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure no-reply@cambridge.org
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
This monograph deals with the generalized Riemann problem (GRP) of mathematical fluid dynamics and its application to computational fluid dynamics. It shows how the solution to this problem serves as a basic tool in the construction of a robust numerical scheme that can be successfully implemented in a wide variety of fluid dynamical topics. The flows covered by this exposition may be quite different in nature, yet they share some common features; they all belong to the class of compressible, inviscid, time-dependent flows. Fluid dynamical phenomena of this type often contain a number of smooth flow regions separated by singularities such as shock fronts, detonation waves, interfaces, and centered rarefaction waves. One must then address various computational issues related to this class of fluid dynamical problems, notably the “capturing” of discontinuities such as shock fronts, detonation waves, or interfaces; resolution of centered rarefaction waves where flow gradients are unbounded; and evaluation of flow variables in irregular computational cells at the intersection of a moving boundary surface with an underlying mesh.
From the mathematical point of view, the various systems of equations governing compressible, inviscid, time-dependent flow phenomena may all be characterized as systems of “(nonlinear) hyperbolic conservation laws.”
Hyperbolic conservation laws (in one space variable) are systems of time-dependent partial differential equations.
The GRP algorithm was developed in Part I and tested against a variety of analytical examples. The next challenge is to adapt it to the needs of “Scientific Computing,” that is, to implement it in the simulation of problems of physical significance. This is a formidable task for any numerical algorithm. The problems encountered in applications usually are multidimensional and involve complex geometries and additional physical phenomena. In this chapter we first describe in more detail some of these problems, as a general background for the following chapters. We then proceed to the main goal of the chapter, namely, the upgrading of the GRP algorithm (which is essentially one dimensional) to a two-dimensional, second-order scheme. To this end we recall (Section 7.2) Strang's method of “operator splitting” and then (Section 7.3) apply it to the (planar) fluid-dynamical case. Although the method can be further extended to the three-dimensional case, we confine our presentation to the two-dimensional setup, which serves in our numerical examples (Chapters 8 and 10).
General Discussion
In Part I we studied the mathematical basis of the GRP method. We also considered a variety of numerical examples for which analytic (or at least asymptotic) solutions were available. This provided us with some measure of the accuracy of the computational results, and helped identifiy potential difficulties (such as the resolution of contact discontinuities).
The GRP method was developed (Chapter 5) for compressible, unsteady flow in a duct of varying cross section. In the case of a planar two-dimensional duct, the quasi-1-D formulation is taken to be a reasonable approximation of the actual (2-D) flow. In this chapter we study a duct flow where an incident wave interacts with a short converging segment, producing interesting wave structures. An illustrative case is that of a rarefaction wave propagating through a “converging corridor,” producing (at later times) a complex “reflected” wave pattern. Such a case is studied (numerically) in this chapter, using (a) the quasi-1-D approach of Chapter 5 and (b) the full two-dimensional computation as described in Section 8.3 (with the duct contour taken as a stationary boundary). The comparison between the two computations reveals some bounds of validity of the quasi-1-D approximation. We conclude the chapter by listing (Remark 10.1) several articles describing the application of the GRP to diverse fluid-dynamical problems, including well-known test cases, shock wave reflection phenomena compared to experimental observation, and even a case where a “moving boundary” experiment is favorably compared to the corresponding GRP solution.
Consider a centered rarefaction wave that propagates in a planar duct comprising two long segments of uniform cross-sectional area joined by a smooth converging nozzle.
This overview of Fortran 90 (F90) features is presented as a series of tables that illustrate the syntax and abilities of F90. Frequently, comparisons are made with similar features in the C++ and F77 languages and the Matlab environment.
These tables show that F90 has significant improvements over F77 and matches or exceeds newer software capabilities found in C++ and Matlab for dynamic memory management, user-defined data structures, matrix operations, operator definition and overloading, intrinsics for vector and parallel processors and the basic requirements for object-oriented programming.
They are intended to serve as a condensed quick-reference guide for programming in F90 and for understanding programs developed by others.
The programming process is similar in approach and creativity to writing a paper. In composition, you are writing to express ideas; in programming, you are expressing a computation. Both the programmer and the writer must adhere to the syntactic rules (grammar) of a particular language. In prose, the fundamental idea-expressing unit is the sentence; in programming, two units – statements and comments – are available.
Composition, from technical prose to fiction, should be organized broadly, usually through an outline. The outline should be expanded as the detail is elaborated and the whole reexamined and reorganized when structural or creative flaws arise. Once the outline settles, you begin the actual composition process using sentences to weave the fabric your outline expresses. Clarity in writing occurs when your sentences, both internally and globally, communicate the outline succinctly and clearly. We stress this approach here with the aim of developing a programming style that produces efficient programs humans can easily understand.
To a great degree, no matter which language you choose for your composition, the idea can be expressed with the same degree of clarity. Some subtleties can be better expressed in one language than another, but the fundamental reason for choosing your language is your audience: people do not know many languages, and if you want to address the American population, you had better choose English over Swahili.
Fortran 90 includes several features to give the programmer the tools necessary to manage dynamic memory usage. However, one tends to think of these tools as completely free-standing statements or functions. In practice, a large code often has several related arrays or pointers that need to be created and released from memory at the same time. Basically, that means we should supply subprograms that generalize the operations provided by the intrinsic functions allocated and associated.
Here we illustrate this concept with a segment of a class that came from a classic finite element analysis system. The attributes are various types of allocatable arrays – local integers that will establish the array sizes. Additional items required to manage the memory are accessed through the use association of the module, called system_constants. The encapsulated members include initialization, debugging, and printing subprograms as well as the actual memory management members.
Figure 9.1 shows segments of the code Elem_Type_Data_Class. Here the word “type” is not used in the language sense but to identify one of about 18 possible finite elements from an existing library (such as a line, triangle, tetrahedron, etc.). Among the class attributes note that the local integer array item, line 5, serves the purpose of checking for local fatal error checks. It is sized to receive the number of subgroup allocations. Recall that the allocate function has an optional status return code, stat=, lines 36, 37, and so forth.
In Section 1.7 we outlined procedures that should be considered while conducting the object-oriented analysis and object-oriented design phases that are necessary before the OOP can begin. Here we will expand on those concepts, but the reader is encouraged to read some of the books on those subjects. Many of the references on OOA and OOD rely heavily on detailed graphical diagrams to describe the classes, their attributes and states, and how they interact with other classes. Often those OO methods do not go into any programming language–specific approaches. Our interest is on OOP, and so we usually will assume that the OOA and OOD have been completed and supplied to us as a set of tables that describe the application and possibly a software interface contract. Sometimes we will use a subset of the common OO methods diagrams to represent the attributes and members of our classes graphically. Since they are being used for OOP, the graphical representations will contain, in part, the intrinsic-data type descriptions of the language being employed as well as the derived types created with them.
The Drill Class
Our first illustration of typical OO methods will be to apply them to a common electric drill. It feeds a rotating cutting bit through a workpiece, thereby removing a volume of material. The effort (power or torque) required to make the hole clearly depends on the material of the workpiece as well as the attributes of the drill.
The preceding chapter described the programming process as starting with a clearly specified task, expressing it mathematically as a set of algorithms, translating the algorithms into pseudocode, and finally, translating the pseudocode into a “real” programming language. The final stages of this prescription work because most (if not all) computational languages have remarkable similarities: they have statements, the sequencing of which is controlled by various loop and conditional constructs, and functions that foster program modularization. We indicated how similar Matlab, C++, and Fortran are at this level, but these languages differ the more they are detailed. It is the purpose of this chapter to describe those details and bring you from a superficial acquaintance with a computational language to fluency. Today, the practicing engineer needs more than one programming language or environment. Once achieving familiarity with one, you will find that learning other languages is easy.
When selecting a programming tool for engineering calculations, one is often faced with two different levels of need. One level occurs when you need to solve a small problem quickly once, such as a homework assignment, and computational efficiency is not important. You may not care if your code takes 10 seconds or 100 seconds to execute; you want convenience. At that level it may make sense to use an engineering environment like Matlab or Mathematica.