Namelist parameters#

In this chapter, we cover how users control simulations via namelist parameters.

1. What is a namelist#

In RAMSES, namelist parameters form the primary user interface for configuring a simulation. They allow users to specify runtime settings without recompiling the code — such as solver options, output frequency, cosmological constants, or model flags. At runtime, the user provides an input file (typically simulation_name.nml) containing these parameters. An example namelist file and overview of all runtime parameters can be found in the User Documentation. For example, the namelist block setting the AMR-related parameters can look like this:

&AMR_PARAMS
levelmin=3
levelmax=10
ngridmax=2000
nexpand=1
boxlen=1.0
/

Namelists are Fortran constructs that group configuration variables. They are defined using the keyword namelist, followed by a chosen name and a list of the associated variables. For example the amr_params namelist in RAMSES is defined as follows:

namelist/amr_params/levelmin,levelmax,ngridmax,ngridtot &
& ,npartmax,nparttot,nexpand,boxlen,nlevel_collapse

In RAMSES, the variables associated to namelist parameters are usually declared in the one of the parameter or common modules (found in the module_parameter.f90 or module_commons.f90 files). They are globally accessible by importing the module, for example:

use amr_parameters

2. Reading and processing namelist parameters#

Namelists are read once during program initialization. The keywords in the namelist file provided by the user are mapped to the variables names in the code. Their value is altered from the default value specified in the code to the value provided by the user. In RAMSES, this is handled by the read_params subroutine (found in amr/read_params.f90), which is called at the very beginning of the simulation. The code to process a namelist will go through the following steps:

! Definition of the namelist
namelist/something_params/param1,param2,param3

! Go to the beginning of the namelist file
rewind(namelist_unit)

! Read namelist
read(namelist_unit,NML=something_params,IOSTAT=nml_err)

! Checks in whether the namelist was present in the file
if(nml_err<0)then
   ! EOF reached before namelist was found
elseif(nml_err>0)then
   ! Problem with formatting in the file
endif

! Do some check on the read values
if(param1<0) nml_ok=.false.
...

Older parts of the code may use more unorthodox syntax, but effectively do the same thing. For example:

  ! Read namelist file
  rewind(1)
  read(1,NML=init_params,END=121)
  goto 122
121 write(*,*)' You need to set up namelist &INIT_PARAMS in parameter file'
  call clean_stop
122 rewind(1)

The identifier number for the namelist file is 1.

Remark that each MPI process will read the namelist file, and so each process has access to all parameters.

3. Where are namelists defined in RAMSES#

Each module or subsystem (e.g. AMR, hydrodynamics, gravity) is controlled by its own namelist definition and associated variables. The naming convention for namelists is <module>_params. The namelist definitions can be found in one of the following places:

  • amr/read_params.f90, which contains:

    • run_params

    • amr_params

    • output_params

    • movie_params

    • lightcone_params

    • tracer_params

    • poisson_params

  • hydro/read_hydro_params.f90, which contains:

    • init_params

    • hydro_params

    • refine_params

    • boundary_params

    • feedback_params

    • cooling_params

    • sf_params

    • units_params

    • grackle_params

    • physics_params (legacy)

  • the corresponding code module:

    • clumpfind_params in pm/clump_finder.f90

    • mergertree_params in pm/merger_tree.f90

    • stellar_params in pm/read_sink_feedback_params.f90

    • sink_params in pm/sink_particle.f90

    • unbinding_params in pm/unbinding.f90

    • rt_params and rt_groups in rt/rt_init.f90

    • turb_params in turb/read_turb_params.f90

Remark that recently dedicated subroutines have been created in amr/read_params.f90 to handle the namelist defined in this file.

4. Adding a new namelist parameter#

When introducing a new algorithm or making small modification to the code, you may need to add a new parameter to an existing namelist. The procedure is straightforward:

  • Step 1: Determine to which namelist the new variable belongs and add it to the namelist declaration.

  • Step 2: Identify the module to which to add the new variable and declare it. A default value should be set, which will be used in case the parameter is not specified in the namelist file. This also ensures backward compatibility with existing namelist files. A comment should be added to describe what the variable represents.

  • Step 3: Since the variable is added to an existing namelist, it will be automatically read when the corresponding namelist is parsed. Optionally, you can add checks to verify whether the user provided a sensible value.

  • Step 4: Document the new parameter. Add an entry to the markdown file listing the parameters of the altered namelist, which can be found in the folder

doc/wiki.

Exercise

Add a new fictional parameter called tuto_heating_model. Imagine that setting this parameter enables an additional heating source for which three models exist in the literature. By default, we want this source to be turned off. Test your code by printing the value of tuto_heating_model.

5. Defining a new namelist block#

When adding major new features, it is appropriate to define a new namelist to group the parameters that control the new part of the code. When developing bigger modules, we encourage to follow the example of the turbulence module. In short:

  • Define module-specific variables in a module/module_parameters.f90 file

  • Write a routine read_module_params in which you define the namelist, read it and process its parameters. Place it in a file read_module_params.f90 file included in the module’s directory.

  • Add the call to read_module_params to read_params.

  • Update the documentation of your module.

Remember that when creating new directories and files, the Makefile needs to be updated.

Exercise

In amr/read_params.f90, add a subroutine that will read and process a new fictional namelist called tuto_params, which contains two parameters: tuto_efficiency and tuto_timescale. Both of these parameters have to be positive and cannot be zero. For simplicity, you can define the variables inside the new subroutine.

6. Bonus: namelist and Python#

If you want to read/write namelist with python, check out the f90nml package.