I'm working in a simulation of a surface that traps multiple molecules which make some interactions between them. This code is based in another made by @merano99
here.
The steps this code follows are the following:
1) I start with a completely empty surface.
2) I select at random an "site" of the surface, given by its random coordinates x and y.
3) If such a selected site, I continue to the step 4). Otherwise, I select at random another site again
4) The molecules that I would like to trap are N (nitrogen) and NO (nitric oxide). The NO could be possibly split into N and O (O is the label I chose for oxygen). To do those choices, I defined two random numbers (r1 and r2) that will help me to decide which one will be trapped.
5) There are also defined the numbers XNO (probability that NO is chosen) and RNO (probability that NO splits itself into N and O).
6) If r1 is less or equal than XNO, I choose NO to be trapped. Otherwise, I choose N.
7) If I have chosen NO and additionally r2 is less or equal than RNO, NO can be split into N and O (only if I find a nearest neighbor empty. In that case N and O are trapped in two different sites). Otherwise, it remains in its molecular form (said NO).
8) I explore the right nearest neighbor of the sites where the particles were chosen. This "right nearest neighbor" is the neighbor located at right of the chosen site. To do so, I defined the function
rightneighbor(int x, int y, gstate grid[MAX_X][MAX_Y])
I also considered periodic boundary conditions by defining the function
get_limited_coord(int coord, int coord_max)
just in case the chosen site is located at a border of the surface.
9) Well, if the right neighbor of a trapped N is occupied with another N, it will be created N2 and this reaction will left 2 sites available.
10) If the right neighbor of the trapped N is filled by an NO, it will be generated N2, but O will remain trapped and the interaction will leave 1 available site.
11) If the right site with the NO molecule is occupied by N, also, it will be generated N2, but O will remain trapped and the interaction will leave 1 available site.
What I have tried:
The code I have so far is
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_X 2
#define MAX_Y 2
#define XNO 0.300000
#define RNO 0.500000
typedef enum { S_EMPTY, NO_OCCUPIED, N_OCCUPIED, O_OCCUPIED, S_NONE } gstate;
int gridrnd(int max)
{
return (rand() % max);
}
int generate_coords(int* y, int* x )
{
if (!x || !y)
return 1;
*x = gridrnd(MAX_X);
*y = gridrnd(MAX_Y);
printf("(%d,%d)\n\n", *y, *x);
return 0;
}
void grid_init(gstate grid[MAX_Y][MAX_X])
{
for (int y = 0; y < MAX_Y; y++) {
for (int x = 0; x < MAX_X; x++) {
grid[y][x] = S_EMPTY;
}
}
}
int get_limited_coord(int coord, int coord_max){
if (coord >= 0 && coord < coord_max) {
return coord;
} else if (coord >= coord_max) {
return coord - coord_max;
} else {
return coord + coord_max;
}
}
gstate rightneighbor(int x, int y, gstate grid[MAX_X][MAX_Y]){
grid [y][x] = grid[get_limited_coord(y, MAX_Y)][get_limited_coord(x+1, MAX_X)];
return grid[y][x];
}
int main()
{
int x = 0, y = 0;
gstate grid[MAX_Y][MAX_X];
int availcells = MAX_X * MAX_Y;
int rounds = 0;
float r1, r2;
srand((unsigned)time(0));
grid_init(grid);
while (availcells)
{
generate_coords(&y, &x);
rounds++;
switch (grid[y][x])
{
case S_EMPTY:
printf("IT'S S_EMPTY, LET'S FILL IT WITH A MOLECULE. FIRST LET'S GENERATE A RANDOM NUMBER TO DECIDE WHICH ONE WILL BE TRAPPED\n\n");
r1 = rand()/(float)RAND_MAX;
if(r1 < XNO || r1 == XNO){
printf("r1 = %f IS LESS THAN XNO = %f, LET'S SEE IF (NO) CAN SPLIT\n\n",r1,XNO);
r2 = rand()/(float)RAND_MAX;
if(r2 < RNO || r2 == RNO){
printf("r2 = %f IS LESS THAN RNO = %f, (NO) WILL BE SPLITTED IF I FIND ANOTHER EMPTY NEAREST NEIGHBOR\n\n",r2,RNO);
rightneighbor(x,y,grid);
if( rightneighbor(x,y,grid) == S_EMPTY ){
grid[y][x] = N_OCCUPIED;
rightneighbor(x,y,grid) == O_OCCUPIED;
availcells = availcells - 2;
printf("THE RIGHT NEIGHBOR IS EMPTY, (NO) IS SPLITTED INTO (N) AND (O)\n\n");
}else{
printf("The right neighbor isn't empty, NO can't disociate and the trial ends. Please, start again\n\n");
}
}else{
printf("r2 = %f IS GREATER THAN RNO = %f, THE (NO) IS LEFT IN ITS MOLECULAR FORM\n\n",r2,RNO);
grid[y][x] = NO_OCCUPIED;
availcells--;
if( rightneighbor(x,y,grid) == N_OCCUPIED ){
printf("IT'S PRODUCED N2!\n\n");
grid[y][x] = O_OCCUPIED;
rightneighbor(x,y,grid) == S_EMPTY;
availcells++;
}else{
printf("There is no an N the right neighbor. N2 isn't produced. Start again\n\n");
}
}
}else{
printf("r1 = %f IS GREATER THAN XNO = %f, LET'S FILL IT WITH AN (N) MOLECULE\n\n",r1,XNO);
grid[y][x] = N_OCCUPIED;
availcells--;
if(rightneighbor(x,y,grid) == N_OCCUPIED ){
printf("It is formed N2\n\n");
grid[y][x] = S_EMPTY;
rightneighbor(x,y,grid) == S_EMPTY;
availcells = availcells + 2;
}else if(rightneighbor(x,y,grid) == NO_OCCUPIED){
printf("It is formed N2 and an O remains trapped\n\n");
grid[y][x] = S_EMPTY;
rightneighbor(x,y,grid) == O_OCCUPIED;
availcells++;
}else{
printf("There aren't N or NO on the right neighbor. N2 is not created. Start again\n\n");
}
}
break;
case NO_OCCUPIED:
printf("IT'S NO_OCCUPIED. PLEASE, GENERATE ANOTHER SITE ON THE SURFACE\n\n");
break;
case N_OCCUPIED:
printf("IT'S N_OCCUPIED. PLEASE, GENERATE ANOTHER SITE ON THE SURFACE\n\n");
break;
case O_OCCUPIED:
printf("IT'S O_OCCUPIED. PLEASE, GENERATE ANOTHER SITE ON THE SURFACE\n\n");
break;
}
}
printf("Needed %d rounds to fill complete grid\n", rounds);
return 0;
}
But, when it selects a site an fills a site with N and another with O, it doesn't remember that such sites were filled already by those, if I attempt to trap another molecule. To explain myself better, the following is the result I obtain after the compilation:
(0,0)
IT'S S_EMPTY, LET'S FILL IT WITH A MOLECULE. FIRST LET'S GENERATE A RANDOM NUMBER TO DECIDE WHICH ONE WILL BE TRAPPED
r1 = 0.053598 IS LESS THAN XNO = 0.300000, LET'S SEE IF (NO) CAN SPLIT
r2 = 0.473955 IS LESS THAN RNO = 0.500000, (NO) WILL BE SPLITTED IF I FIND ANOTHER EMPTY NEAREST NEIGHBOR
THE RIGHT NEIGHBOR IS EMPTY, (NO) IS SPLITTED INTO (N) AND (O)
(0,0)
IT'S S_EMPTY, LET'S FILL IT WITH A MOLECULE. FIRST LET'S GENERATE A RANDOM NUMBER TO DECIDE WHICH ONE WILL BE TRAPPED
r1 = 0.335047 IS GREATER THAN XNO = 0.300000, LET'S FILL IT WITH AN (N) MOLECULE
There aren't N or NO on the right neighbor. N2 is not created. Start again
(0,1)
IT'S S_EMPTY, LET'S FILL IT WITH A MOLECULE. FIRST LET'S GENERATE A RANDOM NUMBER TO DECIDE WHICH ONE WILL BE TRAPPED
r1 = 0.580490 IS GREATER THAN XNO = 0.300000, LET'S FILL IT WITH AN (N) MOLECULE
There aren't N or NO on the right neighbor. N2 is not created. Start again
Needed 3 rounds to fill complete grid
I put all those "printf" to verify if the code is working as expected, but it doesn't. Thank you in advance