# PRACTICA 3. INTEGRACIÓN COMPLEJA. 
REPRESENTACIÓN DEFUNCIONES Y SERIES DE POTENCIAS.

## Curvas en C. Integración.

Las integrales en el campo complejo son integrales de línea en el plano. No obstante, como ya sabemos existen unos 
resultados específicos para estas integrales complejas que nos permitirán calcular las mismas sin necesidad de acudir 
a la definición (es decir, sin necesidad de tener que tomar una parametrización de la curva plana y de resolver la posterior 
integral de línea). Estos resultados son la independencia del camino de integración (más conocida como regla de Barrow para estas 
integrales), y para el caso de curvas cerradas, el teorema de Cauchy-Goursat y las fórmulas integrales de Cauchy (todos estos 
resultados tienen que ver con que f(z) sea analítica en la región encerrada por la curva). 

Intentaremos desarrollar todo ésto conceptos, en los ejemplos que vienen a continuación.

EJEMPLO 1. Representar las curvas complejas 

abs(z)=2; 

abs(z-3)=2.

Las curvas anteriores son dos circunferencias de radio 2, centradas en 0 y 3 respectivamente. Para hacer la representación
gráfica de las mismas necesitamos el paquete 

draw 

para realizar gráficas en coordenadas implícitas.

load(draw)$

La curva abs(z)=2 equivale a la circunferencia de ecuación

x^2+y^2=4

draw2d(implicit(x^2+y^2=4,x,-2,2,y,-2,2));

La curva abs(z-3)=2 equivale a la circunferencia de ecuación

(x-3)^2+y^2=4

draw2d(implicit((x-3)^2+y^2=4,x,0,6,y,-2,2));

EJEMPLO 2. Representar las curvas complejas 

z=2*exp(i*theta); 

z=3+2*exp(i*theta) 

en este caso las curvas vienen dadas por sus coordenadas polares; nosotros 
las representaremos en coordenadas paramétricas:

La curva z=2*exp(i*theta) equivale a la parametrización 

(2*cos(theta),2*sin(theta))

plot2d([parametric, 2*cos(t), 2*sin(t), [t, 0, 2*%pi], [nticks, 300]]);

La curva z=3+2*exp(i*theta) equivale a la parametrización

(3+2*cos(theta),2*sin(theta))

que es la que representamos a continuación

plot2d([[parametric, 3+2*cos(t), 2*sin(t), [t, 0, 2*%pi], [nticks, 300]]])$

Cardioide:

x = cos(t)*(1+cos(t))

y = sen(t) *(1+cos(t))


t en [0,2pi]);

plot2d([parametric,cos(t)*(1+cos(t)), sin(t)*(1+cos(t))],[t,0,2*%pi]);

Función Lemniscata

x(t) = cos(t)/(1+sin(t)^2)

y(t) = (sin(t)*cos(t))/(1+sin(t)^2)

t en [0,2pi]);

plot2d([parametric,cos(t)/(1+sin(t)^2), (sin(t)*cos(t))/(1+sin(t)^2)],[t,0,2*%pi]);

Función alas de mariposa.

exp(cos(t)) - 2 cos(4t) - sen(t/12)^5

r: (exp(cos(t))-2*cos(4*t)-sin(t/12)^5)$
plot2d([parametric, r*sin(t), r*cos(t), [t, -8*%pi, 8*%pi], [nticks, 2000]])$

EJEMPLO 3. Calcular, usando la definición de integral compleja, la
integral de 

f(z)=conjugate(z) 

a lo largo de la parte derecha de la circunferencia 

abs(z)=2:

La parametrización de la curva viene dada por 

curva(t)=(2*cos(t),2*sin(t)), 

donde t varia en [-%pi/2,%pi/2]

plot2d([[parametric, 2*cos(t), 2*sin(t), [t, -%pi/2,%pi/2], [nticks, 300]]])$

Usando la definición de integral sobre una curva, la función a integrar será
 
f(curva(t))*d/dt(curva(t)) 

en el intervalo [-%pi/2,%pi/2]

curva(t):=2*cos(t)+%i*2*sin(t);

integrando: curva(t)*diff(curva(t),t,1);

integrate(integrando, t, -%pi/2, %pi/2);

EJEMPLO 4: Calcula la integral de 

f(z)=z^2

entre los puntos 

z1=0 y z2=1+i. 

a lo largo de las siguientes curvas:

a) A través de la recta que une ambos puntos.
b) A través de la curva y=x^2 (que también pasa por ambos puntos).
c) A través de la regla de Barrow.

(a) La curva para este apartado es el segmento lineal que une z1 con z2, por tanto utilizaremos la definición correspondiente.
Definimos en primer lugar los puntos

z1:0;
z2:1+%i;

Ahora utilizamos la definición de segmento lineal

segmento(t):= (1-t)*z1 + t*z2;

Finalmente calculamos la integral mediante la fórmula correspondiente:

f(z):=z^2;
integrando:f(segmento(t))*diff(segmento(t),t);

integrate(integrando, t, 0, 1);

(b): La parametrización de la curva viene dada en este caso por 

curva(t) = (t, t^2), 

donde t varia en [0,1]

Definimos la curva

parabola(t):= t+%i*t^2;

E integramos mediante la fórmula general de la integración

integrando:f(parabola(t))*diff(parabola(t),t);

integrate(integrando, t, 0, 1);

Observamos que el resultado de (a) y (b) es el mismo a pesar de cambiar de curva. 
Esto es debido a que la función f(z)=z^2 es analítica, como podemos comprobar ya 
que verifica las ecuaciones de Cauchy-Riemann y el valor de la integral
es independiente de la trayectoria elegida, sólo de los puntos inicial y final.

(c) También podremos calcular esta integral como nos pide el usando la regla de Barrow. 
Maxima no calcula integrales definidas si los límites de integración son complejos,
por lo que procederemos a calcular la primitiva de f(z) y evaluarla en los puntos 0 y 1+i:

remvalue(all)$
f(z) := z^2;
F(z) := ''(integrate(f(z), z))$
F(z);

expand(F(1+%i)-F(0));

## Polos y ceros de funciones complejas de variable compleja

Maxima nos permite obtener los ceros y los polos de funciones complejas. 

Los ceros de una función compleja no son sino las raíces que tiene la propia función; 
mientras que los polos suelen ser las raíces del denominador (siempre que no anulen el numerador, 
porque entonces puede ser que tengamos una singularidad evitable). 

Veamos un ejemplo:

EJEMPLO 5: Vamos a definir la función
 
f(z) = (z^2+z-1)/(z^3-1.5*z^2-0.5*z-1)

y ver como podemos elegir su numerador y denominador:

remvalue(all)$
f(z):=(z^2+z-1)/(z^3-1.5*z^2-0.5*z-1);

num(f(z));

denom(f(z));

EJEMPLO 6: Vamos a calcular los ceros  y polos de la función del ejercicio 5

remvalue(all)$
f(z):=(z^2+z-1)/(z^3-1.5*z^2-0.5*z-1);

Para los ceros de f(z) usamos:

solve([f(z)=0], [z]);

O bien usando la función num

solve([num(f(z))=0], [z]);

mientras que para calcular las singularidades (polos) haremos

solve([denom(f(z))=0], [z]);

Como observamos que no hay repetición entre las raíces del numerador
y denominador, tanto los ceros como los polos son simples.

Si queremos comprobar si estos polos están, por ejemplo, en el 
interior del círculo unidad, obtendremos su módulo y preguntamos
si éste es menor que la unidad:

cabs(-(sqrt(7)*%i+1)/4);

is(%<1)

Y lo mismo para el segundo polo:

cabs((sqrt(7)*%i-1)/4);

is(%<1);

mientras que para el tercero:

cabs(2);
is(%<1);

Por tanto, los dos primeros sí que están en el interior del círculo
unidad, mientras que el tercero (z=2) está fuera.

Esta propiedad es importante cuando estudiamos la estabilidad de sistemas descritos por
ecuaciones diferenciales ordinarias.

## Singularidades

Para determinar el tipo de singularidad podemos usar la función 

limit

EJEMPLO 7: Singularidad tipo evitable:

limit(sin(z)/z,z,0);

EJEMPLO 8: Singularidad tipo polo:

limit((z-1)/(z^2+1),z,%i);

EJEMPLO 9: Singularidad tipo esencial:

limit(sin(1/z),z,0);

limit(exp(1/z),z,0);

En estos dos casos MAXIMA considera que la variable z es real, 
para obtener de forma adecuada los límites complejos hay que 
utilizar los límites iterados:

kill(all);
z:x+%i*y;
limit(limit(exp(1/z),x,0),y,0);
limit(limit(exp(1/z),y,0),x,0);
limit(limit(sin(1/z),x,0),y,0);
limit(limit(sin(1/z),y,0),x,0);

## Series de potencias

Podemos desarrollar una función en Serie de potencias en torno a un punto z0 (es decir, desarrollar f como potencias de z-z0), 
para ello se utiliza la función:

powerseries(f(z), z, z_0);

EJEMPLO 10: Si queremos desarrollar como potencias de z (es decir, tomando z0=0) la función 

g(z)=(z+1)/(z^3+4*z^2-3*z-18)

haremos

remvalue(all);
g(z):=(z+1)/(z^3+4*z^2-3*z-18);

sp: powerseries(g(z),z,0);

Notar que los índices del sumatorio no son los habituales y pueden 
causar confusión, para clarificar la expresión se utiliza la función 

niceindices 

niceindices(sp);

También es posible utilizar los índices habituales n y m

niceindicespref;
niceindicespref:[n,m]$
niceindices(powerseries(g(z),z,0));

Podemos desarrollar una función en Serie de Laurent en torno a un 
punto z0 (es decir, desarrollar f como potencias de z-z0, pudiendo
ser los exponentes de z-z0 positivos o negativos):

EJEMPLO 11: Si queremos desarrollar como serie de Laurent en potencias de 
z+3 (ya que -3 es un polo de dicha función) la anterior función g(z) 
haremos

niceindices(powerseries(g(z),z,-3));

EJEMPLO 12: También es posible para singularidades esenciales

niceindices(powerseries(exp(1/z),z,0));

niceindices(powerseries(sin(1/z),z,0));

Podemos utilizar la variable verbose para incluir información del
proceso de cálculo de la serie de potencias:

verbose:true;
niceindices(powerseries(exp(1/z),z,0));

verbose:false;

FUNCIONES RACIONALES:

Como se ha visto en clase, cada fracción de la forma 1/(z-a), con "a" cualquier número complejo,
tiene dos posibles desarrollos en potencias de z: Uno en el interior de la bola B(0,|a|) y otro en el exterior de
esa bola; es decir, hay un desarrollo para |z|<|a| y otro para |z|>|a|.

El desarrollo en potencias en cada región sería:

A) Dentro de la bola: 

niceindices(powerseries(1/(z-a),z,0));

B) En el exterior se utiliza como centro el punto del infinito.

niceindices(powerseries(1/(z-a),z,inf));

Para encontrar el desarrollo de una función racional dentro de un anillo, tenemos que proceder como en el ejemplo siguiente.


EJEMPLO 13: Sea f(z) la siguiente función:

f(z)=(z+1)/(z^3+4*z^2-3*z-18)

y buscamos su desarrollo en series de potencias dentro del anillo A(0,2,3)

f(z):=(z+1)/(z^3+4*z^2-3*z-18);

Descomponemos en fracciones simples utilizando todas las raíces

partfrac(gfactor(f(z)),z);

Después se desarrolla cada fracción, según esté en el "interior" o en el "exterior" de la región de estudio

niceindices(powerseries(-3/(25*(z+3)),z,0))+niceindices(powerseries(2/(5*(z+3)^2),z,0))+niceindices(powerseries(3/(25*(z-2)),z,inf));

## Residuos

Una vez que conocemos los polos de una función, podemos calcular de manera
sencilla sus residuos en dichos polos:

EJEMPLO 14: Si queremos calcular los residuos de la función g(z) 
en sus puntos singulares (que son 2 y -3):

kill(all);
g(z):=(z+1)/(z^3+4*z^2-3*z-18);

residue(g(z),z,2);

residue(g(z),z,-3);

No se puede utilizar la función residue, para encontrar los residuos de singularidades esenciales:

residue(exp(1/z),z,0);

Cuando al utilizar la serie de potencias

niceindices(powerseries(exp(1/z),z,0));

se puede comprobar que b1 que es el coeficiente de 1/z vale 1 (tomando n=1)

## Representación de funciones.
Varios ejemplos con plot2d.

En la Práctica 0 se describe la forma de representar gráficos con Maxima, tanto en 2D como en 3D. 

No podemos realizar gráficos de funciones complejas de variable compleja,
ya que su representación se haría en un espacio de 4 dimensiones. Sin embargo
podemos estudiar el comportamiento de estas funciones estudiando ciertas 
representaciones gráficas:

Recordemos que para representar una función real de variable real en forma explícita
se puede utilizar el comando plot2d:

EJEMPLO 15: Vamos a representar gráficamente la función y=cos(x), definiendo x en [-3pi,3pi]:

plot2d(cos(x),[x,-3*%pi,3*%pi]);

Podemos poner el nombre a los ejes y a la función que representamos:

plot2d(cos(x),[x,-3*%pi,3*%pi],[legend,"coseno"],
[xlabel,"Eje OX"], [ylabel,"Eje OY"]);

Podemos eliminar los ejes y la caja donde representamos la función:

plot2d(cos(x),[x,-3*%pi,3*%pi],[box,false]);

EJEMPLO 16: Vamos a representar gráficamente la función y=A*cos(wt+fi),
siendo A=2, la fase fi=pi/4, la frecuencia angular w=2pi/T y el 
periodo T=10^(-6). Hacerlo en el intervalo de t dado por
[-2(10^(-6)),2(10^(-6))]:

plot2d(2*cos((2*%pi/10^(-6))*t+%pi/4),
[t,-2*(10^(-6)),2*(10^(-6))]);

EJEMPLO 17: Representa gráficamente la función y=2*exp(-0.5*x),
en [-2,2]x[-1,7]:

plot2d(2*exp(-0.5*x),[x,-2,2],[y,-1,7]);

EJEMPLO 18: Representa gráficamente la parte real de la función 
compleja y=A*exp(s*t), con los datos siguientes:
t varía en [-3*(10^(-3)),3*(10^(-3))]; A=0.5*exp(i*pi/4),
s=0.5*10^3+i*2pi/10^(-3):

f(t):=(0.5*exp(%i*%pi/4))*exp((0.5*10^3+%i*2*%pi/10^(-3))*t);

plot2d(realpart(f(t)),[t,-3*(10)^(-3),3*(10)^(-3)]);

Hacemos lo mismo con su parte imaginaria:

plot2d(imagpart(f(t)),[t,-3*(10)^(-3),3*(10)^(-3)]);

o con su módulo:

plot2d(abs(f(t)),[t,-3*(10)^(-3),3*(10)^(-3)]);

Como se ha indicado antes, aunque no es posible hacer una representación de R^2 en R^2, 
sí que es posible hacerse una  idea del comportamiento de una función compleja de variable 
compleja representando de forma conjunta su módulo y su argumento.

EJEMPLO 19: Por ejemplo, si tenemos la siguiente función

remvalue(all);
z:x+%i*y;
h(z):= z^2;

Y representamos módulo y su argumento de h(z). 

plot3d(cabs(h(z)),[x,-1,1],[y,-1,1]);

plot3d(carg(h(z)),[x,-1,1],[y,-1,1]);

Observa la discontinuidad que hay a lo largo del eje
OX, que aparece debido a que por un lado el argumento es -2pi y por otro es 2pi

Repetimos el proceso con la función 1/z

remvalue(all);
z:x+%i*y;
h(z):= 1/z;
plot3d(cabs(h(z)),[x,-1,1],[y,-1,1]);

plot3d(carg(h(z)),[x,-1,1],[y,-1,1]);

## Ejercicios para practicar.

PROBLEMA 1. Dada la función f(z)=(z^2+3z)/(z^2-4):

1.1 Calcular los ceros y polos de f(z). 

1.2 Determinar si las singularidades están o no localizadas en 
el interior del círculo unidad. 

1.3 Obtener el desarrollo en serie de potencias de z.

1.4 Obtener el desarrollo en serie de Laurent como potencias de
z+2.

1.5 Obtener el valor de los residuos en sus singularidades.


PROBLEMA 2. Representa gráficamente en [-8,8]x[-0.25,1.25] la función
seno cardinal, que viene dada por f(t)=sin(pi*t)/(pi*t).


PROBLEMA 3. Representa gráficamente la función y=A*sin(wt+fi),
siendo A=-2, la fase fi=3*pi/4, la frecuencia angular w=2pi/T y el 
periodo T=10^(-4). Hacerlo en el intervalo de t dado por
[-2*(10^(-4)),2*(10^(-4))].