WRITE from a Module in a Subroutine

I am attempting to write values obtained in a nested Do loop inside a fortran Module (dftd3_module in core.f90 which is part of the large Quantum Espresso package). The Module is called by a subroutine A. Subroutine A is called by subroutine B which is called by the main program. When I run the main program, the WRITE statement produces no output. Looking at similar online questions, I did the following:

  1. write a subroutine at the end of the Module (dftd3 module) such as
   contains
   SUBROUTINE printval
   write(*,*) "r=",r
   write(*,*) "e6=", c6/(r6+bj_dmp6)
   write(*,*) "e8=", c8/(r8+bj_dmp8)
   END SUBROUTINE printval
  1. Call the subroutine where the values are calculated inside the Do loops in the Module. This compiles fine but does not work either.

Is what I am trying to do possible and if so, I would appreciate any tips in the right direction.

Thanks,
Vahid

A module contains functions and subroutines that can be called, but you cannot call a module, only module procedures within it. Are you sure that printval is being called? At the beginning of printval you could add

error stop "entered printval"

to verify that it is.

Thank you for the quick response. On my end, I had to wait for the Cluster to run my job. I added your suggestion and the job finished as before with no print out. So the printval is not being called. I have it placed here in a subroutine (pbcedisp) in the Module

          do taux=-rep_vdw(1),rep_vdw(1)
            do tauy=-rep_vdw(2),rep_vdw(2)
              do tauz=-rep_vdw(3),rep_vdw(3)
                tau=taux*lat(:,1)+tauy*lat(:,2)+tauz*lat(:,3)

                dxyz=rxyz+tau

                r2=sum(dxyz*dxyz)
                ! cutoff
                if (r2.gt.rthr) cycle
                r =sqrt(r2)
                rr=r0ab(iz(jat),iz(iat))/r

                r6=r2**3

                e6 =e6+c6/(r6+bj_dmp6)
               
                c8 =3.0d0*c6*r42
                r8 =r6*r2

                e8 =e8+c8/(r8+bj_dmp8)
              
                counter=counter+1
                CALL printval

              end do
            end do
          end do 

The printval subroutine is placed at the end of the pbcedisp subroutine

 contains

   SUBROUTINE printval
   error stop "entered printval"
   write(*,*) "r=",r
   write(*,*) "e6=", c6/(r6+bj_dmp6)
   write(*,*) "e8=", c8/(r8+bj_dmp8)
   END SUBROUTINE printval

  end subroutine pbcedisp

You could add print statements or use a debugger to understand why printval is not being called. For example what are the values of the loop bounds above? When is the cycle statement in the loop triggered? You could add a line

print*,"calling printval, counter =",counter

before call printval.

1 Like

Your routine never gets called because the loop is always skipped, if you add this statement you should be able to check it

       ! cutoff
       if (r2.gt.rthr) print *, ' CUTOFF: r2=',r2,' threshold=',rthr
       if (r2.gt.rthr) cycle
1 Like

Maybe somebody is blocking any IO to the standard output in QE to avoid random printing from subprocesses (especially in an MPI run)?

❯ cat test.f90
use iso_fortran_env, only : output_unit
open(unit=output_unit, file="/dev/null")
print *, "Hello, world!"
end
❯ gfortran test.f90 && ./a.out

In this case it is easier to open a separate file and write to this one instead.

The test.90 produced no output on the screen.

Using Federico’s idea, the output did not show any CUTOFF. The print statement does not work inside these subroutines.

My immediate suspicion then is your do loop nest, check what the values for rep_vdw are with beforehand.

1 Like

The rep_vdw, calculated with another subroutine, are 6, 6, and 2. The material is a 2D material and so it is elongated along the third direction and requires fewer replicas.

It looks like QE actually does connect /dev/null to the standard output if you are not on an ionode process: Modules/environment.f90 · 0279435 · QEF - Quantum ESPRESSO Foundation / q-e · GitLab. This means print and write will not work in this case because they send their data to a write-only file. Not sure if one can recover standard output once it is connected to dev/null (a quick check didn’t look too promising).


In case anyone is interested the version of dftd3-lib used in QE can be found here:

2 Likes

You might still be able to write to the standard error:

block
  use iso_fortran_env, only : stderr => error_unit
  write(stderr, *) "Should be visible"
end block

Note that many scripts in QE actually redirect the standard error to /dev/null as well (from a quick search for 2> /dev/null in the repo), however this is not done in the global initialization routine meaning it might be an option if you are careful.

Interesting way to suppress output from the program - I wonder (besides disk space) if this leads to any performance benefits: it would seem not, since all formatted io internals will be called anyways, I guess

I got it to work. What I was doing before was using “make” for the dft-d3 package after all the changes. This updated the .mod files and the library in the dft-d3 package. This time, I used “make” for the whole package of Quantum Espresso of which dft-d3 is only part of. Now I can run QE and the Subroutine printval works fine.

Thank you for all the inputs to my query, a learning experience for me as well. It is very encouraging to know that there are many out there willing to help.

Vahid

1 Like

Oh, QE has a recursive make setup, I wouldn’t have guessed that this could lead to such hard to discover errors. Losing time on build errors made me move away from makefiles for all my projects.

The CMake build files in QE might provide a different developing experience, not necessarily better if you are new to CMake, though. It definitely provides possibilities to lose time on other kind of build errors ;).

1 Like

The “/dev/null” trick does have performance issues, and depending on what version of fortran and what compiler you are using opening more than one file to “/dev/null” can be unsupported … there have been long discussions about that, some of which are still in the fortran newsgroup. There are lots of reasons I would discourage that myself, but I have seen that heavily used to avoid writing many “if(debug)write(…)…” statements. It would be nice if there were a way to literally turn off a LUN, or even some option on the write; and there are a few tricky codes that call functions with side effects in WRITE statements that would be particularly problematic. I personally wish a LUN could be an array, including being an empty array; which would allow “turning off” a WRITE and also allow writing to multiple files like the screen and a log file efficiently.

See the previous discussion on this, the one you had opened at the J3 Fortran proposals site: