LifeV
FortranWrapper.hpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5 Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6 Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8 This file is part of LifeV.
9 
10 LifeV is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14 
15 LifeV is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 /*!
27  @file
28  @brief Fortran wrapper for C++
29 
30  @date 1-03-2002
31  @author Luca Formaggia
32 
33  @maintainer Radu Popescu <radu.popescu@epfl.ch>
34 */
35 
36 #ifndef FORTRAN_WRAPPER_H
37 #define FORTRAN_WRAPPER_H
38 
39 #include <cassert>
40 #include <cstddef>
41 #include <cstring>
42 
43 namespace LifeV
44 {
45 
46 //! \file fortran_wrap.h
47 /*
48  Useful utilities for interfacing FORTRAN77 subroutines with C++
49  code. Mainly based on the utilities developed by Carsten A. Arnholm
50  (http://www.lctn.u-nancy.fr/design/hcomp.html), slightly simplified by
51  Luca Formaggia (March 2002).
52 */
53 typedef int I_F77; // INTEGER 4 bytes
54 typedef float R4_F77; // REAL 4 bytes
55 typedef double R8_F77; // DOUBLE PRECISION 8 bytes
56 typedef int L_F77; // LOGICAL 4 bytes
57 
58 #define FALSE_F77 0
59 #define TRUE_F77 1
60 
61 #define SUBROUTINE_F77 extern "C" void
62 #define INTEGER_FUNCTION_F77 extern "C" int
63 #define REAL_FUNCTION_F77 extern "C" float
64 #define LOGICAL_FUNCTION_F77 extern "C" int
65 #define DOUBLE_PRECISION_FUNCTION_F77 extern "C" double
66 #define F77NAME(X) X ## _
67 
68 //! A matrix class for interfacing with fortran
69 /*!
70 
71  A minimal class used when passing multi-dimensional array arguments from
72  C++ to FORTRAN 77 (received as FORTRAN arrays), and subsequently returned
73  back to C++ as properly aranged C++ arrays.
74 
75  \paragraph Problem
76 
77  FORTRAN organises data in a "column-first" order,
78  while C++ organises data in a "row-first" order.
79 
80  \paragraph Solution
81 
82  (1) The FortranMatrix class can take a C++ array as a constructor
83  parameter. A FORTRAN compatible copy of the array is
84  then made. The destructor will then copy the result back
85  to the original c++ array.
86 
87 
88  (2) The FortranMatrix class provides "subscript operators" allowing
89  the programmer to read and write from the array, using
90  FORTRAN-like syntax and indexing semantics.
91 
92  /author Carsten A. Arnholm, 04-MAR-1996 (Modified by L. Formaggia MAR 2002)
93 */
94 template <class ScalarType>
95 class FortranMatrix
96 {
97 public:
98  //! @name Public typedefs
99  //@{
100  typedef ScalarType scalar_Type;
101  //! @name Constructors and destructor
102  //@{
103  FortranMatrix() {}
104  FortranMatrix ( size_t dim1, size_t dim2 = 1 );
105  FortranMatrix ( ScalarType* cppArray, size_t dim1, size_t dim2 = 1 );
106  virtual ~FortranMatrix();
107  //@}
108 
109  //! @name Operators
110  //@{
111  operator ScalarType* ();
112  ScalarType& operator() ( size_t index1, size_t index2 = 0 ); // numbering from 0
113  //@}
114 
115 public:
116  size_t M_arrayDimensions[ 7 ]; // size of each dimension
117  ScalarType* M_cppRepresentation; // original c++ array
118  ScalarType* M_fortranRepresentation; // array used by FORTRAN
119  const size_t M_numDimensions; // number of array dimensions
120 };
121 
122 //! F77 compatible character class
123 /*!
124  *
125  A minimal class used when passing string arguments from C++ to FORTRAN 77
126  (received as FORTRAN 77 FortranCharacterString strings), and subsequently returned back
127  to C++ as properly zero terminated strings.
128 
129  \paragraph Method used for zero-termination:
130 
131  When the FortranCharacterString destructor is activated the zero-termination of the
132  c-string is automatically managed. Zero termination is also done each time
133  a string array is subscripted using
134 
135  \verbatim
136  FortranCharacterString::operator()(size_t index)
137  \endverbatim
138 
139  \paragraph FORTRAN Assumptions:
140 
141  (1) F77 truncates strings when FortranCharacterString variable is short
142 
143  (2) F77 pads variable with blanks when assigned string is short
144 
145  (3) F77 represents a string as a pointer followed by a length
146 
147  (4) A string array is stored in contiguous memory
148 
149  \author: Carsten A. Arnholm, 20-AUG-1995
150 
151 */
152 class FortranCharacterString
153 {
154 public:
155  //! @name Constructors and destructor
156  //@{
157  FortranCharacterString() {}
158  FortranCharacterString ( char* cstring );
159  FortranCharacterString ( char* cstring, const size_t stringLength );
160  virtual ~FortranCharacterString();
161  //@}
162 
163  //! @name Operators
164  //@{
165  FortranCharacterString operator() ( size_t index );
166  void operator= ( char* str );
167  operator char* ();
168  //@}
169 
170  //! @name Methods
171  //@{
172  void pad ( size_t first, size_t paddingSize = 1 );
173  //@}
174 
175 public:
176  char* M_representation; // Actual string
177  size_t M_length; // String length
178 };
179 
180 // ======================
181 // IMPLEMENTATIONS
182 // ======================
183 
184 // =======================================
185 // FortranMatrix Constructors and destructor
186 // =======================================
187 
188 template <class ScalarType>
189 FortranMatrix<ScalarType>::FortranMatrix ( size_t dim1, size_t dim2 ) :
190  M_cppRepresentation ( NULL ),
191  M_fortranRepresentation ( new ScalarType[ dim1* dim2 ] ),
192  M_numDimensions ( 2 )
193 {
194  M_arrayDimensions[ 0 ] = dim1;
195  M_arrayDimensions[ 1 ] = dim2;
196  M_arrayDimensions[ 2 ] = 0;
197  M_arrayDimensions[ 3 ] = 0;
198  M_arrayDimensions[ 4 ] = 0;
199  M_arrayDimensions[ 5 ] = 0;
200  M_arrayDimensions[ 6 ] = 0;
201 }
202 
203 template <class ScalarType>
204 FortranMatrix<ScalarType>::FortranMatrix ( ScalarType* cppArray, size_t dim1, size_t dim2 ) :
205  M_cppRepresentation ( cppArray ),
206  M_fortranRepresentation ( new ScalarType[ dim1* dim2 ] ),
207  M_numDimensions ( 2 )
208 {
209  M_arrayDimensions[ 0 ] = dim1;
210  M_arrayDimensions[ 1 ] = dim2;
211  M_arrayDimensions[ 2 ] = 0;
212  M_arrayDimensions[ 3 ] = 0;
213  M_arrayDimensions[ 4 ] = 0;
214  M_arrayDimensions[ 5 ] = 0;
215  M_arrayDimensions[ 6 ] = 0;
216 
217  // make a FORTRAN-compatible copy of the array
218  size_t index_cpp = 0;
219  size_t index_f77;
220  for ( size_t i = 0; i < M_arrayDimensions[ 0 ]; i++ )
221  {
222  for ( size_t j = 0; j < M_arrayDimensions[ 1 ]; j++ )
223  {
224  index_f77 = j * M_arrayDimensions[ 0 ] + i;
225  M_fortranRepresentation[ index_f77 ] = M_cppRepresentation[ index_cpp++ ];
226  }
227  }
228 }
229 
230 template <class ScalarType>
231 FortranMatrix<ScalarType>::~FortranMatrix()
232 {
233  if ( M_cppRepresentation )
234  {
235  assert ( M_numDimensions == 2 ); // only 2d arrays supported (so far)
236  // copy back from FORTRAN to C++ array
237  size_t index_cpp;
238  size_t index_f77 = 0;
239  for ( size_t j = 0; j < M_arrayDimensions[ 1 ]; j++ )
240  {
241  for ( size_t i = 0; i < M_arrayDimensions[ 0 ]; i++ )
242  {
243  index_cpp = i * M_arrayDimensions[ 1 ] + j;
244  M_cppRepresentation[ index_cpp ] = M_fortranRepresentation[ index_f77++ ];
245  }
246  }
247  }
248  // delete the FORTRAN copy of the arry
249  delete[] M_fortranRepresentation;
250 }
251 
252 // ============================
253 // FortranMatrix Operators
254 // ============================
255 
256 template <class ScalarType>
257 FortranMatrix<ScalarType>::operator ScalarType* ()
258 {
259  // Pass the FORTRAN representation when calling a function
260  return M_fortranRepresentation;
261 }
262 
263 template <class ScalarType>
264 ScalarType& FortranMatrix<ScalarType>::operator() ( size_t index1, size_t index2 )
265 {
266  assert ( M_numDimensions == 2 ); // only 2d arrays supported (so far)
267  // indexing according to F77 conventions
268  size_t index_f77 = index2 * M_arrayDimensions[ 0 ] + index1;
269  // return a reference to the array element
270  return * ( M_fortranRepresentation + index_f77 );
271 }
272 
273 // =======================================
274 // FortranCharacterString Constructors and destructor
275 // =======================================
276 
277 inline FortranCharacterString::FortranCharacterString ( char* cstring ) :
278  M_representation ( cstring ),
279  M_length ( strlen ( cstring ) )
280 {}
281 
282 inline FortranCharacterString::FortranCharacterString ( char* cstring, const size_t stringLength ) :
283  M_representation ( cstring ),
284  M_length ( stringLength )
285 {
286  // find position from where to start padding
287  size_t slen = strlen ( M_representation ); // upper limit
288  size_t actual = ( slen < M_length ) ? slen : M_length; // actual <= M_length.
289  for ( size_t i = actual; i < M_length; i++ )
290  {
291  M_representation[ i ] = ' '; // Do the padding.
292  }
293 }
294 
295 inline FortranCharacterString::~FortranCharacterString()
296 {
297  if ( M_representation[ M_length ] == '\0' )
298  {
299  return ; // catches string constants
300  }
301  for ( int i = M_length - 1; i >= 0; i-- )
302  {
303  if ( M_representation[ i ] == '\0' )
304  {
305  break; // already zero terminated
306  }
307  if ( M_representation[ i ] != ' ' )
308  {
309  // non-blank discovered, so
310  M_representation[ i + 1 ] = '\0'; // zero-terminate and jump out
311  break;
312  }
313  }
314 }
315 
316 // ================================
317 // FortranCharacterString Operators
318 // ================================
319 
320 inline FortranCharacterString FortranCharacterString::operator() ( size_t index )
321 {
322  // Construct a temporary FortranCharacterString object for the array element
323  // identified by "index" in order to zero-terminate that element
324  size_t pos = index * M_length; // start pos of array element
325  FortranCharacterString element ( M_representation + pos, M_length ); // construct new FortranCharacterString.
326  return element; // destructor called here.
327 }
328 
329 inline void FortranCharacterString::operator= ( char* str )
330 {
331  strncpy ( M_representation, str, M_length ); // this will copy a zero if str < rep
332  M_representation[ M_length - 1 ] = '\0'; // zero terminate in case strncpy did not
333  size_t slen = strlen ( M_representation ); // upper limit
334  size_t actual = ( slen < M_length ) ? slen : M_length; // actual <= M_length.
335  for ( size_t i = actual; i < M_length; i++ )
336  {
337  M_representation[ i ] = ' '; // Do the padding.
338  }
339 }
340 
341 inline FortranCharacterString::operator char* ()
342 {
343  return M_representation;
344 }
345 
346 // ================================
347 // FortranCharacterString Methods
348 // ================================
349 
350 inline void FortranCharacterString::pad ( size_t first, size_t paddingSize )
351 {
352  size_t pos = 0, i = 0, stop = first + paddingSize - 1;
353  for ( size_t index = first; index <= stop; index++ )
354  {
355  pos = index * M_length;
356  size_t slen = strlen ( M_representation + pos ); // upper limit
357  size_t actual = ( slen < M_length ) ? slen : M_length;
358  for ( i = pos + actual; i < pos + M_length; i++ )
359  {
360  M_representation[ i ] = ' '; // Do the padding.
361  }
362  }
363 }
364 
365 } // Namespace LifeV
366 
367 #endif // FORTRAN_WRAPPER_H
void updateInverseJacobian(const UInt &iQuadPt)