更新了问题的内容,因为我自己理解并纠正了一些地方。因此有以下变量:
hx (шаг по пространству)= 0.1
ht (шаг по времени) = 0.5
Nx (Количество шагов по пространству) = 10;
Nt (Количество шагов по времени) = 12;
wx[i] - массив содержит все шаги по пространству
wt[j] - массив содержит все шаги по времени
wht[j][i]-двумерный массив по которому будет строится результирующий график;
于是发现了几个问题:
1)在代码中找到
for(int i = 0; i < Nx; i++)
{
wx[i+1] = wx[i] + hx; //массив
wht[0][i] = fn(T, i * hx); //i * hx//Исправлено.
}
它在哪里fn:
//Функция Хэвисайда - Начальное условие(Граничное условие) а начальное 0-1
public:static double fn(int T, double x)
{
if (x >= 0)
return T;
else if(x < 0)
return 0;
}
我设置的初始条件不正确
就像图表上的酒一样,在耻辱中,一般解决方案“wave”在某处可见,但其余部分是错误的,因为我在代码中错误地设置了初始条件
2)循环和数组,即:
调用了数组中不存在的元素,结果出现了可怕的数字和图表中的跳跃,但我无法更改索引,因为存在特定的公式。
for(int j = 0;j<Nt;j++)
{
for(int i = 1;i<Nx-1;i++)///Исправлено с помощью ответа пользователя Denis Protopopov(и график немного изменился)
{
wht[j+1][i] =
((wht[j + 1][i] - wht[j][i]) / ht) + a * ((wht[j][i+1] - wht[j][i]) / hx);
wht[j+1][i] = -a * (ht * (wht[j][i+1] + wht[j][i]) / hx) + (wht[j][i]);
}
}
如果我写而不是i = 0,i = 2或j = 2,那么图形的绘制将很糟糕。
所有代码:
public:static double qx0(double x)//ось пространства
{
if (x<=0)
return 0;
else
return x;
}
public:static double qt0(double t)//ось по времени
{
if (t<=0)
return 0;
else
return t;
}
public:static double fn(int T,double x)//Функция Хэвисайда - Начальное условие
{
if (x>=0)
return T;
else if(x<0)
return 0;
}
public: void drawfunc(double T)
{
double xmin = -5;
double xmax = 10;
for(double x = xmin;x<xmax;x+=0.01)
{
chart1->Series["Функция Хэвисайда"]->BorderWidth=3;
chart1->Series["Функция Хэвисайда"]->Points->AddXY(x,fn(T,x));
}
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
///-------Переменные для работы с разностными схемами
double a;//скорость переноса
double hx,ht;//шаги по пространству и времени
int Nx,Nt;//На сколько частей разбивае отрезок сетки
int T;//Входной параметр для искомой функции(Хэвисайд)
double wx[20]={0};//массив точек x
double wt[20]={0};//массив точек t
double wht[20][20]={0};// массив для разностной схемы(сетки)
//double res[20][20]={0};//результирующий массив
if(textBox1->Text!="" && textBox2->Text!="" && textBox3->Text!="" && textBox4->Text!="" && textBox5->Text!="" && textBox6->Text!="" && textBox6->Text!="")
{
///-----Ввод данных-----
a=Convert::ToDouble(textBox1->Text);
hx=Convert::ToDouble(textBox2->Text);
q=Convert::ToDouble(textBox3->Text);
ht=Convert::ToDouble(textBox4->Text);
Nx=Convert::ToInt32(textBox5->Text);
Nt=Convert::ToInt32(textBox6->Text);
T=Convert::ToInt32(textBox7->Text);
//----Построение сетки,узлов
for(int i = 0;i<Nx;i++)
{
wx[i+1]=wx[i]+hx;//массив
wht[0][i]=qx0(wx[i]);
}
for(int j = 0;j<Nt;j++) //
{
wt[j+1]=wt[j]+ht;
wht[j+1][0] = qt0(wt[j+1]);
}
///-----------------Вычисление основых формул с разностной схемой
for(int j = 0;j<Nt;j++)
{
for(int i = 1;i<Nx-1;i++)///Вывод формул wht[j+1][i]
{
wht[j+1][i]=((wht[j+1][i]-wht[j][i])/ht)+a*((wht[j][i+1]-wht[j][i])/hx);
wht[j+1][i]=-a*(ht*(wht[j][i+1] + wht[j][i])/hx) + (wht[j][i])+ht*fn(wt[j],hx);
}
}
//----Для записи в простой текстовый файл
String^ fileName = "results.txt";
StreamWriter^ sw = gcnew StreamWriter(fileName);
for(int j = 0;j<Nt;j++)
{
for(int i = 0 ;i<Nx;i++)
{
sw->Write("{0} ",wht[j][i]);
}
sw->WriteLine();
}
sw->Close();
//Тестовые функции для отображения
drawfunc(T);// Вызов функции для рисования
///---------------Построение графика
for(int j = 0;j<Nt;j++)
{
for(int i = 0;i<Nx-1;i++)
{
chart2->Series["Series2"]->BorderWidth=3;
chart2->Series["Series2"]->Points->AddXY(i,wht[j][i]);
}
}
}
else MessageBox::Show("Ошибка!Не все поля заполнены!");
}

为了回答为什么波浪不在图表上运行,您必须先处理数值方法,然后再处理 C++ 代码。数值分析理论不包括在本网站讨论的主题范围内,但简要参考可能会有用。
1.差分方案的一个小题外话
所以,我们正在寻找一个函数 u(x,t) 来解决偏微分方程的 Cauchy 问题
有初始条件
方程 (1) 称为输运方程,因为我们问题的解是
u(x,t) = f(x-at)。这是一个函数,其图形随时间向右移动,速度为a。老师教导学生不要寻找简单的方法,而是要用有限差分法来解这个方程。可以提出等式(1)的几个差分近似。我们被邀请使用其中之一。很快就会清楚,这是一个非常不幸的选择。
因此,让我们考虑一种方案,其中关于 的导数
t由差分算子 近似Dt u。该运算符具有一阶近似值。
x我们近似于差分算子的导数Dx u得到
数值分析人员很清楚这个方案在 dt 和 dx 上有一个一阶近似,并且也是绝对不稳定的。这意味着该方案以指数方式增加任何小的扰动。
所以,这个方案是绝对不稳定的,因此不满足Lax定理的条件,所以不能指望按这个方案计算出的函数收敛于原偏微分方程问题的解。
x有趣的是,如果我们根据公式计算导数然后我们得到一个稳定的方案。
2. 限定区间内的问题陈述
我们不希望在整个数值轴上寻找解决方案,而是在有限的区间内寻找解决方案
[xmin,xmax]。为了使函数f(x-at)成为我们问题的解决方案,有必要用以下边界条件补充问题。现在我们可以根据一阶近似的显式方案来编写解决问题(1-4)的方法。
三、软件实现
以下仅是方法本身的示例实现。与可视化相关的一切都是单独决定的。
第一个代码块是边界条件的定义。
下一个代码块包含一个计算解决方案并将其存储在数组中的函数。我们的函数将任务的参数作为参数 - 计算区域边界的坐标和对应保存结果的数组的引用。
在这里,实现了一个具有稳定方案的变体——差分算子
D'x4. 结果
下图为和,和的函数值
u(x,t)。a=0.5t=0t=5.0t=10.0可以看出,波浪与其说是在运行,不如说是在空间中被涂抹。
现在让我们用一个实现由 operator 定义的绝对不稳定方案的循环替换主循环
Dx。结果看起来像这样
这个结果一点也不像是向右跑的台阶。
5.结论
我希望这个例子说明在查找代码中的错误之前,有必要研究算法的属性。
既然没有人愿意处理这个问题,我就敢说出我的想法。
问题是缺少一段代码,即:
wx,wt和都未设置wht。当一个数组被声明时,内存中的一个位置被分配给它,如果在声明之后你没有为数组的元素设置值,那么当你访问它们时,你会得到那里的东西。这就是这些“可怕”含义的来源。))T??a??稍微修改的代码: