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.
The use of object-oriented (OO) design and object-oriented programming (OOP) methods is becoming increasingly popular. Thus, it is useful to have an introductory understanding of OOP and some of the programming features of OO languages. You can develop OO software in any high-level language like C or Pascal. However, newer languages such as Ada, C++, and F90 have enhanced features that make OOP much more natural, practical, and maintainable. Appearing before F90, C++ currently is probably the most popular OOP language, yet F90 was clearly designed to have almost all of the abilities of C++. However, rather than study the new standards, many authors simply refer to the two-decade-old F77 standard and declare that Fortran can not be used for OOP. Here we will overcome that misinformed point of view.
Modern OO languages provide the programmer with three capabilities that improve and simplify the design of such programs: encapsulation, inheritance, and polymorphism (or generic functionality). Related topics involve objects, classes, and data hiding. An object combines various classical data types into a set that defines a new variable type or structure. A class unifies the new entity types and supporting data that represent its state with routines (functions and subroutines) that access or modify those data, or both. Every object created from a class, by providing the necessary data, is called an instance of the class. In older languages like C and F77, the data and functions are separate entities.
We have seen that F90 has a very strong intrinsic base for supporting the use of subscripted arrays. Fortran arrays can contain intrinsic data types as well as user-defined types (i.e., ADTs). One cannot directly have an array of pointers, but an array containing defined types that are pointers or that have components that are pointers is allowable. Arrays offer an efficient way to contain information and to insert and extract information. However, there are many times when creating an efficient algorithm dictates that we use some specialized storage method, or container, and a set of operations to act with that storage mode. The storage representation and the set of operations that are allowed for it are known as a data structure. How you store and retrieve an item from a container is often independent of the nature of the item itself. Thus, different instances of a data structure may produce containers for different types of objects. Data structures have the potential for a large amount of code reuse, which is a basic goal of OOP methods. In the following sections we will consider some of the more commonly used containers. We will begin with stacks and queues, which are illustrated in Figure 7.1.
Stacks
A stack is a data structure in which access is restricted to the last inserted object. It is referred to as a last-in first-out (LIFO) container. In other words, a stack is a container to which elements may only be inserted or removed at one end of the container called the top of the stack.
There has been an explosion of interest in, and books on, object-oriented programming (OOP). Why have yet another book on the subject? In the past a basic education was intended to result in mastery of the three r's: reading, 'riting, and 'rithmetic. Today a sound education in engineering programming leads to producing code that satisfies the four r's: readability, reusability, reliability, and real efficiency. Although some object-oriented programming languages have some of these abilities, Fortran 90/95 offers all of them for engineering applications. Thus, this book is intended to take a different tack by using the Fortran 90/95 language as its main OOP tool. With more than 100 pure and hybrid object-oriented languages available, one must be selective in deciding which ones merit the effort of learning to utilize them. There are millions of Fortran programmers, and so it is logical to present the hybrid object-oriented features of Fortran 90/95 to them to update and expand their programming skills. This work provides an introduction to Fortran 90 as well as to OOP concepts. Even with the current release (Fortran 95) we will demonstrate that Fortran offers essentially all of the tools recommended for OOP techniques. It is expected that Fortran 200X will offer additional object-oriented capabilities such as declaring “extensible” (or virtual) functions. Thus, it is expected that the tools learned here will be of value far into the future.
As we saw earlier in our introduction to OOP, inheritance is a mechanism for deriving a new class from an older base class. That is, the base class, sometimes called the super class, is supplemented or selectively altered to create the new derived class. Inheritance provides a powerful code reuse mechanism since a hierarchy of related classes can be created that share the same code. A class can be derived from an existing base class using the module construct illustrated in Figure 6.1.
We note that the inheritance is invoked by the USE statement. Sometimes an inherited entity (attribute or member) needs to be slightly amended for the purposes of the new classes. Thus, at times one may want to bring into the new class selectively only certain entities from the base class. The modifier ONLY in a USE statement allows one to select the desired entities from the base class as illustrated in Figure 6.2. It is also common to develop name conflicts when combining entities from one or more related classes. Thus, a rename modifier, =>, is also provided for a USE statement to allow the programmer to pick a new local name for an entity inherited from the base class. The form for that modifier is given in Figure 6.3.
It is logical to extend any or all of the aforementioned inheritance mechanisms to produce multiple inheritance. Multiple Inheritance allows a derived class to be created by using inheritance from more than a single base class.
Any computer program is going to have to operate on the available data. The valid data types that are available will vary from one language to another. Here we will examine the intrinsic or built-in data types and user-defined data types or structures and, finally, introduce the concept of the abstract data type, which is the basic foundation of object-oriented methods. We will also consider the precision associated with numerical data types. The Fortran data types are listed in Table 2.1. Such data can be used as constants, variables, pointers, and targets.
Intrinsic Types
The simplest data type is the LOGICAL type, which has the Boolean values of either .true. or .false. and is used for relational operations. The other nonnumeric data type is the CHARACTER. The sets of valid character values will be defined by the hardware system on which the compiler is installed. Character sets may be available in multiple languages such as English and Japanese. There are international standards for computer character sets. The two most common ones are the English character sets defined in the ASCII and EBCDIC standards that have been adapted by the International Standards Organization (ISO). Both of these standards for defining single characters include the digits (0 to 9), the 26 uppercase letters (A to Z), the 26 lowercase letters (a to z), common mathematical symbols, and many nonprintable codes known as control characters.
It is common in engineering and mathematics to employ a notation in which one or more subscripts are appended to a variable that is a member of some larger set. Such a variable may be a member of a list of scalars, or it may represent an element in a vector, matrix, or Cartesian tensor. In engineering computation, we usually refer to subscripted variables as arrays. Since programming languages do not have a convenient way to append the subscripts, we actually denote them by placing them in parentheses or square brackets. Thus, an element usually written as Ajk becomes A(j,k) in Fortran and Matlab, and A[j] [k] in C++.
Arrays have properties that need to be understood in order to utilize them correctly in any programming language. The primary feature of an array is that it must have at least one subscript. The “rank” of an array is the number of subscripts, or dimensions, it has. Fortran allows an array to have up to seven subscripts, C++ allows four, and Matlab allows only two since it deals only with matrices. An array with two subscripts is called a rank-two array, and one with a single subscript is called a rank-one array, or a vector. Matrices are rank-two arrays that obey special mathematical operations. A scalar variable has no subscripts and is sometimes called a rank-zero array. Rank-one arrays with an extent of one are also viewed as a scalar.
Domain decomposition for numerical solution of PDEs has been an active area of research, with a well-organized international conference series held annually since 1987. The area encompasses preconditioning of linear systems, discretizations, and solution of hybrid systems (e.g., coupled Navier–Stokes and Euler problems). We consider the first two of these in the context of high-order methods.
Introduction
Domain decomposition (dd) alleviates the solution complexity associated with the full problem in a complicated geometry. Broadly, the aim of dd consists in formulating independent problems in separate subdomains whose union constitutes the whole. The decomposition of the domain may be motivated by differing physics within different subdomains, by the availability of fast solvers for each subdomain, by the desire to partition the computational effort across separate processors, or by the inherent heterogeneity of the discretization. We discuss in Section 7.2 preconditioning methods such as substructuring, Schwarz overlapping, and multigrid techniques. Section 7.3 describes the mortar element method, which encompasses both functional and geometrical nonconforming discretizations; suggestions for implementation are given. Section 7.4 reviews the coupling between finite and spectral elements, provides some theoretical considerations about adaptivity near geometrical singularities, and considers for the 2D case hp-spectral triangular elements, which open the way for the coupling between quadrilaterals and triangles.
Preconditioning Methods
Domain-decomposition preconditioning has gained much attention over the past decade, both in theory and in practice.
According to the Greek philosopher Heraclitus, who used to say “πανταρ∈ι …,” daily life is concerned with the flow of ordinary fluids: water, air, blood, and so forth, in very common situations like breathing, coffee drinking, and hand washing.
Most flows are generated by nature (e.g., oceans, winds, rivers) and by human industrial activity (e.g., planes, cars, materials processing, biomedical engineering). There is a need to model fluid flow problems in order to improve the basic understanding of these complex phenomena and to increase the design quality of technological applications. With the advent of large and powerful computational tools, modeling has become more and more a substitute for direct experimentation. In some circumstances, experimentation may be too expensive – particularly if it leads to the destruction of the facility – or even impossible to perform, so that modeling is the only reasonable way to get answers and to study a range of parameters for optimal design.
Viscous Fluid Flows
We know from experience that many flows are set into motion by shear forces, and hence viscous effects play a vital role in fluids. In general, the viscosity depends on the shear rate (roughly speaking, the velocity gradient), as is explained by non-Newtonian theory. In this book, however, we will restrict ourselves mainly to the case of viscous Newtonian incompressible fluids in isothermal situations or under the influence of thermal convection as described by the Boussinesq approximation.
High-order methods have gained increasing attention in recent years. Their theoretical development has reached a high level of sophistication, and at the same time the range of applications has been broadening, including such diverse topics as global atmospheric modeling, aerodynamics, oceanography, thermal convection, and theoretical chemistry. Specialized conferences on the subject like the International Conference on Spectral Applications and High-Order Methods (ICOSAHOM) have been launched to bring mathematicians, engineers, and computer scientists together in order to stimulate further work in the field and to prospect new areas: high-order time schemes, treatment of singularities, complex geometries, mixed discretization techniques, domain decomposition, and parallelism. These topics were once considered as the stumbling block of spectral methods. As time goes on, this is no longer true, and high-order methods apply more and more to real-life engineering problems.
The monograph by Gottlieb and Orszag [163] and the book by Canuto et al. [64] remain milestones in the subject. They are cited in almost every paper written on the topic. Gottlieb and Orszag's monograph was the first on the subject and contains very little about applications. Moreover, it is silent on the topics mentioned above. Most of the developments covered by Canuto et al. are devoted to simple geometries, but a last chapter entitled “Domain Decomposition Methods” introduces extensions to more complex geometries. Recent achievements in the field of high-order methods have far-reaching consequences for geometrically complex configurations.