第一篇:关于Fortran调用C++函数的小结
关于Fortran调用C++函数的小结
2017-3-12 背景
工作中遇到了需要在Fortran代码中调用C++提供的函数的情况。通过在网上查阅资料,总结了实现方法,制作了一个实例。
工具
集成开发环境是VS2010。由于默认安装模式下的VS2010是无法编译调试Fortran的,所以又补充安装了Intel(R)Virual Fortran 2011(英特尔可视化Fortran编译器)。
参考资料分析
本文需要用到Fortran与C/C++的混合编程,Fortran和C/C++分别编译各自的功能模块源代码,得到各自的目标文件(.obj),然后集成链接这些obj 文件生成一个统一的可执行文件,实现对对方函数的调用,数据交换通过约定接口来实现[1]。C++代码中函数说明前需要用到extern关键字,说明函数可以在本模块或其它模块中使用[2]。extern与“C”一起连用时,如: extern “C” void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非[3]。
要在Fortran中调用C++的函数,意味着Fortran项目对C++项目产生了依赖关系,如果项目依赖项未设置会导致类似“无法解析的外部符号 _XXX,该符号在函数 _XX 中被引用”的错误。另外还要保证Fortran与C++项目的运行库设置都是“多线程调试”[4]。
实现过程 创建Fortran项目
1)启动VS2010,新建一个Fortran控制台应用程序,名称为Console1。2)在该项目下的Source Files下添加一个新文件Source1.f90。3)在Source1.f90中写入如下代码:
program main implicit none interface
subroutine SUB(a,b)!DEC$ ATTRIBUTES C,ALIAS:'_sub'::SUB!DEC$ ATTRIBUTES reference::a,b integer a , b end subroutine SUB end interface integer(4)a,b,c a=100 b=1 write(*,*)“开始调用C++里的函数SUB” call SUB(a,b)read(*,*)endprogram main
注:接口中为_sub这个来自于C++的函数起了个别名SUB,所以在后面调用SUB时其实就是调用_sub。在接口中还规定了a和b两个参数的传递方式是传引用。
创建C++项目
在解决方案资源管理器中的“解决方案”处右键,添加一个新建项目,在新建窗口中选中Win32控制台应用程序,输入项目名称Cpp2。在随后弹出的应用程序设置中选择应用程序类型为静态库。
在项目的头文件中新建一个sub.h,在其中输入如下代码:
//sub.h #ifndef _SUB_H #define _SUB_H extern“C”void_cdecl sub(int *a,int *b);
[5]#endif 注:在头文件中使用#ifdef和#ifndef是非常重要的,可以防止双重定义的错误。
在项目的源文件中新建一个sub.cpp,在其中输入如下代码:
//sub.cpp
#include“stdafx.h” #include“sub.h” #include
extern“C”void_cdecl sub(int *a,int *b){ std::cout<<“C++: 已经进入C++的函数内部n”<<“a=”<<*a<<“, b=”<<*b< 设置Fortran项目的项目依赖项 在Console1项目上右键,选择项目依赖项,在弹出窗口中依赖项页内选中Cpp2,切换到生成顺序页,可以看到Cpp2排在Console1前面。 设置运行库 1)设置Fortran项目的运行库,在Console1项目上右键选择属性,然后找到【配置属性】【Fortran】【Libraries】【Runtime Library】,设置其值为Debug Multithreaded(/libs:static/threads/dbglibs)即多线程调试。 2)设置C++项目的运行库,在Cpp2项目上右键选择属性,找到【配置属性】【C/C++】【代码生成】【运行库】,设置其值为多线程调试(/MTd)。 生成项目 1)在解决方案上右键选择重新生成解决方案。 2)在解决方案所在的Console1文件夹下找到Debug文件夹,可以看到其中有一个Cpp2.lib文件,这个静态库文件就是Cpp2项目生成的。 3)在Console1Console1Debug文件夹下可以看到Console1.exe文件,这个可执行文件是Console1项目生成的。 注:如果要单独生成Cpp2,可以在Cpp2项目上右键选择重新生成。如果在Console1项目上右键选择重新生成,因为前文设置了项目依赖项的关系,Cpp2也会被生成。 启动调试 按下F5,启动调试。可以看到调试成功。 参考文献 [1] suiyi1234546,第11章 Fortran和C的混合语言编程-授课版,百度文库,http://wenku.baidu.com/link?url=ogwgYldzkmbgJXM86iXjAMt60wimIN1bMVy6uoz1dFn0pWuPPj1mKapYZ9RAK1rXrMZCmQAmJYjGCA0B1IpvDh9wb1joBcFdJ3VO2fz19jO [2] ForFreeDom,关于C++的extern关键字,博客园,[3] chao_yu,C/C++中extern关键字详解,博客园,http:// [5] Arthursky,C++在头文件中使用#ifdef和#ifndef,ChinaUnix,http://blog.chinaunix.net/uid-11572501-id-2868707.html 1.单双精度 Program ex01 implicit none real(kind=4):: a real(kind=8):: b a=3.***66666666_4 !确定这个数字是使用单精度 b=3.***66666666_8 !确定这个数字是使用双精度 write(*,*)a,b End program ex01 2.判断kind值 program ex02 Implicit none !判断可以记录9个位数的整数kind值 integer, parameter :: long_int = selected_int_kind(9)!判断可以记录3个位数的整数kind值 integer, parameter :: short_int = selected_int_kind(3) !判断可以有3个有效位数, 指数可以记录到3的浮点数kind值 integer, parameter :: long_real = selected_real_kind(10, 50)!判断可以有10个有效位数, 指数可以记录到50的浮点数kind值 integer, parameter :: short_real= selected_real_kind(3, 3)integer(kind=long_int):: a = 123456 integer(kind=short_int):: b = 123 real(kind=long_real) :: c = +1.23456789D45 real(kind=short_real) :: d =+1230 write(*, “(I3,1X,I10)”) long_int,a write(*, “(I3,1X,I10)”) short_int, b write(*, “(I3,1X,E10.5)”)long_real, c write(*, “(I3,1X,E10.5)”)short_real, d END 3.TYPE program ex0434 implicit none Type :: person !开始建立person这个类型 character(len=30):: name!人名 integer :: age !年龄 integer :: height !身高 INTEGER :: weight !体重 character(len=80):: address!地址 End type person type(person):: a !声明一个person类型的变量 write(*,*)“NAME:” read(*,*)a%name write(*,*)“AGE:” read(*,*)a%age write(*,*)“HEIGHT:” read(*,*)a%height write(*,*)“WEIGHT:” read(*,*)a%weight write(*,*)“ADDRESS:” read(*,*)a%address write(*,100)a%name,a%age,a%height,a%weight 100 format(“Name:”,A10/,“Age:”,I3/,“Height:”,I3/,“Weight:”,I3/,& “Addres:”,A80)End 4.REAL 与 INTEGER Program ex0431 implicit none integer :: a=1 integer :: b=2 real :: c c=a/b!c=1/2=0, 虽然c是浮点数,但因为a,b是整数,计算a/b时会用整数去计算.write(*,“(F5.2)”)c End 5.DATA 变量表/初值表/,变量表/初值表/,… PROGRAM ex0430 IMPLICIT NONE INTEGER A REAL B COMPLEX C CHARACTER(20)STR DATA A,B,C,STR /1, 2.0,(1.0,2.0), 'FORTRAN 77'/ WRITE(*,*)A,B,C,STR END 6.复数实虚部 Program ex0430 complex :: c =(1,2)write(*,100)real(c),'+',aimag(c),'i' 100 format(f5.1,a1,f5.1,a1)End 7.逻辑输出 Program ex0416 logical a,b a=.true.b=.false.write(*,100)a,b format(L5,L4)End 8.Program ex0415 character(len=20)string character(len=5)substring string = “Have a nice day.” substring = “nice” write(*,*)ichar('A')!输出字符A的ASCII码 write(*,*)char(65) !输出ASCII码65所代表的字符,也就是A write(*,*)len(string)!输出字符串string声明时的长度 write(*,*)len_trim(string)!输出字符串string内容的长度 write(*,*)index(string, substring)!nice在Have a nice day的第8个位置 End 9.Program ex0414 character(len= 6)first character(len=10)second character(len=20)add first=“Happy ” second=“Birthday” add = first//second!经由两个连续的除号可以连接两个字符串 write(*,100)add FORMAT('生日快乐',/,A)End 10.带精度计算 Program ex0408 real(kind=8):: a,b a=1 b=0.1 write(*,*)a,“+”,b,“=”,a+b End 11.逻辑if语句 Program ex0504 implicit none integer rain, windspeed logical r,w write(*,*)“Rain:” read(*,*)rain write(*,*)“Wind:” read(*,*)windspeed r =(rain>=500) !如果rain>=150, r=.true, 不然r=.false.w =(windspeed>=10)!如果windspeed>=10, w=.true, 不然w=.false.if(r.or.w)then !只要r或w有一个值是true就成立 write(*,*)“停止上班上课” else write(*,*)“照常上班上课” End if End 12.Select Case用法 Program ex0512 implicit none integer :: score character grade write(*,*)“Score:” read(*,*)score select case(score) case(90:100) grade='A' case(80:89) grade='B' case default grade='?' End select write(*,“('Grade:',A1)”)grade End 13.IF GOTO语句 PROGRAM ex0514 IMPLICIT NONE REAL height REAL weight WRITE(*,*)“height:” READ(*,*) height WRITE(*,*)“weight:” READ(*,*) weight IF(weight > height-100)GOTO 200 100 WRITE(*,*)“Under control.” GOTO 300 200 WRITE(*,*)“Too fat!” 300 STOP END 14.DO WHILE 循环 Program ex0604 implicit none integer, parameter :: limit=10 integer counter integer :: ans = 0 counter = 2 do while(counter <= limit) ans = ans + counter counter = counter + 2 end do write(*,*)ans END 15.CYCLE,EXIT 语句 Program ex0609 implicit none integer :: i,j loop1: do i=1,3 loop2: do j=1,3 if(i==3)exit loop1 !跳离loop1循环 if(j==2)cycle loop2 !重做loop2循环 write(*, “('(',i2,',',i2,')')”)i, j end do loop2 end do loop1 End 16.大小写字符 Program ex0612 implicit none integer i integer strlen character(len=20):: string write(*,*)“String:” read(*,*)string strlen = LEN_TRIM(string) do i = 1, strlen string(i:i)= char(ichar(string(i:i))+32) end do write(*,“('encoded:',A20)”)string End 17.循环计算 Program ex0614 implicit none real a,b,ans character :: key = 'y' !为了至少循环一次 do while(key=='y'.or.key=='Y') read(*,*)a read(*,“(A1)”)key read(*,*)b select case(key)case('+') ans = a+b case('-') ans = a-b case('*') ans = a*b case('/') ans = a/b case default write(*,“('Unknown operator ',A1)”)key stop end select write(*,“(F6.2,A1,F6.2,'=',F6.2)”)a,key,b,ans write(*,*)“(Y/y)to do again.(Other)to exit.” read(*,“(A1)”)key end do End 18.矩阵相加 pogram ex implicit none integer, parameter :: row = 2 integer, parameter :: col = 2 integer :: matrixA(row,col) integer :: matrixB(row,col) integer :: matrixC(row,col) integer r integer c write(*,*)“Matrix A” do r=1, row do c=1, col write(*,“('A(',I1,',',I1,')=')”)r,c read(*,*)matrixA(r,c)end do end do write(*,*)“Matrix B” do r=1, row do c=1, col write(*,“('B(',I1,',',I1,')=')”)r,c read(*,*)matrixB(r,c)end do end do write(*,*)“Matrix A+B=” do r=1, row do c=1, col matrixC(r,c)= matrixB(r,c)+matrixA(r,c) write(*,“('(',I1,',',I1,')=',I3)”)r,c,matrixC(r,c)end do end do end pogram ex [ write(*,“(I3,I3,/,I3,I3)”)((mc(i,j), i=1,2),j=1,2)] 19.program ex implicit none integer, parameter :: row = 2 integer, parameter :: col = 2 integer :: a(2,2)=(/ 1,2,3,4 /) !a(1,1)=1, a(2,1)=2, a(1,2)=3, a(2,2)=4 integer :: b(4)=(/ 5,6,7,8 /) integer :: c(2) write(*,*)a,2) write(*,*)a(:,1) c = a(:,1) !c(1)=a(1,1), c(2)=a(2,1) write(*,*)c!c(1), c(2) c = a(2,:) !c(1)=a(2,1), c(2)=a(2,2) write(*,*)c!c(1), c(2) write(*,*)c(2:1:-1) !c(2), c(1) c = b(1:4:2) !c(1)=b(1), c(2)=b(3) write(*,*)c !c(1), c(2)End 20.FORALL语句 Program ex Implicit none integer :: I,J integer, parameter :: size = 5 integer :: a(size,size) forall(I=1:size, J=1:size, I>J)a(I,J)=1 !上半部分 forall(I=1:size, J=1:size, I==J)a(I,J)=2!对角线 forall(I=1:size, J=1:size, I !下半部分 write(*,“(5(5I5,/))”)a End 21.Allocatable Program EX Implicit none integer :: size, error=0 integer, parameter :: one_mb=1024*1024 !1MB character, allocatable :: a(:) Do size=size+one_mb! allocate(a(size), stat=error) if(error/=0)exit write(*,“('Allocate ',I10, ' bytes')”)size write(*,“(F10.2,' MB used')”)real(size)/real(one_mb) deallocate(a) End do End 22.Function 函数 Program ex implicit none real :: a=10 real :: b=20 real :: add write(*,“(f6.2)”)add(a,b)End Function add(a,b)implicit none real :: a,b real :: add add = a*b End 23.SAVE语句 Program ex Implicit none call sub() call sub() call sub()End program Subroutine sub() Implicit none Integer :: count = 1 Save count !指定save变量永远活着,不会忘记它的内容 Write(*,*)count count = count+1 End [运行结果:1 2 3 ] 24.生成随机数 program ex implicit none interface!定义函数的接口 function random10(lbound, ubound)implicit none real :: lbound, ubound real :: random10(10) end function end interface real :: a(10) CALL RANDOM_SEED()!系统根据日期和时间随机地提供种子 a = random10(1.0, 10.0) write(*,“(10F6.2)”)a end function random10(lbound, ubound)implicit none real :: lbound, ubound real :: len real :: random10(10) real t integer i len = ubound-lbound!计算范围大小 do i=1,10 call random_number(t)!t会是0~1之间的随机数 random10(i)= lbound + len * t!把t转换成lbound~ubound间的随机数 end do End 25.MODULE语句 Module global implicit none integer a,b common a,b End module Program ex0834 use global implicit none a=1 b=2 call sub()End program Subroutine sub() use global implicit none write(*,*)a,b return End subroutine 26.写文件到text program ex0902 implicit none character(len=20):: string open(unit=10, file=“test.txt”) write(10,“(A20)”)“I LOVE YOU.”!写到文件中 rewind(10) read(10,“(A20)”)string!从文件中读出来 write(*,“(A20)”)string!写到屏幕上 end 27.随机成绩 program gendata implicit none integer students integer i real r(3) write(*,“(4A5)”)“座位”,“语文”,“数学”,“英语” call random_seed() write(*,*)“How many students?” read(*,*)students do i=1,students call random_number(r) write(*,“(6I5)”)i,int(r*50+50) end do end program C++的学习心得 注意:因为我们在实验室大多是以项目为基础来学习C++,这样可能导致我们不能形成一个知识体系,所以建议大一同学脚踏实地的从头学习C++,即使时间不充裕的大 二、大三同学在学习时也要做好笔记,以便下次遇到同样的错误能很快解决。 介于大多数人都要学C语言,所以本文就以C++与C语言的对比开始。 要区分C语言和C++的不同,首先要想明白,用砖头建造城市、用房屋建造城市与用两者共同建造城市的不同。1.想要学C++必须掌握C语言的基础运用,这要从C++的产生说起。C++其实并不是一个新的计算机语言,它只是在C语言的基础上预先编写好了很多函数。所以如果把C语言比为砖块,那么C++就是有砖块组成的一些小的建筑。所以学习C++必需先掌握C语言的基础运用。2.C语言和C++哪个难? 其实这个问题提的很不理想。试问:建起一个城市,是用砖头从头建起来简单,还是把一些已经建好,并且使我们需要的房子摆放好简单?很明显C++本身的作用是为了方便使用C语言编程。3.C语言和C++在语法上有什么不同? 就我最近对C++学习时遇到的一些问题来看,C++在语法上基本与C语言一致。但是由于房屋是别人建的,要使用它就要明白它们的建造过程(当然有些我们只要直接使用就行了,尤其是在前期)。而C++中封装的函数,也是C++的开发者已经建好的,所以我们要很好地使用它们就要明白它们的建造方式,至少要知道它们的使用语法。 4.C++语言与C语言的不同之处(准确的说应该是来看看C++开发者已经为我们做好了什么) 注意:以下只是我在编写六维鼠标时遇到的,不全面,其余区别大家可以在以后的学习中自己摸索。1)c语言后缀.c,c++后缀.cpp。 2)当函数定义放在函数调用之后时,C程序的函数原型即声明有时可省略,而C++的函数声明不能省略,而且还要求函数的所有参数在函数原型的圆括号中声明。一个不带参数的C函数原型必须使用void关键字,而C++函数原型可以使用空参数表。 3)C++中用new和delete运算符取代C的内存分配和释放函数malloc()和free()。4)const常量类型:用来表示一个“常值变量”与#define的区别: #define size 20 //不加;只是文本替换此后不再检查,可能产生负作用 Const int size=20;//加;替换时进行严格检查,只有当size是int型时才替换。 C++面向对象的程序设计 概述:面向对象不只是一种程序设计方法,还是一种建立客观事物模型、分析复杂事物的思想方法,他是以人们通常描述现实世界的方法来描述要解决的问题。 1.结构化程序设计:是一种自顶而下、逐步求精的模块化程序设计方法。 类:对象是累的一个实例。类=数据结构+对数据进行操作的函数 面向对象的程序设计的基本特征:抽象、封装、继承和多态。 抽象:对一类对象进行概括,抽出他们共同的性质并加以描述的过程。 封装:将抽象得到的属性数据和行为代码有机的结合,形成一个具有类特征的统一体。继承:一个新类可以从已有的类派生而来。 多态:不同对象对于同样的施加于其上的作用会有不同的反应。2.类的定义与实现: 加上类名和作用域限定符(::)。 3.成员函数的定义形式与一般函数的定义形势基本相同,但如果在类的外部定义成员函数,必须在成员函数名前一般将类的定义放在头文件(.h)中,类的实现放在源文件(*.cpp)中,二main主函数可以放在另一个源文件中。在源文件中用#include编译预处理指令包含头文件。 4.对象:对象是类的一个实例,定义并实现了类,就可以利用类来声明对象,其形式与普通变量的声明类似。 例如:以下用类Time声明了对象t1,today和对象的指针pt1: Time t1,today;//声明对象t1,today //声明指向对象t1的指针pt1 Time *pt1=&t1; 声明对象后,就可以像引用结构变量一样,利用成员运算符“.”或指向运算符“->”引用对象的公有成员,但注意不能引用对象的非公有成员。如:pt1->setTime()或t1.showTime()5.构造函数和析构函数:在声明对象时,对象一般需要进行初始化,及对成员变量进行初始化。在定义类时不能对成员变量进行初始化,因为不能确定类中定义的成员变量是属于哪一个对象。 构造函数:是一种特殊的成员函数,特殊性在于:它不需要用户程序调用,就能在创建对象时由系统自动调用。其作用就是在对象被创建时利用初始值去构建对象,使得在声明对象时就能自动地完成对象的初始化。析构函数:是在对象的生存期即将结束时由系统自动调用的。析构函数的作用与构造函数相反,用来在对象被删除前做一些清理工作和数据保存工作。 构造函数的名称与类名相同,析构函数的名称是在类明前加符号“~”构成(表达取反的意思)。注意,构造函数和析构函数不能有任何返回类型,包括void类型;析构函数不能有参数。下例说明了构造函数和析构函数的定义方法及执行顺序 6.静态数据成员在储存类型上类似于一般的static静态变量,也具有全局性。 静态数据成员的属性也可以是公有、私有或保护的。对于公有静态数据成员,除了可以像一般数据库成员那样,直接通过对象或在成员函数中访问它们,还可以利用类名加作用域限定符(::)来访问他们。对于私有和保护属性的静态数据库成员,只能在成员函数中访问它们。 由于静态数据成员不具体属于哪一个对象,因此不能构造函数或其他成员函数中对他们进行初始化,他们的初始化必须在类体外进行。 注意:静态成员函数只能访问类的静态成员(成员变量和成员函数),而不能访问非静态函数。解决这个问题的方法是将对象作为静态成员函数的参数,然后在静态成员函数中通过对象访问非静态成员。 7.this指针:在成员函数中访问数据成员或调用其他成员函数不需要指定对象,因为他们都是通过一个隐藏的this指针确定当前的对象。 例如:void Time :: showTime(){cout< void Time :: showTime(Time* this){ cout< 8.友元 定义:友元的另一种类型是友元类,一个类可以声明另一个类为其友元类,友元类的所有成员函数都可以访问声明其为友元类的所有成员。 构成:一个函数要成为一个类的有元函数,需要在类的定义中声明该函数,并在函数声明的前面加上关键字friend。 作用:友元提供了不同类或不同类的成员函数之间以及成员函数和一般函数之间的数据共享机制。注意:友元关系是单方向的,不具有交换性和传递性。 9.常对象和常对象成员:对于急需要共享又需要安全的数据,可以利用const来进行保护。 常对象:常对象的数据成员的值在对象的整个生存期内不能被改变,必须利用构造函数进行初始化,且以后不能再被更新。声明格式有以下两种: const<类名><对象名>(初始值类表)例如:const Time meeting(8,30,00);成员函数称为常成员函数。格式如下: <函数类型> <函数名>(<参数表>)const;例如,下面声明的成员函数MemberFun()就不能修改对象的数据成员。 void MemberFun()const;在常成员函数中只能调用常成员函数,而调用其他普通函数可能会造成简介修改数据成员。 常数据成员:可以使用const关键字将数据成员声明为常数据成员。常数据成员的初始值只能通过构造函数获取,并且只能在构造函数的初始化列表中设置其初始值。静态常数据成员初始化只能在类体外进行。11. 继承与派生:C++中,可以在已有类的基础上定义一个新类,新类称为原有类的派生类或子类,而原有类称为新定义类的基类或父类。 语法如下: class<派生类名> : [<派生方式>] <基类名>{… 例如: //派生类新增加的成员声明列表}; <类名> const <对象名>(初始值类表)10.常成员函数:可以使用const关键字限制成员函数对数据成员进行修改操作,这种使用const关键字进行声明的class Car : public Vehicle{… //在派生类Car中新增加的成员};基类中原有成员的访问权限在派生类中可以被修改,它们的访问权限由派生类定义中的<派生方式>决定。但注意,为了不破坏基类的封装性,无论采用哪种派生方式,基类的私有成员在派生类中都是不可见的,即不允许在派生类的成员函数中访问基类的私有成员。 public:punlic(公有派生)是类继承中最常见派生方式。这样就可以在派生类的成员函数中访问基类中原有的非私有成员,并能通过派生类的对象直接访问基类中原有的公有成员。private:采用private(私有派生),只允许在派生类的成员函数中访问基类的非私有成员,不能通过派生类的对象直接访问基类的任何成员。 protected:采用protected(保护派生),基类中所有的公有和保护成员在派生类中都成为保护成员。总结:派生方式就是把基类的非私有成员在派生类中以什么类型存在。 ABAQUS与FORTRAN论坛问题小结 Q:索了一下论坛发现以前的问题都是不同类型的子程序,如UEL, UMAT...这样把它们放在一个.for文件里不会有误会,但是如果都是UEL的话,该怎么识别呢? A:subroutine Umat()IF(CMNAME(1:4).EQ.'MAT1')THENCALL UMAT_MAT1(argument_list)ELSE IF(CMNAME(1:4).EQ.'MAT2')THENCALL UMAT_MAT2(argument_list)END IF上面是区分不同umat的方法,区分uel应该类似吧 Q:行abaqus的时候出现这样的提示“Problem during compilation-df.exe not found in PATH.”请问这是什么原因.A: 就是说找不到用于编译的df.exe文件(好像是Fortran的编译运行文件),在Windows控制面板的“系统”里,打开高级属性,将系统的PATH添加上Fortran的路径,最好也一并把INCLUDE和LIB也都添加上对应的FORTRAN的路径。 Q: 如何在ABAQUS中调用用户子程序UMAT A:abaqus job=*** user=*.for or *.objA: 装好fortran编译器的前提下,有两种方式: 1、命令行:abaqus job=*.inp user=*.for或 abaqus job=*.inp user=*.obj(可以由*.f90编译后得到) 2、菜单格式:先运行CAE,在general设置中可以指定Umat用户子程序A: job=jobname user=yourfortran.for(其它类型子程序)A:如果是本构的二次开发:*material, user Q: abaqus job=job-name user={source-file | object-file}source-file和object-file各是什么? A: fortran的源文件(.for)或者目标文件(.o)在command下面输入以上命令行就可以正常运行.用户子程序再调用别的fortran程序时,要加入abaqus 子程序中的include 'ABA_PARAM.INC'。 Q: 自己编写子程序需要哪些工作步骤 A: 1.建立工作目录 2.将abaqus安装目录6.4-pr11site下的aba_param_dp.inc 或 aba_param_sp.inc拷贝到工作目录,并改名为aba_param.inc ; 3.将编好的fortran程序拷贝到工作目录; 4.编译fortran程序,将.obj文件拷贝到工作目录; 5.建立好输入文件.inp;6.运行abaqus job=inp file name user=fortan name即可。我的要运行abq64pr11 job=inp file name user=fortan name我也学了没多久,按照这个过程成功了一个!你们试一下吧!Q: 想用FORTRAN实现:...result = SYSTEMQQ('abq job=e:abaqu***amplesbeam interactive')...出错提示:ABAQUS ERROR:Unable to create a temporary directory C:DOCUME~1ADMINI~1LOCALS~1TEMPAdministrato_ e:abaqu***amplesbeam_3628 to be used for scratch files.ABAQUS/Analysis exited with errors.但如果是 result = SYSTEMQQ('abq job=beam interactive'),但需要在FORTRAN弹出的DOS窗口里手工输入文件的绝对路径则计算正常。但我的目的是实现Fortran程序对ABAQUS的计算程序的自动调用。 A: 说个投机的花招,有没有试过在前面加上result = SYSTEMQQ('path=e:/abaqu***amples')这样的命令~~方法简单,不过能解决问题最好 A:把要算的工况都集中在一个文件夹下,fortran生成.exe文件,放在该文件夹下,然后双击运行。计算结束之后再把各种工况分类。笨招,但好用。 A: 我想,或者把systemQQ改一下,先cd e:...,然后再systemQQ(abaqus job=jobname interactive)。 Q: 偶想在FORTRAN里设定一个计时器,其功能就是每隔一段时间(如10s)就去读一次ABAQUS的(.fil)文件。哪个函数可以实现这个功能?怎么实现?? A: 通过一个while循环和下面的语句:call sleepqq(时间间隔)就可以了。 Q: 本人尝试使用ABAQUS的子程序SUBROUTINE,根据帮助文件需要编译通过生成*.for和*.lib文件,可是编译的时候出现错误:Error: Cannot open include file 'ABA_PARAM.INC'不知道是什么原因,怎么解决? A: 1.确认Visual Fortran及VC++正确安装,并在安装ABAQUS之前安装。2.首先将用户子程序*.f文件后缀名改为*.for。3.到控制面板-》系统-》高级-》环境变量中的 Administrator用户变量:修改—— 变量名:lib变量值:C:Program FilesMicrosoft Visual StudioDF98LIB;C:Program FilesMicrosoft Visual StudioVC98LIB(我的问题就是因为只加了一个LIB,必须两个都加!)完成以上步骤以后,就可以运行了。 Q: 怎样把自己编写的子程序倒入到*.INP文件中。 A: Using the following command : abaqus job=job-id As can be seen this is no different from running a standard abaqus job.The user subroutine itself can be embedded in the abaqus input file.Here it is illustrated with the umat subroutine.<....part of the abaqus input file....> ........*END STEP*USER SUBROUTINES SUBROUTINE UMAT(........) ........END ........Alternatively the user subroutine can be in a separate file(say my_material.f)and the INPUT parameter is set to that file name.<....part of the abaqus input file....> ........*USER SUBROUTINES, INPUT=my_material.f ........Q: 用Fortran SYSTEMQQ函数作批处理遇到问题,在fortran中使用result = systemqq(abaqus job=job1 interactive)作批处理,总是在计算两个job之后就不继续往下算了,cmd明令行提示:run time error:floating-point...请问这是怎么回事? A: 个方法就是做一个批处理文件,abaqus job=beam interactiveabaqus job=beam1 interactiveabaqus job=beam2 interactiveabaqus job=beam n? interactive存为.bat文件即可。python好像一般是做CAE前后处理界面的。 A:前面加call.call abaqus job=1 interactivecall abaqus job=2 interactivecall abaqus job=3 interactive Q:FORTRAN如何调用ABAQUS? A: use the function “system” or “systemqq” USE DFLIB LOGICAL(4)result result = SYSTEMQQ('abaqus job=xx')QA: 首先我用ABAQUS的VARIFY命令对系统进行修正和检测,这个命令会自动运行,对ABAQUS进行调试等操作,其中涉及到对用户子程序的模拟计算,如果计算失败,就会在VARIFY.LOG文件中说明,确实发现“USER SUBROUTINE...和SINGLE...和DOUBLE...”失败,说明用户子程序安装不成功,肯定与VISUAL FORTRAN6.5有关!然后,找到FORTRAN_MAKE文本文件,发现错误,可能是与FORTRAN安装有关!于是卸载FORTRAN,重新安装在C盘!安装完毕后,改变环境变量如下: INCLUDE C:Program FilesMicrosoft Visual StudioDF98IMSLINCLUDE;C:Program FilesMicrosoft Visual StudioVC98INCLUDE;D:程序文件VC98INCLUDE;LIB C:Program FilesMicrosoft Visual StudioDF98IMSLLIB;C:Program FilesMicrosoft Visual StudioDF98LIB;C:Program FilesMicrosoft Visual StudioVC98LIB;D:程序文件VC98LIB;PATH C:Program FilesMicrosoft Visual StudioCommonTools;D:程序文件VC98BIN;%SystemRoot%system32;%SystemRoot%;%SystemRoot%System32Wbem;C:KAV6;D:程序文件KV6;c:program filesmicrosoft visual studiodf98bin;c:program filesmicrosoft visual studiovc98bin;c:program filesmicrosoft visual studiocommonmsdev98bin;D:ABAQUSCommands;C:Program FilesMicrosoft Visual StudioDF98BIN我们只需要关注MICROSOFT VISUAL STUDIO文件夹!最后,再次执行VARIFY命令,等运行完毕后,检查VARIFY文本文件,发现: ABAQUS/Standard with User Subroutines...PASSContinuing...ABAQUS/Explicit with User Subroutines(single precision)...PASSContinuing...ABAQUS/Explicit with User Subroutines(double precision)...PASSContinuing...OK!!!!!!!!!搞定 Q: 因为ABAQUS是用PYTHON编写的,那么我想要PYTHON 的原代码,因为我想 在其中加一个椭圆程序,不知可行么?(访问原代码问题) A: 所有的PY都是差不多一样的,把ABAQUS的PY拿到MARC试试看 文档来源:http://www.xiexiebang.com/bbs/redirect.php?fid=10&tid=9031&goto=nextnewset C++继承中构造函数、析构函数调用顺序及虚函数的动态绑定 昨天面试被问到这些,惭愧的很,居然搞混了,悔恨了一把。决定要彻底搞清楚。也算是有所收获。 首先说说构造函数,大家都知道构造函数里就可以调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就可以调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数,只有这样子类才能在构造函数里使用基类的成员,所以是创建子类时先调用基类的构造函数然后再调用自己的构造函数。通俗点说,你要用某些物品,但这些物品你没办法自己生产,自然就要等别人生产出来,你才能拿来用。 接着就是析构函数了,上面说到子类是将基类的成员变成自己的成员,那么基类就会只存在子类中直到子类调用析构函数后。做个假设:假如在基类的析构函数调用比子类的先,这样会发生什么事呢?类成员终止了,而类本身却还在,但是在类存在的情况下,类成员就应该还存在的,这不就产生矛盾了吗?所以子类是调用自身的析构函数再调用基类的析构函数。 现在到了虚函数了,virtual主要作用是在多态方面,而C++的多态最主要的是类的动态绑定,动态绑定则是指将子类的指针或引用转换成基类对象,基类对象就可以动态判断调用哪个子类成员函数。这就说明在没有子类指针或引用转换为基类对象的话,virtual没有存在意义(纯虚函数除外),也就是有没有virtual都是调用其自身的成员函数。通过这些分析,对于virtual就有了眉目了。当子类指针或引用转换为基类时,若基类中有用virtual定义的函数,被子类重写后,此基类对象就会根据子类调用子类中的重写后的函数,而不是基类中的函数;反之,若是基类中没有用virtual定义,则不管基类被赋值的是哪个子类的值,调用的都是基类的成员函数(当然指的是子类重载的基类函数,不然就算要调用子类特有的成员函数也会编译不过)。第二篇:Fortran语言编程小结
第三篇:C++学习心得小结
第四篇:ABAQUS与FORTRAN论坛问题小结
第五篇:构造函数-析构函数的调用顺序