常见fortran系统错误
- 格式:doc
- 大小:81.50 KB
- 文档页数:12
fortran read error 处理-回复如何使用Anki创建常用单词卡片。
第一步:理解Anki和其优点在开始之前,我们需要了解Anki是什么以及它的优点。
Anki是一款强大的记忆辅助软件,它使用间隔重复算法来帮助用户有效地记忆信息。
使用Anki创建常用单词卡片能够帮助我们扩展词汇量,提升语言技能。
Anki的优点有以下几点:1. 自适应学习:Anki根据用户的学习状态和记忆曲线来调整卡片的出现频率,使学习更高效。
2. 多平台支持:Anki可以在各种操作系统和设备上运行,包括Windows、Mac、Linux、iOS和Android。
3. 可定制性:Anki可以按照用户的需求进行定制,例如添加图片、音频和视频等。
4. 社区资源丰富:Anki拥有活跃的用户社区,可以分享和下载其他用户创建的卡片组。
第二步:准备工作在创建常用单词卡片之前,我们需要准备工作。
首先,我们需要下载并安装Anki软件。
Anki有一个官方网站,可以在上面找到各个平台的安装包。
安装完成后,打开Anki软件并注册一个账号。
第三步:创建一个新的卡片组在Anki中,卡片组是卡片的集合。
创建一个新的卡片组可以帮助我们更好地管理和组织单词卡片。
点击Anki软件中的“文件”->“新建”或者使用快捷键“Ctrl+N”来创建一个新的卡片组。
在弹出的窗口中输入卡片组的名称,例如“常用单词”,点击“确定”按钮创建新的卡片组。
第四步:添加一个新的卡片类型在Anki中,卡片类型定义了卡片的格式。
通常,我们会创建一个基本卡片类型,用于添加新的单词和其对应的释义。
在刚刚创建的卡片组中,点击“工具”->“管理笔记类型”,在弹出的窗口中点击“添加”按钮创建一个新的卡片类型。
输入卡片类型的名称,例如“基本”,点击“确定”按钮创建新的卡片类型。
第五步:设计卡片的模板在Anki中,卡片模板定义了卡片的布局和显示方式。
我们需要设计一个适合我们的常用单词卡片的模板。
fortran debug案例
Fortran是一种程序设计语言,其用途广泛,在科学计算和工程领域使用较多。
在编写Fortran程序时,调试是非常重要的,以下是一个Fortran调试的案例。
假设我们有一个Fortran程序,用于计算给定数组的平均值。
然而,当我们运行这个程序时,得到的结果并不正确。
我们需要进行调试来找到问题所在。
首先,我们可以检查程序中的算法。
可以通过在代码中添加打印语句来跟踪程序的执行。
例如,我们可以在计算平均值之前打印出数组的值,以确保数组中的数据正确无误。
其次,我们可以检查数组的大小是否与程序的预期相匹配。
如果数组的大小不正确,程序可能会访问无效的内存位置,导致错误的结果。
在这种情况下,我们需要仔细检查数组的定义和传递给计算平均值函数的参数。
此外,我们还可以使用调试工具来进一步分析程序。
例如,我们可以使用gdb或者Ddt来调试Fortran程序。
这些调试工具可以帮助我们在程序运行时跟踪变量的值,执行代码的流程,并定位错误所在的位置。
最后,一些常见的Fortran调试技巧包括:
1. 使用正确的输出格式打印变量值,以检查其值是否正确。
2. 检查循环和条件语句的逻辑,确保程序按照预期的方式执行。
3. 检查程序中的错误处理机制,例如数组越界或除以零等情况。
总之,Fortran调试是找出程序错误的关键步骤。
通过仔细检查代码逻辑、打印变量值、使用调试工具以及遵循常见的调试技巧,我们可以快速有效地找到问题所在,并修复程序中的错误。
fortran end-of-file during read的解决方法在Fortran中,"end-of-file during read" 错误通常表示在尝试读取文件时已经到达了文件的末尾。
这可能是由于文件结尾符号不正确、文件被意外删除或其他一些问题引起的。
以下是一些可能的解决方法:1. 检查文件路径和文件是否存在:-确保你正在尝试读取的文件路径是正确的。
-确保文件确实存在于指定的路径中。
2. 检查文件格式:-确保你的Fortran程序中的文件格式与文件本身的格式匹配。
例如,如果文件是以ASCII 格式存储的,你的程序应该使用`READ(*,*)`而不是二进制读取。
3. 检查文件是否为空:-如果文件是空的,你可能会遇到此错误。
在尝试读取文件之前,你可以添加一些逻辑来检查文件是否为空。
```fortranINTEGER :: file_unitOPEN (UNIT=file_unit, FILE='your_file.txt', STATUS='OLD', ACTION='READ', IOSTAT=iostat) IF (iostat /= 0) THEN! 文件不存在或无法打开PRINT *, 'Error opening file'ELSE! 文件已成功打开READ (file_unit, *, IOSTAT=iostat)IF (iostat /= 0) THEN! 在尝试读取文件时出现错误PRINT *, 'Error reading file'ELSE! 文件成功读取PRINT *, 'File read successfully'END IFEND IFCLOSE (file_unit)```4. 检查文件访问权限:-确保你的程序有足够的权限读取指定的文件。
在某些操作系统上,文件权限可能是一个问题。
Fortran是一种编程语言,用于科学计算和数值计算的高级程序设计。
在使用Fortran编程时,函数声明是一项重要的操作,它可以帮助程序员正确地定义和调用函数,确保程序的正确性和可靠性。
然而,有时候在编写Fortran程序时,程序员会遇到一些没有声明的函数,这可能会导致程序出现错误或者无法正常运行。
本文将就这一问题展开讨论,并提出解决方法。
1. 为什么会出现没有声明的Fortran函数Fortran编程中出现没有声明的函数的原因有很多,常见的包括:(1)函数声明遗漏:有时候在编写Fortran程序时,程序员可能会忘记对函数进行声明,这可能是由于疏忽或者粗心造成的。
(2)函数定义错误:有时候程序员可能会在程序中直接定义函数而没有进行声明,这样会导致编译器无法正确识别函数的类型和参数。
(3)函数命名冲突:有时候程序员可能会在程序中使用了与其他库函数同名的函数而没有进行声明,这样会导致编译器无法确定到底应该调用哪一个函数。
2. 没有声明的Fortran函数可能会带来的问题出现没有声明的Fortran函数可能会导致以下问题:(1)编译错误:如果程序中调用了没有声明的函数,那么在编译阶段就会出现错误,编译器无法识别这个函数,从而导致编译失败。
(2)运行错误:即使程序能够顺利编译通过,但是在运行时调用了没有声明的函数也会导致程序运行错误,可能会出现未定义行为或者崩溃。
(3)难以调试:如果程序中存在没有声明的函数,那么调试起来会比较困难,因为程序员无法准确地确定函数到底做了什么,可能需要耗费更多的时间和精力来进行调试。
3. 如何解决没有声明的Fortran函数问题针对没有声明的Fortran函数问题,可以采取以下解决方法:(1)添加函数声明:在程序中的函数调用之前,确保要调用的函数已经被声明过,包括函数的类型、参数类型和个数等信息。
(2)修改函数定义:如果程序中存在直接定义但未声明的函数,可以通过在程序的开头添加函数声明来解决这一问题。
ABAQUS与FORTRAN论坛问题小结Q:索了一下论坛发现以前的问题都是不同类型的子程序,如UEL, UMA T...这样把它们放在一个.for文件里不会有误会,但是如果都是UEL的话,该怎么识别呢?A:subroutine Umat()IF (CMNAME(1:4) .EQ. 'MA T1') THENCALLUMA T_MA T1(argument_list)ELSE IF(CMNAME(1:4) .EQ. 'MA T2') THENCALLUMA T_MA T2(argument_list)END IF上面是区分不同umat的方法,区分uel应该类似吧Q:行abaqus的时候出现这样的提示"Problem during compilation - df.exe not found in PA TH."请问这是什么原因.A: 就是说找不到用于编译的df.exe文件(好像是Fortran的编译运行文件),在Windows控制面板的“系统”里,打开高级属性,将系统的PA TH添加上Fortran的路径,最好也一并把INCLUDE和LIB也都添加上对应的FORTRAN的路径。
Q: 如何在ABAQUS中调用用户子程序UMA TA: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, userQ: abaqus job=job-name user={source-file | object-file}source-file和object-file各是什么?A: fortran的源文件(.for)或者目标文件(.o)在command下面输入以上命令行就可以正常运行. 用户子程序再调用别的fortran程序时,要加入abaqus 子程序中的include'ABA_PARAM.INC'。
Fluent 计算错误汇总:1. .fluent 不能显示图像在运行fluent 时,导入case 后,检查完grid,在显示grid 时,总是出现这样的错误Error message from graphics function Update_Display:Unable to Set OpenGL Rendering ContextError: FLUENT received a fatal signal SEGMENTA TION VIOLATION.Error Object: 解决办法:右键单击快捷方式,把目标由x:fluent.incntbinntx86fluent.exe改成:x:fluent.incntbinntx86fluent.exe 2d -driver msw如果还有三维的,可以再建立一个快捷方式改成:x:fluent.incntbinntx86fluent.exe 3d -driver msw这就可以直接调用了。
如果不是以上原因引起的话,也有可能是和别的软件冲突,如MATLAB 等,这也会使fluent 无法显示图像。
2:GAMBIT 安装后无法运行,出错信息是“unable find Exceed X Server”A. GAMBIT 需要装EXCEED 才能用。
gambit 的运行:先运行命令提示符,输入gambit,回车fluent 的运行:直接在开始-程序-Fluent Inc 里面3:Fluent 安装后无法运行,出错信息是“unable find/open license.datA. FLUENT 和GAMBIT 需要把相应license.dat 文件拷贝到FLUENT.INC/license 目录下4:出错信息:运行gambit 时提示找不到gambit 文件A. FLUENT 和GAMBIT 推荐使用默认安装设置,安装完GAMBIT 请设置环境变量,设置办法“开始-程序-FLUENT INC-Set Environment 另外设置完环境变量需要重启一下,否则仍会提示找不到环境变量。
gnu fortran编译fortran程序摘要:1.Gnu fortran 编译器简介2.使用Gnu fortran 编译Fortran 程序的基本步骤3.编译过程中可能遇到的问题及解决方案正文:Gnu fortran 编译器是一款免费、开源的Fortran 编译器,它可以编译Fortran 77、Fortran 90 和Fortran 95 标准的程序。
使用Gnu fortran 编译器,可以让Fortran 程序在多种平台上运行,为科研和工程领域提供便利。
在使用Gnu fortran 编译Fortran 程序之前,需要确保已经安装了Gnu fortran 编译器。
安装完成后,可以按照以下步骤进行编译:1.编写Fortran 程序:首先,创建一个Fortran 源文件,例如:main.f。
在文件中编写程序代码。
2.使用Gnu fortran 编译器编译程序:打开终端或命令提示符,导航到源文件所在的目录,然后输入以下命令开始编译:```gfortran main.f -o main```该命令将源文件main.f 编译为可执行文件main。
如果编译器检测到任何错误,将给出错误信息。
请根据错误信息修改源文件并重新编译。
3.运行编译后的程序:在命令行中输入以下命令运行编译后的程序:```./main```如果在编译或运行过程中遇到问题,可以尝试以下方法解决:- 检查源文件中的语法错误,确保代码符合Fortran 标准。
- 检查编译器版本是否与源文件兼容。
如果不兼容,可以尝试升级或降级编译器。
- 检查系统环境变量设置,确保Gnu fortran 编译器可执行文件路径已添加到环境变量中。
总之,Gnu fortran 编译器为Fortran 程序提供了强大的支持。
gfortran编译gfortran编译器是GNU编译器套件(GCC)中的一部分,专门用于编译Fortran语言程序。
本文将介绍gfortran编译器的基本使用方法、编译选项和一些常见问题的解决方案。
一、gfortran编译器简介gfortran是一个开源的Fortran编译器,由GNU开发并维护。
它支持Fortran 95、Fortran 2003和Fortran 2008标准,并提供了许多扩展功能。
gfortran编译器可在多个平台上运行,包括Linux、macOS和Windows等。
1. Linux系统:可以使用包管理器安装gfortran,如在Ubuntu上使用apt命令:sudo apt-get install gfortran。
2. macOS系统:可以使用Homebrew包管理器安装gfortran,如:brew install gfortran。
3. Windows系统:可以从MinGW-w64项目的官方网站下载并安装gfortran。
三、使用gfortran编译器1. 编写Fortran源代码:使用任何文本编辑器创建一个以".f"或".f90"为后缀的Fortran源代码文件,例如hello.f90。
2. 编译源代码:打开终端或命令提示符窗口,使用gfortran命令编译源代码。
例如:gfortran -o hello hello.f90。
3. 运行可执行文件:编译成功后,可以运行生成的可执行文件。
例如:./hello(Linux/macOS)或hello.exe(Windows)。
四、编译选项gfortran编译器提供了许多编译选项,可以根据需要进行配置。
以下是一些常用的选项:1. -o <output>:指定生成的可执行文件的名称。
2. -c:只编译源代码,生成目标文件而不链接。
3. -Wall:显示所有警告信息。
4. -O<level>:指定优化级别,如-O0(禁用优化)、-O1(基本优化)等。
fortran read error 处理Fortran Read Error Handling: A Step-by-Step GuideIn Fortran, read statements are used to input data from a specified source, such as a file or the standard input. However, there are cases where errors can occur during the execution of a read statement, which can lead to program failures or incorrect results. Therefore, it is essential to understand how to effectively handle read errors in Fortran. In this article, we will take a step-by-step approach to guide you through the process of handling Fortran read errors.Step 1: Enable Error HandlingTo begin, you need to enable error handling in your Fortran program. This can be achieved by including the `ERR` parameter in your read statement. The `ERR` parameter allows you to specify an error handling routine that will be executed if an error occurs during the execution of the read statement. For example:READ(UNIT, *, ERR = errorHandler) variableIn this example, `UNIT` is the unit number associated with the input source, `variable` is the variable to store the input data, and`errorHandler` is the name of the error handling routine.Step 2: Define the Error Handling RoutineNext, you need to define the error handling routine that will be executed when an error occurs during the read statement. This routine should handle the error appropriately, such as displaying an error message or taking corrective actions. For example:SUBROUTINE errorHandler()IMPLICIT NONEINTEGER :: errorCodeerrorCode = IOSTAT ! Get the error code from IOSTATSELECT CASE (errorCode)CASE (-1)WRITE(*, *) "End-of-file reached."CASE (-i)WRITE(*, *) "Input error occurred (code = ", ABS(i), ")."CASE (i)WRITE(*, *) "Output error occurred (code = ", i, ")."CASE DEFAULTWRITE(*, *) "Unknown error occurred."END SELECT! Take appropriate actions based on the error...END SUBROUTINE errorHandlerIn this example, we use the `SELECT CASE` construct to handle different error codes. The `IOSTAT` function returns the error code, which can be negative for input errors and positive for output errors. You can customize the error handling routine to suit your specific needs, such as logging errors or terminating the program.Step 3: Implement Error Detection and RecoveryAfter defining the error handling routine, you can now implement error detection and recovery mechanisms in your program. One common approach is to use a loop to continuously read input until a valid data isobtained or an error occurs. For example:INTEGER :: i, errorCodeDOREAD(UNIT, *, ERR = errorHandler, IOSTAT = errorCode) iIF (errorCode == 0) THEN! Valid input obtained, exit the loopEXITELSE! Error occurred, display error message and continue readingCALL errorHandler()END IFEND DOIn this example, the loop continues until a valid input is obtained(`errorCode == 0`), at which point the program exits the loop. If an error occurs, the `errorHandler` routine is called to handle the error and the loop continues.Step 4: Test and DebugFinally, it is crucial to thoroughly test your Fortran program with different input scenarios to ensure the error handling mechanism is functioning correctly. Test for common read errors, such as invalid input types, reaching end-of-file prematurely, or unexpected input format. Use test cases that cover a wide range of possible inputs to verify the effectiveness of your error handling implementation.In conclusion, handling Fortran read errors involves enabling error handling, defining an error handling routine, implementing error detection and recovery mechanisms, and testing and debugging the program. By following this step-by-step guide, you can ensure that your Fortran programs handle read errors effectively, improving the stability and reliability of your code.。
[sourcefile(line)]run-time error M62xxMATH错误号函数级数学错误信息M6201 functionnames:DOMAIN error函数的自变量超出了约定的取值域,例如sqrt(-l)M6202 functionname:SING error无意义的变量。
例如loglO(O)M6203 functionname:OVERFLOW error函数的结果值或其中一个既时计算值太大以致不能表示,例如EXP(250000.0)M6204 functionname:UNDERFLOW error函数的结果值或其中一个既时计算值太小以致不能表示。
M6205 functionname: TLOSS error完全丢失精度,例如COS(1E30)M6206 functionname:PLOSS errorCVF中有两种编译(连接、执行)模式:release模式和debug模式。
调试程序时,宜用debug模式;调好后再用release模式,得到高效的执行程序。
设定debug模式:点击菜单Build/Set Active Project Configuration,选*- Win32 Debug, OK,即设定为debug 模式。
以debug 模式执行:点击"Go (F5)”按钮,或直接按F5键,则执行程序,并在第一个出错语句处停止,在该语句前有一个小黄色箭头。
若程序没错, 则一直执行完毕,自动关闭dos窗口。
此时,宜用“!〃按钮或"Ctrl+F5〃键,执行完成后,dos窗口等待用户关闭。
设置断点:若希望执行时在某一语句处暂停,可将光标置于该语句,点击〃手〃形状的按钮,或按F9键,则程序执行到该语句时停在该语句处。
单步执行:F10 (不进入了过程程序段)或者FM (遇到了过程进入了过程程序段继续单步执行)。
在工具栏上都有相应的按钮。
查看变量值:小黄箭头停在某语句时,按下Variable按钮,显示当前程序段的变量值;对于简单变量,将光标放在该变量上,则即时显示该变量值。
Mistakes in Fortran 90 Programs That Might Surprise YouOver the years we have made lots of interesting and fun mistakes in Fortran 90 that we would like to share with you. We welcome your contributions and experiences so that we can share your pain.TopicsThese "gotchas" are nasty because they will not fail on some machines, while failing on others (given various combinations of compilers and machine platforms).∙Danger with Optional Arguments∙Danger with intent(out)∙ A suprise with non-advancing I/O∙Suprise with locally initialized variables∙Danger of calling Fortran 90 style routines∙Danger with interfaces to Fortran 77 subroutines∙ A suprise with generic functions∙Big Danger with Undefined Pointers∙Subtle danger with overloading (=) to assign pointers∙Danger with pointers to pointersDanger with Optional ArgumentsIn this example an optional argument is used to determine if a header is printed.subroutine print_char(this,header)character(len=*), intent (in) :: thislogical, optional, intent (in) :: header! THIS IS THE WRONG WAYif (present(header) .and. header) thenprint *, 'This is the header 'endifprint *, thissubroutine print_char(this,header)character(len=*), intent (in) :: thislogical, optional, intent (in) :: header! THIS IS THE RIGHT WAYif (present(header)) thenif (header) print *, 'This is the header 'endifprint *, thisend subroutine print_charExplanationThe first method is not safe because the compiler is allowed to evaluate the header argument before the present function is evaluated. If the header argument is not in fact present an out of bounds memory reference could occur, which could cause a failure.Danger with intent(out)In this example we assign components of a derived type with intent(out). program intent_gotchatype mytypeinteger :: xreal :: yend type mytypetype (mytype) :: aa%x = 1 ; a%y = 2.call assign(a)! a%y COULD BE UNDEFINED HEREprint *, acontainssubroutine assign(this)type (mytype), intent (out) :: this! THIS IS THE WRONG WAYthis%x = 2end subroutine assignsubroutine assign(this)type (mytype), intent (out) :: this! THIS IS THE RIGHT WAYthis%x = 2 ; this%y = 2.end subroutine assignExplanationThe problem is that when intent(out) is used with a derived type, any component not assigned in a procedure could become undefined on exit. For example, even though a%y was defined on entry to this routine, it could become undefined on exit because it was never assigned within the routine. The lesson is that all components of a derived type should be assigned within a procedure, when intent(out) is used. Intent(out) behaves like the result variable in a function: all components must be assigned.As an alternative, use intent(inout).A suprise with non-advancing I/OMany people think that the new non-advancing I/O in Fortran 90 is the same as stream I/O in other languages. It is not.do i = 1, 128write (unit=6,fmt='(a)',advance='no') 'X'end doWe expect this program to print 128 X's in a row. However, unexpected behavior may occur if the record length for unit 6 is less than 128.One can inquire the record length in the follow way:open(unit=6)inquire(unit=6, recl=i)print *, 'recl =', iExplanationAll Fortran I/O is still record based. Non-advancing I/O allows partial reads and writes within a record. For many compilers the default record length is very large (e.g., 2147483647) giving the appearance of stream I/O. This is not true for all compilers however.On some compilers it is possible to set the record length as follows:open(unit=6, recl = 2147483646)On other compilers unit 6 is preconnected and the record length cannot be changed. (Thanks to Jon Richards of the USGS for this tip.)Note that unit 6 and unit * are not necessarily the same. Although they both may point to the default output device, with non-advancing I/O, each could keep track of the current location in its own record separately. Therefore we advise choosing one default unit and sticking with it.Suprise with locally initialized variablesOne must be careful when initializing a locally declared variable.real function kinetic_energy(v)real, dimension(:), intent(in) :: vinteger i! THIS IS THE WRONG WAYreal :: ke = 0.0do i = 1, size(v)ke = ke + v(i)**2enddokinetic_energy = .5*keend function kinetic_energyreal function kinetic_energy(v)real, dimension(:), intent(in) :: vinteger i! THIS IS THE RIGHT WAYreal :: keke = 0.do i = 1, size(v)ke = ke + v(i)**2enddokinetic_energy = .5*keend function kinetic_energyExplanationA local variable that is initialized when declared has an implicit save attribute. ke is initialized only the first time the function is called. On subsequent calls the old value of ke is retained. This is a real suprise to C programmers.To avoid confusion it is best to add the save attribute to such locally initialized variables explicitly, even though this is redundant.Danger of calling Fortran 90 style routinesprogram mainreal, dimension(5) :: xx = 0.! THIS IS WRONGcall incb(x)print *, xend program mainsubroutine incb(a)! this is a fortran90 style subroutinereal, dimension(:) :: aa = a + 1.end subroutine incbExplanationThe subroutine incb uses a Fortran 90 style assumed shape array (containing dimension(:)). Such routines must either be in a module, or have an explicit interface wherever they are used. In this example, neither one was true.One correct way to call such procedures is to use an explicit interface as follows:program mainreal, dimension(5) :: x! THIS IS THE RIGHT WAYinterfacesubroutine incb(a)real, dimension(:) :: aend subroutine incbend interfacex = 0.call incb(x)print *, xend program mainsubroutine incb(a)! this is a fortran90 style subroutinereal, dimension(:) :: aa = a + 1.end subroutine incbIf the routine is in a module interfaces are generated automatically and do not need to be explicitly written.! THIS IS ANOTHER RIGHT WAYmodule inccontainssubroutine incb(a)! this is a fortran90 style subroutinereal, dimension(:) :: aa = a + 1.end subroutine incbend module incprogram mainuse increal, dimension(5) :: xx = 0.call incb(x)print *, xend program mainIf interfaces are used, the interface MUST match the actual function. Danger with interfaces to Fortran 77 subroutinesprogram mainreal, dimension(5) :: x! interface to Fortran 77 style routineinterfacesubroutine inca(a,n)integer :: n! THIS IS THE WRONG WAYreal, dimension(:) :: a! THIS IS THE RIGHT WAYreal, dimension(n) :: aend subroutine incaend interfacex = 0.call inca(x,5)print *, xend program mainsubroutine inca(a,n)! this is a fortran77 style subroutinedimension a(n)do 10 j = 1, na(j) = a(j) + 1.10 continuereturnendExplanationThe interface declaration must always match the actual subroutine declaration. In this case, the interface statement refers to a Fortran 90 style assumed shape array. The actual subroutine refers to a Fortran 77 explicit shape array. The lesson here is: Interfaces to Fortran 77 style routines must only use Fortran 77 style constructs.In this example, it is permitted to leave out the interface altogether since routines without interfaces are treated as Fortran77 style routines by default. However, if the interface is left out, the compiler will no longer check whether the arguments of calling procedures agree with the arguments listed in the interface.A Suprise with Generic Functions (Function Overloading)Fortran 90 allows the same function name to be used for different actual functions, so long as the arguments to the functions differ. One would expect that the functions first_sub and second_sub below would be different, because in first_sub, the first argument is a real and the second is an integer, while in second_sub the arguments are reversed. subroutine first_sub(a,i)real :: ainteger :: i...end subroutine first_sub!subroutine second_sub(i,a)integer :: ireal :: a...end subroutine second_subSo that one could define a generic function first_or_second below:interface first_or_secondmodule procedure first, secondend interfaceThis is NOT so.ExplanationThe reason is that Fortran 90 allows procedures to be called by name (keyword) arguments. The followingreal :: binteger :: ncall first_or_second(i=n,a=b)does not work because when called by keyword, first_sub and second_sub are indistinguishable,call first_sub(i=n,a=b)call second_sub(i=n,a=b)and therefore a generic function cannot be defined. A generic function must be able to distinguish its arguments by type AND by name.The solution is to not use the same dummy argument name in both procedures. For example, the following would work:subroutine second_sub(i,aa)integer :: ireal :: aa...end subroutine second_subDangers with PointersFortran 90 has 3 ways to implement dynamic memory: Automatic arrays, allocatable arrays, and pointers.Automatic arrays are automatically created on entry and deleted on exit from a procedure, and they are safest and easiest to use. Allocatable arrays require the user to manually create and delete them, and should only be used if automatic creation and deletion is not the desired behavior.Pointers are the most error prone and should only be used when allocatable arrays are not possible, e.g., when one desires an array to be a component of a derived type.Big Danger with Undefined PointersMany people think that the status of a pointer which has never been associated is .not. associated. This is false.In this example we are allocating a local_table on first entry that is to be reused on subsequent entries.subroutine local_pointer(this)real, dimension(:) :: thisreal, dimension(:), save, pointer :: local_table! THIS IS THE WRONG WAYif (.not. associated(local_table)) thenallocate(local_table(size(this)))endiflocal_table = ......end subroutine local_pointersubroutine local_pointer(this)real, dimension(:) :: thisreal, dimension(:), save, pointer :: local_table! THIS IS THE RIGHT WAYlogical, save :: first_entry = .true.if (first_entry) thennullify(local_table) ; first_entry = .false.end ifif (.not. associated(local_table)) thenallocate(local_table(size(this)))endiflocal_table = ......end subroutine local_pointerExplanationWhen a pointer is declared its status is undefined, and cannot be safely queried with the associated intrinsic. A second variable is introduced to nullify the pointer on first entry so that its status can be safely tested. This is not a problem in Fortran 95 which allows one to nullify a pointer on declaration.Note that the save attribute for local_table is necessary to guarantee that the array and the pointer status are preserved on subsequent entries. We recommend that the save attribute should always be used when pointers and allocatable arrays are allocated in procedures.Subtle danger with overloading (=) to assign pointersOne must be careful with overloading the assignment operator.In this module we have created a private type which contains a pointer and a public procedure to assign that pointer.module assign_pointer_classtype mytypeprivatereal, pointer :: prend type mytypeinterface assignment (=)module procedure assign_pointerend interfacecontainssubroutine assign_pointer(this, a)type (mytype), intent(out) :: thisreal, target, intent(in) :: athis%pr => aend subroutine assign_pointerend module assign_pointer_classIn this main program we intend to assign the pointer component x%pr to the variable a, x%pr =>a. We cannot do so directly because the components of mytype are private. One must use a public procedure to do so. Furthermore, to simplify the syntax one might be tempted to use an overloaded assignment operator (=).program mainuse assign_pointer_classtype (mytype) :: xreal :: a = 0! THIS IS THE WRONG WAYx = aend program mainDon't give into this temptation! The only safe way to accomplish this is to call the procedure directly.program mainuse assign_pointer_classtype (mytype) :: x! THIS IS THE RIGHT WAYreal, target :: a = 0call assign_pointer(x,a)end program mainExplanationThe Fortran 90 standard says that the right hand side of an assignment operator is an expression that may potentially only persist for the duration of the call. In other words, x%pr could inadvertently point to a temporary copy of the variable a.Thanks to Henry Zongaro of IBM for pointing this out. (We never would have figured this one out on our own.)Also, James Giles found a subtle point regarding this example. We did not include "target" in the declaration of the real variable "a" (this has been corrected above). In James' words:"Notice that for this to really work, the actual argument, 'a', must be declared with the target attribute. You correctly declare the dummy argument in the assign_pointer routine with the target attribute, but the actual argument must also have that attribute (otherwise it's illegal for any pointer to be associated with it). Just a minor point..."Danger with pointers to pointersWhen creating a hierarchy of pointers to pointers, each level of pointers must be allocated before being used.program maintype mytypereal, dimension(:), pointer :: pend type mytypetype (mytype), pointer :: x! BOTH OF THESE ARE THE WRONG WAY! AND THE COMPILER WON'T CATCH IT! nullify(x%p)! allocate(x%p(5))! ONE SHOULD ALWAYS IMMEDIATELY NULLIFY THE PARENT POINTER! OR ALLOCATE ITnullify(x) ! or allocate(x)...! THEN LATER NULLIFY OR ALLOCATE THE CHILD POINTERcall child_construct(x,5)if (associated(x%p)) print *, x%pcontainssubroutine child_construct(this,len)! child constructor for pointer within mytype! if len is present, then allocate it, otherwise nullify it.! mytype is assumed to be already nullified or allocatedtype (mytype), pointer :: thisinteger, optional, intent(in) :: lenif (.not.associated(x)) allocate(x)if (present(len)) thenallocate(x%p(len))x%p = 0.elsenullify(x%p)endifend subroutine child_constructend program mainExplanationThis example creates a pointer to a pointer to an array of reals where the first pointer has not been allocated. For safety one should always either allocate or nullify the parent pointer immediately after its declaration. The child pointer cannot be allocated before the parent. Since the child pointer may be allocated elsewhere in the code, it is convenient to use constructor routines for this purpose.Each child constructor can safely allocate or nullify its pointers only when it can be sure that its parent's pointers have been allocated or nullified.。