- •Цели и задачи лабораторной работы
- •Исходные Данные
- •Анализ исходных данных и ход работы
- •Экспериментальные кинетические кривые
- •Дополненная диаграмма
- •Алгоритмы методов расчета
- •Метод Эйлера
- •Блок-схема алгоритма
- •Список идентификаторов
- •Метод двойного просчета
- •Блок-схема алгоритма
- •Список идентификаторов
- •Результат расчета
- •Кривые, полученные методом Эйлера
- •Текст программы
- •Результаты программного расчета
Алгоритмы методов расчета
Метод Эйлера
Блок-схема алгоритма
Список идентификаторов
Смысл переменной
Обозначение
В алгоритме
В программе
Исходные данные
Константы скорости реакции
Шаг интегрирования
Таблица реперных точек
Количество точек
k1, k2
T
n
k1, k2
dt
C
n
Промежуточные данные
Текущее значение времени
Текущая концентрация вещества А
Текущая концентрация вещества В
Предыдущая концентрация вещества А
Предыдущая концентрация вещества В
T
Ca
Cb
Pca
Pcb
T
ca
cb
pca
pcb
Выходные данные
Таблица значений функции
T
C
Метод двойного просчета
Блок-схема алгоритма
Список идентификаторов
Смысл переменной
Обозначение
В алгоритме
В программе
Исходные данные
Константы скорости реакции
Допустимая погрешность
Таблица реперных точек
Количество точек
k1, k2
e
T
n
k1, k2
e
c
n
Промежуточные данные
Шаг интегрирования
Вспомогательная таблица
Текущая погрешность
Погрешность в данной точке
Коэффициент уменьшения шага
dt
T’
ef
d
k
dt
c_tmp
d
d
K
Выходные данные
Таблица значений функции
T
c
Результат расчета
В результате решения системы дифференциальных уравнений получены следующие значения констант скоростей реакции.
k1 = 0.08
k2 = 0.025
k3 = 0.7
k4 = 0.7
Аналитически зависимости примут вид, указанный на рисунке 3.
Кривые, полученные методом Эйлера
Выводы
В ходе лабораторной работы освоили методику формирования математической модели кинетики химической реакции в форме дифференциальных уравнений
Подобраны численные значения констант скорости реакции по исходным экспериментальным данным кинетического исследования с использованием метода Эйлера.
Получены в ходе решения системы дифференциальных уравнений концентрационные зависимости для компонентов A, B, C, D. Данные зависимости практически совпадают с опытными кинетическими кривыми по соответствующим компонентам (среднеквадратичное отклонение 0,71%).
Вычисленные значения констант подтверждают верность выбранной математической модели кинетики процесса, так как при достижении =40 мин (время достижения равновесных концентраций) скорости обратимых реакций выравниваются.
Текст программы
program lab_2;
const
array_max = 30;
{ global types * }
type
point = record
t: real;
ca: real;
cb: real;
end;
table_t = array [1..array_max] of point;
vector = array[1..array_max] of real;
{ reporting of errors * }
procedure error(msg: string);
begin
writeln('ERROR: ',msg);
readln;
halt;
end;
{ method of Euler * }
procedure euler(
k1: real;
k2: real;
dt: real;
var c: table_t;
n: integer);
var
ca: real;
cb: real;
pca: real;
pcb: real;
t: real;
i: integer;
begin
t := c[1].t;
ca := c[1].ca;
cb := c[1].cb;
for i:= 2 to n do
begin
while c[i].t-t >= dt do
begin
pca := ca;
pcb := cb;
ca := pca + (-k1*pca + k2*pcb)*dt;
cb := pcb + (k1*pca - k2*pcb)*dt;
t := t + dt;
end;
c[i].ca := ca;
c[i].cb := cb;
end;
end;
{ double calculation method * }
procedure double_calc(
k1: real;
k2: real;
e: real;
var c: table_t;
n: integer);
const
k = 0.5;
var
ca: vector;
cb: vector;
dt: real;
ef: real;
e_pred: real;
d: real;
i: integer;
begin
dt := (c[n].t-c[1].t)/100;
repeat
euler(k1, k2, dt, c, n);
e_pred := ef;
ef := 0;
for i:= 2 to n do
begin
d := abs(c[i].ca - ca[i]);
if d > ef then ef := d;
d := abs(c[i].cb - cb[i]);
if d > ef then ef := d;
ca[i] := c[i].ca;
cb[i] := c[i].cb;
end;
dt := k*dt;
until (ef < e) or (ef > e_pred);
end;
{ difference between two tables * }
function difference(
t1: table_t;
t2: table_t;
n: integer): real;
var
i: integer;
max: real;
s: real;
d: real;
begin
max := 0;
for i:=2 to n do
begin
d := abs(t1[i].ca - t2[i].ca);
s := s + sqr(d/t1[i].ca);
if d > max then max := d;
d := abs(t1[i].cb - t2[i].cb);
s := s + sqr(d/t1[i].cb);
if d > max then max := d;
end;
difference := 100*sqrt(s/2/n);
end;
{ printing a table * }
procedure print_table(const table: table_t; n: integer);
var
i: integer;
begin
writeln(' time | Ca | Cb');
writeln('------------------------------------');
for i:= 1 to n do
writeln(
table[i].t:10:3,' | ',
table[i].ca:10:3,' | ',
table[i].cb:10:3);
writeln;
end;
{ reading a table * }
procedure read_table(var table: table_t; n: integer);
var i: integer;
begin
for i:= 1 to n do
begin
writeln(i,':');
write(' t : ');
readln(table[i].t);
write(' Ca: ');
readln(table[i].ca);
write(' Cb: ');
readln(table[i].cb);
end;
end;
{ copy from array to table * }
procedure copy(
const src: array of point;
var dst: table_t;
n: integer );
var
i: integer;
begin
for i:= 1 to n do
dst[i] := src[i-1];
for i:= n+1 to array_max do
begin
dst[i].t := 0;
dst[i].ca := 0;
dst[i].cb := 0;
end;
end;
{ input data * }
procedure input_data(
var c: table_t;
var n: integer);
var
i: integer;
begin
write('Enter number of points: ');
readln(n);
writeln('Enter graph data');
read_table(c,n);
end;
{ display a menu * }
function choice(
const v: array of string;
n: integer;
var selected: integer): boolean;
var
i: integer;
begin
writeln;
for i:=0 to n-1 do
writeln(i+1,' - ',v[i]);
writeln;
write('Your choice: ');
readln(selected);
if (selected > n) or (selected < 1) then
begin
writeln('Nothing selected');
choice := false;
end
else
choice := true;
end;
{ get data * }
procedure get_data(
var c: table_t;
var n: integer);
const
menu: array [1..3] of string =
('Your own data',
'Sample data. Variant 1',
'Sample data. Variant 2');
sample_1: array [1..3] of point =
((t: 0; ca: 400; cb: 0),
(t: 10; ca: 200; cb: 200),
(t: 40; ca: 100; cb: 300));
sample_2: array [1..3] of point =
((t: 0; ca: 200; cb: 0),
(t: 5; ca: 150; cb: 50),
(t: 40; ca: 100; cb: 100));
var
ch: integer;
begin
writeln('Select type of data');
if choice(menu, 3, ch) then
case ch of
1: { own data }
input_data(c,n);
2: { sample 1 }
begin
n := 3;
copy(sample_1,c,3);
end;
3: { sample 2 }
begin
n := 3;
copy(sample_2,c,3);
end;
end
else
error('Unable to read data');
end;
{ manual run * }
procedure manual_run;
var
str: string;
ch: integer;
make_check: boolean;
c: table_t;
rc: table_t;
c_tmp: table_t;
n: integer;
m: integer;
k1: real;
k2: real;
i: integer;
time: real;
interval: real;
prec: real;
d: real;
begin
{ read the data }
make_check := true;
get_data(c,n);
writeln('You have selected the following data');
print_table(c,n);
c_tmp := c;
{define some reference points}
write('Enter total time(min): ');
readln(time);
write('Enter reference interval(min): ');
readln(interval);
m := trunc(time/interval) + 1;
for i:= 1 to m do
rc[i].t := (i-1)*interval;
rc[1].ca := c[1].ca;
rc[1].ca := c[1].ca;
write('enter precision: ');
readln(prec);
repeat
{ enter the constants }
writeln('Enter the constants');
write('k1 = ');
readln(k1);
write('k2 = ');
readln(k2);
{ build the table }
double_calc(k1, k2, prec, rc, m);
print_table(rc,m);
{ calculate diffefence }
if make_check then
begin
double_calc(k1, k2, prec, c_tmp, n);
d := difference(c, c_tmp, n);
writeln('maximum difference is ',d:8:3);
end;
write('Press enter to continue. Type ''exit'' to exit: ');
readln(str);
until 'exit' = str;
end;
{ main program * }
var
c: integer;
begin
writeln('Hello');
writeln;
manual_run;
writeln('Finished. Press enter');
readln;
end.