Scheduled Downtime
On Tuesday 24 October 2023 @ 5pm MT the forums will be in read only mode in preparation for the downtime. On Wednesday 25 October 2023 @ 5am MT, this website will be down for maintenance and expected to return online later in the morning.
Normal Operations
The forums are back online with normal operations. If you notice any issues or errors related to the forums, please reach out to help@ucar.edu

Outputting Both Input and Output of a particular subroutine

simondriscoll

Simon Driscoll
Member
If I should wish to output all the inputs to a particular subroutine (i.e. with the information it is passed) and output the values it outputs immediately after it is called, how may I do this? Currently I believe most of the literature points to a way to output diagnostics etc. at 'the end of all calculations' at any given time step. Thanks.
 

Philippe Blain

New Member
Hi again Simon ! :)

In general, to do this you would need to either:

1. change the code to add print statements at the beginning of each subroutine, to print the input arguments, and at the end to print the results of the computation.

or

2. Use a debugger to run the code, and print whatever you want at any point in the code.


For CICE specifically, there are facilities that can help you with 1). See 3.5. Troubleshooting — CICE documentation. If you use CICE standalone (and thus the Consortium's driver (cicecore/drivers/standalone/cice/), several debug_ice calls are already added, so if you add debug_model to your namelist and adjust lonpnt and latpnt to the lon/lat of your choice, it will print extended diagnostics each time debug_ice is called (and so several times per time step). You can also use debug_model_i,j,iblk,task instead of lat/lon to choose a specific grid point by its indices instead.

If these options are not sufficient to help you debug, then you could add additional calls to debug_ice, or go with option 2 and use a debugger. Of course this has a learning curve if you've never used a debugger before. Here is some advice:

1. On macOS, there is no Fortran debugger available by default. You can install GDB (for example using Homebrew or conda), but GDB unfortunately does not work reliably on recent macOS versions (which I remember you are using). So it would be easier to find a Linux machine to do your debugging.

2. It will be easier to debug if you run CICE in single process mode, i.e. ./cice.setup -p 1x1. If not, you need to use some tricks, or use a commercial parallel debugger like Arm DDT or Totalview. You university *might* have licenses for these.
 

simondriscoll

Simon Driscoll
Member
Hi Philippe! (and thanks once again for your help!! :))

I have done a test of option 1 (I am using the Icepack component of CICE as standalone and wasn't sure if option 2 existed for Icepack).

I have done a few test runs with printing output from the subroutine and can print input to it and those values changed by the subroutine that are output. I would like to link each input/output of this subroutine to the output as given in the proper output files (e.g. like ice_diag.full_ITD), as I would like to see if my changes to this subroutine result in an improved performance of Icepack as a whole.

I have identified that the ice_diag.land/slab/ocean/full_ITD files are written in the subroutine runtime_diags (in configuration/driver/icedrv_diagnostics.F90). If I put a print statement there for testing "Print *, "from runtime"", and one similarly in the subroutine I'm trying to improve e.g. "Print *, "from mysubroutine"", and diagfreq=1, I can see in the runlog I have 20 "from mysubroutine"'s before I have one "from runtime".

My belief is that this would be calculations over 5 ice thickness categories and done for each of the four cells (ocean/land/ITD/slab). Is there any way of telling if this is true for sure?

I would like then to be able to e.g. ignore all but full_ITD, and then I would have input/output at every tilmestep for my subroutine, and be able to relate it to the output. Thank you once again!!
 

dbailey

CSEG and Liaisons
Staff member
In the full CICE, we use print_points to get information at a particular location. This is not exactly in Icepack and it is only the runtime_diags. Definitely using diagfreq=1 gives you every timestep information. I added some information to the Icepack documentation to add additional diagnostics. It is perhaps not quite complete, but it would be great if you could test drive it:


Dave
 

simondriscoll

Simon Driscoll
Member
Hi Dave, I have tested your guide - I can confirm the method works for me and is very useful in Icepack (many many thanks for this! It's been super useful for me so far). I have used it to update/add a few more diagnostics to the output files and is very handy. One thing I would like to do is print all the input to a subroutine, and the output of that subroutine (which seems to be the rough and ready print statements right now).

I am not sure of a way of adding just those values, i.e. the values as sent to a subroutine each timestep, and the values it outputs only from the updates in that subroutine only (i.e. before these diagnostics get passed to other subroutine (possibly) and therefore possibly changing their values). Maybe one strategy above print statements is to create new variables that store those values only and pass them to the more standard output via icedrv_diagnostics.F90 as above? I would like in essence:

- 1) all the input values to a subroutine (of a melt pond parametrisation)
- 2) all output of that subroutine
- 3) standard model output

To link these together (I think there are 5 calls for each ice thickness category to these subroutines? for every 1 model output at the end of each timestep), i.e. to understand how to combine 1) and 2) (over 5 ITD categories) to standard output.

As then I can see if an improvement would improve the subroutine and also compare its performance directly against the overall performance of the model/output to directly compare against current Icepack.

As far as I can see the current way for adding diagnostics is for the 'complete/fully calculated' value (i.e. diagnostic X after X has been passed through all relevant subroutines and so on). But I am maybe limited to print statements or creating a new set of variables that copy and store the input and output value, then send them through icedrv_diagnostics.F90 for each timestep?
 

dbailey

CSEG and Liaisons
Staff member
It is true that some variables are just local and need to become global if you want them to come through in the diagnostics. For example if something is local to icepack_therm_vertical.F90, then this needs to be added somewhere else as a "global" variable. Or, you can provide it from icepack_therm_vertical.F90 as a "public" so it can be used elsewhere. Sometimes this creates circular dependencies which may cause the code not to compile.
 
Top