Форум для моих друзей
http://atheist4.flybb.ru/

Нахождение концентрации вещества при диффузии.
http://atheist4.flybb.ru/topic31.html
Страница 1 из 1

Автор:  atheist4 [ 02-06, 08:26 ]
Заголовок сообщения:  Нахождение концентрации вещества при диффузии.

Обновлены публикации:

http://atheist4.narod.ru/diffuz.htm

http://atheist4.narod.ru/simplediffuz.htm

Исправлена опечатка.

Хотел решение трансцендентного уравнения искать методом касательных, а не методом деления отрезка пополам. Но погрешность вычислений стала больше, и программа зависает уже при N=1000, при h=1, L=3, DX=1E-8 ,например:

procedure PCoInvoluta;
const
DX=1E-8;
var
h:real;
L:real;
M:real;
K:integer;
W: real;
N: integer;

function Y(X:real):real;
begin
Y:=h*Cos(X*L)/Sin(X*L)-X;
end;

function Z(X:real):real;
begin
Z:=-h*L/Sin(X*L)/Sin(X*L)-1;
end;

begin
h:= StrToFloat(Form1.Edit1.Text);
L:= StrToFloat(Form1.Edit2.Text);
N:= StrToInt(Form1.Edit3.Text);
if Form1.CheckBox1.State = cbChecked
then Form1.Memo1.Visible:=true
else Form1.Memo1.Visible:=false;
Form1.Memo2.Visible:=false;
Form1.Memo3.Visible:=false;
for K:=1 to N do
begin
M:=Pi/4/L;
if Y(Pi*(K-1)/L+M)<=0
then
repeat M:=M/2;
until Y(Pi*(K-1)/L+M)>0;
W:=Pi*(K-1)/L+M;
While Y(W)/(h*L+1)>DX do W:=W-Y(W)/Z(W);
Form1.Memo1.Lines.Add('W('+IntToStr(K)+')='+FloatToStrF(W,ffFixed,20,14));
Form1.Memo2.Lines.Add('d('+IntToStr(K)+')='+FloatToStr(Y(W)));
Form1.Memo3.Lines.Add('f('+IntToStr(K)+')='+FloatToStr(abs(Y(W)/W)));
end;
Form1.Memo1.Lines.Add('Êîðíè óðàâíåíèÿ W=h*ctg(W*L)');
Form1.Memo1.Lines.Add('h='+FloatToStr(h)+' L='+FloatToStr(L));
Form1.Memo1.Visible:=true;
end;

Поэтому оставлю лучше всё, как было - буду искать методом деления отрезка пополам:

procedure PCoInvoluta;
const
DX=1E-30;{погрешность вычисления}
var
h:real;{Значение h}
L:real;{Значение L}
M:real;
K:integer;
I,P: integer;
X1,X2 :real;
W: real;
N: integer;
F: TextFile;
function Y(Z:real):real;
begin
Y:=h*Cos(Z*L)/Sin(Z*L)-Z;
end;
begin
h:= StrToFloat(Form1.Edit1.Text);
L:= StrToFloat(Form1.Edit2.Text);
N:= StrToInt(Form1.Edit3.Text);
if Form1.CheckBox1.State = cbChecked
then Form1.Memo1.Visible:=true
else Form1.Memo1.Visible:=false;
Form1.Memo2.Visible:=false;
Form1.Memo3.Visible:=false;
Form1.Memo1.Lines.Add('Корни уравнения W=h*ctg(W*L)');
Form1.Memo1.Lines.Add('h='+FloatToStr(h)+' L='+FloatToStr(L));
Form1.Memo2.Lines.Add('Абсолютные погрешности:');
Form1.Memo3.Lines.Add('Относитенльные погрешности:');
if Form1.CheckBox2.State = cbChecked
then Form1.Label5.Caption:='h'+Form1.Edit1.Text+'L'+Form1.Edit2.Text+'.txt';
for K:=1 to N do
begin
M:=Pi/4/L;
if Y(Pi*(K-1)/L+M)<=0
then
repeat M:=M/2;
until Y(Pi*(K-1)/L+M)>0;
X1:=Pi*(K-1)/L+M;
X2:=Pi*(K-1)/L+2*M;
W:=X2;
P:=Round(Ln(M/DX)/Ln(2));
for I:=1 to P do
begin
if Y(X1)*Y(W)<=0
then X2:=W
else X1:=W;
W:=(X1+X2)/2;
end;
Form1.Memo1.Lines.Add('W('+IntToStr(K)+')='+FloatToStr(W));
Form1.Memo2.Lines.Add('d('+IntToStr(K)+')='+FloatToStr(Y(W)));
Form1.Memo3.Lines.Add('f('+IntToStr(K)+')='+FloatToStr(abs(Y(W)/W)));
end;
Form1.Memo1.Visible:=true;
if Form1.CheckBox2.State = cbChecked
then
begin
AssignFile(F,Form1.Label5.Caption);
Rewrite(F);
WriteLn(F,Form1.Memo1.Text);
WriteLn(F,Form1.Memo2.Text);
WriteLn(F,Form1.Memo3.Text);
Close(F);
end;
end;

Автор:  atheist4 [ 02-06, 22:26 ]
Заголовок сообщения: 

Обновлённая программа

http://atheist4.narod.ru/programs/diffuz.rar

показывает терерь проверку решения дифференциального уравнения

procedure PDiffuz;
const
DX=1E-17; { погрешность вычисления }
var
h: real; { Значение h }
L: real; { Значение L - длина промежутка }
b: real; { Значение b }
D: real; { Значение коэффициента диффузии D }
A0: real; { Значение начальной концентрации }
N: integer; { Количество членов ряда}
M: real;
K: integer; { Номер члена ряда }
I, P: integer;
X1, X2: real;
x: real; { Координата x }
t:real; { Время t }
W: real; { Корни уравнения W=h*ctg(W*L) }
a: real; { Коэффициенты разложения единицы в ряд по cos(wx) }
V: real; { K-й член ряда в сумме n(x, t) }
Q: real; { n(x, t) - концентрация }
G: real; { K-й член ряда в сумме dn(x, t)/dx }
U: real; { dn(x, t)/dx - производная от концентрации по координате x }
{ Данные для проверки правильности решения диф. уравнения }
C1: real; { K-й член ряда в сумме dn(x, t)/dt }
F1: real; { dn(x, t)/dt - производная от концентрации по времени t}
C2: real; { K-й член ряда в сумме d2n(x, t)/dx2 }
F2: real; { d2n(x, t)/dx2 - вторая производная от концентрации по x }

function Y(Z:real):real;
begin
Y:=h*Cos(Z*L)/Sin(Z*L)-Z;
end;

begin
U:=0;
L:= StrToFloat(Form1.Edit1.Text);
h:= StrToFloat(Form1.Edit2.Text);
b:= StrToFloat(Form1.Edit3.Text);
D:= StrToFloat(Form1.Edit4.Text);
A0:=StrToFloat(Form1.Edit5.Text);
x:= StrToFloat(Form1.Edit6.Text);
t:= StrToFloat(Form1.Edit7.Text);
N:= StrToInt(Form1.Edit8.Text);
Q:= A0*exp(-b*t);
U:= 0;
F1:= -A0*b*exp(-b*t);
F2:= 0;
if x>L then
begin
x:=L;
Form1.Edit6.Text:=FloatToStr(x);
end;
for K:=1 to N do
begin
M:=Pi/4/L;
if Y(Pi*(K-1)/L+M)<0>0;
X1:= Pi*(K-1)/L+M;
X2:= Pi*(K-1)/L+2*M;
W:= X2;
P:= Round(Ln(M/DX)/Ln(2));
for I:=1 to P do
begin
if Y(X1)*Y(W)<0>L then
begin
x:=L;
Form1.Edit6.Text:=FloatToStr(x);
end;
for K:=1 to N do
begin
W:= Pi*(2*K-1)/2/L;
a:= sin(W*L)/(W*L/2+sin(2*W*L)/4);
V:= A0*b*a/(D*W*W-b)*(exp(-b*t)-exp(-D*W*W*t))*cos(W*x);
Q:= Q+V;
G:= -A0*b*a*W/(D*W*W-b)*(exp(-b*t)-exp(-D*W*W*t))*sin(W*x);
U:= U+G;
C1:= A0*b*a/(D*W*W-b)*(-b*exp(-b*t)+D*W*W*exp(-D*W*W*t))*cos(W*x);
F1:= F1+C1;
C2:= -A0*b*a*W*W/(D*W*W-b)*(exp(-b*t)-exp(-D*W*W*t))*cos(W*x);
F2:= F2+C2;
end;
Form1.Label10.Caption:=' Концентрация n(x, t) = '+FloatTostr(Q)+
#13+#13+'Градиент концентрации dn(x,t)/dx = '+ FloatTostr(U) ;
Form1.Label11.Caption:='Проверка: dn/dt = '+ FloatToStr(F1)+ #13+
' D*d2n/dx2 = '+ FloatToStr(D*F2);
if x=L then
Form1.Label11.Caption:=Form1.Label11.Caption + #13 +
'на границе A*exp(-b*t) = ' +FloatToStr(A0*exp(-b*t));

end;

Эта программа даёт верное решение дифференциального уравнения.

http://atheist4.narod.ru/diffuz.htm

Автор:  atheist4 [ 02-06, 22:34 ]
Заголовок сообщения: 

Но такая же программа с проверкой для второй задачи даёт ошибочное решение дифференциального уравнения

procedure PSimpleDiffuz;
var
h: real; { Значение h }
L: real; { Значение L - длина промежутка }
b: real; { Значение b }
D: real; { Значение коэффициента диффузии D }
A0: real; { Значение начальной концентрации }
N: integer; { Количество членов ряда}
K: integer; { Номер члена ряда }
x: real; { Координата x }
t:real; { Время t }
W: real; { Корни уравнения cos(W*L)=0 }
a: real; { Коэффициенты разложения единицы в ряд по cos(wx) }
V: real; { K-й член ряда в сумме n(x, t) }
Q: real; { n(x, t) - концентрация }
G: real; { K-й член ряда в сумме dn(x, t)/dx }
U: real; { dn(x, t)/dx - производная от концентрации по координате x }
{ Данные для проверки правильности решения диф. уравнения }
C1: real; { K-й член ряда в сумме dn(x, t)/dt }
F1: real; { dn(x, t)/dt - производная от концентрации по времени t}
C2: real; { K-й член ряда в сумме d2n(x, t)/dx2 }
F2: real; { d2n(x, t)/dx2 - вторая производная от концентрации по x }

function Y(Z:real):real;
begin
Y:=h*Cos(Z*L)/Sin(Z*L)-Z;
end;

begin
U:=0;
L:= StrToFloat(Form1.Edit1.Text);
h:= StrToFloat(Form1.Edit2.Text);
b:= StrToFloat(Form1.Edit3.Text);
D:= StrToFloat(Form1.Edit4.Text);
A0:=StrToFloat(Form1.Edit5.Text);
x:= StrToFloat(Form1.Edit6.Text);
t:= StrToFloat(Form1.Edit7.Text);
N:= StrToInt(Form1.Edit8.Text);
Q:= A0*exp(-b*t);
U:= 0;
F1:= -A0*b*exp(-b*t);
F2:= 0;
if x>L then
begin
x:=L;
Form1.Edit6.Text:=FloatToStr(x);
end;
for K:=1 to N do
begin
W:= Pi*(2*K-1)/2/L;
a:= sin(W*L)/(W*L/2+sin(2*W*L)/4);
V:= A0*b*a/(D*W*W-b)*(exp(-b*t)-exp(-D*W*W*t))*cos(W*x);
Q:= Q+V;
G:= -A0*b*a*W/(D*W*W-b)*(exp(-b*t)-exp(-D*W*W*t))*sin(W*x);
U:= U+G;
C1:= A0*b*a/(D*W*W-b)*(-b*exp(-b*t)+D*W*W*exp(-D*W*W*t))*cos(W*x);
F1:= F1+C1;
C2:= -A0*b*a*W*W/(D*W*W-b)*(exp(-b*t)-exp(-D*W*W*t))*cos(W*x);
F2:= F2+C2;
end;
Form1.Label10.Caption:=' Концентрация n(x, t) = '+FloatTostr(Q)+
#13+#13+'Градиент концентрации dn(x,t)/dx = '+ FloatTostr(U) ;
Form1.Label11.Caption:='Проверка: dn/dt = '+ FloatToStr(F1)+ #13+
' D*d2n/dx2 = '+ FloatToStr(D*F2);
if x=L then
Form1.Label11.Caption:=Form1.Label11.Caption + #13 +
'на границе A*exp(-b*t) = ' +FloatToStr(A0*exp(-b*t));

end;

Где ошибка в решении второй задачи:

http://atheist4.narod.ru/simplediffuz.htm ?

Автор:  atheist4 [ 09-06, 20:00 ]
Заголовок сообщения: 

Всё проверено. Ошибки нет. Просто на границе ряд не допускает почленного дифференцирования. Обновлённые программы можете скачать по ссылкам:
http://atheist4.narod.ru/programs/diffuz.rar

http://atheist4.narod.ru/programs/simplediffuz.rar

http://atheist4.narod.ru/programs/diffuzall.rar

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/