Figure 1: Demonstration how scripts can be used across multiple projects (if validated and verified)
One of the key benefits of scripting is the potential to automate. Scripting allows for a large amount of designs to be completed in a shorter period. However, the initial setup time can take longer for individual scripts. To reduce setup time rather than each project starting from scratch, consider developing shared libraries of analysis and design modules that can be imported and reused across multiple projects.
At present, many engineers write scripts where a single file handles all aspects of a calculation such as inputs, analysis, design checks, and formatting. This approach makes reuse difficult and often leads to copy-pasting between scripts, increasing the risk of error. When all components of a workflow are bundled into a single script, it becomes harder to test individual parts, increasing the likelihood that errors go unnoticed. This approach also adds cognitive load, making the script more difficult to understand and maintain, while raising the risk of version control conflicts and hidden dependencies that can lead to subtle, hard-to-trace bugs.
Consider the structural analysis of two simply supported beams, one in concrete and one in timber. These will involve the same calculations for analysing shear, bending moment, and deflection. Similarly, the design equations for two different concrete elements, such as a beam and a column, will share many common design checks.
Best practice is to separate the calculation process from the equations themselves where verified equations can be imported as reusable blocks. This forms a hierarchy of reusable modules which can be checked in more easily understandable chunks during their creation.
Figure 2: By using modular building blocks scripting becomes more efficient
A modular structure promotes reuse, improves consistency, and makes it easier to validate and review each component independently. By validating individual equations or modules, engineers can focus system-level validation on the overall process rather than the underlying calculations. This layered approach also simplifies future updates, as changes can be made to specific components without affecting the entire script.
Nine principle are set out here, while it may not be possible to follow all nine in every scenario this aims to provide guidance on how scripts can be setup with the aim of improving structural safety.
1) Document design codes and reference standards
Clear documentation ties the script to the design or analysis requirements. In safety-critical development all scripts should be traceable to the original requirements.
At the top of the document, a description should be added to describe what the script in the file is supposed to do. Well documenting scripts is widely recognized as crucial for reliability, and it lets anyone verifying it know that the implementation matches the engineer’s intent and the governing standard.
For design standard equations, always provide a clear reference and include descriptive attributes for each equation used. For analysis, specify the exact equation applied; if it is non-conventional, cite the source. If an Application Programming Interface (API) to software is used, include the software name, version number, and the solver or algorithm type (e.g., linear analysis, non-linear analysis, modal analysis).
2) Validate inputs early
Scripts must “fail fast” on bad inputs so errors don’t silently propagate. Checking argument types and meaning reduces the risk of multiplying apples by oranges. Although, it doesn’t guarantee that it is the right apple. Input validation helps ensure that the data being processed is accurate and free from errors, which is crucial in safety-critical calculations.
The three things to look out for with inputs:
- Is the input the right parameter?
Has a force been input where a length should be. Is it the right force?
- Are the input units correct?
This one applies only if the formula requires a specific unit for inputs.
- Is the input class correct?
Most scripting languages will fail if the wrong type of input is given. However, some languages like python are more flexible and a manual check will need to be added.
The consequences of incorrect inputs decreases if the inputs are validated by the script, and the outputs verified by the user. Having validation checks as part of the script does not mean errors wont sneak through but it adds a layer of built-in protection.
Figure 3: Making validation of the inputs part of the script makes it easier to catch errors, although additional verification of the output is always needed.
When something is wrong, the script should tell us exactly what and where. Instead of letting the script throw a generic exception provide relevant information:
- What type of error has occurred. Is it related to the class, type, value, units?
- A description of the error that lets the user know what the mistake is and how to fix it.
“The input should be type ‘int’.”
This does not give any context as to why the script has failed or where. It is meaningless.
“Argument ‘Fx’ must be of type ‘int’, not ‘string’.”
This lets the script know which input is wrong and why.
Error messages should be meaningful and provide enough context to understand what exactly went wrong. The snippet above exemplifies this by naming the bad argument and its expected form, so errors are caught and reported in context.
Logging gives a narrative output of what the script is doing, this invaluable for later checking (and debugging).
This means that when the code runs you can see exactly what values went in and what came out. Such logs are valuable for debugging issues, diagnosing errors, and auditing because they provide a history of the computation.
In practice, if a calculation looks off, an engineer can check these debug logs to trace the flow of data through the formula. These lines ensure that anyone reviewing a log can follow exactly what inputs produced what outputs, enhancing confidence in the result.
In structural engineering, inconsistent units can lead to disastrous outcomes. Maintaining unit consistency throughout all calculations is essential, as even minor mistakes can have severe consequences. Centralizing unit handling and carrying units through calculations helps guard against errors, and engineers routinely double-check conversions, because unit mistakes can jeopardize safety and result in significant costs.
This one may seem obvious, the core calculation must be understandable in the script to someone reading it. Straightforward implementation means the script is doing precisely what the design code formula dictates. This is essential so any checker, or new team member, can quickly confirm the correct equation being used is correct.
Consistency in output format is crucial. If one script returns an array, another a single value, and another text, users are left guessing. Adopting a standard structure makes data easier to access, understand, and use. Consistent outputs also streamline peer review and debugging.
When everyone knows what to expect, it’s easier to trace errors, compare results, and ensure reliability. Standardized conventions improve usability, transparency, and overall workflow quality.
Consider making your outputs more meaningful. Ideally, they should return an object that includes the numerical result, its units, and relevant references. While this level of detail may not be necessary in every scenario, using objects and classes helps ensure that all results carry essential metadata for future checks or calculations.
Consider creating a custom object that stores information in a consistent format. Including context alongside input and output parameters makes the results far more useful and meaningful than returning only a raw numerical value.
Figure 4: For languages that allow it custom classes are useful to return more information than a single output.
As an example, here is the output from a script which returns an object vs a script that returns a single value. Which would be more useful to you?
The table below summarizes what parameters might be needed for a custom class depending on its use case:
Table 1: Suggested parameters that can be captured in the output of a script.
| |
Analysis Equations |
Design Equations |
Values
(Design or Analysis) |
Factors
(Design or Analysis) |
Parameters required
“Provides basic information for users” |
Formula |
Design Standard
Equation Number |
Meaningful Names
Numerical Values
Units |
Meaningful Names
Numerical Values |
Parameters recommended
“Additional information for users” |
Source
Software*
Version*
Solver Type* |
Section
Subsection
Clause |
Sources |
Sources |
Further parameters
“Improves understanding for users” |
Assumptions Applicability |
Assumptions |
Tolerances
Limits |
Description of Purpose |
* If using another piece of software to do the analysis include information about the software should be included for traceability.
Finally, the script should present results, whether this is done through a designed user interface or through outputs in a console window, the results should show unambiguously and clearly:
An example of this in a user interface:
Figure 5: When setting up a user interface provide context for the user.
An example of this from a console interface:
Figure 6: If you prefer to have a console or text based output ensure that the calculations can be checked by the user.
As a checking engineer, your role in the validation and verification of structural engineering scripts is critical for ensuring that they are accurate, reliable, and reusable. The following are nine principles, independent of who authored the script, that should guide how you check such code:
The nine principles above should be clearly followed. If you’re unable to find one of the principles, then ask the author of the script to add in commentary that makes it clearer. The script and comments should read like a narrative.
Anyone using the script needs to understand, and check it, this may happen years in the future when the original author is not around to explain what the script does. To avoid confusion, make sure that:
- There is information at the top of the file that explains what it does, the inputs, and the expected outputs.
- All the abbreviations used are listed in a central glossary or documentation. These abbreviations and definitions should ideally match the definitions defined in the design codes and standards.
Good testing can prevent future errors, any script should be tested for both success and failure cases. A good checker will test conditions where the script should and should not work this can be done by testing edge cases such as:
- Zero values,
- Negatives,
- Unrealistic extremes,
- or uncommon units.
Ideally a checker would setup a unit test to ensure the script:
- Using a known unit testing framework,
- Test invalid inputs to verify error handling and check the script raises correct exceptions,
- Test valid inputs and compare the output against an expected result.
Unlike traditional calculations, scripts can become “black boxes,” but they don’t have to. Logging is essential for debugging and tracing unexpected outputs during reuse. Ensure logs capture key steps, such as input parsing and output calculation. If the log doesn’t clearly narrate what the script is doing, add more detail.
Error reporting is equally critical. When a script encounters an error, it must clearly indicate what went wrong, where it occurred, and how to fix it. Review error messages during testing to confirm they are informative. A script that continues running after an error can be dangerous and should be avoided.