Professional Documents
Culture Documents
Master Thesis
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 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.
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.
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
Figure 2.4.: Coarse mesh with prismatic elements. An example of an unstructured 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
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 )
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. Denition of the Test Cases CFD1 CFD2 CFD3 Uave = 0.3 m/s Uave = 1.0 m/s Uave = 2.0 m/s
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
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.
10
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.
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
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)
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
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 ).
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
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
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
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.
meshId partId
IN IN
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)
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.
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.
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
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.
cciProcess IN
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 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
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
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
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.
IN OUT IN
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
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.
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:
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
= struct ( = C: = binary1 =4
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.
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.
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.
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.
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
Fx 1 2 0 dL 2
CL =
Fy 1 2 0 dL 2
respectively, Fx =
s
nx dS
Fy =
s
ny dS
36
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.
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.
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
(a) lift
(b) drag
Figure 5.1.: lift and drag forces [0-20 s.] (Test Case 1)
40
(a) lift
(b) drag
Figure 5.2.: lift and drag forces [0-5 s.] (Test Case 1)
41
(a) lift
(b) drag
Figure 5.3.: lift and drag forces [10-15 s.] (Test Case 1)
42
(a) lift
(b) drag
Figure 5.4.: Comparision of coarse meshes that have dierent thickness [0-20 s.] (Test Case 1)
43
(a) lift
(b) drag
Figure 5.5.: Comparision of coarse meshes that have dierent thickness [0-5 s.] (Test Case 1)
44
(a) lift
(b) drag
Figure 5.6.: Comparision of coarse meshes that have dierent thickness [10-15 s.] (Test Case 1)
45
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
(a) lift
(b) drag
Figure 5.9.: lift and drag forces around the cylinder and ag (CFD2,M1)
47
(a) lift
(b) drag
Figure 5.10.: lift and drag forces around the cylinder and ag (CFD2,M2)
48
(a) lift
(b) drag
Figure 5.11.: lift and drag forces around the cylinder and ag (CFD2,M3)
49
(a) lift
(b) drag
(c) Fourier
Figure 5.12.: lift and drag forces around the cylinder and ag (CFD3,M1) 50
(a) lift
(b) drag
(c) Fourier
Figure 5.13.: lift and drag forces around the cylinder and ag (CFD3,M2) 51
(a) lift
(b) drag
(c) Fourier
Figure 5.14.: lift and drag forces around the cylinder and ag (CFD3,M3) 52
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
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
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
/*--- 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;
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
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);
/*~~~~~~~~~~~~~~~~~~~~~~* * 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);
/*~~~~~~~~~~~~~~~~~~~~~~* * Partition 3 : * *~~~~~~~~~~~~~~~~~~~~~~*/ printf("before CCI_Get_nodes Part 3 \n"); CCI_Get_nodes(meshId, partId3, quantityId, quantityDim, nNodes3, nNodesIds3, nodeIds3, valuesDataType, force3, maxnEmptyNodes,
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
/* 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);
74
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