1 // vim: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab:
3 // Trabajo Práctico I de Análisis Numérico I
4 // Este programa resuelve un sistema de ecuaciones lineales ralo
5 // resultante de la discretización mediante diferencias finitas
6 // de ecuaciones diferenciales.
7 // Copyright (C) 2002 Leandro Lucarella <leandro@lucarella.com.ar>
9 // Este programa es Software Libre; usted puede redistribuirlo
10 // y/o modificarlo bajo los términos de la "GNU General Public
11 // License" como lo publica la "FSF Free Software Foundation",
12 // o (a su elección) de cualquier versión posterior.
14 // Este programa es distribuido con la esperanza de que le será
15 // útil, pero SIN NINGUNA GARANTIA; incluso sin la garantía
16 // implícita por el MERCADEO o EJERCICIO DE ALGUN PROPOSITO en
17 // particular. Vea la "GNU General Public License" para más
20 // Usted debe haber recibido una copia de la "GNU General Public
21 // License" junto con este programa, si no, escriba a la "FSF
22 // Free Software Foundation, Inc.", 59 Temple Place - Suite 330,
23 // Boston, MA 02111-1307, USA.
36 typedef unsigned int Indice;
50 const Numero DEFAULT_W = 1.0,
54 // Calcula la iteración para un nodo.
55 Numero procesarNodo( Datos&, Indice );
57 // Calcula la iteración para un nodo dependiendo del tipo de nodo.
58 Numero procesarNodo( Datos&, Indice, bool, bool, bool, bool, Numero = 0 );
60 // Calcula la norma 2 de un vector.
61 Numero norma2( Numero*, Indice );
63 // Imprime un vector por la salida estándar.
64 void imprimirVector( Indice, Numero* );
66 // Imprime un vector por la salida estándar.
67 void imprimirVector( Numero*, Indice );
69 // Resuelve el sistema de ecuaciones lineales por el método S.O.R.
70 // (o Gasuss-Seidel si w=1).
71 void resolver( Datos& );
73 int main( int argc, char* argv[] ) {
75 // Se fija que tenga los argumentos necesarios para correr.
77 printf( "Faltan argumentos. Modo de uso:\n" );
78 printf( "\t%s N w RTOL TS TO TN TE\n", argv[0] );
79 printf( "Desde w en adelante son opcionales. Los valores por defecto son:\n" );
80 printf( "\tw = %f\n", DEFAULT_W );
81 printf( "\tRTOL = %f\n", DEFAULT_RTOL );
82 printf( "\tTS = TO = TN = TE = %f\n", DEFAULT_T );
86 // Se inicializan los datos.
88 D.N = Indice( atol( argv[1] ) );
90 printf( "N Debe ser un entero mayor o igual a 3\n" );
94 D.rtol = DEFAULT_RTOL;
99 // Se aloca uno más de lo necesario para usar el rango [1,n]
100 D.X = new Numero[Indice(pow(D.N-1,2))+1];
102 // Si se pasaron datos como argumento, se los va agregando.
104 case 8: D.TE = Numero( atof( argv[7] ) );
105 case 7: D.TN = Numero( atof( argv[6] ) );
106 case 6: D.TO = Numero( atof( argv[5] ) );
107 case 5: D.TS = Numero( atof( argv[4] ) );
108 case 4: D.rtol = Numero( atof( argv[3] ) );
109 case 3: D.w = Numero( atof( argv[2] ) );
120 Numero procesarNodo( Datos& D, Indice i ) {
124 // Si es el primero, es SO.
126 return procesarNodo( D, i,
127 false, false, true, true,
130 // Si es N - 1 es NO.
131 if ( i == ( N - 1 ) )
132 return procesarNodo( D, i,
133 false, true, false, true,
136 // Si es N² - 3N + 3 es SE.
137 if ( i == ( N*N - 3*N + 3 ) )
138 return procesarNodo( D, i,
139 true, false, true, false,
142 // Si es N² - 2N + 1 es NE.
143 if ( i == ( N*N - 2*N + 1 ) )
144 return procesarNodo( D, i,
145 true, true, false, false,
148 // Si pertenece al intervalo [2;N-1] es O.
149 if ( ( 1 < i ) && ( i < ( N - 1 ) ) )
150 return procesarNodo( D, i,
151 false, true, true, true,
154 // Si pertenece al intervalo [N² - 3N + 3;N² - 2N + 1] es E.
155 if ( ( ( N*N - 3*N + 3 ) < i ) && ( i < ( N*N - 2*N + 1 ) ) )
156 return procesarNodo( D, i,
157 true, true, true, false,
160 // Si i - 1 es múltiplo de N - 1 (y no es NE, SE, NO, SO) es S.
161 if ( ( ( i - 1 ) % ( N - 1 ) ) == 0 )
162 return procesarNodo( D, i,
163 true, false, true, true,
166 // Si i es múltiplo de N - 1 (y no es NE, SE, NO, SO) es N.
167 if ( ( i % ( N - 1 ) ) == 0 )
168 return procesarNodo( D, i,
169 true, true, false, true,
172 return procesarNodo( D, i, true, true, true, true );
176 Numero procesarNodo( Datos& D, Indice i,
177 bool i_n1, bool i_1, bool i1, bool in_1,
183 // Voy sumando los elementos que corresponden.
193 // Calculo el elemento i.
194 D.X[i] = ( 1 - D.w ) * D.X[i] + ( b + x ) * D.w / 4;
196 // Devuelve parte de la sumatoria para calcular la norma 2.
197 return pow( D.X[i] - Xo, 2 );
201 Numero norma2( Numero* X, Indice n ) {
205 for ( Indice i = 1; i <= n; i++ )
206 sum += pow( X[i], 2 );
212 void imprimirVector( Indice n, Numero* X ) {
214 for ( Indice i = 1; i <= n; i++ )
215 printf( "%.7e%s", X[i], ( i == n ) ? "\n" : " " );
219 void resolver( Datos& D ) {
222 n = Indice( pow( D.N - 1, 2) );
223 Numero r = D.rtol + 1,
227 // Imprime datos iniciales.
228 // Formato de salida:
229 // iteración R S <vector X>
230 // (si no se puede calcular S, se muestra 0)
231 printf( "%d %.2e 0.00000000 ", ite, r );
232 imprimirVector( n, D.X );
234 while ( r > D.rtol ) {
236 for ( Indice i = 1; i <= n; i++ )
237 Ek += procesarNodo( D, i );
239 r = Ek / norma2( D.X, n );
240 printf( "%d %.2e %.8f ", ++ite, r, Ek_1 ? ( Ek / Ek_1 ) : 0 );
241 imprimirVector( n, D.X );