Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29429 Discussions

Exporting Fortran Modules to C# and Returning NaN

Master_Fortran
Beginner
3,901 Views

Dear,

I have 3 Modules in Fortran. Those modules return 3 variables. Let's call them: Modules A, B and C and variables A, B and C.  

I'm exporting the Modules through a DLL to be showed in three diferent TextBoxes in C#.  Module A is independent. Module B calls Module A and Module C calls both Modules A and B.

When I importing those Modules in C# and display the variables A, B and C, what I get is a correct value for variable A in the fisrt TextBox and NaN for variables B and C! (See the attatched figure)

I really don't know I to do now. I get all the right results when I run the code in a main program only in Fortran.

Can somebody help me, please?

Thanks in advance.

 

0 Kudos
9 Replies
DavidWhite
Valued Contributor II
3,901 Views

We really need to see your code to understand what you are doing.

0 Kudos
Master_Fortran
Beginner
3,901 Views

Ok David.

I'm attaching the codes. 3 Modules in Fortran and 1 class in C#.

Is it enough?

Thanks.

0 Kudos
Master_Fortran
Beginner
3,902 Views

Guys,

I discovered that when I fix the value of the variable reyOleo, for example: reyOleo = 4000, it calculates the fatAtrito. However, if reyOleo is calculated, it returns a correct value for reyOleo, but NaN for fatAtrito.

I'm really don't understanding. It seems that C# is not  undestading the follwing peace of code:

reyOleo  = (39370.1/86400.0) * (vazaoOleo * diametroTubo * massaEspecOleo / (viscOleo * areaTubo))

Any clue?

Thanks.

 

0 Kudos
mecej4
Honored Contributor III
3,902 Views

Given a problem description that is imprecise and vague, there may be little that we can do to help you. Try to remember that we are not standing at your shoulder observing all the things that you do. If you are going to do mixed language programming with shared variables, you need a good understanding of the scope of variables, accessibility of variables and the consequences of aliasing.

Nevertheless, I spot one source of trouble: in the Reynol.f90 file, you have module variables with the same names as the formal (dummy) arguments to a contained subprogram. Read the the Fortran documentation as to the implications of doing this, and ask yourself, "what do I want the compiler to do when it sees a reference or an assignment to one of these variables in the subprogram code? Use/update the formal  argument, the module variables, or both? Furthermore,  if the caller also uses the module, you could have two seemingly different variables that are tied to the same memory address, and chaos can follow -- the left hand does not know what the right hand is doing.

Try the following test: add the following lines to reynol.f90, and run the program. You will see that the variable Reyoleo retains the original value of 20000, whereas you might have expected it to have the newly computed value of the actual argument e, which corresponds to the formal argument ReyOleo in the subroutine.

program bugrey
use Reynolds
double precision a,b,c,d,e

ReyOleo = 20000
a=5; b=0.1; c=800; d=10; e=20
call Reynol(a,b,c,d,e)
write(*,*)ReyOleo,e
end program

 

0 Kudos
Master_Fortran
Beginner
3,902 Views

Thank you, mecej4.

I think I got it. I did what you suggested. In Reynol.f90 I have no more module variables with the same name of the dummy arguments.

Now I have different variables in this module with this call:

call Reynol(vazaoOleo_, diametroTubo_, massaEspecOleo_, viscOleo_, reyOleo_)

However, it's resulting in fatrito = 1, i.e, when reyOleo is passed to reyOleo_ , for some reason it assumes a zero value or:(reyOleo_ <= 2100d0).

Jesus, it's not so simple... 

In FatFan.f90 I did:

 module Fatrito

    use Reynolds

    implicit none

    contains
    
    subroutine Fatfan(rugoTubo, fatAtrito)   
    
        !DEC$ ATTRIBUTES DLLEXPORT :: Fatfan
                            
        double precision, intent(in)  :: rugoTubo   
        double precision, intent(out) :: fatAtrito

        double precision :: A1
        double precision :: A2
        
        double precision :: vazaoOleo_, diametroTubo_, massaEspecOleo_, viscOleo_, reyOleo_
        
        call Reynol(vazaoOleo_, diametroTubo_, massaEspecOleo_, viscOleo_, reyOleo_)
        
        if (reyOleo_ <= 2100d0) then
            
            fatAtrito = 1
             
        end if         
        
        if (reyOleo_ >= 4000.d0) then
            
            fatAtrito = 2
            
        end if
            
        if (reyOleo_ >2100d0 .and. reyOleo_ <4000d0) then 
                
            fatAtrito = 3
            
        end if
        
    end subroutine
end module
 module Reynolds
 
    implicit none
    
    contains
 
    subroutine Reynol(vazaoOleo, diametroTubo, massaEspecOleo, viscOleo, reyOleo)
    
        !   ReyOleo = Número de Reynolds do óleo
    
        !DEC$ ATTRIBUTES DLLEXPORT :: Reynol
        
        double precision, intent(in)  :: vazaoOleo, diametroTubo, massaEspecOleo, viscOleo  
        double precision, intent(out) :: reyOleo
    
        double precision :: areaTubo
    
        parameter pi = 3.1415927d0
    
        areaTubo = (pi * diametroTubo **2) / 4
       
        reyOleo  = (39370.1/86400.0) * (vazaoOleo * diametroTubo * massaEspecOleo / (viscOleo * areaTubo))
        
    end subroutine
end module
0 Kudos
mecej4
Honored Contributor III
3,902 Views

It is not worthwhile to mix code fragments that are scattered in the various posts. Please show a complete example and we can look at the problem.

0 Kudos
Master_Fortran
Beginner
3,902 Views

mecej4,

I reproduced this problem in a simpler example of 2 modules. In one I sum two numbers and in the other to get the result of this sum and multiply it for another entry value. For the first module I got the right result, but for the other I had a problem, as you can see below.

 

module SumTwoNumbers
    
    implicit none
    
    contains
    
subroutine SumNumbers(a, b, c)	

	!DEC$ ATTRIBUTES DLLEXPORT :: SumNumbers
    
    ! Declaring variables:
    double precision, intent(in) :: a, b
    double precision, intent(out) :: c
        
    ! Summing two numbers:        
	c = a + b   
    
end subroutine 

end module

module MultiplyNumbers
    
    use SumTwoNumbers
    
    implicit none
    
    contains
    
subroutine MultiNumbers(d, e)	

	!DEC$ ATTRIBUTES DLLEXPORT :: MultiNumbers
    
    !Declaring variables:
    double precision, intent(in) :: d
    double precision, intent(out) :: e
    
    double precision :: a_,b_,c_
    
    call SumNumbers(a_,b_,c_)
    
    !Multiplying numbers:        
    e = c_ * d
    
end subroutine 

end module

 

0 Kudos
FortranFan
Honored Contributor III
3,902 Views

Ewerton C. wrote:

..

..
    
subroutine MultiNumbers(d, e)	

	!DEC$ ATTRIBUTES DLLEXPORT :: MultiNumbers
    
    !Declaring variables:
    double precision, intent(in) :: d
    double precision, intent(out) :: e
    
    double precision :: a_,b_,c_
    
    call SumNumbers(a_,b_,c_)
    
    !Multiplying numbers:        
    e = c_ * d
    
end subroutine 

end module

Amongst other things, in your MultiNumbers procedure, think about where and how the variables a_, b_, and c_ get their values.

0 Kudos
Master_Fortran
Beginner
3,902 Views

It WORKED!

See what I did in module SumTwoNumbers.

Variables a_, b_ and c_  receives a, b and c, respectively. And I declared a_, b_ and c_ globally.

In MultiplyNumbers module, I didn't need to call SumNumbers, just used the USE statement. However, I dont know if it's the only and most appropriate way to pass variables through modules.

module SumTwoNumbers
    
    implicit none
    
    double precision :: a_,b_,c_
    
    contains
    
subroutine SumNumbers(a, b, c)	

	!DEC$ ATTRIBUTES DLLEXPORT :: SumNumbers
    
    ! Declaring variables:
    double precision, intent(in) :: a, b
    double precision, intent(out) :: c
        
    ! Summing two numbers:        
	c = a + b
    
    a_  = a
    b_  = b
    c_  = c
    
end subroutine 

end module


module MultiplyNumbers
    
    use SumTwoNumbers
    
    implicit none
      
    contains
    
subroutine MultiNumbers(d, e)	

	!DEC$ ATTRIBUTES DLLEXPORT :: MultiNumbers
    
    !Declaring variables:
    double precision, intent(in) :: d
    double precision, intent(out) :: e
    
    !Multiplying numbers:        
    e = c_ * d
    
end subroutine 

end module

 

0 Kudos
Reply