error #5415

error #5415

I'm very frustrated by this error. Not only is it a feature for Fortran 2003 and it is 2014, but it keeps me from being able to file read using namelist for a derived type that contains any allocatable elements or types containing allocatable elements even if I'm not assigning anything to those fields in the namelist read.

Is there a workaround/fix other than creating a second type without the allocatable elements and transferring them post-read?

22 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Zitat:

Tripp L. schrieb:

I'm very frustrated by this error. Not only is it a feature for Fortran 2003 and it is 2014, but it keeps me from being able to ...

What is it that you say "is a feature for Fortran 2003"? Surely not Error #5415, as you seem to think?

If, on the other hand, the error message is emitted when the compiler cannot digest a feature of Fortran 2003 that you have in your code but is not yet implemented in the compiler, the situation is understandable. Intel Fortran does not yet implement Fortran 2003 in its entirety.

In your position, I should prefer to see the compiler state up-front that it does not understand the section of code, rather than have the compiler silently producing incorrect object code and leave to me the unpleasant task of investigating mysterious run time errors.

Knowing and working within the limits of one's compiler is a fact of life.

 

Mecej4,

The exact error message is "error #5415: Feature not yet implemented: Allocatable or pointer fields require user-defined derived-type I/O procedure.", so yes surely it is error #5415 as I seem to think. It occurs when you try to read from a file using namelist containing a derived-type that has a field that is allocatable. The compiler doesn't have this feature yet, as it says in the error message.

I'm unsure of the reason you posted. You did not answer my question, and simply posted some pseudo-sage advice.

"Knowing and working within the limits of one's compiler is a fact of life."

I suppose that statement is true, but I have used many languages in my few years on this earth and the Intel Fortran compiler is the most expensive, and gives me the most problems. I've never been working on something in javascript, C#, visual basic, java, python, or perl and had the compiler just not do what the language specifications say it can do. I understand it takes a couple years sometimes to add in new features of a language when a major update is issued, but it has been over a decade and another major release has since come and gone. I wouldn't be using the Intel Fortran compiler if it were up to me, but we live in an imperfect world and I must. I accept that; however, that does not mean that I should hold my tongue when I see what I feel is a real issue. A compiler failing to implement features that are over a decade old and charging over a grand for a license is just absurd. Not only that but the documentation on Fortran in general is pitiful at best, and the Intel Fortran documentation is even worse unless there is some hidden document I have been unable to acquire.

Now if you have a solution to my question I would love to know, but don't act like I have no idea what I'm talking about.

Error 5415 is a catch-all for unimplemented features, as https://software.intel.com/en-us/articles/fdiag5415/ says. Therefore, the number 5415 does not suffice to pin down the specific feature that you used, which is the reason that I asked what feature you needed.

Intel is responsive to user input regarding how to prioritize the addition of new language features to the compiler. You could, if you choose, submit a write-up in which you advance arguments and make a case for this particular feature (namelist I/O with derived type variables containing allocatable components) to be added.

Where can I submit a write up? I'll add that an error number should be unique to the error it encounters, to my list of suggestions.

I have found that here are a lot of quite helpful people in this Forum but it is difficult to think of a workaround without seeing some specific example of what you are trying to do. Perhaps making the assignments with a function that does the read and a bit of data structure manipulation might be a way. Is is one particular read or do you have lots of them that are all a bit different?

F2003 was a massive step and if you look at what other compilers do all have some deficiency in this department when I last looked. You identify issues with Intel Fortran on the grounds features, documentation and cost, so as a matter of interest why do you use Intel Fortran rather than one of the alternatives? 

 

I had considered writing my own read function, and might should in the future, but I have been trying to avoid doing that since using namelist does almost everything I want (except automatically allocate arrays). Fortran just doesn't have particularly strong native string manipulation, and I have a long list of features I need to add to my project.

The company I work for decided to use Intel Visual Fortran, and Fortran in general for that matter. I've been pleasantly surprised by Fortran as a language since using it. It does a lot of things that other languages have trouble with very easily, but it does have it's pitfalls. The code itself is classified, and the compiler is on a classified machine so putting up an example is difficult. But basically I have a file of about 20-30 fields, potentially multiple times, that need to be assigned to a derived type that has allocatable fields in addition to the fields being input from the file. I'm trying to avoid making multiple versions of the derived types if possible.

It looks something like the following (disclaimer: code was written without a compiler):
 

Type car_T

  integer :: x, y, z
  real :: a, b, c

  type(Tires_T) :: currentTires
  type(Tires_T), dimension(5) :: potentialTires

  type(owner_T), dimension(:), allocatable :: owners

End Type car_T

function initCars(fileName1, fileName2) result(cars)

  !input
  character*(*), intent(in) :: fileName1, fileName2

  !output
  type(Car_T), dimension(:), allocatable :: cars

  !local
  integer :: carsLength
  character*(50), dimension(:), allocatable :: carsModels
  type(Car_T) :: car

  if(allocated(cars)) then
    deallocate(cars)
  end if

  namelist /nml_length/ carsLength
  namelist /nml_carModels/ carModels
  namelist /nml_Car/ car

  open(1, file=fileName1, status='old')
  read(1, nml=nml_length)
  close(1)

  allocate(cars(carsLength))
  allocate(carModels(carsLength))

  open(2, file=fileName2, status='old')
  read(2, nml=nml_carModels)
  close(2)

  do i=1, carsLength
    open(3, file=carModels(i), status='old')
    read(3, nml=nml_Car)
    close(3)
    cars(i) = car
  end do
end function initCars

where fileName1 contains an integer

fileName2 contains a list of fileNames

carModels(i) containts :

&nml_Car
  car%a = 2.9
  car%b = 3.2
  car%c = 7.4

  car%x = 6
  car%y = 1
  car%z = 80

  potentialTires(1)%size = 60
  potentialTires(1)%name = "someTire"

  potentialTires(2)%size = 24
  potentialTires(2)%name = "teenyTire"

  potentialTires(3)%size = 67
  potentialTires(3)%name = "anotherTire"

  potentialTires(4)%size = 44
  potentialTires(4)%name = "smallTire"

  potentialTires(5)%size = 99
  potentialTires(5)%name = "bigTire"

/

 

Tripp,

It seems like your issue may be related to this thread, https://software.intel.com/en-us/forums/topic/269585, over at the Intel Fortran Linux forum.  You did make one comment there.  The last comment was by Steve Lionel from Intel who thought there was some bug in their implementation.  Have you followed up with Steve about this?

I don't use NAMELIST much and I've not studied what Fortran 2003 offers in terms of NAMELIST I/O and derived-types with allocatable components.  So I don't know much other than the fact there are some restrictions with memory allocation of derived-type components.

However, there is Intel Composer 2015 Beta evaluation underway which, per comments by Steve and others at Intel, includes a Fortran compiler version that has close to complete implementation of Fortran 2003 features (if not fully-compliant with 2003 standard).  If you are not already signed up for beta-testing this version, you may want to consider getting an evaluation copy.

Separately, it will help if you post a simple namelist I/O example involving derived types and allocatable components that you think should be supported by the Fortran 2003 standard.  Forum readers can then review this example vis-a-vis the standard as well as how Intel Fortran 2015 Beta compiler version treats such code and offer their analysis.  You can then take the findings and apply them in your actual code.

 

I appreciate it. I'll look into those options.

It is discouraging though because I doubt my employer will want to buy a new license so soon after purchasing the 2013 copy I am currently using.

Zitat:

Tripp L. schrieb:
It is discouraging though because I doubt my employer will want to buy a new license so soon after purchasing the 2013 copy I am currently using.

You can get a license for the 2015 beta gratis (I am not certain if this is still true in July. Please try https://softwareproductsurvey.intel.com/survey/150347/2afa/ ). All that you have to do is request a license and register as a tester of the beta version.

In fact, if you post complete source code (the part that you posted above is missing declarations of types Tyres_T and Owner_T), one of the readers here would probably try their 2015 beta compiler on it. 

Yes, I understand that; however, the beta key ceases to work in September from my understanding of what I read on the beta key page. Am I mistaken?

You are not mistaken about the short term nature of the beta license. However, trying the beta on your code would let you verify if the new feature matches your requirements, and enable your company to make a better assessment of whether paying for upgrading to the 2015 release is justified.

I've already almost implemented my original idea for a work around in the time this conversation has taken place. Even if it adds that feature is not worthwhile, for the cost. The entire point of this post was to comment that I shouldn't have had to find a workaround, and to ask if anyone knew a better solution that what I had already come up with. One person suggested I write my own read function which I already knew I could do from the error message that started this whole thread. Other than that I have not been given any sort of solution other than to find out if the new version supports the F2003 feature.

I do not think that you have given us enough information to elicit "solutions". For instance, the allocatable component owners of car_t is never used. Therefore, we have to simply accept your claim as to the need for that component and the need for it to be allocatable.

Not knowing what it is needed for, and having doubts as to its being needed, I do not think that it is useful for me to attempt to "solve" a problem for which I have not yet seen a complete description.

Intel software licenses don't expire with the version you first licensed; they expire annually (unless you are on enterprise license).  If your production ifort license or renewal extends beyond September, it will cover the 15.0 release version.

I totally agree with mecej4's comments, especially those in Quotes #12 and #13.

Tripp,

AGAIN it'll be good if you can offer a specific example.  Your position that you're trying something that you believe to be standard Fortran 2003 but that Intel Fortran compiler 13 fails to accept it as such and wrongly gives an error #5415 is simply untenable unless you can show some actual code.

In your partial, uncompiled example in Quote #7, it'd appear there is at least one problem at line 47: the owners component of the variable car of type car_T will be undefined and I don't think the standard permits the I/O statement to function under such circumstances.  But again you're only showing pseudo-code, so it may not match the actual situation.  Can you confirm you've gone through documentation such as this: https://software.intel.com/en-us/node/511133?

 

Tim Prince,

Thank you. That is helpful. I will check with my IT department and see what our licenses allow for.

FortranFan, Mecej4:

I know owners is not used in the example code. That is the point. Trust me the allocatable aspect of it is a requirement. The actual code is actually a derived-type with multiple allocatable arrays within it. These lengths will not be known before the code starts, nor are they necessarily all known during the initialization process. I know I could make the arrays comprehensively large and then have checks to determine how far they are filled, but this is bad coding. I could also create non-allocatable versions of the types and then transfer them but that is really just moving the problem.

As far as writing executable code. I do not have access to a compiler on my unclassified machine and I cannot copy code from the classified one.

Also, I never said it was erroneously giving me an error. I am aware that the compiler does not support this method, hence why I am on this forum looking for an alternative solution that doesn't leave a bad taste in my mouth. I believe the answer to my question from the information I have gathered here, is that if I want a good solution I need to write my own file parsing function that will not get upset when dealing with allocatable arrays.

I definitely cannot say that I have read all of the documentation on the Intel Fortran compiler. I will read through the link that was sent though. Thank you.

Unfortunately my company does not have a license that allows upgrading.

@Tripp L. With many licences I believe installing on more than one PC e.g. desktop & laptop is OK so long as you are only using one of them at any time which might be a solution to the  unclassified machine problem. 

In response to the original problem it suggests to me that at the design stage the derived type might have been better having some fields that tracked the size of the record so you could have a partial read and then do a full read of the record knowing its content sizes....

User-defined derived type I/O is in the 14.0 (2013 SP1) compiler. I don't think the Linux forum thread linked by mecej4 is relevant. I'm home right now and can't access our internal database, but I think we missed implementing NAMELIST and user-defined I/O in the 14.0 compiler. It is supported in the 15.0 compiler.

Yes, it is 2014 and the number of compilers with full F2003 support can be counted on your thumbs - there are two, Cray and IBM, though Intel and PGI are close. It is for this reason that the Fortran standards committee chose to dramatically slow down the introduction of new features in the standard so that implementors have a chance to catch up.

Steve - Intel Developer Support

The 14.0 compiler appears to support it here.  That said (and noting that I don't use namelist - I think it is an anachronism that inappropriately exposes internal implementation - so the potential for misunderstanding on my part is high) I don't think the way the language specifies how UDDTIO works will suit the OP here.

To the OP - there are multiple ways that the extended data associated with pointer and allocatable components could be represented in text (in the case of pointer components there's also the question of whether the component has value or reference semantics) and the choices for some of those representations might also involve or influence the representation for other simple components.  Consequently it looks like the language has made a design decision that the representation for such objects needs to be provided by a user defined procedure, and that procedure has to provide the representation (and be able to read the representation - which if you use the namelist format is not going to be trivial) for the entire object.  So you are going to have to write your own parsing procedure anyway - all that the "missing" language feature provides is some syntactic nicety and integration convenience.

A better arrangement for you may be to split the type definition into a parent object that has all the simple components that can be easily defined by namelist, with the allocatable and pointer components going into an extension of that parent.  You can the use a namelist object that is a pointer of the parent type to reference the parent component of the extension for input and output.  The amount of code duplication associated with this is pretty minimal.  An example attached.

(The 14.0/15.0 compilers appear to incorrectly complain about an assumed shape array as a namelist object (calling it an assumed size array in the error message) - i.e. `SUBROUTINE proc(arg) ; INTEGER, INTENT(IN) :: arg(:) ; NAMELIST /nml/ arg ; END` )

Attachments: 

AttachmentSize
Download 2014-07-10 cars.f904.13 KB

It sounds like the OP wants a magic solution where he can perform:

OPEN(someFileOfUnknownLayout)
READ(saidFile) IntoGenericObject

And do so without writing import code (User defined type I/O).

Once ingested, I would imagine the OP wants magic operators without writing the operator code.

I might suggest that the OP look at using a library such as HDF5 (http://www.hdfgroup.org/HDF5/), or any or the XML parser libraries. These may still require user defined type I/O if he does not want to use the library's get and put routines (performance).

A simpler method would be to consider an INI file processor (http://www.fortranlib.com/iniFile.for):

C PARSER - parse an ini file
C     V1.0 6 AUG 03
C     Written by Douglas S. Elder elderdo@yahoo.com

C** common block that will contain the iniFile
      BLOCK DATA iniFile
      LOGICAL initialized
      INTEGER CNT
      CHARACTER LINES(100)*256
      CHARACTER iniFilename*256
      COMMON /Options/ CNT, LINES, initialized, iniFilename
      DATA initialized, CNT, iniFilename / .FALSE., 0, 'Options.ini' /
      END

C** allow you to use a different iniFile or to switch to another
      SUBROUTINE setIniFilename(value)
      CHARACTER value*(*)
      LOGICAL initialized
      INTEGER CNT
      CHARACTER LINES(100)*256
      CHARACTER iniFilename*256
      COMMON /Options/ CNT, LINES, initialized, iniFilename
      if (initialized .EQV. .TRUE.) then
        if (value .NE. iniFilename) then
        iniFilename = value
C****** switching to a different ini file
                call loadOptions

        end if
      else
C****** overriding the default ini file
        iniFilename = value
      end if
      END

C***** search for the Section and keyword, if found return its value
C***** otherwise return the default
      SUBROUTINE getValue(section, kwd, value, default)
      IMPLICIT NONE
      CHARACTER section*(*)
      CHARACTER kwd*(*)
      CHARACTER value*(*)
      CHARACTER default*(*)
      INTEGER I
C**      WRITE(*,*) 'getValue', section, kwd, value, default
      value = ''
      call getValueX(section, kwd, value)
C**      WRITE(*,*) 'Got value ', value
      if (value .EQ. '') then
  value = default
      end if
      END

C**** read in the iniFile into the common Options block
      SUBROUTINE loadOptions
      IMPLICIT NONE
      INTEGER CNT
      LOGICAL initialized
      CHARACTER LINES(100)*256
      CHARACTER iniFilename*256
      COMMON /Options/ CNT, LINES, initialized, iniFilename
      CHARACTER LINE*256 
C**      WRITE(*,*) 'loadOptions'
      CNT = 0
      OPEN(UNIT=33, FILE=iniFilename)
1     READ(33,'(A)', END=10) LINE
      CNT = CNT + 1
      if (CNT .GT. 100) then
C**         WRITE(0,*) 'Options.ini file > 100 lines.'
  STOP 16
      else
       LINES(CNT) = LINE 
      end if
      GOTO 1
10    CONTINUE
C**      WRITE(*,*) 'CNT = ',CNT
      CLOSE (UNIT=33)
      initialized = .TRUE.
      END


C*** try to find the Section and keyword, if found return its value
C*** otherwise return an empty string
      SUBROUTINE getValueX(section, kwd, value)
      IMPLICIT NONE
      CHARACTER section*(*)
      CHARACTER kwd*(*)
      CHARACTER value*(*)
      INTEGER I, J, STARTVAL
      INTEGER CNT
      LOGICAL initialized
      CHARACTER LINES(100)*256
      CHARACTER iniFilename*256
      COMMON /Options/ CNT, LINES, initialized, iniFilename
      INTEGER MAXLINE
      PARAMETER (MAXLINE = 256)
      CHARACTER LINE*256
      LOGICAL foundSection, foundKwd
      if (initialized .EQV. .FALSE.) then
            call loadOptions
      end if
      foundSection = .FALSE.
      foundKwd = .FALSE.
      value = ''
C**      WRITE(*,*) 'Looking for ',section
      DO I=1, CNT
       if (LINES(I)(1:1) .EQ. '[') then
  DO J=2, MAXLINE
    if (LINES(I)(J:J) .EQ. ']') then
   if (section .EQ. LINES(I)(2:J-1)) then
    foundSection = .TRUE.
C**    Write(*,*) 'foundSection=', foundSection
    GOTO 15
   end if
    end if
  ENDDO
 else
  if (foundSection .EQV. .TRUE.) then
                        STARTVAL = 0
C**   WRITE(*,*) 'Looking for keyword ', kwd
   DO J=1, MAXLINE
    if (LINES(I)(J:J) .EQ. '=') then
     if (kwd .EQ. LINES(I)(1:J-1)) then
      STARTVAL = J+1
      foundKwd = .TRUE.
C**      Write(*,*) 'found keyword ', kwd
      GOTO 13
     end if
    end if
   END DO
13   CONTINUE
   if (foundKwd .EQV. .TRUE.) then
    DO J=MAXLINE, STARTVAL, -1
C**     Write(*,*) 'Looking for value at ', STARTVAL, J
     if (LINES(I)(J:J) .NE. '') then
      value = LINES(I)(STARTVAL:J)
C**      Write(*,*) 'Got value at line ', I, ' pos ', STARTVAL, J
      GOTO 20
     end if
    END DO
   end if
  end if
 end if
15 CONTINUE
      ENDDO
20    CONTINUE 
      END

Jim Dempsey

 

www.quickthreadprogramming.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today