Skip to content

Conversation

@AlexBuccheri
Copy link

This MR does two separate things:

  • Several commits, removing several gfortran compiler warnings
  • One commit replacing MPI_INIT with MPI_Init_thread, where I request the maximum threading support

W.r.t. compiler warnings, most of the changes silence false positives resulting from implicit LHS allocation. In these cases, I've just added explicit allocate statements. A couple others are from unused arguments. In one instance, I've removed an argument (see the logger) and in the other I'm assigned a dummy attribute.

W.r.t. replacing MPI_INIT with MPI_Init_thread. There's no obvious reason (to me) not to do this, and if a consumer/client code initialises with anything other than MPI_THREAD_SINGLE, this is required. As such, I initialise with MPI_THREAD_MULTIPLE, which should maximise support.

It is still the client code's responsibility to check what's actually provided by the MPI library, and handle appropriately:

    call MPI_Query_thread(provided)
    if (provided < required) then
      call MPI_Comm_rank(MPI_COMM_WORLD, rank)
      if (rank == 0) write(*, '(a)') 'MPI library threading support is less than required by <MY CODE>'
      call MPI_Abort(MPI_COMM_WORLD, 1, ierr)
    end if
``





 

Copy link
Member

@aradi aradi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the PR! This PR should be split into 2 separate ones:

  • Compiler warning workarounds
  • MPI-initialization
    as the two features are completely unrelated.

As for the compiler warnings: I am not a big fan of writing workarounds to avoid false positive compiler warnings. I am fine with the explicit allocate() statements (to avoid automatic lhs-(re)allocation), but I would not prefer to incorporate the other changes (the string addition and the placeholder local instance variable.)

For the MPI initialization, see the detailed comment below, I think the solution proposed there would be more elegant and robust.

Comment on lines 29 to 30
!> State of global random number
integer :: rn = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, this example is there to demonstrate the usage of module variables to pass initialization information. We should, therefore, explicitly do not create a variable within the type, in order to make the example clearer. (What is the actual reason for adding this (unused) instance variable?)

Copy link
Author

@AlexBuccheri AlexBuccheri Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've got a type-bound procedure that does not use this.

Happy to roll back the change

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please. That is somewhat unfortunate, that compilers complain about unused this even in extending types, where you can not change the signature of the type bound procedure...

Comment on lines 169 to 170
allocate(match(size(value1, dim=1), size(value1, dim=2)))
match = value1 == value2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allocate(match(size(value1, dim=1), size(value1, dim=2)))
match = value1 == value2
allocate(match(size(value1, dim=1), size(value1, dim=2)))
match(:,:) = value1 == value2

Whenever lhs reallocation is not wanted (because lhs had been already allocated) or not possible (because lhs is not allocatable), the placeholder indices should be used for arrays on the lhs. This makes the intention of assigning into more pronounced.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this only occur when the LHS is an allocatable variable being assigned a value whose shape/length doesn’t match its current allocation (like, the LHS not being allocated)? In this case, a shape mismatch is impossible because you have if-statements guarding against it.

But happy to make the change

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, theoretically, it only makes a difference if the LHS is not allocated or is allocated with a mismatching shape. However, I adopted the convention from DFTB+, that placeholder indices on the LHS are consistently used to indicate the intent of the assignment:

  • no placeholder indices: I wish to trigger automatic reallocation if necessary
  • placeholder indices: I want to make sure, that no reallocation is triggered (either because the array is static or because it has been allocated with the matchin shape)
    So it is semantically consistent, easier to understand the intention and helps to avoid bottlenecks by triggering automatic reallocation by mistake within a loop or similar.

I think, this convention would be also useful for Fortuno.

Comment on lines 47 to 48
allocate(match(size(value1, dim=1)))
match = value1 == value2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allocate(match(size(value1, dim=1)))
match = value1 == value2
allocate(match(size(value1, dim=1)))
match(:) = value1 == value2


! Note: factorial(n) with n > 13 overflows with 32 bit integers
nn = int(13 * rand) + 1
this%rn = nn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed, as we do not want to use variables within the type instance in this example.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Comment on lines 205 to 206
allocate(match(size(value1, dim=1), size(value1, dim=2)))
match = is_close_elem(value1, value2, atol=atol, rtol=rtol)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allocate(match(size(value1, dim=1), size(value1, dim=2)))
match = is_close_elem(value1, value2, atol=atol, rtol=rtol)
allocate(match(size(value1, dim=1), size(value1, dim=2)))
match(:,:) = is_close_elem(value1, value2, atol=atol, rtol=rtol)

Comment on lines 241 to 242
allocate(match(size(value2, dim=1), size(value2, dim=2)))
match = is_close_elem(value1, value2, atol=atol, rtol=rtol)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allocate(match(size(value2, dim=1), size(value2, dim=2)))
match = is_close_elem(value1, value2, atol=atol, rtol=rtol)
allocate(match(size(value2, dim=1), size(value2, dim=2)))
match(:,:) = is_close_elem(value1, value2, atol=atol, rtol=rtol)

Comment on lines +173 to +175
! & helpmsg="list of tests and suites to include or to exclude when prefixed with '~' (e.g. " //&
! & "'somesuite ~somesuite/avoidedtest' would run all tests except 'avoidedtest' in the test " //&
! & "suite 'somesuite')")&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we use sting addition, if Fortran has a perfect feature of breaking strings into continuation lines? I don't see the point for this change...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it makes no sense, but GCC with warnings enabled will catch what you currently have. Unlike most of the warning fixes, which affect fortuno's test cases (we don't build by default), this one gets caught by Octopus's CI.

So the point is either client codes are forced into disabling specific warnings or one does a trivial patch upstream. Alternatively, we discussed scoping compiler flags on a per library basis some time ago, but since Cristian's left, this is a non-starter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have checked gfortran 15.2:

gfortran -Dfortuno_EXPORTS -I[...]fortuno/src/modules -I[...]fortuno/src/fortuno/checkers -I[...]fortuno/include -fcheck=all -std=f2018 -Wall -pedantic -g -Jmodules -fPIC -c [...]fortuno/src/fortuno/cmdapp.f90 -o CMakeFiles/fortuno.dir/fortuno/cmdapp.f90.o

which does not produce any warnings in cmdapp.f90. Do you use any other flags, which trigger this warning? Or does the warning appear in your case with the most recent gfortran? (In case, they fixed it in recent gfortran versions, I would probably tend to keep the original formulation. I kind consider Fortuno also as a demonstration of best practices when programming in modern Fortran.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I also checked GFortran 13.2 now and I do not get any warnings for cmdapp.f90 with the -std=f2018 -Wall -pedantic flag combination. Do you use an older compiler (which could cause other troubles due to compiler bugs) or a different warning level setting?

Comment on lines +183 to +185
& helpmsg="list of tests and suites to include or to exclude when prefixed with '~' (e.g. " // &
& "'somesuite ~somesuite/avoidedtest' would run all tests except 'avoidedtest' in the test " // &
& "suite 'somesuite')")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment just above. Let's keep the original form, unless there is a really convincing argument for the change.


call MPI_Init(ierror)
if (ierror /= 0) error stop "MPI_Init failed in init_mpi_env"
call MPI_Init_thread(MPI_THREAD_MULTIPLE, provided)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with this approach is, that if the client is using the high level runner routine execute_mpi_cmd_app(), it has no way to check before the tests start, whether the MPI framework provides the necessary level of thread support. So, it is safer here to use the lowest possible threading level (MPI_THREAD_SINGLE, which must work, if the MPI framework works at all). This is also the level of threading support Fortuno requires.

In order to allow codes to use a more advanced threading support, we should allow clients to initialize the MPI-framework before calling execute_mpi_cmd_app() and pass then the global communicator (as optional argument) to execute_mpi_cmd_app(). Fortuno should then just use the provided communicator without initializing or finalizing the MPI framework. The client would then also be responsible for the finalization of the MPI framework after the call.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it has no way to check before the tests start, whether the MPI framework provides the necessary level of thread support.

How does this prevent the caller from calling execute_mpi_cmd_app , followed by a setup that calls MPI_Query_thread?

Fortuno should then just use the provided communicator without initializing or finalizing the MPI framework. The client would then also be responsible for the finalization of the MPI framework after the call.

As discussed over email, I'm fine with this idea. I'll open a separate PR for it

@AlexBuccheri
Copy link
Author

For the MPI initialization, see the detailed comment below, I think the solution proposed there would be more elegant and robust.

I'll drop the commit and open a separate PR

@aradi
Copy link
Member

aradi commented Nov 26, 2025

I've just tested the build process with GFortran 15.2 using the code from the main branch. I get with -Wall -pedantic -std=f2018 only a single warning about an unused dummy argument in consolelogger.f90. (Which we could easily fix). No other warnings anywhere else. So it seems, that the GFortran folks fixed the warning artifacts in the compiler already. I am wondering, where does this leave us?

@aradi
Copy link
Member

aradi commented Nov 26, 2025

@AlexBuccheri I have added in my cleanup PR (#46) a fix, which also eliminates the unused dummy argument problem in the console logger. That code runs with GFortran 15.2 without any warnings with the settings above. Would that code version something you could live with?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants