Documentos de Académico
Documentos de Profesional
Documentos de Cultura
MODO
PROGRAMACIÓN
El uso del Modo Consola es muy útil para realizar cálculos de baja complejidad y que no se repetirán
nuevamente. En la realidad este tipo de cálculos constituyen la minoría de los casos, ya que en la gran mayoría
de las veces, seguramente será necesario repetir la secuencia de cálculos o los mismos son de tal grado de
complejidad, que justifican una resolución minuciosa y documentada.
El Modo Programación permite escribir funciones específicas de cálculo y almacenarlas en archivos, de manera
tal de poder utilizarlas todas las veces que sea necesario, sin tener que escribir las expresiones matemáticas que
conforman los cálculos ingenieriles una y otra vez.
La esencia del Modo Programación es la posibilidad de crear funciones adaptadas a las necesidades de cálculo
del ingeniero, y este es el punto en donde se centrará la discusión en este apunte.
FUNCIONES
Aspectos Generales
En un curso de Análisis Matemático se aprende que una función, en su caso más sencillo, es una relación con
ciertas restricciones, que se establece entre dos conjuntos numéricos, y simbólicamente se representa como
𝑦 = 𝑓(𝑥), donde x es la variable independiente e y es la dependiente. También se puede decir que x es un dato
de entrada de la función, mientras que y es el dato de salida que resulta al aplicarle a x la función f.
Desde el punto de vista de programación, una función tiene muchos puntos en común con lo dicho en el párrafo
1
anterior, sin embargo hay diferencias que es necesario resaltar. Una función está compuesta por:
2- Cuerpo de la función, que incluye todas las instrucciones de cálculo y decisiones lógicas.
3- Final de la función.
Así por ejemplo, si se desea hacer una función para calcular el número de Reynolds, el cual responde a la
siguiente expresión matemática:
𝐷𝑣𝜌
𝑅𝑒 =
𝜇
Se observa que se necesitan cuatro argumentos, o variables de entrada (diámetro, velocidad, densidad y
viscosidad), y hay dos variables de salida: una que es el número de Reynolds, representada en la expresión
dada, y otra que es la condición de error, la cual siempre debe ser tenida en cuenta, con el objeto de determinar
la posibilidad de existencia de errores en los cálculos. De esta manera se debe especificar la siguiente
información:
2
Nombre de la función: reynolds
3
Variables de entrada: diam, vel, dens, visc .
Variable de salida: re, er.
1
Cuando se haga uso de la palabra función será desde el punto de vista de programación, caso contrario se hará la correspondiente
aclaración.
2
Los nombres de las funciones responden a las mismas reglas que los de las variables, pero no puede haber una variable y una función que
tengan el mismo nombre.
3
Se recuerda que los caracteres alfabéticos utilizados en nombres de variables y funciones deben corresponder a las 26 letras del alfabeto
inglés, en su versión minúscula o mayúscula.
1- Inicio
2- Leer diam, vel, dens, visc
3- Asignar er=0
4- Asignar re=0
5- Si visc <= 0 entonces er=1. Ir al paso 7
6- Calcular re=diam*vel*dens/visc
7- Escribir re, er
8- Fin
if visc<=0 then
er=1
return
end
re=diam*vel*dens/visc
endfunction
1- Los comentarios son las líneas que comienzan con //. Los mismos se utilizan para hacer descripciones de
las distintas partes de la función. En este caso se utiliza para documentar las características básicas de la
función reynolds y dichos comentarios están compuestos de la siguiente manera:
Esta información es importante, ya que al documentar cada una de las funciones que se hagan, permite
recordar para qué sirve, qué datos necesita y qué información devuelve. El lector debe imaginar el caso
en que ya hayan desarrollado muchas funciones, por lo que se vuelve muy difícil recordar las
3 3 4
características específicas de cada una, por ejemplo: ¿la densidad se expresaba en g/cm o kg/m ?
Scilab hace caso omiso de todo lo escrito como comentario, por lo que se puede escribir haciendo uso de
cualquier carácter; de esta manera, se pueden usar eñes y acentos.
Si hay más de una variable de salida o de entrada, la lista de las mismas va separada por comas. El
nombre de la función cumple con las mismas reglas que los nombres de las variables, no pudiendo tener
el mismo nombre una variable y una función.
Es importante observar que la lista de variables de salida van encerradas entre corchetes, mientras que
las variables de entrada están encerradas entre paréntesis.
Modo Programación
Como se vio anteriormente, Scilab puede funcionar en el Modo Consola, en el cual se realizan los cálculos en
forma inmediata, como si se tratara de una calculadora. Otra forma de operación corresponde al Modo
Programación, en la cual se escriben las instrucciones en un archivo, para ser ejecutadas con posterioridad,
todas las veces que sea necesaria. Básicamente el archivo al que se hace alusión está constituido por funciones
que realizan los cálculos necesarios para resolver el problema que se desee. El conjunto de todo lo escrito en
este archivo recibe el nombre de código fuente.
Para poder escribir este archivo se hace uso de un editor específico, el cual es invocado escribiendo la siguiente
instrucción en la consola:
-->scinotes
Tras lo cual se abre una nueva ventana con un editor a pantalla completa, la que se puede apreciar en la figura 2.
4
El manejo de las unidades de medida es absoluta responsabilidad de quien utiliza la función. La función recibe valores numéricos en la
entrada, realiza cálculos con dichos valores y devuelve un resultado numérico, es el ingeniero el responsable de verificar que dicho resultado
sea consistente con la realidad.
La primera vez que se ejecute se seleccionará el menú Opciones y allí se verá el menú Auto-completion on, el
cual tiene dos opciones: (, [, … y if, function, … las cuales se encuentran marcadas con una tilde. Se deben
seleccionar las dos para eliminar las tildes. Esta operación evita que el editor de Scilab realice tareas para
autocompletar las líneas de código que se escriban, ya que esta facilidad complica la comprensión de lo que se
está escribiendo. Esta operación se realiza una sola vez, tras lo cual se puede comenzar a escribir el código de
las distintas funciones que se necesite.
Para grabar el archivo se recurre a la opción Guardar del menú Archivo, en donde se tendrá que asignar un
nombre la primera vez que se haga la grabación, se supondrá que el archivo se grabará con el nombre
funciones.sci. La extensión del archivo será en general sci pero también puede ser sce, si bien existe una
diferencia entre los dos tipos de archivo, a los efectos prácticos se considerarán iguales.
Para poder utilizar las funciones así definidas, deben ser incorporadas a la base de datos de las funciones
utilizadas por Scilab, para lo cual se debe hacer clic en el ícono Ejecutar de la barra de herramientas, el cual está
encerrado en un círculo rojo en la figura 3.
Fig. 3. Botón de ejecución para incorporar las funciones del usuario a las nativas de Scilab.
Para utilizar la función reynolds lo haremos como si se tratara de cualquier función de Scilab, así se puede
escribir la siguiente instrucción:
-->[re,er]=reynolds(0.01,2,1000,0.001)
er =
0.
re =
20000.
Es importante acotar que Scilab no es capaz de manejar unidades, ni tampoco es capaz de saber si el orden en
que se han escrito los valores de los datos coinciden con las respectivas variables de entrada, por lo que el
usuario es el responsable de colocar los datos en las unidades adecuadas y en el orden correcto, de acuerdo a
como fue escrita la función. Por este motivo es muy importante colocar los comentarios necesarios delante de
cada función que se haga.
Toda función debe ser diseñada con el objeto no solo de resolver una problemática, sino también lo debe hacer
5
de forma eficiente, flexible, robusta y confiable .
Eficiencia
Significa que el código que se está escribiendo debe ser pensado para simplificar los cálculos a
su mínima expresión, de esta forma el microprocesador de la computadora no es utilizado
innecesariamente en operaciones extras que no aportan nada al resultado final: por ejemplo,
para calcular una raíz cuadrada se pueden escribir las dos instrucciones siguientes:
y = sqrt(x) o y = x^(1/2)
cualquiera de las dos instrucciones devolverá la raíz cuadrada de x; sin embargo, la primera es
más eficiente, ya que utiliza una función específica, mientras que la segunda obliga al
microprocesador a realizar dos operaciones: la primera resolver el exponente y después resolver
la potencia.
Otro ejemplo puede ser el cálculo de una función trigonométrica. Suponemos que se desea
calcular el coseno de un ángulo expresado en grados sexagesimales, entonces se puede realizar
la operación de las siguientes maneras:
y =cos(x*%pi/180) o y = cosd(x)
En el primer caso, dentro del argumento de la función, se realiza la conversión del argumento en
grados sexagesimales a radianes (ya que la función cos requiere que el argumento esté
expresado en radianes); mientras que en el segundo caso se hace uso de la función que
requiere el argumento directamente en grados sexagesimales. Naturalmente la segunda forma
es más eficiente que la primera.
Flexibilidad
Esta característica nos permite evaluar la capacidad que tiene una función de adaptarse a
distintas condiciones de cálculo. Así por ejemplo, supongamos una función para hacer cálculos
que involucren la presión atmosférica y la aceleración de la gravedad; por lo general, por una
cuestión de simplicidad, estos datos se considerarán constantes, de esta manera la presión será
2
igual a una atmósfera y la aceleración de la gravedad será igual a 9.81 m/s . Sin embargo, es
más flexible una función que permitiera trabajar con otras presiones y otras aceleraciones, esto
teniendo en cuenta que difícilmente el sistema al que se desee aplicar el cálculo se encuentre a
45º de latitud y a nivel del mar.
5
Estos cuatro conceptos están basado en la experiencia del autor en trabajos realizados sobre confiabilidad de software.
Robustez
En su enorme mayoría las funciones reciben información a través de sus argumentos. Esta
información es procesada, mediante cálculos matemáticos de la más variada complejidad, y los
resultados obtenidos son devueltos a través de las variables de salida de dicha función.
La robustez de una función está dada por la capacidad de reaccionar correctamente frente a
valores inadecuados de los argumentos o situaciones no previstas, como puede ser una división
por cero. Por ejemplo, si se desea calcular una velocidad conociendo el valor de la distancia y
del tiempo, se podría escribir el código de la siguiente función:
Esta función devuelve el valor 45 si d vale 90 y t vale 2, por otro lado devuelve 10 si d vale 200 y
t vale 20. En el caso en que t valga cero, la función devuelve el siguiente error:
vel=velocidad(10,0)
!--error 27
División por cero...
Este es el caso de una función poco robusta. Una función robusta no debe producir el aborto de
la ejecución, por lo que siempre debe terminar devolviendo un resultado. En pocas palabras se
puede decir que una función robusta es aquella que devuelve resultados sin importar el valor de
sus argumentos; es decir, la función no se bloquea ni emite errores de mal funcionamiento.
Confiabilidad
Las funciones deben devolver resultados correctos si los argumentos de entrada son correctos, y
deberían indicar la situación eventual en la que los parámetros de entrada son incorrectos y no
realizar ningún cálculo. Para ejemplificar esta situación se puede recurrir al ejemplo de función
visto al principio de este apunte, en el cálculo del número de Reynolds, por lo menos se debe
verificar que las variables de entrada (diámetro, velocidad, densidad y viscosidad) sean valores
positivos, para evitar que la función devuelva un valor de Reynolds negativo o nulo, algo que
desde el punto de vista físico carece de sentido.
Los conceptos de robustez y confiabilidad, si bien pueden parecer similares, apuntan a dos aspectos distintos.
Haciendo una analogía un poco burda, se puede decir que robustez y confiabilidad son conceptos similares a
precisión y exactitud en metrología. La robustez nos indica que el código va a devolver resultados, sin bloquearse
ni detenerse, siempre hace su trabajo y entrega un resultado; por otro lado, la confiabilidad asegura que ese
6
resultado es correcto .
6
Un resultado correcto se debe entender como un valor numérico cuando los datos son adecuados, o como un mensaje de aviso cuando se
detectan problemas con los datos.
ESTRUCTURAS DE CONTROL
Las estructuras de control son un conjunto de instrucciones que permiten modificar el funcionamiento de un
código, de acuerdo a determinados parámetros. Estas estructuras dan una enorme versatilidad a la hora de
programar funciones, y su estudio y dominio es fundamental para poder desarrollar códigos de gran potencia de
cálculo y que además, tengan los atributos ya vistos.
Al escribir una función por primera vez, nunca es todo lo eficiente, flexible, robusta o confiable que podría ser, por
lo que siempre va a haber un proceso de maduración, donde la función se va enriqueciendo a través de la
experiencia adquirida por su uso.
A continuación se verá un proceso simple de maduración de un código. Se recuerda que este proceso se da a
través de la experiencia en el uso del código, detectando falencias, errores o simplemente identificando posibles
mejoras que se puedan realizar para aumentar la velocidad de cálculo, la precisión, etc.
re=diam*vel*dens/visc
endfunction
re=reynolds(0.01,2,1000,0.001);
En este caso se utilizó un diámetro de tubería de 0.01 metros, una velocidad de fluido de 2 m/s, una densidad de
3
fluido de 1000 kg/m y una viscosidad de 0.001 kg/m s. Para ver el resultado se escribe el nombre de la variable
7
de salida , en este caso re y el resultado que muestra Scilab es 20000.
--> re=reynolds(0.01,2,1000,0)
re =
Inf
Se observa como Scilab devuelve un resultado no adecuado ingenierilmente, debido a que la viscosidad tiene un
valor nulo. Sin importar las causas por las que el valor de la viscosidad es cero, se demuestra que el código de la
función es poco confiable ya que no devuelve una respuesta adecuada.
Para resolver este problema se va a utilizar la capacidad de un lenguaje de programación para tomar decisiones.
En el caso de Scilab se usará la instrucción if – then – else, que recibe el nombre de condicional.
La sentencia if evalúa una expresión lógica (condición), cuyo resultado puede ser verdadero o falso
exclusivamente, y ejecuta un grupo de instrucciones solo si el resultado fue verdadero, caso contrario puede
ejecutar otro conjunto de instrucciones o simplemente no hacer nada.
Para construir una expresión lógica se utilizan los denominados operadores lógicos, los cuales tienen la
característica de comparar los valores almacenados en variables, dando como resultado verdadero o falso, de
acuerdo al resultado de comparación que se utilice. En ningún caso los valores de las variables son modificados.
Los distintos comparadores lógicos se observan en la tabla que se da a continuación:
7
Nótese que la instrucción de cálculo termina con punto y coma, por lo que no hay un eco en la pantalla.
Teniendo en cuenta lo dicho, la nueva lógica de la función del cálculo del número de Reynolds, sería la siguiente:
Si el valor de la viscosidad es menor o igual a cero entonces retornar sin calcular el número de
Reynolds.
function [re]=reynolds(diam,vel,dens,visc)
re=0
if visc<=0 then
return
end
re=diam*vel*dens/visc
endfunction
De acuerdo a la nueva lógica, el número de Reynolds a veces será calculado y otras veces no, de acuerdo al
valor de la viscosidad. Sin embargo, las funciones siempre deben devolver valores en sus variables de salida.
Esta es la razón por la cual se debe agregar la instrucción re=0, ya que al ser re una variable de salida sí o sí
hay que asignar un valor, de lo contrario se obtendrá un error como el que se ve a continuación:
re=reynolds(0.01,2,1000,0.0)
!--error 4
Variable indefinida: re
Se observa que la expresión lógica justamente está preguntando si (if) el valor almacenado en la variable visc,
es nula o negativa, y si esto es cierto entonces (then) se sale de la función mediante la instrucción return, sin
hacer nada, y a continuación finaliza la instrucción condicional (end).
Si el valor de la viscosidad es positivo, la condición de la estructura de control es falsa, por lo que el condicional
no se ejecuta y directamente es salteado hasta la siguiente instrucción, que es el cálculo del número de
Reynolds.
8
Como símbolo de desigualdad también se puede utilizar ~=, pero el símbolo tilde “~” sólo está disponible en teclado inglés o en los
españoles con distribución latinoamericana, pero este último no es muy común en la actualidad.
9
Esta expresión lógica permite saber cuándo una variable se encuentra comprendida en un determinado intervalo. En este caso el resultado
es verdadero sólo cuando el valor de x está entre 0 y 10, sin tomar ninguno de estos valores.
10
Esta expresión lógica se utiliza cuando se desea comprobar si una variable está fuera de un determinado intervalo. En este caso el
resultado es verdadero si la variable x contiene un valor menor a 0 o mayor a 10.
Manejo de errores
Con esta modificación se ha mejorado la robustez de la función, porque no se detiene o aborta por problemas
con el valor de la viscosidad; pero no su confiabilidad, ya que en caso que la viscosidad sea nula o negativa no
devuelve un resultado válido, de todas maneras no se puede hacer ningún cálculo en estas circunstancias. Para
solucionar este problema, es decir, que la función devuelva información que permita saber si el resultado es
válido o no, se va a utilizar el concepto de manejo de errores visto con anterioridad, como se puede observar en
el siguiente código de la función:
re=diam*vel*dens/visc
endfunction
El análisis de esta función permite identificar una nueva variable de salida, er, cuya finalidad es la de devolver un
código de error, para este caso se supone el valor 0 si el cálculo se realizó con éxito y 401 si no se pudo realizar
porque la viscosidad es nula. Es importante aclarar que como convenio se utilizará para los códigos de error el
formato x01, x02, etc. donde x será la unidad temática en la que se esté trabajando. Esto se debe a que cuando
se estudie métodos numéricos se mezclarán funciones de diversas unidades, y de esta manera no se producirán
conflictos debido a códigos de error repetidos.
Se asigna el valor 0 a la variable er al principio de la función. De esta manera sólo es necesario asignar los
valores correspondientes a las condiciones de error, a medida que se vayan sucediendo.
De esta forma, cuando se utilice la función, se debe revisar el valor de la variable er, si el valor es cero entonces
la variable re contiene un resultado válido, si por el contrario er contiene el valor 1, significa que la viscosidad,
por alguna razón que habrá que averiguar, vale cero y el valor de la variable re no es válido. De esta manera se
consigue una función más robusta y confiable que la primera que se hizo.
Análisis de resultados
Una característica interesante, al hacer el desarrollo de una función, es implementar la capacidad de analizar los
resultados obtenidos, con el objeto de facilitar la interpretación de los mismos. En el caso del cálculo del número
de Reynolds se sabe que el valor define el tipo de flujo, el cual se clasifica de acuerdo a lo detallado en la
siguiente tabla:
return
end
re=diam*vel*dens/visc
if re<2100 then
flujo="laminar"
else
if re<10000 then
flujo="transición"
else
flujo="turbulento"
end
end
endfunction
Como se observa se han agregado un par de condicionales al final de la función. Estas instrucciones se pueden
interpretar de la siguiente manera: si el número de Reynolds es menor que 2100 entonces (if re<2100 then)
el flujo es laminar (flujo="laminar"), de lo contrario (else) si el número de Reynolds es menor que 10000
entonces (if re<10000 then) el flujo es de transición (flujo="transición"), de lo contrario (else) el flujo
es turbulento (flujo="turbulento"). Para terminar se encuentran las dos instrucciones de finalización de
cada uno de los condicionales (end).
1- [re,flujo,er]=reynolds(0.01,2,1000,0.001)
er =
0.
flujo =
turbulento
re =
20000.
2- [re,flujo,er]=reynolds(0.01,0.9,1000,0.001)
er =
0.
flujo =
transición
re =
9000.
3- [re,flujo,er]=reynolds(0.01,0.02,1000,0.001)
er =
0.
flujo =
laminar
re =
200.
Con este ejemplo también se muestra la forma de asignar cadenas de caracteres (texto) a una variable. En este
caso se han utilizado comillas para encerrar el texto, pero también es posible utilizar apóstrofes.
AUTODOCUMENTACIÓN
Como se ha observado en los sucesivos agregados que se han hecho a la función de cálculo del número de
Reynolds, la complejidad de la misma ha ido aumentando, haciendo cada vez más difícil una rápida
interpretación del funcionamiento de la función. Incluso para el mismo programador, que diseñó, escribió y
corrigió la función. Después de algún tiempo, se va a ir olvidando de los detalles de la misma, por lo que si debe
hacer modificaciones va a tener que estudiarla previamente para recordar todos los pormenores.
Para evitar esta pérdida de tiempo, es que se deben autodocumentar las funciones, mediante el uso de
comentarios con textos concisos pero clarificadores. A modo de ejemplo se reproduce la última versión de la
función vista, en su versión autodocumentada.
endfunction
Como se describió anteriormente, la instrucción condicional corresponde a una estructura de control, lo que
significa que permite controlar la forma en que el código se ejecuta, otorgando flexibilidad al mismo ya que
permite realizar tareas que de otra manera serían difíciles de ejecutar. A continuación se verán el resto de las
estructuras de control.
Consiste en una instrucción de selección múltiple, permitiendo escribir un código claro y limpio. Así por ejemplo,
anteriormente se habló de la necesidad de manejar los errores, para lograr códigos más robustos, de manera tal
que a cada error se le asignaba un número; sin embargo, cuando se tienen muchos códigos de error es difícil
recordarlos y se vuelve conveniente convertirlos a una expresión literal que explique el error de manera clara y
precisa. En la siguiente tabla se reproduce un ejemplo hipotético de errores.
Código
Descripción
de error
0 No se han producido errores.
401 División por cero en el cálculo del Reynolds, la viscosidad es nula.
402 La velocidad del fluido excede el máximo admitido.
403 La temperatura supera la temperatura crítica del fluido.
404 La presión de vapor excede la presión exterior. El sistema no está en equilibrio.
405 El sistema de ecuaciones es indeterminado, hay dependencia lineal entre ecuaciones.
Una forma sencilla y clara para traducir los códigos de error a su correspondiente significado literal, es mediante
la instrucción select como se observa en el siguiente ejemplo de código:
endfunction
Para utilizar esta función se debe introducir como argumento el código de error que corresponda, según se
observa en el siguiente ejemplo:
error=describeError(3);
error =
La temperatura supera la temperatura crítica del fluido
Esta instrucción permite realizar lo que en programación se denomina lazo; es decir, una porción de código que
para el caso de la instrucción for se repite una cantidad determinada de veces.
Para ejemplificar el uso de esta instrucción se supondrá la siguiente situación problemática: Supóngase el tanque
que se muestra en la figura, el cual contiene un sistema multicomponente bifásico, representando con V la fase
vapor y con L la fase líquida.
Se desea diseñar una función que permita calcular la fracción molar de todos los compuestos de la fase vapor,
para lo cual se debe realizar el siguiente cálculo:
𝑛𝑖
𝑦𝑖 =
𝑛𝑖
Se observa que se debe dividir la cantidad de moles en la fase vapor, de cada especie química, por el total de
moles en dicha fase. Debido a que la información de cada fase se encuentra mezclada en un único vector, es
conveniente separar en un nuevo vector toda la información relativa a la fase vapor exclusivamente. Para lograr
esto, se debe hacer una lectura, elemento por elemento del vector compos, analizando a qué fase pertenece, y
en caso de corresponder, se hace la copia de la información en otro vector, que se llamará yi. Este último vector
contendrá una cantidad indefinida de elementos, ya que no necesariamente la fase vapor y líquida contienen
todas las especies químicas involucradas, téngase en cuenta que bien podría haber un compuesto no volátil en la
fase líquida, como podría ser un compuesto iónico, o una sustancia incondensable en la fase gaseosa, por
ejemplo nitrógeno.
Para determinar el tamaño del vector yi se utiliza un criterio de máximo; es decir, no puede ser más grande que
el tamaño del vector compos. Sin embargo sigue existiendo el problema de indicar cuántos datos válidos
contiene el vector yi. Esto se solucionará mediante el uso de lo que en programación se denomina flag o
bandera, que consiste básicamente en colocar después del último dato un valor no válido; así por ejemplo, a
continuación del último valor, se colocará un -1, que constituye un valor imposible para un número de moles. Por
este motivo, el vector yi será dimensionado con un elemento más que compos, previendo la posibilidad que en
algún caso particular, todo el contenido del tanque sea vapor.
A continuación se transcribe una función que cumple con los lineamientos discutidos, además de incluir al
principio la gestión de errores. En este ejemplo se ha hecho uso de la función size, la cual devuelve el tamaño
de la matriz que se le ha pasado como primer argumento, mientras que el segundo argumento indica qué es lo
que se desea conocer, si la cantidad de columnas (c) o de filas (r), este último argumento puede ir entre comillas
o apóstrofes.
A continuación se reproduce el código de la función nuevamente, pero con comentarios que explican el
funcionamiento de cada una de las partes de la misma:
Para utilizar esta función se ingresarán en Scilab los siguientes vectores de datos:
-->fase=[1 0 0 1 0 1 1];
-->[yi,er]=FraccionMolar(compos,fase)
er =
0.
yi =
0.3085554 0.4796634 0.0168303 0.1949509 -1. 0. 0. 0.
Como se observa, el vector yi contiene cuatro valores antes de encontrarse el -1, indicador de finalización.
Analizando el vector fase, se aprecia que justamente hay cuatro datos correspondientes a la fase vapor. Para
hacer una última verificación, se sumarán esos cuatro valores del vector yi:
-->sum(yi(1:4))
ans =
1.
Verificando de esta manera, que los datos contenidos en yi son las fracciones molares de todas las especies
químicas en la fase vapor. Es importante destacar que si se hubiera utilizado la instrucción sum(yi) se sumarían
todos los elementos del vector, incluyendo el -1, dando como resultado cero si todo está en orden.
La instrucción for incluye el nombre de una variable, que recibe el nombre de índice, y en el caso del ejemplo
precedente es i, seguida de una expresión similar a la utilizada para declarar matrices, tema visto anteriormente.
Se verán distintos ejemplo con sus correspondientes resultados:
Como se aprecia, los valores pueden ir tanto en sentido ascendente como descendente, incluso no es necesario
que sean números enteros, pero en este caso no se puede utilizar el contenido de la variable masa como índice
de un vector o matriz, pero sí se lo puede usar para realizar cálculos matemáticos.
La instrucción while también permite realizar lazos, pero que se repiten una cantidad indeterminada de veces,
esto significa que no se puede establecer a ciencia cierta cuántas veces se ejecutará el lazo, a diferencia de la
instrucción for, en la cual es fácil determinar cuántas veces se repite el lazo.
La indeterminación del lazo while se debe fundamentalmente a que se va a ejecutar mientras se cumpla una
condición. Para ejemplificar su uso, se continuará con el ejemplo visto previamente. Una vez calculadas las
fracciones molares de la fase gaseosa, si se conoce la presión total de la misma, se pueden calcular las
presiones parciales, de acuerdo a la siguiente expresión:
𝑝𝑖 = 𝑦𝑖 ∙ 𝑃
Por lo que simplemente se deben multiplicar las fracciones molares por la presión total; sin embargo, si bien se
tiene un vector con las fracciones molares, la cantidad de datos válidos es desconocida de antemano, y sólo se
dispone de un flag, ubicado en algún lugar del vector. Por este motivo, se dice que el cálculo se va a hacer
mediante un lazo que va a funcionar una cantidad indeterminada de veces, por lo cual se utilizará el lazo while
en lugar del for.
La función que realiza esta operación se reproduce a continuación, en la cual se puede observar una estructura
similar a la anterior respecto de la gestión de errores. El vector Pi, que va a contener todas las presiones
parciales, se dimensiona con el mismo tamaño que yi, que ya incluye un lugar adicional para almacenar el flag.
El lazo while se ejecutará hasta que se encuentre el flag en el vector yi; mientras esto no ocurra, se irán
multiplicando una a una las fracciones molares por la presión total y almacenando el resultado en el vector Pi.
Una vez alcanzada la condición de salida del lazo, se almacena el flag correspondiente en el vector Pi y se
finaliza la función.
A continuación se reproduce la misma función con los comentarios correspondientes respecto del funcionamiento
de la misma.
er=0
// se verifica la cantidad de filas ('rows') del vector yi
if size(yi,'r')<>1 then
er=404
return
end
// se verifica que la presión no sea negativa o nula
if P<=0 then
er=405
return
end
nDatos=size(yi,'c')
// se verifica que el vector yi tenga por lo menos un dato válido
if nDatos<2 then
er=406
return
end
// se dimensiona el vector Pi con el mismo tamaño que yi
Pi=zeros(1,nDatos)
// se inicializa el índice para recorrer el vector yi
k=1
// se repite el lazo mientras no se encuentre el flag
while yi(k)<>-1
// se calcula la presión parcial del vapor k-ésimo
Pi(k)=yi(k)*P
// se avanza al siguiente componente
k=k+1
end
// se coloca el flag después del último dato del vector Pi
Pi(k)=-1
endfunction
-->[Pi,er]=PresionParcial(yi,15)
er =
0.
Pi =
Como la suma de las presiones parciales es igual a la presión total, se puede realizar la siguiente verificación:
-->sum(Pi(1:4))
ans =
15.
Estas dos instrucciones se utilizan tanto con los lazos for como con los lazos while. La instrucción break
fuerza la interrupción del lazo, continuando la ejecución del programa en la instrucción siguiente al fin del lazo,
mientras que la instrucción continue fuerza el fin del ciclo actual del lazo, comenzando la ejecución del lazo en
el ciclo siguiente.
yi =
De esta manera la función demuestra que no es robusta. Seguidamente se muestra una función mejorada,
mediante el uso de la instrucción break y con un nuevo código de error, el número 7, que indica de manera
explícita la inexistencia del flag en el vector yi. Tal como se observa a continuación:
Pi(k)=yi(k)*P
// se avanza al siguiente componente
k=k+1
if k>nDatos then
// si el índice k supera la longitud del vector yi
// significa que el flag no está, por lo que se asigna
// el código de error y se cancela el lazo
er=407
break
end
end
endfunction
Al ser llamada, con el vector yi sin el flag correspondiente, la función se comporta de una forma adecuada, como
se ve en el siguiente caso:
-->[Pi,er]=PresionParcial(yi,15)
er =
407.
Pi =
Se debe recordar que lo primero que se debe analizar, cuando se obtienen resultados de una función, es el valor
de la variable er, si la misma es distinta de cero, se deben descartar los resultados y revisar la situación. En el
caso anterior, los resultados entregados son correctos; sin embargo, la inexistencia del flag genera el error, esto
puede significar que hay más datos, que por algún motivo se han perdido. Hasta no definir adecuadamente el
motivo por el cual apareció el error, los resultados no pueden darse como válidos.
FUNCIÓN DE FUNCIÓN
Al estudiar las instrucciones for y while, se desarrollaron dos funciones de cálculo aplicables a mezclas de
gases, las cuales están íntimamente relacionadas.
La primera de dichas funciones permite el cálculo de la fracción molar de una mezcla, la cual se llama
FraccionMolar; mientras que la segunda, denominada PresionParcial, utiliza el resultado de la primera
para calcular las presiones parciales de cada componente de la mezcla. Tal cual se ha presentado el desarrollo
de las funciones mencionadas, el uso de las mismas es independiente. Se puede pensar en ir aumentando la
cantidad de funciones aplicable a mezclas gaseosas, que permitan determinar valores como: densidades, masas,
volúmenes parciales, etc. Todas estas funciones deberían ser llamadas una por una, para poder realizar los
cálculos correspondientes, volviéndose la tarea bastante tediosa, sobre todo si se tienen muchas mezclas de
gases que resolver.
Con el objeto de simplificar toda la operación de resolución, es que se escribe lo que se llama una función de
función, que consiste en una función que va llamando en secuencia lógica a cada una de las funciones
individuales, obteniendo todos los resultados. De esta manera, se llama a una única función para poder resolver
la mezcla de gases en forma completa.
De esta manera se pueden armar funciones que llamen a otras funciones y a su vez, éstas últimas pueden seguir
llamando a más funciones, lográndose una estructura de cálculo bastante compleja y potente.
Para ejemplificar lo dicho, se puede hacer una función que abarque las dos funciones vistas anteriormente; por lo
tanto, no es necesario estar llamando a cada una por separado, sino a una sola y que esta última devuelva todos
los resultados.
Seguidamente se puede ver la misma función de función con los comentarios explicativos de cada una de las
partes de la misma:
En las siguientes líneas se transcriben las instrucciones necesarias para poder hacer uso de esta nueva función,
con las verificaciones correspondientes, las cuales nunca están de más.
-->fase=[1 0 0 1 0 1 1];
-->[yi,Pi,er]=CalcularMezcla(compos,fase,15)
er =
0.
Pi =
yi =
-->sum(yi(1:4))
ans =
1.
-->sum(Pi(1:4))
ans =
15.
Las funciones permiten que sus argumentos sean expresiones racionales y también pueden devolverlas como
resultados.
Para ejemplificar lo expresado se utilizará la ecuación de Van der Waals de gases reales, que se expresa
habitualmente de la siguiente manera:
𝑛2 𝑎
𝑃+ . 𝑉 − 𝑛𝑏 = 𝑛𝑅𝑇
𝑉2
Sin embargo, para poder trabajar la misma, es común desarrollarla algebraicamente hasta obtener una ecuación
cúbica en V, tal como se expresa a continuación:
𝑃 ∙ 𝑉 3 − 𝑛𝑏𝑃 + 𝑛𝑅𝑇 ∙ 𝑉 2 + 𝑛2 𝑎 ∙ 𝑉 − 𝑛3 𝑎𝑏 = 0
𝑐3 ∙ 𝑉 3 + 𝑐2 ∙ 𝑉 2 + 𝑐1 ∙ 𝑉 + 𝑐0 = 0
𝑐3 = 𝑃
𝑐2 = − 𝑛𝑏𝑃 + 𝑛𝑅𝑇
𝑐1 = 𝑛2 𝑎
𝑐0 = −𝑛3 𝑎𝑏
Por lo que conociendo, P, T, n, R y las constantes de Van der Waals a y b del gas en cuestión, se puede definir la
ecuación en V. Como es un trabajo arduo, sobre todo si se está trabajando con varios gases, se diseñó una
función para definirlo, pero la misma sólo trabajará con valores escalares en sus argumentos, de esta manera es
posible definir una única ecuación a la vez.
return
end
if a<=0 | length(a)>1 then
er=412
return
end
if b<=0 | length(b)>1 then
er=413
return
end
c3=P
c2=-(n*b*P+n*R*T)
c1=n^2*a
c0=-n^3*a*b
pVdW=poly([c0 c1 c2 c3],'V','c')
endfunction
En la función se ha hecho uso de la instrucción length que devuelve como resultado la cantidad de elementos
de la matriz que se pasa como argumento, al tratarse de valores escalares, dicha cantidad necesariamente debe
ser 1.
𝑏 = 0.03913 𝑙/𝑚𝑜𝑙
-->a=1.390;b=0.03913;
-->T=300;P=1;n=10;
-->R=0.0820562;
-->[pVdW,er]=VanderWaals(P,T,R,n,a,b)
er =
0.
pVdW =
2 3
- 54.3907 + 139V - 246.5599V + V
Si se calculan las raíces del polinomio resultante, se obtendrán los volúmenes del fluido a la presión y
temperatura dadas. En el caso del ejemplo:
-->v=roots(pVdW)
v =
245.99575
0.2820758 + 0.3762147i
0.2820758 - 0.3762147i
Analizando la respuesta, se encuentra una raíz real y dos complejas conjugadas (estas últimas se descartan), por
lo tanto el fluido tiene un único estado cuyo volumen es de 245.996 litros.
Para verificar si este valor es correcto, primero se calculará la densidad del fluido, teniendo en cuenta que la
masa molar de una molécula de nitrógeno es de 28.0134 g/mol, el resultado será:
-->dens=28.0134*10/v(1)
dens =
1.1387758
Una densidad de 1.139 g/l corresponde a un gas o vapor, por lo que se utilizará la ecuación de los gases ideales
para calcular el volumen de los 10 moles de nitrógeno:
-->10*R*T/P
ans =
246.1686
Como se observa se obtiene un valor bastante cercano al calculado por la ecuación de Van der Waals. Se debe
aclarar que esta verificación es posible ya que la condición utilizada, de presión y temperatura, se encuentra
bastante alejada del punto crítico del nitrógeno.
Si se observa la función de cálculo del número de Reynolds, vista al principio de este apunte, se verá que dicha
función permite calcular un valor determinado, de acuerdo a los distintos argumentos de la misma. De esta forma
se puede conocer un determinado valor de Reynolds para cada conjunto de valores de entrada.
Una característica de Scilab es que permite definir vectores, que incluyan como componentes distintos valores de
un determinado argumento. De esta manera, si se desean calcular los valores del número de Reynolds para
velocidades desde 0.2 m/s hasta los 2 m/s, con un intervalo de 0.1 m/s, se pueden escribir las siguientes
instrucciones:
-->vel=[0.1:0.1:2]
vel =
column 1 to 13
0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. 1.1 1.2 1.3
column 14 to 20
-->re=reynolds(0.01,vel,1000,0.001)
re =
column 1 to 10
1000. 2000. 3000. 4000. 5000. 6000. 7000. 8000. 9000. 10000.
column 11 to 19
column 20
20000.
Como se observa el cálculo ha sido realizado en forma correcta por Scilab, dando por resultado veinte valores de
Reynolds, correspondientes a cada una de las velocidades del vector vel.
A continuación se desea calcular los distintos valores de Reynolds para cambios de la viscosidad, desde 0.001
kg/m s hasta 0.002 kg/m s, en incrementos de 0.0001 kg/m s. Para realizar esta tarea se escriben las siguientes
instrucciones:
-->visc=[0.001:0.0001:0.002]
visc =
column 1 to 9
0.001 0.0011 0.0012 0.0013 0.0014 0.0015 0.0016 0.0017 0.0018
column 10 to 11
0.0019 0.002
-->re=reynolds(0.01,2,1000,visc)
re =
773.69439
851.06383
928.43327
1005.8027
1083.1721
1160.5416
1237.911
1315.2805
1392.6499
1470.0193
1547.3888
Al analizar el resultado se observa que el primer valor de Reynolds es de 773.69439, el cual corresponde a una
viscosidad de 0.001, sin embargo este cálculo ya se había realizado con anterioridad, dando como resultado
20000. Por otro lado, la variable visc es un vector fila, mientras la variable re es un vector columna, lo que da la
pauta que Scilab está haciendo un cálculo matricial y no un cálculo elemento a elemento.
re=diam*vel*dens/visc
Al ser la variable visc un vector, la operación de división Scilab la resuelve en forma matricial, por lo que se
debe modificar la instrucción de cálculo por esta otra:
11
re=diam*vel*dens./visc
Una vez hecha esta modificación, el cálculo de los números de Reynolds para las distintas viscosidades dará el
siguiente resultado:
-->re=reynolds(0.01,2,1000,visc)
re =
column 1 to 7
20000. 18181.818 16666.667 15384.615 14285.714 13333.333 12500.
column 8 to 11
11764.706 11111.111 10526.316 10000.
11
Nótese la presencia del punto antes de la barra de división, indicando una operación elemento a elemento.
Con este ejemplo se desea hacer hincapié en la importancia de escribir en forma adecuada las expresiones de
cálculo. En la medida que se utilicen valores escalares las funciones devolverán valores correctos, pero si se
utilizan vectores, con el objeto de armar tablas de valores, el resultado puede ser incorrecto.
Las expresiones lógicas dan una gran versatilidad a la hora de procesar información. Si bien ya se han utilizado a
lo largo del apunte, se hará una discusión más profunda de sus posibilidades.
Instrucción Descripción
La condición es verdadera para todos aquellos valores de x que sean
mayores a 1000. Si x es una matriz, devuelve otra matriz del mismo
tamaño, donde cada elemento es T o F, según si se cumple o no la
condición para cada elemento de la matriz original.
a- if x>1000 then …
El comportamiento es similar para los símbolos relacionales:
<: menor que
>=: mayor o igual que
<=: menor o igual que
La condición es verdadera si el valor de x es igual a 1000. Si x es una
if x==1000 then … matriz, devuelve otra matriz del mismo tamaño, donde cada elemento es
b-
T o F, según si se cumple o no la igualdad con cada elemento de la matriz
original.
La condición es verdadera si el valor de x es distinto a 1000. Si x es una
if x<>1000 then … matriz, devuelve otra matriz del mismo tamaño, donde cada elemento es
c-
T o F, según si se cumple o no la desigualdad con cada elemento de la
matriz original.
Este tipo de expresión lógica se utiliza para saber si un determinado valor
de la variable se encuentra dentro de ciertos límites. Se utiliza el conector
lógico Y, simbolizado por &.
Se pueden usar también los símbolos relacionales: <, >=, <=, ==, <>
Instrucción Descripción
La instrucción sum(x>0) indica cuantos elementos de la matriz x son
positivos, mientras que la instrucción length(x) indica cuantos
elementos hay en la matriz x en total.
if sum(x>0)==length(x)
g- then … La expresión dada en el ejemplo es verdadera si la cantidad de elementos
positivos es igual a la cantidad de elementos totales de la matriz x. En
otras palabras, la expresión es verdadera si todos los elementos de x son
positivos.
Se verán a continuación ejemplos de los dos últimos casos, ya que los anteriores han sido utilizados a lo largo del
apunte.
Caso f
--> sum(x>=1100)
ans =
3.
Caso g
--> sum(x>0)
ans =
5.
--> length(x)
ans =
6.
2.
Como se discutió previamente, las computadoras representan los números en un formato de punto flotante. Los
números irracionales y periódicos deben ser redondeados a 16 dígitos, ya que la representación exacta requiere
de infinitos dígitos, produciendo un error de truncamiento. Esto ocasiona problemas inevitables que deben ser
tenidos en cuenta al programar. Además, las computadoras utilizan el sistema binario para codificar la
información, por lo que números que en sistema decimal tienen representación finita, en binario pueden ser
periódicos.
Así por ejemplo, el número 0,1 en decimal tiene una representación finita; sin embargo, en binario es periódica,
como se muestra a continuación:
1
= 0,110 = 0,0001100110011001100110011 …2
10
Por lo que este número es almacenado con un error de truncamiento, lo cual puede ser fácilmente verificado
mediante el uso de la siguiente función:
function [s]=suma(n)
s=0
for i=1:n
s=s+0.1
end
endfunction
Analizando la misma se puede ver que se trata de un simple acumulador, que suma 0.1 tantas veces como
indique el argumento de entrada n.
Como se va a analizar la exactitud de cálculo de la computadora, se utilizará la función format para visualizar
los 16 dígitos de precisión, con la siguiente instrucción:
--> format('v',18)
Seguidamente se llamará a la función suma(n) con distintos argumentos, y se analizarán los resultados:
--> s=suma(10)
s =
1.
--> s=suma(15)
s =
1.5
--> s=suma(20)
s =
2.
--> s=suma(30)
s =
3.000000000000001
Como se observa, en las primeras sumas los resultados son exactos; sin embargo, cuando se utiliza n=30
aparece un residuo, producto de la acumulación de errores de truncamiento del valor 0,1. Esta situación se va
empeorando a medida que aumenta n, como se aprecia en los siguientes cálculos:
--> s=suma(100)
s =
9.999999999999981
--> s=suma(1000)
s =
99.99999999999859
--> s=suma(10000)
s =
1000.000000000159
--> s=suma(100000)
s =
10000.00000001885
--> s=suma(1000000)
s =
100000.0000013329
Si bien, el residuo mencionado se mantiene relativamente despreciable, frente al valor del resultado, su presencia
hace que ciertas instrucciones de comparación puedan ser evaluadas como falsas, cuando en realidad no lo son.
12
Analícense las siguientes instrucciones :
--> suma(1)==0.1
ans =
--> suma(2)==0.2
ans =
--> suma(3)==0.3
ans =
Todos los casos son estrictamente verdaderos; sin embargo, el último es evaluado como falso debido a la
presencia del residuo mencionado. Recuérdese que las computadoras son estrictas, la mínima diferencia indica
desigualdad.
Dada esta explicación es fácil entender que cuando se trabaja con valores en punto flotante, expresiones como:
if vel==0 then …
if vel==100 then …
pueden fallar aunque la variable vel sea técnicamente nula o valga “casi” 100, debido a la presencia de los
mencionados residuos.
Por este motivo, nunca se utiliza la igualdad en expresiones lógicas con números en punto flotante, sino que se
usan expresiones del siguiente tipo:
if abs(vel)<1d-7 then …
if abs(vel-100)<1d-7 then …
Al analizar las expresiones lógicas se observa que se está preguntando si la variable vel está dentro de un
entorno de radio 10−7 del valor de referencia (0 ó 100), lógicamente el valor del radio debe ser ajustado al nivel
de precisión deseado. Sin embargo, este radio no debe ser excesivamente reducido, ya que se puede dar el caso
de que nunca se alcance ese nivel de precisión, debido a una oscilación permanente alrededor del resultado final.
12
Se recuerda que al evaluar expresiones lógicas, los resultados dados por Scilab son T para verdadero (true) y F para falso (false).