Search code examples
stringfortranconcatenationstring-concatenation

String concatenation not working in Fortran


I have a subroutine which concatenates strings in order to create file names so I can track solution change over nonlinear iterations. It doesn't appear to work however. I've used this code snippet before with no problems so I wonder if maybe this relies on certain compiler flags? The string concatenation portion is at the bottom, and I return the following:

output_name:PLT/Res filename1: PLT/Res
filename2: PLT/Res
Writing to File... 0

Which shows clearly that my string is not concatenated. I call the subroutine with:

   IF (MOD(counter, plot_freq) == 0) call plotSolution(2, counter, 'PLT/Solution', Mesh, W)

And the routine is below.

subroutine plot_nodal_field(opt, iter, output_file, Mesh, Q)
   use Globals_module,  only : c_in
   use inputs_module,   only : p_in, gamma, rho_in, M_inf
!--------------------------------------------end of use--------------------------------------------!
   integer(i4),     intent(in) :: iter, opt
   type(Mesh_Type), intent(in) :: Mesh
   character(*),    intent(in) :: output_file
   real(dp),        intent(in) :: Q(Mesh%numFields, Mesh%numNodes)
!------------------------------------------end of intents------------------------------------------!
   integer(i4)   :: elem_id,n1,n2,n3
   character(80) :: filename, file_num
   integer(i4)   :: iunit
   integer(i4)   :: n,io, i
   real(dp)      :: x, y, rho, rhoU, rhoV, rhoE, u, v, P, CP, c, MachNum, s
!------------------------------------------end of declare------------------------------------------!


  iunit = 2

  write(file_num,'(I6.6)') iter
  write(*,*) 'output_name:', output_file
  filename = adjustl(trim(output_file)) // '_' // adjustl(trim(file_num)) // '.plt'
  write(*,'(A)') 'filename1:', filename
  filename = adjustl(trim(filename))
  write(*,'(A)') 'filename2:', filename
  print*,'# Writing to File...', iter

   open(unit = iunit, file = filename, status = 'replace', iostat = io)
   if( io /= 0) then
       print*,'ERROR: Opening 2nd order plt file'
   else
       if (opt == 1) then 
           write(iunit,'(A)')  'VARIABLES = "x","y","rho","U","V","P","MachNum","entropy"'
       elseif(opt == 2) then
           write(iunit,'(A)')  'VARIABLES = "x","y","rho","U","V","P"'
   end if
       write(iunit,'(A7, I, A3, I, A41)')  'ZONE N=', Mesh%numNodes, ' E=', Mesh%numTri, ' DATAPACKING=POINT ZONETYPE=FETRIANGLE'
       do i = 1, Mesh%numNodes
           x    = Mesh%nodeCoords(1, i)
           y    = Mesh%nodeCoords(2, i)
           if (opt == 1) then
               rho  = Q(1, i)
               U = Q(2, i)
               V = Q(3, i)
               P = Q(4, i)
               c = sqrt(gamma*P/Q(1,i))
               MachNum = sqrt(Q(2,i)**2 + Q(3,i)**2)/c
               s = P/Q(1,i)**gamma - P_in/rho_in**gamma

               write(iunit,'(8ES)') Real(x), Real(y), Real(Q(1,i)), Real(Q(2,i)), Real(Q(3,i)), Real(Q(4,i)), &
               & Real(MachNum), Real(s)
           elseif (opt == 2) then
               write(iunit,'(6ES)') Real(x), Real(y), Real(Q(1,i)), Real(Q(2,i)), Real(Q(3,i)), Real(Q(4,i))
           end if
     
       end do
       do i = 1, Mesh%numTri
           write(iunit,'(3I)') Mesh%trilist(1,i), Mesh%trilist(2,i), Mesh%trilist(3,i) 
       end do
   end if
   close(iunit)

end subroutine

EDIT:

I tried to make a minimum verifiable example:

program plotSolution                                                                                                        
!--------------------------------------------end of use--------------------------------------------!
integer       :: iter
character(80) :: filename
!------------------------------------------end of intents------------------------------------------!
filename = 'PLT/Solution'
iter = 1
call plot_nodal_field(iter, filename)

contains


subroutine plot_nodal_field(iter, output_file)
!--------------------------------------------end of use--------------------------------------------!
integer,      intent(in) :: iter
character(*), intent(in) :: output_file
!------------------------------------------end of intents------------------------------------------!
character(80) :: filename, file_num
integer       :: iunit
!------------------------------------------end of declare------------------------------------------!


iunit = 2

write(file_num,'(I6.6)') iter
write(*,*) 'output_name:', output_file
filename = adjustl(trim(output_file)) // '_' // adjustl(trim(file_num)) // '.plt'
write(*,'(A)') 'filename1:', filename
filename = adjustl(trim(filename))
write(*,'(A)') 'filename2:', filename
print*,'# Writing to File...', iter

open(unit = iunit, file = filename, status = 'replace', iostat = io)
if( io /= 0) then
   print*,'ERROR: Opening 2nd order plt file'
else
end if
close(iunit)
end subroutine
end program

But this works: and returns:

output_name: PLT/Solution

filename1: PLT/Solution_000001.plt
filename2: PLT/Solution_000001.plt
Writing to File... 1 ERROR: Opening 2nd order plt file

which indicates to me I may have some odd memory error in the main code. I'm not sure. Thanks for all the suggestions and help!


Solution

  • I appreciate all the help I got from you folks, and decided to return to this today and found the issue. As far as I can tell it's a compiler flag issue where the compiler/preprocessor takes the concatentation operator (//) as a c++ comment and the preprocessor comments everything out after the concatenation. I had to use continuation ampersands to kludge together a fix, but it works for now, and then I can look into the flags another time. If anyone has any insight though, I'd appreciate that.