This page is for anyone writing code for the CASINO distribution: the main program, its utilities and its converters. It sets out the rules the code follows and the route by which a change reaches the repository. The full Fortran style guide is in the manual, in its section on programming style; this page summarises it and adds what the manual does not cover. If you have not yet read Developing CASINO, start there.
Languages
- Fortran 2008, and nothing later. The main program and most utilities are Fortran. CASINO is built with many compilers, some of them old, and a feature that a recent gfortran accepts without comment may stop another compiler altogether. Do not use Fortran 2018 features, assumed-type and assumed-rank arguments (
TYPE(*),DIMENSION(..)) among them, or any vendor extension. - C appears only in two small routines in
src/,etime.candalloc_shm.c, which are the models for layout. Use C only where Fortran cannot do the job, and use/* */comments, never//. - Shell scripts, such as
runqmcand its relatives, are written for bash. Any script that reads or computes with numbers from CASINO’s output does its arithmetic underLC_ALL=C: in a locale with a decimal comma, which many of CASINO’s users have,awkandprintfmisread numbers without any warning. - Converters and analysis tools may be written in Fortran or in Python 3. A Python tool states in its README the Python version and any packages it needs, and avoids packages it can do without. Anything else, ask first.
- Libraries. The main program calls no external library other than MPI, BLAS and LAPACK, and it must still build and run without MPI.
Fortran style
The code should read as if one person wrote it, so that it is easy to read and so that a text search finds every instance of a thing. The source in src/ is the reference. In summary:
- One module per file.
- Compile-time keywords in upper case (
MODULE,SUBROUTINE,FUNCTION, declarations); executable code in lower case. - Indent the body of each
if,doandselect caseblock by one space. - Relational operators as
==,/=,<,<=,>,>=, never.eq.and its relatives. - Lines of 80 characters at most. A continued line ends with
&and the next begins with one. endifandenddo, notend ifandend do.- Declarations use
::only where the language requires it (INTEGER ialloc, butINTEGER,INTENT(in) :: n). Dummy arguments come first, in the orderin,inout,out, then local variables; within each group the types runINTEGER,REAL(sp),REAL(dp),COMPLEX(sp),COMPLEX(dp),LOGICAL,CHARACTER,TYPE. WriteCHARACTER(12), notCHARACTER*12. USEstatements in alphabetical order, followed by theUSE ... ONLYstatements, also in alphabetical order. When you add or remove aUSEstatement insrc/, runbuild-tools/update-makefile-toolfromsrc/to bring the Makefile’s dependencies up to date.- No tab characters; no
returnbeforeEND SUBROUTINEorEND FUNCTION; noGOTOwhere it can be avoided; two blank lines between routines. - Input/output units are allocated with
open_units, never chosen by hand. - Comments are sentences: capital letter, correct spelling, full stop. They say what the reader needs and cannot see.
Errors are reported through errstop, errstop_master and errwarn in run_control.f90, called as call errstop('ROUTINE_NAME','Message.'). Use errstop_master only where every process reaches the same call with the same condition; if only one process can see the condition, for instance because only the master has read the file in question, use errstop, or the other processes wait for ever. Only the master process writes to the output file.
A new input keyword is registered, with its help text, in src/esdf_key.f90, and documented in the manual.
The style checker, utils/casinostyle_checker/casinostyle_checker.py, should report nothing new in a file you have changed. Compare its output on your version with its output on the original, since some older files do not pass it.
Headers and Changes logs
Every routine begins with a boxed comment giving its name, what it does, and its author’s initials and date (month and year). Every change to an existing routine, however small, adds a dated line to the Changes section of that routine’s box, in the box’s own format, for example
! 10.2026 VK Analytical derivatives with respect to the cutoff. !
padded to the box’s right-hand edge. Use your own initials; the key to initials lists those already in the code. Code imported from another program keeps a single box at the top of the file recording where it came from, with its own Changes log.
Scope: dimensions, orbitals and methods
A new facility should work for systems periodic in 0, 1, 2 and 3 dimensions, with every type of orbital CASINO supports, and in VMC, DMC and RMC, or else refuse the input with a clear message. It must never run and return a wrong answer in a case it was not written for. You are not expected to test every combination. Say in the note that comes with your patch which combinations you ran, which go through the same code and so are covered by reading, which are refused, and which you have not examined. The same applies to utilities.
Speed and scale
CASINO’s speed was bought over many years and is easily given back. Say whether your change is in code executed for every move, for every block, or once at setup.
- A change to code executed for every move comes with timings before and after, on a system of realistic size, at the number of processes it would be run with, repeated often enough to show the noise. For a small change, instruction counts from valgrind’s callgrind are more reliable than timings. A change that makes the code slower needs a reason; a speed-up that changes printed numbers needs an explanation.
- DMC runs on very large numbers of processes. Decisions about redistributing walkers are taken within groups of about 500 processes, so that their cost does not grow with the size of the machine. Code executed for every move must not add arrays dimensioned by the number of processes, loops over processes, or new collective communication outside that machinery.
- Prefer MPI calls the code already uses. A new one must also be provided in the serial stand-in for the communications module, so that CASINO still builds without MPI.
timing_info=Tin the input prints a breakdown of where the time goes. It is off by default because it slows the run.
Testing
The regression suite is in examples/TEST, and its README is the authority on how to run it. Run it in serial and in parallel, building the reference library from the unmodified code separately for each, since serial and parallel output cannot be compared with each other: four runs in all. For example,
cd examples/TEST ./autotest --library -- --binary=casino_orig # reference, serial ./autotest # your code, serial ./autotest --library -- --binary=casino_orig --nproc=4 # reference, parallel ./autotest -- --nproc=4 # your code, parallel
where casino_orig is a binary built from the unmodified code. If you run the suite from a second copy of the source, check that the runqmc found first on your PATH is that copy’s, or you will test the wrong program. A new facility brings a test case of its own.
The suite runs the main program only. A change to a utility or a converter is tested by running it before and after on named inputs and comparing the results, and those inputs are described in the note with the patch.
For debugging, make debug in the CASINO directory or in src/ builds with checking enabled, and runqmc --debug (or runqmc -d) runs that build; autotest uses it by default. The debug build stops at the first invalid floating-point operation, division by zero or overflow: treat a stop as a finding, not as noise. runqmc --debugger=gdb runs under a debugger. Test with more than one compiler where you can (gfortran, Intel ifx, and NAG, whose checking is the strictest), and on more than one process. When looking for a fault, simplify the input first: remove the Jastrow factor, the cusp correction or the backflow and see whether it persists.
Submitting a patch
Small fixes are welcome without notice. For anything larger, write first, so that the work is not duplicated and the approach is agreed before you spend time on it.
- Work against the current development version, one logical change per commit, and send the result of
git format-patchto Mike Towler. Pablo López Ríos’s guide to git in CASINO shows how. - Never include the
DIARYorVERSIONfiles, which the build generates. - With the patch, send a short note: what was wrong or is new, what you ran, numbers before and after, the scope statement above, and anything the manual or an example in
examples/should gain, which may be part of the patch itself.
Each patch is built, run against the suite in serial and in parallel, and read in full by a reviewer other than its author. It is then either returned with the reasons or applied to the repository under its author’s name.
Commit messages
Each commit message becomes an entry in the development log, which ships with CASINO and is read by its users, so it is written for them.
- The subject line is in the imperative and says what CASINO now does, prefixed with the file’s name where one file dominates the change.
- The body is in the past tense and says what was wrong and what a user sees now, or, for something new, what it is and in a sentence how to use it. Two or three sentences are usually enough.
- A change made for speed states the speed-up measured, for which system and on how many processes, and whether any printed number changes.
- The message does not describe how the change was made or tested; that belongs in the note that comes with the patch.
For example:
reblock.f90: don't print a failed effective-population estimate as a number. POPSTATS's effective population and measured inefficiency could come out negative and were printed as if they were results. When the estimate fails they, and the two error bars built on them, now print as unavailable, with a warning that the estimator failed and not the walk. No other printed number changes.
The CHANGES file is a short summary of the log for users, kept by the maintainer, and records only new capabilities, significant speed-ups and changes that users at large will notice. If you think your change belongs there, say so in your note.
Bug reports and requests
Report a fault on the forum, with the input files that show it, the version line printed at the top of the output file, and the compiler and machine. A fault that can be reproduced is already a contribution. Requests for new features are welcome there too; many items on the list of things to do began that way.
