Tag Archives: fortran

在mingw/win7上进行 micromet/snowmelt

Micro-met提供了优秀的气象要素的插值方法。其代码是fortran写成。在windows 7下进行编译需要一点trick。

1. 安装mingw,我安装的gcc 是4.4.0 版本。

2. 安装gfortran,一样4.4.0 版本。

3. 在micro-met code目录下,写一个 build.bat文件,内容是

gfortran -O3 -I. -o ../snowmodel enbal_code.f micromet_code.f preprocess_code.f readparam_code.f snowmodel_main.f snowpack_code.f snowtran_code.f dataassim_user.f outputs_user.f

4. Build.bat生成的snowmodel.exe将在上一级目录。

5. 确保 mingw的bin目录在path里,双击 build.bat,将在上级目录生成 snowmodel.exe

6. 切换到上级目录,双击生成的snowmodel.exe,提示说 页面文件太小,无法执行,类似。在命令行里执行snowmodel,将提示“系统无法执行指定的程序”。此提示是由于内存不够引起。清空占用内存的程序腾出内存一般可以解决。如果还不够,设置page file缓冲。

7. 这是由于 gfortran生成的代码受32MB 内存的限制。一些详细的解释可见以下网址:

http://www.trnicely.net/misc/vista.html

8. 使用管理员权限打开 regedit,在ComputerHKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlWOW 目录下,新建一个 DWORD类型的键DpmiLimit,并将其值设成128000000 (10进制),或者0x7A12000(16进制)。关闭注册表。

9. 双击build.bat重新编译。

10. 在命令行里,执行 snowmodel,将执行。

在C中调用Fortran中的字符串数组

modparm.f

!在此模块下定义了很多共用变量,此处以title为例,定义为60个数组,每数组包括4字符

      module parm
      character(len=4) :: title(60), cpnm(5000)
      end module parm

getallo.f

!此函数(子例程)将使用modparm.f中定义的title变量,将从file.cio文件中读取3行填充title

      subroutine getallo
      use parm

!!    initialize variables
!      write(*,*) title
      title = “”

      open (23,file=”file.cio”)
      read (23,6000) titldum
      read (23,6000) titldum
      read (23,5100) title
      read (23,6000) titldum
      read (23,5000) figfile
      read (23,*) myr

      close (23)
      return
5000 format (6a)
5100 format (20a4)
6000 format (a80)
       end

将两fortran文件使用gfortran联编成 dll ,此时,title的实际符号为 __parm_MOD_title,getallo的实际符号为 getallo_。

在Qt/C++代码中读取和修改 title 变量,两个方法,如下:

1. 直接申明外部变量

#include <QtCore/QCoreApplication>
#include <QDebug>

extern “C” char __parm_MOD_title[60][4];
extern “C” void getallo_();

int main1(int argc, char *argv[])
{

     getallo_();
    char* aa = new char[60*4 +1];

    memcpy(aa, __parm_MOD_title, 60*4);
    aa[240]=”;

    qDebug()<<“__parm_MOD_title:”<<
            aa;
}

同样可以通过数组访问的方式对元素进行修改。

2. 通过动态加载resolve方法

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QLibrary>

extern “C” void getallo_();

int main(int argc, char *argv[])
{
    char * title =(char *)QLibrary::resolve(“../bin/test.dll”,”__parm_MOD_title”);

     getallo_();
    char* aa = new char[60*4 +1];
aa[240]=”;

    memcpy(aa, title, 60*4);

    qDebug()<<“__parm_MOD_title:”<<
            aa;

//修改第一个字符
title[0]=’h’;
   memcpy(aa, title, 60*4);
   qDebug()<<“__parm_MOD_title:”<<
           aa;
}

第二种方法将多维数组作为一维数组进行访问。

qt4与fortran 90的连接

面临的问题是fortran与qt4联编,在qt/c++代码里要访问fortran的4个函数,和很多的数据结构。在c++里全部用extern “C”暴露出来。作了compiler specific的函数名和变量名调整。

试了G95编译fortran代码,与gcc v3进行连接,在传递数组指针时出现问题,疑是编译器级别的问题,无法解决。

找了gfortran,在新版的mingw gcc 4里已经集成里面,重新配置了mingw,安装包如下:

binutils-2.19.1-mingw32-bin
gcc-4.3.0-20080502-mingw32-alpha-bin
mingw32-make-3.81-20080326-2
mingwrt-3.15.2-mingw32-dev
mingwrt-3.15.2-mingw32-dll
w32api-3.13-mingw32-dev

先用gfortran编译了三个f90文件,生成 .o文件,如

gfortran –c module_sf_noahlsm.f90

然后在qt4 pro文件里添加,

OBJECTS += ./module_model_constants.o
./module_Noahlsm_utility.o
./module_sf_noahlsm.o

在LIBS里也需要添加 –lgfortran

qt4编译连接国;过,加载数据测试无误。实现了fortran 90与qt4的一种连接。当然不是最好的方式,有见人在讨论版上说通过修改qt4 spec文件实现直接在pro里添加.f90,调用gfortran直接进行编译,然后相连。这当然是最好的,但对于一般用途,上述方式也足够。