Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

# Copyright (C) 2011, 2014 Ben Elliston 

# 

# This file is free software; you can redistribute it and/or modify it 

# under the terms of the GNU General Public License as published by 

# the Free Software Foundation; either version 3 of the License, or 

# (at your option) any later version. 

 

# pylint: disable=too-many-public-methods 

 

"""A testsuite for NEMO.""" 

 

import math 

import nem 

import regions 

import generators 

import unittest 

 

 

class SuperGenerator(generators.Generator): 

 

    """A synthetic generator that can always meet demand.""" 

 

    def __init__(self, capacity): 

        """Create a super generator.""" 

        generators.Generator.__init__(self, regions.nsw, capacity, 'super') 

        self.energy = 0 

        self.runhours = 0 

 

    def reset(self): 

        """Reset context between tests.""" 

        self.energy = 0 

        self.runhours = 0 

 

    # pylint: disable=unused-argument 

    def step(self, hr, demand): 

        """Step the super generator.""" 

        self.runhours += 1 

        self.energy += demand 

        if self.capacity is None: 

            # meet demand exactly 

            return demand, 0 

        else: 

            # meet demand, spill surplus capacity 

            surplus = max(0, self.capacity - demand) 

            return demand, surplus 

 

 

class TestSequenceFunctions(unittest.TestCase): 

 

    """Basic tests for now.""" 

 

    def setUp(self): 

        """Test harness setup.""" 

        self.context = nem.Context() 

        self.minload = math.floor(self.context.demand.sum(axis=0).min()) 

 

    def test_001(self): 

        """Test that all regions are present.""" 

        self.assertEqual(self.context.regions, regions.All) 

 

    def test_002(self): 

        """Demand equals approx. 204 TWh.""" 

        self.context.generators = [] 

        nem.run(self.context) 

        self.assertEqual(math.trunc(self.context.demand.sum() / pow(10, 6)), 204) 

 

    def test_003(self): 

        """Power system with no generators meets none of the demand.""" 

        self.context.generators = [] 

        nem.run(self.context) 

        self.assertEqual(math.trunc(self.context.unserved_energy), math.trunc(self.context.demand.sum())) 

 

    def test_004(self): 

        """100 MW fossil plant generates exactly 876,000 MWh.""" 

        ccgt = generators.CCGT(regions.nsw, 100) 

        self.context.generators = [ccgt] 

        nem.run(self.context) 

        self.assertEqual(sum(ccgt.hourly_power.values()), self.context.timesteps * 100) 

 

    # Create a super generator that always meets demand. 

    # Check unserved_energy = 0 

 

    def test_005(self): 

        """Super generator runs every hour.""" 

        gen = SuperGenerator(None) 

        self.context.generators = [gen] 

        nem.run(self.context) 

        self.assertEqual(gen.runhours, self.context.timesteps) 

 

    def test_006(self): 

        """Generation to meet minimum load leads to no spills.""" 

        self.context.generators = [SuperGenerator(self.minload)] 

        nem.run(self.context) 

        self.assertEqual(self.context.spill.sum(), 0) 

 

    def test_007(self): 

        """Generation to meet minimum load + 1GW produces some spills.""" 

        self.context.generators = [SuperGenerator(self.minload + 1000)] 

        nem.run(self.context) 

        self.assertTrue(self.context.spill.sum() > 0) 

 

    def test_008(self): 

        """A NSW generator runs in NSW only.""" 

        for rgn in regions.All: 

            self.context.regions = [rgn] 

            gen = SuperGenerator(None) 

            self.context.generators = [gen] 

            nem.run(self.context) 

            if rgn == regions.nsw: 

                self.assertEqual(gen.runhours, self.context.timesteps) 

            else: 

                self.assertEqual(gen.runhours, 0) 

 

    def test_009(self): 

        """A NSW generators runs in any set of regions that includes NSW.""" 

        rgnset = [] 

        for rgn in regions.All: 

            rgnset.append(rgn) 

            self.context.regions = rgnset 

            gen = SuperGenerator(None) 

            self.context.generators = [gen] 

            nem.run(self.context) 

            self.assertEqual(gen.runhours, self.context.timesteps) 

 

    def test_010(self): 

        """Running in one region only produces no interstate exchanges.""" 

        for rgn in regions.All: 

            if rgn is regions.snowy: 

                continue 

            self.context = nem.Context() 

            self.context.track_exchanges = True 

            self.context.regions = [rgn] 

            self.context.generators = [generators.OCGT(regions.nsw, 100), 

                                       generators.OCGT(regions.qld, 100), 

                                       generators.OCGT(regions.sa, 100), 

                                       generators.OCGT(regions.tas, 100), 

                                       generators.OCGT(regions.vic, 100)] 

            nem.run(self.context, endhour=100) 

            self.assertEqual((self.context.exchanges[0] > 0).sum(), 1, 'Only one exchange > 0') 

            self.assertTrue(self.context.exchanges[0, rgn, rgn] > 0, 'Only rgn->rgn is > 0') 

 

    def test_011(self): 

        """Running in two regions only produces limited interstate exchanges.""" 

        for rgn1 in regions.All: 

            for rgn2 in regions.All: 

                if rgn1 is rgn2: 

                    continue 

                self.context.regions = [rgn1, rgn2] 

                nem.run(self.context, endhour=1) 

                self.assertTrue(self.context.exchanges[0, rgn1, rgn1] >= 0) 

                self.assertTrue(self.context.exchanges[0, rgn2, rgn2] >= 0) 

                for i in regions.All: 

                    for j in regions.All: 

                        # Check that various elements of the exchanges matrix are 0. 

                        # Ignore: diagonals, [RGN1,RGN2] and [RGN2,RGN1]. 

                        if i != j and (i, j) != (rgn1, rgn2) and (i, j) != (rgn2, rgn1): 

                            self.assertEqual(self.context.exchanges[0, i, j], 0) 

 

    def test_012(self): 

        """A NSW generator does not run in other regions.""" 

        rgnset = [] 

        # Skip NSW (first in the list). 

        for rgn in regions.All[1:]: 

            rgnset.append(rgn) 

            self.context.regions = rgnset 

            gen = SuperGenerator(None) 

            self.context.generators = [gen] 

            nem.run(self.context) 

            self.assertEqual(gen.runhours, 0) 

 

    def test_013(self): 

        """Fossil plant records power generation history.""" 

        ccgt = generators.CCGT(regions.nsw, 100) 

        self.context.generators = [ccgt] 

        nem.run(self.context) 

        self.assertTrue(len(self.context.generators[0].hourly_power) > 0)