1

Тема: Хімічне моделювання на С++

Доброго ранку!
Морочу собі голову вже понад 2 місяці одним питанням.
Хочу створити програму, яка б могла моделювати хімічні процеси на С++, самостійним ходом і без допомоги програміста. Тобто, програма після запуску має згенерувати кілька мільйонів моделей атомів і ці атоми мають між собою повзаємодіяти і на виході має бути каша з різних речовин. Але суть в тому, що всі ці речовини мають бути існуючими.
З мене хімік поганий, до речі. Ну і фізик теж. І програміст теж.
Вожуся вже 2 місяці. У вільний час думаю, як його зробити, але не знаю.

Тому хочу просити допомоги у тих, кому це питання може теж цікаве.

Я цю програму не знаю навіть як почати, хоч вона і проста, а тому код надавати немає ніякого сенсу.

Чисто символічно,

#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <math.h>
#include <windows.h>
using namespace std;
struct element
{
   int protons;//назва елементу залежить тільки від протонів, а від нейтронів задежить ізотоп
   string name;
   bool initb;
   int init (int p, string nm)
   {
      if(initb==true) return 1;
      protons=p;
      name=nm;
      initb=1;
   }
};
struct isotop
{
   element e;
   int neutrons;
   bool initb;
   int init (element el, int n)
   {
      if(initb==true) return 1;
      e.init(el.protons, el.name);
      neutrons=n;
      initb=1;
   }
};



class Atom
{
   private:
      element e;//оригінальний елемент
   public:
      isotop *ist;//масив похідних
      int el_ist;//кількість елементів в масиві ist
      
      int electrons;//масив електронів.

      int is_id=0;//використовуваний на даний момент ізотоп з масиву ist
      
      void gen(int el)
      {
            ist=new isotop[el];
            for (int i=0; i<el; i++) ist[i].init(e, i+1);//кількість нейтронів дорівнює кількості елементів
            
            el_ist=el;
       }
      
      void set_stable(int neutrons)//установка стабільного ізотопа
      {
           is_id=neutrons-1;
      }
      
      void init(int protons, int els)
      {
            string name;
            switch(protons)
            {
                case 1: name="H"; break;
                case 2: name="He"; break;
                case 3: name="Li"; break;
                // і так далі
            }
           e.init(protons, name);
           gen(els);
           return;
      }
      
      
      
};

Atom* atoms;

void randgen(int el)
{
   atoms=new Atom[el];
   int rand_protons;
   for (int i=0; i<el; i++) {
      rand_protons=rand()%100;
      atoms[i].init(rand_protons, 40);//40 ізотопів на кожного, з запасом
      switch(rand_protons)//вибираємо стабільні по таблиці Менделєєва
      {
        case 1: atoms[i].set_stable(1); break;
        case 2: atoms[i].set_stable(2); break;
        case 14: atoms[i].set_stable(15); break; // хоча і 14 і 15 є стабільними
        // і так далі
      }
}

void atom_connect(int source, int dest)
{
   atoms[dest].try_connect(source);//та функція, якої немає.
}      

int main()
{
   randgen(1024*1024*8);
   double i=0;
   while(true) {
        atom_connect(rand()%1024*1024*8, rand()%1024*1024*8);
        i++;
        if (i>1000*1000*1000*1000) break;
   }
   print_result();//функція, якої немає
   return 0;
}

Проблема скоріше не у С++. Я не можу зрозуміти закономірність приєднання одних атомів до інших. Як програма може спрогнозувати, що один атом не може під'єднатися до іншого? От головне питання.

2

Re: Хімічне моделювання на С++

Звісно, якщо ви взагалі не тямите в предметній області, то до написання коду вам ще далеко.

Подякували: koala, progheheh, leofun013

3

Re: Хімічне моделювання на С++

Так, перш ніж щось закодити, ви маєте зрозуміти, що саме. Комп'ютер може виконати код значно швидше, ніж ви - але не може зробити щось, чого не може зробити програміст.
Тому для початку, боюся, вам доведеться вивчити хімію і фізику. Або придумати свою власну "хімію", значно спрощену (наприклад - до рівня шкільної), і її запрограмувати. Вивчати програмування на предметі, якого ви не знаєте, у вас точно не вийде.

progheheh написав:

Як програма може спрогнозувати, що один атом не може під'єднатися до іншого?

Взагалі для цього їй треба моделювати фізику процесу - енергії електронів на різних рівнях. Звісно, ви можете спростити це до просто імовірностей (та й з моделюванням фізики без імовірностей не обійтися, процеси ж квантові); ну і прочитайте хоча б вікіпедію для початку.

Подякували: wander, progheheh, leofun013

4

Re: Хімічне моделювання на С++

progheheh написав:

не знаю навіть як почати, хоч вона і проста

Схоже ви навіть приблизно не можете оцінити складність вашої програми, що є трохи погано.
Пан koala, дав вам хорошу пораду для старту. Візьміть деяку спрощену фізично-хімічну модель для початку, також можете брати ідеальні умови для з'єднання атомів та електронів.

Звісно, тут на буквах це виглядає просто, проте навіть цю спрощену модель потрібно детально описати, щоб мати змогу довести, що елементи будуть з'єднуватися не випадково. Тобто вам все одно потрібно пройти, як мінімум шкільний курс фізики/хімії/математики.

Подякували: progheheh1

5

Re: Хімічне моделювання на С++

тут і з боку фізики усе негаразд, і з точки зору програмування ще гірше.
По-перше, що таке елемент? Є атом, що складається з протонів, нейтронів, та електронів. Є молекула, що складається з атомів. Потрібно лише створити фабрику для випікання атомів і фабрику для випікання молекул.

По-друге, слід вивчати мову, щоб їй користуватися. Слід окремо вивчати програмування, щоб не робити помилок. Для цього є книжки та відеокурси. Форуми для цього не призначені.

По-третє, не слід поспішати на усіх стадіях розробки ПЗ.  Бо потім кількість проблем зростатиме експоненціально.

як на мене масив тут взагалі не потрібний достатньо просто в циклі генерувати кілка атома і намагатись їх з'єднати хімічно. Але це довго, тому можна зробити генетичний алгоритм.


Якщо конкретно, почніть з того, які бібліотеки і нащо ви підключаєте
Почитайте про вказівники, знайдіть помилку.
Почитайте про фабрики, нащо вони.
Почитайте про атоми, бо тут найбільший хліб, тобто логіка навиворіт

Подякували: progheheh1

6

Re: Хімічне моделювання на С++

Дякую за відповіді. Розумієте, я читав і про хімічні зв'язки і про все ще раніше. Але мені от не зрозуміло, яка ключова властивість хімічного зв'язку. Ймовірність це не те. Якби

#define IS_ION 10
#define NO_ION 70
struct isotop
{
   int protons;
   int neutrons;
};
struct atom
{
   isotop i;
   int electrons;
   double id;//унікальний ідентифікатор атома в програмі
   double *ids;//унікальні ідентифікатори приєднаних елементів
   double ind_id;//кількість приєднаних елементів
   bool setid;
   int is_ion(void)
   {
       if(electrons!=i.protons) return IS_ION;
       else return NO_ION;
    }
    int set (int pr, int ne)
   {
        i.protons=pr;
        i.neutrons=ne;
    }
    int create_ion(int elect)
    {
        electrons=elect;
     }
     int set_id(double _id)//блокування повторного встановлення ід
     {
         if(setid==0)
         id=_id;
         setid=1;
     }
};
bool combine(atom a, atom b)
{
   bool ret;
   if(a.is_ion()==IS_ION)
   {
       if(a.electrons<a.i.protons)//недостача електронів
       {
            int result_a=a.i.protons-a.electrons;//різниця
            if(b.electrons>b.i.protons)//надлишок електронів
            {
                 int result_b=b.electrons-b.i.protons;
                 if (result_b==result_a) 
                 {
                      double *tmp=new double[a.ind_id];
                      for (int i=0; i<a.ind_id; i++) tmp[i]=a.ids[i];
                      a.ind_id++;
                      a.ids=new double[a.ind_id];
                      for (int i=0; i<i.ind_id-1; i++) a.ids[i]=tmp[i];
                      a.ids[a.ind_id]=b.id;

                      double *tmp2=new double[b.ind_id];
                      for (int i=0; i<b.ind_id; i++) tmp[i]=b.ids[i];
                      b.ind_id++;
                      b.ids=new double[b.ind_id];
                      for (int i=0; i<b.ind_id-1; i++) b.ids[i]=tmp[i];
                      b.ids[a.ind_id]=a.id;
                      
                      ret=1;//з'єднались
                 }
             }
        }
       if(a.electrons>a.i.protons)//надлишок електронів
       {
            int result_a=electrons-a.i.protonss;//різниця
            if(b.electrons<b.i.protons)//недостача електронів
            {
                 int result_b=b.i.protons-b.electrons;
                 if (result_b==result_a) 
                 {
                      double *tmp=new double[a.ind_id];
                      for (int i=0; i<a.ind_id; i++) tmp[i]=a.ids[i];
                      a.ind_id++;
                      a.ids=new double[a.ind_id];
                      for (int i=0; i<i.ind_id-1; i++) a.ids[i]=tmp[i];
                      a.ids[a.ind_id]=b.id;

                      double *tmp2=new double[b.ind_id];
                      for (int i=0; i<b.ind_id; i++) tmp[i]=b.ids[i];
                      b.ind_id++;
                      b.ids=new double[b.ind_id];
                      for (int i=0; i<b.ind_id-1; i++) b.ids[i]=tmp[i];
                      b.ids[a.ind_id]=a.id;
                      
                      ret=1;//з'єднались
                 }
             }
        }
    }
    return ret;
}

Треба, по-перше, виносити протони та нейтрони в окрему структуру. Вони оточені оболонкою і в хімічних процесах не взаємодіють. Тому їм місце в окремій структурі.
По-друге, кількість електронів завжди має дорівнювати кількості протонів в ядрі, інакше такий атом вважається іоном.
А значить, може реалізувати хоча б іонний зв'язок. Як я його хріново реалізував видно на коді.
Але хоч до якоїсь реалізації вже можна прикрутити якісь правила приєднання (окрім кількості електронів). Знати б, які.

З приводу цього коду, мене цікавить, як додати новий елемент в масив без видалення всього масиву і без циклу for. Бо інакше знадобиться серверний кластер розміром з дата-центр для роботи програми.

7

Re: Хімічне моделювання на С++

Читайте ще раз хімію я вже не пам'ятаю як воно працює, але то 100% є в шкільній програмі ну або той
Форум хіміків

Подякували: progheheh1

8

Re: Хімічне моделювання на С++

Я ще раз вам кажу: ви намагаєтеся одночасно розбиратися в мові (не найпростішій) і в предметній області. Це надмірне завдання.

progheheh написав:

Треба, по-перше, виносити протони та нейтрони в окрему структуру. Вони оточені оболонкою і в хімічних процесах не взаємодіють. Тому їм місце в окремій структурі.

Ні. Ви плутаєте фізичний об'єкт (який далеко не факт, що буде відповідати вашій моделі) і структури даних вашого коду. Тобто цілком можливо, що кінець-кінцем ви прийдете до такої структури; але одразу казати так - неправильно. У хімії важливі атомний номер (який відповідає кількості протонів) і атомна маса (сума протонів і нейтронів). Я не бачу, нащо вам лізти глибше, принаймні, на цьому етапі. Дві змінні замість двох структур - поки що цілком достатньо.

progheheh написав:

По-друге, кількість електронів завжди має дорівнювати кількості протонів в ядрі, інакше такий атом вважається іоном.

Так має завжди дорівнювати - чи може не дорівнювати, і тоді це іон? Ви розумієте, що програма - це, кінець-кінцем, просто точний формальний запис вашої моделі, і від формулювань залежить все?

progheheh написав:

А значить, може реалізувати хоча б іонний зв'язок.

Якщо ви вважаєте, що іонний зв'язок утворюють виключно іони, то я вас розчарую. І відправлю читати підручник. Атоми можуть ставати іонами при утворенні такого зв'язку - це прямо написано за посиланням; в рамках моделі, в принципі, можна навіть цього не відображати.

progheheh написав:

якісь правила приєднання (окрім кількості електронів).

А немає їх. Всі хімічні властивості атому визначаються енергіями електронів; а ці енергії, якщо не розглядати спеціально збуджені атоми (а ви ж явно не плануєте заглиблюватися в це), визначаються їхньою кількістю.

progheheh написав:

як додати новий елемент в масив без видалення всього масиву і без циклу for

Ніяк. Вам просто потрібен не масив.
Взагалі, якщо ви не пишете щось дуже критичне по часу (а якщо ви не знаєте навіть базових алгоритмів і бібліотечних можливостей мови, то ви взагалі не зможете нормально це написати), то використовуйте стандартну бібліотеку, у вас все одно набагато швидше не вийде. Чим вам std::vector і std::set не подобаються?

Подякували: progheheh, leofun012

9

Re: Хімічне моделювання на С++

ОК. А можна конкретику з кодом?

Я загуглив, що таке фабрики, шаблони, vector і std::set. Але я нічого не зрозумів, як це використати для моєї задачі.

Я хочу взагалі на Windows API зробити так, щоб кожен атом - це був окремий потік (thread), і щоб ці потоки обмінювалися даними. Тут все одно потрібен якийсь клас чи щось таке.

А іще я ні з підручника, ні за посиланням, так і не отримав відповіді на питання "конкретики", тобто що саме визначає, може з'єднатися один атом з іншим, чи не може?
Валентність? Але ж існують різні виключення і таке інше, значить валентність не ключова.
Кількість електронів? А яким чином?
Енергія? Яким чином?

Для мене не існує слова "вірогідність". Вірогідність - це гадання на кофейній гущі у тому випадку, коли недостатньо даних для точного прогнозу. Вірогідність може бути будь-де, але не у програмі. Бо в програмі немає тих факторів, які неможливо передбачити - всі фактори створює програміст.
Тому тут можливий тільки точний прогноз. Або true, або false. Іншого немає.

10

Re: Хімічне моделювання на С++

progheheh написав:

.

Я хочу взагалі на Windows API зробити так, щоб кожен атом - це був окремий потік (thread), і щоб ці потоки обмінювалися даними. Тут все одно потрібен якийсь клас чи щось таке.

.

Скільки у вас має бути атомів???

тобто що саме визначає, може з'єднатися один атом з іншим, чи не може?

В методі валентних зв'язків утворення хімічного зв'язку асоціюється зі спаровуванням спінів електронів, що утворюють електронні пари

Подякували: progheheh1

11 Востаннє редагувалося koala (04.03.2020 23:47:06)

Re: Хімічне моделювання на С++

Фабрики і шаблони - це хай ur_naz пояснює, він розумні слова любить, а от відповідати за них - не дуже.
std::vector<int> - це, якщо коротко, той самий int * ... = new int[...]. Але з автоматичними управлінням розміром та видаленням, і ще з купою додаткових корисних функцій. Оцей ваш жах

                     double *tmp=new double[a.ind_id];
                      for (int i=0; i<a.ind_id; i++) tmp[i]=a.ids[i];
                      a.ind_id++;
                      a.ids=new double[a.ind_id];
                      for (int i=0; i<i.ind_id-1; i++) a.ids[i]=tmp[i];
                      a.ids[a.ind_id]=b.id;

                      double *tmp2=new double[b.ind_id];
                      for (int i=0; i<b.ind_id; i++) tmp[i]=b.ids[i];
                      b.ind_id++;
                      b.ids=new double[b.ind_id];
                      for (int i=0; i<b.ind_id-1; i++) b.ids[i]=tmp[i];
                      b.ids[a.ind_id]=a.id;

на векторах буде виглядати так:

struct atom
{ ...
   std::vector<double> ids;
   ...
}
                     a.ids.push_back(b.id);//всі операції зі створенням/переміщенням, ще й оптимізовані, в push_back
                     b.ids.push_back(a.id);
//якщо знадобиться кількість елементів a.ids - це a.ids.size()

std::set - приблизно те саме, але складність пошуку менша, хоча за індексом звертатися не можна (всередині там бінарне дерево, насправді).

progheheh написав:

кожен атом - це був окремий потік

Я бачу, ви вже знайшли серверний кластер із кількістю ядер, що відповідає кількості атомів?

progheheh написав:

Для мене не існує слова "вірогідність"

Ніхто про вірогідність і не писав, писали про ймовірності. Вірогідність - це ймовірність 100%, якщо ви не в курсі. Тобто true, якщо вам так зрозуміліше. Ви, мабуть, мали на увазі навпаки - що вас цікавлять виключно вірогідні події.
Однак тоді я зовсім не розумію, що ви плануєте програмувати. Будь-яка комбінація атомів за певних умов (тиск, температура, правильно підібране лазерне опромінення) може об'єднуватися. Хімічні реакції ідуть не тому, що вони можуть іти лише в один бік, а тому, що ймовірність однієї реакції більша за ймовірність протилежної. Наприклад, натрій активно заміщує гідроґен у воді, але ж із цього не випливає, що гідроген не реагує з оксиґеном - звісно, реагує, просто натрій активніший, і кількість реакцій 2Na+2H2O-> 2NaOH + H2 буде значно перевищувати кількість реакцій H2 + 2NaOH -> 2H2O + 2Na, тим більше, що водень швидко вийде з води і ці реакції більше не відбуватимуться. Реакції, які не викликають виділення газу, осаду чи температури, спокійно можуть іти в обидва боки - наприклад, додавання Na2O в H2O призведе до утворення розчину, де плаватимуть H2O, NaOH і Na2O (а якщо точніше - купа іонів  Na+, H+ та OH-), постійно вступаючи в різні реакції і знову розпадаючися.

Ну і дуже раджу поцікавитися принципом невизначеності Гейзенберга і його наслідками для фізики. Ваші уявлення про природу і її закони застаріли років так на 100.

Подякували: progheheh, leofun012

12

Re: Хімічне моделювання на С++

А. Тепер уже зрозумів. Дякую за код. Після того, як ви дали код, я ось знайшов іще додатково сторінку
http://www.cplusplus.com/reference/vect … or/vector/
І там все детально описано із прикладом. А на лівій панелі збоку на тому сайті можна вибирати додаткову інформацію по векторах. А ось іще функція push_back
http://www.cplusplus.com/reference/vect … push_back/
На тій же лівій панелі збоку ще купа корисного. Поцікавився <array>
http://www.cplusplus.com/reference/array/array/array/
І ще багато чим поцікавився. Мені б одразу це знайти.
З гугл-пошуку посилання йде на цей самий сайт, але на сторінку типу
http://www.cplusplus.com/reference/vector/
А на цій сторінці немає нормального прикладу.
На інших сайтах теж з 2 разів не зрозумів, далі дивитися вже полінився.
Але тепер все зрозуміло.

Ось оновлений код:

using namespace std;
struct atom
{
   int n;//атомний номер
   int m;//атомна маса
   vector <double> ids;
   bool created;
   double id;

   int set(int nn, int mm)
   {
      if(!created) 
      {
             m=mm; 
             n=nn;
             created=true;
             return 0;
       }
       else return 1;
    }
};
bool combine(atom a, atom b)
{
      if (no_error(a, b)) //перевірка можливості з'єднання не реалізована поки що
      {
          a.ids.push_back(b.id);
          b.ids.push_back(a.id);
          return true;
      }
      else return false;
}

13

Re: Хімічне моделювання на С++

Щодо того, що саме я хочу моделювати.
Є, наприклад, вікно (віконна процедура). В ньому є кнопочки і текстові поля. Користувач має туди в ці поля вводити різні хімічні формули, а програма має показувати, що вийде після взаємодії двох речовин.
Може, така бібліотека уже десь є? Я поки що такої не зустрічав. Всяке є, але такого чомусь немає.
Можливо, треба тоді додавати змінні оточуючуго середовища - температури, яскравості, магнітного поля і таке інше. Але б мені ключ до з'єднання 2-х атомів при
*23 градуси Цельсія
*768 мм рт.ст.
*магнітне поле Землі
*у темній кімнаті без джерел світла.
*при земній гравітації
*і так далі
Тобто з'єднати 2 атоми за н.у.



Я поки що написав наступний код

struct molecules 
{
   atom *atoms;
   
   struct molecule
   {
       double id;
       vector <double> ids;//id атомів, що належать до даної молекули

       int add_atoms(atom *a)//додавання атомів, які будуть управлятися даною молекулою
       {
           //тут має проходити спроба під'єднання атомів з масиву a до масиву atoms
           //якщо один з атомів масиву atoms активніший за наявний в atoms, наявний видаляється
           //для економії пам'яті, структура використовує тільки ідентифікатори
           //перед кожною операцією, структура перевіряє, чи належить даний атом їй.
       }
       
   };
   
   molecule *m;

   int add_atom(atom a)
   {
      atom *tmp;
      double col_atom=sizeof(atoms)/sizeof(atom);
      tmp=new atom[col_atom];

      for (double i=0; i<col_atom; i++)
      {
         tmp[i]=atoms[i];
      }

      col_atom++;

      atoms=new atom[col_atom];

       
      for (double i=0; i<col_atom-1; i++)
      {
         atoms[i]=tmp[i];
      }

      atoms[col_atom]=a;
     
      return 0;
    }

    
    int add_molecule(void)
    {
       //не реалізована
       //має просто збільшувати масив m.
    }

};
       

Ну от власне треба знайти ту закономірність приєднання атомів від кількості електронів і програма готова.

14

Re: Хімічне моделювання на С++

progheheh написав:

*і так далі

Це нескінчений список, насправді. Наприклад, можете взяти соду і лимонну кислоту (суху), змішати їх - і реакції не буде. А коли додасте воду — почнеться, хоча вода ні з тим, ні з тим не реагує, бо для того, щоб молекули опинилися поруч, їм треба здобути мобільність у розчині. Як ви це врахуєте?
Гм. Можете навести приклад реакції, що при цих умовах не іде? Інертні гази, добре, з ними зрозуміло. А що ще, на вашу думку, не має реагувати? Солі з солями при правильній комбінації? Для того, щоб це в загальному вигляді зробити, треба енергії електронів розраховувати; а без такої комбінації шкільна хімія послуговується таблицями, які склали розумні хіміки до цього.

Подякували: progheheh1