def test_no_name(self): ptree = PropertyTree() ptree.put_double('initial_voltage', 0) ptree.put_double('final_voltage', 0) ptree.put_double('scan_limit_1', 1) ptree.put_double('scan_limit_2', 0) ptree.put_double('step_size', 0.1) ptree.put_double('scan_rate', 1) ptree.put_int('cycles', 1) cv = CyclicVoltammetry(ptree) try: cv.run(device) except: self.fail('calling run without data should not raise') data = initialize_data() cv.run(device, data) voltage = array([0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1., 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.], dtype=float) time = linspace(0, 2, 21) try: testing.assert_array_almost_equal(data['voltage'], voltage) testing.assert_array_almost_equal(data['time'], time) except AssertionError as e: print(e) self.fail()
def test_charge_constant_current(self): ptree = PropertyTree() ptree.put_string('charge_mode', 'constant_current') ptree.put_double('charge_current', 10e-3) ptree.put_string('charge_stop_at_1', 'voltage_greater_than') ptree.put_double('charge_voltage_limit', 1.4) ptree.put_double('time_step', 0.2) charge = Charge(ptree) data = initialize_data() charge.run(device, data) self.assertAlmostEqual(data['current'][0], 10e-3) self.assertAlmostEqual(data['current'][-1], 10e-3) self.assertGreaterEqual(data['voltage'][-1], 1.4) self.assertAlmostEqual(data['time'][1] - data['time'][0], 0.2)
def test_force_discharge(self): ptree = PropertyTree() ptree.put_string('mode', 'constant_voltage') ptree.put_double('voltage', 0.0) ptree.put_string('end_criterion', 'current_less_than') ptree.put_double('current_limit', 1e-5) ptree.put_double('time_step', 1.0) stage = Stage(ptree) data = initialize_data() steps = stage.run(device, data) self.assertGreaterEqual(steps, 1) self.assertEqual(steps, len(data['time'])) self.assertAlmostEqual(data['voltage'][-1], 0.0) self.assertLessEqual(data['current'][-1], 1e-5)
def test_constant_current_charge_for_given_time(self): ptree = PropertyTree() ptree.put_string('mode', 'constant_current') ptree.put_double('current', 5e-3) ptree.put_string('end_criterion', 'time') ptree.put_double('duration', 15.0) ptree.put_double('time_step', 0.1) stage = Stage(ptree) data = initialize_data() steps = stage.run(device, data) self.assertEqual(steps, 150) self.assertEqual(steps, len(data['time'])) self.assertAlmostEqual(data['time'][-1], 15.0) self.assertAlmostEqual(data['current'][-1], 5e-3)
def test_charge_constant_voltage(self): ptree = PropertyTree() ptree.put_string('charge_mode', 'constant_voltage') ptree.put_double('charge_voltage', 1.4) ptree.put_string('charge_stop_at_1', 'current_less_than') ptree.put_double('charge_current_limit', 1e-6) ptree.put_string('charge_stop_at_2', 'time') ptree.put_double('charge_max_duration', 60) ptree.put_double('time_step', 0.2) charge = Charge(ptree) data = initialize_data() charge.run(device, data) self.assertTrue(data['time'][-1] >= 60 or abs(data['current'][-1]) <= 1e-6) self.assertAlmostEqual(data['voltage'][-1], 1.4)
def run_discharge(device, ptree): data = initialize_data() # (re)charge the device initial_voltage = ptree.get_double('initial_voltage') charge_database = PropertyTree() charge_database.put_string('charge_mode', 'constant_current') charge_database.put_double('charge_current', 10.0) charge_database.put_string('charge_stop_at_1', 'voltage_greater_than') charge_database.put_double('charge_voltage_limit', initial_voltage) charge_database.put_bool('charge_voltage_finish', True) charge_database.put_double('charge_voltage_finish_current_limit', 1e-2) charge_database.put_double('charge_voltage_finish_max_time', 600) charge_database.put_double('charge_rest_time', 0) charge_database.put_double('time_step', 10.0) charge = Charge(charge_database) start = time() charge.run(device, data) end = time() # used for tracking time of this substep print('Charge: %s min' % ((end-start) / 60)) data['time'] -= data['time'][-1] # discharge at constant power discharge_power = ptree.get_double('discharge_power') final_voltage = ptree.get_double('final_voltage') time_step = ptree.get_double('time_step') discharge_database = PropertyTree() discharge_database.put_string('discharge_mode', 'constant_power') discharge_database.put_double('discharge_power', discharge_power) discharge_database.put_string('discharge_stop_at_1', 'voltage_less_than') discharge_database.put_double('discharge_voltage_limit', final_voltage) discharge_database.put_double('discharge_rest_time', 10 * time_step) discharge_database.put_double('time_step', time_step) discharge = Discharge(discharge_database) start = time() discharge.run(device, data) end = time() # used for tracking time of this substep print('Discharge: %s min' % ((end-start) / 60)) return data
def run_discharge(device, ptree): data = initialize_data() # (re)charge the device initial_voltage = ptree.get_double('initial_voltage') charge_database = PropertyTree() charge_database.put_string('charge_mode', 'constant_current') charge_database.put_double('charge_current', 10.0) charge_database.put_string('charge_stop_at_1', 'voltage_greater_than') charge_database.put_double('charge_voltage_limit', initial_voltage) charge_database.put_bool('charge_voltage_finish', True) charge_database.put_double('charge_voltage_finish_current_limit', 1e-2) charge_database.put_double('charge_voltage_finish_max_time', 600) charge_database.put_double('charge_rest_time', 0) charge_database.put_double('time_step', 10.0) charge = Charge(charge_database) start = time() charge.run(device, data) end = time() # used for tracking time of this substep print('Charge: %s min' % ((end - start) / 60)) data['time'] -= data['time'][-1] # discharge at constant power discharge_power = ptree.get_double('discharge_power') final_voltage = ptree.get_double('final_voltage') time_step = ptree.get_double('time_step') discharge_database = PropertyTree() discharge_database.put_string('discharge_mode', 'constant_power') discharge_database.put_double('discharge_power', discharge_power) discharge_database.put_string('discharge_stop_at_1', 'voltage_less_than') discharge_database.put_double('discharge_voltage_limit', final_voltage) discharge_database.put_double('discharge_rest_time', 10 * time_step) discharge_database.put_double('time_step', time_step) discharge = Discharge(discharge_database) start = time() discharge.run(device, data) end = time() # used for tracking time of this substep print('Discharge: %s min' % ((end - start) / 60)) return data
def test_time_steps(self): ptree = PropertyTree() ptree.put_int('stages', 2) ptree.put_int('cycles', 1) ptree.put_double('time_step', 1.0) ptree.put_string('stage_0.mode', 'hold') ptree.put_string('stage_0.end_criterion', 'time') ptree.put_double('stage_0.duration', 2.0) ptree.put_string('stage_1.mode', 'rest') ptree.put_string('stage_1.end_criterion', 'time') ptree.put_double('stage_1.duration', 1.0) ptree.put_double('stage_1.time_step', 0.1) multi = MultiStage(ptree) data = initialize_data() steps = multi.run(device, data) self.assertEqual(steps, 12) self.assertEqual(steps, len(data['time'])) self.assertAlmostEqual(data['time'][5], 2.4) self.assertAlmostEqual(data['voltage'][0], data['voltage'][1]) self.assertAlmostEqual(data['current'][3], 0.0)
def testFourierAnalysis(self): ptree = PropertyTree() ptree.put_int('steps_per_cycle', 3) ptree.put_int('cycles', 1) ptree.put_int('ignore_cycles', 0) ptree.put_string('harmonics', '1') # uninitialized data data = {} self.assertRaises(KeyError, fourier_analysis, data, ptree) # empty data data = initialize_data() self.assertRaises(IndexError, fourier_analysis, data, ptree) # bad data data['time'] = array([1, 2, 3], dtype=float) data['current'] = array([4, 5, 6], dtype=float) data['voltage'] = array([7, 8], dtype=float) self.assertRaises(AssertionError, fourier_analysis, data, ptree) # poor data (size not a power of 2) data['voltage'] = array([7, 8, 9], dtype=float) with catch_warnings(): simplefilter("error") self.assertRaises(RuntimeWarning, fourier_analysis, data, ptree) # data unchanged after analyze dummy = array([1, 2, 3, 4, 5, 6, 7, 8], dtype=float) data['time'] = dummy data['current'] = dummy data['voltage'] = dummy # ptree needs to be updated self.assertRaises(AssertionError, fourier_analysis, data, ptree) ptree.put_int('steps_per_cycle', 4) ptree.put_int('cycles', 2) ptree.put_int('ignore_cycles', 0) fourier_analysis(data, ptree) try: testing.assert_array_equal(data['time'], dummy) testing.assert_array_equal(data['current'], dummy) testing.assert_array_equal(data['voltage'], dummy) except AssertionError: self.fail('data should not be changed by the fourier analyzis')
def test_fourier_analysis(self): ptree = PropertyTree() ptree.put_int('steps_per_cycle', 3) ptree.put_int('cycles', 1) ptree.put_int('ignore_cycles', 0) ptree.put_string('harmonics', '1') # uninitialized data data = {} self.assertRaises(KeyError, fourier_analysis, data, ptree) # empty data data = initialize_data() self.assertRaises(IndexError, fourier_analysis, data, ptree) # bad data data['time'] = array([1, 2, 3], dtype=float) data['current'] = array([4, 5, 6], dtype=float) data['voltage'] = array([7, 8], dtype=float) self.assertRaises(AssertionError, fourier_analysis, data, ptree) # poor data (size not a power of 2) data['voltage'] = array([7, 8, 9], dtype=float) with catch_warnings(): simplefilter("error") self.assertRaises(RuntimeWarning, fourier_analysis, data, ptree) # data unchanged after analyze dummy = array([1, 2, 3, 4, 5, 6, 7, 8], dtype=float) data['time'] = dummy data['current'] = dummy data['voltage'] = dummy # ptree needs to be updated self.assertRaises(AssertionError, fourier_analysis, data, ptree) ptree.put_int('steps_per_cycle', 4) ptree.put_int('cycles', 2) ptree.put_int('ignore_cycles', 0) fourier_analysis(data, ptree) self.assertTrue(all(equal(data['time'], dummy))) self.assertTrue(all(equal(data['current'], dummy))) self.assertTrue(all(equal(data['voltage'], dummy)))