You are on page 1of 87

Lehrstuhl fur Bauinformatik Technische Universitt Munchen a

Master Thesis

On MpCCI as a coupling library for Fluid-Structure Interaction with CFX


Ozgur Gurses
Matr. Nr.: 2628532

Supervisior: Dipl.-Ing. S. Kollmannsberger

ogurses@yahoo.com

Acknowledgements

I would like wholeheartedly and genuinely thank to Univ. Prof. Dr. K.Uwe Bletzinger and Prof.Dr.rer.nat.Ernst Rank for their guidance and kindness throughout this work. Their patience as advisors, their limitless energy while teaching and passion kept in deep for research are to be commended. I am indebt to Dipl-Ing. S. Kollmannsberger for enhancing my knowledge by his questions and rationalistic advices despite his busy schedule. A special thank goes to the sta of Lehrsthle fr Statik und Bauinformatik which u u helped me to enter the exciting harmony of computations and computers. I would like to thank all those friends who have gave me their support during the completion of this work. Most importantly, I would like to thank my family for their boundless support and love. Their encouragement makes everything easier to achieve.

ii

Abstract On MPCCI as a coupling library for Fluid-Structure Interaction with CFX One major simplication made when calculating physical behaviour is to take one eld into account. While this may often be sucient, some engineering problems require to consider two or more elds. For a exible structure submerged in a uid, the interaction of the uid with the structure may be the driving mechanism characterising its behaviour. For the individual disciplines sophisticated solvers exists. Dierent solution methods for various ow problems have been developed. Various numerical methods and code implementations have been used to increase the quality of the results. In order to nd a common basis of comparison, a set of benchmark problems have been dened. In view of the results of previous numerical tests a commercial robust uid solver ANSYS-CFX was chosen. MpCCI is a communication library to which ANSYS-CFX provides an interface. Goal of this thesis was to assess this interface such that a structural solver could be connected to this interface. Therefore, the major steps had to be followed. First to assess the uid solver by calculating a cylinder submerged in a uid benchmark. Second to write a dummy structural code providing an interface to MpCCI and nally to couple the both codes such that an algorithmic coupling was possible.

iii

Contents

List of Figures 1. Introduction 1.1. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2. Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3. Outline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. Denition of the Test Cases 2.1. Test Cases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2. Test Case 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1. Geometry and Boundary Conditions . . . . . . . . . . . . . . 2.2.2. Computational Grid . . . . . . . . . . . . . . . . . . . . . . . 2.3. Test Case 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1. Geometry and Boundary Conditions . . . . . . . . . . . . . . 2.3.2. Computational Grid . . . . . . . . . . . . . . . . . . . . . . . 2.4. Mesh Quality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1. Determinant . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.2. Warpage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.3. Angle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5. Error Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1. Modelling Error . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.2. Iteration Error . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.3. Discretisation Error . . . . . . . . . . . . . . . . . . . . . . . .

vi 1 1 1 2 3 3 3 3 5 8 8 8 9 10 10 10 10 10 11 11

iv

Contents 3. MpCCI 3.1. Coupling Concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2. MpCCI:Mesh-Based Parallel Code Coupling Interface . . . . . . . . . 3.3. MpCCI Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1. Naming Conventions and Descriptions . . . . . . . . . . . . . 3.3.2. Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.3. Coupling Denition . . . . . . . . . . . . . . . . . . . . . . . . 3.4. MpCCI Input File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1. Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. Moving Boundaries 4.1. Outline of achieveing a Bi-Directional coupling via MpCCI . . . . . . 4.1.1. AdhoC Dummy Code . . . . . . . . . . . . . . . . . . . . . . 4.1.2. Implementation of MpCCI on a written Dummy Structure Code and CFX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.3. CFX Expression Language (CEL) . . . . . . . . . . . . . . . . 4.1.4. Monitor Points . . . . . . . . . . . . . . . . . . . . . . . . . . 5. Discussion of the Results 5.1. Discussion of the Results of the Test Case 1 . . . . . . . . . . . . . . 5.1.1. Comparision of Coarse Meshes . . . . . . . . . . . . . . . . . . 5.2. Discussion of the Results of the Test Case 2 . . . . . . . . . . . . . . 5.2.1. Eect of Velocity Change . . . . . . . . . . . . . . . . . . . . 5.2.2. Eect of Grid Type . . . . . . . . . . . . . . . . . . . . . . . . 6. Concluding Remarks and Recommendations References A. THE DUMMY CODE B. PYTHON SCRIPT 31 33 34 36 36 37 38 38 38 53 54 55 76 12 12 12 14 15 15 16 25 26 30 30 30

List of Figures

2.1. Dimensions of the Test Case 1 . . . . . . . . . . . . . . . . . . . . . . 2.2. Hexahedral mesh. An example of a structured mesh. . . . . . . . . . 2.3. Hexahedral mesh detail around the cylinder. . . . . . . . . . . . . . . 2.4. Coarse mesh with prismatic elements. An example of an unstructured mesh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 5 5 6 6 7 7 8 13 31 40 41 42 43 44 45 46

2.5. Fine mesh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6. Very ne mesh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7. Optimal mesh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.8. Dimensions of the Test Case 2 . . . . . . . . . . . . . . . . . . . . . . 3.1. Coupling Scheme [1] . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1. Parts of Adhoc Dummy . . . . . . . . . . . . . . . . . . . . . . . . . 5.1. lift and drag forces [0-20 s.] (Test Case 1) . . . . . . . . . . . . . . . 5.2. lift and drag forces [0-5 s.] (Test Case 1) . . . . . . . . . . . . . . . . 5.3. lift and drag forces [10-15 s.] (Test Case 1) . . . . . . . . . . . . . . . 5.4. Comparision of coarse meshes that have dierent thickness [0-20 s.] (Test Case 1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5. Comparision of coarse meshes that have dierent thickness [0-5 s.] (Test Case 1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6. Comparision of coarse meshes that have dierent thickness [10-15 s.] (Test Case 1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7. Values for lift and drag forces. The results shown are calculated for the last 5 seconds . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

vi

LIST OF FIGURES 5.8. lift and drag forces around the cylinder and ag (CFD1,M1 ) . . . . . 5.9. lift and drag forces around the cylinder and ag (CFD2,M1 ) . . . . . 5.10. lift and drag forces around the cylinder and ag (CFD2,M2 ) . . . . . 5.11. lift and drag forces around the cylinder and ag (CFD2,M3 ) . . . . . 5.12. lift and drag forces around the cylinder and ag (CFD3,M1 ) . . . . . 5.13. lift and drag forces around the cylinder and ag (CFD3,M2 ) . . . . . 5.14. lift and drag forces around the cylinder and ag (CFD3,M3 ) . . . . . 46 47 48 49 50 51 52

vii

1. Introduction
1.1. Motivation
The Finite Element Method (FEM) is a widely used technique to solve all sorts of dierential equations. It is an approximation method for engineering problems which usually cannot be solved analytically. There are dierent FE implementations each adjusted to the discipline and degree of complexity of the problems. Generally, major FE-based analysis codes have specialized in and restricted themselves to a single analysis discipline like, structural, uid, thermal etc. However, scientists and engineers are sometimes interested in handling problems concerning the interaction of these elds. These multidisciplinary approaches are known as coupled problems and require signicant eort to be solved. There are two ways to solve a coupled problem.
Internally Coupled Analysis- coupling through internal data structures. (MSC.Dytran,

ADINA)
Externally Coupled Analysis- coupled through boundary data exchanged be-

tween separate solvers. (MpCCI -coupling library) [8] Internal coupling provides better compatibility between the exchanging variables and values of the participating disciplines. External coupling provides the combination of the powerful solvers.

1.2. Objectives
This thesis emerges from a research project worked on at the Chair of Bauinformatik at the Technical University of Munich. The primary objective of this thesis is to

1. Introduction perform a series of numerical simulations and to check the suitability of ANSYS-CFX with MpCCI library by means of coupling with a self written dummy code [7]. Besides, as a major task, in order to reduce computational costs while being economical in terms of calculation time, optimal mesh studies were performed. Structured and unstructured meshes were constructed with ICEM-CFD and Domesh, respectively. The results obtained were compared. The name of the communication library MpCCI drifts the readers into the expectation of that a speed-up of an analysis by a parallel computation research is a part of work. Although it would be an interesting task for a future study, this research does not attempt to perform parallel computations. Furthermore, it is an applicationbased study. Hence, presentation of theoretical knowledge or formulations is out of scope.

1.3. Outline
In Chapter 2, denitions of the study cases are given. Some comments about the grids formation and their quality checks as well as an outlook over error analysis can also be found here. Chapter 3 describes in detail the parts of the required MpCCI input le. Besides, denitions of the basic functions that are used in coupling are given. Moving boundary concept is studied in detail in Chapter 4. Chapter 5 is dedicated to the discussion of the results. Several graphical and tabulated results are presented. Finally, in Chapter 6, conclusions to this work are drawn and suggestions for further research are recommended.

2. Denition of the Test Cases


This chapter starts with the denition of the test cases, then continues with the computational grids and parameters that are required for the numerical computations. Besides, error analysis will be covered.

2.1. Test Cases


In the scope of this thesis, two dierent test cases are studied. The rst one is based on the classical DFG laminar ow around cylinder benchmark test for Re=100 [9]. It is simulated to check the numerical computation capability of CFX, as well as to generate optimum meshes which provide ecient simulations in relation to time and memory. The optimum mesh will later be used as a template for the meshes of the second test case. The second test [7]is the uid part of a uid part interaction test case dened in section2.3. For the sake of easiness, the names test case 1 and test case 2 are used to refer to the both benchmarks, respectively.

2.2. Test Case 1


2.2.1. Geometry and Boundary Conditions
The conguration of the test case 1 is depicted in gure 2.1. A 2-dimensional channel with a length of 2.2 m, a height of 0.41 m is dened as a domain. The radius of the circular hole inside the domain is 0.1 m and the centre of it is located at B (0.2, 0.2). The cylinder is mounted slightly o the symmetry axis in order to trigger the von Karman vortex shedding as soon as possible. In future it is planned to

2. Denition of the Test Cases calculate 3D uid-structure interaction and the structure code ([6]) is especially suited to investigate 3D structures. In order to change the setup as little as possible it was decided to calculate this 2D benchmark with a 3D setup. To simulate 2D behaviour with a 3D calculation, the third dimension z was discretised with one element only and symmetrical boundary conditions were applied in z direction in the x-y plane. The depth is varied in a study (section 5.1.1) to study the eect of the chosen depth and resulting unfavourable element ratio.

Figure 2.1.: Dimensions of the Test Case 1

On the upper and the lower walls and around the cylinder boundary condition is dened as no-slip condition. That is, the velocity of the uid on the wall and the velocity on the walls are the same. All the surfaces with no-slip boundary condition have zero velocity. The inlet part (gure 2.1) has a parabolic velocity distribution with its maximum velocity in the center of the domain at y=0.205 m. To have a smoother start without numeric instabilities and to trigger the vortex shedding, the parabolic inow velocity is blended in within one second by a cosine function and remains constant afterwards. The outlet has a do nothing boundary condition.

2. Denition of the Test Cases

2.2.2. Computational Grid


The domain of the test case is divided into number of elements to get a discrete representation. This procedure is called discretization. Through discretization, a set of algebraic equations are obtained from the dierential equations. These algebraic equations are solved and related values are extracted from the results. Basically, there are two types of grid structure used for the computations, structured and unstructured grids. In a structured grid the elements edges are mainly oriented along the coordinate axis of the domain whereas in an unstrucured grid the elements are created randomly. Unstructured meshes are easier to create, however structured ones lead to more accurate results with the same amount of elements.

Figure 2.2.: Hexahedral mesh. An example of a structured mesh.

Figure 2.3.: Hexahedral mesh detail around the cylinder. Five meshes are tested in the numerical simulation. A structured mesh with hexahedral elements and four more with unstructured prismatic elements. They are

2. Denition of the Test Cases

Figure 2.4.: Coarse mesh with prismatic elements. An example of an unstructured mesh.

Figure 2.5.: Fine mesh.

named Hexa, DoMeshCoarse, DoMeshFine, DoMeshVeryFine and DoMeshOptimal. The unstructured grids are investigated rst since it is an easy and a fast way of meshing the geometries with curved edges. A programme called Domesh
1

which is

developed at the chair of Bauinformatik (TUM) is used to obtain unstructured grids. The dierence between DoMeshCoarse (gure 2.4) and DoMeshFine (gure 2.5) is the element size around the cylinder region. As the given names imply the latter one has smaller elements. DoMeshVeryFine (gure 2.6) has considerably ner elements not only around the cylinder part but also anywhere in the domain. The number of elements is almost ve times larger than DomesFines. After the analysis of the results of the rst four meshes an optimized mesh is chosen. Hexahedral elements, for the structured grid, are created with a commercial programme called ANSYSICEM-CFD-5.0. Blocking strategy is utilized to divide the domain into smaller parts. These blocks are then meshed with a macro from the assigned number of elements at its boundaries. O-grid is a robust technique to improve the mesh quality. This technique is facilitated when it is desired to mesh a circular or O-type mesh around
1

Interfacing DO MESH, Lehrstuhl fr Bauinformatik, TU Muenchen, 2000 u

2. Denition of the Test Cases

Figure 2.6.: Very ne mesh.

Figure 2.7.: Optimal mesh.

an object (gure). Roughly speaking a big block (sometimes blocks) is transformd to 5 sub blocks. Elements are kept ne around the cylinder. In the rest of the domain relatively coarser elements are preferred to reduce the computation eort. The thickness is chosen to be the maximum element size (0.04 m.) so that the element ratio stays within reasonable bounds. (Table 2.1 )

Mesh Name Hexa DoMeshCoarse DoMeshFine DoMeshVeryFine DoMeshOptimal

Number of nodes 13700 5442 8720 43682 25568

Number of elements 6636 4996 7568 42608 24932

Maximum Element Ratio 7.526 16.243 37.197 39.894 11.841

Table 2.1.: Mesh properties

2. Denition of the Test Cases

2.3. Test Case 2


2.3.1. Geometry and Boundary Conditions
Test case 2 has the same geometric dimensions as the test case 1. Additionally, a ag part is attached to the right side to the cylindrical hole (2.8). The tip of the tail is located 0.6 m away from the origin. Like the cylinder, the ag is assigned a no-slip boundary condition. The AdhoC Dummy code creates a structure composed of three plates which surrounds the tail part and forces tail to move up and down. For the details it is referred to section 4.1.4

Figure 2.8.: Dimensions of the Test Case 2 Three dierent inlet velocities are used (Table 2.2). CFD1, CFD2, and CFD3 dier only in the average velocities 0.3m/s, 1.0m/s, and 2.0m/s, respectively while the geometry stays xed as depicted in gure 2.8

2.3.2. Computational Grid


Three dierent hexahedral meshes are investigated for this test case 2. They are labelled as M1, M2 and M3. Table 2.3 shows the numbers of elements of each grid. CFD1 is tested only with mesh M1 since the ow develops to a steady-state and

2. Denition of the Test Cases CFD1 CFD2 CFD3 Uave = 0.3 m/s Uave = 1.0 m/s Uave = 2.0 m/s

Table 2.2.: Average Velocity

the mesh is ne enough to simulate the ow with the required accuracy. CFD2 and CFD3 are tested applying all of the mesh samples (Table 2.3). Mesh Name Number of hexa elements M1 11.984 M2 136.308 M3 269.328

Table 2.3.: Mesh information of the Test Case 2

2.4. Mesh Quality


The solution phase is the most time-consuming part of the FE analysis. The time needed is directly aected by the mesh used. A mesh of good quality should fulll certain conditions. The size of the elements should be chosen properly. Coarse meshes usually dont provide good results since a too coarse discretization of the domain is not expensive but leads to poor results. On the other hand, the ner the mesh, the more time required. Hence, a mesh providing an optimal solution between the two extremes has to be found. The biggest problem of meshing in the test cases is to assign a good quality mesh by putting rectangular elements around the cylinder and/or ag section. A grid is consists of blocks and blocks have four edges (note we only regard the 2D case here, for the 3D-Mesh is obtained by extrusion). The lines opposite to the each other have to have the same sampling. Additionally, these edges bounding the blocks are at the same time bounding the neighbour blocks such that this eect carries over until the boundaries of the domain. Although good quality local meshes are possible, the global mesh might be spoiled by this carry-over eect. At this point some remarks can be made about the quality of the grids. There are three criteria used to check the mesh quality.

2. Denition of the Test Cases

2.4.1. Determinant
Determinant takes a value between 0 and 1. 1 represents a perfect hexahedral cube whereas 0 represents a cube that has one or more degenerated edges. Determinants value above the 0.3 is acceptable.

2.4.2. Warpage
Maximum internal angle deviation from 90 degrees is checked with this quality criterion. Dierent solvers have dierent tolerance values. Therefore, for the tolerance limits solvers should be checked. Internal angles are small if the cells are distorted.

2.4.3. Angle
The level of cell distortion is determined with the warpage check. Degree of the warpage is increased if the nodes that make elements are distorted in plane direction. Minimum value is 0 and maximum is 90.

2.5. Error Analysis


Without any study of errors and uncertainties a CFD simulation cannot be assessed properly. There are possible error sources. Some these errors can be classied as modelling error, discretisation error, iteration error, etc.

2.5.1. Modelling Error


The modelling error emerges from the simplications. That is, the real physical problem is reduced to a mathematical problem through modelling. This is a crucial part of the simulation, since the modelling assumptions decide how close the simulation results are to your engineering problem. Fluid models are simplied by reducing some terms of governing equations to only the terms having the biggest inuence on the problem to be calculated.

10

2. Denition of the Test Cases

2.5.2. Iteration Error


Numerical methods inevitably produce iteration errors. There are some techniques to judge how accurate the computation is. One of them is to make a convergence study of the method. If the dierence between the results of the successive iteration steps gets smaller, the result is getting closer to the answer. This is certied for the methods used here. In other words, the result is converging to the solution. Computers are prone to round o errors. Sincethe oating numbers get discrete values, they have to be truncated up to certain precision level. These errors are accumulated and magnied with the increasing numbers of iteration loops necessary and might accumulate and aect the results. For CFX there is an option to limit the cut o error up to e-20 level. Hence, arrangement of the cut o error is not a problem for the computation.

2.5.3. Discretisation Error


The modelling error stems from simplication. However, this simplication phase is not enough to reach a solution. A decision has to be made about the method which will be used. Simplied problems can be solved analytically or numerically. Most engineering tasks need numerical computation. To make a numerical simulation the domain often has to be discretized to get a nite number of degrees of freedom. If the number of degrees of freedom is increased the solution is expected to improve. This error may be evaluated by comparison of two succesive discretizations (When it is done hierarchically, it is also possible to assess the order of this error ).

11

3. MpCCI
3.1. Coupling Concept
The exchange of variables dened on an interface may have to be done only in one direction. One code then exports the variables which in turn are imported by the other code. Depending on the application, a two-way coupling might be required in which both code have to send and receive. Furthermore, data exchange may be required at every time step or at certain time steps only. MpCCI is a library which oers the functionality needed for this data exchange. It also provides a framework with which the coupling algorithm of calculation may be progressed.

3.2. MpCCI:Mesh-Based Parallel Code Coupling Interface


MpCCI [2] is an application independent code coupling interface for multidisciplinary applications. The library has been developed at the Fraunhofer-Institute for Algorithms and Scientic Computing (SCAI). The main goal of this software is to enable users to combine dierent stand-alone simulation codes. Dierent solvers for the solution of coupled problems may be integrated without much eort. MpCCI provides an exchange of mesh based quantities between two or more simulation codes in the coupling area. Since dierent simulation codes generally possess incompatible numerical grids, MpCCI performs an interpolation or several methods of conservative mapping of the quantities dened thereon. In other words, the meshes of the codes do not have to match at the coupling region (Figure 3.1). This mapping (and the necessary neighbourhood search) is done even if the coupling region is distributed

12

3. MpCCI over dierent processes. By using the MpCCI coupling library for coupled solutions the functionality of every simulation code is preserved. There is no need to reprogram the new simulation packages for specic applications. It is very exible and can be applied to various problems such as uid-structure, uid-uid, structure-thermo, uid-acoustic-interaction, etc. MpCCI can be adjusted by the user to demand the specic needs and therefore is applicable to almost every kind of multidisciplinary problems. As mentioned before, the necessity for this library came from the demand

Figure 3.1.: Coupling Scheme [1]

for generating a general environment for coupling of any simulation code to another. The basic notions of MpCCI are loose couplings between codes, minimal source code changes, minimal knowledge requirement of the other codes, facility of sequential, distributed, parallel execution and portability. It is possible to use dierent coupling areas like lines, surfaces, and volumes. For parallel simulation codes MpCCI distinguishes the separation of code internal and external communication. Although the source code is completely written in C++, language interfaces for both FORTRAN and C are also available. Additionally, MpCCI enables users to control facilities like convergence checks, monitoring and debugging. MpCCI is available on the following platforms[3]:

13

3. MpCCI
SUN (Solaris) SGI (IRIX) IBM (AIX) Hitachi Fujitsu VPP CRAY T3E (UNICOSmk) PC (WINDOWS NT) PC (Linux)

3.3. MpCCI Functions


The general structure of the application interface of MpCCI depends on the coupling algorithm, but generally can be assigned to three major steps:
Initialisation: Denition of partitions, nodes, elements, grids, parameters, etc. Coupling: Sending and receiving MpCCI messages. Termination: Closing the coupling phase.

The section 3.3.3 gives a short and basic information about the subroutines used for the coupling. Denition and the explanation of these subroutines are inspired from the MpCCI manual.[2]
Function name:

Denition of the variables used: Function call for C and FORTRAN: Data type of variables used for FORTRAN: Short remarks about the function: Example:

14

3. MpCCI pArgc pArgv int subroutine integer


CCI Init

INOUT pointer to pass the argument count to MPI Init INOUT pointer to pass the arguments to MPI Init

CCI Init ( int* pArgc, char*** pArgv ) for C CCI INIT ( ierror ) ierror for FORTRAN

pArgc and pArgv are the parameters required for this function. INOUT means that these parameters can be input or output of the call. Some parameters can be used only as an input(IN ) or an output (OUT ).

3.3.1. Naming Conventions and Descriptions


As indicated before, there are FORTRAN and C interfaces of MpCCI. The naming convention and description of subroutines are similar for these two versions. For the C version, subroutine names of MpCCI start with CCI (Code Coupling Interface) and are followed by a list of words separated by the underscore symbol . The rst letter of the word after CCI is written in capital, e.g. CCI Recv. Unlike the C interface, capital letters are used for the subroutine nomenclature of the FORTRAN interface, e.g. CCI RECV. A maximum length of 30 characters is allowed to account for portability. I is used as the rst letter of the rst word after CCI if a non-blocking routine is chosen (CCI I followed by lowercase letters). For instance, a name for non-blocking C is CCI Irecv and for non-blocking FORTRAN is CCI IRECV. The naming convention for MpCCI and MPI are quite similar.

3.3.2. Data Types


MpCCI data types are introduced to solve platform-dependent data types clash problems. Data types are required for some of the routines. They are listed in (Table 3.1 Table 3.2) for C and FORTRAN, respectively.

15

3. MpCCI C Type int oat double long double char [] bool MpCCI type CCI INT CCI FLOAT CCI DOUBLE CCI LONG DOUBLE CCI STRING CCI BOOL

Table 3.1.: MpCCI data types for C

FORTRAN Type integer real real*4 real*8 double precision Character*(*) logical

MpCCI type CCI INTEGER CCI REAL CCI REAL4 CCI REAL8 CCI DOUBLE PRECISION CCI STRING CCI LOGICAL

Table 3.2.: MpCCI data types for FORTRAN

3.3.3. Coupling Denition


Dierent codes are connected to each other in the initialisation phase. MPI communicators are determined by the codes and some constants are computed in this start up phase. These constants, MpCCI denitions and the data types are attained by adding an appropriate library le (#include cci.h (for C ), #include ccif.h (for FORTRAN )) to the related codes.

16

3. MpCCI In the coupling phase, each code introduces its coupling area to MpCCI. Nodes and elements are generated then a neighborhood search is performed.

CCI Init

pArgc pArgv

INOUT INOUT

pointer to pass the argument count to MPI Init pointer to pass the arguments to MPI Init

int subroutine integer

CCI Init ( int* pArgc, char*** pArgv ) for C CCI INIT ( ierror ) ierror for FORTRAN

CCI Init is the rst MpCCI call which passes the array of command line arguments argv[] to the communication library and initialises MpCCI. The working directory, environment variables, etc. are set as dened in the MpCCI input le 3.4. MpCCI is based on MPI communication. Hence, MPI Init is initialised inside CCI Init automatically.

CCI Def partition

meshId partId

IN IN

grid identier within each code partition identier of each code

int subroutine integer

CCI Def partition ( int meshId, int partId ) CCI DEF PARTITION ( meshId, partId, ierror ) meshId, partId, ierror

Partitions of meshes which will be considered in the coupling computation are specied by using CCI Def partition. Grids are identied by meshId and for the partitions on each meshId, partId s are set. Partitions can be thought of being a subdivision of a grid.

17

3. MpCCI meshId partId nNodes nNodeIds nodeIds realType coords int subroutine integer IN IN IN IN grid identier within each code partition identier of each code dimension of the global coordinate system number of nodes switch node numbering, dimension of array nodes

globalDim IN

IN node identier IN data type of elements of coords IN address of coordinate array CCI Def nodes ( int meshId, int partId, int globalDim, int nNodes, int nNodeIds, const int nodeIds[], int realType, const void* coords ) CCI DEF NODES ( meshId, partId, globalDim, nNodes,nNodeIds, nodeIds,realType, coords, ierror ) meshId, partId, globalDim, nNodes, nNodeIds,nodeIds(nNodeIds), realType,coords, ierror)

<real type> coords (globalDim*nNodes)


CCI Def nodes

Nodes which participate in coupling are specied with this call. With nNodeIds, the numbering scheme of the nodes is set. realType (Table 3.1 Table 3.2) is for the data type of the nodes that are created. CCI Def nodes have to be called for every partition and only once. That means, the CCI Def partition has to be called before this subroutine. The coords array has a maximum of globalDim dimensions. For instance, if globalDim = 2 then coords array will be stored as, Ax , Ay , Bx , By , where A and B denote the name of nodal arrays, x and y are the axes.

CCI Def elems

After the nodes are created, elements are formed. Element types, sequence of nodes in elements and number of elements are dened. Dierent types of elements can be chosen for dierent dimensional space coupling. A wide range of element types from line to pyramid are provided. nElems make the denition

18

3. MpCCI meshId partId nElems nElemIds elemIds nElemTypes elemTypes elemNodes int IN grid identier within each code IN partition identier of each code IN number of elements IN switch for element numbering, dimension of array elemIds IN element identier IN length of array elemTypes IN element type of the specied elements IN indices of the nodes which dene the elements CCI Def elems ( int meshId, int partId, int nElems, int nElemIds, const int elemIds[], int nElemTypes, const int elemTypes[], const int nNodesPerElem[], const int elemNodes[] ) subroutine integer CCI DEF ELEMS ( meshId, partId, nElems, nElemIds, elemIds, nElemTypes, elemTypes, nNodesPerElem, elemNodes, ierror ) meshId, partId, nElems, nElemIds, elemIds(nElemIds), nElemTypes, elemTypes(nElemTypes), NodesPerElem( ), elemNodes( ), ierror of dierent element types possible in a partition.

nNodesPerElem IN number of nodes needed to describe one specic element

CCI Def comm

localCommId remoteCodeId remoteCommId nQuantityIds quantityIds nLocalMeshIds localMeshIds

IN communicator of local code IN id of the remote code IN communicator of remote code IN length of array quantityIds IN ids as dened in the input le IN length of array localMeshIds IN id of local meshes

Communicators are created with the CCI Def comm subroutine. It collects required information of the parameters that are needed. Another way to spec-

19

3. MpCCI int CCI Def comm( int localCommId, int remoteCodeId, int remoteCommId, int nQuantityIds, const int quantityIds[], int nLocalMeshIds,const int localMeshIds[] ) subroutine integer CCI DEF COMM( localCommId, remoteCodeId, remoteCommId, nQuantityIds, quantityIds, nLocalMeshIds, localMeshIds, ierror ) localCommId, remoteCodeId, remoteCommId, nQuantityIds, quantityIds (nQuantityIds), nLocalMeshIds, localMeshIds (nLocalMeshIds), ierror ify the communicator parameters is through the MpCCI input le. However, to attain those parameters CCI Comm info has to be called before calling CCI Def comm. localCommId is a variable that is only known to every process within the local code. On the remote side it searches its counterpart in the variable remoteCommId. nQuantityIds keeps the number of quantities which are stored in quantityIds. Both ids (localCommId and remoteCodeId ) should be greater than zero.
CCI Def sync point

syncPointId nQuantitiesToSend quantitiesToSend nMeshIdsToSend meshIdsToSend nQuantitiesToRecv quantitiesToRecv nMeshIdsToRecv meshIdsToRecv

IN identier of the synchronization point IN number of quantities to be sent IN array of quantity identiers, length nQuantitiesToSend IN length of the array meshIdsToSend, either 1 or nQuantitiesToSend IN array of mesh identiers, length nMeshIdsToSend IN number of quantities to be received IN array of quantity identiers, length nQuantitiesToRecv IN length of the array meshIdsToRecv, either 1 or nQuantitiesToRecv IN array of mesh identiers, length nMeshIdsToRecv

Synchronisation points are the places where send and receive operations are established. They have to be generated at the initialization phase. CCI Reach sync point and the input le are the two complementary parts of CCI Def sync point.

20

3. MpCCI int CCI Def sync point ( int syncPointId, int nQuantitiesToSend, const int quantitiesToSend[], int nMeshIdsToSend, const int meshIdsToSend[], int nQuantitiesToRecv, const int quantitiesToRecv[], int nMeshIdsToRecv, const int meshIdsToRecv[] ) subroutine CCI DEF SYNC POINT (syncPointId, nQuantitiesToSend, quantitiesToSend, MeshIdsToSend, meshIdsToSend, nQuantitiesToRecv, quantitiesToRecv, nMeshIdsToRecv, meshIdsToRecv, ierror ) integer syncPointId, nQuantitiesToSend, quantitiesToSend (nQuantitiesToSend), nMeshIdsToSend, meshIdsToSend (nMeshIdsToSend), nQuantitiesToRecv, quantitiesToRecv (nQuantitiesToRecv), nMeshIdsToRecv, meshIdsToRecv( nMeshIdsToRecv ), ierror CCI Sync point info should be called to get the required data from the input le. The identier for synchronisation points can be dierent in various codes. There is no need to match the codes since matching is done by the input le.

CCI Close setup

cciProcess IN

ag for MpCCI process

int subroutine integer

CCI Close setup ( int cciProcess ) CCI CLOSE SETUP( cciProcess, ierror ) cciProcess, ierror

This routine terminates the denition phase. It has to be called by every process which also called the CCI Init.

CCI Put nodes

CCI Put nodes is used to specify the coupling quantities at the nodes to MpCCI. The values with the identier quantityId must be dened in the relevant code

21

3. MpCCI meshId partId quantityId quantityDim nNodes nNodeIds nodeIds valuesDataType values int IN IN IN IN IN IN IN IN IN grid identier within each code partition identier of each code identier specied in the input le dimension of quantity number of nodes switch node numbering, dimension of array nodeIds node identier identier of input data returned data values

CCI Put nodes( int meshId, int partId, int quantityId, int quantityDim, int nNodes, int nNodeIds, const int nodeIds[], int valuesDataType, const void* values )

subroutine integer

CCI PUT NODES( meshId, partId, quantityId, quantityDim, nNodes, nNodeIds, nodeIds, valuesDataType, values, ierror ) meshId, partId, quantityId, quantityDim, nNodes, nNodeIds, nodeIds(nNodeIds), valuesDataType, ierror

<real type> values(quantityDim*nNodes) block of the MpCCI input le. The location specication in the input le decides which call is used for the coupling. (Since loc = nodes is chosen the CCI Put nodes subroutine is used. If loc = elem was chosen CCI Put elems would have to be used.) If scalar is chosen as a quantity, quantityDim has to be set to 1. If vector is chosen, quantityDim must be equal the dimension of the vector.
CCI Reach sync point

syncPointId status

IN OUT

identier of a synchronization point status object

CCI Reach sync point performs the communication between the codes which are specied in the match syncpt statement of the coupling block of the input le. The send and receive operations are determined by the synchronisation

22

3. MpCCI int subroutine integer CCI Reach sync point ( int syncPointId, CCI Status* status ) CCI REACH SYNC POINT( syncPointId, status, ierror ) syncPointId, status( CCI STATUS SIZE ), ierror

point denition of the codes. The communication at the synchronisation point with the identier syncPointId is carried out.
CCI Get nodes

meshId partId quantityId quantityDim nNodes nNodeIds nodeIds valuesDataType values emptyNodes nEmptyNodes

IN IN IN IN IN IN IN IN OUT OUT OUT

grid identier within each code partition identier of each code identier specied in the input le dimension of quantity number of nodes switch node numbering, dimension of array nodeIds node identier identier of input data returned data values maximum number of nodes without data returned nodes containing no data length of array emptyNodes

maxnEmptyNodes IN

int

CCI Get nodes( int meshId, int partId, int quantityId, int quantityDim, int nNodes, int nNodeIds, const int nodeIds[], int valuesDataType, const void* values,int maxnEmptyNodes, int emptyNodes[], int* nEmptyNodes )

subroutine

CCI GET NODES( meshId, partId, quantityId, quantityDim, nNodes, nNodeIds, nodeIds, valuesDataType, values, maxnEmptyNodes, emptyNodes, nEmptyNodes, ierror )

integer

meshId, partId, quantityId, quantityDim, nNodes, nNodeIds, maxnEmptyNodes, emptyNodes (maxnEmptyNodes), nEmptyNodes, nodeIds(nNodeIds), valuesDataType, ierror

<real type> values(quantityDim*nNodes)

23

3. MpCCI CCI Get nodes are used to obtain coupling values received from the other code. valuesDataType must be chosen according to the quantities transferred (Table 3.1 Table 3.2). nNodes are the number of nodes specied by the call of CCI Def nodes. The array emptyNodes determines the nodes where no new values are obtained.

CCI Check convergence

myConvergence globalConvergence comm

IN OUT IN

code of local convergence state global convergence state MpCCI communicator

int subroutine integer

CCI Check convergence( int myConvergence, int *globalConvergence, int comm ) CCI CHECK CONVERGENCE( myConvergence, globalConvergence, comm, ierror ) myConvergence, globalConvergence, comm, ierror

CCI Check convergence must be called by all codes and exchanges the convergence states. Each code species its local convergence state myConvergence by an integer. These integers are exchanged between the codes and the maximum of all integers is returned to each code in globalConvergence. MpCCI denes four constants for the local convergence state with the following meaning: CCI CONVERGED ( = 0 ) converged and could stop here, but I can also do a further coupling step. CCI CONVERGED ( = 1 ) not yet converged and would like to do a further coupling step. CCI CONVERGED ( = 2 ) converged and must stop here. No further coupling step is possible. CCI CONVERGED ( = 3 ) diverged and must stop here.

24

3. MpCCI Another important meaning of this subroutine is the creation of coupling steps when writing a MpCCI tracele. CCI Check convergence introduces a new coupling step in the tracele. With a suitable visualisation tool for MpCCI traceles the user can observe the data sent and received in the dierent steps in an animation.
CCI Finalize

int subroutine integer

CCI Finalize() CCI FINALIZE( ierror ) ierror

Subroutine CCI Finalize terminates the coupling. It has to be called by the processes which called CCI Init. The coupled computation is nished after this subroutine MpCCI terminates. After the termination messages all processes do a clean-up and write their output les.

3.4. MpCCI Input File


The MpCCI input le has to provide information regarding the following questions.
Which codes should be run? Where should they be located? How should they be started? What are the environmental variables to be specied? What are the quantities to be mapped and how are they recognised by the

codes? The input le is an important part of the denition of coupling process. Part of the exibility when using MpCCI to couple the codes is due to this input le. MpCCI library contains some values by default. These default values can be altered via input le. Moreover, it contains the coupling algorithms itself, quality checks and level of debugging, etc. It is important to note that the input le is a case-sensitive le.

25

3. MpCCI

3.4.1. Structure
The le comprises of several blocks. Some of them have to be specied whereas some of them are optional and only change default values. The ordering structure listed below is important and must not be changed. Each block starts with its name (code block, quantities block, etc.) and nishes with the word end.
code block(s) quantities block(s) control block contact block switches block jobs block parameters block coupling block additional block

Code Block This block is mandatory in the input le. The numbers of codes which participate in the coupling determine the number of code blocks. For each code there must be a code block. The quantities to be exchanged (received and sent) are named here. Their type, dimension and location in the grid are also specied.

name of the quantity ( number, location, dimension, type ) force ( no=1, loc=elem, dim=vector, type=ux )

Number is given to label the name of the quantity in a code block. Dierent numbers must be chosen for dierent quantities. Negative numbering is allowed. [4] Location indicates whether it is an elemental or nodal quantity. Dimension can be a

26

3. MpCCI vector or a scalar. Besides, user dened extended dimension can be created. Finally, the type is generally described as ux or eld. Field is used for scalar type values like heat and ux is a vector type like force. Quantity Block This mandatory part claries how the quantities of the dierent codes dened in the code block are related to each other. The matching of two quantities is valid if they have the same type and dimension set in their code blocks. However, it is independent of their location. Example:

code1.quantity = code2.quantity ansys.force = cfx.force

Control Block This part species parameters related with the control of algorithms used by MpCCI. It is an optional block. To visualise the coupled computation a tracele section should be established in this block. If no name is specied then there will not be any tracele written. There are numbers of on/o switches with which the quality of the meshes can be checked. Contact Block This optional block is for the attributes of the grids. It denes the contact detection algorithm and matching criterion. Switches Block Switches block is the place where the debugging level is decided. There are dierent possibilities ranging between no output and maximum output choices. It is also possible to dene a group. A group is a section used to dene in which part of MpCCI the switch command is applied. For the group part there is a hierarchy to

27

3. MpCCI obey. For the list of hierarchy, please check the appendix. This block is another optional block in the input le. [5] Jobs Block This section describes the coupling codes which participate in the coupling. Paths for the executables of the individual codes are dene here. Arrangements related with the parallisation is done under jobs block. Number of processes and environmental variables are set in a group name. In the following example, a group named struct1 is created with a keyword struct, number of processes are decided to be 4 and the environmental variable STRUCT JOB is set to part. Pwd species the working directory and exec sets the command to start the process. Example: jobs

struct1 pwd exec nprocs ); end Parameters Block

= struct ( = C: = binary1 =4

env (STRUC JOB) = part

This block is optional. It helps users to introduce some string, oat or integer values. Coupling Block This is one of the crucial parts of an input le although it is an optional block. Communicators and synchronisation points are described in this block. Synchronisation points are the points where the send and receive operations are performed. They are combined with the match syncpt command. If match syncpt is not dened then the synchronisation is performed between the points which have the same identier.

28

3. MpCCI Example: In this example, the generation of synchronisation points and their relation to each syncpt jobname1 (syncPt1) = send (quantityId1/meshId1, quantityId2/meshId2, ) recv (quantityId1/meshId1, quantityId2/meshId2, ) syncpt jobname2 (syncPt2) = send (quantityId1/meshId1, quantityId2/meshId2, ) recv (quantityId1/meshId1, quantityId2/meshId2, ) match syncpt jobname1 (syncPt1, syncPt2, ) = jobname2 (syncPt1, syncPt2, ) other are illustrated. A synchronisation point denition starts with the job name dened in the code block. Then, quantities that are sent and received which are specied together with its grid id. If one of the operations is not needed (send or recv) then it is omitted from the denition. The equality in the specication of match syncpt depicts that the synchronisation point 1 (syncPt1) of job1 is matched with the synchronisation point 1 (syncPt1) of job2. Similarly, synchronisation point 2 (syncPt2) of job1 is related with the synchronisation point 2 (syncPt2) of job 2. Additional Block This block is optional. Some additional features are placed in this block such as coordinate transformation or intersection points.

29

4. Moving Boundaries
Moving boundaries were implemented on a third trial example derived from test case 2. Here, the tail of test case 2 was moved with a sinusoidal movement in time and with a parabolic displacement in space. The following describes how this movement was implemented in CFX via coupling to a pseudo-code. This code received forces at the tail shaped boundary only to discharge them and return a xed displacement in form of 4.1.

4.1. Outline of achieveing a Bi-Directional coupling via MpCCI


The long term goal is to couple the high-order structure code AdhoC to the uid code CFX. In order to achieve this goal it was decided to take three major intermediate steps using MpCCI. 1. Couple a dummy uid code to a dummy AdhoC code 2. Replace the dummy uid code with CFX 3. Replace the dummy AdhoC code with AdhoC Step one (section 4.1.1) and step two (section 4.1.2) are described in this thesis. Step three has yet to be taken. The necessary dummy codes were written in C.

4.1.1. AdhoC Dummy Code


In step 1, the dummy codes received either forces (AdhoC Dummy) or displacements (Fluid Dummy) and vice versa, sent displacemets (AdhoC Dummy) or sent forces

30

4. Moving Boundaries (Fluid Dummy). This dummy code rst is used solely both as a solid dummy and uid dummy but with dierent settings. Three planes are created and they are connected together to obtain the shape of tail. Denition of a plane is based on the specication of the coordinates of the three corners. Number of the nodes should be set in both transverse and longitudinal directions to generate quadratic local meshes. Meshes are combined with each other and a global mesh is obtained. Since two partitions are on a line, nodes on the line of combination must have the same values. The subroutine Associate Partitions (Appendix A)is generated to take care of this problem. The basic idea of the subroutine is to delete one set of common nodes (there are two sets of nodes with dierent mesh identities but the same geometric properties) and to assign the remaining nodes to the other mesh.

Figure 4.1.: Parts of Adhoc Dummy The dummy forces and displacements to be exchanged are dened using some indices that are a function of position and time by calling the AdhoC Dummy routine in the code. During mesh generation, geometric information of the nodes and elements are kept in matrices. One-way data transfer is applied rst. Then, program is extended for the quantity exchange. Please refer to appendix for the AdhoC Dummy code.

4.1.2. Implementation of MpCCI on a written Dummy Structure Code and CFX


ANSYS-CFX ANSYS-CFX is a program package for modelling general uid ow in complex geometries. CFX is composed of the preprocessor, the ow solver, and the postprocessor. CFX oers a wide area of physical models and numerical solution algorithms for

31

4. Moving Boundaries steady or transient, incompressible or compressible, laminar or turbulent, free surface ows and etc. In this thesis, CFX 5.7 version is used. CFX-Pre There are two steps to set up a CFD problem, mesh generation and physical problem set-up. In the new version of the program mesh geometry and meshes can be generated by CFX. However, in version 5.7 there is no option to generete a geometry or a mesh and therefore these data have to be imported. CFX-Pre can import meshes from lots of programs using a variety of formats like ACIS and IGES. ANSYS-ICEM-CFD and Domesh (reference) are chosen to create the required geometries and meshes. Once meshes have been imported, the user assigns meshes to domains. Depending on the demands of the problem multiple meshes can be combined to form a single domain or a single mesh can be split into several of domains. It is easy to set and access the details of the physical problem through an interactive control panel. Any changes made in the denition of the problem can be displayed simultaneously. Errors in denitions can be detected via colorful descriptive messages in interactive panels. After the problem denition is complete, a denition le for the CFX solver is written. CFX-Solve The solver manager enables users to monitor the convergence progress of the calculations through graphs while the calculation is running. Residuals, forces, monitor points, and expressions can be displayed during the process. CFX-Post Post-processing is an important step in the CFD analysis. Data obtained from the solver manager should be clearly presented in order to make reasonable comments on the application. Not only is the visualization important but the calculation data should be assessed carefully by analysing the output les of the monitor points an res-les.

32

4. Moving Boundaries CFX-Post has powerful tools to extract valuable information from ANSYS-CFX. CFX-Post provides users with all the graphical features. Streamlines, planes, vectors, isosurfaces and charts are available to display the ows within the specied domain. Animation of the applications is also available. However, it was foud to be useful to create monitor points and analyse the monitor les by a script written in python. Please, check the python scripts in appendix B. CFX Expression Language(CEL) is available in the postprocessor. Specic functions such as area integral and averages of some quantities can be obtained. Expressions can be used to dene new user dened variables. When the uid code was replaced by CFX, the forces sent by CFX were received by the AdhoC Dummy code (See, appendix A) and discharged. A xed displacement according to (i 1.0) (i 1.0) maxEndDisplZ sin(3.14159265 insT ime) ((n 1.0) (n 1.0)) Formula was then returned by the AhoC Dummy to CFX and this displacement was imposed on the boundary at test case 2.

4.1.3. CFX Expression Language (CEL)


CEL is a declarative language that is used to dene relationship that depends on other variables and complex boundary condition proles. Some values or expressions are generated by using CEL. Values can be dened either dimensionless or with the dimensions in terms of time, length, mass, temperature, etc. Arithmetic operations like addition or subtraction are possible. Any name can be chosen as an expression name except the names of some predened expressions, mathematical functions, system variables or other user dened functions .The value of a CEL expression can also be monitored during the solution process. To call the required function a certain syntax has to be followed. The general syntax is as follows: <function> (<variable>) @ <location> <function> is used for the CEL function specication. <variable> is the variable to be applied. If there is no need an empty brackets must be leaved.

33

4. Moving Boundaries <location> is the region or boundary that of interest. For the calculation of the lift and drag forces around the cylinder and the ag some functions are dened. Boundary conditions are dierent for the each test case, hence dierent expressions are specied. Denition of the parabolic velocity prole at the inlet is also experienced with CEL functions. CEL expressions that are used during the test case computations are given below. ForceX = force x()@cylinder ForceY = force y()@cylinder ForceX = force x()@cylinder + force x()@tail ForceY = force y()@cylinder + force y()@tail InowVelicity = 1.5 [m s-1] StartSlow = (cos(t * 3.141[rad s-1]-3.141)*1/2 + 0.5) ParabolicInow = InowVelicity*y*(0.41 [m]-y)/((0.41 [m]/2)2)*StartSlow* step(1-t*1[s-1])+InowVelicity*y*(0.41 [m]-y)/((0.41 [m]/2)2)*step(t*1[s-1]-1) The rst thing that can be deduced from the examples is that an expression can be used to dene another one. To dene parabolic inow boundary condition expressions like StartSlow or InowVelicity are dened in order to run to simulations with dierent velocity settings spending much eort. The CEL function force is already dened internally. The force function which is separated by an underscore from the direction to be projected on (x or y) is then followed by an @ operator to specify the domain, sub-domain or boundary of interest. Since arithmetic operations are available to calculate the total drag and lift forces around the cylinder and ag, their domains are added to each other. All the variables are dimensionalised by assigning values with dimensions.

4.1.4. Monitor Points


Specication of the expressions is not enough to attain the pressure values, drag or lift forces. Monitor objects which are the points at which certain quantities are observed, are also needed to extract the required quantities from the output data. For the extraction following command needs to be run from the command line.

34

4. Moving Boundaries

cfx5dle <le> -read-monitor > output.txt <le> is the result le that contains the monitor points data. Output data (output.txt is referred as output data from now on.) contains a list of variable names followed by a list of values. A line of data for every iteration in the order of the variable names is written to the le. They all are separated from each other with a comma. Output data is parsed with the help of a python (Appendix B) script into the format required for the gnuplot. Python is an interactive, object-oriented programming language and gnuplot is an interactive plotting programme. With the python script, quantities that are needed can easily be extracted from the output data with a simple run.

35

5. Discussion of the Results


5.1. Discussion of the Results of the Test Case 1
All tests are calculated with CFX 5.7. To get an idea about the eect of the spatial discretization the time step is kept constant. In other words, it is intended to depict only the spatial error of computations (reference). The time step is set to 0.01[s]. The velocity prole introduced at the inlet boundary is increased with a sinusoidal function so that the full velocity is reached after one second. Fluid force exerted on the cylinder can be separated and analyzed as lift and drag forces. Drag forces are the forces exerted on the submerged cylinder in x-direction whereas lift forces are perpendicular to it. Related to lift and drag forces, two important dimensionless parameters are dened, CD and CL , to ensure the comparison criteria free from any dimensions. CD = where,
CD , CL : Lift and drag coecients, Fx and Fy : Resultant forces tangential and perpendicular to the velocity vector,

Fx 1 2 0 dL 2

CL =

Fy 1 2 0 dL 2

respectively, Fx =
s

nx dS

Fy =
s

ny dS

: Flow is density, : Bulk velocity, D : Diameter of the cylinder,

36

5. Discussion of the Results


L : Lenght of the channel.

Following diagrams present change of lift and drag forces with dierent time periods. If the graphs are examined, it is observed that Hexa mesh is not shown in any graphs. It is because, the results obtained are too far from our references. Hence, Only the results of unstructured meshes are compared to each other. Starting from rest, the ow develops and nally reaches a periodic stage. Vortex shedding causes the lift and drag forces to oscillate. They oscillate at dierent frequencies. Figures (5.1a and 5.1b) show that the lift has half the frequency of the drag. After certain transition period all the lift forces show similar pattern in period but not in amplitude and phase angle.(Figures 5.1a, 5.2a and 5.3a). The best results are obtained form DoMeshVeryFine and DoMeshOptimal. (Figures 5.1b, 5.2b and 5.3b) All drag forces overshoot before they oscillate around their mean value. As it is the case in lift good results are obtained from DoMeshVeryFine and DoMeshOptimal. To conclude, DoMeshOptimal leads to suciently accurate results and is used as a template for the second test case.

5.1.1. Comparision of Coarse Meshes


In this part was to test the eect of the element ratio in connection with symmetry boundary conditions. In the graphs 0.005, 0.01 and 0.02 show the length of the thicknesses, respectively. Table 5.1 shows the maximum edge length ratio for dierent the thicknesses. Thickness(m) Max. Edge Length Ratio M1 13.692 M2 11.828 M3 74.391

Table 5.1.: Comparison of Max. Edge Length Ratios

Figures 5.4 5.5 5.6 show the drag and lift force for dierent time steps. If the overall pattern of the lift forces ([0-20s]) is considered it is observed that there is almost no dierence between the lift forces. They have almost the same frequency and amplitude over the entire analysis time. However, in the beginning of the simulation([0-5s]) there

37

5. Discussion of the Results is slight deviation of lift and drag of the thickness 0.005 in amplitude and phase. As time passes([10-15s]) the amplitude dierence vanishes although phase dierence continues until the end of the simulation. Normally, the forces should be the same since we do not change any boundary conditions. But, still the error between the values are very small and can be neglected.

5.2. Discussion of the Results of the Test Case 2


The results of test case 2 are shown in the following graphs.

5.2.1. Eect of Velocity Change


A chosen mesh is tested with the average inow velocities 0.3, 1.0 and 2,0 (in m/s). All the velocities are applied to the mesh type M1. However, M2 and M3 are tested without the velocity value 0,3 m/s. The reason is that M1 is ne enough to simulate an inow velocity 0,3 m/s. The ow shows a steady-state situation and the results are close to the other benchmark test results. [7] For the grid M1, as the velocity is incresed from 0,3 m/s to 1, 0 m/s there is no change in the pattern of the drag forces. The value increases about 10 times. If the lift forces are considered not only the values increase but also the graph changes. Increase in velocity results in a signifcant peak in the graph. (Figures 5.8a and 5.9a) Further increase in velocity maintain the increase in drag and lift values. Additionally, the steady state situation is disturbed and periodic behavior is observed.(Figures 5.12a and 5.12b). Negative and positive lift forces are formed and drag forces uctuates with small amplitudes. For the meshes M2 and M3 the increase in velocity results in periodic forces with higher lift and drag values as mentioned above for the mesh M1. This time drag forces show macroscopic alteration.

5.2.2. Eect of Grid Type


For CFD1, only one mesh was investigated since the benchmark tests are reproduced with sucient accuracy with the coarsest grid. (Figures 5.8b and 5.8a)

38

5. Discussion of the Results For CFD2 (Figures 5.9a, 5.10a and 5.11a), in other words for the average inow velocity 1,0 m/s, renement of the mesh causes reduction in lift and drag forces, respectively. After certain transition period forces stabilize themselves and reach constant values. Renement does not change the graphical pattern. For CFD3 (Figures 5.12a, 5.13a and 5.14a) where the ow is 2,0 m/s, renement results in increase in amplitude of the periodic motion of the drag forces. Besides, uctuations start earlier as the number of elements increases. Similar observations can be made for the lift forces, as well.

39

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.1.: lift and drag forces [0-20 s.] (Test Case 1)

40

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.2.: lift and drag forces [0-5 s.] (Test Case 1)

41

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.3.: lift and drag forces [10-15 s.] (Test Case 1)

42

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.4.: Comparision of coarse meshes that have dierent thickness [0-20 s.] (Test Case 1)

43

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.5.: Comparision of coarse meshes that have dierent thickness [0-5 s.] (Test Case 1)

44

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.6.: Comparision of coarse meshes that have dierent thickness [10-15 s.] (Test Case 1)

45

5. Discussion of the Results

Figure 5.7.: Values for lift and drag forces. The results shown are calculated for the last 5 seconds

(a) lift

(b) drag

Figure 5.8.: lift and drag forces around the cylinder and ag (CFD1,M1)

46

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.9.: lift and drag forces around the cylinder and ag (CFD2,M1)

47

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.10.: lift and drag forces around the cylinder and ag (CFD2,M2)

48

5. Discussion of the Results

(a) lift

(b) drag

Figure 5.11.: lift and drag forces around the cylinder and ag (CFD2,M3)

49

5. Discussion of the Results

(a) lift

(b) drag

(c) Fourier

Figure 5.12.: lift and drag forces around the cylinder and ag (CFD3,M1) 50

5. Discussion of the Results

(a) lift

(b) drag

(c) Fourier

Figure 5.13.: lift and drag forces around the cylinder and ag (CFD3,M2) 51

5. Discussion of the Results

(a) lift

(b) drag

(c) Fourier

Figure 5.14.: lift and drag forces around the cylinder and ag (CFD3,M3) 52

6. Concluding Remarks and Recommendations


In this study, coupling analysis of the two benchmark tests are successfully performed. First, computation of the DFG-Benchmark 1995/6: Channel ow around a circle for laminar ow is carried out. MpCCI library and AdhoC-Dummy are used for external coupling. An optimal mesh is needed to reduce the computation time and memory requirements. With the help of optimal mesh, new grids are created for he second test case, interaction between uid and an elastic structure. Finally, the second test case is numerically studied. Dierent average inow velocities are tested using dierent grids. Results are compared to the studies of the other numerical benchmark calculations. For this goal, forces are splitted as drag and lift forces. In the near future, further research is in progress to test AdhoC, p- version of nite element code written at the Chair of Bauinformatik, for uid-structure interaction problems of dierent settings such as laminar ow-elastic structure or laminar ow inelastic-solid structure interaction, etc. Testing process can be enlarged to compare the responses of p and h -versions of nite element codes. Another research study can be related to the eciency investigation of time and memory of AdhoC for dierent FSI problems.

53

References

[1] Frauenhofer Institute for Algorithms and Scientic Computating SCAI. Mpcci 3.0.4 manuals. page 9, 2005. [2] Frauenhofer Institute for Algorithms and Scientic Computating SCAI. Mpcci 3.0.4 manuals. 2005. [3] Frauenhofer Institute for Algorithms and Scientic Computating SCAI. Mpcci 3.0.4 manuals. page 2, 2005. [4] Frauenhofer Institute for Algorithms and Scientic Computating SCAI. Mpcci 3.0.4 manuals. page 78, 2005. [5] Frauenhofer Institute for Algorithms and Scientic Computating SCAI. Mpcci 3.0.4 manuals. page 86, 2005. [6] Lehrstuhl fr Bauinformatik (Technische Universitt Mnchen). Adhoc users u a u guide. 30 March 2004. [7] J. Hron and S. Turek. Proposal for numerical benchmarking of uid-structure interaction between elastic object and laminar incompressible ow. Journal of Process Control, 10(2-3):209218, 25 July 2005. [8] D.Dennis Parsons. Methods and applications in coupled engineering simulations. 7th US National Congress on Computational Mehanics. http://usnccm.sandia. gov/mslist/msDetail.lasso?RecID=il960.32. [9] M. Schfer and S. Turek. Benchmark computations of laminar ow around cylina der. Numerical Fluid Mechanics, 52(1):547566, 1996.

54

A. THE DUMMY CODE

This program is a small benchmark example for coupling algorithm between fluid and a solid structure. Solid code is aimed to be written (defined and computed) in C while fluid part is defined and solved with CFX. Both codes specify a simple mesh to MpCCI. Code SOLID sends some vectorial values (displacements) to the FLUID code and gets some vectorial data (forces) from it. Each code has only one process i.e. runs sequentially. Compile/link/run benchmark example # # # # # make clean Solid # # # # # # Do some cleanup and remove all non-source files

If you prefer to do it by hand instead of typing make, you can use the compile, link and run scripts of the MpCCI distribution. The compile and link scripts print to stdout the full command which they are going to perform (all include or lib flags). # # Compilation of structureCode.c: # # Compile the C version # Alternatively: Compile the C version # using the C++ compiler ccilink structureCode.o -o structureCodeBinary # Link # the 1st code (C version) with MpCCI ccilink structureCode.o -o structureCodeBinary # Link # the 2nd code (C version) with MpCCI # NOTE: MpCCI input file benchmark.cci # expects the name of the binary to be # structureCodeBinary # # Start the coupled computation: # ccirun -log structureCode.c # Start the coupled computation. # You can also try out the -xterm # option of the ccirun script. ccicc -c structureCode.c cciCC -c structureCode.c

55

A. THE DUMMY CODE

The resulting output files of the coupled computation are ccirun.out<r> where <r> is the global rank process. These files should be in the form of ccirun.out.*. # # # # # Fluid # # # # #

For fluid to make the CFX program ready for coupling job COMMAND should be run. /* This file is the structure part of the coupling. The code provides users to define three planes and then to mesh them as it is shown in the following figure. Users should provide to the function createPlane three corners of a plane and number of nodes in both directions (longitudinal and transverse) required for quadratic mesh generation. Planes should be joined together in order to get a mesh with three partitions. For this goal a function Associate_partitions is used to volatile the duplication of nodes that lie on the common boundaries of the partition. MpCCI library is used to transfer the force and displacement data between structure code and fluid code. Structure code gets force data whereas fluid part needs to get the displacement from the structure. The displacement is a parabolic function of position. (please, check the AdhoC_Dummy function !) It also changes sinosidually with time. ---Plane 1-------| | Plane 3 ---Plane 2-------| */ /*--- Header files ---*/ #include<cci.h> #include<stdio.h> #include<stdlib.h> #include<math.h> /*--- Create a vector (namely a point) ---*/ typedef struct { int id; double x; double y; double z; } Node;

56

A. THE DUMMY CODE

/*--- Vector addititon ---*/ void addVectors(Node *v1, Node *v2, Node *res) { res->x = v1->x + v2->x; res->y = v1->y + v2->y; res->z = v1->z + v2->z; } /*--- Vector subtraction ---*/ void subVectors(Node *v1, Node *v2, Node *res) { res->x = v1->x - v2->x; res->y = v1->y - v2->y; res->z = v1->z - v2->z; } /*--- Multiplication of a vector by a constant ---*/ void multConstant(Node *v1, Node *res, double n) { res->x = n* v1->x; res->y = n* v1->y; res->z = n* v1->z; } /*--- Division of a vector by a constant ---*/ void divConstant(Node *v1, Node *res, double n) { res->x = v1->x / n; res->y = v1->y / n; res->z = v1->z / n; } /*--- Creates a plane ---*/ Node ***createPlane(Node RefKo, Node P_00, Node P_n0, Node P_0m int elem_u, int elem_v) { /* RefKo is the origin in the plate system */ /* P_0m elem_v o--o--o--o--o | | | | | o--o--o--o--o sample plane | | | | | o--o--o--o--o elem_u P_00 P_n0 elem_u and elem_v are both the maximum node numbers in both directions successively. */

57

A. THE DUMMY CODE Node ***P; Node u,v,du,dv; du.x=0.0; du.y=0.0; dv.x=0.0; dv.y=0.0; int i,j,inc=0;

du.z=0.0; dv.z=0.0;

/* u and v are both vectors*/

P= (Node***)calloc(elem_u, sizeof(Node**)); /* allocate memory for the nodes of a plane for (i=0; i<elem_u; i++) {P[i]=(Node**)calloc(elem_v, sizeof(Node*)); for (j=0; j<elem_v; j++) P[i][j]=(Node*)calloc(1, sizeof(Node)); } subVectors(&P_n0, &P_00, &u); /* vector in u direction (non-normalized) */ subVectors(&P_0m, &P_00, &v); /* vector in v direction (non-normalized) */ divConstant(&u, &du, (double)(elem_u-1)); divConstant(&v, &dv, (double)(elem_v-1)); for (j=0; j<elem_v; j++) { inc=elem_u*j; for (i=0; i<elem_u; i++) { /*--- in pseudo code: n[i][j]= P_00 + du*i + dv*j ---*/ P[i][j]->id = inc + i + 1 + RefKo.id; P[i][j]->x = i*du.x + j*dv.x + RefKo.x; P[i][j]->y = i*du.y + j*dv.y + RefKo.y; P[i][j]->z = i*du.z + j*dv.z + RefKo.z; } } return P; } /*--- Free the memory ---*/ destructPlane(Node ***P, int elem_u, int elem_v) { int i,j; for(j=0; elem_v; j++) { for(i=0; i<elem_u; i++) { cfree(P[i][j]); } cfree(P[j]); } cfree(P); } /*--- This function will return to the displacement vector ---*/

58

A. THE DUMMY CODE void AdhoC_Dummy(int n, int m, int change, double* displacement float insTime) /*--- AdhoC_Dummy(node number in u direction, node number in v direction, change, displacement, instantaneous time)---*/ { int index=1; int i,j; float maxEndDisplZ=0.01; if(change==1) /*--- parabolic displacement for all nodes ---*/ { for(j=1; j<=m; j++) { index= (j-1)*n+1; for (i=0; i<=n; i++, index++) { displacement[3*index-3]=0.0; displacement[3*index-2]=((i-1.0)*(i-1.0)/((n-1.0)*(n-1.0))* maxEndDisplZ*sin(3.14159265*insTime)); displacement[3*index-1]=0.0; } } } if(change==2) /*--- constant displacement for all nodes ---*/ { for(index=1; index<=m*n; index++) { displacement[3*index-3]=0.0; displacement[3*index-2]=maxEndDisplZ*sin(3.14159265*insTime); displacement[3*index-1]=0.0; } } return; } /*--- Combines different partitions of the same mesh ---*/ void Associate_partitions(Node ***partition1, Node ***partition2 int n1, int m1, int n2, int m1) /*--- void Associate_partitions(1st partition, 2nd (1st partition)number of nodes in u (1st partition)number of nodes in v (2nd partition)number of nodes in u (2nd partition)number of nodes in v { int i,j,k,l; double eps; eps=0.0001; for (i=0; i<n1; i++) { partition, direction, direction, direction, direction) ---*/

59

A. THE DUMMY CODE for (j=0; j<n1; j++) { for (k=0; k<n1; k++) { for (l=0; l<m2; l++) { If( (fabs(partition[i][j]->x - partition[i][j]->x) <=eps) && (fabs(partition[i][j]->y - partition[i][j]->y) <=eps) && (fabs(partition[i][j]->z - partition[i][j]->z) <=eps) ) { cfree(partition[i][j]); /*--- delete one of the objects that are created on the boundaries of the different partitions ---*/ partition[i][j] = partition[k][l]; } } } } } } /*--- Created for debugging purpose ---*/ void debug(Node ***partition, int n, int m) { int i,j; double eps; eps=1E-6; for (j=0; j<m; j++) { for(i=0; i<n; i++) { printf("i=%d, j=%d, i,j"); printf("id1 %d, x% lf, y% lf, z% lf \n", partition[i][j]->id, partition[i][j]->x, partition[i][j]->y, partition[i][j]->z); } } } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%* * * * introduce some variables: * * * *%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*--- for the definition of the Partitions: CCI_Def_partitions ---*/ int meshId; /* grid IDs */ int partId1, partId3, partId3; /* partition IDs */ /*--- for the definition of the Nodes: CCI_Def_nodes ---*/

60

A. THE DUMMY CODE int globalDim = 3; /* dimension of the system */ int nNodes1, nNodes2, nNodes3; /* number of nodes (for each partition) */ int nNodesIds1, nNodesIds2, nNodesIds3; /* switch node numbering ; dimension of array of nodeIds*/ int nodeIds1[2000], nodeIds2[2000], nodeIds3[2000]; /* actual node IDs*/ int realType = CCI_DOUBLE; /* type of elements of coords */ double coords1[3*2000], coords2[3*2000], coords3[3*2000]; /* address of coordinate array */ /*--- for the definition of the Elements: CCI_Def_elements ---*/ int nElements1, nElements2, nElements3; /* number of elements in the mesh */ int nElemIds1, nElemIds2, nElemIds3; /* switch node numbering; dimension of array of nElemIds*/ int elemIds1[2000], elemIds2[2000], elemIds3[2000]; /* number of elements in the mesh */ int elemTypes1[] = {CCI_ELEM_QUAD}, elemTypes2[] = {CCI_ELEM_QUAD}, elemTypes3[] = {CCI_ELEM_QUAD}; /* element type*/ int nNodesPerElem1[] = {4}, nNodesPerElem2[] = {4}, nNodesPerElem3[] = {4}; int elemNodes1[nNodesPerElem1[0]*2000], elemNodes2[nNodesPerElem2[0]*2000], elemNodes3[nNodesPerElem3[0]*2000]; /*--- for the definition of communication with the remote code ---*/ /* CCI_Get_Nodes */ /* CCI_Put_Nodes */ int quantityId; int quantityDim; int valuesDataType; double displacement1[2000*3], displacement2[2000*3], displacement3[2000*3]; double force1[2000*3], force2[2000*3], force3[2000*3], fx1, fy1, fz1, fx2, fy2, fz2, fx3, fy3, fz3; int maxnEmptyNodes; int* EmptyNodes; int nEmptyNodes; /*--- for the definition of syncronization point: CCI_Def_Sync_point ---*/ int sycnPointId; /* identifier of the syncronization points */ int maxnQuantToSend; int nQuantitiesToSend; /* number of quantities to be sent */ int quantitiesToSend[CCI_MAX_NQUANTITIES]; /* array of quantity-identifiers, length of nQuantitiesToSend */ int nMeshIdsToSend; /* length of meshIdsToSend, either 1 or

61

A. THE DUMMY CODE nQuantitiesToSend */ int meshIdsToSend[CCI_MAX_NQUANTITIES]; /* array of mesh-identifiers, length of MeshIdsToSend */ int maxnQuantToRecv; int nQuantitiesToRecv; /* number of quantities to be received */ int quantitiesToRecv[CCI_MAX_NQUANTITIES]; /* array of quantity-identifiers, length of nQuantitiesToRecv */ int nMeshIdsToRecv; /* length of meshIdsToRecv, either 1 or nQuantitiesToRecv */ int meshIdsToRecv[CCI_MAX_NQUANTITIES]; /* array of mesh-identifiers, length of MeshIdsToRecv */ /*--- convergence check ---*/ int remoteCodeId; int myConvergenceState; int globalConvergenceState; int error, cont = 1; int comm, Iteration = 0; /*--- general variables ---*/ int i_am_a_cci_process; int change = 1; int index,i,j; double inc; int ix,iy,iNode,nNodex,nNodey,el_id_n,m,n1,n2,n3,m1,m2,m3; double dx,dy,x,y,z; int ElmIndexShift; double deltax = 0,deltay = 0,deltaz = 0; float insTime = 0.0, maxTime = 5.0, deltaTime= 0.1; float eps = 0.0001; /*--- this part is from plane123.c file decleration of the plates variables ---*/ Node point1, point2, point3; Node ***nodeMatrix_Plane1, ***nodeMatrix_Plane2, ***nodeMatrix_Plane3; Node RefKo1, RefKo2, RefKo3; /*********************************************************************** ***********************************************************************/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%* * * * initialization phase: * * * *%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

62

A. THE DUMMY CODE CCI_Init (&argc, &argv); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%* * * * mesh definition phase: * * * *%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /***** ----- Define partitions ----- *****/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~* * CCI_Def_partition 1 : * *~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ meshId = 1; partId1 = 1; CCI_Def_partition(meshId, partId1); printf("... returned from CCI_Def_partition. \n"); fflush(stdout); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~* * CCI_Def_partition 2 : * *~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ meshId = 1; partId2 = 2; CCI_Def_partition(meshId, partId2); printf("... returned from CCI_Def_partition. \n"); fflush(stdout); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~* * CCI_Def_partition 3 : * *~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ meshId = 1; partId1 = 3; CCI_Def_partition(meshId, partId3); printf("... returned from CCI_Def_partition. \n"); fflush(stdout);

deltax = 0.25 - 0.001046717167; deltay = 0.21; deltaz = 0.0; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* * Nodes for partition 1 (nodeMatrix_Plane1) * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ n1 = 36, m1 = 42 ; /* n1 is the node number along the longitudinal(u) direction, m1 is the node number along the transverse(v) direction, respectively */

63

A. THE DUMMY CODE RefKo1.x = 0.0 + deltax; RefKo1.y = 0.0 + deltay; RefKo1.z = 0.0 + deltaz; RefKo1.id = 0; /* three points are needed in order in the global coordinate system */ point1.x = 0.0; point1.y point2.x = 0.35 + 0.001046717167; point2.y point3.x = 0.0; point3.y to create a plane = 0.0; point1.z = 0.0; = 0.0; point2.z = 0.0; = 0.0; point3.z = 0.41;

nodeMatrix_Plane1 = createPlane(Refko, point1, point2, point3, n1, m1); /* nodeMatrix_Plane1=createPlane(Refko,1st point,2nd point,3rd point,n1,m1) */ nNodes1 = m1 * n1; /* number of nodes */ nNodesIds1 = nNodes1; /* switch node numbering */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* * Nodes for partition 2 (nodeMatrix_Plane2) * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ n2 = 36, m2 = 42 ; RefKo2.x = 0.0 + deltax; RefKo2.y = -0.02 + deltay; RefKo2.z = 0.0 + deltaz; RefKo2.id = 1512; point1.x = 0.0; point2.x = 0.35 + 0.001046717167; point3.x = 0.0; point1.y = 0.0; point1.z = 0.0; point2.y = 0.0; point2.z = 0.0; point3.y = 0.0; point3.z = 0.41;

nodeMatrix_Plane2 = createPlane(Refko, point1, point2, point3, n2, m2); /* nodeMatrix_Plane2=createPlane(Refko,1st point,2nd point,3rd point,n2,m2) */ nNodes2 = m2 * n2; /* number of nodes */ nNodesIds2 = nNodes2; /* switch node numbering */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* * Nodes for partition 3 (nodeMatrix_Plane3) * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ n1 = 3, m1 = 42 ; RefKo1.x = 0.0 + deltax; RefKo1.y = 0.0 + deltay;

64

A. THE DUMMY CODE RefKo1.z = 0.0 + deltaz; RefKo1.id = 0; point1.x = 0.35 + 0.001046717167; point2.x = 0.35 + 0.001046717167; point3.x = 0.35 + 0.001046717167; point1.y = 0.0; point1.z = 0.0; point2.y = 0.02; point2.z = 0.0; point3.y = 0.0; point3.z = 0.41;

nodeMatrix_Plane3 = createPlane(Refko, point1, point2, point3, n3, m3); /* nodeMatrix_Plane3=createPlane(Refko,1st point,2nd point,3rd point,n3,m3) */ nNodes3 = m3 * n3; /* number of nodes */ nNodesIds3 = nNodes3; /* switch node numbering */ /***** ----- Associate node partitions ----- *****/ printf("... begin associating nodes. \n"); fflush(stdout); Associate_partitions (nodeMatrix_Plane1, nodeMatrix_Plane3,n1,m1,n3,m3); Associate_partitions (nodeMatrix_Plane2, nodeMatrix_Plane3,n2,m2,n3,m3); printf("... returned Associate_partitions. \n"); fflush(stdout); /***** ----- for debugging ----- *****/ printf("********* Plane1 *********\n"); debug (nodeMatrix_Plane1, 36, 42); printf("********* Plane2 *********\n"); debug (nodeMatrix_Plane2, 36, 42); printf("********* Plane3 *********\n"); debug (nodeMatrix_Plane3, 3, 42); /***** ----- Create node matrices ----- *****/ for (j=0; iNode=1; j<m1, j++) { for (i=0; i<n1; i++, ++iNode) { nodeIds1[iNode-1] = nodeMatrix_Plane1[i][j] -> id; coodrs1[(iNode-1)*globalDim + 0] = nodeMatrix_Plane1[i][j] -> x; coodrs1[(iNode-1)*globalDim + 1] = nodeMatrix_Plane1[i][j] -> y; coodrs1[(iNode-1)*globalDim + 0] = nodeMatrix_Plane1[i][j] -> z; } } for (j=0; iNode=1; j<m2, j++) { for (i=0; i<n2; i++, ++iNode) { nodeIds2[iNode-1] = nodeMatrix_Plane2[i][j] -> id;

65

A. THE DUMMY CODE coodrs2[(iNode-1)*globalDim + 0] = nodeMatrix_Plane2[i][j] -> x; coodrs2[(iNode-1)*globalDim + 1] = nodeMatrix_Plane2[i][j] -> y; coodrs2[(iNode-1)*globalDim + 0] = nodeMatrix_Plane2[i][j] -> z; } } for (j=0; iNode=1; j<m3, j++) { for (i=0; i<n3; i++, ++iNode) { nodeIds3[iNode-1] = nodeMatrix_Plane3[i][j] -> id; coodrs3[(iNode-1)*globalDim + 0] = nodeMatrix_Plane3[i][j] -> x; coodrs3[(iNode-1)*globalDim + 1] = nodeMatrix_Plane3[i][j] -> y; coodrs3[(iNode-1)*globalDim + 0] = nodeMatrix_Plane3[i][j] -> z; } } /***** ----- Define CCI_Def_nodes ----- *****/ printf("... calling CCI_Def_nodes ... \n"); fflush(stdout); /* to observe the progress */ CCI_Def_nodes ( meshId, partId1, globalDim, nNodes1, nNodesIds1, nodeIds1, realType, coords1); CCI_Def_nodes ( meshId, partId2, globalDim, nNodes2, nNodesIds2, nodeIds2, realType, coords2); CCI_Def_nodes ( meshId, partId3, globalDim, nNodes3, nNodesIds3, nodeIds3, realType, coords3); printf("... returned from CCI_Def_nodes ... \n"); fflush(stdout); /* to observe the progress */ /***** ----- Create node matrices ----- *****/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~* * CCI_Def_elems 1 : * *~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ nElements1 = /* n1 nElemIds1 = nElemTypes1 = (m1-1)*(n1-1); and m1 are the numbers of the nodes in 2D */ nElements1; 1;

for(index=0; index<nElements1; ++index) elemIds1[index]=index+1; /* create elements and assign a number each of them */ /* m_el = m-1; n_el =n-1; for (i=1; i<m_el;i++)... */

66

A. THE DUMMY CODE

for (j=1; j<m1, j++) { for (i=1; i<n1; i++) { el_id = (j-1)*(n1-1) + i; /* printf("Element ID %d, i:%d, j:%d\n", el_id, i,j); */ /* printf("elemNode1 %d,\n", nodeMatrix_Plane1[i-1][j-1] ->id); */ elemNodes1[4*(el_id-1) + 0] = nodeMatrix_Plane1[i-1][j-1]->id; /* printf("elemNode2 %d,\n", nodeMatrix_Plane1[i][j-1] ->id); */ elemNodes1[4*(el_id-1) + 1] = nodeMatrix_Plane1[i][j-1]->id; /* printf("elemNode4 %d,\n", nodeMatrix_Plane1[i][j] ->id); */ elemNodes1[4*(el_id-1) + 2] = nodeMatrix_Plane1[i][j]->id; /* printf("elemNode3 %d,\n", nodeMatrix_Plane1[i-1][j] ->id); */ elemNodes1[4*(el_id-1) + 3] = nodeMatrix_Plane1[i-1][j]->id; } } printf("... calling CCI_Def_elements. Part 1. \n"); fflush(stdout); CCI_Def_elems ( meshId, partId1, nElements1, nElemIds1, elemIds1, nElemTypes1, elemTypes1, nNodesPerElem1, elemNodes1); printf("... returned from CCI_Def_elements. Part 1. \n"); fflush(stdout); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* * CCI_Def_elems 3 : !!!!! MUST BE BEFORE CCI_Def_elems 2 !!!!! * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ nElements3 = /* n3 nElemIds3 = nElemTypes3 = (m3-1)*(n3-1); and m3 are the numbers of the nodes in 2D */ nElements3; 1;

ElmIndexShift = nElements1 ; for(index=0 + ElmIndexShift ; index<nElements3 + ElmIndexShift; ++index) { elemIds3[index - ElmIndexShift]=index+1; /* printf("%d\n", elemIds3[index - ElmIndexShift]); */ } /* m_el = m-1; n_el =n-1; for (i=1; i<m_el;i++)... */

67

A. THE DUMMY CODE for (j=1; j<m3, j++) { for (i=1; i<n3; i++) { el_id = (j-1)*(n3-1) + i; /* printf("Element ID %d, i:%d, j:%d\n", el_id, i,j); */ /* printf("elemNode1 %d,\n", nodeMatrix_Plane3[i-1][j-1] ->id); */ elemNodes3[4*(el_id-1) + 0] = nodeMatrix_Plane3[i-1][j-1]->id; /* printf("elemNode2 %d,\n", nodeMatrix_Plane3[i][j-1] ->id); */ elemNodes3[4*(el_id-1) + 1] = nodeMatrix_Plane3[i][j-1]->id; /* printf("elemNode4 %d,\n", nodeMatrix_Plane3[i][j] ->id); */ elemNodes3[4*(el_id-1) + 2] = nodeMatrix_Plane3[i][j]->id; /* printf("elemNode3 %d,\n", nodeMatrix_Plane3[i-1][j] ->id); */ elemNodes3[4*(el_id-1) + 3] = nodeMatrix_Plane3[i-1][j]->id; } } printf("... calling CCI_Def_elements. Part 3. \n"); fflush(stdout); CCI_Def_elems ( meshId, partId3, nElements3, nElemIds3, elemIds3, nElemTypes3, elemTypes3, nNodesPerElem3, elemNodes3); printf("... returned from CCI_Def_elements. Part 3. \n"); fflush(stdout); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~* * CCI_Def_elems 2 : * *~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ nElements1 = /* n2 nElemIds2 = nElemTypes2 = (m2-1)*(n2-1); and m2 are the numbers of the nodes in 2D */ nElements2; 1;

ElmIndexShift = nElements1 + nElements3; for(index=0 + ElmIndexShift ; index<nElements2 + ElmIndexShift; ++index) { elemIds2[index - ElmIndexShift]=index+1; /* printf("%d\n", elemIds3[index - ElmIndexShift]); */ } /* m_el = m-1; n_el =n-1; for (j=1; j<m2, j++) for (i=1; i<m_el;i++)... */

68

A. THE DUMMY CODE { for (i=1; i<n2; i++) { el_id = (j-1)*(n2-1) + i; /* printf("Element ID %d, i:%d, j:%d\n", el_id, i,j); */ /* printf("elemNode2 %d,\n", nodeMatrix_Plane1[i-1][j-1] ->id); */ elemNodes2[4*(el_id-1) + 0] = nodeMatrix_Plane2[i-1][j-1]->id; /* printf("elemNode2 %d,\n", nodeMatrix_Plane2[i][j-1] ->id); */ elemNodes2[4*(el_id-1) + 1] = nodeMatrix_Plane2[i][j-1]->id; /* printf("elemNode4 %d,\n", nodeMatrix_Plane2[i][j] ->id); */ elemNodes2[4*(el_id-1) + 2] = nodeMatrix_Plane2[i][j]->id; /* printf("elemNode3 %d,\n", nodeMatrix_Plane2[i-1][j] ->id); */ elemNodes2[4*(el_id-1) + 3] = nodeMatrix_Plane2[i-1][j]->id; } } printf("... calling CCI_Def_elements. Part 2. \n"); fflush(stdout); CCI_Def_elems ( meshId, partId2, nElements2, nElemIds2, elemIds2, nElemTypes2, elemTypes2, nNodesPerElem2, elemNodes2); printf("... returned from CCI_Def_elements. Part 2. \n"); fflush(stdout); /*********************************************************************** ***********************************************************************/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* * Syncronization Point 1 : CCI_Def_Sync_point * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ syncPointId=1; maxnQuantToSend = CCI_MAX_NQUANTITIES; maxnQuantToRecv = CCI_MAX_NQUANTITIES; printf("... calling CCI_Sync_point_info ... \n"); fflush(stdout); CCI_Sync_point_info ( syncPointId, CCI_MAX_NQUANTITIES, quantitiesToSend, meshIdsToSend, &nQuantitiesToSend, CCI_MAX_NQUANTITIES, quantitiesToSend, meshIdsToRecv,

69

A. THE DUMMY CODE &nQuantitiesToRecv); printf("... returned from CCI_Sync_point_info ... \n"); fflush(stdout); nMeshIdsToSend = nQuantitiesToSend; /* to send each quantities we need a mesh */ nMeshIdsToRecv = nQuantitiesToRecv; printf("... calling CCI_Def_sync_point ... \n"); fflush(stdout); CCI_Def_sync_point ( syncPointId, nQuantitiesToSend, quantitiesToSend, nMeshIdsToSend, meshIdsToSend, nQuantitiesToRecv, quantitiesToRecv, nMeshIdsToRecv, meshIdsToRecv);

printf("... returned from CCI_Def_sync_point ... \n"); fflush(stdout); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* * Syncronization Point 2 : * * for sending displacements to CFX * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ syncPointId=2; maxnQuantToSend = CCI_MAX_NQUANTITIES; maxnQuantToRecv = CCI_MAX_NQUANTITIES; CCI_Sync_point_info ( syncPointId, CCI_MAX_NQUANTITIES, quantitiesToSend, meshIdsToSend, &nQuantitiesToSend, CCI_MAX_NQUANTITIES, quantitiesToSend, meshIdsToRecv, &nQuantitiesToRecv); nMeshIdsToSend = nQuantitiesToSend; /* to send each quantities we need a mesh */ nMeshIdsToRecv = nQuantitiesToRecv; CCI_Def_sync_point ( syncPointId, nQuantitiesToSend, quantitiesToSend, nMeshIdsToSend, meshIdsToSend, nQuantitiesToRecv,

70

A. THE DUMMY CODE quantitiesToRecv, nMeshIdsToRecv, meshIdsToRecv); i_am_a_cci_process = 1; /* Close definition phase */ CCI_Close_setup(i_am_a_cci_process); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%* * * * coupled computation phase: * * * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ do{ insTime = insTime + deltaTime; printf("Inst.time = %lf \n", insTime); printf("Max.time = %lf \n", maxTime); /***** ----- Get the values from the MpCCI ----- *****/ for(index=1; index<=3*nNodes1; index++) { force1[index] = 0.0; } for(index=1; index<=3*nNodes2; index++) { force2[index] = 0.0; } for(index=1; index<=3*nNodes3; index++) { force3[index] = 0.0; } fx1 = 0.0; fy1 = 0.0; fz1 = 0.0; fx2 = 0.0; fy2 = 0.0; fz2 = 0.0; fx3 = 0.0; fy3 = 0.0; fz3 = 0.0; printf("before Sync. point ID 1 \n", insTime); /* for debugging */ syncPointId = 1; quantityId = 2; /* forces have ID 2 */ quantityDim = 3; valuesDataType = CCI_DOUBLE_PRECISION; maxnEmptyNodes = 0; CCI_Status status; printf("before CCI_Reach_sync_point 1 \n"); /* for debugging */ CCI_Reach_sync_point (syncPointId, &status);

71

A. THE DUMMY CODE /*~~~~~~~~~~~~~~~~~~~~~~* * Partition 1 : * *~~~~~~~~~~~~~~~~~~~~~~*/ printf("before CCI_Get_nodes Part 1 \n"); CCI_Get_nodes(meshId, partId1, quantityId, quantityDim, nNodes1, nNodesIds1, nodeIds1, valuesDataType, force1, maxnEmptyNodes, EmptyNodes, &nEmptyNodes);

/* the force vector */

/*~~~~~~~~~~~~~~~~~~~~~~* * Partition 2 : * *~~~~~~~~~~~~~~~~~~~~~~*/ printf("before CCI_Get_nodes Part 2 \n"); CCI_Get_nodes(meshId, partId2, quantityId, quantityDim, nNodes2, nNodesIds2, nodeIds2, valuesDataType, force2, maxnEmptyNodes, EmptyNodes, &nEmptyNodes);

/* the force vector */

/*~~~~~~~~~~~~~~~~~~~~~~* * Partition 3 : * *~~~~~~~~~~~~~~~~~~~~~~*/ printf("before CCI_Get_nodes Part 3 \n"); CCI_Get_nodes(meshId, partId3, quantityId, quantityDim, nNodes3, nNodesIds3, nodeIds3, valuesDataType, force3, maxnEmptyNodes,

/* the force vector */

72

A. THE DUMMY CODE EmptyNodes, &nEmptyNodes); /***** ----- Check sum of the incoming forces ----- *****/ for(index=1; index<=nNodes1; index++) { fx1 = fx1 + force1[3*index - 2]; fy1 = fy1 + force1[3*index - 1]; fz1 = fz1 + force1[3*index]; } for(index=1; index<=nNodes2; index++) { fx2 = fx2 + force2[3*index - 2]; fy2 = fy2 + force2[3*index - 1]; fz2 = fz2 + force2[3*index]; } for(index=1; index<=nNodes3; index++) { fx3 = fx3 + force3[3*index - 2]; fy3 = fy3 + force3[3*index - 1]; fz3 = fz3 + force3[3*index]; } printf(sum of the forces (partition 1) received by AdhoC_Dummy = %4.2f", sqrt(fx1*fx1 + fy1*fy1 + fz1*fz1)); printf(sum of the forces (partition 2) received by AdhoC_Dummy = %4.2f", sqrt(fx2*fx2 + fy2*fy2 + fz2*fz2)); printf(sum of the forces (partition 3) received by AdhoC_Dummy = %4.2f", sqrt(fx3*fx3 + fy3*fy3 + fz3*fz3)); /***** ----- Calculation of the displacements ----- *****/ printf("before calling AdhoC_Dummy \n"); change = 1; /* parabolic displacement of the nodes of the first and second plane */ AdhoC_Dummy (n1,m1,change,displacement1,insTime); /* returns to the displacement vector */ AdhoC_Dummy (n2,m2,change,displacement2,insTime); /* returns to the displacement vector */ change = 1; /* constant displacement for all nodes of the third plane */ AdhoC_Dummy (n3,m3,change,displacement3,insTime); /* returns to the displacement vector */ printf("before Sync. point 2 \n");

73

A. THE DUMMY CODE

/* Put the displacements into MpCCI */ syncPointId = 2; quantityId = 1; /* forces have ID 1 */ quantityDim = 3; valuesDataType = CCI_DOUBLE_PRECISION; /***** ----- Send the values to the MpCCI ----- *****/ /*~~~~~~~~~~~~~~~~~~~~~~* * Partition 1 : * *~~~~~~~~~~~~~~~~~~~~~~*/ CCI_Put_nodes(meshId, partId1, quantityId, quantityDim, nNodes1, nNodesIds1, nodeIds1, valuesDataType, displacement1); /*~~~~~~~~~~~~~~~~~~~~~~* * Partition 2 : * *~~~~~~~~~~~~~~~~~~~~~~*/ CCI_Put_nodes(meshId, partId2, quantityId, quantityDim, nNodes2, nNodesIds2, nodeIds2, valuesDataType, displacement2); /*~~~~~~~~~~~~~~~~~~~~~~* * Partition 3 : * *~~~~~~~~~~~~~~~~~~~~~~*/ CCI_Put_nodes(meshId, partId3, quantityId, quantityDim, nNodes3, nNodesIds3, nodeIds3, valuesDataType, displacement3);

/* the displacement vector */

/* the displacement vector */

/* the displacement vector */

74

A. THE DUMMY CODE

CCI_Reach_sync_point (syncPointId, &status); /***** ----- Iteration Control ----- *****/ myConvergenceState = CCI_CONTINUE; remoteCode = 2; comm = CCI_COMM_RCODE[remoteCodeId]; error = CCI_Check_convergence(myConvergenceState, &globalConvergenceState, comm); printf("error = %d\n", error); switch(globalConvergenceState) { case CCI_CONVERGED: cont = 1; printf("case CCI_CONVERGED, cont = %d\n", cont); break; case CCI_CONTINUE: cont = 1; printf("case CCI_CONTINUE, cont = %d\n", cont); break; case CCI_STOP: cont = 0; printf("case CCI_STOP, cont = %d\n", cont); break; case CCI_DIVERGED: cont = 0; printf("case CCI_DIVERGED, cont = %d\n", cont); break; } Iteration++; printf("iteration number = %d\n", Iteration); If(Iteration == 50) cont =0; }while (cont); /* fabs(maxTime - insTime)<=eps */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%* * * * termination phase: * * * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ CCI_Finalize(); printf("CCI_Finalize\n"); return 0; }

75

B. PYTHON SCRIPT
#!/usr/bin/env python # This script reads a MonitorPointFile and filters it # using given data in order to obtain suitable format for gnuplot import sys from Numeric import * resultList = [] # for global result list scale = 200 #scaling for depth def readHeader( fileIn, iterationCounterName, colNames ): # it will be the column number of iterationCounters iterationCounter=0 # list of column numbers of the result of interest cols=[] # aktuel column number colPos = 0 for line in fileIn: if line.find("@END@") > -1: return (iterationCounter,cols) if line.find(iterationCounterName) == 0: iterationCounter = colPos for n in colNames: if line.find(n) == 0: cols.append(colPos) # rows with "@" will not be accepted as column name if line.find("@") == -1: colPos += 1 def processData( fileIn, fileOut, iterationCounter, cols): prevLine=[] fileIn.seek(0) while fileIn.readline().find("@END@") == -1: pass # local definition, result will be written def writeResultLine(): res=[] # c is an index of prevLine

76

B. PYTHON SCRIPT for c in cols: res.append(prevLine[c]) # res is a list of the row of the filtered results fileOut.write(" ".join(res)) fileOut.write("\n") # "\n\r" fr windows u # global result list for calculation of mean value resultList.append(res[0]) # print #float(res[0]) for l in print line = # print # fileIn: l l.strip().split(",") line[5]

if prevLine == []: prevLine = line continue if prevLine[iterationCounter] >= line[iterationCounter]: writeResultLine() prevLine = line writeResultLine() ################# main program ############################## if len(sys.argv) < 5: print "usage : %s inFile outFile iteratorColName resultColName_1 [... resultColName_n]"%sys.argv[0] sys.exit(0) # open files fileIn = open(sys.argv[1],"r") fileOut = open(sys.argv[2],"w") # read Header (iterationCounter,cols) = readHeader(fileIn, sys.argv[3], sys.argv[4:]) processData(fileIn,fileOut,iterationCounter,cols) fileIn.close() fileOut.close() # setting things to 0 sum = 0.0 vonwo = 1500 biswo = 2000 mean = 0.0 plus = 0.0 minus = 0.0 # consider the last results only resultList = resultList[vonwo:biswo] # convert contents of list into floats resultList = map(float,resultList) for n in resultList: sum = sum + float(n)

77

B. PYTHON SCRIPT

summax = 0.0 summin =0.0 min = [] # list of minimums max = [] # list of maximums mean = (sum/len(resultList)) for n in resultList: n = n - mean for i in range(len(resultList)-2): if ((resultList[i+1]<=resultList[i]) and (resultList[i+1]<= resultList[i+2])): min.append(resultList[i+1]) summin = summin + resultList[i+1] if ((resultList[i+1]>=resultList[i]) and (resultList[i+1]>= resultList[i+2])): max.append(resultList[i+1]) summax = summax + resultList[i+1] meanmax = (summax/len(max))*scale meanmin = (summin/len(min))*scale resultList = asarray (resultList) # convert list into array max = asarray (max) min = asarray (min) plusminus = abs(meanmax-meanmin) print meanmax print meanmin print plusminus/2 #print resultList*scale print mean*scale print end }

78