10 APPLIED COMPUTATIONAL FLUID DYNAMICS TECHNIQUESElement Pass 1: Count the number of elements connected to each point Initialize esup21:npoin+1=0!. Update storage counter and store esup
Trang 110 APPLIED COMPUTATIONAL FLUID DYNAMICS TECHNIQUES
Element Pass 1: Count the number of elements connected to each point
Initialize esup2(1:npoin+1)=0
! Update storage counter, storing ahead
! Update storage counter and store
esup2(ipoin)=esup2(ipoin)+esup2(ipoin-1)
enddo
Element pass 2: Store the elements inesup1
! Update storage counter, storing in esup1
2.2.2 POINTS SURROUNDING POINTS
As with the number of elements that can surround a point, the number of immediateneighbours or points surrounding a point can vary greatly for an unstructured mesh Thebest way to store this information is in a linked list This list will be denoted by
psup1(1:mpsup), psup2(1:npoin+1),
where, as before, psup1 stores the points, and the ordering is such that the points rounding pointipoinare stored in locationspsup2(ipoin)+1topsup2(ipoin+1)
Trang 2sur-The construction of psup1, psup2makes use of the element–surrounding-point mation stored inesup1, esup2 For each point, we can find the elements that surround
infor-it from esup1, esup2 The points belonging to these elements are the points we arerequired to store In order to avoid the repetitive storage of the same point from neighbouringelements, a help-array of the formlpoin(1:npoin)is introduced As will become evident
in subsequent sections, help-arrays such as lpoin play a fundamental role in the fastconstruction of derived data structures As the points are being stored inpsup1andpsup2,their entry is also recorded in the arraylpoin As new possible nearest-neighbour candidatepoints emerge from theesup1,esup2andinpoellists,lpoinis consulted to see if theyhave already been stored
Algorithmically,psup1andpsup2are constructed as follows:
Initialize: lpoin(1:npoin)=0
Initialize: psup2(1)=0
Initialize: istor =0
! Loop over the elements surrounding the point
do iesup=esup2(ipoin)+1,esup2(ipoin+1)
if(jpoin.ne.ipoin and lpoin(jpoin).ne.ipoin) then
! Update storage counter, storing ahead, and mark lpoin
lhash(1:mhash),
wheremhashdenotes the maximum possible number of entries or subdivisions of the datarange The key idea is that one can use the sparsity of neighbours of a given point to reducethe storage required fromnpoinlocations forlpointomhash, which is typically a fixed,relatively small number (e.g.mhash=1000) In the algorithm described above, the arraylhash replaces lpoin Instead of storing or accessinglpoin(ipoin), one accesseslhash(1+mod(ipoin,mhash)) In some instances, neighbouring points will have thesame entries in the hash table These instances are recorded and an exhaustive comparison iscarried out in order to see if the same point has been stored more than once
Trang 312 APPLIED COMPUTATIONAL FLUID DYNAMICS TECHNIQUES2.2.3 ELEMENTS SURROUNDING ELEMENTS
A very useful data structure for particle-in-cell (PIC) codes, the tracking of particles forstreamline and streakline visualization, and interpolation in general is one that stores theelements that are adjacent to each element across faces (see Figure 2.3) This data structurewill be denoted by
esuel(1:nfael, 1:nelem),
wherenfaelis the number of faces per element
In order to construct this data structure, we must match the points that comprise any ofthe faces of an element with those of a face of a neighbour element In order to acquire thisinformation, we again make use ofinpoel,esup1andesup2, and help-arrayslpoinandlhelp
Theesuelarray is built as follows:
Initialize: lpoin(1:npoin)=0
Initialize: esuel(1:nfael,1:nelem)=0
! Obtain the nodes of this face, and store the points in lhelp
nnofa=lnofa(ifael)
lhelp(1:nnofa)=inpoel(lpofa(1:nnofa,ifael),ielem)
! Loop over the elements surrounding the point
do istor=esup2(ipoin)+1,esup2(ipoin+1)
if(jelem.ne.ielem) then
do jfael=1,nfael ! Loop over the element faces
! Obtain the nodes of this face, and checknnofj=lnofa(jfael)
if(nnofj.eq.nnofa) thenicoun=0
do jnofa=1,nnofa ! Count the nr of equal pointsjpoin=inpoel(lpofa(jnofa,jfael),jelem)icoun=icoun+lpoin(jpoin)
enddoif(icoun.eq.nnofa) thenesuel(ifael,ielem)=jelem! Store the elementendif
endifenddo
endif
enddo
enddo
Trang 4k l
m
c
esuel(1,i)=k esuel(2,i)=l esuel(3,i)=m
Figure 2.3.esuelentries
Whilelhelp(1:nnofa)is a small help-array,
lnofa(1:nfael) and lpofa(1:nnofa,1:nfael)
contain the data that relates the faces of an element to its respective nodes Figure 2.4 showsthe entries in these arrays for tetrahedral elements
} Face 1} Face 2} Face 3} Face 4
Figure 2.4 Face-data for a tetrahedral element
The generalization to grids with a mix of different elements is straightforward Thealgorithm described may be improved in a number of ways First, the point chosen to accessthe neighbour elements via esup1 and esup2 (ipoin) can be chosen to be the onewith the smallest number of surrounding elements Secondly, once the neighbourjelem
of elementielemis found,ielemmay be stored with very small additional search cost
in the corresponding entry of esuel(1:nfael,jelem) This effectively halves CPUrequirements A third improvement, which is relevant mostly to grids with only one type ofelement and vector machines, is to obtain all the neighbours of the faces coalescing at a point
Trang 514 APPLIED COMPUTATIONAL FLUID DYNAMICS TECHNIQUES
at once For the case of tetrahedra and hexahedra, this implies obtaining three neighbours forevery point visited withesup1andesup2 The coding of such an algorithm is not trivial,but effective: it again halves CPU requirements on vector machines
2.2.4 EDGES
Edge representations of discretizations are often used to reduce the CPU and storage ments of field solvers based on linear (triangular, tetrahedral) elements They correspond tothe graph of the point–surrounding-point combinations However, unlikepsup1andpsup2,they store the endpoints in pairs of the form
require-inpoed(1:2,1:nedge),withinpoed(1,iedge) <inpoed(2,iedge).
For linear triangles and tetrahedra the edges correspond exactly to the physical edges
of the elements For bi/trilinear elements, as well as for all higher order elements, thiscorrespondence is lost, as ‘internal edges’ will appear (see Figure 2.5)
Physical Edges Numerical Edges
Figure 2.5 Physical and internal edges for quad-elements
The edge data structure can be constructed immediately frompsup1 andpsup2, ordirectly, using the same algorithm as described forpsup1 and psup2 above The onlymodifications required are:
(a) anifstatement in order to satisfy
inpoed(1,iedge) < inpoed(2,iedge), and
Trang 6are simply all the entries for which
esuel(1:nfael,1:nelem)=0.
However, a significant storage penalty has to be paid if the external faces are obtained in thisway: bothesuelandesup1(required to obtainesuelefficiently) are very large arrays.Therefore, alternative algorithms that require far less memory have been devised
Assuming that the boundary points are known, the following algorithm is among the mostefficient
Step 1: Store faces with all nodes on the boundary
Initialize: lpoin(1:npoin)=0
Initialize: nface=0
! Obtain the nodes of this face, and store the points in lhelp
bface(1:nnofa,nface)=lhelp(1:nnofa)) ! Store the faceendif
enddo
enddo
After this first step, faces that have all nodes on the boundary, yet are not on theboundary, will be stored twice An example of the equivalent 2-D situation is illustrated inFigure 2.6
11 12
13
Figure 2.6 Interior faces left after the first pass
Trang 716 APPLIED COMPUTATIONAL FLUID DYNAMICS TECHNIQUESThese faces are removed in a second step.
Step 2: Remove doubly defined faces This may be accomplished using a linked list that
stores the faces surrounding each point, and then removing the doubly stored faces using alocal exhaustive search
Initialize: lface(1:nface)=1
Build the linked list fsup1(1:nfsup), fsup2(npoin+1) that stores the facessurrounding each point using the same techniques outlined above for
esup1(1:nfsup), esup2(npoin+1)
! Outer loop over the faces surrounding the point
do istor=fsup2(ipoin)+1,fsup2(ipoin+1)-1
if(lface(iface).ne.0) then
! See if the face has been marked ⇒
! Inner loop over the faces surrounding the point:
do jstor=istor+1,fsup2(ipoin+1)
if(iface.ne.jface) thenif: Points of iface, jface are equal then
lface(jface)=0endif
endifenddo
endif
enddo
Retain all faces for which lface(iface).ne.0
Given the inpoel, inpoed and inpoe1 arrays, the construction of inedel isstraightforward:
Trang 8do ielem=1,nelem ! Loop over the elements
2 3
4
5 6
Figure 2.7 Edges of a tetrahedral element
2.3 Derived data structures for dynamic data
In many situations (e.g during grid generation) the data changes constantly Should deriveddata structures be required, then linked lists will not perform satisfactorily This is becauselinked lists, in order to achieve optimal storage, require a complete reordering of the dataeach time a new item is introduced A better way of dealing with dynamically changing data
is the N-tree
Trang 918 APPLIED COMPUTATIONAL FLUID DYNAMICS TECHNIQUES2.3.1 N-TREES
Suppose the following problem is given: find all the faces that surround a given point Onecould use a linked listfsup1, fsup2as shown above to solve the problem efficiently.Suppose now that the number of faces that surround a point is changing constantly A situationwhere this could happen is during grid generation using the advancing front technique Inthis case the arraysfsup1andfsup2have to be reconstructed each time a face is eithertaken or added to the list Each reconstruction requires several passes over all the facesand points, making it very expensive Recall that the main reason for using linked listswas to minimize storage requirements The alternative is the use of an array of the formfasup(1:mfsup,1:npoin), wheremfsupdenotes the maximum possible number offaces surrounding a point As this number can be much larger than the average, a great waste
of memory is incurred A compromise between these two extremes can be achieved by using
so-called N-trees An array of the formfasup(1:afsup,1:mfapo)can be constructed,whereafsupis a number slightly larger than the average number of faces surrounding apoint The idea is that in most of the instances, locations1:afsup-1will be sufficient tostore the faces surrounding a point Should this not be the case, a ‘spill-over’ contingency isbuilt in by allowing further storage at the bottom of the list This can be achieved by storing
a markeristorin locationfasup(afsup,ipoin)for each pointipoin, i.e
istor=fasup(afsup,ipoin).
As long as there is storage space in locations1:afsup-1andistor.ge.0a face can
be stored Should more thanafsup-1faces surround a point, the markeristoris set tothe negative of the next available storage location at the bottom of the list An immediatereduction of memory requirements for cases when not all the points are connected to a face(e.g boundary faces) can be achieved by first defining an arraylpoin(1:npoin)over thepoints that contain the placeifapoinfasupwhere the storage of the faces surroundingeach point starts It is then possible to reducemfapoto be of the same order as the number
of facesnface To summarize this N-tree, we have
lpoin(ipoin): the place ifapo in fasup where the storage of the faces
surrounding point ipoin starts,fasup( afsup, ifapo) : >0 : the number of stored faces
<0 : the place jfapo in fasup where thestorage of the faces surrounding point ipoin
is continued,fasup(1:afsup-1,ifapo) : = 0 : an empty location
>0 : a face surrounding ipoin
In two dimensions one typically has two faces adjacent to a point, soafsup=3, whilefor 3-D meshes typical values areafsup=8-10 Once this N-tree scheme has been set up,storing and/or finding the faces surrounding points is readily done The process of adding
a face to the N-treelpoin, fasupis shown in Figure 2.8 Faces f1andf2surroundpointipoin Facef3is also attached toipoin The storage space infasup(1:afsup-1,ifapo)is already exhausted withf1,f2 Therefore, the storage of the faces surroundingipoinis continued at the end of the list
Trang 10nfapo nfapo+1
Figure 2.8 Adding an entry to an N-tree
N-trees are not only useful for face/point data Other applications include edges rounding points, elements surrounding points, all elements surrounding an element, pointssurrounding points, etc
sur-2.4 Sorting and searching
This section will introduce a number of searching and sorting algorithms and their associateddata structures A vast number of searching and sorting techniques exist, and this topic isone of the cornerstones of computer science (Knuth (1973)) The focus here will be on thosealgorithms that have found widespread use for CFD applications
Consider the following task: given a set of items (e.g numbers in an array), order themaccording to some property or key (e.g the magnitude of the numbers) Several ‘fast sorting’algorithms have been devised (Knuth (1973), Sedgewick (1983)) Among the most often usedare: binsort, quicksort and heapsort While the first two perform very well for static data, thethird algorithm is also well suited to dynamic data
A way must now be devised to add or delete entries from such an ordered tree withoutaltering the ordering
Trang 1120 APPLIED COMPUTATIONAL FLUID DYNAMICS TECHNIQUES
E 1.
L M
5 6.
A 7.
Figure 2.9 Heap list: addition of entries
Suppose the array to be ordered consists of nelem elements and is denoted bylelem(1:nelem) with associated keys relem(1:nelem) The positions of theson or the father in the heap list lheap(1:nelem) are denoted by ipson andipfath, respectively Accordingly, the element numbers of the son or the father in thelelemarray are denoted by ieson andiefath Then ieson=lheap(ipson) andiefath=lheap(ipfath) From Figure 2.9 one can see that the two sons of positionipfathare located atipson1=2∗ipfathandipson2=2*ipfath+1, respectively
2.4.1.1 Adding a new element to the heap list
The idea is to add the new element at the end of the tree If necessary, the internal order of
the tree is re-established by comparing father and son pairs Thus, the tree is traversed from
the bottom upwards A possible algorithmic implementation would look like the following:
lheap(nheap)=ienew ! Place the new element at the end of the heap listipson=nheap ! Set the positions in the heap list for father and sonwhile(ipson.ne.1):
Trang 12In this way, the element with the smallest associated keyrelem(ielem)remains atthe top of the list in positionlheap(1) The process is illustrated in Figure 2.9, where theletters of the word ‘example’ have been inserted sequentially into the heap list.
2.4.1.2 Removing the element at the top of the heap list
The idea is to take out the element at the top of the heap list, replacing it by the element
at the bottom of the heap list If necessary, the internal order of the tree is re-established by
comparing pairs of father and sons Thus, the tree is traversed from the top downwards.
A possible algorithmic implementation would look like the following:
! Place the element stored at the end of the heap list at the top:
lheap(1)=lheap(nheap)
It is easy to prove that both the insertion and the deletion of an element into the heap list
will take O(log (nheap)) operations (Williams (1964), Floyd (1964)) on average