The following guidelines will help you to add a test case to Notus test case bank.
A Notus test case is based on a NTS file and, eventually, some Fortran routines that compute initialization, boundary conditions, post-processing, etc. that cannot be done within the NTS file. Solution of a test case is also checked automatically at each release of the code by running the validation script. Finally, documentation should be written.
The next sections helps to realize these points.
Test case are separated into verification and validation test cases:
So, you have to put your NTS file in test_cases/verification or test_cases.validation directory.
Within each directory, you will find subdirectories where you can copy your file (or create a new category if necessary). For instance:
$ ls verification/ cell_advection_schemes laplacian linear_system_test navier phase_advection species_transport surface_tension $ ls validation/ free_convection laminar_flows mixed_convection multiphase thermosolutal turbulent_flow
We will name your_test_case_category this directory.
For more clarity, make sure that your NTS file has the suffix *_2D* or *_3D* before the NTS extension.
The test case should be validated precisely against exact solution, numerical solution or experimental data. Once this work is done, the associated documentation that presents the test case and the obtained solutions are written in a doc.f90 file. This file is put in src/notus/test_cases/your_test_case_category/your_test_case_directory, where your_test_case_directory matches the NTS file without the extension.
For each equation solved, a reference solution can be obtained during the validation process of the test case (the mean velocity magnitude, the mean temperature, the mean species concentration, and/or the mean volume). These reference values, as well as a tolerance value, are entered in the NTS file in the post_processing block:
post_processing { validation { tolerance 1.d-13; reference_mean_temperature 2.999999999997118E+02; reference_mean_velocity_magnitude 3.7921755054867766E-03; reference_mean_volume_fraction 3.7921755054867766E-03; reference_mean_concentration 3.7921755054867766E-03; } }
After its creation, a new test case is nowhere to be listed. Indeed, the script will determine by itself the test cases required for the execution of the process chosen by the user (Validation or Run). At each new execution of the code, the solution is checked against the referenced one, and the test case is validated if the error is below the tolerance value.
Sometimes, you may want to execute more than a specific case determined by a specific set of parameters. Indeed, you may have to deal with variables that can take several values. All of these cases can be executed during the same process if variables are defined with the following syntax, where values_list can be any list generator of Python:
# @PARAMETER variable_type variable_name values_list
You can even filter the values taken by the variable:
# @PARAMETER integer variable [n for n in range(10) if n%2 == 0]
This syntax will return a list of integers between 0 and 9 where all odd numbers have been removed.
Notus will create as many jobs as there are possible combinations of the values taken by the variables. For instance:
# @PARAMETER integer dimension [1,2] # @PARAMETER string advection_scheme ['upwind_o1','weno5']
Notus will treat all the following cases: dimension = 1 and advection_scheme = 'upwind_o1', dimension = 1 and advection_scheme = 'weno5', dimension = 2 and advection_scheme = 'upwind_o1' and dimension = 2 and advection_scheme = 'weno5'.
If you want to use several solvers, values_list needs to be replaced since the list of all the solvers available will be automatically determined by the script.
# @PARAMETER string solver_name @SOLVER
Of course, the code can still be executed with the parameters defined at the beginning of the NTS file. The argument - f must be used in the command line to execute all cases. For further information, see run notus guide.
The number of MPI processors in Validation Mode is determined at the beginning of every NTS, regardless of the dimension of the case. The syntax is similar to the one used to define parameters :
# @MPI_PROCS integer
where integer is the number of MPI processors required.
To realise a convergence test case you have to put additionnal information into the NTS file:
# @CONVERGENCE [time|space] # @TIME_STEP float # @FINAL_TIME float # @STEPS int # @MESH int int [int] # @GEOMETRIC_FACTOR int
With this information, you can test spacial or time convergence. For instance:
# @CONVERGENCE time # @TIME_STEP 1.5 # @FINAL_TIME 4.0 # @STEPS 3 # @GEOMETRIC_FACTOR 2
Or for a spacial convergence:
# @CONVERGENCE space # @MESH 10 10 # @STEPS 3 # @GEOMETRIC_FACTOR 2
If you realize a time convergence, you will have to replace the time step value by TIME_STEP
in the nts file. As well for the final time value, that has to be replaced by FINAL_TIME
. For a space convergence, you will have to put N_CELLS_X
, N_CELLS_Y
(and N_CELLS_Z
if there are 3 dimensions) for the number of cells in the x, y (and z) direction.
The # @MESH
option is specific to spacial convergence. It has no impact on time convergence. As well, # @TIME_STEP
and # @FINAL_TIME
are specific to the time convergence.
You will also have to put a validation
block in the post_processing
block in the NTS file to choose to chose which output value will be taken for the convergence study. For more information, see post_processing in the [nts language documentation] (User Interface).
To add a scalability test case, it is the same principle. You have to put information about the scalability study into the nts file. You can set the following parameters:
# @SCALABILITY [weak|strong|strong_node] # @PROGRESSION [arithmetic|geometric|custom] int [int ...] # @MPI_PROCS_PER_NODE int # @TIME_ITERATIONS int # @DIMENSION int # @THREADS int [int ...] # @MESH int int [int] # @CELLS_PER_CORE int
The option # @PROGRESSION
indicates the series of number of nodes you want to do the scalability test. For instance, if you want to compute for 1, 2, 5, 10 nodes, you can use the command:
# @PROGRESSION custom 1 2 5 10
To make an arithmetic progression \( \left\{ u_n = u_0 + nr~|~\forall n<N \right\} \) you will have to indicate the initial term \( u_0 \), the common difference of successive members r and the number of terms N after the word arithemetic:<>>
# @PROGRESSION arithmetic u0 r n
It is also possible to make a geometric progression following the same principle. To make a geometric progression \( \left\{ u_n = u_0r^n~|~\forall n<N \right\} \), you will have to indicate the initial term \( u_0 \), the common ratio r and the number of terms N after the word geometric:<>>
# @PROGRESSION geometric u0 r n
For instance, if you want the progression \( u_n = 1 + 2n \), with 5 terms, you will use the command:
# @PROGRESSION arithmetic 1 2 5
You can set the initial mesh using # @MESH
or # @CELLS_PER_CORE
. You need to replace the number of cells in the x, y (and z) direction by N_CELLS_X
, N_CELLS_Y
(and N_CELLS_Z
if there are 3 dimensions). With the # @MESH
option, you set the number of cells for each directionxs. Withxe the # @CELLS_PER_CORE
, you set the number of cells per core, and with the total number of cells, the script will generate a mesh with the same number of cells for each direction.
For instance, for 2 cores, in 2D, you can use # @MESH 10 10
or # @CELLS_PER_CORE 50
to generate the same mesh.
You can precise the number of threads you want. If you put several number of threads, like # @THREADS 1 2
, the script will launch a study for 1 thread, and then a study on 2 threads.
By default, if you do not precise the number of threads, the computation will use only 1 threads.
To lead scalability studies, some options are necessary:
# @MPI_PROCS_PER_NODE # @MESH or # @CELLS_PER_CORE # @DIMENSION # @PROGRESSION
# @MPI_PROCS_PER_NODE # @DIMENSION # @PROGRESSION
# @DIMENSION # @PROGRESSION
There is an example of the option you can write in the nts file to create a weak scalability:
# @SCALABILITY weak # @DIMENSION 2 # @THREADS 1 # @MPI_PROCS_PER_NODE 16 # @PROGRESSION geometric 1 2 4 # @CELLS_PER_CORE 5000
This options will generate a weak study on 1, 2, 4, 8 nodes, with a mesh of 282x282.
If the test case needs special Fortran routines, the execution mode switches from the default mode (that passes through user routines) to the test_case mode that passes through specific routines associated to the test case that is run. This is done thanks a special keyword that is added to the NTS file.
First, add your test case in the Notus test case enumeration that needs specific Fortran routines, in the src/notus/test_cases/enum.f90
file:
enumerator :: test_case_your_test_case_name
In the User Interface part of the code, src/notus/ui/keywords.f90 file, add an enumerator beginning with kw_tc_
:
! Test case keywords enumerator :: kw_tc_your_test_case_name
Then, in the same file, in subroutine ui_keyword_list_initialize
, add the keyword into the keyword list:
ui_keywords(kw_tc_your_test_case_name )%name = "tc_your_test_case_name"
Then, in src/notus/ui/tree/system/block_reader.f90 file, in the select case(tok_test_casekeyword_id)
section, add your test case:
case(kw_tc_your_test_case) test_case = test_case_your_test_case
Now, compile again the code !
Specific routines must be separated into several ones which names are:
These routine are put in the src/notus/test_cases/your_test_case_category/your_test_case_directory directory.
The switch during the execution from a set of routines associated to one test case to another is done in the src/notus/test_cases directory in which you have to modify compute_reference_solution.f90, tc_prepare_next_iteration.f90, tc_post_process.f90 and tc_prepare.f90 routines.
Now, compile again the code, and your test case should be added !