I want to do something like this:
main.f90 uses module A and module B.
module_A.f90 is independent.
module_B.f90 uses module A.
My code is like this:
main.f90
include "module_A.f90"
include "module_B.f90"
program MAIN
use A
use B
write(*,*) Array(I)
end program MAIN
module_A.f90
module A
integer, parameter :: I = 10
end
module_B.f90
include "module_A.f90"
module B
use A
real*8 :: Array(I)=1d0
end module B
However, the error information shows:
Error: module_A name 'module_A' at (1) is already being used as a MODULE at (2)
It seems that I can't use a module to cite another module.
Is there any way to solve this problem?
(Note: it is not the problem of missing "contains" because it doesn't involve subroutine or function)
The problem
when you included modA.f90 and modB.f90 in main.f90, since you already included modA.90 in modB.90, then your main.f90 look like this:
module modA
...
end module
module modA
...
end module
module modB
use mod A
...
end module
program
...
end program
Since in fortran you can't have two unitwith the same name, the compiler fails with the error you see because you declared two module modA.
Fixing with use statement (recommended)
modA.f90
module modA.f90
...
end module
modB.90
module modB
use modA
...
end module
main.f90
program main
use modB
use modA
...
end program
However usestatement needs to deals with dependencies, so modA.90 must be compiled before modB.f90
gfortran -o main modA.f90 modB.90 main.f90
Fixing with include statement (depreciated)
I do not recommend this solution, but for the sake of completness, it is provided.
First answer
modA.f90
module modA.f90
...
end module
modB.90
module modB
use modA
...
end module
main.f90
include modA.f90
include modB.f90
program main
use modB
use modA
...
end program
In this case, since include is like copy-pasting, we only need to compile the program
gfortran -o main main.f90
Second answer
modA.f90
module modA.f90
...
end module
modB.90
include modA.f90
module modB
use modA
...
end module
Since modA is already included, no need to do it again
main.f90
include modB.f90
program main
use modB
use modA
...
end program
Again we only need to compile the program
gfortran -o main main.f90
Related
I'm having trouble trying to compile a simple fortran program which uses a module in the same directory.
I have 2 files: test1.f90 which contains the program and modtest.f90 which contains the module.
This is test1.f90:
program test
use modtest
implicit none
print*,a
end program test
This is modtest.f90:
module modtest
implicit none
save
integer :: a = 1
end module modtest
Both files are in the same directory. I compile modtest.f90 and test.f90 like this:
gfortran -c modtest.f90
gfortran -o test1 test1.f90
But then I get this error:
/tmp/cckqu8c3.o: In function `MAIN__':
test1.f90:(.text+0x50): undefined reference to `__modtest_MOD_a'
collect2: ld returned 1 exit status
Is there something I'm missing?
Thanks for the help
What you're doing is not telling the linker where reference module modtest is so that the your code can use its contents.
This should work:
gfortran -o test1 test1.f90 modtest.o
Some context:
The -o option tells the compiler to put the output of the full build (compile + link) into a program called test1. Then we supply a file that we are to compile (test1.f90). Finally we are telling the compiler to consider a file that contains the compiled output of another build (modtest.o) and to link this to the compiled output of test1.f90, and use the contents of modtest.o when trying to sort out references within the test1.f90 that reference the module modtest (in the statement use modtest in the source code).
So the statement says:
Please compile and subsequently link test1.f90 to modtest.o, and produce a file called test1 as the final output.
I have 3 modules (in free form .f90 format) which are being called from inside of UMAT subroutine, such as:
module module_A
use module_C
use module_B
....
end module_A
module module_B
use module_C
....
end module_B
module module_C
....
end module_C
subroutine UMAT(STRESS,...)
....
Here the subroutines from module_A and module_B are being called
...
end subroutine UMAT
Now, my question is what should be the appropriate format of writing these modules with UMAT subroutine? How to merge different module files into a single *.for file (free format)?
If I understand correctly you have multiple source files that you want to compile for your UMAT. Since the built-in Abaqus make utility only takes one file you can use an INCLUDE statement to tell the Fortran compiler to include other source files in the main source file. So let's say you have four files: module_A.for, module_B.for, module_C.for and umat.for. umat.for should contain some INCLUDE statements at the top:
INCLUDE 'module_C.for'
INCLUDE 'module_B.for'
INCLUDE 'module_A.for'
SUBROUTINE UMAT(... umat args ...)
USE module_A
ENDSUBROUTINE UMAT
Make sure all of the *.for files are in the same directory so the compiler can easily find them. When the compiler encounters an INCLUDE it will read the referenced source file and continue compiling as if it's contents were directly in the umat.for source file, and then return to compiling umat.for.
Assume I have two Fortran modules called modA and modB. Is there a way to use one or the other in a program based on a conditional statement? Does this require some type of preprocessing? For example, I want to be able to do something like the following code:
if (condition)
use modA
else
use modB
end
I am using the GNU Fortran compiler.
Yes, you must do some kind of preprocessing. The most common is the C preprocessor included in GNU Fortran.
#if (condition)
use modA
#else
use modB
#endif
The preprocessor does not understand your Fortran code, it is only a text for it. It has it's own set of directives and it's own set of variables. Only the preprocessor variables can be used in the condition, not your Fortran variables.
Another common directive is #ifdef which is a variant of #if defined. See the manual for more https://gcc.gnu.org/onlinedocs/cpp/Traditional-Mode.html (gfortran runs the preprocessor in the traditional mode).
To enable the preprocessor use the -cpp flag or in Unix you can use capital F in the file suffix.
I have a project that uses fruit for testing (fortran code).
This is my code.
calculator.f90
module calculator
implicit none
contains
subroutine add (a, b, output)
integer, intent(in) :: a, b
integer, intent(out):: output
output = a+b
end subroutine add
end module calculator
And my test calculator_test.f90
module calculator_test
use fruit
contains
subroutine test_5_2_2
use calculator, only: add
integer :: result
call add(2,2,result)
call assertEquals(4,result)
end subroutine test_5_2_2
subroutine test_5_2_3
use calculator, only: add
integer :: result
call add(2,3,result)
call assertEquals(5,result)
end subroutine test_5_2_3
end module
Now I'd like to use Cmake to build and run my tests (triggered by jenkins), so my question is: Do I need to change the tests or is it possible to just run the test I've written through cmake, and if so how?
I've searched a lot online but all testing with cmake seems to be done with c++ and then by using executeable testfiles files.
Thanks!
-Minde
You can run the tests you have written as is, you just need to tell CMake how to run them. This is what the COMMAND argument to ADD_TEST is for.
ENABLE_TESTING()
ADD_TEST(NAME "YourTest"
WORKING_DIRECTORY ${TEST_DIRECTORY}
COMMAND ${TEST_DIRECTORY}/test_dim)
Usually, you see some example like the one above, where the command is an executable (as you have seen in c++ examples). But it doesn't have to be. For example, I am running python tests through CMake, and I add the test like so:
ADD_TEST(NAME PythonTests
WORKING_DIRECTORY ${TEST_DIRECTORY}
COMMAND ${PYTHON_EXECUTABLE} setup.py test
So, to run your Fruit tests, you would call the command that creates the Fruit test runner for you (I believe it is a rake command... I will assume this is true below, but you should substitute for whatever you actually call on the command line to run your tests):
ADD_TEST(NAME FruitTests
WORKING_DIRECTORY ${TEST_DIRECTORY}
COMMAND rake test) # Or whatever the command is.
When you run make test on the command line, it should tell you if "FruitTests" failed or succeeded.
A word of caution CMake determines the success or failure of the test by the exit code of the program. By default Fortran programs do not have a exit code (or if they do, it is always 0). When I use Fruit and CMake to do my Fortran tests, I write the test runner myself and use the call exit(exit_code) builtin subroutine to make sure an exit code is returned to CMake. I am not sure if Fruit's automatic test runner creator does this; you will have to verify this yourself.
In summary, is it possible to access via use association a preprocessor directive defined in a Fortran module?
Context
I use preprocessor statements to define subroutines to print warning and error messages. For example, I use the following module/subroutine, in the file errors.f, to print warning messages
module errors
use, intrinsic :: iso_fortran_env, only : error_unit=>stderr
implicit none
contains
!> Print formatted warning message.
subroutine warn_print( file, line, mesg )
implicit none
character(len=*), intent(in) :: file
integer, intent(in) :: line
character(len=*), intent(in) :: mesg
write(stderr,'(a,a,a,i4,a,a)') "WARNING::", file, ":", line, ": ", mesg
end subroutine warn_print
end module errors
and, in a separate file errors.h, I use the above module and define a preprocessor macro
use errors
#define warn( text )warn_print(__FILE__,__LINE__,text)
I then #include the file errors.h in whichever file/module I wish to use the warning print routine which allows me to simply write
call warn("Some warning message")
and the compiler will automatically include the file and line number at which the warning message was called.
Question
The use of #include 'errors.h' is rather idiosyncratic in Fortran code and it hides the use of the errors module. Ideally I would prefer to define the above preprocessor in the errors module itself. However, then when using that module, this preprocessor directive is not available to the program/module which uses this module.
Is there a way to make a preprocessor directive accessible via use association?
The only other way I can think of doing it is to just have the errors module and define the preprocessor directive in my call to the compiler (using, for example, the -D flag with ifort). Any suggestions for any alternative way of achieving the above would be greatly appreciated.
No, it is simply not possible, since the preprocessing and the compilation stages are completely separate one from each other and the C preprocessor does not know anything about the Fortran USE statement.
I use to #include 'config.h' (from autoconf) in most of my .F90 sources, without problems.
This may not be what you are looking for, but if you are using ifort, you can use traceback functionality to achieve something similar (a bit more powerful, but also more ugly), e.g.
program tracetest
call sub(5)
write(*,*) '=== DONE ==='
end program tracetest
subroutine sub(n)
use ifcore
integer :: n
character(len=60) :: str
write(str,*) '=== TROUBLE DETECTED: n =',n ! code -1 means "do not abort"
call tracebackqq(str,-1)
end subroutine sub
Then, compile with -traceback to see the source file, line, and stack trace. The stack trace and line may be obscured because of inlining; to avoid that, you can specify -traceback -O0 to get smth like this:
=== TROUBLE DETECTED: n = 5
Image PC Routine Line Source
a.out 0000000000473D0D Unknown Unknown Unknown
a.out 0000000000472815 Unknown Unknown Unknown
a.out 0000000000423260 Unknown Unknown Unknown
a.out 0000000000404BD6 Unknown Unknown Unknown
a.out 0000000000402C14 sub_ 12 tracetest.f90
a.out 0000000000402B18 MAIN__ 2 tracetest.f90
a.out 0000000000402ADC Unknown Unknown Unknown
libc.so.6 000000323201EC5D Unknown Unknown Unknown
a.out 00000000004029D9 Unknown Unknown Unknown
=== DONE ===
Alternatively, if want to keep the optimizations, and also want to see the correct line (12), you can compile with (for example) -fast -traceback -debug all,inline_debug_info. Something similar may be available in other compilers, but I am not sure.