From: Friedrich on 19 Jun 2010 18:10 Hello everyone, I'm learning a little bit about organization in fortran, and was wondering, if I could trouble you for a bit of answers on some questions - well, ... advice more, actually. The answers I'll find in a manual, but good experience is hard to come by. The structure of most of my programs (f77 mostly with some f90 newer features) is the main program plus subroutines and functions. No modules, just main program and lot of subroutines (but there are rather a lot of them). If I wished to make, for ease of use, a number of functions for unit conversion (you know, feet to meters, horsepower to kW and so on) what would be the best way to put it so it gets as little in the way in the main program. I thought of the below, but I cannot know will I have any problems with this concept in larger programs. My intent is to use these functions almost like intrinsics, in my main program and functions and subroutines. So far I've mostly relied on parameters and then multiplying where needed, but that gets. I would be grateful, if anyone could put down a quick word of advice. Kind regards, Friedrich module helpful implicit none contains !------------------------------------------------------------------------------- real function degrees(radians) implicit none real, intent(in) :: radians degrees = (360./(2.*3.141592654)) * radians end function degrees !------------------------------------------------------------------------------- real function radians(degrees) implicit none real, intent(in) :: degrees radians = ((2.*3.141592654)/360.) * degrees end function radians !------------------------------------------------------------------------------- end module helpful program test_both_functions use helpful implicit none real :: degs = 30. write(*,'("sin(30) should be = ",f5.2)')sin(radians(degs)) call bla1(sin(radians(degs))) write(*,'("End of program test_both_functions")') end program test_both_functions subroutine bla1(number) real, intent(in) :: number write(*,'("sin(30) should be = ",f5.2)')number end subroutine bla1
From: Arjan on 20 Jun 2010 14:35 Getting organized is a good thing! Like you use "IMPLICIT NONE" to allow for trapping undeclared variables, I would use "PRIVATE" to ensure that only your own exceptions are passed to the outside world via a PUBLIC statement. See sample code below. Then, I would define some code-words for real-valued variables, e.g. "Float", or "R8Kind", see below, to allow for easy switching from one precision to another. Use these types in all further programs, modules, functions and routines. For the names of the conversion routines I would use something like "deg2rad", showing the units of both input and output, and not just "Radians". Furthermore, I would advise to give your parameters names that make sense. I guess that in your code 3.141592654 refers to Pi? Better define Pi once and for all for all of your code and never think of typing in decimals of it ever again! Suppose you have something cyclic going on and after years of running you have used 3.141592654 in one subroutine and 3.14159265 in another. The last digit might wrench your work! In your sample code, there are still many arithmetic operations. Smart compilers will replace these by a single multiplication factor. Still I think I would define such a single multiplication factor myself and use that in my function. Good luck! Arjan MODULE LibUseful ! ! Useful functions and other stuff ! ! Enforce explicit declarations: ! IMPLICIT NONE ! ! Principally everything is LOCAL... ! PRIVATE ! ! ... except for the following [this is the line where you list all that ! should be known to programs and modules that USE this module]: ! PUBLIC :: Float,R8Kind,Pi,Deg2Rad,Rad2Deg,... ! ! From now on only use "REAL(float)" for reals ! ! Number of bytes associated with 6 digits precision: ! INTEGER,PARAMETER :: Float = SELECTED_REAL_KIND(p=6) ! ! The number of bytes associated with 15 digits precision ! INTEGER,PARAMETER :: R8Kind = SELECTED_REAL_KIND(p=15) ! ! And why on earth does FORTRAN not have PI ????? ! REAL(Float),PARAMETER :: Pi = 3.1415926535897932384626433832795_Float ! ! Below this line you'll get the real implementations ! CONTAINS REAL(Float) FUNCTION Deg2Rad(x) ! ! Convert degrees to radians ! REAL(Float), INTENT(IN) :: x REAL(Float), PARAMETER :: c = Pi/180._Float Deg2Rad = c*x END FUNCTION Deg2Rad REAL(Float) FUNCTION Rad2Deg(x) ! ! Convert radians to degrees ! REAL(Float), INTENT(IN) :: x REAL(Float), PARAMETER :: c = 180._Float/Pi Rad2Deg = c*x END FUNCTION Rad2Deg
From: Dave Flower on 21 Jun 2010 04:41 On Jun 19, 11:10 pm, Friedrich <friedrich.schwa...(a)wahoo.with.a.y.com> wrote: > Hello everyone, > > I'm learning a little bit about organization in fortran, > and was wondering, if I could trouble you for a bit of answers on some > questions - well, ... advice more, actually. The answers I'll find in > a manual, but good experience is hard to come by. > > The structure of most of my programs (f77 mostly with some f90 newer > features) is the main program plus subroutines and functions. No > modules, just main program and lot of subroutines (but there are > rather a lot of them). > > If I wished to make, for ease of use, a number of functions for unit > conversion (you know, feet to meters, horsepower to kW and so on) what > would be the best way to put it so it gets as little in the way in the > main program. > > I thought of the below, but I cannot know will I have any problems > with this concept in larger programs. My intent is to use these > functions almost like intrinsics, in my main program and functions and > subroutines. > > So far I've mostly relied on parameters and then multiplying where > needed, but that gets. > > I would be grateful, if anyone could put down a quick word of advice. > > Kind regards, > Friedrich > > module helpful > implicit none > > contains > !------------------------------------------------------------------------------- > real function degrees(radians) > implicit none > > real, intent(in) :: radians > > degrees = (360./(2.*3.141592654)) * radians > end function degrees > !------------------------------------------------------------------------------- > real function radians(degrees) > implicit none > > real, intent(in) :: degrees > > radians = ((2.*3.141592654)/360.) * degrees > end function radians > !------------------------------------------------------------------------------- > end module helpful > > program test_both_functions > use helpful > implicit none > > real :: degs = 30. > write(*,'("sin(30) should be = ",f5.2)')sin(radians(degs)) > > call bla1(sin(radians(degs))) > > write(*,'("End of program test_both_functions")') > end program test_both_functions > > subroutine bla1(number) > real, intent(in) :: number > write(*,'("sin(30) should be = ",f5.2)')number > end subroutine bla1 Might I suggest a naming convention that worked well in practice. Add a suffix so that variables take the form: Angle_Deg So that we may write code of the form: Angle_Rad = RadPDeg ( Angle_Deg ) (The 'P' isn short for Per) The advantage of this system is that it is very easy to check. (LHS- Rad;RHS:(Rad/Deg).Rad=Rad) Dave Flower
From: Paul van Delst on 24 Jun 2010 11:39 Also, I would recommend making these sorts of simple, but very useful, procedures ELEMENTAL. I know the OP only mentioned f90, but he should be using at least f95 (if not f2003 if fully-compliant compilers *ever* become widely available). cheers, paulv Arjan wrote: > Getting organized is a good thing! > > Like you use "IMPLICIT NONE" to allow for trapping undeclared > variables, I would use "PRIVATE" to ensure that only your own > exceptions are passed to the outside world via a PUBLIC statement. See > sample code below. > > Then, I would define some code-words for real-valued variables, e.g. > "Float", or "R8Kind", see below, to allow for easy switching from one > precision to another. Use these types in all further programs, > modules, functions and routines. > > For the names of the conversion routines I would use something like > "deg2rad", showing the units of both input and output, and not just > "Radians". Furthermore, I would advise to give your parameters names > that make sense. I guess that in your code 3.141592654 refers to Pi? > Better define Pi once and for all for all of your code and never think > of typing in decimals of it ever again! Suppose you have something > cyclic going on and after years of running you have used 3.141592654 > in one subroutine and 3.14159265 in another. The last digit might > wrench your work! > > In your sample code, there are still many arithmetic operations. Smart > compilers will replace these by a single multiplication factor. Still > I think I would define such a single multiplication factor myself and > use that in my function. > > Good luck! > > > Arjan > > > MODULE LibUseful > ! > ! Useful functions and other stuff > ! > ! Enforce explicit declarations: > ! > IMPLICIT NONE > ! > ! Principally everything is LOCAL... > ! > PRIVATE > ! > ! ... except for the following [this is the line where you list all > that > ! should be known to programs and modules that USE this module]: > ! > PUBLIC :: Float,R8Kind,Pi,Deg2Rad,Rad2Deg,... > ! > ! From now on only use "REAL(float)" for reals > ! > ! Number of bytes associated with 6 digits precision: > ! > INTEGER,PARAMETER :: Float = SELECTED_REAL_KIND(p=6) > ! > ! The number of bytes associated with 15 digits precision > ! > INTEGER,PARAMETER :: R8Kind = SELECTED_REAL_KIND(p=15) > ! > ! And why on earth does FORTRAN not have PI ????? > ! > REAL(Float),PARAMETER :: Pi = > 3.1415926535897932384626433832795_Float > ! > ! Below this line you'll get the real implementations > ! > CONTAINS > > REAL(Float) FUNCTION Deg2Rad(x) > ! > ! Convert degrees to radians > ! > REAL(Float), INTENT(IN) :: x > REAL(Float), PARAMETER :: c = Pi/180._Float > Deg2Rad = c*x > END FUNCTION Deg2Rad > > > REAL(Float) FUNCTION Rad2Deg(x) > ! > ! Convert radians to degrees > ! > REAL(Float), INTENT(IN) :: x > REAL(Float), PARAMETER :: c = 180._Float/Pi > Rad2Deg = c*x > END FUNCTION Rad2Deg >
|
Pages: 1 Prev: Functions with side effects in I/O list Next: F2003's get_command_argument() intrinsic |