3.1 Verification

Verification tests check that the simulation model has been implemented consistently. In other words, verification tests check that the math of the simulator is consistent with the intended governing equations. These tests do not test that the governing equations are appropriate in the first place, which is done through BlasterSim’s validation tests.

3.1.1 Run-time consistency checks

Every time step, BlasterSim performs internal consistency checks to alert the user if the simulation is becoming inaccurate in a detectable way. If an error is detected, BlasterSim terminates the simulation and prints out the return code. These checks are made in the check_sys subroutine of cva.f90. See § 1.5 for details.

3.1.2 Debugging run-time assertions

BlasterSim contains hundreds of run-time assertions which perform deeper internal consistency checks. These additional checks are disabled in the released versions of BlasterSim for speed but are enabled during all developer testing runs for debugging purposes.

3.1.3 Fuzz testing

BlasterSim is periodically tested with randomly generated input files, which is called fuzz testing. Fuzz testing has mostly improved BlasterSim’s robustness and had no impact on the correctness of the result. Before fuzz testing, BlasterSim would crash on certain inputs either due to mass or energy going negative in a control volume, the energy conservation tolerance being violated, or an invalid floating point operation, for example. These errors were mostly solved by adding stricter input validation to catch physically impossible inputs (that the fuzz tester itself can not know are physically impossible), better internal error detection and reporting, adding adaptive time stepping in response to mass and energy conservation errors reaching a certain threshold, and improving the numerical stability of floating point operations. These robustness improvements will be useful when design optimization is added as an optimizer is similar to a fuzz tester in that it will try many strange inputs, and BlasterSim not crashing is necessary for the process to continue.

3.1.4 Compile-time unit checking

Variables in BlasterSim are assigned units like meters or seconds, allowing the Fortran compiler to check for inconsistencies. This is achieved through a system called genunits which generates a custom Fortran module containing the required Fortran types [15, 16]. This system has proved useful to locate bugs as the compiler will often know precisely where the unit inconsistency is. A failing test will rarely provide such precision.

Some examples will illustrate how this works from the programmer’s perspective. Consider the following Fortran code:

program test_units_pass
use units
implicit none
type(si_length) :: x
type(si_time) :: t
type(si_velocity) :: v
x%v = 1.0
t%v = 1.0
v = x / t
print "(f3.1)", v
end program test_units_pass

The units module contains Fortran derived types and associated operations which allow for unit checking. When test_units_pass.f90 is compiled and run, the following output is produced:

1.0

However, consider what happens the velocity v is given the wrong unit:

program test_units_fail
use units
implicit none
type(si_length) :: x, v
type(si_time) :: t
x%v = 1.0
t%v = 1.0
v = x / t
print "(f3.1)", v
end program test_units_fail

test_units_fail.f90 will not compile, returning the following when compiled with gfortran :

test_units_fail.f90:12:4:
12 | v = x / t
| 1
Error: Cannot convert TYPE(si_velocity) to TYPE(si_length) at (1)

The compiler error message quickly tells the programmer that this code has a bug. In this case, the bug is in the variable definition and not in the highlighted line, however, often the compiler will identify precisely which term in the line has the bug.

The specific units used in cva.f90 and BlasterSim’s core simulation procedures otherwise are SI units. BlasterSim input and output may use other units, but the genunits types themselves represent SI units.

3.1.5 Verification test suite

The test suite mentioned at the start of § 3 has 390  the vast majority of which are verification tests checking that various functions and subroutines of BlasterSim produce the expected results. This section details some of the more important verification tests.

Comparison with single control volume exact solution

To test that the time integration in BlasterSim is working correctly, an exact solution for a simple case was constructed. This case has only two control volumes, one for the barrel, and one for the atmosphere. See figure 3.1 for an illustration of this test case.

xbarrelatmosphere
Figure 3.1: Single control volume test case.

The barrel is initially filled with pressurized gas and the projectile has both dynamic and static friction pressure set to pf. The tube has a constant cross-sectional area of A, so the volume of the barrel is V=Ax. The gas is ideal with a constant ratio of specific heats, γ, and the process is adiabatic, so pVγ=constant in the barrel [8, p. 129, eq. 3.53]. So for any time t, the pressure in the barrel is

p0(Ax0)γ=p(t)(Ax(t))γ, (3.1)

which can be rearranged and simplified to

p(t)=p0(x0x(t))γ, (3.2)

where P0 and x0 are the initial pressure and projectile position, respectively.

The equation of motion of the projectile is

mpdx˙dt =A(p(t)patmpf), (3.3)
=A[p0(x0x(t))γpatmpf]. (3.4)

The trick dx˙dtdx=x˙dx˙ can be applied to solve this nonlinear differential equation for x˙ as a function of x rather than t. Substituting in the trick returns

mpx˙dx˙=A[p0(x0x)γpatmpf]dx. (3.5)

Now integrate from an initial velocity (x˙0):

x˙0x˙mpx˙^dx˙^=x0xA[p0(x0x^)γpatmpf]dx^. (3.6)

Evaluating the integrals returns the projectile kinetic energy as a function of x:

12mpx˙2=12mpx˙02+A[p0(x0γx1γx0)1γ(patm+pf)(xx0)]. (3.7)

In terms of the projectile velocity, the result is

x˙=x˙02+2Amp[p0(x0γx1γx0)1γ(patm+pf)(xx0)]. (3.8)

This case was implemented in test_cva.f90 in the subroutine test_exact. For Δt=27.3106 s, the numerical error was measured at 0.484109 m/s, which is negligible. The numerical order-of-accuracy was measured at 4.012, which is close to the theoretically expected order-of-accuracy of 4 for the RK4 integrator. In other words, not only does BlasterSim closely match the exact solution, but BlasterSim’s numerical error decreases at the theoretically expected rate as the time step decreases. This is the most rigorous test that can be made with an exact solution. For more information on order-of-accuracy verification, see Roy [10, § 2.3].

Comparison with plunger impact exact solution

m˙pxAgas
Figure 3.2: Plunger impact test case.

In figure 3.2, a constant velocity (x˙1) plunger is approaching the end of the plunger tube. In BlasterSim, a constant velocity plunger can be created by making the plunger have infinite mass, so no force will be able to change the plunger’s velocity. The mass flow rate out of the plunger tube is set to a constant m˙ defined so that it perfectly balances the plunger mass flow rate:

m˙=ρ1Ax˙1. (3.9)

Note that x˙1 is negative here, so m˙ is positive. Because m˙, A, and x˙1, are constant, ρ1 is necessarily also constant. The internal energy u1 and temperature T1 also end up being constant due to the balance of the mass flow rate, but the derivation is omitted for brevity.

Equation 3.9 will necessarily be the mass flow rate as x approaches 0 because there will be no volume to absorb the difference between the plunger mass flow rate and the mass flow rate out of the plunger tube, so this test case should approximate conditions as the plunger approaches impact. Note that for numerical reasons, the minimum x position of the plunger will be xmin, which is greater than zero, as discussed in § 2.1.9, so x will not actually approach zero.

The solution before impact is:

m(t) =ρ1A(x0+x˙1t), (3.10)
E(t) =ρ1Au(x0+x˙1t), (3.11)
x(t) =x0+x˙1t, (3.12)
x˙(t) =x˙1, (3.13)
u(t) =u1, (3.14)
ρ(t) =ρ1, (3.15)

where x0 is the initial plunger position.

The plunger impacts the end of the plunger tube at time

timpact=xminx0x˙1. (3.16)

The solution after plunger impact might not be possible to express in closed form and is not of particular interest aside from the plunger velocity after impact, x˙2=epx˙1.

The solution in this case is simply a series of linear algebraic equations, and BlasterSim solves these equations extremely accurately even for large time steps. Consequently, the order-of-accuracy test used in § 3.1.5 can not be applied as the numerical error is negligible. After the plunger has moved for 0.10 s (which is well before plunger impact), the error in m is 3.1091015 kg, the error in E is 2.298 J (negligible compared against the expected energy of 1.441106 J), the error in x is 0.0 m, and the error in x˙ is 0.0 m/s. The error in timpact is 2.9161012 s. Immediately after impact, the error in x˙ is 0.0 m/s.