Imported Upstream version 4.6.0
[debian/atlc] / src / non_gui / update_voltage_array.c
1 /*
2 The code below for calculating the voltage at a point i,j, given the
3 voltages and permittivities at the four adjacent points (i,j+1),
4 (i,j-1), (i-1,j), and (i+1,j), although I am not convinced it is 
5 100% correct in the case of mulitple dielectrics, the errors are 
6 still very small. 
7 */
8
9
10 #include "config.h"
11
12 #ifdef HAVE_STDLIB_H
13 #include <stdlib.h>
14 #endif 
15
16 #ifdef HAVE_STDIO_H
17 #include <stdio.h>
18 #endif 
19
20 #include "definitions.h"
21
22
23 extern int width, height;
24 extern double **Er;
25 extern unsigned char  **oddity;
26 extern int dielectrics_to_consider_just_now;
27 extern double r; 
28 extern int coupler;
29
30 #include "exit_codes.h"
31
32 /* The following function updates the voltage on the matrix V_to given data about the 
33 oddity of the location i,j and the voltages in the matrix V_from. It does this for n interations
34 between rows jmin and jmax inclusive and between columns imain and imax inclusive */
35
36 void update_voltage_array(int nmax, int imin, int imax, int jmin, int jmax, double **V_from, double **V_to)
37 {
38   int k, i, j, n;  
39   unsigned char oddity_value;
40   double Va, Vb, Vl, Vr, ERa, ERb, ERl, ERr;
41   double Vnew, g;
42
43   if (dielectrics_to_consider_just_now==1)
44     g=r;
45   else 
46     g=1; 
47   for(n=0; n  < nmax; ++n)
48     for(k=0; k < 4; ++k)
49       for (i = k&1 ? imax : imin;   k&1 ? i >=imin : i <= imax ;  k&1 ? i-- : i++)
50         for (j = (k==0 || k ==3) ? jmin : jmax; (k ==0 || k == 3)  ? j <= jmax : j >= jmin ; (k == 0 || k ==3) ?  j++ : j--){
51           oddity_value=oddity[i][j];
52
53           if( oddity_value == CONDUCTOR_ZERO_V ){  
54             V_to[i][j]=0.0;
55           }
56
57           else if( oddity_value == CONDUCTOR_PLUS_ONE_V ){  
58             V_to[i][j]=1.0;
59           }
60
61           else if( oddity_value == CONDUCTOR_MINUS_ONE_V ){  
62             V_to[i][j]=-1.0;
63           }
64
65           else if( oddity_value == TOP_LEFT_CORNER ) {  /* top left */
66             Vnew=0.5*(V_from[1][0]+V_from[0][1]);               
67             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
68           }
69           else if( oddity_value == TOP_RIGHT_CORNER ) {
70             Vnew=0.5*(V_from[width-2][0]+V_from[width-1][1]);         /* top right */
71             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
72           }
73
74           else if(oddity_value == BOTTOM_LEFT_CORNER) {
75             Vnew=0.5*(V_from[0][height-2]+V_from[1][height-1]);       /* bottom left */
76             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
77           }
78
79           else if( oddity_value == BOTTOM_RIGHT_CORNER) {   
80             Vnew=0.5*(V_from[width-2][height-1]+V_from[width-1][height-2]); /* bottom right */
81             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
82           }
83
84           /* Now the sides */
85
86           else if( oddity_value == ORDINARY_POINT_LEFT_EDGE ){  /* left hand side  */
87             Vnew=0.25*(V_from[0][j-1]+V_from[0][j+1] + 2*V_from[1][j]);
88             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
89           }
90
91           else if( oddity_value == ORDINARY_POINT_RIGHT_EDGE){   /* right hand side */
92             Vnew=0.25*(V_from[width-1][j+1]+V_from[width-1][j-1]+2*V_from[width-2][j]);
93             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
94           }
95         
96           else if( oddity_value == ORDINARY_POINT_TOP_EDGE ){ /* top row */ 
97             Vnew=0.25*(V_from[i-1][0]+V_from[i+1][0]+2*V_from[i][1]);
98             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
99           }
100
101           else if( oddity_value == ORDINARY_POINT_BOTTOM_EDGE ){   /* bottom row */ 
102             Vnew=0.25*(V_from[i-1][height-1]+V_from[i+1][height-1]+2*V_from[i][height-2]);
103             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
104           }
105
106           else if ( oddity_value == ORDINARY_INTERIOR_POINT || (oddity_value>=DIFFERENT_DIELECTRIC_ABOVE_AND_RIGHT && oddity_value < UNDEFINED_ODDITY && dielectrics_to_consider_just_now == 1) ) {
107             Va=V_from[i][j-1]; 
108             Vb=V_from[i][j+1];
109             Vl=V_from[i-1][j];
110             Vr=V_from[i+1][j];
111
112             Vnew=(Va+Vb+Vl+Vr)/4.0;
113             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
114           }
115
116           /* I'm not sure the following equations, which compute the voltage  
117           where there is a metal around are okay. One line of thought would 
118           say that the same equations as normal  i.e.
119           v_new=(v(i+1,j_+v(i-1,j)+v(i,j-1)+v(i,j+1))/4 should be used
120           but then since the electric field across the metal surface is zero,
121           the equation that was used to derrive  that equation is not valid.
122
123           Another thought of mine is that voltage near a metal will be more affected
124           by the metal than the dielectric, since the nearest part of the metal is at
125           at the same voltage as the node, whereas for a dielectric is less so. Hence
126           the following seems a sensible solution. Since the metal will have twice 
127           the effect of a dielectric, the voltage at i,j should be weighted such
128           that its effect is more strongly affected by the metal. This seems to 
129           produce reasonably accurate results, but whether this is chance or not
130           I don't know. */
131
132           else if( oddity_value == METAL_ABOVE ){  
133             Va=V_from[i][j-1]; 
134             Vb=V_from[i][j+1];
135             Vl=V_from[i-1][j];
136             Vr=V_from[i+1][j];
137
138             Vnew=0.25*(4*Va/3+2*Vb/3+Vl+Vr);
139             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
140           }
141
142           else if( oddity_value == METAL_BELOW ){   
143             Va=V_from[i][j-1]; 
144             Vb=V_from[i][j+1];
145             Vl=V_from[i-1][j];
146             Vr=V_from[i+1][j];
147
148             Vnew=0.25*(4*Vb/3+2*Va/3+Vl+Vr);
149             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
150           }
151
152           else if( oddity_value == METAL_LEFT ){   
153             Va=V_from[i][j-1]; 
154             Vb=V_from[i][j+1];
155             Vl=V_from[i-1][j];
156             Vr=V_from[i+1][j];
157
158             Vnew=0.25*(4*Vl/3+2*Vr/3+Va+Vb);
159             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
160           }
161
162           else if( oddity_value == METAL_RIGHT ){   
163             Va=V_from[i][j-1]; 
164             Vb=V_from[i][j+1];
165             Vl=V_from[i-1][j];
166             Vr=V_from[i+1][j];
167
168             Vnew=0.25*(4*Vr/3+2*Vl/3+Va+Vb);
169             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
170           }
171
172           else if( oddity_value == METAL_ABOVE_AND_RIGHT ){   
173             Va=V_from[i][j-1]; 
174             Vb=V_from[i][j+1];
175             Vl=V_from[i-1][j];
176             Vr=V_from[i+1][j];
177
178             Vnew=0.25*(4*Vr/3+4*Va/3 +2*Vl/3 + 2*Vb/3);
179             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
180           }
181
182           else if( oddity_value == METAL_ABOVE_AND_LEFT ){   
183             Va=V_from[i][j-1]; 
184             Vb=V_from[i][j+1];
185             Vl=V_from[i-1][j];
186             Vr=V_from[i+1][j];
187
188             Vnew=0.25*(4*Vl/3+4*Va/3+2*Vr/3+2*Vb/3);
189             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
190           }
191
192           else if( oddity_value == METAL_BELOW_AND_LEFT ){   
193             Va=V_from[i][j-1]; 
194             Vb=V_from[i][j+1];
195             Vl=V_from[i-1][j];
196             Vr=V_from[i+1][j];
197
198             Vnew=0.25*(4*Vl/3+4*Vb/3+2*Vr/3+2*Va/3);
199             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
200           }
201
202           else if( oddity_value == METAL_BELOW_AND_RIGHT ){   
203             Va=V_from[i][j-1]; 
204             Vb=V_from[i][j+1];
205             Vl=V_from[i-1][j];
206             Vr=V_from[i+1][j];
207
208             Vnew=0.25*(4*Vb/3+4*Vr/3+2*Va/3+2*Vl/3);
209             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
210           }
211
212           /* Again, when there is a change of permittivity, my equations may
213           (probably are wrong). My logic is that if there's and RF field,
214           the impedance is inversly proportional to Er. So if the material
215           above a node is of a higher permittivity, then the 
216           voltage will be closer to that of the node above, becuase of this.
217           The same applies for other directions of change in Er. */
218
219
220           else if(dielectrics_to_consider_just_now > 1){
221
222             Va=V_from[i][j-1]; 
223             Vb=V_from[i][j+1];
224             Vl=V_from[i-1][j];
225             Vr=V_from[i+1][j];
226
227             ERa=Er[i][j-1]; 
228             ERb=Er[i][j+1];
229             ERl=Er[i-1][j];
230             ERr=Er[i+1][j];
231
232             Vnew=(Va * ERa + Vb * ERb + Vl * ERl + Vr * ERr)/(ERa + ERb + ERl + ERr);
233             V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
234
235           }
236           else if ( (dielectrics_to_consider_just_now == 1 && oddity_value == UNDEFINED_ODDITY) || (dielectrics_to_consider_just_now > 1)) {
237             fprintf(stderr,"Internal error in update_voltage_array.c\n");
238             fprintf(stderr,"i=%d j=%d oddity[%d][%d]=%d\n",i,j,i,j,oddity[i][j]);
239             exit(INTERNAL_ERROR);
240           } /* end if if an internal error */
241
242         } /* end of j loop */
243