1、一般派生结构体数组 a、一般派生类型定义 TYPE A integer,allocatable,dimension(:,:,:)::data real:: ... ENDTYPE b、一般派生类型申明,结构体或结构体数组 TYPE(A)::B 或 TYPE(A),dimension(ndim)::B c、一般派生类型动态分配 DO i=1,ndim ALLOCATE(B(i)%data(n1,n2,n3)) ENDDO 2、嵌套派生结构体数组 a、嵌套派生类型定义 TYPE A real,allocatable,dimension(:,:,:)::data ENDTYPE TYPE B TYPE(A),dimension(ndim1)::A1 ENDTYPE TYPE(B),dimension(ndim2)::B1 .... 依此类推 b,嵌套派生结构体动态空间分配 DO i=1,ndim2 DO j=1,ndim1 ALLOCATE(B1(j)%A1(i)%data(n1,n2,n3)) ENDDO ENDDO
环境 Win7 x86 SP1,Intel Fortran XE2011,IMSL 7.0 x86 运行如下测试代码时没有问题 program main INCLUDE 'link_fnl_shared.h' !USE IMSL_INT USE EIG_INT USE RAND_INT implicit none real B(32,32) real :: a(3,3)=(/ 1,0,0, 0,2,0, 0,0,3 /) real eigenvalue(3),eigenvector(3,3) integer i B=rand(B) eigenvalue=eig(A, v=eigenvector) do i=1,2 write(*,('eigenvalue=',f5.2))eigenvalue(i) write(*,('eigenvector= '))eigenvector(:,i) enddo end program main !------------------------------------------------------ 为了测试.i.运算符但是运行如下代码的时候出现问题(代码来自cgl_lgs大大的一个帖子) program exammm include 'link_fnl_shared.h' use imsl_libraries implicit none real:: v=2.3 integer i,j real h00(6,6) real h0(6,6),h(6,6) h00=0.0 do i=1,6 if(mod(i,2)==0) then h00(i,i-1)=v else h00(i,i+1)=v end if end do h0=.i.h00 h=h0.x.h00 write(*,'(6f5.2)') h !检验结果是否为单位矩阵 end program !---------------------------------- 提示如下 1------ 已启动生成: 项目: fnltest, 配置: Debug Win32 ------ 1Compiling with Intel(R) Visual Fortran Compiler XE 12.1.3.300 ... 1Source2.f90 1D:\\Users\\liulinsl\\Documents\\Visual Studio 2010\\Projects\\fnltest\\fnltest\\Source2.f90(115): internal error: Please visit 'http://www.intel.com/software/products/support' for assistance. 1 h00=0.0 1^ 1 1compilation aborted for D:\\Users\\liulinsl\\Documents\\Visual Studio 2010\\Projects\\fnltest\\fnltest\\Source2.f90 (code 1) 1 1Build log written to file://D:\\Users\\liulinsl\\Documents\\Visual Studio 2010\\Projects\\fnltest\\fnltest\\Debug\\BuildLog.htm 1fnltest - 1 error(s), 0 warning(s) ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ========== 运行IMSL的范例.xt. program xt use linear_operators implicit none integer, parameter :: n=32 real(kind(1d0)) :: one=1d0, zero=0d0 real(kind(1d0)) A(n,n), P(n,n), Q(n,n), S_D(n), U_D(n,n), V_D(n,n) ! Generate a random matrix. A = rand(A) ! Compute the singular value decomposition. S_D = SVD(A, U=U_D, V=V_D) ! Compute the (left) orthogonal factor. P = U_D .xt. V_D ! Compute the (right) self-adjoint factor. Q = V_D .x. diag(S_D) .xt. V_D ! Check the results. if (norm( EYE(n) - (P .xt. P)) = sqrt(epsilon(one))) then if (norm(A - (P .x. Q))/norm(A) = sqrt(epsilon(one))) then write (*,*) 'Example 2 for LIN_SOL_SVD (operators) is correct.' end if end if end 同样会出错 1Compiling with Intel(R) Visual Fortran Compiler XE 12.1.3.300 ... 1Source2.f90 1D:\\Users\\liulinsl\\Documents\\Visual Studio 2010\\Projects\\fnltest\\fnltest\\Source2.f90(114): internal error: Please visit 'http://www.intel.com/software/products/support' for assistance. 1 A = rand(A) 1^ 1 1compilation aborted for D:\\Users\\liulinsl\\Documents\\Visual Studio 2010\\Projects\\fnltest\\fnltest\\Source2.f90 (code 1) 1 1Build log written to file://D:\\Users\\liulinsl\\Documents\\Visual Studio 2010\\Projects\\fnltest\\fnltest\\Debug\\BuildLog.htm 1fnltest - 1 error(s), 0 warning(s) ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ========== 改成use rand_int之后 其他地方,例如.xt.处还是会出现internal error 请大大们指教 然后,有人回答: 是这样的,imsl7.0中用use linear_operators这句话是会出错的,当时intel论坛上也有人问,后来intel给出了个X64 imsl的补丁,但是32位的没有。 要使用包含在linear_operators这个库中的函数时,要用use+原函数 例如:上面那个例子把use linear_operators改成use operation_xt即可 另外,imsl7.0引用函数和以前版本不一样的 补充一点: linear_operators这个文件是这样子的(一看就知道原因了): module linear_operators use cond_int use det_int use diag_int use diagonals_int use fft_int use ifft_int use eye_int use lin_eig_self_int use lin_sol_self_int use norm_int use operation_i use operation_ix use operation_t use operation_h use operation_tx use operation_hx use operation_x use operation_xi use operation_xt use operation_xh use orth_int use rand_int use rank_int use svd_int use unit_int use eig_int use chol_int use isnan_int end module
! Random walk in 2 dimensions ! Program to accompany "Computational Physics" by N. Giordano and H. Nakanishi ! Copyright Prentice Hall 1997, 2006 program walk_2d option nolet library "sgfunc.trc" library "sglib.trc" randomize dim x2ave(1000) ! keep r^2 averages here call initialize(x2ave,n_walks,n_steps) ymax = sqr(n_steps) open #1: screen 0,1,0,0.93 set window -2*ymax,2*ymax,-2*ymax,2*ymax set background color "white" clear set color "black" plot area: -0.1,-0.1;-0.1,0.1;0.1,0.1;0.1,-0.1;-0.1,-0.1 plot 0,0; call calculate(x2ave,n_walks,n_steps) call display(x2ave) close #1 end ! initialize variables ! n_walks = number of walkers n_steps = number of steps taken by each walker sub initialize(x2ave(),n_walks,n_steps) input prompt "number of steps per walk = ": n_steps input prompt "number of walks = ": n_walks print "Hit p to pause, anything else to stop plotting." mat redim x2ave(n_steps) end sub ! do the calculation here ! x2ave(n) contains the average of r^2 at step n ! n_walks = total number of walkers ! n_steps = number of steps taken by each walker sub calculate(x2ave(),n_walks,n_steps) randomize cross_flag = 1 plot_flag = 1 for i = 1 to n_walks x = 0 ! current location of the walker y = 0 for j = 1 to n_steps r = rnd if r = 0.25 then x = x + 1 else if r = 0.5 then x = x - 1 else if r = 0.75 then y = y + 1 else y = y - 1 end if if plot_flag = 1 and jn_steps then plot x,y; ! plot each walk until a keystroke is hit else if plot_flag = 1 then plot x,y end if if cross_flag=1 and key input then get key z c$ = chr$(z) if c$="s" or c$="p" then get key z else cross_flag=0 plot_flag=0 end if end if x2ave(j) = x2ave(j) + x^2 + y^2 next j clear next i for i = 1 to n_steps ! normalize x2ave when finished x2ave(i) = log(x2ave(i) / n_walks) next i end sub ! display results now sub display(x2ave()) dim t(0) ! dummy array for plotting call setcanvas("white") set color "black" n = size(x2ave) mat redim t(n) for i = 1 to n t(i) = log(i) next i call settitle("Random Walks") call sethlabel("ln N") call setvlabel("ln R^2") call datagraph(t,x2ave,1,0,"black") call addlsgraph(t,x2ave,1,"red") ! compute and plot least squares fit call fitline(t,x2ave,m,b) set cursor 4,20 print "slope = ";m;", steps =";n get key z end sub
FORTRAN中的数组声明可以有如下几种类型:Explicit-shape Array, Assumed-shape Array, Assumed-size Array, and Deferred-size Array Explicit-shape array: An explicit-shape array is declared with explicit values for the bounds in each dimension of the array(显式指定数组各维的上下界) . http://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/fortran-mac/GUID-1071BCFF-5A84-4CA9-B296-CB1BD5571777.htm#GUID-1071BCFF-5A84-4CA9-B296-CB1BD5571777 Both automatic array and adjustable array are explicit-shape arrays. Automatic Array: an automatic array is an explicit shape array that is a local variable. Automaticarrays are only allowed in function and subroutine subprograms, and are declared in the specification part of the subprogram. At least one bound of an automatic array must be a nonconstant specification expression. The bounds are determined when the subprogram is called. (自动数组是子程序的局地变量,在子程序内部声明,数组维数中至少一维由子程序的参数传递获得,其他维可在子程序中指定) Adjustable Array: a n adjustable array is an explicit shape array that is a dummy argument to a subprogram . At least one bound of an adjustable array must be a nonconstant specification expression. The bounds are determined when the subprogram is called. (局地可调数组是子程序的传递参数之一,同时可调数组维数中至少一维由子程序参数传递获得) Assumed-shape array : a n assumed-shape array is a dummy argument array that assumes the shape of its associated actual argument array(假定形状数组通常在子程序内部声明,指定维数/rank,但不指定维的大小 ) . http://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/fortran-mac/GUID-70941978-B44B-46CE-9156-67A02F23768E.htm#GUID-70941978-B44B-46CE-9156-67A02F23768E Assumed-size array : a n assumed-size array is a dummy argument array that assumes the size (only) of its associated actual argument array; the rank and extents can differ for the actual and dummy arrays(假定大小数组通常在子程序中声明,可以指定1维或多维的大小). http://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/fortran-mac/GUID-E094C9ED-8A70-4220-AA83-CBF957F7223C.htm#GUID-E094C9ED-8A70-4220-AA83-CBF957F7223C Deferred-shape array : a deferred-shape array is an array pointer or an allocatable array(递延形状数组指数组指针或可分配数组,数组的维数和各维大小在指针赋值时或使用allocate语句时获得). http://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/fortran-mac/GUID-885E4216-44C6-47B5-84D7-9F40CBF0008E.htm#GUID-885E4216-44C6-47B5-84D7-9F40CBF0008E 不同类型数组的存储结构不一样,比如Local Adjustable Array是stack array(栈型数组),而Deferred-shape array就是heap array (堆型数组)。stack的大小具有平台依赖性,因此程序中出现较大的局部数组时,可能会出现“segmentation fault”(即所谓的栈溢出,stack overflow),此时要么人为增加系统栈大小,要么将数组存储结构更改为堆结构。同时,两种数据结构在存取效率等多方面具有显著差异。 可参考: http://metman.info/blog/2013/08/12/fortransheng-ming-shu-zu-guo-da-wen-ti-jie-jue-ban-fa/ http://metman.info/blog/2013/05/31/segmentation-faultchan-sheng-gen-ben-yuan-yin/ http://bbs.csdn.net/topics/390147637
转载自: http://blog.163.com/jey_df/blog/static/182550161201222132825185/ 这两天看Hwang的程序中看到这样一个语法: IF (3-N) 30,30,40 30 T2=T2+SQROOT(N-1)*SQROOT(N-2)*PBAR(INDXP(N-2,1))/SQROOT(2*N-3) 40 PBAR(INDXP(N,1))=SQROOT(2*N+1)*T2/(SQROOT(N)*SQROOT(N+1)) 这个IF语句完全不明白是什么意思,然后去询问了高手SnoopyZhao,给我了有建设意义的帮助。这个形式的语法叫Arithmetic IF Statement,三个标号,按顺序分别对应负、零和正的条件 Arithmetic IF Statement It is a three way branch statement of the form, IF( expression ) label1 , label2 , label3 Here expression is any expression producing a result of type INTEGER, REAL or DOUBLE PRECISION, and the three labels are statement labels of executable statements. If the value of the expression is negative, execution transfers to the statement labelled label1 . If the expression is zero, transfer is to the statement labelled label2 , and a positive result causes transfer to label3 . The same label can be repeated. This relic of the original Fortran has been redundant since the early 1960s when the logical IF and computed GOTO were introduced and it should be replaced by an equivalent CASEor IF construct.
对应的C++、C、Fortran、Python、Matlab源码可从 http://geodesy.cn/glonass/index.xml 处下载。 GLONASS Frequency Channels (GFC) are generated using data from official information of GLONASS. This file constains all latest data in the form of a set of date and frequency channels of 24 satellites. All satellites' frequency channels remain unchanged until the date in next set. It's not available if a satellite frequency channel is 99.
Step 1. Google the 'non-commerical intel fortran compiler' tofind the install package of Intel fortran. The download link on thewebsit ( http://software.intel.com/en-us/non-commercial-software-development ). Step 2. Fillyour information to obtain anemail which includes the serial number and filedownload link. Download the files. Step 3. unpack the install filewith the command tar-xzvf ....tar.gz Step 4. installseveral probably necessary sources for intalling fortran.( During my install process, g++ isasked .) sudo apt-get install build-essential sudo apt-get install libstdc++5 apt-get install gcc apt-get install g++ if you want install 32-bit compiler on 64-bit PC, ohter sources maybe needed. Atfirst: apt-get install ia32-libs Then you can install others sources: apt-get install libstdc++5 apt-getinstall lib32stdc++6 apt-get install libc6-dev-i386 apt-get install gcc-multilib apt-get install g++-multilib Moreover,the new version of ubuntu may not include the libstdc++5. We canuse the source of debian. http://packages.debian.org/stable/base/libstdc++5 Download package of deb in the version of i386 andamd64. Come to the directory which include the package of deb.Install package of amd6 4. dpkg -i libstdc++5_xxxxx_amd64.deb Itis more complex for the package of i386, because it may recover thelibrary of 64-bit. So you sould better extract the packagemanually. dpkg –extract libstdc++_xxxxx_i386.deb ./ Then copy thefile 'libstdc++.so.5.xxx' in the directory of lib to the 32-bitlibrary, and link it with libstdc++.so.5. cd usr/lib cp libstdc++.so.5.xxx /usr/lib32 cd/usr/lib32 ln -s libstdc++.so.5.xxx libstdc++.so.5 Step 5. run the file install.sh to install intelfortran. In this process, you must input the serial numer. Look theinformation carefully during this process. sudo ./install.sh Step 6. Source the variables with bash command which will be listedon the screen. Until here,the install process is finished.You can check the install directory with command 'which ifort',check the verison of intel fortran with 'ifort-v'. for64-bit source /opt/intel/Compiler/11.x/xxx/bin/ifortvars.shintel64 ifort –help for 32-bit source /opt/intel/Compiler/11.x/xxx/bin/ifortvars.shia32 ifort –help (/opt/intel/ may be changed to your installdirectory) Step 7. If you do not want to set the enviroment variableseverytime when you open a new terminal, you should better modifythe file .bashrc in your home directory. You need to open the.bashrc file, and all the below command in the last line. source / install-directory /intel/Compiler/11.x/xxx/bin/ifortvars.shintel64 (the command in step 6). Actually, during my install process, I open the .bashrc file athome directory, and add a path below the lastline PATH="$HOME/intel/bin:$PATH" After that you can compile your fortran programwith the most simple command: ifort -o execute-file language.f Sometimes, there will be an unpredicted error (e.g. segmentation fault...) Since my desktop is a 64 bit PC, I don't install the 32 bit library. But actually, I sould better also intall package listed below apt-get install ia32-libs (only needed if you install the 32bit compiler) apt-get install openjdk-6-jre-headless
Sublime的Ctrl+B快捷键是编译过程,Ctrl+Shilt+B是运行过程。个人感觉科研必须要编程,因此选择一门好的编程语言,一个好的IDE,另外加上一个好的键鼠套装,外加一个好的显示器,这样的配置后的编程会是一个很愉悦的体验过程,大家在路上喜欢看美女,编程上当然也需要好的视觉感受,那么请选择Sublime!举几个小例子提升下大家用这个IDE的心情。 编译运行python效果图: 编译运行C效果图: 编译运行C++效果图: 编译运行fortran效果图: 编译运行Makefile效果图: Matlab效果图: 当然了无所不能的sublime还可以写C#,由于本人用的不多,所以留感兴趣的各位体验吧。 Wish you have a good experience with Sublime Text 2. Good Luck. Feng Zhou do the work above.
目前 Abaqus 的最新版本已经是 6.12-1,Intel Fortran 编译器的最新版本也已经到了 IntelParallel Studio XE 2013 Fortran Compiler, visual studio 的版本也有 2012 了。 但是根据: http://www.hiyip.com/?p=321 的介绍, VS2012 不支持 Abaqus6.12-1 ,这也难怪, VS 2012 发布的时间要比 Abaqus6.12 的晚, Abaqus 支持的最高 VS 版本是 VS2010 。 目前流行的搭配是: Abaqus 6.9+VS2005+Intel Fortran 9.1/10.0/10.1 Abaqus 6.10/6.11/6.12+VS2008+Intel Fortran 10.1 本文想要实现的是 将 Abaqus6.12-1 与 Intel Fortran Compiler XE 2013 以及 visualstudio 2010 连接起来,以实现在 Abaqus6.12-1 中调用 subroutine 子程序。 操作系统: win 7 x64 ; CPUintel i3 Abaqus 版本: Abaqus6.12-1 x64 Fortran 版本: Intel Parallel Studio XE 2013 Intel CompilerXE VS 版本: Visual studio 2010 ultimate en ( 1 ) Fortran Intel Fortran Compiler XE 2013 的 ifortvars.bat 批处理文件与 10.1 有较大的不同,在调用 ifortvars.bat 时,需要设定两个参数: 1-arch ; 2-vs ,第一个参数为系统架构 ,第二个参数为 vs 的版本。 格式为: ifortvas.bat arch 在我的电脑上,提供两种模式: C:\Windows\SysWOW64\cmd.exe /E:ON /V:ON /K C:\Program Files (x86)\Intel\Composer XE 2013\bin\ipsxe-comp-vars.bat ia32 vs2010 C:\Windows\SysWOW64\cmd.exe /E:ON /V:ON /K C:\Program Files (x86)\Intel\Composer XE 2013\bin\ipsxe-comp-vars.bat intel64 vs2010 可以查看 开始菜单 - 所有程序 -IntelParallel Studio XE 2013 -CommandPrompt-Parallel Studio XE with Intel Compiler XE v13.0-{IA-32mode ; intel 64 mode ; } 鼠标右击查看属性,从目标中可以看到以上调用方式。 在本系统下,选择 64 位系统 archtechture ,调用方式为: ifortvas.bat intel64 vs2010 即系统架构为 intel64 , vs 版本为 vs2010 。。。 ( 2 ) VS 2010 VS2010 的 vcvarsall.bat 批处理文件在调用时,也需要指定参数 同样,通过 commandprompt 中可以看到有如下几种参数调用方式。。。。 %comspec% /k C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat x86 %comspec% /k C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat x86_ia64 %comspec% /k C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat x86_amd64 %comspec% /k C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat amd64 本文选择第二种,即 x86_ia64 ( 3 ) Abaqus6.12-1 的设置 上面废话了那么多,现在才是正题 记事本打开批处理文件: abq6121.bat 我的电脑上默认位置为: C:\SIMULIA\Abaqus\Commands\abq6121.bat 将 abq6121.bat 中的内容由 @echo off C:\SIMULIA\Abaqus\6.12-1\code\bin\abq6121.exe %* 修改为 call C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat x86_ia64 call C:\Program Files (x86)\Intel\Composer XE 2013\bin\ifortvars.bat intel64 vs2010 @echo off C:\SIMULIA\Abaqus\6.12-1\code\bin\abq6121.exe %* 然后通过 : 程序 -SIMULIA FLEXnet Licensing-Licensing utilities 打开 lmtools , 启动 Abaqus 的 License 再运行 AbaqusVerification 查看 verify.log 文件 Abaqus Product Install Verification... Fri May 10 18:08:08 2013 Running system requirement checks. Requirement: Windows Server 2003, Windows Server 2008,Windows Server 2008 R2, Windows HPC Server2008, Windows XP, Windows Vista, or Windows 7 Product: All Abaqus Products Status: Pass - Found Windows 7 UltimateService Pack 1 (Build 7601) (x64). Requirement: Microsoft Visual C++ 9.0 (2008), or 10.0(2010) Product: Abaqus make utility with C++ and Abaquswith user subroutines Status: Pass - Found Microsoft Visual C++10.0.30319.1. Requirement: Intel Fortran Compiler 10.1 or 11.1 Product: Abaqus make utility with Fortran andAbaqus with user subroutines Status: Warning - Found Intel Fortran Compiler13.0, which is newer than the published Abaqusrequirement at the time this version was released. Later minor releases of a published requirement are generallycompatible with Abaqus. Please check the system requirementsweb page for the latest information on supportedconfigurations. Requirement: MS-MPI 2.0, 3.0 or greater Product: Abaqus analyses using MPI-basedparallelization and Abaqus/CFD Status: Pass - Found MS-MPI 3.0.2369.0. Requirement: Internet Explorer 8.0 or 9.0 or greater,Firefox 3.0 or 3.5 or greater Product: Abaqus Documentation Status: Pass - Found Internet Explorer8.0.7601.17514 WARNING: Verification for all selectedproducts will be attempted, but some products may fail because of the indicated system deficiencies. Found C:\D\AbaqusTemp\verify. All verification files will reside in this directory. 上述方法为解决方案之一,我试过是行得通的 , 也可以不用改 abq6121.bat 批处理文件,只需在启动目标中加入 fortran 和 vs 的 bat ,不过同样要传递参数。 有什么问题大家可以留言,一起讨论看该怎么解决。 ------------------------------------------------------------------------ 参考内容: 关于 ABAQUS 和 User Subroutine 的若干问题 http://www.hiyip.com/?p=321 succeed in installing ABAQUS subroutine http://polymerfem.com/showthread.php?910-succeed-in-installing-ABAQUS-subroutine How to link the fortran compiler with Abaqus? http://imechanica.org/node/11219 abaqus verification------link abaqus with fortran http://blog.renren.com/share/1393531270/7448777700 abaqus 子程序安装过程详解 http://hi.baidu.com/xiaomingbing/item/5de5a5f9f8e5540885d27800 ABAQUS 子程序验证时 Microsoft Visual C++ 无法通过问题的解决【原创,已测试】 http://blog.163.com/scut_yumin/blog/static/1404680092010102974120563/ Abaqus user subroutine in c++ running on 64 bit machine http://polymerfem.com/showthread.php?2168-Abaqus-user-subroutine-in-c-running-on-64-bit-machine
Eclipse安装与配置 涉及软件: Eclipse IDE for C/C++ Developers 安装目录:$HOME/Software/eclipse 安装 注意:此前请确保已经安装了JRE 非常简单。将下载的包解压缩后放到要安装的位置即可,比如$HOME/Software/eclipse。 双击里面的”eclipse”即可启动。 配置 装好后还需要安装PTP和Photran。 第一步: 点击” Help “——》” Install New Software… “来进行软件的安装。 第二步: 在最上面” Work with “的输入框中输入一个国内镜像地址,如 http://mirror.neu.edu.cn/eclipse/releases/helios/ 1) 。然后直接回车即可(这个地址会被自动保存,以后可以再用)。稍等片刻会出来软件列表 第三步: 选择合适软件并安装。 在”General Purpose Tools”分组下勾选”Parallel Tools Platform (PTP) End-User Runtime” 在”Programming Languages”分组下勾选”Fortran Development Tools (Photran)” 2) 然后一路”Next”、”Finish”下去吧,中间会让你接收License。安装完成后提示重启eclipse 第四步: 安装Photran的Intel编译器支持 将地址改为PTP的更新地址 http://download.eclipse.org/tools/ptp/updates/helios 。在”Fortran Development Tools (Photran)“分组下勾选”Linux Intel(R) Fortran Compiler Support”并安装 第五步: 安装idb的Eclipse插件 手动安装。将 H O M E / S o f t w a r e / i n t e l / c o m p o s e r x e − 2011 / e c l i p s e s u p p o r t / c d t 7.0 / e c l i p s e 里 的 文 件 复 制 到 HOME/Software/eclipse 启动 如果直接双击eclipse是不能识别ifort等命令的,因为环境变量是在~/.bashrc中设置的。两种方法: 在命令行启动 建立启动器,修改启动器的启动命令 建立启动器方法 对于Gnome2.X而言(恕我不知道其它DE/WM/Gnome3怎么做),在菜单上 右键 -》 编辑菜单 ,打开主菜单编辑器。选择一个合适的分类,如 “编程” ,然后选择 “新建项目” 填入必要信息: 类型:应用程序 名称:eclipse(随意) 命令:bash -c ”. ~/.bashrc;$HOME/Software/eclipse/eclipse” 点击左侧的图标按钮可以更改图标。
http://www.roguewave.com/Portals/0/products/imsl-numerical-libraries/fortran-library/docs/6.0/math/default.htm?turl=evesf.htm EVESF(输出的结果为本征值的绝对值按照从大到小的顺序) Computes the largest or smallest eigenvalues and the corresponding eigenvectors of a real symmetric matrix. Required Arguments NEVEC — Number of eigenvalues to be computed. (Input) A — Real symmetric matrix of order N . (Input) SMALL — Logical variable. (Input) If . TRUE ., the smallest NEVEC eigenvalues are computed. If . FALSE ., the largest NEVEC eigenvalues are computed. EVAL — Real vector of length NEVEC containing the eigenvalues of A in decreasing order of magnitude. (Output) EVEC — Real matrix of dimension N by NEVEC . (Output) The J -th eigenvector, corresponding to EVAL ( J ), is stored in the J -th column. Each vector is normalized to have Euclidean length equal to the value one. Optional Arguments N — Order of the matrix A . (Input) Default: N = SIZE ( A ,2). LDA — Leading dimension of A exactly as specified in the dimension statement in the calling program. (Input) Default: LDA = SIZE ( A ,1). LDEVEC — Leading dimension of EVEC exactly as specified in the dimension statement in the calling program. (Input) Default: LDEVEC = SIZE ( EVEC ,1). FORTRAN 90 Interface Generic: CALL EVESF (NEVEC , A , SMALL , EVAL , EVEC ) Specific: The specific interface names are S_ EVESF and D_ EVESF . FORTRAN 77 Interface Single: CALL EVESF (N , NEVEC , A , LDA , SMALL , EVAL , EVEC , LDEVEC) Double: The double precision name is DEVESF . Description Routine EVESF computes the largest or smallest eigenvalues and the corresponding eigenvectors of a real symmetric matrix. Orthogonal similarity transformations are used to reduce the matrix to an equivalent symmetric tridiagonal matrix. Then, an implicit rational QR algorithm is used to compute the eigenvalues of this tridiagonal matrix. Inverse iteration is used to compute the eigenvectors of the tridiagonal matrix. This is followed by orthogonalization of these vectors. The eigenvectors of the original matrix are computed by back transforming those of the tridiagonal matrix. The reduction routine is based on the EISPACK routine TRED2 . See Smith et al. (1976). The rational QR algorithm is called the PWK algorithm. It is given in Parlett (1980, page 169). The inverse iteration and orthogonalization computation is discussed in Hanson et al. (1990). The back transformation routine is based on the EISPACK routine TRBAK1 . Comments 1. Workspace may be explicitly provided, if desired, by use of E5ESF/DE5ESF . The reference is: CALL E5ESF (N, NEVEC, A, LDA, SMALL, EVAL, EVEC, LDEVEC, WK, IWK) The additional arguments are as follows: WK — Work array of length 9 N . IWK — Integer array of length N . 2. Informational errors Type Code 3 1 The iteration for an eigenvalue failed to converge. The best estimate will be returned. 3 2 Inverse iteration did not converge. Eigenvector is not correct for the specified eigenvalue. 3 3 The eigenvectors have lost orthogonality. Example In this example, a DATA statement is used to set A to a matrix given by Gregory and Karney (1969, page 55). The largest two eigenvalues and their eigenvectors are computed and printed. The performance index is also computed and printed. This serves as a check on the computations. For more details, see IMSL routine EPISF . USE EVESF_INT USE EPISF_INT USE UMACH_INT USE WRRRN_INT IMPLICIT NONE ! Declare variables INTEGER LDA, LDEVEC, N PARAMETER (N=4, LDA=N, LDEVEC=N) ! INTEGER NEVEC, NOUT REAL A(LDA,N), EVAL(N), EVEC(LDEVEC,N), PI LOGICAL SMALL ! ! Set values of A ! ! A = ( 5.0 4.0 1.0 1.0) ! ( 4.0 5.0 1.0 1.0) ! ( 1.0 1.0 4.0 2.0) ! ( 1.0 1.0 2.0 4.0) ! DATA A/5.0, 4.0, 1.0, 1.0, 4.0, 5.0, 1.0, 1.0, 1.0, 1.0, 4.0, 2.0, 1.0, 1.0, 2.0, 4.0/ ! ! Find eigenvalues and vectors of A NEVEC = 2 SMALL = .FALSE. CALL EVESF (NEVEC, A, SMALL, EVAL, EVEC) ! Compute performance index PI = EPISF(NEVEC,A,EVAL,EVEC) ! Print results CALL UMACH (2, NOUT) CALL WRRRN ('EVAL', EVAL, 1, NEVEC, 1) CALL WRRRN ('EVEC', EVEC, N, NEVEC, LDEVEC) WRITE (NOUT,'(/,A,F6.3)') ' Performance index = ', PI END Output EVAL 1 2 10.00 5.00 EVEC 1 2 1 0.6325 -0.3162 2 0.6325 -0.3162 3 0.3162 0.6325 4 0.3162 0.6325 Performance index = 0.031
一个python和fortran90混编的例子 fortran90程序pow.f90: SUBROUTINE pow(x,n,p) IMPLICIT NONE !f2py intent(in) x !f2py intent(in) n !f2py intent(out) p REAL(KIND=8) :: x,n,p p = x**n END SUBROUTINE pow 这三个 !f2py intent(in) x !f2py intent(in) n !f2py intent(out) p 必须要有! 接着终端: f2py -m pow -c pow.f90 然后test.py内容: #!/usr/bin/env python import pow as pw x = 3. n = 3.5 p = pw.pow(x,n) print p 接着终端输入./test.py即可,下面继续深入python和fortran混编。
大一学的FORTRAN,都忘光了 关于无格式文件读写的一点资料,很有用 http://paulbourke.net/dataformats/fortran/ Reading FORTRAN unformatted binary files in C/C++ Problem Ever wanted to read binary files written by a FORTRAN program with a C/C++ program? Not such an unusual or unreasonable request but FORTRAN does some strange things ..... consider the following FORTRAN code, where "a" is a 3D array of 4 byte floating point values. open(60,file=filename,status='unknown',form='unformatted') write(60) nx,ny,nz do k = 1,nz do j = 1,ny write(60) (a(i,j,k),i=1,nx) enddo enddo close(60) What you will end up with is not a file that is (4 * nx) * ny * nz + 12 bytes long as it would be for the equivalent in most (if not all) other languages! Instead it will be nz * ny * (4 * nx + 8) + 20 bytes long. Why? Reason Each time the FORTRAN write is issued a "record" is written, the record consists of a 4 byte header, then the data, then a trailer that matches the header. The 4 byte header and trailer consist of the number of bytes that will be written in the data section. So the following write(60) nx,ny,nz gets written on the disk as follows where nx,ny,nz are each 4 bytes, the other numbers below are 2 byte integers written in decimal 0 12 nx ny nz 0 12 The total length written is 20 bytes. Similarly, the line write(60) (a(i,j,k),i=1,nx) gets written as follows assuming nx is 1024 and "a" is real*4 0 4096 a(1,j,k) a(2,j,k) .... a(1024,j,k) 0 4096 The total length is 4104 bytes. Fortunately, once this is understood, it is a trivial to read the correct things in C/C++. A consequence that is a bit shocking for many programmers is that the file created with the above code gives a file that is about 1/3 the size than one created with this code. open(60,file=filename,status='unknown',form='unformatted') write(60) nx,ny,nz do k = 1,nz do j = 1,ny do i = 1,nx write(60) a(i,j,k) enddo enddo enddo close(60) In this case each element of a is written in one record and consumes 12 bytes for a total file size of nx * ny * nz * 12 + 20. Note · This doesn't affect FORTRAN programs that might read these files, that is because the FORTRAN "read" commands know how to handle these unformatted files. · The discussion here does not address the transfer of binary files between machines with a different endian. In that case after a short, int, float, double is read the bytes must be rearranged. Fortunately this is relatively straightforward with these macros. · #define SWAP_2(x) ( (((x) 0xff) 8) | ((unsigned short)(x) 8) ) · #define SWAP_4(x) ( ((x) 24) | (((x) 8) 0x00ff0000) | \ · (((x) 8) 0x0000ff00) | ((x) 24) ) · #define FIX_SHORT(x) (*(unsigned short *)(x) = SWAP_2(*(unsigned short *)(x))) · #define FIX_LONG(x) (*(unsigned *)(x) = SWAP_4(*(unsigned *)(x))) · #define FIX_FLOAT(x) FIX_LONG(x) · It appears that the endianness of the 4 byte header and trailer reflect the endianness of the machine doing the writing. Of course if you know the format of the data being written then you can simply skip over the header/trailer bytes, but if you need to decode the file or do error checking then knowledge of the endian of the machine where the file was written and the endian of the machine where the file is being read is necessary. · And lastly, the above does not address the possibility (fairly rare these days) that the files may be transferred between two machines with different internal representations of floating point numbers. If that is the case then you're really in trouble and should probably revert to transferring the data in a readable ASCII format. · Update (Jan 2008): It would appear that on 64 bit machines the 2 header elements are each written as 4 bytes instead of 2 bytes each. · If the file is not already in existence then writing files in FORTRAN to avoid the above, one can use the access='stream' option. This option was introduced reasonably recently explicitly to overcome this issue. C++ 语言 : 用 C ++来读 Fortran 语言写的 bin ( unformatted )形式文件 /* How to read a bin file written by fortran in C program. Fortran write data in bin mode: open(unit=10,file='restart',form='unformatted',status='unknown') write(10) nx,ny,cfl,gamma,tcur,cpu write(10) (((uc(i,j,m,0),i=1,nx),j=1,ny),m=1,4) close(10) In Fortran, every write code, it will first write the bytes that will save, then is the data, and at the end also is the bytes saved. bytewrite, ,bytewrite so, if nx,ny is integer, cfl,gamma,tcur,cpu is double , then total bytes will be 2*4+4*8=40, then bytewrite will be 40. Also, in fortran, the file can not be read as: open(unit=10,file='restart',form='unformatted',status='unknown') read(10) nx,ny,cfl,gamma,tcur,cpu read(10) ((uc(i,j,1,0),i=1,nx),j=1,ny) read(10) ((uc(i,j,2,0),i=1,nx),j=1,ny) ! here will be an error will running close(10) the second write line, will first write nx*ny*4*(8) The code in C to read the file will be fp=fopen("restart","r"); fread(ntemp,sizeof(int),1,fp); fread(nx,sizeof(int),1,fp); fread(ny,sizeof(int),1,fp); fread(cfl,sizeof(double),1,fp); fread(gamma,sizeof(double),1,fp); fread(tcur,sizeof(double),1,fp); fread(cpu,sizeof(cpu),1,fp); fread(ntemp,sizeof(int),1,fp); // begin an other write line fread(ntemp,sizeof(int),1,fp); fread(data,sizeof(double),nx*ny*4),fp); fread(ntemp,sizeof(int),1,fp); */ #include stdlib.h #include stdio.h int main( int argc, char *argv = "restart" ; FILE *fp; int nx,ny; double cfl,gamma,t0,cpu0; double vmin,vmax; int nmin,nmax; int ntemp; if (argc== 1 ) fp=fopen( "restart" , "r" ); else fp=fopen(argv , "r" ); if (!fp) return 1 ; fread(ntemp, sizeof ( int ), 1 ,fp); printf( "write %d bytes\n" ,ntemp); fread(nx, sizeof ( int ), 1 ,fp); // fseek(fp,4,SEEK_SET); fread(ny, sizeof ( int ), 1 ,fp); // fseek(fp,16,SEEK_SET); fread(cfl, sizeof ( double ), 1 ,fp); fread(gamma, sizeof ( double ), 1 ,fp); fread(t0, sizeof ( double ), 1 ,fp); fread(cpu0, sizeof ( double ), 1 ,fp); printf( "Resolution:%d,%d\n" ,nx,ny); printf( "CFL:%f\n" ,cfl); printf( "Gamma:%f\n" ,gamma); printf( "CPU:%f\n" ,cpu0); printf( "Current Time:%f\n" ,t0); fread(ntemp, sizeof ( int ), 1 ,fp); printf( "read %d bytes\n" ,ntemp); fread(ntemp, sizeof ( int ), 1 ,fp); printf( "write %d=%dx%dx(4*8) bytes\n" ,ntemp,nx,ny); double *data= new double ; if (data) { for ( int m= 0 ;m 4 ;m++){ fread(data, sizeof ( double ),nx*ny,fp); double tmin,tmax; int nmax,nmin; tmin= 0.0 ,tmax= 0.0 ; nmin=- 1 ,nmax=- 1 ; for ( int j= 0 ;jnx*ny;j++) { if (data tmax) { tmax=data ; nmax=j; } if (data tmin) { tmin=data ; nmin=j; } } printf( "***Min:%f at %d \n" ,tmin,nmin); printf( "***Max:%f at %d \n" ,tmax,nmax); } } fclose(fp); fread(ntemp, sizeof ( int ), 1 ,fp); printf( "read %d=%dx%dx(4*8) bytes\n" ,ntemp,nx,ny); return 0 ; } http://www.ibm.com/developerworks/aix/library/au-endianc/index.html?ca=drs - Writing endian-independent code in C
粘帖过来的部分很乱,直接打开转载网址。 转载自:http://www.cae.tntech.edu/help/programming/mixed_languages Mixing Code in C, C++, and FORTRAN on Unix It is becoming increasingly common for engineers to write different parts of a final program in different languages. For example, you might use legacy FORTRAN code for calculations, C++ code for writing a graphical interface to the program, and C for other system functions. This page is intended to show simple examples of how to write programs and functions that can be accessed from other languages. Major points to keep in mind when mixing languages include: Call By Value / Call By Reference C and C++ default to passing arguments by value; FORTRAN defaults to passing arguments by reference. In other words, the normal way that FORTRAN subroutines or functions are called allows them to modify their argument variables inside the subroutine code, while C and C++ do not. C and C++ subroutines use a slightly different syntax to allow for modification of arguments, and this syntax is consistently used in the following examples. Splitting Code Into Multiple Files Normally, as your program code grows larger, you'll want to separate it into several files, one per function or subroutine. Then each source code file is compiled into an object file (a .o file in Unix, or a .obj file in Windows), and the various object files are linked together into a final single executable. The advantages of splitting your code up this way include: Being able to use different languages for different portions of the program Being able to delegate the writing of different functions to different people More efficient compilation, since a change to one source file only requires its object file to be recompiled and the object files to be relinked, rather than recompiling the entire body of code from scratch. Once you exceed the two or three source code files we use in the following examples, you'll almost definitely want to investigate using the make utility to automate the build process on your program. Internal Function Names When the compiler turns source code into object files, it might change the internal name of the function, for example, by appending or prepending underscores. In Unix, you can use the nm command to list those internal names: mwr@ch208m:~$ nm cppfunction.o cppfunction.o: Value Size Type Bind Other Shndx Name | 0| 0|SECT |LOCL |0 |4 | | 0| 0|SECT |LOCL |0 |2 | | 0| 0|SECT |LOCL |0 |3 | | 0| 0|NOTY |LOCL |0 |4 |__FRAME_BEGIN__ | 0| 76|FUNC |GLOB |0 |2 |cppfunction | 0| 0|FILE |LOCL |0 |ABS |cppfunction.C | 0| 0|NOTY |LOCL |0 |2 |gcc2_compiled. mwr@ch208m:~$ nm ffunction.o ffunction.o: Value Size Type Bind Other Shndx Name | 0| 0|SECT |LOCL |0 |2 | | 0| 0|SECT |LOCL |0 |3 | | 0| 0|FILE |LOCL |0 |ABS |ffunction.f | 0| 68|FUNC |GLOB |0 |2 |ffunction_ | 0| 0|NOTY |LOCL |0 |2 |gcc2_compiled. mwr@ch208m:~$ Note that the FORTRAN compiler appended a single underscore to the function name, while the C++ compiler left the name intact. Example 1: Main Program in C, with Subroutines in C, C++, and FORTRAN The C program is nothing out of the ordinary: it defines two variables, and calls various functions that change those variables' values. C requires that we use a "call by reference" syntax to make these changes persistent, rather than its default "call by value" method. Note that the name of the FORTRAN function called from the C program is ffunction_, a name we extracted via the nm command shown above. Note also that the C++ function has an extern "C" directive above the code of the function, indicating not that cppfunction() is written in C, but that it is called from a C-style interface instead of a C++ interface. File cprogram.c: #include stdio.h int main(void) { float a=1.0, b=2.0; printf("Before running Fortran function:\n"); printf("a=%f\n",a); printf("b=%f\n",b); ffunction_(a,b); printf("After running Fortran function:\n"); printf("a=%f\n",a); printf("b=%f\n",b); printf("Before running C++ function:\n"); printf("a=%f\n",a); printf("b=%f\n",b); cppfunction(a,b); printf("After running C++ function:\n"); printf("a=%f\n",a); printf("b=%f\n",b); printf("Before running C function:\n"); printf("a=%f\n",a); printf("b=%f\n",b); cfunction(a,b); printf("After running C function:\n"); printf("a=%f\n",a); printf("b=%f\n",b); return 0; } File ffunction.f: subroutine ffunction(a,b) a=3.0 b=4.0 end File cppfunction.C: extern "C" { void cppfunction(float *a, float *b); } void cppfunction(float *a, float *b) { *a=5.0; *b=6.0; } File cfunction1.c: void cfunction(float *a, float *b) { *a=7.0; *b=8.0; } Compilation Steps: each program is compiled into an object file using the appropriate compiler with the -c flag. After all the object files are created, the final gcc command links the object files together into a single executable: mwr@ch208m:~$ gcc -c cprogram.c mwr@ch208m:~$ g77 -c ffunction.f mwr@ch208m:~$ g++ -c cppfunction.C mwr@ch208m:~$ gcc -c cfunction1.c mwr@ch208m:~$ gcc -o cprogram cprogram.o ffunction.o cppfunction.o cfunction1.o mwr@ch208m:~$ Though this example problem does not require it, many of the math functions (for example, sin, cos, pow, etc.) require that you also link in the libm math library. Add a -lm flag to the final gcc command above to link in the math library. Results: mwr@ch208m:~$ ./cprogram Before running Fortran function: a=1.000000 b=2.000000 After running Fortran function: a=3.000000 b=4.000000 Before running C++ function: a=3.000000 b=4.000000 After running C++ function: a=5.000000 b=6.000000 Before running C function: a=5.000000 b=6.000000 After running C function: a=7.000000 b=8.000000 mwr@ch208m:~$ Example 2: Main Program in C++, with Subroutines in C, C++, and FORTRAN The only differences between the C++ code in a normal program is that we have to account for the C and FORTRAN subroutines expecting to be called with a C-style interface, and also that the FORTRAN compiler will append an underscore to the FORTRAN function name. Also, since the C++ function is held in a separate file from the C++ main program, we need to declare a function prototype before the main program code. File cppprogram.C: #include iostream.h extern "C" { void ffunction_(float *a, float *b); } extern "C" { void cfunction(float *a, float *b); } void cppfunction(float *a, float *b); int main() { float a=1.0, b=2.0; cout "Before running Fortran function:" endl; cout "a=" a endl; cout "b=" b endl; ffunction_(a,b); cout "After running Fortran function:" endl; cout "a=" a endl; cout "b=" b endl; cout "Before running C function:" endl; cout "a=" a endl; cout "b=" b endl; cfunction(a,b); cout "After running C function:" endl; cout "a=" a endl; cout "b=" b endl; cout "Before running C++ function:" endl; cout "a=" a endl; cout "b=" b endl; cppfunction(a,b); cout "After running C++ function:" endl; cout "a=" a endl; cout "b=" b endl; return 0; } File cfunction1.c: void cfunction(float *a, float *b) { *a=7.0; *b=8.0; } File ffunction.f: subroutine ffunction(a,b) a=3.0 b=4.0 end Compilation Steps: mwr@ch208m:~$ g++ -c cppprogram.C mwr@ch208m:~$ gcc -c cfunction1.c mwr@ch208m:~$ g++ -c cppfunction1.C mwr@ch208m:~$ g77 -c ffunction.f mwr@ch208m:~$ g++ -o cppprogram cppprogram.o cfunction1.o cppfunction1.o ffunction.o mwr@ch208m:~$ Results: mwr@ch208m:~$ ./cppprogram Before running Fortran function: a=1 b=2 After running Fortran function: a=3 b=4 Before running C function: a=3 b=4 After running C function: a=7 b=8 Before running C++ function: a=7 b=8 After running C++ function: a=5 b=6 mwr@ch208m:~$ Example 3: Main Program in FORTRAN, with Subroutines in C, C++, and Fortran Though the non-FORTRAN subroutines don't have any underscores after their names in the main FORTRAN program, running the nm command on fprogram.o shows that the FORTRAN program expects that they'll have underscores appended to the function name internally. Therefore, in both the C and C++ files, we need to write the function prototype statement accordingly, with an underscore after the function name. We also must use the extern "C" directive in the C++ file, indicating that the C++ function is called with a C-style interface, similar to the first example. File fprogram.f: program fprogram real a,b a=1.0 b=2.0 print*,'Before Fortran function is called:' print*,'a=',a print*,'b=',b call ffunction(a,b) print*,'After Fortran function is called:' print*,'a=',a print*,'b=',b print*,'Before C function is called:' print*,'a=',a print*,'b=',b call cfunction(a,b) print*,'After C function is called:' print*,'a=',a print*,'b=',b print*,'Before C++ function is called:' print*,'a=',a print*,'b=',b call cppfunction(a,b) print*,'After C++ function is called:' print*,'a=',a print*,'b=',b stop end File ffunction.f: subroutine ffunction(a,b) a=3.0 b=4.0 end File cppfunction2.C: extern "C" { void cppfunction_(float *a, float *b); } void cppfunction_(float *a, float *b) { *a=5.0; *b=6.0; } File cfunction2.c: void cfunction_(float *a, float *b) { *a=7.0; *b=8.0; } Compilation Steps: mwr@ch208m:~$ g77 -c fprogram.f mwr@ch208m:~$ g77 -c ffunction.f mwr@ch208m:~$ g++ -c cppfunction2.C mwr@ch208m:~$ gcc -c cfunction2.c mwr@ch208m:~$ g77 -lc -o fprogram fprogram.o ffunction.o cppfunction2.o cfunction2.o mwr@ch208m:~$ Results: mwr@ch208m:~$ ./fprogram Before Fortran function is called: a= 1. b= 2. After Fortran function is called: a= 3. b= 4. Before C function is called: a= 3. b= 4. After C function is called: a= 7. b= 8. Before C++ function is called: a= 7. b= 8. After C++ function is called: a= 5. b= 6. mwr@ch208m:~$
We love advanced computer language because it is easy to learn and easy to use. However, valuable heritage of basic language is still our treasures. It’s easy to quote “code” of basic language, such as FORTRAN, in advanced language. But the path of calling advanced “code” in basic language is tourist. In this article, the path of calling managed C# dll in FORTRAN is addressed. Routing C# cannot generate traditional dll, which is unmanageable and face to progress. So managed dll exported in C# cannot be used in FORTRAN directly. A wrapper is required. C++ can be used as this media. The managed dll from C# can be wrapped by C++. Further a unmanaged dll can be generated and called in Fortran. Basic knowledge Tip1: Export dll using c++ Step 1: Open VS2008: New, VC++, Win32 Project; then named the file as “Trans”. Then click next and choose application type as dll. Step 2: implement the following code in trans.cpp file: //____________________________________________________ #include "stdafx.h" extern "C" { __declspec(dllexport) void TRANS(int a, int b, int* c) ; } void TRANS(int a, int b, int* c) { *c = a+b; } //____________________________________________________ OK! You can find the trans.dll and trans.lib file in debug directory. Tip2: Calling dll in Fortran Step 1: Create a new “simple”, Fortran console application, Project. Compile it. Step 2: Copy trans.dll and trans.lib to the directory where the Fortran application lives. Step 3: Click Projects, Settings, Link. Then you can locate the box of “Object/Library modules”. Enter “trans.lib” in that box. “Space “ is using as the indicator between different libs. Step 4: The following code can be used to quote the function in dll files, as: !_______________________________________________________________ program Call implicit none ! Variables INTERFACE subroutine TRANS(a, b, c) !dec$ attributes c, dllimport, alias:'_TRANS' :: TRANS integer*4 a integer*4 b integer*4 c END subroutine END INTERFACE ! Body of Call integer Iget, Ia, Ib call trans(1, 2, Iget) write(*, *) Iget Read (*, *) Ia Read (*, *) Ib call trans(1, 2, Iget) write(*, *) Iget Read (*, *) Ia end program Call !_______________________________________________________________ OK! You can found the dll is work. Tip3: Debug c++ dll using Fortran exe Step 1: There are two ways to link the dll and exe. First, you can change the directory of dll generated in C++ from the debug directory of C++ project To the directory of Fortran project. Which follows: Projects, properties, output directory. Alternatively, You can copy the fortran exe to the debug directory to C++ project. Otherwise, the dll and the exe file are not linked together. Step2: click debugging, select the call.exe . Done! Tip 4: Generate dll utilizing C# Step 1: Open VS2008, Click “Other languages, Visual C#, Windows, Class library” To Create a new lib project. Named the project as Csharpdll Step 2: Typing the followed code in the calss1.cs //___________________________________________________________ namespace Csharpdll { public class Class1 { public static void Multiply(double a, double b, double c) { c = a*b; } } } //___________________________________________________________ Step 3: build the project. OK! You can find the dll in the project directory/Csharpdll/obj/. Copy csharpdll.dll to any place you want to use it. Tip 5: Calling C# dll in C++ Step 1: Open VS2008, Create a new, VC++, Win32, Console application. Name it as “trycall”. Step 2: Click Project, Properties, Configuration properties, General, Common language Runtime Support. Switch the value to Common language Runtime Support/Clr. Step 3: copy csharpdll.dll to the directories of this project, i.e. both the directory of debug and the directory saving cpp file. Step 4: Click Trycall.cpp in the source files and input the followed code: //_______________________________________________________ // Trycall.cpp : Defines the entry point for the console application. #include "stdafx.h" #include iostream using namespace std; #using "Csharpdll.dll" using namespace Csharpdll; int _tmain(int argc, _TCHAR* argv char* System::String string Integer*4 dimension D(*) int* int* //***********************Example**************************// 1st part in C#: //_______________________________________________________ // C#, Class1.cs namespace Csharpdll { public class Class1 { public static unsafe void Multiply(int* array, string msg) { array = array * array ; msg = msg.ToLower(); } } } //_______________________________________________________ 2nd part in the head file of C++: //_______________________________________________________ // C++, stdafx.h #include string using namespace std; using namespace System; std::string ConvertTostring(System::String^ str); //_______________________________________________________ 3rd part in the cpp file of C++: //_______________________________________________________ // C++, Trycall.cpp #include "stdafx.h" #include iostream using namespace std; #using "Csharpdll.dll" using namespace Csharpdll; #include string using namespace System; int _tmain(int argc, _TCHAR* argv ={9,9,9}; int *a; a = b; std::string str1 = "STRING IS TROUBLE!! HAHA"; cout str1 "\n"; //Convert the string String^ str2 = gcnew String(str1.c_str()); str1 = ConvertTostring(str2); cout str1 "\n"; Csharpdll ::Class1:: Multiply( a, str2); //attention: str2 is const, it’s value can be transfer into c# by dll. //but str2 will not be updated after the transfer. str1 = ConvertTostring(str2); cout str1 "\n"; cout b "\n"; cin b ; return 0; } std::string ConvertTostring(System::String^ str) { int q=(int)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str); char* p=(char*)q; return std::string(p); } //***********************Example**************************// Step by step: calling c# dll from FORTRAN Step 1: Create a class library project using C#. Set unsafe build mode! The main class contains: //___________________________________________________ namespace Remesh { public class Cremesh { public static unsafe void remesh(double* Coordinate, string key, double* variable) { } } } //___________________________________________________ Step 2: Create a win32 dll project using VC++. Copy Remesh.dll to the right directory. Set option: Common language Runtime Support/Clr. The WRAP.h head file contains: //___________________________________________________ #include string using namespace std; using namespace System; std::string ConvertTostring(System::String^ str); extern "C" { __declspec(dllexport) void REMESH(double* coor, char* key, double* variable, char* filename); } //___________________________________________________ The WRAP.cpp file contains: //___________________________________________________ #include "stdafx.h" #include "wrap.h" #include string using namespace std; using namespace System; #using "Remesh.dll" using namespace Remesh; std::string ConvertTostring(System::String^ str) { int q=(int)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str); char* p=(char*)q; return std::string(p); } void REMESH(double* coor, char* key, double* variable, char* filename) { std::string str; str = key; String^ Strkey = gcnew String(str.c_str()); str = filename; String^ Strfilename = gcnew String(str.c_str()); Remesh::Cremesh::remesh(coor, Strkey, variable, Strfilename); } //___________________________________________________ Step 3: Create a fortran project; copy wrap.dll and wrap.lib to the right diretory; add wrap.lib to the project link properties. The *.f90 contains !_____________________________________________________ program Call implicit none ! Variables INTERFACE subroutine REMESH(coor, key, variable, filename) !dec$ attributes c, dllimport, alias:'_REMESH' :: REMESH double precision coor character*(*) key double precision variable character*(*) filename END subroutine END INTERFACE double precision coor, variable character*100 filename character*10 key dimension coor(1000, 2), variable(10, 2), key(10) ! Body of Call call remesh(coor(1, 1), key(1), variable(1, 1), filename) end program Call !_____________________________________________________ Ok! Everything is done.
Writing Matlab MEX files using Fortran 90 / 95 (and the Intel Fortran Compiler) (Update: This text refers primarily to Matlab 6.5 (aka R13) on Linux. The new Matlab 7 introduces some serious problems with non-GNU compilers due to throwing C++ exceptions. Read on below for details.) The Mathworks do not officially support Fortran 90 / 95, but thanks to people like Benjamin Barrowes who wrote Matlab2FMex and the people at NAGWare it is easy to figure out how to write your MEX files in Fortran 95 without using the awkward mxCopy-functions. Lately, I also found this page which describes in detail all three possible ways of writing MEX files entirely in Fortran. However, of these three ways, two make a local copy of the data which is less than optimal when dealing with big data sets. The trick is to declare the pointer you get from mxGetPr as an integer pointer and pass it along with the array dimensions to a subroutine which expects a double precision array. Until now this works for me without any problems (Linux w/ Intel Compiler), but note that this procedure may not work with every compiler or on any platform. I may also add that this procedure does NOT work with the F programming language as it forbids passing "wrong" arguments to subroutines. First, we will have to explicitly define the used Matlab API functions, at least those who have a return value: module mexf90 interface function mxGetPr(pm) integer,pointer :: mxGetPr integer :: pm end function mxGetPr function mxGetM(pm) integer :: mxGetM,pm end function mxGetM function mxGetN(pm) integer :: mxGetN,pm end function mxGetN function mxCreateDoubleMatrix(m,n,type) integer :: m,n,type,mxCreateDoubleMatrix end function mxCreateDoubleMatrix function mxGetScalar(pm) integer :: pm double precision :: mxGetScalar end function mxGetScalar end interface end module mexf90 Just save this file under the name "mexf90.f90" and compile it. (For those unfamiliar with modules: you must prevent the compiler from also linking the file - this is usually done with the "-c" switch.) This module contains only the API functions we need, but adding further functions is straightforward. You may also click here to obtain a module file with more function definitions. Now the actual function, consisting of the subroutine "mexFunction" (the gateway to Matlab) and an example subroutine "scalarMult" which multiplies the matrix A with a scalar "alpha" and returns the result in matrix B. The comments should make clear how these functions work: subroutine mexFunction(nlhs, plhs, nrhs, prhs) use mexf90 ! API function definitions implicit none integer, intent(in) :: nlhs, nrhs integer, intent(in), dimension(*) :: prhs integer, intent(out), dimension(*) :: plhs integer :: m,n integer, pointer :: A,B ! These are the pointers to the matrix data double precision :: alpha ! Check input arguments if(nrhs /= 2) then call mexErrMsgTxt('Function requires two input arguments.'); end if ! Get data and size of the input matrix A = mxGetPr(prhs(1)) m = mxGetM(prhs(1)) n = mxGetN(prhs(1)) ! Get scalar value alpha = mxGetScalar(prhs(2)) ! Create output matrix plhs(1) = mxCreateDoubleMatrix(m,n,0) B = mxGetPr(plhs(1)) ! Call subroutine for multiplication call scalarMult(A,B,alpha,m,n) end subroutine mexFunction subroutine scalarMult(A,B,alpha,m,n) implicit none integer :: m,n double precision :: alpha ! Now define the matrices with the actual data type and dimension double precision, dimension(m,n) :: A,B ! Now do something useful... B = alpha * A end subroutine scalarMult For more complex functions it is a bit tedious to pass the dimensions along with the data pointers - if someone finds a better solution, please let me know! The Intel Fortran Compiler for Linux is free for non-commercial use, but you probably already know that... These are the relevant parts in the mexopts.sh file for MEXing the above file with the IFC FC='ifort' FFLAGS='-fPIC -u -w95 -warn all' FLIBS='$RPATH $MLIBS -L/opt/intel_fc_80/lib -lm' FOPTIMFLAGS='-O3' FDEBUGFLAGS='-g' LD='icc' LDFLAGS='-pthread -shared' LDOPTIMFLAGS='$FOPTIMFLAGS' LDDEBUGFLAGS='-g' As you can see, I do not use any map-files as that didn't work for me. It is important to note that linking with "ifort" will usually NOT work, the above file uses the Intel C++ Compiler "icc" instead. If you do not have icc installed, the GNU compiler "g++" should also work. If you also want to use functions like "print", e.g. for debugging purposes (mexprintf does not allow format strings in Fortran...), you will also have to link "ifcore", but you should remove that for the release version of your code. If you get error messages about unresolved symbols when executing the mex-file, make sure that the Intel libraries are scanned by ldconfig or put them into your LD_LIBRARY_PATH before starting Matlab. If you get an error message saying that __MAIN couldn't be found, check again that you are NOT linking with ifort. If you still have problems with unresolved symbols, try using the "-static-libcxa" switch. Now happy MEXing! Oh, and also check out LAPACK95, incredibly useful for porting M-files to MEX. And Matran looks very promising, although I didn't use it yet. Update: Problems with Matlab 7 (aka R14) The new Matlab 7 now uses C++ exceptions in library functions like mexErrMsgTxt. As Matlab was built on Linux with the GNU compiler, this breaks practically all other compilers which are unable to correctly propagate these exceptions - including the Intel Fortran Compiler (and also Ocaml, by the way...). (A sidemark: the Intel C Compiler (icc) will usually work as long as you always compile with "-Kc++"). This means, as soon as a Fortran MEX file compiled with the Intel Fortran Compiler calls mexErrMsgTxt, the complete Matlab session will abort and return to the shell, as there is no handler to catch the exception. I doubt that there exists an easy solution to this problem, as the implementation of exception handling in C++ differs between different compilers. Thus, if you want to write your files entirely in Fortran 95 and you want to use the IFC, don't call mexErrMsgTxt or your session will abort. If you have to use mexErrMsgTxt, you are for now forced to use a GNU Fortran compiler. Although Fortran and C don't "know" exception handling, the GNU C and Fortran compilers have a switch "-fexceptions" which includes code to correctly propagate these exceptions. For Fortran 95 you can use either g95 or GNU Fortran 95, both work for creating Matlab MEX files as long as you compile with "-fexceptions". However, both compilers are not yet stable, but they are making rapid progress recently.
最近,好几个人问到公共块出错的问题,都是出于一个原因,特在这里把老贴整理一下供大家参考。 问题: 20924057 Compiling Fortran... D:\FRAME2D.FOR D:\FRAME2D.FOR(314) : Warning: Because of COMMON, the alignment of object is inconsistent with its type COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6)--------------------------^ D:\FRAME2D.FOR(314) : Warning: Because of COMMON, the alignment of object is inconsistent with its type COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6) ---------------------------^ 解答: 这是老Fortran的规则。看你的公共语句: COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6),SF(6),T(3,3) 根据程序的隐含规则,LM(6),ND一共是7个整型数,每个整型数4个字节,共28个字节,不是8字节的整倍数。紧跟着是双精度的ASA(6,6),每个数是8个字节,可是ASA(1,1)不能从8字节整倍数位置开始存储,这就是the alignment of object is inconsistent with its type 的意思。 对于警告错误,可以忽略,一般不致于影响执行结果。如果要改的话,有几种办法: 1)在公共语句中,把双精度数放在前边,整形数跟在后边; 2)在ASA()前插一个整型变量(哪怕是没用的),用来占用4个字节,以使得后面的双精度数可以从8字节整数倍位置开始存储。 准则:作为好的编程习惯,建议在公共块中,把实型变量排在前边,把整型数据放在后边,就不会有对位不整的错误! 仅供参考。 补充:(05.06.01) 公共块不是用堆栈实现的,是内存中的一段连续存储的数据。 按照Fortran的规定,当读取双精度数据时,总是假定前面的数据长度是双精度数字节长度(8个字节)的整数倍。 对于本例,ASA(1,1)从第29个字节开始存放8个字节;可是读取的时候,要从第33个字节(28不是8的倍数,32是28之后最小的8的倍数)开始读入8个字节,这就是定位(alignment)错误。 所以F90之后不提倡用公共块共享数据,而可用更为灵活的module来代替公共块共享数据。 公共块是过时的语言功能
转自:编程爱好者论坛 Fortran区的一篇置顶文章 最近,好几个人问到公共块出错的问题,都是出于一个原因,特在这里把老贴整理一下供大家参考。 问题: 20924057 Compiling Fortran... D:\FRAME2D.FOR D:\FRAME2D.FOR(314) : Warning: Because of COMMON, the alignment of object is inconsistent with its type COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6) --------------------------^ D:\FRAME2D.FOR(314) : Warning: Because of COMMON, the alignment of object is inconsistent with its type COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6) ---------------------------^ 解答: 这是老Fortran的规则。看你的公共语句: COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6),SF(6),T(3,3) 根据程序的隐含规则,LM(6),ND一共是7个整型数,每个整型数4个字节,共28个字节,不是8字节的整倍数。紧跟着是双精度的ASA(6,6),每个数是8个字节,可是ASA(1,1)不能从8字节整倍数位置开始存储,这就是the alignment of object is inconsistent with its type 的意思。 对于警告错误,可以忽略,一般不致于影响执行结果。如果要改的话,有几种办法: 1)在公共语句中,把双精度数放在前边,整形数跟在后边; 2)在ASA()前插一个整型变量(哪怕是没用的),用来占用4个字节,以使得后面的双精度数可以从8字节整数倍位置开始存储。 准则:作为好的编程习惯,建议在公共块中,把实型变量排在前边,把整型数据放在后边,就不会有对位不整的错误! 仅供参考。 补充:(05.06.01) 公共块不是用堆栈实现的,是内存中的一段连续存储的数据。 按照Fortran的规定,当读取双精度数据时,总是假定前面的数据长度是双精度数字节长度(8个字节)的整数倍。 对于本例,ASA(1,1)从第29个字节开始存放8个字节;可是读取的时候,要从第33个字节(28不是8的倍数,32是28之后最小的8的倍数)开始读入8个字节,这就是定位(alignment)错误。 所以F90之后不提倡用公共块共享数据,而可用更为灵活的module来代替公共块共享数据。 公共块是过时的语言功能
如何在fortran中读写文件时不换行(上传供大家学习) 转自ifelseif的博客 如何在fortran中读写文件时不换行?这是个极简单又极复杂的问题,简单到只要一个字符,复杂到翻破了好几本语法书也没找见。fortran中默认一条read或者write结束之后就换一行,但是读和写还有些不太一样。 读文件时,read之后如果写了一个数组,就像这样: read(10,*)Y(1:n) 整整一行数就全都读到数组里了。但是如果用write,写到文件中却不是这个样子,会给你一个超级长的文件然后每行只有一个数。有一个选项叫ADVANCE='YES'/'NO',可以控制输入输出语句完了之后要不要换行,默认是'YES',很不幸,在intel的fortran中这个选项只对read起作用,write依旧不行。 在fortran的输入输出中,/表示换行,那么\表示什么意思呢,就是不换行。这是我在网上逛了老半天才看到的,为了防止忘记,写到博客里面,立此存照。 下面是一段fortran代码样例,要处理的数据20个数就会换一行,一般来讲最后一行是不满20个数的,需要用个同余判断一下 PROGRAM MAIN IMPLICIT NONE INTEGER I,J,NY,A,B REAL X,Y(60),Z(60) OPEN(UNIT=10,FILE='SX-RIVER.TXT') OPEN(UNIT=11,FILE='SX-OUTPUT.TXT') DO I=1,9 READ(10,*) END DO DO I=1,372 !!!!!!!!! DATA INPUT !!!!!!!!!!!!!!!! READ(10,(18X,I2,1X,F7.3))NY,X CALL MOD(20,NY,A,B) DO J=1,A READ(10,(20(1X,F7.2)))Y(20*(J-1)+1:20*J) END DO DO J=1,B READ(10,(1X,F7.2),ADVANCE='NO')Y(20*A+J) END DO READ(10,*) DO J=1,A READ(10,(20(1X,F7.2)))Z(20*(J-1)+1:20*J) END DO DO J=1,B READ(10,(1X,F7.2),ADVANCE='NO')Z(20*A+J) END DO READ(10,*) !!!!!!!!! DATA OUTPUT !!!!!!!!!!!!!!! !WRITE(11,(I4,1X,F7.3))NY,X WRITE(11,(1X,F7.2,\))Y(1:NY) WRITE(11,*) WRITE(11,(1X,F7.2,\))Z(1:NY) WRITE(11,*) END DO CLOSE(10) CLOSE(11) STOP END PROGRAM MAIN !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! SUBROUTINE FOR CONGRUENCE(TONGYU) ! ! Y=A*X+B ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SUBROUTINE MOD(X,Y,A,B) IMPLICIT NONE INTEGER X,Y,A,B,TMP A=1 TMP=X DO WHILE(Y.GT.TMP) A=A+1 TMP=TMP+X END DO A=A-1 B=X-(TMP-Y) RETURN END SUBROUTINE MOD
有一个问题困扰我许多年了:同样是Fortran语言用Unformatted格式生成的数据文件,在32位和64位机器上大小不同。关于这一问题,在 这里 描述道: Update (Jan 2008): It would appear that on 64 bit machines the 2 header elements are each written as 4 bytes instead of 2 bytes each. 但也没有给出解决方案。 终于我想到一个另类做法,可以通用地读取这样的文件。 假设原来的文件是这样生成的: real*8 u_tmp(k1:kmax,k1:kmax,0:n/16-1) open(10,file=filename,form='unformatted') write(10)(((u_tmp(i,j,k),i=k1,k2),j=k1,k2),k=0,n/16-1) close(10) 如果原来文件是在64位机上生成的,那么不需要做特殊处理。否则,假设生成的文件是u.dat,则另外新建一个4字节的文件,比如叫tmp。执行 cat z u.dat u_new.dat 将4个字节插到u.dat的文件头,使得新文件的偏移量和原文件相同。 接着,用下面的程序读取 open(10,file=dat(ifn),access='direct', recl=8) do k = 0, n/16-1 do j = k1, k2 do i = k1, k2 read(10, rec = k*n*n+(j-k1)*n+i-k1+2) u_tmp(i,j,k) enddo enddo enddo 这仅仅是针对real*8的读法,但其他格式的做法也类似
我今天弄到了一本书,名字是:Sample page from NUMERICAL RECIPES IN FORTRAN 77 THE ART OF SCIENTIFIC COMPUTING 1100多页啊,刚才看了一下。这本书太牛了,几乎面面俱到。谁要是把这本书一个一个地练习一遍,我觉得吧:不但是fortran编程对他小菜一碟,就是有限元以后也不是什么难的东西了。有点夸张啊,太高兴了,原谅原谅! 呵呵,找了一个晚上,最后是有点巧取豪夺弄过来的。谁要的话,可以说一声。大约7M,最好是留QQ邮箱吧! 下面给出本书的目录吧: 目录 分卷压缩: part1 分卷压缩: part2 我压缩的时候没注意,这里下载之后注意要把扩展名.zip改为.rar