Меню
Главная
Авторизация/Регистрация
 
Главная arrow Информатика arrow Подсистема прогноза снабжения энергетическими ресурсами теплогенераторных станций

Тестирование и анализ результатов

Для тестирования работы подсистемы прогнозирования изменения температуры воздуха окружающей среды подготовим 4 тестовых набора:

  • 1) статистические данные изменения температуры в городе Вологде в период с 1 недели 2016 года по 52 неделю 2016 года. Количество наблюдений равно 52, следовательно, применим метод простого экспоненциального сглаживания;
  • 2) статистические данные изменения температуры в городе Вологде в период с 1 недели 2012 года по 17 неделю 2017 года. Количество наблюдений равно 277, следовательно, применим метод экспоненциального сглаживания по модели Хольта-Уинтерса;
  • 3) статистические данные изменения температуры в городе Ростове-на-Дону в период с 1 недели 2016 года по 17 неделю 2017 года. Количество наблюдений равно 69, следовательно, применим метод простого экспоненциального сглаживания;
  • 4) статистические данные изменения температуры в городе Ростове-на-Дону в период с 1 недели 2013 года по 13 неделю 2015 года. Количество наблюдений равно 117, следовательно, применим метод экспоненциального сглаживания по модели Хольта-Уинтерса.

Произведём контрольный расчёт по тестовым наборам в программе Excel пакета Microsoft Office. Результаты контрольного и произведённого в разрабатываемой программе расчётов представлены в таблице 3.4.

Таблица 3.4 - Сравнение результатов тестирования подсистемы прогнозирования

Температура воздуха окружающей среды, °C

Тестовый набор №1

Тестовый набор №2

Тестовый набор №3

Тестовый набор №4

Контроль-ный расчёт

Результаты программы

Контроль-ный расчёт

Результаты программы

Контроль-ный расчёт

Результаты программы

Контроль-ный расчёт

Результаты программы

-19,84

-19,84

11,61

11,66

14,33

14,33

11,43

11,42

-14,27

-14,27

12,00

12,05

16,40

16,40

7,24

7,24

-12,73

-12,73

14,56

14,60

16,44

16,44

10,02

10,02

-4,85

-4,85

16,53

16,55

18,20

18,20

11,63

11,64

-1,51

-1,51

14,87

14,89

18,10

18,10

19,52

19,53

-0,42

-0,42

13,23

13,24

17,04

17,04

18,27

18,29

-3,62

-3,62

17,33

17,33

23,67

23,67

19,54

19,57

-1,31

-1,31

17,76

17,74

27,67

27,67

21,04

21,08

-1,51

-1,51

16,54

16,51

25,87

25,87

21,23

21,27

1,42

1,42

16,85

16,82

23,65

23,65

19,33

19,38

-3,71

-3,71

18,04

17,99

27,37

27,37

24,49

24,54

-6,26

-6,26

19,31

19,25

23,27

23,27

20,86

20,92

2,44

2,44

20,05

19,98

24,39

24,39

25,25

25,31

3,47

3,47

17,79

17,72

27,31

27,31

24,09

24,19

5,70

5,70

18,43

18,35

26,70

26,70

25,43

25,51

5,16

5,16

17,71

17,61

24,82

24,82

23,64

23,73

10,70

10,70

16,38

16,27

25,50

25,50

20,68

20,78

13,30

13,30

12,70

12,59

21,67

21,67

20,71

20,82

12,72

12,72

11,53

11,40

20,72

20,72

22,73

22,84

14,01

14,01

10,83

10,69

17,43

17,43

25,54

25,65

17,00

17,00

10,66

10,51

12,57

12,57

23,51

23,63

12,30

12,30

8,88

8,71

11,70

11,70

21,24

21,37

10,64

10,64

6,70

6,52

15,61

15,61

14,91

15,04

18,25

18,25

3,79

3,60

7,01

7,01

15,25

15,39

19,83

19,83

2,66

2,46

4,25

4,25

14,94

15,09

15,88

15,88

-0,33

-0,53

2,27

2,27

9,52

9,67

16,64

16,64

-0,90

-1,11

3,54

3,54

4,72

4,88

19,26

19,26

-1,74

-1,96

10,28

10,28

8,52

8,69

21,57

21,57

-2,21

-2,46

0,29

0,29

10,47

10,65

22,42

22,42

-2,27

-2,53

-1,87

-1,87

6,19

6,37

17,45

17,45

-6,64

-6,91

-0,10

-0,10

8,20

8,39

18,10

18,10

-5,14

-5,42

-1,78

-1,78

8,62

8,81

18,16

18,16

-6,47

-6,76

-7,53

-7,53

5,00

5,19

17,49

17,49

-2,94

-3,25

-5,39

-5,39

3,04

3,24

11,42

11,42

-1,15

-1,46

-2,47

-2,47

1,40

1,61

11,76

11,76

-18,42

-18,73

1,13

1,13

-0,49

-0,27

9,65

9,65

-9,05

-9,38

-0,52

-0,52

-7,04

-6,81

8,82

8,82

-7,31

-7,66

-2,27

-2,27

-2,90

-2,66

6,67

6,67

-8,17

-8,53

-5,86

-5,86

0,44

0,67

6,39

6,39

-7,01

-7,37

-5,74

-5,74

-0,71

-0,47

3,33

3,33

-6,80

-7,18

-8,64

-8,64

-3,68

-3,43

1,65

1,65

-3,69

-4,07

-3,60

-3,60

-2,65

-2,39

-0,19

-0,19

-3,60

-4,00

3,23

3,23

-0,02

0,24

-3,45

-3,45

-1,69

-2,10

5,19

5,19

-2,01

-1,75

-6,20

-6,20

-0,39

-0,80

6,03

6,03

0,69

0,97

-2,68

-2,68

-0,13

-0,56

5,03

5,03

0,31

0,59

-3,36

-3,36

-1,07

-1,51

6,55

6,55

-2,20

-1,91

-9,62

-9,62

-0,55

-0,99

5,86

5,86

0,08

0,38

-7,84

-7,84

2,73

2,27

9,52

9,52

0,79

1,09

-10,97

-10,97

3,69

3,23

11,09

11,09

5,48

5,78

-1,72

-1,72

2,81

2,35

8,54

8,54

2,92

3,24

-0,77

-0,77

7,62

7,13

11,51

11,51

-1,81

-1,49

Из таблицы 3.4 видно, что для тестовых наборов 1 и 3 погрешность в расчётах отсутствует, а для тестовых наборов 2 и 4 максимальная погрешность составляет 0,49 °C, что обусловлено большей точностью производимых расчётов в программе Excel. Таким образом, все тестовые наборы показывают положительные результаты, что свидетельствует о корректной работе программы.

Убедимся в работоспособности пользовательского интерфейса программы. Изменение статистических данных, параметров системы, теплоносителя и топливных ресурсов приводят к пересчёту прогноза изменения температуры воздуха окружающей среды и прогноза затрат энергетических ресурсов. Все пункты меню и кнопки выполняют назначенные им действия.

Сохранение результатов программы в файлы формата *.fpf и *.tsf и последующее их открытие в программе производится успешно, искажений введённых и сохраняемых данных не происходит.

Попытка открытия файла, содержимое которого не соответствует необходимой структуре, происходит вывод уведомления об ошибке, представленного на рисунке 3.4, открытие файла прекращается, программа продолжает работу.

Рисунок 3.4 - Уведомление об ошибке при открытии файла

Таким образом, все тесты прошли успешно, программа работает корректно и без сбоев.

ЗАКЛЮЧЕНИЕ

В ходе дипломного проектирования были пройдены следующие этапы разработки:

  • 1. Проведён аналитический обзор проблемы управления энергетическими ресурсами при производстве тепловой энергии на теплогенераторных станциях, показавший, что задача управления энергетическими ресурсами в соответствии со схемой изменения температуры воздуха окружающей среды является актуальной.
  • 2. Проведён анализ существующих методов прогнозирования.
  • 3. На основе информации, полученной при выполнении предыдущих этапов разработки, была окончательно поставлена и выполнена задача проектирования.
  • 4. Разработаны алгоритмы функционирования подсистемы и пользовательский интерфейс программы.
  • 5. Рассмотрены наиболее популярные языки и среды программирования, недостатки и преимущества каждого из них. Выбран язык и среда программирования, наиболее удовлетворяющие требованиям разработки.
  • 6. Произведён синтез подсистемы - реализованы алгоритмы функционирования на языке программирования с использованием среды программирования, выбранными при выполнении предыдущего этапа разработки.
  • 7. Разработано руководство пользователя системы.
  • 8. Проведено тестирование и отладка программного продукта на реальных данных (использованы данные об изменении температуры воздуха окружающей среды в городах: Вологде, Ростове-на-Дону), в ходе которого были выявлены и устранены некоторые ошибки.

В качестве замечаний к готовому программному продукту можно выделить следующее:

  • 1) требуется доработка формирования программой отчёта о произведённых расчётах (поправка оформления, увеличение объёма полезной информации, содержащейся в отчёте);
  • 2) возможно небольшая доработка пользовательского интерфейса с целью увеличения удобства работы пользователя;
  • 3) возможно увеличение объёма информации руководства пользователя (более подробное описание элементов системы и работы с ними).

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

  • 1. Об энергосбережении и о повышении энергетической эффективности и о внесении изменений в отдельные законодательные акты Российской Федерации» [Электронный ресурс]: федер. закон от 23.11.2009 № 261-ФЗ // КонсультантПлюс: справ.-правовая система / Компания «КонсультантПлюс».
  • 2. Константиновская, Л. В. Методы и приемы прогнозирования [Электронный ресурс] / Л. В. Константиновская // Прогнозирование: электронная книга. - Режим доступа: http://www.astronom2000.info/прогнозирование/mipp.
  • 3. Анкуда, С.Н. Построение детерминированных и стохастических моделей технологических процессов / С.Н. Анкуда, И.М. Хейфец // Прогресивні технології і системи машинобудування. - 2014. - № 3 (49). - С. 3-9.
  • 4. Анализ временных рядов [Электронный ресурс] // StatSoft: электронный учебник. - Москва: StatSoft, 2012. - Режим доступа: http://statsoft.ru/home/textbook/default.htm.
  • 5. Holt-Winters seasonal method [Электронный ресурс] // OTexts: сайт. - Режим доступа: https://www.otexts.org/fpp/7/5.
  • 6. Турунцева, М. Ю. Оценка качества прогнозов: простейшие методы // Российское предпринимательство. - 2011. - № 8-1 (189). - С. 50-56.
  • 7. TIOBE Programming Community Index Definition [Электронный ресурс] // TIOBE: офиц. сайт. - Режим доступа: https://www.tiobe.com/tiobe-index//programming-languages-definition/.
  • 8. Nocedal, Jeorge; Wright, Stephen J. Numerical Optimization / J. Nocedal, S. J. Wright. - USA: Springer, 2006. - 651 p.
  • 9. РД 50-34.698-90. Автоматизированные системы. Требования к содержанию документов. - Введ. 01.01.1992. - Москва: ИПК Издательство стандартов, 2002. - 27 с.
  • 10.

ПРИЛОЖЕНИЕ 1

Исходный текст класса Forecast

Содержимое заголовочного файла forecast.h:

#ifndef FORECAST_H

#define FORECAST_H

#include <QVector>

#include <QMap>

#include <cppoptlib/boundedproblem.h>

static const int WEEKS_PER_YEAR = 52;

class Forecast {

public:

Forecast(const QMap<int, QMap<int, double> > &statsMap, bool isExpSmooth = false);

QMap<int, double> getValues() const { return mForecastMap; }

double getAlpha() const { return mAlpha; }

double getBeta() const { return mBeta; }

double getGamma() const { return mGamma; }

double getRMSE() const { return mRMSE; }

int getFirstWeek() const { return mFirstWeek; }

int getYear() const { return mYear; }

private:

QMap<int, double> mForecastMap;

double mAlpha;

double mBeta;

double mGamma;

double mRMSE;

int mFirstWeek;

int mYear;

};

class ForecastProblem : public cppoptlib::BoundedProblem<double> {

public:

using Superclass = cppoptlib::BoundedProblem<double>;

using typename Superclass::TVector;

ForecastProblem(const QMap<int, QMap<int, double> > &statsMap);

double value(const TVector &x);

QMap<int, double> forecast(const TVector &x);

private:

QVector<double> statsMapToVector(const QMap<int, QMap<int, double> > &statsMap);

void initVectors();

void calculateVectors(const TVector &x, QVector<double> &smooth, QVector<double> &trends, QVector<double> &season, QVector<double> &forecastStats);

private:

QVector<double> mStatsData;

QVector<double> mSmoothInit;

QVector<double> mTrendsInit;

QVector<double> mSeasonInit;

};

#endif // FORECAST_H

Содержимое файла с исходным кодом forecast.cpp:

#include "forecast.h"

#include <cppoptlib/solver/lbfgsbsolver.h>

Forecast::Forecast(const QMap<int, QMap<int, double> > &statsMap, bool isExpSmooth) {

if (isExpSmooth) {

QVector<double> data;

for (QMap<int, double> yearMap : statsMap.values()) {

for (double value : yearMap.values()) {

data.push_back(value);

}

}

QVector<double> y = data;

mRMSE = std::numeric_limits<double>::max();

for (double alpha = 0.99; alpha >= 0.01; alpha -= 0.01) {

QVector<double> yTemp = data;

for (int i = 1; i < data.size(); ++i) {

yTemp[i] = alpha * data.at(i) + (1 - alpha) * yTemp.at(i - 1);

}

double sum = 0;

for (int i = 0; i < yTemp.size(); ++i) {

sum += pow(data.at(i) - yTemp.at(i), 2);

}

const double rmse = sqrt(sum / yTemp.size());

if (rmse < mRMSE) {

mRMSE = rmse;

y = yTemp;

mAlpha = alpha;

}

}

while (y.size() > 52) {

y.removeFirst();

}

for (int i = 0; i < y.size(); ++i) {

mForecastMap.insert(i + 1, y.at(i));

}

mFirstWeek = statsMap.last().lastKey() + 1;

mYear = statsMap.lastKey();

if (mFirstWeek > 52) {

mFirstWeek = 1;

++mYear;

}

} else {

ForecastProblem problem(statsMap);

ForecastProblem::TVector x = ForecastProblem::TVector::Zero(3);

cppoptlib::LbfgsbSolver<ForecastProblem> solver;

solver.minimize(problem, x);

mAlpha = x[0];

mBeta = x[1];

mGamma = x[2];

mRMSE = problem(x);

mForecastMap = problem.forecast(x);

mFirstWeek = statsMap.last().lastKey() + 1;

mYear = statsMap.lastKey();

if (mFirstWeek > 52) {

mFirstWeek = 1;

++mYear;

}

}

}

ForecastProblem::ForecastProblem(const QMap<int, QMap<int, double> > &statsMap)

: Superclass(TVector::Zero(3), TVector::Ones(3))

{

mStatsData = statsMapToVector(statsMap);

initVectors();

}

double ForecastProblem::value(const TVector &x) {

QVector<double> smooth; // сглаженный ряд

QVector<double> trends; // значения тренда

QVector<double> season; // коэффициенты сезонности

QVector<double> forecastStats; // модель прогноза

calculateVectors(x, smooth, trends, season, forecastStats);

double sumPowError = 0; // сумма квадратов отклонений модели прогноза от реальных данных

for (int i = 0; i < mStatsData.size(); ++i) {

sumPowError += pow(mStatsData.at(i) - forecastStats.at(i), 2);

}

return sqrt(sumPowError / mStatsData.size());

}

QMap<int, double> ForecastProblem::forecast(const TVector &x) {

QVector<double> smooth; // сглаженный ряд

QVector<double> trends; // значения тренда

QVector<double> season; // коэффициенты сезонности

QVector<double> forecastStats; // модель прогноза

calculateVectors(x, smooth, trends, season, forecastStats);

const double smoothLast = smooth.last();

const double trendsLast = trends.last();

QMap<int, double> forecastMap;

for (int period = 1; period <= WEEKS_PER_YEAR; ++period) {

forecastMap.insert(period, smoothLast + period * trendsLast + season.at(season.size() - WEEKS_PER_YEAR - 1 + period));

}

return forecastMap;

}

QVector<double> ForecastProblem::statsMapToVector(const QMap<int, QMap<int, double> > &statsMap) {

QVector<double> data;

for (auto it = statsMap.constBegin(); it != statsMap.constEnd(); ++it) {

data += it->values().toVector();

}

return data;

}

void ForecastProblem::initVectors() {

double sumYear1 = 0, sumYear2 = 0;

for (int i = 0; i < WEEKS_PER_YEAR; ++i) {

sumYear1 += mStatsData.at(i);

sumYear2 += mStatsData.at(i + WEEKS_PER_YEAR);

}

mSmoothInit.push_back(sumYear1 / WEEKS_PER_YEAR);

mTrendsInit.push_back((sumYear2 - sumYear1) / (WEEKS_PER_YEAR * WEEKS_PER_YEAR));

for (int i = 0; i < WEEKS_PER_YEAR; ++i) {

mSeasonInit.push_back(mStatsData.at(i) - mSmoothInit.at(0));

}

}

void ForecastProblem::calculateVectors(const TVector &x,

QVector<double> &smooth, QVector<double> &trends, QVector<double> &season,

QVector<double> &forecastStats)

{

double alpha = x[0];

double beta = x[1];

double gamma = x[2];

smooth = mSmoothInit;

trends = mTrendsInit;

season = mSeasonInit;

forecastStats.clear();

for (int i = 0, period = 1; i < mStatsData.size(); ++i, ++period) {

forecastStats.push_back(smooth.at(i) + trends.at(i) + season.at(i));

double newSmooth = alpha * (mStatsData.at(i) - season.at(i)) + (1 - alpha) * (smooth.at(i) + trends.at(i));

double newTrends = beta * (newSmooth - smooth.at(i)) + (1 - beta) * trends.at(i);

double newSeason = gamma * (mStatsData.at(i) - smooth.at(i) - trends.at(i)) + (1 - gamma) * season.at(i);

smooth.push_back(newSmooth);

trends.push_back(newTrends);

season.push_back(newSeason);

}

}

ПРИЛОЖЕНИЕ 2

Описание работы алгоритма BFGS

Алгоритм Бройдена - Флетчера - Гольдфарба - Шанно (Broyden - Fletcher - Goldfarb - Shanno algorithm - BFGS) - итерационный метод численной оптимизации, предназначенный для нахождения локального максимума/минимума нелинейного функционала без ограничений.

BFGS - один из наиболее широко применяемых квазиньютоновских методов. Также существуют модификации данного метода с ограниченным использованием памяти (L-BFGS), который предназначен для решения нелинейных задач с большим количеством неизвестных, и с ограниченным использованием памяти в многомерном кубе (L-BFGS-B).

Данный метод находит минимум любой дважды непрерывно дифференцируемой выпуклой функции.

Пусть решается задача оптимизации функционала:

Идея BFGS заключается в разложении в полином второй степени:

в текущей точке , где - симметричная положительно определенная матрица (приближение гессиана - матрицы вторых производных), обновляемая на каждой итерации.

После чего находится минимум данной квадратичной задачи:

И находится следующий шаг:

Где удовлетворяет условиям Вольфе:

Вместо того, чтобы заново считать на каждой итерации, к добавляется матрица изменений на каждом шаге. В отличии от BFGS алгоритм L-BFGS-B менее требовательный к памяти, потому что хранит матрицу неявно.

ПРИЛОЖЕНИЕ 3

Исходный текст класса UtilsCals

Содержимое заголовочного файла utilscalc.h:

#ifndef UTILSCALC_H

#define UTILSCALC_H

#include <QString>

#include <QMap>

#include <QCoreApplication>

#include <QTableWidget>

class UtilsCalc {

Q_DECLARE_TR_FUNCTIONS(CalcUtils)

public:

enum WATER_TYPE {

WATER = 0,

OTHER_WATER

};

enum FUEL_TYPE {

GAS = 0, // газ природный

LIGNITE, // бурый уголь

CHARCOAL, // древесный уголь

ANTHRACITE, // антрацит (каменный уголь)

WOOD_OAK, // древесина дубовая

WOOD_SPRUCE, // древесина еловая

WOOD_PINE, // древесина сосновая

DIESEL, // дизельное топливо

MASUT, // мазут

OTHER_FUEL

};

enum FUEL_UNITS {

M3 = 0,

KG

};

static const QString toString(WATER_TYPE type);

static const QString toString(FUEL_TYPE type);

static const QString toString(FUEL_UNITS units);

static double getWaterHeat(WATER_TYPE type, int temperature);

static double getWaterDensity(WATER_TYPE type, int temperature);

static double getFuelHeat(FUEL_TYPE type);

static double getFuelDensity(FUEL_TYPE type);

static double getFuelCost(FUEL_TYPE type);

static FUEL_UNITS getFuelUnits(FUEL_TYPE type);

static double getSystemHeat(double temperature, double tempOff, const QTableWidget *tableTempHeat);

static double getOutHeat(double waterHeat, double waterDensity, double waterTempOut, double waterTempIn, double systemLosses);

static double getOutWater(double systemHeat, double systemLosses, double waterHeat, double waterDensity, double waterTempOut, double waterTempIn);

static double getOutElectricity(double pumpsPower, bool heatByElectricity, double outWater, double outHeat);

static double getOutElectricityCost(double outElectricity, double electricityPrice);

static double getOutFuel(double outHeat, double outWater, double fuelHeat, FUEL_TYPE fuelType);

static double getOutFuelCost(double outFuel, double fuelPrice);

private:

static QMap<WATER_TYPE, QMap<int, double> > initWaterHeat();

static QMap<WATER_TYPE, QMap<int, double> > initWaterDensity();

private:

UtilsCalc();

UtilsCalc(const UtilsCalc&);

UtilsCalc& operator = (const UtilsCalc&);

};

#endif // UTILSCALC_H

Содержимое файла с исходным кодом utilscalc.cpp:

#include "utilscalc.h"

const QString UtilsCalc::toString(UtilsCalc::WATER_TYPE type) {

switch (type) {

case WATER: return tr("вода");

case OTHER_WATER: return tr("другое");

default: return "[unknown type " + QString::number(type) + "]";

}

}

const QString UtilsCalc::toString(UtilsCalc::FUEL_TYPE type) {

switch (type) {

case GAS: return tr("газ природный");

case LIGNITE: return tr("уголь бурый");

case CHARCOAL: return tr("уголь древесный");

case ANTHRACITE: return tr("антрацит (уголь каменный)");

case WOOD_OAK: return tr("древесина дубовая");

case WOOD_SPRUCE: return tr("древесина еловая");

case WOOD_PINE: return tr("древесина сосновая");

case DIESEL: return tr("дизельное топливо");

case MASUT: return tr("мазут");

case OTHER_FUEL: return tr("другое");

default: return "[unknown type " + QString::number(type) + "]";

}

}

const QString UtilsCalc::toString(UtilsCalc::FUEL_UNITS units) {

switch (units) {

case M3: return tr("мі", "1 кубический метр");

case KG: return tr("кг", "1 килограмм");

default: return "unknown units " + QString::number(units) + "]";

}

}

// возвращает удельную теплоёмкость теплоносителя [Дж/(кг*град)] при заданной температуре

double UtilsCalc::getWaterHeat(UtilsCalc::WATER_TYPE type, int temperature) {

static const QMap<UtilsCalc::WATER_TYPE, QMap<int, double> > HEAT_MAP = initWaterHeat();

if (HEAT_MAP.contains(type) && !HEAT_MAP.value(type).isEmpty()) {

const QMap<int, double> map = HEAT_MAP.value(type);

QMap<int, double>::const_iterator it = map.find(temperature);

if (it == map.end()) {

it = map.lowerBound(temperature);

if (it == map.end()) {

it = map.upperBound(temperature);

}

}

if (it != map.end()) {

return it.value();

}

}

switch (type) {

case WATER: return 4200;

default: return 1;

}

}

// возвращает плотность теплоносителя [кг/м^3] при заданной температуре

double UtilsCalc::getWaterDensity(UtilsCalc::WATER_TYPE type, int temperature) {

static const QMap<WATER_TYPE, QMap<int, double> > DENSITY_MAP = initWaterDensity();

if (DENSITY_MAP.contains(type) && !DENSITY_MAP.value(type).isEmpty()) {

const QMap<int, double> map = DENSITY_MAP.value(type);

QMap<int, double>::const_iterator it = map.find(temperature);

if (it == map.end()) {

it = map.lowerBound(temperature);

if (it == map.end()) {

it = map.upperBound(temperature);

}

}

if (it != map.end()) {

return it.value();

}

}

switch (type) {

case WATER: return 1000;

default: return 1;

}

}

// возвращает удельную теплоту сгорания топлива [МДж/кг]

double UtilsCalc::getFuelHeat(UtilsCalc::FUEL_TYPE type) {

switch (type) {

case GAS: return 50.00;

case LIGNITE: return 25.00;

case CHARCOAL: return 33.89;

case ANTHRACITE: return 34.80;

case WOOD_OAK: return 19.87;

case WOOD_SPRUCE: return 20.30;

case WOOD_PINE: return 20.85;

case DIESEL: return 41.87;

case MASUT: return 41.84;

default: return 1;

}

}

// возвращает плотность топлива [кг/м^3]

double UtilsCalc::getFuelDensity(UtilsCalc::FUEL_TYPE type) {

switch (type) {

case GAS: return 0.7168;

case WOOD_OAK: return 710;

case WOOD_SPRUCE: return 432;

case WOOD_PINE: return 510;

case DIESEL: return 850;

case MASUT: return 995;

default: return 1;

}

}

// возвращает цену за единицу заданного типа топлива

double UtilsCalc::getFuelCost(UtilsCalc::FUEL_TYPE type) {

switch (type) {

case GAS: return 4.86;

case LIGNITE: return 4.7;

case CHARCOAL: return 16;

case ANTHRACITE: return 10;

case WOOD_OAK: return 1000;

case WOOD_SPRUCE: return 800;

case WOOD_PINE: return 900;

case DIESEL: return 32250;

case MASUT: return 12;

default: return 1;

}

}

// возвращает единицы измерения для заданного типа топлива

UtilsCalc::FUEL_UNITS UtilsCalc::getFuelUnits(UtilsCalc::FUEL_TYPE type) {

switch (type) {

case GAS: return M3;

case LIGNITE: return KG;

case CHARCOAL: return KG;

case ANTHRACITE: return KG;

case WOOD_OAK: return M3;

case WOOD_SPRUCE: return M3;

case WOOD_PINE: return M3;

case DIESEL: return M3;

case MASUT: return KG;

default: return KG;

}

}

// возвращает количество энергии для компенсации теплопотерь

double UtilsCalc::getSystemHeat(double temperature, double tempOff, const QTableWidget *tableTempHeat) {

if (temperature > tempOff) {

return 0;

}

QMap<double, double> tempHeatMap;

for (int i = 0; i < tableTempHeat->rowCount(); ++i) {

double temp = tableTempHeat->locale().toDouble(tableTempHeat->item(i, 0)->text());

double heat = tableTempHeat->locale().toDouble(tableTempHeat->item(i, 1)->text());

tempHeatMap.insert(temp, heat);

}

double tempUp = tempOff;

double tempDown = std::numeric_limits<double>::lowest();

for (double temp : tempHeatMap.keys()) {

if (temp > temperature && temp < tempUp) {

tempUp = temp;

}

if (temp < temperature && temp > tempDown) {

tempDown = temp;

}

}

if (tempDown == std::numeric_limits<double>::lowest()) {

tempDown = tempHeatMap.keys().first();

}

if (tempDown == tempUp) {

tempUp = tempHeatMap.keys().at(1);

}

double heatUp = (tempUp == tempOff) ? 0 : tempHeatMap.value(tempUp);

double heatDown = tempHeatMap.value(tempDown);

double heat = (heatDown - heatUp) / (tempUp - tempDown) * qAbs(temperature - tempDown);

if (temperature < tempDown) {

heat += heatDown;

} else {

heat = heatDown - heat;

}

return heat;

}

// расход энергии для нагрева теплоносителя [МДж/м^3]

double UtilsCalc::getOutHeat(double waterHeat, double waterDensity, double waterTempOut, double waterTempIn, double systemLosses) {

return waterHeat * waterDensity * (waterTempOut - waterTempIn) * (1 + systemLosses / 100.f) / 1000000.f;

}

// расход теплоносителя [м^3/ч]

double UtilsCalc::getOutWater(double systemHeat, double systemLosses, double waterHeat, double waterDensity, double waterTempOut, double waterTempIn) {

if (waterDensity == 0) {

return 0;

}

return systemHeat * (1 + systemLosses / 100.f) / (waterHeat * (waterTempOut - waterTempIn)) * 3600.f / waterDensity;

}

// расход электроэнергии [кВт*ч в сутки]

double UtilsCalc::getOutElectricity(double pumpsPower, bool heatByElectricity, double outWater, double outHeat) {

double outElectricity = pumpsPower / 1000.f;

if (heatByElectricity) {

outElectricity += outWater * outHeat / 3.6;

}

return outElectricity * 24.f;

}

// затраты на электроэнергию [рублей в сутки]

double UtilsCalc::getOutElectricityCost(double outElectricity, double electricityPrice) {

return outElectricity * electricityPrice;

}

// расход топлива [кг/ч] или [м^3/ч]

double UtilsCalc::getOutFuel(double outHeat, double outWater, double fuelHeat, UtilsCalc::FUEL_TYPE fuelType) {

if (fuelHeat == 0) {

return 0;

}

double outFuel = outHeat * outWater / fuelHeat;

if (getFuelUnits(fuelType) == M3) {

outFuel /= getFuelDensity(fuelType);

}

return outFuel;

}

// затраты на топливо [рублей в сутки]

double UtilsCalc::getOutFuelCost(double outFuel, double fuelPrice) {

return outFuel * fuelPrice * 24.f;

}

QMap<UtilsCalc::WATER_TYPE, QMap<int, double> > UtilsCalc::initWaterHeat() {

QMap<UtilsCalc::WATER_TYPE, QMap<int, double> > map;

QMap<int, double> mapWater;

mapWater.insert(1, 4217); mapWater.insert(10, 4191); mapWater.insert(15, 4187); mapWater.insert(20, 4183);

mapWater.insert(25, 4179); mapWater.insert(30, 4174); mapWater.insert(35, 4174); mapWater.insert(40, 4174);

mapWater.insert(45, 4177); mapWater.insert(50, 4181); mapWater.insert(55, 4182); mapWater.insert(60, 4182);

mapWater.insert(65, 4185); mapWater.insert(70, 4187); mapWater.insert(75, 4191); mapWater.insert(80, 4195);

mapWater.insert(85, 4202); mapWater.insert(90, 4208); mapWater.insert(95, 4214); mapWater.insert(100, 4220);

map.insert(WATER, mapWater);

return map;

}

QMap<UtilsCalc::WATER_TYPE, QMap<int, double> > UtilsCalc::initWaterDensity() {

QMap<UtilsCalc::WATER_TYPE, QMap<int, double> > map;

QMap<int, double> mapWater;

mapWater.insert(0, 999.8); mapWater.insert(2, 999.9); mapWater.insert(4, 1000); mapWater.insert(6, 999.9); mapWater.insert(8, 999.9);

mapWater.insert(10, 999.7); mapWater.insert(12, 999.5); mapWater.insert(14, 999.2); mapWater.insert(16, 999); mapWater.insert(18, 998.6);

mapWater.insert(20, 998.2); mapWater.insert(22, 997.8); mapWater.insert(24, 997.3); mapWater.insert(26, 996.8); mapWater.insert(28, 996.2);

mapWater.insert(30, 995.7); mapWater.insert(32, 995); mapWater.insert(34, 994.4); mapWater.insert(36, 993.7); mapWater.insert(38, 993);

mapWater.insert(40, 992.2); mapWater.insert(42, 991.4); mapWater.insert(44, 990.6); mapWater.insert(46, 989.8); mapWater.insert(48, 988.9);

mapWater.insert(50, 988); mapWater.insert(52, 987.1); mapWater.insert(54, 986.2); mapWater.insert(56, 985.2); mapWater.insert(58, 984.2);

mapWater.insert(60, 983.2); mapWater.insert(62, 982.1); mapWater.insert(64, 981.1); mapWater.insert(66, 980); mapWater.insert(68, 978.9);

mapWater.insert(70, 977.8); mapWater.insert(72, 976.6); mapWater.insert(74, 975.4); mapWater.insert(76, 974.2); mapWater.insert(78, 973);

mapWater.insert(80, 971.8); mapWater.insert(82, 970.5); mapWater.insert(84, 969.3); mapWater.insert(86, 967.8); mapWater.insert(88, 966.6);

mapWater.insert(90, 965.3); mapWater.insert(92, 963.9); mapWater.insert(94, 962.6); mapWater.insert(96, 961.2); mapWater.insert(98, 959.8);

mapWater.insert(100, 958.4);

map.insert(WATER, mapWater);

return map;

}

ПРИЛОЖЕНИЕ 4

Структура документов форматов *.fpf и *.tsf на языке XML Schema

Описание структуры документов формата *.tsf:

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="stats">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="place" type="placeType" minOccurs="0" maxOccurs="1" />

<xsd:element name="temperatures" type="temperaturesType" minOccurs="1" maxOccurs="unbounded">

<xsd:unique name="uniqueTempDate">

<xsd:selector xpath="temp" />

<xsd:field xpath="@date" />

</xsd:unique>

</xsd:element>

</xsd:sequence>

</xsd:complexType>

<xsd:unique name="uniqueTemperaturesYear">

<xsd:selector xpath="temperatures" />

<xsd:field xpath="@year" />

</xsd:unique>

</xsd:element>

<xsd:complexType name="placeType">

<xsd:sequence>

<xsd:element name="title" type="xsd:string" />

<xsd:element name="coords" type="coordsType" minOccurs="0" maxOccurs="1" />

</xsd:sequence>

</xsd:complexType>

<xsd:complexType name="coordsType">

<xsd:attribute name="latitude" use="required">

<xsd:simpleType>

<xsd:restriction base="xsd:float">

<xsd:minInclusive value="-90" />

<xsd:maxInclusive value="90" />

</xsd:restriction>

</xsd:simpleType>

</xsd:attribute>

<xsd:attribute name="longitude" use="required">

<xsd:simpleType>

<xsd:restriction base="xsd:float">

<xsd:minInclusive value="-180" />

<xsd:maxInclusive value="180" />

</xsd:restriction>

</xsd:simpleType>

</xsd:attribute>

</xsd:complexType>

<xsd:complexType name="temperaturesType">

<xsd:sequence>

<xsd:element name="temp" maxOccurs="unbounded">

<xsd:complexType>

<xsd:simpleContent>

<xsd:extension base="xsd:float">

<xsd:attribute name="date" type="xsd:gMonthDay" use="required" />

</xsd:extension>

</xsd:simpleContent>

</xsd:complexType>

</xsd:element>

</xsd:sequence>

<xsd:attribute name="year" type="xsd:gYear" use="required" />

</xsd:complexType>

</xsd:schema>

Описание структуры документов формата *.fpf:

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="forecastProject">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="stats">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="place" type="placeType" minOccurs="0" maxOccurs="1" />

<xsd:element name="temperatures" type="temperaturesType" minOccurs="0" maxOccurs="unbounded" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:element name="forecastParams">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="turnOff" type="xsd:float" />

<xsd:element name="heat" minOccurs="0" maxOccurs="5">

<xsd:complexType>

<xsd:simpleContent>

<xsd:extension base="xsd:float">

<xsd:attribute name="temp" type="xsd:float" use="required" />

</xsd:extension>

</xsd:simpleContent>

</xsd:complexType>

</xsd:element>

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:element name="systemParams">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="losses" type="xsd:integer" />

<xsd:element name="pumpsPower" type="xsd:integer" />

<xsd:element name="electricityPrice" type="xsd:float" />

<xsd:element name="isHeatByElectricity" type="xsd:boolean" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:element name="waterParams">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="type" type="xsd:integer" />

<xsd:element name="tempIn" type="xsd:integer" />

<xsd:element name="tempOut" type="xsd:integer" />

<xsd:element name="heatOther" type="xsd:float" />

<xsd:element name="densityOther" type="xsd:float" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:element name="fuelsList">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="fuel" type="fuelType" minOccurs="1" maxOccurs="unbounded" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:complexType name="placeType">

<xsd:sequence>

<xsd:element name="title" type="xsd:string" />

<xsd:element name="coords" type="coordsType" minOccurs="0" maxOccurs="1" />

</xsd:sequence>

</xsd:complexType>

<xsd:complexType name="coordsType">

<xsd:attribute name="latitude" use="required">

<xsd:simpleType>

<xsd:restriction base="xsd:float">

<xsd:minInclusive value="-90" />

<xsd:maxInclusive value="90" />

</xsd:restriction>

</xsd:simpleType>

</xsd:attribute>

<xsd:attribute name="longitude" use="required">

<xsd:simpleType>

<xsd:restriction base="xsd:float">

<xsd:minInclusive value="-180" />

<xsd:maxInclusive value="180" />

</xsd:restriction>

</xsd:simpleType>

</xsd:attribute>

</xsd:complexType>

<xsd:complexType name="temperaturesType">

<xsd:sequence>

<xsd:element name="temp" maxOccurs="unbounded">

<xsd:complexType>

<xsd:simpleContent>

<xsd:extension base="xsd:float">

<xsd:attribute name="week" type="xsd:integer" use="required" />

</xsd:extension>

</xsd:simpleContent>

</xsd:complexType>

</xsd:element>

</xsd:sequence>

<xsd:attribute name="year" type="xsd:gYear" use="required" />

</xsd:complexType>

<xsd:complexType name="fuelType">

<xsd:sequence>

<xsd:element name="type" type="xsd:integer" />

<xsd:element name="price" type="xsd:float" />

<xsd:element name="typeOther" type="xsd:string" />

<xsd:element name="priceOther" type="xsd:float" />

<xsd:element name="heatOther" type="xsd:float" />

</xsd:sequence>

</xsd:complexType>

</xsd:schema>

ПРИЛОЖЕНИЕ 5

Руководство пользователя

В данном руководстве описаны принципы работы с программой «Подсистема прогноза снабжения энергетическими ресурсами теплогенераторных станций».

Руководство содержит подробное описание функций программы и особенностей её пользовательского интерфейса, порядок работы с программой, описание поддерживаемых форматов файлов, а также список возможных ошибок при работе с программой и способы их решения.

1. О программе.

Программа предназначена для автоматизации процесса прогнозирования затрат энергетических ресурсов при производстве тепловой энергии теплогенераторными станциями.

Прогнозирование затрат осуществляется на основе анализа имеющихся статистических данных за прошедшие периоды времени и составления прогноза изменения температуры окружающей среды в следующий период.

Программа позволяет добавлять неограниченное количество статистических данных температуры воздуха окружающей среды, задавать параметры системы теплоснабжения и теплоносителя. Возможно одновременное сравнение затрат на производство тепловой энергии до 10 видов топливных ресурсов. Также предусмотрено изменение цен и параметров ресурсов для расчета необходимых объемов и стоимости поставок ресурсов потребителю.

Результатами работы программы являются данные о расходе тепловой энергии для нагрева теплоносителя, расходе теплоносителя в системе, расходе и затратах на электроэнергию, а также расходе и затратах топливных ресурсов для работы системы теплоснабжения.

Процесс аппроксимации исходных данных изменения температуры окружающей среды и составления прогноза визуализируется при помощи построения графика прогноза температуры воздуха окружающей среды на следующий период. Результаты работы программы могут быть сохранены в форматах *.fpf и *.tsf, а также в виде отчета в формате *.xlsx.

  • 2. Интерфейс программы.
  • 2.1. Стартовое окно.

Стартовое окно - окно программы, открывающееся при запуске программы. Стартовое окно представлено на рисунке 1.

п. 1 - Стартовое окно

Рисунок п. 1 - Стартовое окно

В центре окна находятся три главные кнопки:

  • l Новый проект.
  • l Открыть проект.
  • l Быстрый расчёт.

'Новый проект' - позволяет открыть окно прогнозирования с заполненными по умолчанию полями для составления нового прогноза затрат энергетических ресурсов теплогенераторными станциями.

'Открыть проект' - позволяет открыть окно прогнозирования с заполненными полями, прочитанными из сохранённого файла форматов *.fpf или *.tsf.

'Быстрый расчёт' - позволяет открыть окно быстрого расчёта для расчёта затрат топливных ресурсов при производстве тепловой энергии без расчёта прогноза изменения температуры воздуха окружающей среды.

В верхней части окна находится главное меню со следующими пунктами:

l Файл:

Ѓ Новый проект - открыть окно прогнозирования.

Ѓ Открыть проект - загрузить данные прогнозирования из файла.

Ѓ Быстрый расчёт - открыть окно быстрого расчёта.

Ѓ Выход - выход из программы.

l Справка:

Ѓ Помощь - открыть руководство пользователя.

Ѓ О программе - открыть диалоговое окно с информацией о программе.

Ѓ О Qt - открыть диалоговое окно с информацией об используемой в программе версии Qt.

Для вызова пунктов меню имеются следующие сочетания клавиш:

  • l Ctrl+N - Новый проект.
  • l Ctrl+O - Открыть проект.
  • l Ctrl+Пробел - Быстрый расчёт.
  • l Ctrl+Q - Выход.
  • l F1 - Помощь.
  • 2.2. Окно прогнозирования.

Окно прогнозирования предназначено для составления прогноза затрат энергетических ресурсов для производства тепловой энергии теплогенераторными станциями. В окне прогнозирования расположены необходимые для составления прогноза поля и элементы управления. Окно прогнозирования представлено на рисунке 2.

п. 2 - Окно прогнозирования

Рисунок п. 2 - Окно прогнозирования

В верхней части окна находится главное меню со следующими пунктами:

l Файл:

Ѓ Новый проект - закрыть текущий проект и установить значения полей на значения по умолчанию.

Ѓ Открыть файл или проект - загрузить данные прогнозирования из файла формата *.fpf или *.tsf.

Ѓ Сохранить - сохранить текущий проект.

Ѓ Сохранить как... - сохранить текущий проект в новый файл.

Ѓ Сохранить отчёт - сохранить отчет о прогнозе в файл формата *.xlsx.

Ѓ Закрыть проект - закрыть текущий проект и открыть стартовое окно программы.

Ѓ Выход - выход из программы.

l Справка:

Ѓ Помощь - открыть руководство пользователя.

Ѓ О программе - открыть диалоговое окно с информацией о программе.

Ѓ О Qt - открыть диалоговое окно с информацией об используемой в программе версии Qt.

Для вызова пунктов меню имеются следующие сочетания клавиш:

  • l Ctrl+N - Новый проект.
  • l Ctrl+O - Открыть файл или проект.
  • l Ctrl+S - Сохранить.
  • l Ctrl+P - Сохранить отчёт.
  • l Ctrl+W - Закрыть проект.
  • l Ctrl+Q - Выход.
  • l F1 - Помощь.

Кнопки на панели быстрого доступа под главным меню представлены на рисунке 3.

п. 3 - Кнопки панели быстрого доступа

Рисунок п. 3 - Кнопки панели быстрого доступа:

  • 1 - новый проект; 2 - открыть файл или проект; 3 - сохранить;
  • 4 - закрыть проект; 5 - закрыть проект; 6 - помощь

Положение панели быстрого доступа может быть изменено. Для этого наведите курсор мыши на левый край панели, зажмите левую клавишу мыши и переместите панель. Перемещение панели быстрого доступа представлено на рисунке 4.

п. 4 - Перемещение панели быстрого доступа

Рисунок п. 4 - Перемещение панели быстрого доступа

После составления прогноза и построения графика, Вы можете изменять положение ползунка на графике путём зажатия левой клавиши мыши над ним и передвижения курсора мыши. В соответствии с графиком и значением текущего положения ползунка будет изменяться прогноз необходимого количества производимой энергии для компенсации теплопотерь потребителей. Изменение прогноза производимой энергии представлено на рисунке 5.

п. 5 - Изменение прогноза производимой энергии

Рисунок п. 5 - Изменение прогноза производимой энергии

Изменение необходимого количества производимой энергии для компенсации теплопотерь потребителей автоматически вызывает обновление расчетных данных в правой части программы. Здесь расположены расчетные параметры системы, а также затраты на электроэнергию и выбранных для сравнения топливных ресурсов.

2.3. Окно быстрого расчёта.

Окно быстрого расчёта предназначено для расчёта затрат топливных ресурсов при производстве тепловой энергии без расчёта прогноза изменения температуры воздуха окружающей среды. Окно быстрого расчёта представлено на рисунке 6.

п. 6 - Окно быстрого расчёта

Рисунок п. 6 - Окно быстрого расчёта

В верхней части окна находится главное меню со следующими пунктами:

l Файл:

Ѓ Сохранить отчёт - сохранить отчет в файл формата *.xlsx.

Ѓ В главное меню - открыть стартовое окно программы.

Ѓ Выход - выход из программы.

l Справка:

Ѓ Помощь - открыть руководство пользователя.

Ѓ О программе - открыть диалоговое окно с информацией о программе.

Ѓ О Qt - открыть диалоговое окно с информацией об используемой в программе версии Qt.

Для вызова пунктов меню имеются следующие сочетания клавиш:

  • l Ctrl+P - Сохранить отчёт.
  • l Ctrl+Q - Выход.
  • l F1 - Помощь.
  • 3. Работа с файлами.

Результаты работы программы могут быть сохранены в форматах *.fpf и *.tsf, а также в виде отчета в формате *.xlsx.

Формат *.fpf (ForecastProjectFile - файл проекта прогноза) содержит всю информацию о составленном в программе прогнозе затрат энергетических ресурсов. В нём хранится информация о статистических данных изменения температуры воздуха окружающей среды, параметры системы теплоснабжения, параметры теплоносителя и список выбранных для сравнения топливных ресурсов с их параметрами. Файл, сохранённый в формате *.fpf позволяет быстро возобновить работу с ранее составленным прогнозом затрат ресурсов.

Формат *.tsf (TemperatureStatisticsFile - файл статистики температуры) содержит только информацию о статистических данных изменения температуры воздуха окружающей среды. Файл, сохранённый в формате *.tsf позволяет загрузить данные об изменении температуры для создания нового проекта.

Формат *.xlsx (Рабочая книга Excel) - стандартный формат рабочих книг приложения Excel 2007, входящий в группу форматов Office Open XML. Предназначен для хранения информации об электронных таблицах для работы в таких программах как Microsoft Office Excel и OpenOffice Calc.

  • 4. Быстрый расчёт.
  • 4.1. Порядок работы.

Быстрый расчёт производится на основе информации о необходимом генерируемом системой количестве тепла для компенсации теплопотерь потребителей системы.

Для выполнения быстрого расчёта выполните следующие шаги:

  • 1. Заполните поля параметров системы теплоснабжения.
  • 2. Заполните поля параметров теплоносителя.
  • 3. Заполните список сравниваемых топливных ресурсов.
  • 4. При необходимости сохраните отчёт с помощью пункта 'Сохранить отчёт' в меню 'Файл'.
 
Если Вы заметили ошибку в тексте выделите слово и нажмите Shift + Enter
< Предыдущая   СОДЕРЖАНИЕ   Следующая >
 
Предметы
Агропромышленность
Банковское дело
БЖД
Бухучет и аудит
География
Документоведение
Естествознание
Журналистика
Информатика
История
Культурология
Литература
Логика
Логистика
Маркетинг
Математика, химия, физика
Медицина
Менеджмент
Недвижимость
Педагогика
Политология
Право
Психология
Религиоведение
Социология
Статистика
Страховое дело
Техника
Товароведение
Туризм
Философия
Финансы
Экология
Экономика
Этика и эстетика
Прочее