Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
The Intel sign-in experience is changing in February to support enhanced security controls. If you sign in, click here for more information.

Operator Overloading

Paul_Dent
New Contributor I
321 Views
C*************************************
	MODULE CHAIN_MATRIX
C*************************************
	TYPE TWOPORT
	COMPLEX A(2,2)
	END TYPE TWOPORT
	INTERFACE OPERATOR(*)
	MODULE PROCEDURE MUL2PORT
	END INTERFACE
C*************************************
	CONTAINS
C*************************************
	FUNCTION MUL2PORT(A,B) RESULT (C)
	TYPE (TWOPORT), INTENT(IN) :: A,B
	TYPE (TWOPORT)::C
	CALL CMATMUL2X2(A%A,B%A,C%A)
	END FUNCTION MUL2PORT
C*************************************
	END MODULE CHAIN_MATRIX
c*************************************

filter.JPG

 

 

 

Recently a radio ham friend of mine wanted a filter for an amateur repeater.  I came up with the above circuit and wanted to plot its frequency response. I thought: " This might be a good candidate to try to finally get operator overloading to work".  I had never any success before due to lack of documentation. But I searched this forum for "Operator Overloading" and found an excellent post by David Car on the subject in 2010, which finally got me into business.   I post what I made work here in case it would be of assistance to others.

The above circuit is a cascade of elements, each of which can be represent by a 2-port "Chain Matrix" which is 2 x 2 complex.  The useful feature of chain matrices is that, for cascaded elements, you just multiply them in order to get the overall matrix.

So I wanted to define a derived type "chain matrix" and then use *  to multiply them.

Thanks to David Car's post, it worked for me so that the key  line of code for the above filter boiled down to the single line:

 

Filter=SeriesR(Rsource)*Stub(stublength,Gamma)*Txline(Length,Gamma)*Stub(stublength,Gamma)*ShuntR(Rload)

 

where all of the functions return the derived type , and their sequence of products  mirrors the network exactly, which is nice. Now I can simulate any cascade of components !

The code to define the type and do operator overloading of the * operator follows David Car's structure as shown in the code at the beginning.

 

Here are some puzzles I had not found the answer to in years before trying David Car's code:

1. Where and in how many places does the declaration of the derived type have to occur? Normally it has to be repeated in every routine that uses it. But note in the above code module it is not and  MUST not be included in the body of the function, otherwise you get a "double definition" error.

2. Where does the Module have to located relative to the main program. By trial and error I found it can be a separate file in the project, which the compiler finds automatically That is nice that it doesn't have to clutter the main program. 

3. Much information on operator overloading that you find by Googling suggests that you also have to overload the = sign, and that is done differently because it is not considered a binary operator. Apparently though, I did not need to redefine the = operator, which is nice. (Do you ever have to in Intel Fortran?)

So it would be good if there was a whole chapter written somewhere in the support documentation on operator overloading for derived types, with tested examples. That would help people get started a lot quicker. If it exists, I never succeeded to locate it !

 

Paul

 

0 Kudos
1 Reply
Steve_Lionel
Black Belt Retired Employee
241 Views

1. The derived type should be defined in a module, which can be (and generally should be) a separate file. Any operators you define would also be defined in that module - just the way you have it. So, I am confused why you are asking. Define the module once and USE it where needed.

2. The module needs to be compiled before any uses. Best practice is to put it in a separate file. Assuming you are using Visual Studio, the build system will give the correct compile order.

3. You don't have to overload assignment if you don't want to. Intrinsic (built-in) assignment of derived types will just copy each component.

Some documentation: 

Defining Generic Operators (intel.com) 

Defining Generic Assignment (intel.com)

Reply