Skip to content
Closed
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
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,13 @@ LIST(APPEND PROCESS_SRCS
heat_transport_variables.f90
buildings_variables.f90
water_usage_variables.f90
constraint_equations.f90
constants.f90
build_variables.f90
current_drive_variables.f90
pfcoil_variables.f90
structure_variables.f90
output.f90
init_module.f90
error_handling.f90
global_variables.f90
constraint_variables.f90
vacuum_variables.f90
Expand Down
26 changes: 3 additions & 23 deletions documentation/proc-pages/usage/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,10 @@ produce infeasible results; that is, the code will not find a consistent set of
The highly non-linear nature of the numerics of PROCESS is the reason for this difficulty, and
it often requires a great deal of painstaking adjustment of the input file to overcome.

<h2>Error handling</h2>

In general, errors detected during a run are handled in a consistent manner, with the code
producing useful diagnostic messages to help the user understand what has happened.

There are three levels of errors and warnings that may occur:

* **Level 1** -- An *informational* message is produced under certain conditions, for example if
the code modified the user's input choice for some reason.
* **Level 2** -- A *warning* message is produced if a non-fatal situation has occurred that may
result in an output case that is inaccurate or unreliable in some way.
* **Level 3** -- An *error* message will occur is a severe of fatal error has occurred and the program cannot continue.

These messages are printed on the screen during the course of a run, and those still active at the
final (feasible or unfeasible) solution point are also written to the end of the output file
(messages encountered during the iteration process are not copied to the output file, as the
convergence to a valid solution might resolve some of the warnings produced earlier in the
solution process).

The `error_status` variable returns the highest security level that has been encountered (or zero
if no abnormal conditions have been found); of a severe error (level 3) is flagged at any point the
program is terminated immediately. The final message number encountered during a run is returned via
output variable `error_id` . In addition, with certain messages, a number of diagnostic values may
also be given; these can be used to provide extra diagnostic information if the source code is available
producing useful diagnostic messages to help the user understand what has happened. In the case of an
unrecoverable error, PROCESS will fail with a Python exception. If the error is recoverable, a warning
will be logged that is written to the terminal and output file at the end of the run.

### General problems

Expand Down
46 changes: 29 additions & 17 deletions examples/single_model_evaluation.ipynb

Large diffs are not rendered by default.

17 changes: 10 additions & 7 deletions process/blanket_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@
build_variables,
constants,
divertor_variables,
error_handling,
fwbs_variables,
heat_transport_variables,
physics_variables,
primary_pumping_variables,
)
from process.fortran import (
error_handling as eh,
)
from process.utilities.f2py_string_patch import f2py_compatible_to_string
from process.warning_handler import WarningManager

# Acronyms for this module:
# BB Breeding Blanket
Expand Down Expand Up @@ -647,7 +644,9 @@ def thermo_hydraulic_model_pressure_drop_calculations(self, output: bool):
if (blanket_library.bllengi < (fwbs_variables.b_bz_liq * 3)) or (
blanket_library.bllengo < (fwbs_variables.b_bz_liq * 3)
):
eh.report_error(278)
WarningManager.create_warning(
"Your blanket modules are too small for the Liquid Metal pipes"
)

# Unless there is no IB blanket...
else:
Expand All @@ -661,7 +660,9 @@ def thermo_hydraulic_model_pressure_drop_calculations(self, output: bool):
) / fwbs_variables.nopipes
# Poloidal
if blanket_library.bllengo < (fwbs_variables.b_bz_liq * 3):
eh.report_error(278)
WarningManager.create_warning(
"Your blanket modules are too small for the Liquid Metal pipes"
)

# Calculate total flow lengths, used for pressure drop calculation
# Blanket primary coolant flow
Expand Down Expand Up @@ -1345,7 +1346,9 @@ def liquid_breeder_properties(self, output: bool = False):
(t_ranges[:, 0] > mid_temp_liq).any()
or (t_ranges[:, 1] < mid_temp_liq).any()
):
error_handling.report_error(280)
WarningManager.create_warning(
"Outside temperature limit for one or more liquid metal breeder properties"
)

if output:
po.ocmmnt(
Expand Down
64 changes: 40 additions & 24 deletions process/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
constants,
current_drive_variables,
divertor_variables,
error_handling,
fwbs_variables,
numerics,
pfcoil_variables,
physics_variables,
tfcoil_variables,
)
from process.variables import AnnotatedVariable
from process.warning_handler import WarningManager

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -101,9 +101,9 @@ def portsz(self):
current_drive_variables.rtanmax = f * np.cos(eps) - 0.5e0 * c

else: # coil separation is too narrow for beam...
error_handling.fdiags[0] = g
error_handling.fdiags[1] = c
error_handling.report_error(63)
WarningManager.create_warning(
"Max beam tangency radius set =0 temporarily; change beamwd", g=g, c=c
)

current_drive_variables.rtanmax = 0.0e0

Expand Down Expand Up @@ -1758,9 +1758,11 @@ def calculate_radial_build(self, output: bool) -> None:

# Notify user that build_variables.r_cp_top has been set to 1.01*build_variables.r_tf_inboard_out (lvl 2 error)
if build_variables.r_cp_top < 1.01e0 * build_variables.r_tf_inboard_out:
error_handling.fdiags[0] = build_variables.r_cp_top
error_handling.fdiags[1] = build_variables.r_tf_inboard_out
error_handling.report_error(268)
WarningManager.create_warning(
"TF CP top radius (r_cp_top) replaced by 1.01*r_tf_inboard_out -> potential top rbuild issue",
r_cp_top=build_variables.r_cp_top,
r_tf_inboard_out=build_variables.r_tf_inboard_out,
)

# build_variables.r_cp_top correction
build_variables.r_cp_top = build_variables.r_tf_inboard_out * 1.01e0
Expand All @@ -1774,9 +1776,11 @@ def calculate_radial_build(self, output: bool) -> None:
elif build_variables.i_r_cp_top == 1:
# Notify user that build_variables.r_cp_top has been set to 1.01*build_variables.r_tf_inboard_out (lvl 2 error)
if build_variables.r_cp_top < 1.01e0 * build_variables.r_tf_inboard_out:
error_handling.fdiags[0] = build_variables.r_cp_top
error_handling.fdiags[1] = build_variables.r_tf_inboard_out
error_handling.report_error(268)
WarningManager.create_warning(
"TF CP top radius (r_cp_top) replaced by 1.01*r_tf_inboard_out -> potential top rbuild issue",
r_cp_top=build_variables.r_cp_top,
r_tf_inboard_out=build_variables.r_tf_inboard_out,
)

# build_variables.r_cp_top correction
build_variables.r_cp_top = build_variables.r_tf_inboard_out * 1.01e0
Expand Down Expand Up @@ -1810,8 +1814,10 @@ def calculate_radial_build(self, output: bool) -> None:
)
+ tfcoil_variables.drtop
):
error_handling.fdiags[0] = build_variables.r_cp_top
error_handling.report_error(256)
WarningManager.create_warning(
"Top CP radius larger that its value determined with plasma shape",
r_cp_top=build_variables.r_cp_top,
)
if build_variables.i_tf_inside_cs == 1:
# Radial position of vacuum vessel [m]
build_variables.r_vv_inboard_out = (
Expand Down Expand Up @@ -2065,24 +2071,34 @@ def calculate_radial_build(self, output: bool) -> None:
)
po.ocmmnt(self.outfile, " its range of applicability.)")
po.oblnkl(self.outfile)
error_handling.report_error(62)
WarningManager.create_warning(
"Ripple result may be inaccurate, as the fit has been extrapolated"
)

if self.ripflag == 1:
error_handling.fdiags[0] = (
tfcoil_variables.wwp1
* tfcoil_variables.n_tf_coils
/ physics_variables.rmajor
WarningManager.create_warning(
"(TF coil ripple calculation) Dimensionless coil width X out of fitted range",
diagnostic=(
tfcoil_variables.wwp1
* tfcoil_variables.n_tf_coils
/ physics_variables.rmajor
),
)
error_handling.report_error(141)

elif self.ripflag == 2:
# Convert to integer as idiags is integer array
error_handling.idiags[0] = int(tfcoil_variables.n_tf_coils)
error_handling.report_error(142)
WarningManager.create_warning(
"(TF coil ripple calculation) No of TF coils not between 16 and 20 inclusive",
n_tf_coils=tfcoil_variables.n_tf_coils,
)
else:
error_handling.fdiags[0] = (
physics_variables.rmajor + physics_variables.rminor
) / build_variables.r_tf_outboard_mid
error_handling.report_error(143)
WarningManager.create_warning(
"(TF coil ripple calculation) (R+a)/rtot out of fitted range",
diagnostic=(
(physics_variables.rmajor + physics_variables.rminor)
/ build_variables.r_tf_outboard_mid
),
)

po.ovarin(
self.outfile,
Expand Down
6 changes: 5 additions & 1 deletion process/caller.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import numpy as np
from tabulate import tabulate

import process.constraints as constraints
from process import fortran as ft
from process.final import finalise
from process.io.mfile import MFile
Expand Down Expand Up @@ -75,7 +76,10 @@ def call_models(self, xc: np.ndarray, m: int) -> tuple[float, np.ndarray]:
self._call_models_once(xc)
# Evaluate objective function and constraints
objf = objective_function(ft.numerics.minmax)
conf, _, _, _, _ = ft.constraints.constraint_eqns(m, -1)
conf, _, _, _, _ = constraints.constraint_eqns(m, -1)

# PyVMCON and other bits of PROCESS require a numpy array
conf = np.array(conf)

if objf_prev is None and conf_prev is None:
# First run: run again to check idempotence
Expand Down
Loading
Loading