00001 /* 00002 00003 This file is part of OpenFLUID software 00004 Copyright(c) 2007, INRA - Montpellier SupAgro 00005 00006 00007 == GNU General Public License Usage == 00008 00009 OpenFLUID is free software: you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation, either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 OpenFLUID is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>. 00021 00022 00023 == Other Usage == 00024 00025 Other Usage means a use of OpenFLUID that is inconsistent with the GPL 00026 license, and requires a written agreement between You and INRA. 00027 Licensees for Other Usage of OpenFLUID may use this file in accordance 00028 with the terms contained in the written agreement between You and INRA. 00029 00030 */ 00031 00032 00033 00034 /** 00035 @file 00036 00037 @author JC.Fabre <fabrejc@supagro.inra.fr>, C.Dagès <dages@supagro.inra.fr> 00038 00039 00040 @see http://www-h.eng.cam.ac.uk/help/tpl/languages/mixinglanguages.html 00041 @see http://www.neurophys.wisc.edu/comp/docs/notes/not017.html 00042 @see http://www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html 00043 @see http://arnholm.org/software/cppf77/cppf77.htm 00044 @see http://www.aei.mpg.de/~jthorn/c2f.html 00045 00046 Below are examples of C++ simulators calling Fortran subroutines. 00047 00048 00049 fortran source code: 00050 @code 00051 subroutine multrealvalue(value,mult,result) 00052 00053 implicit none 00054 real*8 value 00055 real*8 mult 00056 real*8 result 00057 00058 result=value*mult 00059 00060 return 00061 00062 end 00063 00064 00065 ! ============================================================================== 00066 00067 00068 subroutine multintvalue(value,mult,result) 00069 00070 implicit none 00071 integer value 00072 integer mult 00073 integer result 00074 00075 result=value*mult 00076 00077 return 00078 end 00079 00080 00081 ! ============================================================================== 00082 00083 00084 subroutine multrealmatrix(matrix,dim1,dim2,mult,result) 00085 00086 implicit none 00087 integer dim1 00088 integer dim2 00089 real*8 matrix(dim2,dim1) 00090 integer mult 00091 real*8 result(dim2,dim1) 00092 integer i, j, k 00093 subroutine multrealvalue(value,mult,result) 00094 00095 implicit none 00096 real*8 value 00097 real*8 mult 00098 real*8 result 00099 00100 result=value*mult 00101 00102 return 00103 00104 end 00105 00106 00107 ! ============================================================================== 00108 00109 00110 subroutine multintvalue(value,mult,result) 00111 00112 implicit none 00113 integer value 00114 integer mult 00115 integer result 00116 00117 result=value*mult 00118 00119 return 00120 end 00121 00122 00123 ! ============================================================================== 00124 00125 00126 subroutine multrealmatrix(matrix,dim1,dim2,mult,result) 00127 00128 implicit none 00129 integer dim1 00130 integer dim2 00131 real*8 matrix(dim2,dim1) 00132 integer mult 00133 real*8 result(dim2,dim1) 00134 integer i, j, k 00135 00136 do j=1,dim1 00137 do i=1,dim2 00138 result(i,j) = matrix(i,j) * mult 00139 end do 00140 end do 00141 00142 00143 return 00144 end 00145 00146 do j=1,dim1 00147 do i=1,dim2 00148 result(i,j) = matrix(i,j) * mult 00149 end do 00150 end do 00151 00152 00153 return 00154 end 00155 00156 @endcode 00157 00158 00159 C++ code calling fortran subroutines: 00160 @code 00161 BEGIN_EXTERN_FORTRAN 00162 EXTERN_FSUBROUTINE(multrealvalue)(FREAL8*,FREAL8*,FREAL8*); 00163 EXTERN_FSUBROUTINE(multintvalue)(FINT*,FINT*,FINT*); 00164 EXTERN_FSUBROUTINE(multrealmatrix)(FREAL8*,FINT*,FINT*,FINT*,FREAL8*); 00165 END_EXTERN_FORTRAN 00166 00167 // ===================================================================== 00168 // ===================================================================== 00169 00170 bool FortranFunction::runStep(const openfluid::base::SimulationStatus* SimStatus) 00171 { 00172 int i; 00173 00174 00175 // ====== double ====== 00176 00177 double DValue, DMult, DResult; 00178 DValue = 1.5436; 00179 DMult = 2.5; 00180 DResult = 0.0; 00181 00182 CALL_FSUBROUTINE(multrealvalue)(&DValue,&DMult,&DResult); 00183 00184 if (abs(DResult - (DValue*DMult)) > m_Precision) 00185 OPENFLUID_RaiseError("tests.fortran","incorrect fortran call (multrealvalue)"); 00186 00187 00188 // ====== int ====== 00189 00190 int IValue, IMult, IResult; 00191 IValue = 45; 00192 IMult = 18; 00193 IResult = 0; 00194 00195 CALL_FSUBROUTINE(multintvalue)(&IValue,&IMult,&IResult); 00196 00197 if (IResult != (IValue*IMult)) 00198 OPENFLUID_RaiseError("tests.fortran","incorrect fortran call (multintvalue)"); 00199 00200 00201 // ====== matrix of double ====== 00202 00203 int MMult, MDim1,MDim2; 00204 double *MValue; 00205 double *MResult; 00206 MMult = 3; 00207 MDim1 = 2; 00208 MDim2 = 3; 00209 00210 00211 MValue = new double[MDim1*MDim2]; 00212 MResult = new double[MDim1*MDim2]; 00213 00214 for (i=0; i < MDim1*MDim2;i++) MValue[i] = 1.5; 00215 for (i=0; i < MDim1*MDim2;i++) MResult[i] = 0.0; 00216 00217 CALL_FSUBROUTINE(multrealmatrix)(MValue,&MDim1,&MDim2,&MMult,MResult); 00218 00219 for (i=0; i < MDim1*MDim2;i++) 00220 { 00221 if (abs(MResult[i] - (MValue[i] * MMult)) > m_Precision) 00222 OPENFLUID_RaiseError("tests.fortran","incorrect fortran call (multrealmatrix)"); 00223 } 00224 00225 return true; 00226 } 00227 00228 @endcode 00229 00230 */ 00231 00232 00233 00234 00235 #ifndef __FORTRAN2CPP_HPP__ 00236 #define __FORTRAN2CPP_HPP__ 00237 00238 00239 #ifdef __cplusplus 00240 # define BEGIN_EXTERN_FORTRAN \ 00241 extern "C" \ 00242 { 00243 # define END_EXTERN_FORTRAN } 00244 #else 00245 # define BEGIN_EXTERN_FORTRAN 00246 # define END_EXTERN_FORTRAN 00247 #endif 00248 00249 // ===================================================================== 00250 // ===================================================================== 00251 00252 00253 // calling function or subroutine from a F90 module 00254 00255 /** 00256 Macro for declaration of an external fortran function 00257 @param[in] x the name of the function 00258 */ 00259 #define EXTERN_FFUNCTION(x) x##_ 00260 00261 /** 00262 Macro for calling an external fortran function 00263 @param[in] x the name of the function 00264 */ 00265 #define CALL_FFUNCTION(x) x##_ 00266 00267 /** 00268 Macro for declaration of an external fortran subroutine 00269 @param[in] x the name of the subroutine 00270 */ 00271 #define EXTERN_FSUBROUTINE(x) void x##_ 00272 00273 /** 00274 Macro for calling an external fortran subroutine 00275 @param[in] x the name of the subroutine 00276 */ 00277 #define CALL_FSUBROUTINE(x) x##_ 00278 00279 00280 // ===================================================================== 00281 // ===================================================================== 00282 00283 00284 /** 00285 Macro for declaration of an external fortran90 function in a module 00286 @param[in] x the name of the module 00287 @param[in] y the name of the function 00288 */ 00289 #define EXTERN_FMODFUNCTION(x,y) __##x##__##y 00290 00291 /** 00292 Macro for calling an external fortran90 function in a module 00293 @param[in] x the name of the module 00294 @param[in] y the name of the function 00295 */ 00296 #define CALL_FMODFUNCTION(x,y) __##x##__##y 00297 00298 /** 00299 Macro for declaration of an external fortran90 subroutine in a module 00300 @param[in] x the name of the module 00301 @param[in] y the name of the subroutine 00302 */ 00303 #define EXTERN_FMODSUBROUTINE(x,y) void __##x##__##y 00304 00305 /** 00306 Macro for calling an external fortran90 subroutine in a module 00307 @param[in] x the name of the module 00308 @param[in] y the name of the subroutine 00309 */ 00310 #define CALL_FMODSUBROUTINE(x,y) __##x##__##y 00311 00312 // ===================================================================== 00313 // ===================================================================== 00314 00315 00316 // Numeric data handling 00317 00318 /** 00319 Macro for fortran REAL type in C++ (float) 00320 */ 00321 #define FREAL float 00322 00323 /** 00324 Macro for fortran REAL type in C++ (double) 00325 */ 00326 #define FREAL8 double 00327 00328 #define FREAL16 long double 00329 00330 /** 00331 Macro for fortran INT type in C++ (int) 00332 */ 00333 #define FINT int 00334 00335 /** 00336 Macro for fortran INT*2 type in C++ (short int) 00337 */ 00338 #define FINT2 short int 00339 00340 /** 00341 Macro for fortran INT*8 type in C++ (long int) 00342 */ 00343 #define FINT8 long int 00344 00345 #define FLOGICAL int 00346 #define FLOGICAL1 bool 00347 00348 // ===================================================================== 00349 // ===================================================================== 00350 00351 // Character and string handling 00352 00353 #define FCHARACTER char 00354 00355 #define FSTRING char* 00356 #define FSTRINGLEN int 00357 00358 // ===================================================================== 00359 // ===================================================================== 00360 00361 00362 // Conversion of std::string 00363 00364 #define STD2FSTRING(str) strdup((str).c_str()) 00365 #define STD2FSTRINGLEN(str) strlen((str).c_str()) 00366 #define STD2FSTRINGFULL(str) strdup((str).c_str()),strlen((str).c_str()) 00367 00368 00369 #endif /*__FORTRAN2CPP_H__*/ 00370