Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions documentation/source/development/add-vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Code example in the `input.py` file:
To add a `PROCESS` iteration variable please follow the steps below, in addition to the instructions for adding an input variable:


1. The parameter `ipnvars` in module `numerics` of `numerics.f90` will normally be greater than the actual number of iteration variables, and does not need to be changed.
1. The parameter `N_ITERATION_VARIABLES_MAX` in module `numerics` of `numerics.f90` will normally be greater than the actual number of iteration variables, and does not need to be changed.
2. Append a new iteration number key to the end of the `ITERATION_VARIABLES` dictionary in `iteration_variables.py`. The associated variable is the corresponding key value.
3. Set the variable origin file and then the associated lower and upper bounds
4. Update the `lablxc` description in `numerics.f90`.
Expand All @@ -80,7 +80,7 @@ ITERATION_VARIABLES = {

New figures of merit are added to `PROCESS` in the following way:

1. Increment the parameter `ipnfoms` in module `numerics` in source file `numerics.f90` to accommodate the new figure of merit.
1. Increment the parameter `N_FIGURES_MERIT_MAX` in module `numerics` in source file `numerics.f90` to accommodate the new figure of merit.

2. Assign a description of the new figure of merit to the relevant element of array `lablmm` in module `numerics` in the source file `numerics.f90`.

Expand Down
6 changes: 3 additions & 3 deletions documentation/source/io/input-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,16 @@ If bounds are not specified default values are used.
The user can select which solver to use, but only one solver is available at present (VMCON).

```
ioptimz = 1 * for optimisation VMCON only
i_process_run_mode = 1 * for optimisation VMCON only
```

The user can select the figure of merit to be used:

```
minmax = 1 * Switch for figure-of-merit (see lablmm for descriptions)
i_figure_merit = 1 * Switch for figure-of-merit (see lablmm for descriptions)
```

In this case the user is choosing option `1`, which is major radius. For `minmax`
In this case the user is choosing option `1`, which is major radius. For `i_figure_merit`

* a **positive** value means **minimise** the figure of merit
* a **negative** value means **maximise** the figure of merit
Expand Down
18 changes: 9 additions & 9 deletions documentation/source/solver/solver-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A PROCESS input file will, for example, define which constraint equations are be

```
...
neqns = 3
n_equality_constraints = 3

* Equalities
icc = 1 * Beta
Expand All @@ -33,7 +33,7 @@ icc = 15 * LH power threshold limit
Here each `icc=n` statement tells PROCESS to activate a constraint with the name `n`. A list of the constraints and
their corresponding names can be found [here](../../source/reference/process/data_structure/numerics/#process.data_structure.numerics.lablcc).

The `neqns = 3` statement is telling PROCESS to treat the first `3` equations as equality constraints, and the rest as inequality constraints. Therefore, it is imperative that all equality constraints are stated before any inequality constraints.
The `n_equality_constraints = 3` statement is telling PROCESS to treat the first `3` equations as equality constraints, and the rest as inequality constraints. Therefore, it is imperative that all equality constraints are stated before any inequality constraints.


In both types of equations, an optimiser/solver uses the normalised residuals $c_i$ of the constraints (and sometimes its gradient, depending on the solver/optimiser) to guide the solution towards one that satisfies all of the constraints.
Expand Down Expand Up @@ -96,19 +96,19 @@ known as the figure of merit.
Several possible figures of merit are available, all of which are in the
source file `evaluators.f90`.

Switch `minmax` is used to control which figure of merit is to be used. If the
figure of merit is to be minimised, `minmax` should be **positive**, and if a
maximised figure of merit is desired, `minmax` should be **negative**.
Switch `i_figure_merit` is used to control which figure of merit is to be used. If the
figure of merit is to be minimised, `i_figure_merit` should be **positive**, and if a
maximised figure of merit is desired, `i_figure_merit` should be **negative**.

## Convergence

...

## Optimisation mode

Switch `ioptimz` should be set to 1 for optimisation mode.
Switch `i_process_run_mode` should be set to 1 for optimisation mode.

If `ioptimz = 0`, a non-optimisation pass is performed first. Occasionally this provides a feasible set of initial conditions that aids convergence of the optimiser, but it is recommended to use `ioptimz = 1`.
If `i_process_run_mode = 0`, a non-optimisation pass is performed first. Occasionally this provides a feasible set of initial conditions that aids convergence of the optimiser, but it is recommended to use `i_process_run_mode = 1`.

Enable all the relevant consistency equations, and it is advisable to enable the corresponding iterations variables. A number of limit equations (inequality constraints) can also be activated. In optimisation mode, the number of iteration variables is unlimited.

Expand Down Expand Up @@ -137,11 +137,11 @@ Running `PROCESS` in evaluation mode requires few changes to be made to the inpu
As before, the user must decide which constraint equations and iteration variables to activate. For example, an extract from an input file might look like:
```
* Evaluation problem: evaluate models consistently by solving equality constraints only
ioptimz = -2 * evaluation mode
i_process_run_mode = -2 * evaluation mode

*---------------Constraint Equations---------------*
* Define number of equality constraints
neqns = 2
n_equality_constraints = 2

* Equalities
icc = 1 * Beta
Expand Down
8 changes: 4 additions & 4 deletions documentation/source/usage/running-process.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Running PROCESS

There are a number of ways to run PROCESS. The first two are determined by the value of the switch `ioptimz` in the input file:
There are a number of ways to run PROCESS. The first two are determined by the value of the switch `i_process_run_mode` in the input file:

`ioptimz = -2` for evaluation. The physics and engineering models are evaluated and the equality (e.g. model consistency) constraints will be solved using `scipy`'s `fsolve`. The input file and default values together define the input values of all variables. The values of the parameters used to solve the equalities (solution parameters) will be different in the solution, however. This is used when evaluating a set of input parameters (e.g. a "point") whilst ensuring that the models are self-consistent.
`i_process_run_mode = -2` for evaluation. The physics and engineering models are evaluated and the equality (e.g. model consistency) constraints will be solved using `scipy`'s `fsolve`. The input file and default values together define the input values of all variables. The values of the parameters used to solve the equalities (solution parameters) will be different in the solution, however. This is used when evaluating a set of input parameters (e.g. a "point") whilst ensuring that the models are self-consistent.

`ioptimz = 1` for optimisation. Those variables specified as iteration variables (specified by equations such as `ixc = 1` in the input file) are automatically varied during the iteration process, between the bounds given by the arrays `boundl` (lower bounds) and `boundu` (upper bounds). The input file contains the *initial* values of the iteration variables, but the final values will not be same. The iteration process continues until convergence, or until the maximum number of iterations (`maxcal`) is reached. If the code converges, the constraints will be satisfied and the Figure of Merit will be maximised or minimised.
`i_process_run_mode = 1` for optimisation. Those variables specified as iteration variables (specified by equations such as `ixc = 1` in the input file) are automatically varied during the iteration process, between the bounds given by the arrays `boundl` (lower bounds) and `boundu` (upper bounds). The input file contains the *initial* values of the iteration variables, but the final values will not be same. The iteration process continues until convergence, or until the maximum number of iterations (`maxcal`) is reached. If the code converges, the constraints will be satisfied and the Figure of Merit will be maximised or minimised.

If the optimisation fails to converge, a third option is available by using the command line option `-v` (VaryRun), together with a configuration file. PROCESS is run repeatedly in optimisation mode (`ioptimz` = 1 must be set), but a new input file is written each time, with different, randomly selected *initial* values of the iteration variables. The factor within which the initial values of the iteration variables are changed is `FACTOR` (in the configuration file). For example, `FACTOR = 1.1` will vary the initial values randomly by up to 10%. This is repeated until PROCESS converges, or until the maximum number of PROCESS runs (`NITER`) is reached. Sometimes this procedure will generate a converged solution when a single optimisation run does not.
If the optimisation fails to converge, a third option is available by using the command line option `-v` (VaryRun), together with a configuration file. PROCESS is run repeatedly in optimisation mode (`i_process_run_mode` = 1 must be set), but a new input file is written each time, with different, randomly selected *initial* values of the iteration variables. The factor within which the initial values of the iteration variables are changed is `FACTOR` (in the configuration file). For example, `FACTOR = 1.1` will vary the initial values randomly by up to 10%. This is repeated until PROCESS converges, or until the maximum number of PROCESS runs (`NITER`) is reached. Sometimes this procedure will generate a converged solution when a single optimisation run does not.

A SCAN is available in any of these modes. One input variable can be scanned (`scan_dim = 1`) or two input variables (`scan_dim = 2`). A scan variable must not be an iteration variable. For details, see ScanVariables in the [scan module](../../source/reference/process/scan).

Expand Down
6 changes: 3 additions & 3 deletions documentation/source/usage/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ The is the option to turn on extra debugging output; to do this, set `verbose =
### Optimisation problems

On reflection it is perhaps surprising that PROCESS ever does manage to find the global minimum
figure of merit value, if there are `nvar` iteration variables active the search is
over `nvar`-dimensional parameter space, in which there may be many shallow minima of approximately
equal depth. Remember that `nvar` is usually of the order of twenty.
figure of merit value, if there are `n_iteration_variables` iteration variables active the search is
over `n_iteration_variables`-dimensional parameter space, in which there may be many shallow minima of approximately
equal depth. Remember that `n_iteration_variables` is usually of the order of twenty.

The machine found by PROCESS may not, therefore, be the absolute optimal device. It is quite easy
to have two or more solutions, with results only a few percent different, but a long way apart in
Expand Down
4 changes: 2 additions & 2 deletions examples/data/large_tokamak_eval_IN.DAT
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
* Evaluation problem: evaluate models consistently by solving equality constraints only
ioptimz = -2
i_process_run_modess_run_mode = -2

*---------------Constraint Equations---------------*
* Define number of equality constraints
neqns = 2
n_equality_constraints = 2

* Equalities
icc = 1 * Beta
Expand Down
4 changes: 2 additions & 2 deletions examples/data/large_tokamak_varied_min_net_electric_IN.DAT
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
runtitle = Generic large tokamak

* Figure of merit - minimise major radius
minmax = 1
i_figure_merit = 1

* Error tolerance for VMCON
epsvmc = 1e-7

neqns = 3
n_equality_constraints = 3

* Constraint Equations - Consistency Equations *
************************************************
Expand Down
4 changes: 2 additions & 2 deletions examples/data/large_tokamak_varyrun_IN.DAT
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
runtitle = Generic large tokamak

* Figure of merit - minimise major radius
minmax = 1
i_figure_merit = 1

* Error tolerance for VMCON
epsvmc = 1e-7

neqns = 3
n_equality_constraints = 3

* Constraint Equations - Consistency Equations *
************************************************
Expand Down
2 changes: 1 addition & 1 deletion examples/data/mfile_to_csv_vars.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"vars": [
"minmax",
"i_figure_merit",
"p_hcd_injected_max",
"p_plant_electric_net_required_mw",
"ripple_b_tf_plasma_edge_max",
Expand Down
6 changes: 3 additions & 3 deletions process/core/caller.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def call_models(self, xc: np.ndarray, m: int) -> tuple[float, np.ndarray]:
for _ in range(10):
self._call_models_once(xc, self.data)
# Evaluate objective function and constraints
objf = objective_function(data_structure.numerics.minmax, self.data)
objf = objective_function(data_structure.numerics.i_figure_merit, self.data)
conf, _, _, _, _ = constraints.constraint_eqns(m, -1, self.data)

if objf_prev is None and conf_prev is None:
Expand Down Expand Up @@ -262,7 +262,7 @@ def _call_models_once(self, xc: np.ndarray, data: DataStructure):
nvars = len(xc)

# Increment the call counter
data_structure.numerics.ncalls += 1
data_structure.numerics.n_model_calls += 1

# Convert variables
set_scaled_iteration_variable(xc, nvars, self.data)
Expand Down Expand Up @@ -417,7 +417,7 @@ def write_output_files(
ifail : int
solver return code
"""
n = data_structure.numerics.nvar
n = data_structure.numerics.n_iteration_variables
x = data_structure.numerics.xcm[:n]
# Call models, ensuring output mfiles are fully idempotent
caller = Caller(models, data)
Expand Down
23 changes: 14 additions & 9 deletions process/core/final.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def finalise(models, data, ifail: int, non_idempotent_msg: str | None = None):
po.oheadr(constants.NOUT, "Final UNFEASIBLE Point")

# Output relevant to no optimisation
if numerics.ioptimz == -2:
if numerics.i_process_run_mode == -2:
output_evaluation(data)

# Print non-idempotence warning to OUT.DAT only
Expand All @@ -57,18 +57,23 @@ def output_evaluation(data):
po.oblnkl(constants.NOUT)

# Evaluate objective function
norm_objf = objective_function(numerics.minmax, data)
norm_objf = objective_function(numerics.i_figure_merit, data)
po.ovarre(constants.MFILE, "Normalised objective function", "(norm_objf)", norm_objf)

# Print the residuals of the constraint equations

residual_error, value, residual, symbols, units = constraints.constraint_eqns(
numerics.neqns + numerics.nineqns, -1, data
numerics.n_equality_constraints + numerics.n_inequality_constraints, -1, data
)

labels = [
numerics.lablcc[j]
for j in [i - 1 for i in numerics.icc[: numerics.neqns + numerics.nineqns]]
for j in [
i - 1
for i in numerics.icc[
: numerics.n_equality_constraints + numerics.n_inequality_constraints
]
]
]
physical_constraint = [f"{c} {u}" for c, u in zip(value, units, strict=False)]
physical_residual = [f"{c} {u}" for c, u in zip(residual, units, strict=False)]
Expand All @@ -83,7 +88,7 @@ def output_evaluation(data):

po.write(constants.NOUT, tabulate(table_data, headers="keys"))

for i in range(numerics.neqns):
for i in range(numerics.n_equality_constraints):
constraint_id = numerics.icc[i]
po.ovarre(
constants.MFILE,
Expand All @@ -92,11 +97,11 @@ def output_evaluation(data):
residual_error[i],
)

for i in range(numerics.nineqns):
constraint_id = numerics.icc[numerics.neqns + i]
for i in range(numerics.n_inequality_constraints):
constraint_id = numerics.icc[numerics.n_equality_constraints + i]
po.ovarre(
constants.MFILE,
f"{labels[numerics.neqns + i]}",
f"{labels[numerics.n_equality_constraints + i]}",
f"(ineq_con{constraint_id:03d})",
residual_error[numerics.neqns + i],
residual_error[numerics.n_equality_constraints + i],
)
Loading
Loading