I’m writing a program in Fortran 90 that computes a solution to a problem. I have the following problem: In order to solve this problem I have to set some initial values for x.
Compute y=g(x)
Then solve for the z satisfying 0=F(z,y) (i.e., I’m implicity solving for z as a function of y z=Z(y) at a particular value of this seconf argument)
My problem is that to do this I need to use some 3rd party software. This third party software (I’m using IMSL, but the same is true of the minpack routine it’s based on) will only solve functions of z only. This is presenting me a problem as I need to compute y in the main program. I'm trying to figure out the best practice for dealing with global variables. My thoughts are the following:
Program Main
Use mod_passer
Use mod_Fcn
Use librarycontainingsolver
IMPLICIT NONE
Real, parameter :: x
real :: y, z, Fval
!compute the y
y=x**2 !for example
call set_y(y)
call solver(z,Fcn)
end program
!solver takes arguments solver(solution, function name, function value) where the function is !subroutine(a,function value) i.e. takes a and returns function value
And have two seperate modules
Module mod_passer
Implicit none
Real :: param
Contains
subroutine set_y(y)
implicit none
Real, intent(in) ::y
Param=y
End subroutine
End module mod_passer
With the second below
Module mod_Fcn
Use mod_passer param only
Implicit none
Contains
Subroutine Fcn(a, f_a)
!calculates f_a=Fcn(a,Param)
Real, Intent(in) :: a
Real, Intent(out)::f_a
F_a=a**(3*Param)
End subroutine
End module mod_Fcn
This seems like one approach I could take, but it seems awfully clunky. In principle what I need to do is take my solution, perform some operations on it and use that to parameterise another function in some other variables and do this a number of times for a number of ways. Which is why I’m sort of wedded to the idea of global variables and don’t want to declare the y=x**2 equivalent in a module of parameters. Particularly as I may need to recalculate y and repeat the idea of above.
At least this way I can identify the points at which I effectively pass the values to global variables instead of just using param and assigning it in an equals statement. (It's also possible that I've completely missunderstood something fundamental.
I’ve said Fortran 90, but I guess that if I used 2003 I could declare param as protected to avoid any accidents (which seems sensible as it atleast should generate a compile error if I try to do something stupid)? I’m at a loss for a sensible way to do this, that doesn’t involve making this sort of procedure over and over again.
I’m sorry that I haven’t provided a complete working example, but that would involve specifying a solver etc. (also technically I’d want my function to have an extra parameter for the length of a the input array) The above is my best attempt at coming up with a solution and is inspired by something mentioned in answer to Protected global variables in Fortran. In reality the functions are much more complicated than inlcuded above, but I thought this might get the ball rolling. In case it’s needed, I’m using intel ifort to compile.
An alternative might be to build the subroutine in question as contained in the main program. I have some reservations about using the scope like that, plus it seems (for reasons of length and more) a very inelegant solution. Any help would be great. Feel free to tell me there is no better alternative. I hope everything above is clear.
EDIT: I've just realised I missed something! How do I get around the need to know the dimensions of y at the time of compiling the module mod_passer? That's the big downside to this approach