Пример #1
0
    def test_capitalization_species_target(self):
        """Test that species targets with capitalization not matching model works.
        """
        file_path = os.path.join('testfile_st2.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        # ignition target is OH

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        file_path = os.path.join('h2o2-lowercase.cti')
        mechanism_filename = pkg_resources.resource_filename(
            __name__, file_path)
        SPEC_KEY = {'H2': 'h2', 'O2': 'o2', 'N2': 'n2', 'Ar': 'ar'}

        sim = simulations[0]
        sim.setup_case(mechanism_filename, SPEC_KEY)

        # oh is species index 4
        assert sim.properties.ignition_target == 4

        # now try for uppercase in model and lowercase in file.
        properties = ChemKED(filename)
        properties.datapoints[0].ignition_type['target'] = 'oh'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}
        simulations = create_simulations(filename, properties)
        sim = simulations[0]
        sim.setup_case('h2o2.cti', SPEC_KEY)

        # oh is species index 4
        assert sim.properties.ignition_target == 4
Пример #2
0
    def test_shock_tube_temperature_target_setup_case(self):
        """Test that shock tube case with temperature target set up properly.
        """
        file_path = os.path.join('testfile_st.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        properties.datapoints[0].ignition_type['target'] = 'temperature'
        properties.datapoints[1].ignition_type['target'] = 'temperature'

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        mechanism_filename = 'gri30.xml'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}

        sim = simulations[0]
        sim.setup_case(mechanism_filename, SPEC_KEY)

        # Only thing different from last test: ignition target is temperature
        assert sim.properties.ignition_target == 'temperature'

        sim = simulations[1]
        sim.setup_case(mechanism_filename, SPEC_KEY)

        # Only thing different from last test: ignition target is temperature
        assert sim.properties.ignition_target == 'temperature'
Пример #3
0
    def test_shock_tube_setup_case(self):
        """Test that shock tube cases are set up properly.
        """
        file_path = os.path.join('testfile_st.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        assert len(simulations) == 5

        mechanism_filename = 'gri30.xml'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}

        gas = ct.Solution(mechanism_filename)

        sim = simulations[0]
        sim.setup_case(mechanism_filename, SPEC_KEY)

        init_pressure = 220. * units.kilopascal

        assert sim.apparatus == 'shock tube'
        assert np.allclose(sim.time_end, 4.7154e-2)
        assert np.allclose(sim.gas.T, 1164.48)
        assert np.allclose(sim.gas.P, init_pressure.to('pascal').magnitude)
        mass_fracs = np.zeros(sim.gas.n_species)
        mass_fracs[sim.gas.species_index(SPEC_KEY['H2'])] = 0.00444
        mass_fracs[sim.gas.species_index(SPEC_KEY['O2'])] = 0.00556
        mass_fracs[sim.gas.species_index(SPEC_KEY['Ar'])] = 0.99
        assert np.allclose(sim.gas.X, mass_fracs)
        # no wall velocity
        times = np.linspace(0., sim.time_end, 100)
        for time in times:
            assert np.allclose(sim.reac.walls[0].vdot(time), 0.0)
        assert sim.n_vars == gas.n_species + 3

        assert sim.properties.ignition_target == 'pressure'
        assert sim.properties.ignition_type == 'd/dt max'

        sim = simulations[1]
        sim.setup_case(mechanism_filename, SPEC_KEY)

        assert sim.apparatus == 'shock tube'
        assert np.allclose(sim.time_end, 4.4803e-2)
        assert np.allclose(sim.gas.T, 1164.97)
        assert np.allclose(sim.gas.P, init_pressure.to('pascal').magnitude)
        mass_fracs = np.zeros(sim.gas.n_species)
        mass_fracs[sim.gas.species_index(SPEC_KEY['H2'])] = 0.00444
        mass_fracs[sim.gas.species_index(SPEC_KEY['O2'])] = 0.00556
        mass_fracs[sim.gas.species_index(SPEC_KEY['Ar'])] = 0.99
        assert np.allclose(sim.gas.X, mass_fracs)
        # no wall velocity
        times = np.linspace(0., sim.time_end, 100)
        for time in times:
            assert np.allclose(sim.reac.walls[0].vdot(time), 0.0)
        assert sim.n_vars == gas.n_species + 3

        assert sim.properties.ignition_target == 'pressure'
        assert sim.properties.ignition_type == 'd/dt max'
Пример #4
0
    def test_shock_tube_pressure_rise_setup_case(self):
        """Test that shock tube case with pressure rise is set up properly.
        """
        file_path = os.path.join('testfile_st2.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        assert len(simulations) == 1

        mechanism_filename = 'gri30.xml'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}

        init_temp = 1264.2
        init_pres = 2.18 * ct.one_atm

        gas = ct.Solution(mechanism_filename)

        sim = simulations[0]
        sim.setup_case(mechanism_filename, SPEC_KEY)

        assert sim.apparatus == 'shock tube'
        assert np.allclose(sim.time_end, 2.9157e-2)
        assert np.allclose(sim.gas.T, init_temp)
        assert np.allclose(sim.gas.P, init_pres)
        mass_fracs = np.zeros(sim.gas.n_species)
        mass_fracs[sim.gas.species_index(SPEC_KEY['H2'])] = 0.00444
        mass_fracs[sim.gas.species_index(SPEC_KEY['O2'])] = 0.00556
        mass_fracs[sim.gas.species_index(SPEC_KEY['Ar'])] = 0.99
        assert np.allclose(sim.gas.X, mass_fracs)
        assert sim.n_vars == gas.n_species + 3

        # Check constructed velocity profile
        [times, volumes] = simulation.create_volume_history(
            mechanism_filename, init_temp, init_pres,
            'H2:0.00444,O2:0.00566,AR:0.9899', 0.10 * 1000., sim.time_end)
        volumes = volumes / volumes[0]
        dVdt = simulation.first_derivative(times, volumes)
        velocities = np.zeros(times.size)
        for i, time in enumerate(times):
            velocities[i] = sim.reac.walls[0].vdot(time)
        assert np.allclose(dVdt, velocities, rtol=1e-3)
Пример #5
0
    def test_rcm_run_cases(self):
        """Test that RCM case runs correctly.
        """
        # Read experiment XML file
        file_path = os.path.join('testfile_rcm.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        mechanism_filename = 'gri30.xml'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}

        # Setup and run each simulation
        with TemporaryDirectory() as temp_dir:
            sim = simulations[0]
            sim.setup_case(mechanism_filename, SPEC_KEY, path=temp_dir)
            sim.run_case()

            # check for presence of data file
            assert os.path.exists(sim.meta['save-file'])
            with tables.open_file(sim.meta['save-file'], 'r') as h5file:
                # Load Table with Group name simulation
                table = h5file.root.simulation

                # Ensure exact columns present
                assert set([
                    'time', 'temperature', 'pressure', 'volume',
                    'mass_fractions'
                ]) == set(table.colnames)
                # Ensure final state matches expected
                time_end = 1.0e-1
                temp = 2385.3726323703772
                pres = 7785283.273098443
                mass_fracs = np.array([
                    1.20958787e-04, 2.24531172e-06, 1.00369447e-05,
                    5.22700388e-04, 4.28382158e-04, 6.78623202e-02,
                    4.00112919e-07, 1.46544920e-07, 1.20831350e-32,
                    3.89605241e-34, -3.39400724e-33, -2.46590209e-34,
                    -1.74786488e-31, -5.36410698e-31, 4.72585636e-27,
                    7.94725956e-26, 5.20640355e-33, 2.16633481e-32,
                    2.74982659e-34, 5.20547210e-35, 5.96795929e-33,
                    -2.98353670e-48, -1.16084981e-45, -2.33518734e-48,
                    -6.38881605e-47, -3.09502377e-48, -8.14011410e-48,
                    -6.95137295e-47, -8.71647858e-47, -3.34677877e-46,
                    2.05479180e-09, 1.59879068e-09, 2.45613053e-09,
                    2.06962550e-08, 2.82124731e-09, 4.55692132e-04,
                    3.22230699e-07, 1.49833621e-07, 5.93547268e-08,
                    -2.74353105e-33, -1.17993222e-30, -5.51437143e-36,
                    -9.13974801e-37, -1.97028722e-31, -9.69084296e-32,
                    -1.31976752e-30, -2.12060990e-32, 1.55792718e-01,
                    7.74803838e-01, 2.72630502e-66, 2.88273784e-67,
                    -2.18774836e-50, -1.47465442e-48
                ])
                assert np.allclose(table.col('time')[-1], time_end)
                assert np.allclose(table.col('temperature')[-1],
                                   temp,
                                   rtol=1e-5,
                                   atol=1e-9)
                assert np.allclose(table.col('pressure')[-1],
                                   pres,
                                   rtol=1e-5,
                                   atol=1e-9)
                assert np.allclose(table.col('mass_fractions')[-1],
                                   mass_fracs,
                                   rtol=1e-4,
                                   atol=1e-8)
Пример #6
0
    def test_shock_tube_pressure_rise_run_cases(self):
        """Test that shock tube cases with pressure rise run correctly.
        """
        # Read experiment XML file
        file_path = os.path.join('testfile_st2.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        mechanism_filename = 'gri30.xml'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}

        # Setup and run each simulation
        with TemporaryDirectory() as temp_dir:
            sim = simulations[0]
            sim.setup_case(mechanism_filename, SPEC_KEY, path=temp_dir)
            sim.run_case()

            # check for presence of data file
            assert os.path.exists(sim.meta['save-file'])
            with tables.open_file(sim.meta['save-file'], 'r') as h5file:
                # Load Table with Group name simulation
                table = h5file.root.simulation

                # Ensure exact columns present
                assert set([
                    'time', 'temperature', 'pressure', 'volume',
                    'mass_fractions'
                ]) == set(table.colnames)

                # Ensure final state matches expected
                time_end = 2.9157e-2
                temp = 2305.9275837885516
                pres = 915452.1978990212
                mass_fracs = np.array([
                    2.55673782e-06, 5.70019832e-07, 3.73361152e-05,
                    2.61559579e-03, 1.30748753e-04, 1.91579133e-03,
                    1.04724319e-07, 2.70985419e-09, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    9.95297294e-01, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00
                ])
                assert np.allclose(table.col('time')[-1], time_end)
                assert np.allclose(table.col('temperature')[-1], temp)
                assert np.allclose(table.col('pressure')[-1], pres)
                assert np.allclose(table.col('mass_fractions')[-1],
                                   mass_fracs,
                                   rtol=1e-5,
                                   atol=1e-9)
Пример #7
0
    def test_shock_tube_run_cases(self):
        """Test that shock tube cases run correctly.
        """
        # Read experiment XML file
        file_path = os.path.join('testfile_st.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        mechanism_filename = 'gri30.xml'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}

        # Setup and run each simulation
        with TemporaryDirectory() as temp_dir:
            sim = simulations[0]
            sim.setup_case(mechanism_filename, SPEC_KEY, path=temp_dir)
            sim.run_case()

            # check for presence of data file
            assert os.path.exists(sim.meta['save-file'])
            with tables.open_file(sim.meta['save-file'], 'r') as h5file:
                # Load Table with Group name simulation
                table = h5file.root.simulation

                # Ensure exact columns present
                assert set([
                    'time', 'temperature', 'pressure', 'volume',
                    'mass_fractions'
                ]) == set(table.colnames)

                # Ensure final state matches expected
                time_end = 4.7154e-2
                temp = 1250.440275095967
                pres = 235715.78371450436
                mass_fracs = np.array([
                    3.78280811e-09, 6.55635749e-11, 3.88632912e-08,
                    2.68924922e-03, 9.14481216e-07, 2.01249201e-03,
                    7.30336393e-09, 4.48899838e-10, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    9.95297294e-01, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00
                ])
                assert np.allclose(table.col('time')[-1], time_end)
                assert np.allclose(table.col('temperature')[-1], temp)
                assert np.allclose(table.col('pressure')[-1], pres)
                assert np.allclose(table.col('mass_fractions')[-1],
                                   mass_fracs,
                                   rtol=1e-5,
                                   atol=1e-9)

            sim = simulations[1]
            sim.setup_case(mechanism_filename, SPEC_KEY, path=temp_dir)
            sim.run_case()

            assert os.path.exists(sim.meta['save-file'])
            with tables.open_file(sim.meta['save-file'], 'r') as h5file:
                # Load Table with Group name simulation
                table = h5file.root.simulation

                # Ensure exact columns present
                assert set([
                    'time', 'temperature', 'pressure', 'volume',
                    'mass_fractions'
                ]) == set(table.colnames)

                # Ensure final state matches expected
                time_end = 4.4803e-2
                temp = 1250.9289794273782
                pres = 235708.7300698561
                mass_fracs = np.array([
                    4.09616997e-09, 7.26607683e-11, 4.16076690e-08,
                    2.68923307e-03, 9.47551606e-07, 2.01247148e-03,
                    7.82886351e-09, 4.77404824e-10, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                    9.95297294e-01, 0.00000000e+00, 0.00000000e+00,
                    0.00000000e+00, 0.00000000e+00
                ])
                assert np.allclose(table.col('time')[-1], time_end)
                assert np.allclose(table.col('temperature')[-1], temp)
                assert np.allclose(table.col('pressure')[-1], pres)
                assert np.allclose(table.col('mass_fractions')[-1],
                                   mass_fracs,
                                   rtol=1e-5,
                                   atol=1e-9)
Пример #8
0
    def test_rcm_setup_case(self):
        """Test that RCM case is set up properly.
        """
        file_path = os.path.join('testfile_rcm.yaml')
        filename = pkg_resources.resource_filename(__name__, file_path)
        properties = ChemKED(filename)

        # Now create list of Simulation objects
        simulations = create_simulations(filename, properties)

        assert len(simulations) == 1

        mechanism_filename = 'gri30.xml'
        SPEC_KEY = {'H2': 'H2', 'O2': 'O2', 'N2': 'N2', 'Ar': 'AR'}

        gas = ct.Solution(mechanism_filename)

        sim = simulations[0]
        sim.setup_case(mechanism_filename, SPEC_KEY)

        assert sim.apparatus == 'rapid compression machine'
        assert np.allclose(sim.time_end, 0.1)
        assert np.allclose(sim.gas.T, 297.4)
        assert np.allclose(sim.gas.P, 127722.83)
        mass_fracs = np.zeros(sim.gas.n_species)
        mass_fracs[sim.gas.species_index(SPEC_KEY['H2'])] = 0.12500
        mass_fracs[sim.gas.species_index(SPEC_KEY['O2'])] = 0.06250
        mass_fracs[sim.gas.species_index(SPEC_KEY['N2'])] = 0.18125
        mass_fracs[sim.gas.species_index(SPEC_KEY['Ar'])] = 0.63125
        assert np.allclose(sim.gas.X, mass_fracs)

        times = np.arange(0, 9.7e-2, 1.e-3)
        volumes = np.array([
            5.47669375000E+002, 5.46608789894E+002, 5.43427034574E+002,
            5.38124109043E+002, 5.30700013298E+002, 5.21154747340E+002,
            5.09488311170E+002, 4.95700704787E+002, 4.79791928191E+002,
            4.61761981383E+002, 4.41610864362E+002, 4.20399162234E+002,
            3.99187460106E+002, 3.77975757979E+002, 3.56764055851E+002,
            3.35552353723E+002, 3.14340651596E+002, 2.93128949468E+002,
            2.71917247340E+002, 2.50705545213E+002, 2.29493843085E+002,
            2.08282140957E+002, 1.87070438830E+002, 1.65858736702E+002,
            1.44647034574E+002, 1.23435332447E+002, 1.02223630319E+002,
            8.10119281915E+001, 6.33355097518E+001, 5.27296586879E+001,
            4.91943750000E+001, 4.97137623933E+001, 5.02063762048E+001,
            5.06454851923E+001, 5.10218564529E+001, 5.13374097598E+001,
            5.16004693977E+001, 5.18223244382E+001, 5.20148449242E+001,
            5.21889350372E+001, 5.23536351113E+001, 5.25157124459E+001,
            5.26796063730E+001, 5.28476160610E+001, 5.30202402028E+001,
            5.31965961563E+001, 5.33748623839E+001, 5.35527022996E+001,
            5.37276399831E+001, 5.38973687732E+001, 5.40599826225E+001,
            5.42141273988E+001, 5.43590751578E+001, 5.44947289126E+001,
            5.46215686913E+001, 5.47405518236E+001, 5.48529815402E+001,
            5.49603582190E+001, 5.50642270863E+001, 5.51660349836E+001,
            5.52670070646E+001, 5.53680520985E+001, 5.54697025392E+001,
            5.55720927915E+001, 5.56749762728E+001, 5.57777790517E+001,
            5.58796851466E+001, 5.59797461155E+001, 5.60770054561E+001,
            5.61706266985E+001, 5.62600130036E+001, 5.63449057053E+001,
            5.64254496625E+001, 5.65022146282E+001, 5.65761642150E+001,
            5.66485675508E+001, 5.67208534842E+001, 5.67944133373E+001,
            5.68703658198E+001, 5.69493069272E+001, 5.70310785669E+001,
            5.71146023893E+001, 5.71978399741E+001, 5.72779572372E+001,
            5.73517897984E+001, 5.74167271960E+001, 5.74721573687E+001,
            5.75216388520E+001, 5.75759967785E+001, 5.76575701358E+001,
            5.78058719368E+001, 5.80849611077E+001, 5.85928651155E+001,
            5.94734357453E+001, 6.09310671165E+001, 6.32487551103E+001,
            6.68100309742E+001
        ])
        volumes = volumes / volumes[0]
        dVdt = simulation.first_derivative(times, volumes)
        velocities = np.zeros(times.size)
        for i, time in enumerate(times):
            velocities[i] = sim.reac.walls[0].vdot(time)
        assert np.allclose(dVdt, velocities)
        assert sim.n_vars == gas.n_species + 3
Пример #9
0
def evaluate_model(
    model_name,
    spec_keys_file,
    dataset_file,
    data_path='data',
    model_path='models',
    results_path='results',
    model_variant_file=None,
    num_threads=None,
    print_results=False,
    restart=False,
    skip_validation=False,
):
    """Evaluates the ignition delay error of a model for a given dataset.

    Parameters
    ----------
    model_name : str
        Chemical kinetic model filename
    spec_keys_file : str
        Name of YAML file identifying important species
    dataset_file : str
        Name of file with list of data files
    data_path : str
        Local path for data files. Optional; default = 'data'
    model_path : str
        Local path for model file. Optional; default = 'models'
    results_path : str
        Local path for creating results files. Optional; default = 'results'
    model_variant_file : str
        Name of YAML file identifying ranges of conditions for variants of the
        kinetic model. Optional; default = ``None``
    num_threads : int
        Number of CPU threads to use for performing simulations in parallel.
        Optional; default = ``None``, in which case the available number of
        cores minus one is used.
    print_results : bool
        If ``True``, print results of the model evaluation to screen.
    restart : bool
        If ``True``, process saved results. Mainly intended for testing/development.
    skip_validation : bool
        If ``True``, skips validation of ChemKED files.

    Returns
    -------
    output : dict
        Dictionary with all information about model evaluation results.

    """
    # Create results_path if it doesn't exist
    if not os.path.exists(results_path):
        os.makedirs(results_path)

    # Dict to translate species names into those used by models
    with open(spec_keys_file, 'r') as f:
        model_spec_key = yaml.safe_load(f)

    # Keys for models with variants depending on pressure or bath gas
    model_variant = None
    if model_variant_file:
        with open(model_variant_file, 'r') as f:
            model_variant = yaml.safe_load(f)

    # Read dataset list
    with open(dataset_file, 'r') as f:
        dataset_list = f.read().splitlines()

    error_func_sets = numpy.zeros(len(dataset_list))
    dev_func_sets = numpy.zeros(len(dataset_list))

    # Dictionary with all output data
    output = {'model': model_name, 'datasets': []}

    # If number of threads not specified, use either max number of available
    # cores minus 1, or use 1 if multiple cores not available.
    if not num_threads:
        num_threads = multiprocessing.cpu_count() - 1 or 1

    # Loop through all datasets
    for idx_set, dataset in enumerate(dataset_list):

        dataset_meta = {'dataset': dataset, 'dataset_id': idx_set}

        # Create individual simulation cases for each datapoint in this set
        properties = ChemKED(os.path.join(data_path, dataset),
                             skip_validation=skip_validation)
        simulations = create_simulations(dataset, properties)

        ignition_delays_exp = numpy.zeros(len(simulations))
        ignition_delays_sim = numpy.zeros(len(simulations))

        #############################################
        # Determine standard deviation of the dataset
        #############################################
        ign_delay = [
            case.ignition_delay.to('second').magnitude
            for case in properties.datapoints
        ]