1 #include "BSprivate.h"
2 
3 /*+ BSsdo_color - Do a local IDO coloring
4 
5 	Input Parameters:
6 .   sdo_queue - the nodes to color
7 .   n_queue - the length of the sdo_queue
8 .   A - the sparse matrix
9 .   local_color - the local coloring
10 .   global_color - the colors of global nodes adjacent to each processor
11 .   local_ptr - array of pointers indicating which neighbors in
12 .               each row are local neighbors (on this processor)
13 .   global_ptr - array of pointers indicating which neighbors in
14 .                each row are global neighbors (not on this processor)
15 .   color_template - used to figure out what colors are around a node
16 .   sdo_degree - a work vector
17 .   sdo_queue_ptr - a work vector
18 .   sdo_deg_ptr - a work vector
19 .   procinfo - the usual processor info
20 
21 +*/
BSsdo_color(int * sdo_queue,int n_queue,BSspmat * A,int * local_color,int ** global_color,int * local_ptr,int * global_ptr,int * color_template,int * sdo_degree,int * sdo_queue_ptr,int * sdo_deg_ptr,BSprocinfo * procinfo)22 void BSsdo_color(int *sdo_queue, int n_queue, BSspmat *A, int *local_color,
23 		 int **global_color, int *local_ptr, int *global_ptr,
24 		 int *color_template, int *sdo_degree, int *sdo_queue_ptr,
25 		 int *sdo_deg_ptr, BSprocinfo *procinfo)
26 {
27 	BSsprow	**local_col_array;
28 	int	*row_ptr, *adj_row_ptr;
29 	BSsprow	*t_node, *adj_node;
30 	int i, j, k;
31 	int max_sdo_deg, deg, l_vtx, t_color;
32 	int adj_vertex, adj_adj_vertex;
33 	int update;
34 	int tmp_ptr, tmp_vertex;
35 	int	*in_group;
36 	int	n = A->num_rows;
37 
38 	/* Set-up */
39 	MY_MALLOC(in_group,(int *),sizeof(int)*A->num_rows,1);
40 
41 	local_col_array = A->rows;
42 
43 	/* Initialize sdo_degree to be -1 for all nodes */
44 	/* this indicates that a node is NOT in the sdo_queue */
45 	for (i=0;i<A->num_rows;i++) {
46 		in_group[i] = -1;
47 	}
48 
49 	/* Compute sdo_degrees and store as key in sdo_queue_ptr */
50 
51 	for (i=0; i<n_queue; i++) {
52 		l_vtx = sdo_queue[i];
53 		in_group[l_vtx] = 1;
54 		sdo_queue_ptr[i] = 0;
55 
56 		/* Check for global adjacent nodes and update sdo degree */
57 
58 		for (j=0; j<global_ptr[l_vtx]; j++) {
59 
60 			t_color = global_color[l_vtx][j];
61 
62 			if(color_template[t_color] != n + l_vtx) {
63 				color_template[t_color] = n + l_vtx;
64 				sdo_queue_ptr[i]++;
65 			}
66 		}
67 
68 		/* Check local nodes */
69 
70 		t_node = local_col_array[l_vtx];
71 		row_ptr = t_node->col;
72 
73 		for (j=local_ptr[l_vtx]; j<t_node->length; j++) {
74 			(*A->map->fglobal2local)
75 				(1,&(row_ptr[j]),&adj_vertex,procinfo,A->map);CHKERR(0);
76 
77 			t_color = local_color[adj_vertex];
78 			if (t_color == NO_COLOR) {
79 			}
80 			else {
81 				if(color_template[t_color] != n + l_vtx) {
82 					color_template[t_color] = n + l_vtx;
83 					sdo_queue_ptr[i]++;
84 				}
85 			}
86 		}
87 		sdo_degree[l_vtx] = sdo_queue_ptr[i];
88 	}
89 
90 	/* Sort sdo_queue by sdo_degree */
91 
92 	BSheap_sorthl1(n_queue,sdo_queue_ptr,sdo_queue); CHKERR(0);
93 
94 	/* Construct sdo_deg_ptrs for sdo_queue */
95 
96 	max_sdo_deg = sdo_queue_ptr[0];
97 	sdo_queue_ptr[0] = 0;
98 	deg = max_sdo_deg;
99 	for (i=1; i<n_queue; i++) {
100 
101 		while (sdo_queue_ptr[i] != deg) {
102 			sdo_deg_ptr[deg] = i-1;
103 			deg--;
104 		}
105 		sdo_queue_ptr[i] = 0;
106 	}
107 
108 	sdo_deg_ptr[deg] = n_queue - 1;
109 
110 	/* Construct sdo_queue_ptrs */
111 
112 	for (i=0; i<n_queue; i++) {
113 		l_vtx = sdo_queue[i];
114 		sdo_queue_ptr[l_vtx] = i;
115 	}
116 
117 	/* Main elimination loop */
118 
119 	for (i=0; i<n_queue; i++) {
120 
121 		l_vtx = sdo_queue[i];
122 
123 		t_node = local_col_array[l_vtx];
124 		row_ptr = t_node->col;
125 
126 		/* Mark colors of adjacent global vertices */
127 
128 		for (j=0; j<global_ptr[l_vtx]; j++) {
129 			t_color = global_color[l_vtx][j];
130 			color_template[t_color] = l_vtx;
131 		}
132 
133 		/* Mark colors of adjacent local vertices */
134 		for (j=local_ptr[l_vtx]; j<t_node->length; j++) {
135 			(*A->map->fglobal2local)
136 				(1,&(row_ptr[j]),&adj_vertex,procinfo,A->map);CHKERR(0);
137 			t_color = local_color[adj_vertex];
138 			if (t_color == NO_COLOR) {
139 			}
140 			else {
141 				color_template[t_color] = l_vtx;
142 			}
143 		}
144 
145 		/* Choose t_color */
146 
147 		t_color = 0;
148 		while (color_template[t_color] == l_vtx) {
149 			t_color++;
150 		}
151 
152 		/* delete vertex from queue, update deg pointers */
153 		while ((sdo_deg_ptr[max_sdo_deg] == i) && (max_sdo_deg > 0)) {
154 			max_sdo_deg--;
155 		}
156 
157 		/* Update adjacent vertices */
158 		for (j=local_ptr[l_vtx]; j<t_node->length; j++) {
159 			(*A->map->fglobal2local)
160 				(1,&(row_ptr[j]),&adj_vertex,procinfo,A->map);CHKERR(0);
161 			/* do not update chosen vertex */
162 
163 			if(l_vtx == adj_vertex) {
164 				MY_SETERRC(COLOR1_ERROR,"Adjacent to self\n");
165 			}
166 
167 			/* Update sat_degree of adjacent vertices if required */
168 
169 			else if ((in_group[adj_vertex] != -1) && (local_color[adj_vertex] == NO_COLOR)) {
170 				update = TRUE;
171 				adj_node = local_col_array[adj_vertex];
172 				adj_row_ptr = adj_node->col;
173 				k=0;
174 				while ((k<global_ptr[adj_vertex])&&(update==TRUE)) {
175 
176 					/* if tmp_color here, no need to promote */
177 
178 					if(global_color[adj_vertex][k] == t_color) {
179 						update = FALSE;
180 					}
181 					k++;
182 				}
183 				k=local_ptr[adj_vertex];
184 				while ((k<adj_node->length)&&(update==TRUE)) {
185 
186 					/* if tmp_color new, promote adj_vertex in queue */
187 
188 					(*A->map->fglobal2local) (1,&(adj_row_ptr[k]),
189 						&adj_adj_vertex,procinfo,A->map);CHKERR(0);
190 					if(local_color[adj_adj_vertex] == t_color) {
191 						update = FALSE;
192 					}
193 					k++;
194 				}
195 				if(update) {
196 					sdo_degree[adj_vertex]++;
197 
198 					/* if sdo_degree > max_sdo_deg */
199 
200 					if (sdo_degree[adj_vertex] > max_sdo_deg) {
201 						max_sdo_deg++;
202 
203 						if(max_sdo_deg != sdo_degree[adj_vertex]){
204 							MY_SETERRC(COLOR1_ERROR,"Max degree wrong\n");
205 						}
206 						sdo_deg_ptr[max_sdo_deg] = i+1;
207 					}
208 					else {
209 						sdo_deg_ptr[sdo_degree[adj_vertex]]++;
210 					}
211 
212 					/* swap positions, if required */
213 
214 					if (sdo_queue_ptr[adj_vertex] !=
215 							  sdo_deg_ptr[sdo_degree[adj_vertex]])
216 					{
217 						tmp_ptr = sdo_deg_ptr[sdo_degree[adj_vertex]];
218 						tmp_vertex = sdo_queue[tmp_ptr];
219 						sdo_queue[sdo_queue_ptr[adj_vertex]] = tmp_vertex;
220 						sdo_queue_ptr[tmp_vertex] = sdo_queue_ptr[adj_vertex];
221 						sdo_queue[tmp_ptr] = adj_vertex;
222 						sdo_queue_ptr[adj_vertex] = tmp_ptr;
223 					}
224 				}
225 				/* End if(update) */
226 			}
227 			/* End Update sdo_degree */
228 		}
229 		/* End of update adjacent vertices, mark new color */
230 
231 		local_color[l_vtx] = t_color;
232 	}
233 	/* End of main elimination loop */
234 
235 	/* Clean up sdo_queue_ptr */
236 
237 	for (i=0; i < n_queue; i++)
238 	{
239 		l_vtx = sdo_queue[i];
240 		sdo_queue_ptr[l_vtx] = 0;
241 	}
242 
243 	MY_FREE(in_group);
244 }
245 
246