Click here to Skip to main content
16,017,151 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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 the dimensions of the grid
#define MAX_X 2
#define MAX_Y 2
//define the partial pressure of CO
#define XNO 0.300000
//define the probability that NO can disociate
#define RNO 0.500000

//define the states of a cell in grid
typedef enum  { S_EMPTY, NO_OCCUPIED, N_OCCUPIED, O_OCCUPIED, S_NONE } gstate;

// help generate random coordinate of the grid
int gridrnd(int max)
{
	return (rand() % max);
}


// generates random coordinates of the grid
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;
		}
	}
}

//Function that locates the four nearest neighbors of the chosen site, considering periodic boundary conditions
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;
	}
}

	//Function that prints individually the "right" neighbor of the chosen site
	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));
	
	// Initialize grid to be S_EMPTY
	grid_init(grid);

	while (availcells) // repeat till the grid is full
	{
		//LOCATE AN ENTRY OF THE MATRIX RANDOMLY
		generate_coords(&y, &x);
		rounds++;

		//EVALUATE THE CHOOSEN SITE
		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){
				//if r1 is less than XNO we choose NO. Now let's see if it can be splitted or if it remains in its molecular form
				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){
				 	//if r2 is less than RNO, NO can be splitted if its right nearest neighbor is also empty
					printf("r2 = %f IS LESS THAN RNO = %f, (NO) WILL BE SPLITTED IF I FIND ANOTHER EMPTY NEAREST NEIGHBOR\n\n",r2,RNO);
					
					//let's find its right nearest neighbor
					rightneighbor(x,y,grid);
					
					//Is it empty?
					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{//I the right neighbor is not empty
						printf("The right neighbor isn't empty, NO can't disociate and the trial ends. Please, start again\n\n");
					}
					
				}else{
					//if r2 is greater than RNO, NO remain in its molecular form
					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--;
					
					//Let's check its right nearest neighbor. If there is a N, the molecule N2 will be formed, leaving a site with O and one site free
					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{
				//if r1 is less than XNO we choose N to be trapped
				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--;
				
				//Let's see if on the right neighbor there is an N or an NO, so that N2 can be created 
				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
Posted
Updated 3-Feb-23 8:06am
v6

You have several lines that look like
C
rightneighbor(x, y, grid) == O_OCCUPIED;

With warnings turned on I get warnings about computed values not being used for these lines. Remember that == is an equality test, not an assignment. If you did want to do an assignment to a rightneigbor you probably want a function like
C
set_rightneigbor(gstate state, int x, int y, gstate grid[MAX_X][MAX_Y]);
 
Share this answer
 
Comments
yuike 3-Feb-23 12:57pm    
Thanks for responding. I have a question: in the definition of the function do I need to write it as
gstate set_rightneigbor(gstate state, int x, int y, gstate grid[MAX_X][MAX_Y]);
?
k5054 3-Feb-23 13:21pm    
There's a few options for the return value. It could be void, if there is no possibility for set_rightneigbor() to fail. If there is a possible failure mode for set_rightneigbor() you might return an int with 0 meaning success and other values indicating the failure type. Alternatively, you could return a gstate, which might be the previous value of the rightneighbor. This might be useful if you need to know what that value was before it was changed.
yuike 3-Feb-23 20:13pm    
Thank you very much for your advice! I think I got it :)
As k5054 has already written, comparisons were used instead of assignments. Additionally, the value of the right neighbor was copied before. This does not seem to make sense, does it?
C
grid[y][x] = grid[get_limited_coord(y, MAX_Y)][get_limited_coord(x+1, MAX_X)];


// edit:
If I see it correctly you want to check if the right neighbor is unoccupied and then occupy both elements. In my opinion this should look like this.
C++
case S_EMPTY: {
	printf("IT'S S_EMPTY, LET'S FILL IT WITH A MOLECULE\n\n");

	//let's find its right nearest neighbor
	gstate* rnb = rightneighbor(x, y, grid);

	//Is it empty?
	if (*rnb == S_EMPTY) {
		grid[y][x] = N_OCCUPIED;
		*rnb = O_OCCUPIED;
		availcells -= 2;
	}
}
break;
 
Share this answer
 
v2
Comments
yuike 3-Feb-23 19:40pm    
Thank you, I tried with a shorter code (I don't include all the interactions between molecules mentioned above yet). I think it's fixed...Still checking

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900