Есть такая задачка:
В сосуде с идеальным газом, находящимся в равновесном состоянии, помещена большая частица.
Под действием соударений с молекулами она начинает броуновское движение.
Можно менять форму сосуда, форму размер и массу частицы.
/*Следующий абзац можно пропустить, если вопрос непонятен тогда советую прочитать*/
Я хочу сделать так:
Создать класс Частица, который будет содержать номер,координаты частицы(2-х или 3-х мерная модель), направление движения (это тоже координаты куда частица переместится,проще куда направлена скорость) и скорость.
Методы: графическое отображение частицы, моделирование столкновения с другой частицей(соответственно меняется скорость, направление движения) и перемещение(изменение начальной координаты ), еще создать класс Броуновская Частица(БЧ), наследующий от класса Частица, в нем поменяются только координаты, это будет массив содержащий координаты оболочки частицы. И еще мне нужен массив для координат сосуда(молекулы и БЧ с ним сталкиваются).
/*Вопрос*/
В итоге у меня есть координаты молекул, частицы и сосуда. Вопрос в том, что когда я буду моделировать перемещение молекулы или частицы я должен буду перебирать координаты всех молекул для того чтобы узнать столкнется она с кем нибудь или нет, а это грустно и долго...
/*Как можно решить*/
И подходящего алгоритма на ум не приходит, можно конечно разделить сосуд на части и соответственно все молекулы по группам,находящимся в той или иной части. Т е взять самые крайние координаты сосуда(например х1 и х2), также для у (у1 и у2), и наложить своеобразную сетку.
Тогда в класс надо будет добавить номер ячейки в котором находить молекула .Теперь при перемещении мне достаточно проверять на совпадение координат только те молекулы которые находятся с моей в одной ячейке, и еще проверять ячейки окружающие мою(тк молекула может перелететь из одной ячейки в другую),причем перемещение(т е один "шаг ") будет не больше чем размер ячейки . Вот так можно решить, вроде понятно обьяснил.
Может кто-нибудь предложит другой алгоритм, лучше чем мой? Буду благодарен.
Напрягаем мозги
Алгоритм не предложу. Посоветую физику почитать...
Фейнмановские лекции например...
Фейнмановские лекции например...
задача очень интересна, неплохо учесть в решении этой задачи силы вязкости(не столкновения считать а молекулярное взаимодействие).
Вопрос: сколько времини (приблизительно) заемет моделирование такого движения на ПК?
Если есть полезная информация по теме или ссылки скинте на мыло, зарание благодарен.
Вопрос: сколько времини (приблизительно) заемет моделирование такого движения на ПК?
Если есть полезная информация по теме или ссылки скинте на мыло, зарание благодарен.
"направление движения (это тоже координаты куда частица переместится,проще куда направлена скорость) и скорость" можно заменить проекцией вектора скорости на оси x,y и z.
Учитывается только одна сила, сила возникающая при столкновении двух частиц.
Большую частицу сделать не из кучи маленьких, а виде одной с массой и большим радиусом. У маленьких частиц впрочем тоже должна быть масса и радиус.
С сосудом посложнее может быть его форму задавать в виде аглебраической формулы? Можно оставить в виде частиц.
Чтобы не перебирать каждую частицу, это ты хорошо придумал, разбить пространство на кубы. У каждого куба список частиц. И проверять взаимодействия между частицами только в выбраном кубе, хотя нет, с прилежащими кубами тоже нужно делать проверку. Когда частица вылетает из куба, исключать её из списка куба, от куда частица вылетает, и включить её в список куба куда частица влетает.
Плохо то, что будет динамическая память сильно мачалиться, когда будет добавление и удаление из списка. Может для каждого куба выделить динамический массив, и сделать эмуляцию связанного списка. Ссылки не виде указателей, а в виде индексных ссылок. Удалять частицы просто менять ссылки,
A.n = A[A.n].n (где А - массив, n - индексная ссылка, удаляется i-ый элемент)
а добавлять всегда в конец массива. Периодически производить упаковку массива.
В общем на object pascal я это вижу вот так.
TParticle = class
P, V: TVector; // координаты и скорость
M: Real; // масса
R: Real; // радиус
I, J, K: Integer; // координаты кубов
end;
// метод определяет положение частицы относительно сосуда
procedure GetVesslN(P: TVector; var V: TVector; var S: Integer); // P - координата частицы, V вектор к ближайщей точке стенки
//сосуда, если S < 0 то частица погрузилась в стенку сосуда
TCub = array of record
P: TParticle;
N: Integer; // сылка на следующую частицу.
end;
TWorld = class
dT: Real; // шаг интегрирования
Ps: array of TParticle;
Cubs: array [0..MaxC - 1, 0..MaxC - 1, 0..MaxC - 1] of TCub;
procedure Pack; // упаковка массива
procedure Step; // осуществляет движение всех частиц
procedure StepP(P: TParticle); // осуществляет движение одной частицы
procedure CheckCub(P: TParticle); // осуществляем перенос частицы из одного куба в другой, если надо
end;
implementation
procedure TWorld.Step;
var
I: Integer;
begin
for I := 0 to High(Ps) do
StepP(Ps);
// если прошло досточно много времени то производим упаковку массива вызовом метода Pack
end;
procedure TWorld.StepP(P: TParticle);
var
I, J, K: Integer;
begin
for I := Max(0, P.I - 1) to Min(MaxC - 1, P.I + 1) do
for J := Max(0, P.J - 1) to Min(MaxC - 1, P.J + 1) do
for K := Max(0, P.K - 1) to Min(MaxC - 1, P.K + 1) do
begin
// осуществляем взаимодействие с частицами
end;
// осуществляем взаимодействие со стеной сосуда
CheckCub(P);
end;
Ну, вот что-то типа того.
Учитывается только одна сила, сила возникающая при столкновении двух частиц.
Большую частицу сделать не из кучи маленьких, а виде одной с массой и большим радиусом. У маленьких частиц впрочем тоже должна быть масса и радиус.
С сосудом посложнее может быть его форму задавать в виде аглебраической формулы? Можно оставить в виде частиц.
Чтобы не перебирать каждую частицу, это ты хорошо придумал, разбить пространство на кубы. У каждого куба список частиц. И проверять взаимодействия между частицами только в выбраном кубе, хотя нет, с прилежащими кубами тоже нужно делать проверку. Когда частица вылетает из куба, исключать её из списка куба, от куда частица вылетает, и включить её в список куба куда частица влетает.
Плохо то, что будет динамическая память сильно мачалиться, когда будет добавление и удаление из списка. Может для каждого куба выделить динамический массив, и сделать эмуляцию связанного списка. Ссылки не виде указателей, а в виде индексных ссылок. Удалять частицы просто менять ссылки,
A.n = A[A.n].n (где А - массив, n - индексная ссылка, удаляется i-ый элемент)
а добавлять всегда в конец массива. Периодически производить упаковку массива.
В общем на object pascal я это вижу вот так.
TParticle = class
P, V: TVector; // координаты и скорость
M: Real; // масса
R: Real; // радиус
I, J, K: Integer; // координаты кубов
end;
// метод определяет положение частицы относительно сосуда
procedure GetVesslN(P: TVector; var V: TVector; var S: Integer); // P - координата частицы, V вектор к ближайщей точке стенки
//сосуда, если S < 0 то частица погрузилась в стенку сосуда
TCub = array of record
P: TParticle;
N: Integer; // сылка на следующую частицу.
end;
TWorld = class
dT: Real; // шаг интегрирования
Ps: array of TParticle;
Cubs: array [0..MaxC - 1, 0..MaxC - 1, 0..MaxC - 1] of TCub;
procedure Pack; // упаковка массива
procedure Step; // осуществляет движение всех частиц
procedure StepP(P: TParticle); // осуществляет движение одной частицы
procedure CheckCub(P: TParticle); // осуществляем перенос частицы из одного куба в другой, если надо
end;
implementation
procedure TWorld.Step;
var
I: Integer;
begin
for I := 0 to High(Ps) do
StepP(Ps);
// если прошло досточно много времени то производим упаковку массива вызовом метода Pack
end;
procedure TWorld.StepP(P: TParticle);
var
I, J, K: Integer;
begin
for I := Max(0, P.I - 1) to Min(MaxC - 1, P.I + 1) do
for J := Max(0, P.J - 1) to Min(MaxC - 1, P.J + 1) do
for K := Max(0, P.K - 1) to Min(MaxC - 1, P.K + 1) do
begin
// осуществляем взаимодействие с частицами
end;
// осуществляем взаимодействие со стеной сосуда
CheckCub(P);
end;
Ну, вот что-то типа того.