Resumen: Se resuelve la ecuación de Poisson con condiciones de contorno mixtas Dirichlet-Neumann. Además, veremos dos formas diferentes de definir el problema variacional. Por un lado, usando el tipo solve
que define el problema variacional y lo resuelve automáticamente. Por otro, usaremos el tipo varf
, que define el problema variacional a través de la forma bilineal y la forma lineal. El problema considerado aparece, por ejemplo, para describir el desplazamiento vertical de una membrana que ocupa un dominio bajo una fuerza que actúa sobre ella.
Dados
Observación: todos los cálculos que se hacen en esta sección son puramente formales, es decir, se supone siempre la regularidad suficiente para que todos ellos estén justificados.
Introducimos el siguiente espacio de Hilbert
El espacio natural para buscar la solución del problema
Para obtener la formulación variacional de
Teniendo en cuenta que
La formulación variacional de
Vamos a utilizar una aproximación mediante elementos finitos
con
cuya dimensión es igual al número de vértices de
donde
Tomaremos como
Tomaremos, también,
Las siguientes instrucciones definen la frontera del dominio, utilizando sus ecuaciones paramétricas y la dibujan. Obsérvese que hemos asignado las etiquetas label = C1
y label = C2
a las dos fronteras, respectivamente.
// Definicion de la frontera del dominio
int C1 = 1, C2 = 2;
border Gamma1(t= 0, pi){x = cos(t); y = 2*sin(t); label = C1; };
border Gamma2(t= pi, 2*pi){x = cos(t); y = sin(t); label = C2; };
Declaramos primero una variable tipo mesh
y después construimos una triangulación del dominio, tomando 50 segmentos sobre
// Construccion de la triangulacion
mesh Th;
Th = buildmesh( Gamma1(50) + Gamma2(30));
plot(Th, wait = 1);
Definimos el espacio de elementos finitos que vamos a utilizar sobre
// Definicion del espacio de EF
fespace Wh(Th, P1);
solve
Se va a usar aquí el tipo solve
que es muy similar a problem
, que ya hemos usado en otros ejemplos, con la diferencia de que define el problema y lo resuelve automáticamente.
Consideramos el caso con condición de Dirichlet homogénea, es decir
Definimos primero la función del segundo miembro y declaramos las variables del problema.
Se recuerda que en la definición del problema variacional con FreeFEM la ecuación se escribe en forma homogénea (segundo miembro = 0).
// Definicion de la funcion del segundo miembro
func f = 1;
// Declaracion de las variables del problema (elementos de Wh)
Wh u, v;
// Condicion de contorno de Dirichlet homogena y de Neumann no homogenea
func g = 10;
solve Membrana(u, v) =
int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v))
- int2d(Th)( f*v )
- int1d(Th, C2)(g*v)
+ on(C1, u = 0);
// Representacion de la solucion
plot(u, nbiso = 40, cmm ="Condicion de Neumann NO homogenea du/dn = 10", wait = 1);
Aquí, int1d
es la función de FreeFEM que sirve para calcular integrales de línea, en este caso sobre la parte de frontera con etiqueta ilabel
.
int1d(Th, ilabel)( expresion )
// Definicion de la forntera del dominio
int C1 = 1, C2 = 2;
border Gamma1(t= 0, pi){x = cos(t); y = 2*sin(t); label = C1; };
border Gamma2(t= pi, 2*pi){x = cos(t); y = sin(t); label = C2; };
// Triangulacion
mesh Th;
Th = buildmesh( Gamma1(50) + Gamma2(30));
// Definicion de la funcion del segundo miembro
func f = 1;
// Definicion de la condicion de contorno
func g = 10;
// Espacio de elementos finitos
fespace Wh(Th, P1);
Wh u, v;
// Resolucion automatica con solve
solve Membrana(u, v) =
int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v))
- int2d(Th)( f*v )
- int1d(Th, C2)(g*v)
+ on(C1, u = 0);
// Representacion grafica
plot(u, nbiso = 40, cmm="Condicion de Neumann NO homogenea du/dn = 10", wait = 1);
varf
Vamos a considerar ahora otra manera de definir y resolver el problema variacional: usando el tipo varf
, construyendo "a mano" la matriz y el segundo miembro y resolviendo el sistema lineal resultante.
Para la formulación del problema variacional, comenzaremos por definir la forma bilineal y la forma lineal asociadas. En este caso:
Con estas definiciones, la formulación variacional
Vamos a considerar el caso en que
Para definir las formas bilineal y lineal se usa el tipo varf
varf a(u,v) = expresion(u, v)
donde, por convenio, la primera variable, u
, es la incógnita y la segunda, v
, es la función test. Si en expresion(u,v)
no aparece la variable u
, se entiende que se está definiendo una forma lineal.
En las definiciones de
xxxxxxxxxx
// Datos del problema: f y u_0
func f = 1;
func u0 = abs(x);
// Declaracion de las variables del problema (elementos de Wh)
Wh u, v;
// Definicion de la forma bilineal
varf a(u,v) = int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v))
+ on(C1, u = u0);
// Definicion de la forma lineal
varf l(unused, v) = int2d(Th)( f*v )
+ on(C1, unused = u0);
Construimos ahora la matriz del sistema, definiéndola como la matriz asociada a la forma bilineal a(u,v)
:
donde matrix
, que genera matrices huecas con almacenamiento sparse y contiene ya la penalización debida al bloqueo.
// Matriz asociada a la forma bilineal
matrix A = a(Wh, Wh);
A continuación construimos el segundo miembro del sistema
Cada elemento w[]
, de manera que w[][i]
contiene el valor de la función
Para generar el vector asociado a la forma lineal l(v)
antes definida, hay que poner por convenio l(0, Wh)
. Internamente, esto hará que no se tenga en cuenta la variable u
.
// Segundo miembro
Wh F;
F[] = l(0, Wh); // F[] es el vector asociado al elemento F de Wh
A continuación, resolvemos el sistema lineal resultante. Para ello se utiliza el operador ^-1
que "simboliza" la matriz inversa, de manera que A^-1*b
, siendo b
un vector, representa A^-1
no es en realidad la inversa de A
, no genera una matriz.
xxxxxxxxxx
// Resolucion del sistema lineal
u[] = A^-1 * F[]; // u[] es el vector asociado al elemento u de Wh
Por último, representamos gráficamente la solución obtenida.
xxxxxxxxxx
// Representacion de la sulucion
plot(u, nbiso = 40, cmm = "Condicion de Neumann homogenea du/dn = 0", wait = 1);
Resolver el problema varf
.
xxxxxxxxxx
int C1 = 98, C2 = 99;
border Gamma1(t= 0, pi){x = cos(t); y = 2*sin(t); label = C1; };
border Gamma2(t= pi, 2*pi){x = cos(t); y = sin(t); label = C2; };
// Triangulacion
mesh Th;
Th = buildmesh( Gamma1(50) + Gamma2(30));
plot(Th, wait = 1);
// Datos del problema
func f = 1;
func u0 = abs(x);
// Espacio de elementos finitos
fespace Wh(Th, P1);
// Declaracion de las variables del problema
Wh u, v;
// Definicion de la forma bilineal
varf a(u,v) = int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v))
+ on(C1, u = u0);
// Definicion de la forma lineal
varf l(unused, v) = int2d(Th)( f*v )
+ on(C1, unused = u0);
// Matriz asociada a la forma bilineal
matrix A = a(Wh, Wh);
// Segundo miembro
Wh F;
F[] = l(0, Wh); // F[] es el vector asociado al elemento F de Wh
// Resolucion del sistema lineal
u[] = A^-1 * F[]; // u[] es el vector asociado al elemento u de Wh
// Representacion de la sulucion
plot(u, nbiso = 40, cmm = "Condicion de Neumann homogenea du/dn = 0", wait = 1);
Anna Doubova - Rosa Echevarría - Dpto. EDAN - Universidad de Sevilla