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
20 #include "definitions.h"
23 extern int width, height;
25 extern unsigned char **oddity;
26 extern int dielectrics_to_consider_just_now;
30 #include "exit_codes.h"
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 */
36 void update_voltage_array(int nmax, int imin, int imax, int jmin, int jmax, double **V_from, double **V_to)
39 unsigned char oddity_value;
40 double Va, Vb, Vl, Vr, ERa, ERb, ERl, ERr;
43 if (dielectrics_to_consider_just_now==1)
47 for(n=0; n < nmax; ++n)
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];
53 if( oddity_value == CONDUCTOR_ZERO_V ){
57 else if( oddity_value == CONDUCTOR_PLUS_ONE_V ){
61 else if( oddity_value == CONDUCTOR_MINUS_ONE_V ){
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];
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];
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];
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];
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];
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];
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];
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];
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) ) {
112 Vnew=(Va+Vb+Vl+Vr)/4.0;
113 V_to[i][j]=g*Vnew+(1-g)*V_from[i][j];
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.
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
132 else if( oddity_value == METAL_ABOVE ){
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];
142 else if( oddity_value == METAL_BELOW ){
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];
152 else if( oddity_value == METAL_LEFT ){
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];
162 else if( oddity_value == METAL_RIGHT ){
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];
172 else if( oddity_value == METAL_ABOVE_AND_RIGHT ){
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];
182 else if( oddity_value == METAL_ABOVE_AND_LEFT ){
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];
192 else if( oddity_value == METAL_BELOW_AND_LEFT ){
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];
202 else if( oddity_value == METAL_BELOW_AND_RIGHT ){
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];
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. */
220 else if(dielectrics_to_consider_just_now > 1){
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];
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 */
242 } /* end of j loop */