Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Freefem Doc Español

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 377

12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K.

Oh

Página 1

Tercera edición, versión 3.58-1

http://www.freefem.org/ff++

F. Hecht, O. Piro
A. Le Hyaric, K. Oh

Laboratoire Jacques-Louis Lions, Universidad Pierre et Marie Curie, París

https://translate.googleusercontent.com/translate_f 1/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 3
2

FreeFem ++ Tercera edición, versión 3.58-1

http://www.freefem.org/ff++
Frédéric Hecht1 2
mailto: frederic.hecht@upmc.fr
https://www.ljll.math.upmc.fr/˜hecht

En colaboración con:
• Syl an Auliac , mailto: auliac@ann.jussieu.fr , http://www.ann.jussieu.fr/
auliac es estudiante de doctorado en LJLL, hace toda la nueva interfaz de optimización con nlopt, ipopt,
cmaes, ...

• Olivier Pironneau , mailto: olivier.pironneau@upmc.fr , http: //www.ann.jussieu.


fr / pironneau Olivier Pironneau es profesor de análisis numérico en la universidad de
Paris VI y en LJLL. Sus contribuciones científicas se encuentran en métodos numéricos para fluidos. Él es
miembro del Institut Universitaire de France y de la Academia de Ciencias de Francia

• Jacques Morice , mailto: morice@ann.jussieu.fr. Jacaues Morice es Post-Doct en


LJLL. Su trabajo es Tesis en la Universidad de Burdeos I sobre el método rápido multipolar (FMM). En
en esta versión, realiza la generación de malla de las tres dimensiones y el acoplamiento con el software medit.
• Antoine Le Hyaric , mailto: lehyaric@ann.jussieu.fr , http: //www.ann.jussieu.
fr / ˜lehyaric / Antoine Le Hyaric es un ingeniero de investigación del ”Centre National de la
Recherche Scientifique ”(CNRS) en LJLL. Es un experto en ingeniería de software para ciencia
aplicaciones interesantes. Ha aplicado sus habilidades principalmente a la simulación electromagnética, paralela
computación y visualización tridimensional.

• Kohji Ohtsuka , mailto: ohtsuka@hkg.ac.jp, http://www.comfos.org/ Kohji Oht-


suka es profesor en la Universidad Hiroshima Kokusai Gakuin, Japón y presidente de la
Academia y Sociedad Mundial de Ciencia e Ingeniería, capítulo de Japón. Su investigación está en
dinámica de fracturas, modelado y computación.

• Pierre Jolivet , mailto: pierre.jolivet@enseeiht.fr , http: //jolivet.perso.


enseeiht.fr/ es investigador del CNRS, hizo la interfaz MPI con PETSc, HPDDM ...

Agradecimientos Estamos muy agradecidos a l'École Polytechnique (Palaiseau, Francia) por imprimir el
segunda edición de este manual (http://www.polytechnique.fr), y a l'Agence Nationale de
la Recherche (París, Francia) por la financiación de la extensión de FreeFem ++ a un sistema tridimensional paralelo.
versión (http://www.agence-nationale-recherche.fr) Référence: ANR-07-CIS7-002-
01.
1 Laboratoire Jacques-Louis Lions, Universidad Pierre et Marie Curie, París
2 Projet Alpines, Inria Rocquencourt.

Página 4
4

https://translate.googleusercontent.com/translate_f 2/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 5

Contenido

https://translate.googleusercontent.com/translate_f 3/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

1. Introducción 13
1.1 Instalación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.1.1 Para todos:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.1.2 Para los profesionales: instalación desde fuentes . . . . . . . . . . . . . . . . . 15
1.2 Cómo utilizar FreeFem ++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.3 Variables de entorno y el archivo init . . . . . . . . . . . . . . . . . . . . . 20
1.4 Historia. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2 Primeros pasos 23
2.0.1 FEM de FreeFem ++: ¿cómo funciona? . . . . . . . . . . . . . . . 24
2.0.2 Algunas características de FreeFem ++. . . . . . . . . . . . . . . . . . . . . 29
2.1 El ciclo de desarrollo: Editar – Ejecutar / Visualizar – Revisar. . . . . . . . . . . . . 29

3 Aprendiendo con ejemplos 31


3.1 Membranas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2 Intercambiador de calor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.3 Acústica. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.4 Conducción térmica. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.4.1 Axisimetría: Varilla 3D de sección circular. . . . . . . . . . . . . . 41
3.4.2 Un problema no lineal: la radiación. . . . . . . . . . . . . . . . . . . . 42
3.5 Flujo y efectos térmicos de las aspas del ventilador irrotacional. . . . . . . . . . . . . . . . 42
3.5.1 Convección de calor alrededor del perfil aerodinámico. . . . . . . . . . . . . . . . . . . 44
3.6 Convección pura: la colina giratoria. . . . . . . . . . . . . . . . . . . . . . 45
3.7 El sistema de elasticidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.8 El sistema de Stokes para fluidos. . . . . . . . . . . . . . . . . . . . . . . . . 51
3.9 Un algoritmo de proyección para las ecuaciones de Navier-Stokes . . . . . . . . . . . 52
3.10 Método de Newton para las ecuaciones de Steady Navier-Stokes. . . . . . . . . . . . 56
3.11 Un gran problema de fluidos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.12 Un ejemplo con números complejos. . . . . . . . . . . . . . . . . . . . . . 62
3.13 Control óptimo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.14 Un flujo con choques. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sesenta y cinco
3.15 Clasificación de las ecuaciones . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.16 Optimización del esquema dependiente del tiempo para la ecuación de calor. . . . . . . . . . . . . . . 70
3.17 Tutorial para escribir un solucionador de Stokes transitorio en forma matricial . . . . . . . . . . . 71

Página 6
6 CONTENIDO

4 sintaxis 73
4.1 Tipos de datos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.2 Lista de tipos principales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.3 Variables globales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.4 Comandos del sistema. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4.5 Aritmética. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.6 expresión de cadena. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.7 Funciones de una variable. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.8 Funciones de dos variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.8.1 Fórmula. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.8.2 Funciones FE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.9 Matrices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.9.1 Matrices con dos índices enteros versus matrices . . . . . . . . . . . . 91
4.9.2 Construcción y configuración de la matriz. . . . . . . . . . . . . . . . . . . . . 92
4.9.3 Operaciones con matrices. . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

https://translate.googleusercontent.com/translate_f 4/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
4.9.4 Otras matrices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
4.10 Mapear matrices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.11 Bucles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.12 Entrada / Salida. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
4.12.1 Argumentos del script. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.13 preprocesador. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.14 Manejo de excepciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

5 generación de mallas 109


5.1 Comandos para la generación de mallas. . . . . . . . . . . . . . . . . . . . . . . . . 109
5.1.1 Cuadrado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
5.1.2 Borde. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
5.1.3 Multiborde. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.1.4 Estructuras de datos y declaraciones de lectura / escritura para una malla . . . . . . . 114
5.1.5 Conectividad de malla y datos. . . . . . . . . . . . . . . . . . . . . . . 116
5.1.6 La palabra clave "triangular". . . . . . . . . . . . . . . . . . . . . . . . 119
5.2 Espacios FEM de contorno construidos como mallas vacías. . . . . . . . . . . . . . . . 120
5.3 Remallado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
5.3.1 Movemesh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
5.4 Triangulación regular: hTriangle. . . . . . . . . . . . . . . . . . . . . . . 123
5.5 Adaptmesh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.6 Trunc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
5.7 Splitmesh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
5.8 Ejemplos de mallado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
5.9 Cómo cambiar la etiqueta de elementos y elementos de borde de una malla . . . . . 135
5.10 Malla en tres dimensiones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.10.1 cubo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.10.2 Lectura / escritura de declaraciones para una malla en 3D. . . . . . . . . . . . . . . . 137
5.10.3 TeGen: un generador de malla tetraédrica. . . . . . . . . . . . . . . . . 139
5.10.4 Reconstruir / refinar una malla tridimensional con TetGen . . . . . . 143
5.10.5 Malla móvil en tres dimensiones. . . . . . . . . . . . . . . . . . . . 144
5.10.6 Malla de capas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

Página 7
CONTENIDO 7

5.11 Ejemplos de mallado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149


5.11.1 Construya una malla 3D de un cubo con un globo. . . . . . . . . . . . . . . . 151
5.12 La solución de salida formatea .sol y .solb . . . . . . . . . . . . . . . . . . . 153
5.13 medit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
5.14 Mshmet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
5.15 FreeYams. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
5,16 mmg3d. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
5.17 Un primer proceso de adaptación de la malla de isótopos 3d. . . . . . . . . . . . . . . . . . . 164
5.18 Construya una malla 2D a partir de una isolina. . . . . . . . . . . . . . . . . . . . . . . . . . 165

6 elementos finitos 169


6.1 Uso de "fespace" en 2d. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
6.2 Uso de fespace en 3d. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
6.3 Elementos finitos de Lagrange. . . . . . . . . . . . . . . . . . . . . . . . . . . 176
6.3.1 Elemento P0. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
6.3.2 Elemento P1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
6.3.3 Elemento P2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
6.4 Elemento no conforme P1. . . . . . . . . . . . . . . . . . . . . . . . . . . 178
6.5 Otro espacio FE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
6.6 Función FE con valor vectorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
6.6.1 Elemento Raviart-Thomas. . . . . . . . . . . . . . . . . . . . . . . . . 180
6.7 Un interpolador rápido de elementos finitos. . . . . . . . . . . . . . . . . . . . . . . 182

https://translate.googleusercontent.com/translate_f 5/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
6.8 Palabras clave: Problema
6.8.1 Forma y solución.
débil y condición . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 185
de contorno. 184
6.9 Parámetros que afectan la resolución y el problema. . . . . . . . . . . . . . . . . . . 186
6.10 Definición del problema. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
6.11 Integración numérica. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
6.12 Forma variacional, matriz dispersa, vector de datos PDE. . . . . . . . . . . . . . 194
6.13 Matriz de interpolación. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
6.14 Conectividad de elementos finitos. . . . . . . . . . . . . . . . . . . . . . . . . . . 201

7 Visualización 203
7.1 Trazar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
7.2 enlace con gnuplot. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
7.3 enlace con medit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

8 algoritmos y optimización 211


8.1 gradiente conjugado / GMRES. . . . . . . . . . . . . . . . . . . . . . . . . . . 211
8.2 Algoritmos para optimización sin restricciones. . . . . . . . . . . . . . . . . . 214
8.2.1 Ejemplo de utilización para BFGS o CMAES. . . . . . . . . . . . . . 214
8.3 IPOPT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
8.3.1 Breve descripción del algoritmo. . . . . . . . . . . . . . . . . . . . 216
8.3.2 IPOPT en FreeFem ++. . . . . . . . . . . . . . . . . . . . . . . . . 217
8.4 Algunos ejemplos breves utilizando IPOPT. . . . . . . . . . . . . . . . . . . . . . . 222
8.5 Superficie mínima restringida 3D con IPOPT. . . . . . . . . . . . . . . . . . 224
8.5.1 Expresiones de área y volumen. . . . . . . . . . . . . . . . . . . . . . . 224
8.5.2 Derivados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

Página 8
8 CONTENIDO

8.5.3 El problema y su guión:. . . . . . . . . . . . . . . . . . . . . . . 225


8.6 Los optimizadores nlOpt. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
8.7 Optimización con MPI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

9 modelos matemáticos 235


9.1 Problemas estáticos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
9.1.1 Película de jabón. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
9.1.2 Electrostática. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
9.1.3 Aerodinámica. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
9.1.4 Estimación de errores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
9.1.5 Condiciones de contorno periódicas. . . . . . . . . . . . . . . . . . . . . 242
9.1.6 Problemas de Poisson con condiciones de contorno mixtas. . . . . . . . . . . 245
9.1.7 Poisson con elemento finito mixto. . . . . . . . . . . . . . . . . . . 247
9.1.8 Indicador de adaptación métrica y error residual. . . . . . . . . . . . . 248
9.1.9 Adaptación mediante indicador de error residual. . . . . . . . . . . . . . . . 250
9.2 Elasticidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
9.2.1 Mecánica de fracturas. . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
9.3 Problemas estáticos no lineales. . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
9.3.1 Algoritmo de Newton-Raphson. . . . . . . . . . . . . . . . . . . . . . . 260
9.4 Problemas de valores propios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
9.5 Problemas de evolución. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
9.5.1 Teoría matemática sobre aproximaciones en diferencia de tiempo. . . . . . . 267
9.5.2 Convección. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
9.5.3 Ecuación 2D de Black-Scholes para una opción de venta europea . . . . . . . . 271
9.6 Ecuación de Navier-Stokes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
9.6.1 Stokes y Navier-Stokes. . . . . . . . . . . . . . . . . . . . . . . . . 272
9.6.2 Algoritmo de Uzawa y gradientes conjugados. . . . . . . . . . . . . . . 277
9.6.3 NSUzawaCahouetChabart.edp. . . . . . . . . . . . . . . . . . . . . . 278

https://translate.googleusercontent.com/translate_f 6/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
9.7 Desigualdad variacional. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
9.8 Descomposición de dominios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
9.8.1 Esquema de superposición de Schwarz. . . . . . . . . . . . . . . . . . . . . . . . . 283
9.8.2 Esquema de no superposición de Schwarz. . . . . . . . . . . . . . . . . . . . . . 285
9.8.3 Schwarz-gc.edp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
9.9 Problema de acoplamiento de fluidos / estructuras. . . . . . . . . . . . . . . . . . . . . . . 289
9.10 Problema de transmisión. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
9.11 Problema de límite libre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
9.12 Elasticidad no lineal (nolinear-elas.edp) . . . . . . . . . . . . . . . . . . . . . 297
9.13 Materiales neohookeanos comprimibles: soluciones computacionales . . . . . . . 301
9.13.1 Notación. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
9.13.2 Un material comprimible Neo-Hookean. . . . . . . . . . . . . . . . . 302
9.13.3 Un enfoque para la implementación en FreeFem ++. . . . . . . . . . . 303
9.14 Modos de galería de susurros. . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
9.14.1 Ecuación de onda para los WGM. . . . . . . . . . . . . . . . . . . . . . 304
9.15 Formulación débil. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
9.15.1 Un ejemplo de esfera dieléctrica con FreeFem ++ . . . . . . . . . . . . 304

Página 9
CONTENIDO 9

Versión en paralelo de 10 MPI 305


10.1 palabras clave MPI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
10.2 Constantes MPI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
10.3 Constructor MPI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
10.4 Funciones MPI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
10.5 Operador de comunicador MPI. . . . . . . . . . . . . . . . . . . . . . . . . . . 306
10.6 Ejemplo de Schwarz en paralelo. . . . . . . . . . . . . . . . . . . . . . . . . . . 307
10.6.1 Ejemplo de Schwarz paralelo verdadero. . . . . . . . . . . . . . . . . . . . . . 309

11 solucionadores dispersos paralelos 315


11.1 Uso de solucionadores dispersos paralelos en FreeFem ++ . . . . . . . . . . . . . . . . . 315
11.2 Solucionador directo disperso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
11.2.1 Solucionador de MUMPS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
11.2.2 Solucionador distribuido SuperLU. . . . . . . . . . . . . . . . . . . . . . . . 321
11.2.3 Solucionador de Pastix. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
11.3 Solucionador iterativo disperso paralelo . . . . . . . . . . . . . . . . . . . . . . . . . . 325
11.3.1 solucionador de pARMS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
11.3.2 Interfaz con HIPS. . . . . . . . . . . . . . . . . . . . . . . . . . 330
11.3.3 Interfaz con HYPRE. . . . . . . . . . . . . . . . . . . . . . . . . 332
11.3.4 Conclusión. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
11.4 Descomposición del dominio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
11.4.1 Comunicadores y grupos. . . . . . . . . . . . . . . . . . . . . . . 338
11.4.2 Proceso. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
11.4.3 Comunicadores de puntos a puntos. . . . . . . . . . . . . . . . . . . . . 339
11.4.4 Operaciones globales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
11.5 Solucionadores HPDDM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
11.5.1 Problema dependiente del tiempo. . . . . . . . . . . . . . . . . . . . . . . . . 342
11.5.2 Vectores distribuidos en HPDDM. . . . . . . . . . . . . . . . . . . . . 343

12 archivos de malla 345


12.1 Estructura de datos de malla de archivos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
12.2 bb Tipo de archivo para soluciones de tienda . . . . . . . . . . . . . . . . . . . . . . . . . 346
12.3 Tipo de archivo BB para soluciones de tienda. . . . . . . . . . . . . . . . . . . . . . . . 346
12.4 Archivo métrico. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
12.5 Lista de mallas AM FMT, AMDBA. . . . . . . . . . . . . . . . . . . . . . . 347

13 Adición de un nuevo elemento finito 351


https://translate.googleusercontent.com/translate_f 7/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
13.1 Algunas notaciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
13.2 ¿Qué clase agregar? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352

Una tabla de notaciones 357


A.1 Generalidades. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
A.2 Conjuntos, mapeos, matrices, vectores. . . . . . . . . . . . . . . . . . . . . . . . 357
A.3 Números. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
A.4 Cálculo diferencial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
A.5 Mallas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
A.6 Espacios de elementos finitos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359

Página 10
10 CONTENIDO

B gramática 361
B.1 La gramática del bisonte. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
B.2 Tipos de lenguajes y reparto. . . . . . . . . . . . . . . . . . . . . . 365
B.3 Todos los operadores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365

C Enlace dinámico 371


C.1 Un primer ejemplo myfunction.cpp. . . . . . . . . . . . . . . . . . . . . . . . . 371
C.2 Ejemplo: Transformada rápida discreta de Fourier. . . . . . . . . . . . . . . . . . . 374
C.3 Módulo de carga para el método de volumen finito P0-P1 de Dervieux. . . . . . . . . . . 376
C.4 Más sobre la adición de un nuevo elemento finito. . . . . . . . . . . . . . . . . . . . . . 379
C.5 Agregue un nuevo solucionador disperso. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382

Complemento D 387
D.1 gsl. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
D.2 ffrandom. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Código de acoplamiento D.3 con FreeFem ++. . . . . . . . . . . . . . . . . . . . . . . . . 395

E Palabras clave 407

https://translate.googleusercontent.com/translate_f 8/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 11

Prefacio

Fruto de un largo proceso de maduración, freefem, en su último avatar, FreeFem ++, es un alto nivel
entorno de desarrollo integrado (IDE) para resolver numéricamente ecuaciones diferenciales parciales
ciones (PDE) en dimensión 2 y 3. Es la herramienta ideal para enseñar el método de elementos finitos
pero también es perfecto para la investigación para probar rápidamente nuevas ideas o multifísicas y complejas
aplicaciones.

FreeFem ++ tiene un generador de malla automático avanzado, capaz de adaptarse a posteriori


tación; Tiene un solucionador elíptico de propósito general interconectado con algoritmos rápidos como el
método multi-frontal UMFPACK, SuperLU, MUMPS. Problemas hiperbólicos y parabólicos
se resuelven mediante algoritmos iterativos prescritos por el usuario con el lenguaje de alto nivel de
FreeFem ++. Tiene varios elementos finitos triangulares, incluidos elementos discontinuos.
Finalmente, todo está ahí en FreeFem ++ para preparar informes de calidad de la investigación: pantalla a color
en línea con zoom y otras funciones e impresiones PostScript.

Este manual está dirigido a estudiantes de máster, investigadores de cualquier nivel y


ingenieros (incluida la ingeniería financiera) con cierta comprensión de los métodos variacionales
para ecuaciones diferenciales parciales.

11

https://translate.googleusercontent.com/translate_f 9/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Pagina 12
12 CONTENIDO

Página 13

https://translate.googleusercontent.com/translate_f 10/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Capítulo 1

Introducción

Una ecuación diferencial parcial es una relación entre una función de varias variables y su
(Derivadas parciales. Muchos problemas en física, ingeniería, matemáticas e incluso banca.
se modelan mediante una o varias ecuaciones diferenciales parciales.

FreeFem ++ es un software para resolver estas ecuaciones numéricamente. Como su nombre lo indica, es
un software gratuito (consulte los derechos de autor para obtener todos los detalles) basado en el método de elementos finitos; eso
no es un paquete, es un producto integrado con su propio lenguaje de programación de alto nivel.
Este software se ejecuta en todos los sistemas operativos UNIX (con g ++ 3.3 o posterior y OpenGL), en Windows XP,
Vista y 7,8,10 y en MacOS 10 intel

Además, FreeFem ++ es altamente adaptable. Muchos fenómenos involucran varios sistemas acoplados
tems, por ejemplo: interacciones fluido-estructura, fuerzas de Lorentz para fundición de aluminio y
Los problemas océano-atmósfera son tres de esos sistemas. Estos requieren diferentes elementos finitos
aproximaciones y grados polinomiales, posiblemente en diferentes mallas. Algunos algoritmos como
El método de descomposición de dominio de Schwarz también requiere la interpolación de datos en múltiples mallas
dentro de un programa. FreeFem ++ puede manejar estas dificultades, es decir, elemento finito arbitrario
espacios en mallas bidimensionales arbitrarias no estructuradas y adaptadas.

Las características de FreeFem ++ son:

• Descripción del problema (valor real o complejo) por sus formulaciones variacionales, con
acceso a los vectores y matrices internos si es necesario.

• Multi-variables, multi-ecuaciones, bidimensionales y tridimensionales estáticas o de tiempo


sistemas acoplados dependientes, lineales o no lineales; sin embargo, el usuario debe describir
los procedimientos iterativos que reducen el problema a un conjunto de problemas lineales.

• Entrada geométrica sencilla mediante descripción analítica de límites por piezas; sin embargo esto
parte no es un sistema CAD; por ejemplo, cuando dos límites se cruzan, el usuario debe
especificar los puntos de intersección.

• Generador automático de mallas, basado en el algoritmo Delaunay-Voronoi; el punto interior


la densidad es proporcional a la densidad de puntos en los límites [ 11] .

13

Página 14
14 CAPÍTULO 1 INTRODUCCIÓN

• Adaptación de malla anisotrópica basada en métricas. La métrica se puede calcular automáticamente


del hessiano de cualquier función FreeFem ++ [13 ] .

• Lenguaje de entrada mecanografiado fácil de usar de alto nivel con un álgebra analítica y finita
funciones de los elementos.

• Múltiples mallas de elementos finitos dentro de una aplicación con interpolación automática de

https://translate.googleusercontent.com/translate_f 11/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
datos sobre diferentes mallas y posible almacenamiento de las matrices de interpolación.
• Una gran variedad de elementos finitos triangulares: elementos lagrangianos cuadráticos lineales
y más, elementos P1 discontinuos y Raviart-Thomas, elementos de un no escalar
type, el mini-elemento, ... (pero no cuadrángulos).

• Herramientas para definir formulaciones discontinuas de elementos finitos de Galerkin P0, P1dc, P2dc
y palabras clave: jump, mean, intalledges.

• Una gran variedad de solucionadores lineales directos e iterativos (LU, Cholesky, Crout, CG, GM-
RES, UMFPACK, MUMPS, SuperLU, ...) y solucionadores de autovalores y autovectores
(ARPARK).

• Velocidad de ejecución casi óptima (en comparación con las implementaciones de C ++ compiladas).
gramatizado directamente).

• Gráficos en línea, generación de .txt, .eps, .gnu, archivos de malla para mayor manipulación
laciones de datos de entrada y salida.

• Muchos ejemplos y tutoriales: problemas elípticos, parabólicos e hiperbólicos, Navier-


Flujos de Stokes, elasticidad, interacciones de estructuras fluidas, descomposición del dominio de Schwarz
método, problema de valor propio, indicador de error residual, ...

• Una versión paralela que usa mpi

1.1 Instalación

1.1.1 Para todos:


Primero abra la siguiente página web

http://www.freefem.org/ff++/

Y elija su plataforma: Linux, Windows, MacOS X, o vaya al final de la página para obtener
la lista completa de descargas.

Observación 1: los binarios están disponibles para Microsoft Windows, Apple Mac OS X y algunos Linux
sistemas.

Instale haciendo doble clic en el archivo apropiado, bajo linux y MacOS el archivo de instalación se vuelve a
específicamente en el directorio / usr / local / bin, / usr / local / share / freefem ++, / usr / local / lib / ff ++

Página 15
1.1. INSTALACIÓN 15

Instalación de binarios de Windows Primero descargue el ejecutable de instalación de Windows, luego doble
Pinchalo. para instalar FreeFem ++. En la mayoría de los casos, simplemente responda sí (o escriba return) a todos
preguntas. De lo contrario, en las ventanas de tareas adicionales, marque la casilla "Agregar aplicación
directorio a la ruta del sistema a la ruta del sistema ". Esto es necesario, de lo contrario, el programa
No se encontrará ffglut.exe.
A estas alturas, debería tener dos nuevos iconos en su escritorio:

• FreeFem ++ (VERSION) .exe la aplicación FreeFem ++.

• FreeFem ++ (VERSION) Examples un enlace a la carpeta de ejemplos FreeFem ++.

donde (VERSION) es la versión de los archivos (por ejemplo 3.3-0-P4).


Por defecto, los archivos instalados están en

https://translate.googleusercontent.com/translate_f 12/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
C: \ Archivos de programa \ FreeFem ++

En este directorio, tiene todos los archivos .dll y otras aplicaciones: FreeFem ++ - nw.exe, ffglut.exe,
... la aplicación FreeFem ++ sin ventanas gráficas.

La sintaxis de las herramientas de línea de comandos es la misma que la de FreeFem.exe.

Instalación de binarios de MacOS X Descargue el archivo de versión binaria de MacOS X, extraiga todos los archivos
con un doble clic en el icono del archivo, vaya al directorio y ponga el FreeFem + .app
aplicación en el directorio / Aplicaciones. Si desea un acceso de terminal a FreeFem ++
simplemente copie el archivo FreeFem ++ en un directorio de su variable de entorno de shell $ PATH.
Si desea iniciar automáticamente la aplicación FreeFem ++., Haga doble clic en el icono de un archivo .edp.
En el buscador, elija un .edp en el directorio examples ++ - tutorial, por ejemplo, seleccione
menú Archivo -> Obtener información un cambio Abrir con: (elija la aplicación FreeFem ++.) y haga clic en
en el botón cambiar todo ....

A dónde ir desde aquí Un entorno integrado llamado FreeFem ++ - cs, escrito por An-
toine Le Hyaric, se proporciona con FreeFem ++. A menos que desee perfilar ahora su propio
entorno de desarrollo, puede pasar al siguiente párrafo "Cómo utilizar FreeFem ++".

1.1.2 Para los profesionales: instalación desde fuentes


Esta sección es para aquellos que, por alguna razón, no desean utilizar los binarios y, por lo tanto, necesitan
para recompilar FreeFem ++ o instalarlo desde el código fuente:

El archivo de documentación: La documentación también es de código abierto; para regenerarlo tu


necesita un entorno L A TEX capaz de compilar un archivo CVS; bajo MS-Windows
tienes que usar mingw / msys

http://www.mingw.org

y en MacOS X hemos utilizado las herramientas de desarrollo de Apple "Xcode" y L A TEX de http:
//www.ctan.org/system/mac/texmac.

Página 16
dieciséis CAPÍTULO 1 INTRODUCCIÓN

El archivo de C ++: FreeFem ++ debe compilarse desde el archivo de origen, como se indica
en

http://www.freefem.org/ff++/index.htm

Para extraer archivos del archivo comprimido freefem ++ - (VERSION) .tar.gz a una dirección
tory llamado

freefem ++ - (VERSIÓN)

ingrese los siguientes comandos en una ventana de shell:

tar zxvf freefem ++ - (VERSIÓN) .tar.gz


cd freefem ++ - (VERSIÓN)

Para compilar e instalar FreeFem ++, simplemente siga los archivos INSTALL y README. La
Se producen los siguientes programas, dependiendo del sistema que esté ejecutando:

1. FreeFem ++, versión estándar, con una interfaz gráfica basada en GLUT / OpenGL
(use la herramienta de visualización ffglut) o no solo agregue el parámetro -nw.

2. ffglut las herramientas de visualización a través de una tubería de freefem ++ (observación: si ffglut no es
en la ruta del sistema, no tendrá trazado)

https://translate.googleusercontent.com/translate_f 13/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
3. FreeFem ++ - nw, solo salida de trazado postscript y ffmedit (versión por lotes, sin gráficos
windows a través de ffglut)

4. FreeFem ++: mpi, versión paralela, solo salida postscript, pero puede usar el shell
guión como

(a) ff-mpirun -np nbproc mympiscript.edp ## sin gráfico

(b) ff-mpirun -np nbproc mympiscript.edp -glut ffglut ## con


gráfico
(c) ff-mpirun -np nbproc mympiscript.edp -glut parámetros de ffglut
## con parámetros gráficos y de script
(d) ff-mpirun -np nbproc mympiscript.edp -glut ffglut ## con gráfico

donde nbproc en el número de inicio del proceso.

5. /Applications/FreeFem++.app, la aplicación CoCoa MacOSX de arrastrar y soltar-


ción

6. bamg, el generador de mallas bamg

7. cvmsh2, un convertidor de archivos de malla

8. drawbdmesh, un visor de archivos de malla

9. ffmedit la versión freefem ++ del software medit (gracias a P. Frey)

La sintaxis de las herramientas FreeFem ++, FreeFem ++ - nw, FreeFem ++ - mpi, en la línea de comandos
están

Página 17
1.1. INSTALACIÓN 17

• FreeFem ++ [-?] [-V nn] [-fglut file1] [-glut file2] [-f] edpfilepath donde
la

• o FreeFem ++ - nw -? [-v nn] [-fglut file1] [-glut file2] [-f] edpfilepath donde
la

-? mostrar el uso.

-fglut nombre de archivo para almacenar todos los datos del gráfico en el nombre de archivo del archivo y para reproducirlo
ffglut nombre de archivo.
-glut ffglutprogam para cambiar el programa del visualizador.

-nw no hay llamada a ffglut y medit


-v nn establece el nivel de verbosidad en nn antes de la ejecución del script.
-ne sin salida de script edp

-Espere esperar una devolución en la ventana de texto antes de cerrar FreeFem ++


-nowait esperar una devolución en la ventana de texto antes de cerrar FreeFem ++

-ne sin salida de script edp


-cd Cambiar directorio a script dir (la ruta del script debe ser global)
si no hay ruta de archivo, aparece un cuadro de diálogo para elegir el archivo edp en el sistema de Windows.

La notación [] significa "opcional".

Observación 2 En la mayoría de los casos, puede establecer el nivel de salida (verbosidad) en el valor nn agregando
los parámetros -v nn en la línea de comando.

Como prueba de instalación, en Unix: vaya al directorio examples ++ - tutorial y ejecute


FreeFem ++ en el script de ejemplo LaplaceP1.edp con el comando:

https://translate.googleusercontent.com/translate_f 14/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

FreeFem ++ LaplaceP1.edp

Si está utilizando nedit como editor de texto, haga una vez nedit -import edp.nedit to
tienen sintaxis de coloración para sus archivos .edp.

Vincular con otros editores de texto

formulario emacs https://www.gnu.org/s/emacs, puede descargar freefem ++ - modo


aquí : https://github.com/rrgalvan/freefem-mode y siga las instrucciones
ción para instalar. s

formulario de notepad ++ http://notepad-plus.sourceforge.net/uk/site.htm

• Abra Notepad ++ e ingrese F5


• En la nueva ventana ingrese el comando launchff ++ "$ (FULL_CURRENT_PATH)"
• Haga clic en Guardar, e ingrese FreeFem ++ en el cuadro "Nombre", ahora elija el corto
cortar la tecla para iniciar directamente FreeFem ++ (por ejemplo, alt + shift + R)
• Para agregar una sintaxis de color compatible con FreeFem ++ en Notepad ++,

Página 18
18 CAPÍTULO 1 INTRODUCCIÓN

- En el menú "Parámetros" -> "Configuración de la sintaxis del color"


proceder de la siguiente:
- En la lista "Idioma", seleccione C ++
- Agregue ”edp” en el campo "agregar ext"
- Seleccione "PALABRA DE INSTRUCCIÓN" en la lista "Descripción" y en el campo
"palabra clave suplementaria", corte y pegue la siguiente lista:
P0 P1 P2 P3 P4 P5 P1dc P2dc P3dc P4dc P5dc RT0 RT1 RT2 RT3 RT4
RT5 macro plot int1d int2d resolver movemesh adaptmesh trunc checkmovemesh
en func buildmesh cuadrado Valor propio min max imag exec LinearCG NLCG
Newton BFGS LinearGMRES catch try intalledges salto carga media media
savemesh convect abs sin cos tan atan asin acos cotan sinh cosh tanh cotanh
atanh asinh acosh pow exp log log10 sqrt dx dy endl cout
- Seleccione ”TIPO DE PALABRA” en la lista ”Descripción” y ... ”” suplementario
palabra clave ", corte y pegue la siguiente lista
malla real fespace varf problema de matriz cadena borde complejo ifstream of-
Arroyo
- Haga clic en Guardar y cerrar. Ahora nodepad ++ está configurado.

winedt para Windows: este es el mejor, pero podría ser complicado de configurar. Descárgalo desde

http://www.winedt.com

este es un editor de texto multipropósito con funciones avanzadas como colorear sintaxis; a
macro está disponible en www.freefem.org para localizar winedt a FreeFem ++ sin
perturbando el modo funcional winedt para LateX, TeX, C, etc. Sin embargo, winedt no es
gratis después del período de prueba.

TeXnicCenter para Windows: este es el más fácil y será el mejor una vez que encontremos un voluntario
para programar la sintaxis del color. Descárgalo desde

http://www.texniccenter.org/

También es un editor para TeX / LaTeX. Tiene un menú de "herramientas" que se puede configurar para
lanzar programas FreeFem ++ como en:

https://translate.googleusercontent.com/translate_f 15/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

• Seleccione el elemento Herramientas / Personalizar que mostrará un cuadro de diálogo.


• Seleccione la pestaña Herramientas y cree un nuevo elemento: llámelo freefem.

• en las 3 líneas siguientes,

1. busque FreeFem ++. Exe


2. seleccione Archivo principal con opciones adicionales, luego Ruta completa y haga clic también en 8.3
caja
3. seleccione la ruta completa del directorio del archivo principal con 8.3

nedit en Mac OS, Cygwin / Xfree y linux, para importar la sintaxis de color, haga

nedit -import edp.nedit

Página 19
1.1. INSTALACIÓN 19

textmate 2 para Mac 10.7 o superior, descárguelo de https://macromates.com/download


e instálelo cuando obtenga la sintaxis de textmate freefem ++ de http: //www.freefem.
org / ff ++ / Textmate2-ff ++. zip descomprima y siga la explicación dada en el archivo
Cómo hacerlo.

Smultron / fraise (obsoleto) en Mac, disponible en http: //smultron.sourceforge.


neto. Viene listo con sintaxis de color para el archivo .edp. Para enseñarle a lanzar FreeFem ++
archivos, haga un "comando B" (es decir, el menú Herramientas / Manejar comando / nuevo comando) y
crea un comando que hace

/ usr / local / bin / FreeFem ++ - CoCoa %% p

https://translate.googleusercontent.com/translate_f 16/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 1.1: Entorno integrado para el desarrollo de FreeFem ++ con Windows

Página 20
20 CAPÍTULO 1 INTRODUCCIÓN

1.2 Cómo utilizar FreeFem ++


En MacOS X con interfaz gráfica Para probar un archivo .edp, simplemente arrastre y suelte el archivo
icono en la aplicación MacOS icono FreeFem ++. aplicación. También puede iniciar esta aplicación
y use el menú: Archivo → Abrir.
Sin embargo, una de las mejores formas en Mac es usar un editor de texto como Smultron.app (ver
sobre).

Figura 1.2: Los 3 paneles del entorno integrado construido con el editor fraise
con FreeFem ++ en acción. El menú Herramientas tiene un elemento para iniciar FreeFem ++ mediante un
Comando Ctrl + 1.

En modo Terminal Elija el tipo de aplicación de FreeFem ++, FreeFem ++ - nw,


FreeFem ++ - mpi,. . . según sus necesidades. Agregue al menos el nombre de la ruta; por ejemplo

FreeFem ++ su-ruta-de-archivo-edp

1.3 Variables de entorno y el archivo init


FreeFem ++ lee el archivo de inicio de un usuario llamado freefem ++. Pref para inicializar las variables globales:
verbosidad, ruta de inclusión, ruta de carga.

Observación 3 La verbosidad variable cambia el nivel de impresión interna (0, nada (un-
menos hay errores de sintaxis), 1 pocos, 10 lotes, etc. ...), el valor predeterminado es 2.
Los archivos de inclusión se buscan en la lista de rutas de inclusión y los archivos de carga se buscan
de la lista de la ruta de carga.

https://translate.googleusercontent.com/translate_f 17/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 21
1.4. HISTORIA 21

La sintaxis del archivo es:

verbosidad = 5
loadpath + = "/ Library / FreeFem ++ / lib"
loadpath + = "/ Usuarios / hecht / Library / FreeFem ++ / lib"
includepath + = "/ Library / FreeFem ++ / edp"
includepath + = "/ Users / hecht / Library / FreeFem ++ / edp"
# comentario
load + = "funcTemplate"
load + = "myfunction"
cargar + = "MUMPS_seq"

Las posibles rutas de este archivo son

• bajo Unix y MacOs

/etc/freefem++.pref
$ (INICIO) /. Freefem ++. Pref
freefem ++. pref

• debajo de las ventanas

freefem ++. pref

También podemos usar la variable de entorno de shell para cambiar la verbosidad y la regla de búsqueda antes
los archivos de inicio.

exportar FF_VERBOSITY = 50
exportar FF_INCLUDEPATH = "dir ;; dir2"
exportar FF_LOADPATH = "dir ;; dir3" "

Observación: el separador entre directorios debe ser ";" y no ":" porque ":" se usa bajo
Windows.
Observación, para mostrar la lista de init de FreeFem ++, haga

exportar FF_VERBOSITY = 100; ./FreeFem++-nw


- la verbosidad se establece en 100
insertar archivos de inicio /etc/freefem++.pref $
...

1.4 Historia
El proyecto ha evolucionado de MacFem, PCfem, escrito en Pascal. El primer plomo de la versión C
a freefem 3.4; ofreció adaptatividad de malla en una sola malla solamente.

Una reescritura completa en C ++ llevó a freefem + (freefem + 1.2.10 fue su última versión),
que incluía la interpolación sobre múltiples mallas (las funciones definidas en una malla se pueden
utilizado en cualquier otra malla); este software ya no se mantiene, pero todavía está en uso porque

Página 22

https://translate.googleusercontent.com/translate_f 18/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
22 CAPÍTULO 1 INTRODUCCIÓN

maneja una descripción de problema utilizando la forma fuerte de los PDE. Implementando la inter-
La polacin de una malla no estructurada a otra no fue fcil porque tena que ser rpida y
no difusivo; para cada punto, había que encontrar el triángulo contenedor. Este es uno de los básicos
problemas de geometría computacional (ver Preparata & Shamos [23 ] por ejemplo). Haciéndolo
en un número mínimo de operaciones fue el desafío. Nuestra implementación es O (nlog n)
y basado en un quadtree. Esta versión también creció fuera de control debido a la evolución del
sintaxis de plantilla en C ++.

Hemos estado trabajando durante algunos años en FreeFem ++, completamente reescrito nuevamente en
C ++ con un uso completo de plantilla y programación genérica para sistemas acoplados de
tamaño desconocido en tiempo de compilación. Como todas las versiones de freefem, tiene un alto nivel de facilidad de uso.
lenguaje de entrada que no se aleja demasiado de la escritura matemática de los problemas.

El lenguaje freefem permite una rápida especificación de cualquier sistema diferencial parcial de
ecuaciones. La sintaxis del lenguaje de FreeFem ++ es el resultado de un nuevo diseño que hace
uso de STL [31 ], templates y bison para su implementación; se pueden encontrar más detalles
en [17 ]. El resultado es un software versátil en el que se puede incluir cualquier elemento finito nuevo.
en unas pocas horas; pero entonces es necesaria una recopilación. Por tanto, la biblioteca de elementos finitos
disponible en FreeFem ++ crecerá con el número de versión y con el número de usuarios
que programan más elementos nuevos. Hasta ahora tenemos elementos P 0 discontinuos , P 1 lineal y
elementos cuadráticos P 2 Lagrangianos, P 1 discontinuos y elementos Raviart-Thomas y un
a algunos otros les gustan los elementos de burbuja.

Página 23

https://translate.googleusercontent.com/translate_f 19/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Capitulo 2
Empezando

Para ilustrar con un ejemplo, expliquemos cómo FreeFem ++ resuelve la ecuación de Poisson:
para una función dada f (x, y), encuentre una función u (x, y) que satisfaga

−∆u (x, y) = f (x, y) para todo (x, y) ∈ Ω, (2,1)


u (x, y) = 0 para todo (x, y) en ∂Ω ,. (2,2)

Aquí ∂Ω es el límite del conjunto abierto acotado Ω ⊂ R 2 y ∆u = ∂ 2u


∂x 2 +∂ 2 u ∂y 2 .
El siguiente es un programa FreeFem ++ que calcula u cuando f (x, y) = xy y Ω es el
unidad de disco. El límite C = ∂Ω es

C = {(x, y) | x = cos (t), y = sin (t), 0 ≤ t ≤ 2π}

Tenga en cuenta que en FreeFem ++ se supone que el dominio Ω se describe por su límite que está en
el lado izquierdo de su límite orientado por el parámetro.
Como se ilustra en la figura 2.2 , podemos ver el isovalor de u usando plot (ver línea 13 a continuación).

Figura 2.1: malla Th por construcción (C (50)) Figura 2.2: isovalor por parcela (u)

Ejemplo 2.1

// definiendo el límite
1: borde C (t = 0,2 * pi ) { x = cos (t); y = sin (t);}

23

Página 24
24 CAPÍTULO 2. PARA EMPEZAR

// el dominio triangulado Th está en el lado izquierdo de su límite


2: malla Th = buildmesh (C (50));
// el espacio de elementos finitos definido sobre Th se llama aquí Vh
3; fespace Vh (Th, P1 );
4: Vh u, v; // define uyv como funciones continuas por partes-P1
5: función f = x * y; // definición de una función f llamada
6: CPU real = reloj (); // conseguir el reloj en segundo
7: resuelve Poisson (u, v, solucionador = LU) = // define el PDE
8: int2d (Th) ( dx (u) * dx (v) + dy (u) * dy (v)) // parte bilineal
9: - int2d (Th) (f * v) // lado derecho
10: + en (C, u = 0); // Condición de frontera de Dirichlet
11: trama (u);
12: cout << "tiempo de CPU =" << reloj () - cpu << endl ;

https://translate.googleusercontent.com/translate_f 20/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Tenga en cuenta que no se requiere el solucionador calificador = LU y, por defecto, una LU multi-frontal
ha sido usado. Tenga en cuenta también que las líneas que contienen el reloj tampoco son necesarias. Finalmente
tenga en cuenta lo cerca que está el lenguaje de entrada matemático FreeFem ++. Las líneas 8 y 9 corresponden
a la ecuación variacional matemática

∫ ∂u ∂v ∂u ∂v ∫
( + ) dxdy = fvdxdy
Th ∂x ∂x ∂y ∂y Th

para todos los v que están en el espacio de elementos finitos V h y cero en el límite C.

Ejercicio: cambie P1 a P2 y ejecute el programa.

2.0.1 FEM de FreeFem ++ : ¿cómo funciona?


Este primer ejemplo muestra cómo FreeFem ++ ejecuta sin esfuerzo todos los pasos habituales
requerido por el método de elementos finitos (FEM). Repasemos uno por uno.

1ª línea: el límite Γ se describe analíticamente mediante una ecuación paramétrica para xy para y.
J
Cuando Γ = ∑ j = 0 Γ j entonces cada curva Γ j , debe especificarse y no se permiten cruces de Γ j
excepto en los puntos finales.
Se puede agregar la palabra clave "etiqueta" para definir un grupo de límites para su uso posterior (límite
condiciones, por ejemplo). Por lo tanto, el círculo también podría haber sido descrito como dos semicírculos.
con la misma etiqueta:

borde Gamma1 (t = 0, pi ) { x = cos (t); y = sin (t); etiqueta = C}


borde Gamma2 (t = pi , 2 * pi ) { x = cos (t); y = sin (t); etiqueta = C}

Se puede hacer referencia a los límites por su nombre (Gamma1 por ejemplo) o por etiqueta (C aquí)
o incluso por su número interno aquí 1 para el primer semicírculo y 2 para el segundo (más
los ejemplos se encuentran en la Sección 5.8) .

2da línea: la triangulación T h de Ω es generada automáticamente por buildmesh (C (50)) usando


50 puntos en C como en la Fig. 2.1.
Se supone que el dominio está en el lado izquierdo del límite que está implícitamente orientado
por la parametrización. Entonces se puede agregar un agujero elíptico por

Página 25
25

borde C (t = 2 * pi , 0) { x = 0.1 + 0.3 * cos (t); y = 0.5 * sin (t);}

Si por error alguno hubiera escrito

borde C (t = 0,2 * pi ) { x = 0,1 + 0,3 * cos (t); y = 0.5 * sin (t);}

entonces el interior de la elipse se triangularía al igual que el exterior.


La generación automática de mallas se basa en el algoritmo Delaunay-Voronoi. Refinamiento del
mallas se hacen aumentando el número de puntos en Γ, por ejemplo, buildmesh (C (100)),
porque los vértices internos están determinados por la densidad de puntos en el límite. Malla
La adaptación también se puede realizar contra una función f dada llamando adaptmesh (Th, f).
Ahora el nombre T h (Th en FreeFem ++) se refiere a la familia {T k } k = 1, ···, n de triángulos mostrados
t

en la figura 2.1 . Tradicionalmente, h se refiere al tamaño de la malla, n t al número de triángulos en T h y


n v al número de vértices, pero rara vez tendremos que usarlos explícitamente. Si Ω es
no es un dominio poligonal, una "piel" permanece entre el dominio exacto Ω y su aproximación
Ωh=∪n t
k = 1 T k . Sin embargo, notamos que todas las esquinas de Γ h = ∂Ω h están en Γ.

https://translate.googleusercontent.com/translate_f 21/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Tercera línea: un espacio de elementos finitos es, por lo general, un espacio de funciones polinomiales sobre elementos,
triángulos aquí solamente, con ciertas propiedades coincidentes en los bordes, vértices, etc. Aquí fespace
Vh (Th, P1) define V h como el espacio de funciones continuas afines en x, y en
cada triángulo de T h . Como es un espacio vectorial lineal de dimensión finita, se puede encontrar la base.
La base canónica está formada por funciones, llamadas funciones sombrero φ k que son continuas
afín por partes y son iguales a 1 en un vértice y 0 en todos los demás. Una función típica de sombrero
se muestra en la figura 2 .4 1. Luego

{ ∣ METRO }
∣ ∑
V h (T h , P 1 ) = w (x, y) ∣ w (x, y) = w k φ k (x, y), w k son números reales (2,3)
∣ k=1

donde M es la dimensión de V h , es decir, el número de vértices. Los w k se llaman el grado de


libertad de w y M el número del grado de libertad.
También se dice que los nodos de este método de elementos finitos son los vértices.
Actualmente FreeFem ++ implementa los siguientes elementos en 2d, (ver sección 6
para la descripción completa)
P0 constante a trozos,
P1 continuo lineal a trozos,
P2 cuadrático continuo a trozos,
P3 continuo cúbico a trozos, (necesita carga "Element_P3")
P4 cuartica continua a trozos, (necesita cargar "Element_P4")
RT0 Constante a trozos de Raviart-Thomas,

1 La forma más sencilla de definir φ k es haciendo uso de las coordenadas baricéntricas λ i (x, y), i = 1, 2, 3 de un
punto q = (x, y) ∈ T, definido por
∑ λ yo = 1, ∑ λ yo q yo = q
I I

donde q i , i = 1, 2, 3 son los 3 vértices de T.Entonces es fácil ver que la restricción de φ k en T es precisamente
λk.

Página 26
26 CAPÍTULO 2. PARA EMPEZAR

1
5

2 2
6
1

4 8
5
6
7 2 8
3 3
5 8 3 7
3 4
7 7
4 4

Figura 2.3: malla Th Figura 2.4: Gráfico de φ 1 (izquierda) y φ 6

RT1 Raviart-Thomas grado 1 constante por partes (necesita cargar "Element_Mixte")


BDM1 Brezzi-Douglas-Marini grado 1 constante a trozos (necesita cargar "Element_Mixte")
RT0Ortho Nedelec tipo 1 grado 0 constante a trozos
RT1Ortho Nedelec tipo 1 grado 1 constante a trozos (necesita cargar "Element_Mixte")
BDM1Ortho Brezzi-Douglas-Marini grado 1 constante a trozos (necesita cargar "Element_Mixte")
P1nc lineal a trozos no conforme,
P1dc lineal discontinuo a trozos,
P2dc discontinuo cuadrático a trozos,
P2h homogéneo cuadrático continuo (sin P1)
P3dc discontinuo cúbico a trozos, (necesita cargar "Element_P3dc")
P4dc discontinua cuartica a trozos, (necesita cargar "Element_P4dc")
P1b burbuja lineal continua a trozos más,
P2b burbuja continua cuadrática a trozos más.
https://translate.googleusercontent.com/translate_f 22/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Elemento finito de Morley Morley (necesita cargar "Morley")
HCT Hsieh-Clough-Tocher C 1 elemento finito (necesita cargar "Element_HCT", versión 3.40)
P2BR P2 Elemento finito Bernardi-Raugel (necesita cargar "BernadiRaugel.cpp")
P0 bordear una constante de elementos finitos por borde
P1edge a P5edge un polinomio de elementos finitos en el borde (necesita cargar "Element_PkEdge")
...
Actualmente FreeFem ++ implementa los siguientes elementos en 3d, (ver sección 6 por el completo
descripción)
P03d constante a trozos,
P13d continuo lineal a trozos,
P23d cuadrático continuo a trozos,
RT03d Constante a trozos de Raviart-Thomas,
Edge03d, Edge13d, Edge23d El elemento de borde Nedelec 0,1,2
P1b3d lineal a trozos continuo más burbuja,
...
Para obtener la lista completa, en una terminal Unix, en el directorio examples ++ - tutorial do

FreeFem ++ dumptable.edp
grep TypeOfFE lestables

Tenga en cuenta que se pueden agregar otros elementos con bastante facilidad.

Página 27
27

Paso 3: solucionar el problema


Cuarta línea: Vh u, v declara que uyv se aproximan como arriba, es decir

M−1

u (x, y) ≃ u h (x, y) = ∑ u k φ k (x, y) (2,4)


k=0

Quinta línea: el lado derecho f se define analíticamente usando la palabra clave func .
Líneas 7 a 9: define la forma bilineal de la ecuación (2.1 ) y su condición de frontera de Dirichlet.
ciones ( 2.2) .
Esta formulación variacional se obtiene multiplicando ( 2.1 ) por v (x, y) e integrando el
resultado sobre Ω:
∫ ∫
- v∆udxdy = vf dxdy
Ω Ω

Luego, mediante la fórmula de Green, el problema se convierte en encontrar u tal que

a (u, v) - l (f, v) = 0 ∀v satisfaciendo v = 0 en ∂Ω. (2,5)


∫ ∫
con a (u, v) = ∇u · ∇v dxdy, l (f, v) = fv dxdy (2,6)
Ω Ω

En FreeFem ++, el problema de Poisson solo se puede declarar como en

Vh u, v; problema de Poisson (u, v) =

y resuelto más tarde como en

...
Poisson; // el problema se resuelve aquí
...

o declarado y resuelto al mismo tiempo que en

Vh u, v; resolver Poisson (u, v) = int (...

y ( 2.5) se escribe con dx (u) = ∂u / ∂x, dy (u) = ∂u / ∂y y

https://translate.googleusercontent.com/translate_f 23/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Ω
∇u · ∇v dxdy - → int2d (Th) ( dx (u) * dx (v) + dy (u) * dy (v))

fv dxdy - → int2d (Th) (f * v) (Fíjese aquí, u no se usa)
Ω

En FreeFem ++, los términos bilineales y los términos lineales no deben estar bajo la misma integral;
de hecho para construir los sistemas lineales FreeFem ++ descubre qué integral contribuye a
la forma bilineal comprobando si ambos términos, la incógnita (aquí u) y las funciones de prueba (aquí
v) están presentes.

Paso 4: solución y visualización

6ª línea: el tiempo actual en segundos se almacena en la variable cpu de valor real.


7ª línea El problema está resuelto.

Página 28
28 CAPÍTULO 2. PARA EMPEZAR

11a línea: La visualización se realiza como se ilustra en la Fig. 2.2 (consulte la Sección 7.1 para el zoom,
postscript y otros comandos).
Línea 12: El tiempo de cálculo (sin contar los gráficos) está escrito en la consola. Observe el
C ++ - como sintaxis; el usuario no necesita estudiar C ++ para usar FreeFem ++, pero ayuda a
adivina lo que está permitido en el idioma.

Acceso a matrices y vectores


Internamente FreeFem ++ resolverá un sistema lineal del tipo

M−1

∑ A ij u j - F i = 0, i = 0, ···, M - 1; Fi= fφ i dxdy (2,7)
Ω
j=0

que se encuentra usando ( 2.4 ) y reemplazando v por φ i en (2.5 ). Y las condiciones de Dirichlet son
implementado por penalización, es decir, estableciendo A ii = 10 30 y F i = 10 30 ∗ 0 si i es un límite
grado de libertad. Tenga en cuenta que el número 10 30 se llama tgv (tr`es grande valeur) y es
generalmente es posible cambiar este valor, consulte el elemento de índice solve! tgv =.

La matriz A = (A ij ) se llama matriz de rigidez.


Si el usuario desea acceder a A directamente, puede hacerlo utilizando (consulte la sección 6.12, página 195 para
detalles)

varf a (u, v) = int2d (Th) ( dx (u) * dx (v) + dy (u) * dy (v))


+ en (C, u = 0);
matriz A = a (Vh, Vh); // matriz de rigidez,

El vector F en ( 2.7) también se puede construir manualmente

varf l (sin usar, v) = int2d (Th) (f * v) + on (C, sin usar = 0);


Vh F; F [] = 1 (0, Vh); // F [] es el vector asociado a la función F

El problema puede resolverse entonces

u [] = Aˆ-1 * F []; // u [] es el vector asociado a la función u

Nota 2.1 Aquí u y F son funciones de elementos finitos, y u [] y F [] dan la matriz de


valor asociado (u [] ≡ (u i ) i = 0, ..., M − 1 y F [] ≡ (F i ) i = 0, ..., M − 1 ). Entonces tenemos

M−1 M−1

u (x, y) = ∑ u [] [i] φ i (x, y), F (x, y) = ∑ F [] [i] φ i (x, y)


i=0 i=0

donde φ i , i = 0 ...,, M - 1 son las funciones base de Vh como en la ecuación (2 .3), y M =


Vh.ndof es el número de grado de libertad (es decir, la dimensión del espacio Vh).

https://translate.googleusercontent.com/translate_f 24/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

El sistema lineal ( 2.7 ) se resuelve mediante UMFPACK a menos que se mencione otra opción específicamente
como en

Vh u, v; problema Poisson (u, v, solucionador = CG) = int2d (...

lo que significa que Poisson se declara solo aquí y cuando se llama (simplemente escribiendo
Poisson; ) luego (2 .7) se resolverá mediante el método de gradiente conjugado.

Página 29
2.1. EL CICLO DE DESARROLLO: EDITAR – EJECUTAR / VISUALIZAR – REVISAR 29

2.0.2 Algunas características de FreeFem ++


El lenguaje de FreeFem ++ es tipado, polimórfico y reentrante con macrogeneración.
(ver 9.12 ). Cada variable debe escribirse y declararse en una declaración, cada declaración separa
clasificado a partir del siguiente con un punto y coma ”;”. La sintaxis es la de C ++ aumentada por defecto
con algo más parecido a TEX. Para el especialista, una pauta clave es que
FreeFem ++ rara vez genera una matriz interna de elementos finitos; esto fue adoptado por velocidad
y, en consecuencia, FreeFem ++ podría ser difícil de superar en términos de velocidad de ejecución, excepto
por el tiempo perdido en la interpretación del idioma (que puede reducirse mediante una
uso de varf y matrices en lugar de problema.

2.1 El ciclo de desarrollo: Editar – Ejecutar / Visualizar – Revisar


Un entorno integrado se proporciona con FreeFem ++ por A. Le Hyaric; Muchos ejemplos
y tutoriales también se dan junto con esta documentación y es mejor estudiarlos y
aprender con el ejemplo. En esta documentación se dan explicaciones para algunos de estos ejemplos.
en el próximo capítulo. Si eres un principiante de FEM, es posible que también tengas que leer un libro sobre
formulaciones variacionales.
El ciclo de desarrollo tendrá los siguientes pasos:

Modelado: desde formas fuertes de PDE hasta formas débiles, uno debe conocer la forma variacional
mulación para usar FreeFem ++; También hay que tener en cuenta la reutilización del
formulación variacional para mantener las mismas matrices internas; un ejemplo típico es
la ecuación de calor dependiente del tiempo con un esquema de tiempo implícito: la matriz interna
solo se puede factorizar una vez y se puede enseñar a FreeFem ++ a hacerlo.

Programación: escriba el código en lenguaje FreeFem ++ usando un editor de texto como el


proporcionado en el entorno integrado.

Ejecutar: Ejecute el código (aquí escrito en el archivo mycode.edp). tenga en cuenta que esto también se puede hacer en
modo terminal por:

% FreeFem ++ mycode.edp

Visualización: utilice el gráfico de palabras clave para mostrar funciones mientras se ejecuta FreeFem ++.
Utilice el parámetro de trazado wait = 1 para detener el programa en cada trazado. Usa la trama
parámetro ps = "toto.eps" para generar un archivo postscript para archivar los resultados.

Depuración: una variable global "debug" (por ejemplo) puede ayudar como en wait = true to wait = false .

bool debug = true;


borde a (t = 0,2 * pi) {x = cos (t); y = sin (t); etiqueta = 1;}
borde b (t = 0,2 * pi) {x = 0,8 + 0,3 * cos (t); y = 0.3 * sin (t); etiqueta = 2;}
plot (a (50) + b (-30), espera = depurar); // traza los bordes para ver la intersección
// (así que cambie (0.8 en 0.3 en b) luego necesita un clic del mouse
malla Th = buildmesh (a (50) + b (-30));
plot (Th, espera = depurar); // plot Th luego necesita un clic del mouse
fespace Vh (Th, P2);
Vh f = sin (pi * x) * cos (pi * y);
plot (f, esperar = depurar); // trazar la función f

https://translate.googleusercontent.com/translate_f 25/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 30
30 CAPÍTULO 2. PARA EMPEZAR

Vh g = sin ( pi * x + cos ( pi * y));


plot (g, esperar = depurar); // trazar la función g

Cambiar debug a false hará que los gráficos fluyan continuamente; mirando el flujo de
Los gráficos en la pantalla (mientras toma café) pueden convertirse en una experiencia agradable.
Los mensajes de error se muestran en la ventana de la consola. No siempre son muy explícitos
debido a la estructura de la plantilla del código C ++, (¡hicimos nuestro mejor esfuerzo)! sin embargo
se muestran en el lugar correcto. Por ejemplo, si olvida los paréntesis como en

bool debug = true;


malla Th = cuadrado (10,10);
trama (Th);

luego recibirá el siguiente mensaje de FreeFem ++,

2: malla Th = cuadrado (10,10);


Línea de error número 2, en el archivo bb.edp, antes del token;
error de análisis
línea actual = 2
Error de compilación: error de análisis
número de línea: 2,;
error Error de compilación: error de análisis
número de línea: 2,;
código = 1

Si usa el mismo símbolo dos veces como en

aaa real = 1;
real aaa;

entonces recibirás el mensaje

2: aaa real; El identificador aaa existe


el tipo existente es <Pd>
el nuevo tipo es <Pd>

Si encuentra que el programa no está haciendo lo que desea, también puede usar cout para
mostrar en formato de texto en la ventana de la consola el valor de las variables, tal como lo haría
hacer en C ++.
El siguiente ejemplo funciona:

...;
fespace Vh ...; Vh u; ...
cout << u; ...
matriz A = a (Vh, Vh); ...
cout << A;

Otro truco es comentar dentro y fuera usando el "//" como en C ++. Por ejemplo

aaa real = 1;
// real aaa;

https://translate.googleusercontent.com/translate_f 26/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 31

Capítulo 3

Aprendiendo con ejemplos

Este capítulo es para aquellos, como nosotros, a quienes no les gusta leer manuales. Una serie de simples
Los ejemplos cubren gran parte de la capacidad de FreeFem ++ y se explican por sí mismos. Para el
parte de modelado este capítulo continúa en el Capítulo 9, donde algunas PDE de física, ingeniería
y las finanzas se estudian con mayor profundidad.

3.1 Membranas
Resumen Aquí aprenderemos cómo resolver un Dirichlet y / o Dirichlet Neumann mixto
problema para el operador de Laplace con la aplicación al equilibrio de una membrana bajo
carga. También comprobaremos la precisión del método y la interfaz con otros paquetes gráficos.
siglos.

Una membrana elástica Ω está unida a un soporte rígido plano Γ, y una fuerza f (x) dx es
ejercida sobre cada elemento de la superficie dx = dx 1 dx 2 . El desplazamiento vertical de la membrana, ϕ (x),
se obtiene resolviendo la ecuación de Laplace:

−∆ϕ = f en Ω.

Como la membrana está fijada a su soporte plano, se tiene:

ϕ | Γ = 0.

Si el soporte no era plano sino a una elevación z (x 1 , x 2 ), entonces las condiciones de contorno
sería de tipo Dirichlet no homogéneo.

ϕ | Γ = z.

Si una parte Γ 2 del borde de la membrana Γ no se fija al soporte sino que se deja colgando, entonces
debido a la rigidez de la membrana, el ángulo con el vector normal n es cero; así el límite
las condiciones son
∂ϕ
ϕ | Γ = z,
1 |Γ =0 2

En
donde Γ 1 = Γ - Γ 2 ; recuerda eso ∂ϕ En
= ∇ϕ · n. Recordemos también que el operador de Laplace ∆
es definido por:
∂2ϕ ∂2ϕ
∆ϕ = + .
∂x 21 ∂x 22

31

Página 32
32 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

Con tales "condiciones de frontera mixtas", el problema tiene una solución única (ver (1987),
Dautray-Lions (1988), Strang (1986) y Raviart-Thomas (1983)); la prueba más fácil es
observe que ϕ es el estado de menor energía, es decir


https://translate.googleusercontent.com/translate_f 27/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
∫ 1
E (φ) = min E (v), con E (v) = ( | ∇v | 2 - fv)
Ω 2
ϕ − z∈V

y donde V es el subespacio del espacio de Sobolev H 1 (Ω) de funciones que tienen traza cero
en Γ 1 . Recuerda que (x ∈ R d , d = 2 aquí)

H 1 (Ω) = {u ∈ L 2 (Ω): ∇u ∈ (L 2 (Ω)) d }

El cálculo de variación muestra que el mínimo debe satisfacer, lo que se conoce como la forma débil.
del PDE o su formulación variacional (también conocido aquí como el teorema del trabajo virtual)

∫ ∫
∇ϕ · ∇w = fw ∀w ∈ V
Ω Ω

A continuación, una integración por partes (fórmula de Green) mostrará que esto es equivalente al PDE
cuando existen segundas derivadas.

ADVERTENCIA A diferencia de freefem + que tenía formas fuertes y débiles, FreeFem ++ im-
Complementa solo formulaciones débiles. No es posible avanzar más en el uso de este software si
no conoce la forma débil (es decir, formulación variacional) de su problema: o lee un
reservar, pedir ayuda a un colega o dejar el asunto. Ahora si quieres resolver un sistema
de PDE como A (u, v) = 0, B (u, v) = 0 no cierre este manual, porque en forma débil es

(A (u, v) w 1 + B (u, v) w 2 ) = 0 ∀w 1 , w 2 ...
Ω

Ejemplo Supongamos que una elipse tiene la longitud del semieje mayor a = 2, y unitaria
eje semiminor Sea la fuerza superficial f = 1. Programando este caso con FreeFem ++
da:

Ejemplo 3.1 (membrana.edp) // archivo membrana.edp


theta real = 4. * pi / 3 .;
real a = 2., b = 1 .; // la longitud del semieje mayor y el semieje menor
func z = x;

borde Gamma1 (t = 0, theta) {x = a * cos (t); y = b * sin (t); }


borde Gamma2 (t = theta, 2 * pi) {x = a * cos (t); y = b * sin (t); }
malla Th = buildmesh (Gamma1 (100) + Gamma2 (50));

fespace Vh (Th, P2); // P2 conforme a FEM triangular


Vh phi, w, f = 1;

resolver Laplace (phi, w) = int2d (Th) (dx (phi) * dx (w) + dy (phi) * dy (w))
- int2d (Th) (f * w) + en (Gamma1, phi = z);
plot (phi, espera = verdadero, ps = "membrana.eps"); // Trazar phi
plot (Th, espera = verdadero, ps = "membranaTh.eps"); // Trazar Th

savemesh (Th, "Th.msh");

Página 33
3.1. MEMBRANAS 33

https://translate.googleusercontent.com/translate_f 28/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

"phi.txt"

2 2
1,5 1,5
1
1
0,5
0,5
0
0
-0,5
-0,5
-1
-1,5 -1

-2 -1,5

-2

1
0,8
0,6
0.4
0,2 2
0 1,5
1
-0,2 0,5
-0,4 0
-0,6 -0,5
-0,8 -1
-1,5
-1 -2

Figura 3.1: Malla y líneas de nivel de la deformación de la membrana. Abajo: lo mismo en 3D


dibujado por gnuplot a partir de un archivo generado por FreeFem ++.

Página 34
34 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

La triangulación se construye con la palabra clave buildmesh. Esta palabra clave llama triangulación
subrutina basada en la prueba de Delaunay, que primero se triangula solo con el límite
puntos, luego agrega puntos internos subdividiendo los bordes. Que fina la triangulacion
se controla mediante el tamaño de los bordes de los límites más cercanos.
El PDE luego se discretiza usando el método triangular de elementos finitos de segundo orden en el
triangulación; como se indicó brevemente en el capítulo anterior, un sistema lineal se deriva
de la formulación discreta cuyo tamaño es el número de vértices más el número de medios
bordes en la triangulación. El sistema se resuelve mediante una factorización LU de Gauss multi-frontal
implementado en el paquete UMFPACK. El gráfico de palabras clave mostrará tanto T h como ϕ (eliminar
Si solo se desea ϕ) y el calificador fill = true reemplaza la opción predeterminada (coloreada
líneas de nivel) mediante una pantalla a todo color. Los resultados se muestran en la figura 3.1.

plot (phi, wait = true, fill = true); // Trazar phi con pantalla a todo color

¡A continuación nos gustaría comprobar los resultados!


Una forma sencilla es ajustar los parámetros para conocer las soluciones. Por ejemplo en el
círculo unitario a = 1, ϕ e = sin (x 2 + y 2 - 1) resuelve el problema cuando

https://translate.googleusercontent.com/translate_f 29/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
z = 0, f = −4 (cos (x 2 + y 2-1 ) - (x 2 + y 2 ) sin (x 2 + y 2-1 ))

excepto que en Γ 2 ∂ n ϕ = 2 en lugar de cero. Entonces consideraremos un Neumann no homogéneo


condicionar y resolver
∫ ∫ ∫
(∇ϕ · ∇w = fw + 2w ∀w ∈ V
Ω Ω Γ2

Lo haremos con dos triangulaciones, calculamos el error L 2 :


ϵ= |ϕ-ϕe|2
Ω

e imprima el error en ambos casos, así como el logaritmo de su relación, una indicación de la tasa de
convergencia.

Ejemplo 3.2 (membrananerror.edp) // archivo membrananerror.edp


verbosidad = 0; // para eliminar toda la salida predeterminada
theta real = 4. * pi / 3 .;
real a = 1., b = 1 .; // la longitud del semieje mayor y el semieje menor
borde Gamma1 (t = 0, theta) {x = a * cos (t); y = b * sin (t); }
borde Gamma2 (t = theta, 2 * pi) {x = a * cos (t); y = b * sin (t); }

func f = -4 * (cos (xˆ2 + yˆ2-1) - (xˆ2 + yˆ2) * sin (xˆ2 + yˆ2-1));


func phiexact = sin (xˆ2 + yˆ2-1);

real [int] L2error (2); // una matriz de dos valores


para ( int n = 0; n <2; n ++)
{
malla Th = buildmesh (Gamma1 (20 * (n + 1)) + Gamma2 (10 * (n + 1)));
fespace Vh (Th, P2);
Vh phi, w;

resolver laplace (phi, w) = int2d (Th) (dx (phi) * dx (w) + dy (phi) * dy (w))
- int2d (Th) (f * w) - int1d (Th, Gamma2) (2 * w) + encendido (Gamma1, phi = 0);

Página 35
3.1. MEMBRANAS 35

plot (Th, phi, espera = verdadero, ps = "membrana.eps"); // Trazar Th y phi

L2error [n] = sqrt (int2d (Th) ((phi-phiexact) ˆ2));


}

para (int n = 0; n <2; n ++)


cout << "L2error" << n << "=" << L2error [n] << endl;

cout << "tasa de convergencia =" << log (L2error [0] / L2error [1]) / log (2.) << endl;

la salida es

L2error 0 = 0,00462991
L2error 1 = 0,00117128
tasa de convergencia = 1,9829
veces: compila 0.02s, ejecución 6.94s

Encontramos una tasa de 1.93591, que no se acerca lo suficiente a los 3 predichos por la teoría. La
La geometría es siempre un polígono, por lo que perdemos un orden debido a la aproximación de la geometría en
O (h 2 )
Ahora, si no está satisfecho con el gráfico .eps generado por FreeFem ++ y desea
usa otras facilidades gráficas, entonces debe almacenar la solución en un archivo muy parecido a C ++.
De nada servirá si no guardas también la triangulación, por lo tanto debes hacer

{
ofstream ff ("phi.txt");

https://translate.googleusercontent.com/translate_f 30/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
ff << phi [];
}
savemesh (Th, "Th.msh");

Para la triangulación el nombre es importante: es la extensión la que determina el formato.

Aún así, es posible que eso no lo lleve a donde desea. Aquí hay una interfaz con gnuplot para producir
la parte derecha de la figura 3.2 .

// para construir un archivo de datos gnuplot


{ ofstream ff ("graph.txt");
para ( int i = 0; i <Th.nt; i ++)
{ para ( int j = 0; j <3; j ++)
ff << Th [i] [j] .x << " "<< Th [i] [j] .y <<" "<< phi [] [Vh (i, j)] << endl ;
ff << Th [i] [0] .x << " "<< Th [i] [0] .y <<" "<< phi [] [Vh (i, 0)] <<" \ n \ n \ n "
}
}

Usamos la numeración de elementos finitos, donde Wh (i, j) es el índice global de j Th grados de


libertad del triángulo número i.
Luego abre gnuplot y haz

establecer paleta rgbformulae 30,31,32


mancha "graph.txt" wl pal

Esto funciona con P2 y P1, pero no con P1nc porque los 3 primeros grados de libertad de
P2 o P2 están en vértices y no con P1nc.

Página 36
36 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

3.2 Intercambiador de calor


Resumen Aquí aprenderemos más sobre la entrada de geometría y los archivos de triangulación, así como
como operaciones de lectura y escritura.

El problema Sea {C i } 1,2 , 2 conductores térmicos dentro de un recinto C 0 . El primero es


mantenido a una temperatura constante u 1 el otro tiene una conductividad térmica dada κ 2 5 veces
mayor que el de C 0 . Suponemos que el borde del recinto C 0 se mantiene a temperatura
20 ◦ C y que hemos esperado lo suficiente para el equilibrio térmico.
Para conocer u (x) en cualquier punto x del dominio Ω, debemos resolver

∇ · (κ∇u) = 0 en Ω, u | Γ = g

donde Ω es el interior de C 0 menos los conductores C 1 y Γ es el límite de Ω, es decir


C 0 ∪C 1 Aquí g es cualquier función de x igual a u i en C i . La segunda ecuación es una forma reducida
por:

u = u yo en C yo , yo = 0,1.

La formulación variacional de este problema está en el subespacio H 1


0 (Ω) ⊂ H 1 (Ω) de funciones
que tienen rastros cero en Γ.


u-g∈H1 ∇u∇v = 0 ∀v ∈ H 1
0 (Ω): Ω
0 (Ω)

Supongamos que C 0 es un círculo de radio 5 centrado en el origen, C i son rectángulos, C 1


estando a temperatura constante u 1 = 60 ◦ C.

Ejemplo 3.3 (heatex.edp) // archivo heatex.edp


int C1 = 99, C2 = 98; // podría ser cualquier cosa tal que = 0 y C1 = C2
borde C0 (t = 0,2 * pi) {x = 5 * cos (t); y = 5 * sin (t);}

borde C11 (t = 0,1) {x = 1 + t; y = 3; etiqueta = C1;}

https://translate.googleusercontent.com/translate_f 31/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
borde C12 (t = 0,1) {x = 2; y = 3-6 * t; etiqueta = C1;}
borde C13 (t = 0,1) {x = 2-t; y = -3; etiqueta = C1;}
borde C14 (t = 0,1) {x = 1; y = -3 + 6 * t; etiqueta = C1;}

borde C21 (t = 0,1) {x = -2 + t; y = 3; etiqueta = C2;}


borde C22 (t = 0,1) {x = -1; y = 3-6 * t; etiqueta = C2;}
borde C23 (t = 0,1) {x = -1-t; y = -3; etiqueta = C2;}
borde C24 (t = 0,1) {x = -2; y = -3 + 6 * t; etiqueta = C2;}

parcela ( C0 (50) // para ver el borde del dominio


+ C11 (5) + C12 (20) + C13 (5) + C14 (20)
+ C21 (-5) + C22 (-20) + C23 (-5) + C24 (-20),
esperar = verdadero, ps = "heatexb.eps");

malla Th = buildmesh ( C0 (50)


+ C11 (5) + C12 (20) + C13 (5) + C14 (20)
+ C21 (-5) + C22 (-20) + C23 (-5) + C24 (-20));
plot (Th, espera = 1);

Página 37
3.2. INTERCAMBIADOR DE CALOR 37

fespace Vh (Th, P1); Vh u, v;


Vh kappa = 1 + 2 * (x <-1) * (x> -2) * (y <3) * (y> -3);
resolver a (u, v) = int2d (Th) (kappa * ( dx (u) * dx (v) + dy (u) * dy (v)))
+ en (C0, u = 20) + en (C1, u = 60);
plot (u, espera = verdadero, valor = verdadero, relleno = verdadero, ps = "heatex.eps");

Tenga en cuenta lo siguiente:

• C0 está orientado en sentido antihorario por t, mientras que C1 está orientado en sentido horario y C2 está orientado
en sentido anti-horario. Esta es la razón por la que Buildmesh considera que C1 es un agujero.

• C1 y C2 se construyen uniendo piezas de líneas rectas. Para agruparlos en el mismo


unidad lógica para ingresar las condiciones de contorno de una manera legible, asignamos una etiqueta
en los límites. Como se dijo anteriormente, las fronteras tienen un número interno correspondiente
a su orden en el programa (compruébelo agregando un cout << C22; arriba). Esto es
esencial para comprender cómo una malla se puede enviar a un archivo y volver a leer (ver más abajo).

• Como es habitual, la densidad de la malla está controlada por el número de vértices asignados a cada uno.
Perímetro. No es posible cambiar la distribución (uniforme) de los vértices, pero una
La pieza de límite siempre se puede cortar en dos o más partes, por ejemplo, C12 podría ser
sustituido por C121 + C122:

// borde C12 (t = 0,1) x = 2; y = 3-6 * t; etiqueta = C1;


borde C121 (t = 0,0.7) {x = 2; y = 3-6 * t; etiqueta = C1;}
borde C122 (t = 0,7,1) {x = 2; y = 3-6 * t; etiqueta = C1;}
... buildmesh (... / * C12 (20) * / + C121 (12) + C122 (8) + ...);

IsoValue
15.7895
22.1053
26.3158
30.5263
34.7368
38.9474
43.1579
47.3684
51.5789
55.7895
60 64.2105
68.4211
72.6316
76.8421
81.0526
85.2632
89.4737
93.6842
104.211

https://translate.googleusercontent.com/translate_f 32/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 3.2: El intercambiador de calor

Ejercicio Utilice la simetría del problema con respecto a los ejes; triangular solo uno
la mitad del dominio, y establezca las condiciones de Dirichlet en el eje vertical, y las condiciones de Neumann
en el eje horizontal.

Página 38
38 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

Escribir y leer archivos de triangulación Supongamos que al final del programa anterior
agregamos la línea

savemesh (Th, "condensor.msh");

y luego escribimos un programa similar pero deseamos leer la malla de ese archivo.
Entonces así es como se debe calcular el condensador:

malla Sh = readmesh ("condensor.msh");


espacio libre Wh (Sh, P1); Wh nosotros, vs;
resolver b (us, vs) = int2d (Sh) ( dx (us) * dx (vs) + dy (us) * dy (vs))
+ en (1, us = 0) + en (99, us = 1) + en (98, us = -1);
trama (nosotros);

Tenga en cuenta que los nombres de los límites se pierden, pero su número interno (en el caso
de C0) o su número de etiqueta (para C1 y C2) se mantienen.

3.3 Acústica
Resumen Aquí vamos a abordar los problemas mal planteados y los problemas de valores propios
Las variaciones de presión en el aire en reposo se rigen por la ecuación de onda:

∂2u
- c 2 ∆u = 0.
∂t 2

Cuando la onda de solución es monocromática (y eso depende de la frontera y la inicial


condiciones), u es de la forma u (x, t) = Re (v (x) e ikt ) donde v es una solución de Helmholtz
ecuación:

k 2 v + c 2 ∆v = 0 en Ω,
∂v
| Γ = g. (3,1)
En

donde g es la fuente. Tenga en cuenta el signo "+" delante del operador de Laplace y que k> 0 es
verdadero. Este signo puede hacer que el problema esté mal planteado para algunos valores
k
, unde
fenómeno
c llamado
"resonancia".
En resonancia hay soluciones distintas de cero incluso cuando g = 0. Por tanto, el siguiente programa puede
o puede que no funcione:

Ejemplo 3.4 (sound.edp) // archivo sound.edp


kc2 real = 1;
func g = y * (1-y);

borde a0 (t = 0,1) {x = 5; y = 1 + 2 * t;}


borde a1 (t = 0,1) {x = 5-2 * t; y = 3;}
borde a2 (t = 0,1) {x = 3-2 * t; y = 3-2 * t;}
borde a3 (t = 0,1) {x = 1-t; y = 1;}
borde a4 (t = 0,1) {x = 0; y = 1-t;}
borde a5 (t = 0,1) {x = t; y = 0;}

https://translate.googleusercontent.com/translate_f 33/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
borde a6 (t = 0,1) {x = 1 + 4 * t; y = t;}

Página 39
3.4. CONDUCCION TERMICA 39

malla Th = buildmesh (a0 (20) + a1 (20) + a2 (20)


+ a3 (20) + a4 (20) + a5 (20) + a6 (20));
fespace Vh (Th, P1);
Vh u, v;

resolver sonido (u, v) = int2d (Th) (u * v * kc2 - dx (u) * dx (v) - dy (u) * dy (v))
- int1d (Th, a4) (g * v);
plot (u, espera = 1, ps = "sound.eps");

Los resultados se muestran en la Figura 3.3 . Pero cuando kc2 es un valor propio del problema, entonces la solución
no es único: si u e = 0 es un estado propio, entonces para cualquier solución dada u + u e es otro a
solución. Para encontrar todos los u e uno puede hacer lo siguiente

sigma real = 20; // valor del turno


// OP = A - sigma B; // la matriz desplazada
varf op (u1, u2) = int2d (Th) ( dx (u1) * dx (u2) + dy (u1) * dy (u2) - sigma * u1 * u2);
varf b ([u1], [u2]) = int2d (Th) (u1 * u2); // sin condición de contorno ver nota
9.1

matriz OP = op (Vh, Vh, solucionador = Crout, factorizar = 1);


matriz B = b (Vh, Vh, solucionador = CG, eps = 1e-20);

int nev = 2; // número de valores propios solicitados cerca de sigma

real [int] ev (nev); // para almacenar el valor propio nev


Vh [int] eV (nev); // para almacenar el nev autovector

int k = EigenValue (OP, B, sym = true, sigma = sigma, value = ev, vector = eV,
tol = 1e-10, maxit = 0, ncv = 0);
cout << ev (0) << "2 valores propios" << ev (1) << endl;
v = eV [0];
plot (v, espera = 1, ps = "eigen.eps");

3.4 Conducción Térmica


Resumen Aquí aprenderemos cómo lidiar con un problema parabólico dependiente del tiempo. Nosotros
También mostrará cómo tratar un problema axisimétrico y también mostrará cómo tratar un problema.
problema no lineal.

Cómo el aire enfría un plato Buscamos la distribución de temperatura en un plato (0, Lx) × (0, Ly) ×
(0, Lz) de sección transversal rectangular Ω = (0,6) × (0,1); la placa está rodeada de aire en
temperatura u e e inicialmente a la temperatura u = u 0 + x L
u 1 . En el plano perpendicular
para la placa en z = Lz / 2, la temperatura varía poco con la coordenada z; como primera
aproximación el problema es 2D.

Debemos resolver la ecuación de temperatura en Ω en un intervalo de tiempo (0, T).

∂ t u −∇ · (κ∇u) = 0inΩ × (0, T),


u (x, y, 0) = u 0 + xu 1
∂u
κ + α (u - u e ) = 0onΓ × (0, T). (3,2)
En

https://translate.googleusercontent.com/translate_f 34/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 40
40 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

Figura 3.3: Izquierda: Amplitud de una señal acústica procedente de la pared vertical izquierda. Derecha:
primer estado propio (λ = (k / c) 2 = 19.4256) cerca de 20 del problema de valor propio: −∆ϕ = λϕ y
∂ϕ
En
= 0onΓ

Aquí la difusión κ tomará dos valores, uno debajo de la línea horizontal media y diez veces
menos arriba, para simular un termostato. El término α (u - u e ) explica la pérdida de
temperatura por convección en el aire. Matemáticamente, esta condición de frontera es de Fourier (o
Robin, o mixto).
La formulación variacional está en L 2 (0, T; H 1 (Ω)); en términos sueltos y después de aplicar un
aproximación implícita de Euler en diferencias finitas en el tiempo; buscaremos u n (x, y) satisfactorio para todos
w ∈ H 1 (Ω):
∫ u n - u n−1 ∫
( w + κ∇u n ∇w) + α (u n - u u e) w = 0
Ω δt Γ

func u0 = 10 + 90 * x / 6;
func k = 1.8 * (y <0.5) +0.2;
ue real = 25, alfa = 0,25, T = 5, dt = 0,1;

malla Th = cuadrado (30,5, [6 * x, y]);


fespace Vh (Th, P1);
Vh u = u0, v, uold;

problema térmico (u, v) = int2d (Th) (u * v / dt + k * ( dx (u) * dx (v) + dy (u) * dy (v)))


+ int1d (Th, 1,3) (alfa * u * v)
- int1d (Th, 1,3) (alfa * ue * v)
- int2d (Th) (uold * v / dt) + en (2,4, u = u0);
ofstream ff ("datos térmicos");
para ( t real = 0; t <T; t + = dt) {
uold = u; // uold ≡ u n − 1 = u n ≡u
térmico // aquí resuelve el problema térmico
ff << u (3,0.5) << endl ;

Página 41
3.4. CONDUCCION TERMICA 41

trama (u);
}

https://translate.googleusercontent.com/translate_f 35/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Nótese que debemos separar a mano la parte bilineal de la lineal.


Observe también que la forma en que almacenamos la temperatura en el punto (3,0,5) para todos los tiempos en el archivo
thermic.dat. Si se requiere una gráfica unidimensional, el mismo procedimiento puede ser
usó. Por ejemplo, para imprimir x ↦ → ∂u ∂y (x, 0.9) uno haría

para ( int i = 0; i <20; i ++) cout << dy (u) (6.0 * i / 20.0,0.9) << endl ;

Los resultados se muestran en la Figura 3.4.

56
"thermic.dat"

54

52

50

48

46

44

42

40

38

36

34
0 0,5 1 1,5 2 2.5 3 3,5 4 4.5

Figura 3.4: Temperatura a T = 4.9. Derecha: caída de la temperatura en función del tiempo en x = 3, y = 0,5

3.4.1 Axisimetría: Varilla 3D con sección circular


Tratemos ahora con una varilla cilíndrica en lugar de una placa plana. Por simplicidad, tomamos κ = 1.
En coordenadas cilíndricas, el operador de Laplace se convierte en (r es la distancia al eje, z es
la distancia a lo largo del eje, θ ángulo polar en un plano fijo perpendicular al eje):

1 1
∆u = ∂ r (r∂ r u) + ∂2
r r2 θθ u + ∂2 zz .
La simetría implica que perdemos la dependencia con respecto a θ; entonces el dominio Ω es nuevamente
un rectángulo] 0, R [×] 0, | [. Tomamos la convención de numeración de los bordes como en cuadrado ()
(1 para la horizontal inferior ...); el problema es ahora:

r∂ t u - ∂ r (r∂ r u) - ∂ z (r∂ z u) = 0inΩ,


z
u (t = 0) = u 0 + (u 1 - u)
Lz
∂u
u | Γ = u 0 , u | Γ = u 1 , α (u - u e ) +
4 2 |Γ 1 ∪Γ 3 = 0. (3,3)
En

Página 42
42 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

Tenga en cuenta que la PDE se ha multiplicado por r.


Después de la discretización en el tiempo con un esquema implícito, con pasos de tiempo dt, en FreeFem ++
la sintaxis r se convierte en x y z se convierte en y y el problema es:

problema thermaxi (u, v) = int2d (Th) ((u * v / dt + dx (u) * dx (v) + dy (u) * dy (v)) * x)
+ int1d (Jue, 3) (alfa * x * u * v) - int1d (Jue, 3) (alfa * x * ue * v)
- int2d (Th) (uold * v * x / dt) + en (2,4, u = u0);

Observe que la forma bilineal degenera en x = 0. Aún así, se puede probar la existencia y
singularidad para u y debido a esta degeneración no es necesario imponer condiciones de frontera
https://translate.googleusercontent.com/translate_f 36/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
en Γ 1 .

3.4.2 Un problema no lineal: la radiación


La pérdida de calor por radiación es una pérdida proporcional a la temperatura absoluta al cuarto
poder (Ley de Stefan). Esto se suma a la pérdida por convección y da el siguiente límite
condición:
∂u
κ + α (u - u e ) + c [(u + 273) 4 - (u e + 273) 4 ] = 0
En
El problema no es lineal y debe resolverse de forma iterativa. Si m denota el índice de iteración,
una semilinealización de la condición de radiación da

∂u m + 1
+ α (u m + 1 - u e ) + c (u m + 1 - u e ) (u m + u e + 546) ((u m + 273) 2 + (u e + 273) 2 ) = 0 ,
En

porque tenemos la identidad a 4 - b 4 = (a - b) (a + b) (a 2 + b 2 ). El proceso iterativo


trabajar con v = u - u e .

...
fespace Vh (Th, P1); // espacio de elementos finitos
rad real = 1e-8, uek = ue + 273; // def de las constantes físicas
Vh vold, w, v = u0-ue, b;
problema thermradia (v, w)
= int2d (Th) (v * w / dt + k * ( dx (v) * dx (w) + dy (v) * dy (w)))
+ int1d (Th, 1,3) (b * v * w)
- int2d (Th) (vold * w / dt) + on (2,4, v = u0-ue);

para ( t real = 0; t <T; t + = dt) {


vold = v;
para ( int m = 0; m <5; m ++) {
b = alfa + rad * (v + 2 * uek) * ((v + uek) ˆ2 + uekˆ2);
thermradia;
}
}
vold = v + ue; trama (vold);

3.5 Flujo de aspas de ventilador de irrigación y efectos térmicos


Resumen Aquí aprenderemos cómo lidiar con un sistema multifísico de PDE en un complejo
geometría, con múltiples mallas dentro de un problema. También aprendemos a manipular el
indicador de región y ver qué tan suave es el operador de proyección de una malla a otra.

Página 43
3.5. FLUJO DE LA HOJA DEL VENTILADOR IRROTACIONAL Y EFECTOS TÉRMICOS 43

Flujo incompresible Sin viscosidad ni vorticidad Los flujos incompresibles tienen una velocidad
dada por:
( ∂ψ )
∂x
u= , donde ψ es la solución de ∆ψ = 0
2

- ∂ψ∂x 1

Esta ecuación expresa tanto la incompresibilidad (∇ · u = 0) como la ausencia de vórtice (∇ × u = 0).


A medida que el fluido se desliza a lo largo de las paredes, la velocidad normal es cero, lo que significa que ψ satisface:

ψ constante en las paredes.

También se puede prescribir la velocidad normal en un límite artificial, y esto se traduce en


datos de Dirichlet no constantes para ψ.

https://translate.googleusercontent.com/translate_f 37/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Perfil aerodinámico Consideremos un perfil de ala S en un flujo uniforme. El infinito estará representado por
un gran círculo C donde se supone que el flujo es de velocidad uniforme; una forma de modelar esto
el problema es escribir

∆ψ = 0 en Ω, ψ | S = 0, ψ | C = u ∞ y, (3.4)

donde ∂Ω = C ∪ S

El perfil aerodinámico NACA0012 Una ecuación para la superficie superior de un NACA0012 (esta es una clase
perfil de ala sical en aerodinámica) es:

y = 0,17735 x - 0.075597x - 0.212836x 2 + 0.17363x 3 - 0.06254x 4 .

Ejemplo 3.5 (potencial.edp) // archivo potencial.edp

real S = 99;
borde C (t = 0,2 * pi) {x = 5 * cos (t); y = 5 * sin (t);}
borde Splus (t = 0,1) {x = t; y = 0.17735 * sqrt (t) -0.075597 * t
- 0,212836 * (tˆ2) + 0,17363 * (tˆ3) -0,06254 * (tˆ4); etiqueta = S;}
borde Sminus (t = 1,0) {x = t; y = - (0.17735 * sqrt (t) -0.075597 * t
-0,212836 * (tˆ2) + 0,17363 * (tˆ3) -0,06254 * (tˆ4)); etiqueta = S;}
malla Th = buildmesh (C (50) + Splus (70) + Sminus (70));
fespace Vh (Th, P2); Vh psi, w;

resolver potencial (psi, w) = int2d (Th) ( dx (psi) * dx (w) + dy (psi) * dy (w)) +


en (C, psi = y) + en (S, psi = 0);

plot (psi, espera = 1);

Un zoom de las líneas de corriente se muestra en la Figura 3.5.

Página 44
44 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

IsoValue
-10.9395
-3.12159
2.09037
7.30233
12.5143
17.7262
22.9382
28.1502
33.3621
38.5741
43.7861
48,998
54.21
59.4219
64.6339
69.8459
75.0578
80.2698
85.4817
98.5116

Figura 3.5: Zoom alrededor del perfil aerodinámico NACA0012 mostrando las líneas de corriente (curva ψ = con-
stant). Para obtener dicho gráfico, utilice el comando gráfico interactivo: “+” y p. Derecha:
distribución de temperatura en el tiempo T = 25 (ahora el máximo es 90 en lugar de 120). Nota
que aquí se ha añadido un ángulo de incidencia (véase el Capítulo 9).

https://translate.googleusercontent.com/translate_f 38/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
3.5.1 Convección de calor alrededor de la superficie aerodinámica
Ahora supongamos que el perfil aerodinámico está caliente y que hay aire para enfriarlo. Al igual que en el
sección anterior la ecuación de calor para la temperatura v es

∂v
∂ t v −∇ · (κ∇v) + u · ∇v = 0, v (t = 0) = v 0 , |C=0
En

Pero ahora el dominio está fuera Y dentro de S y κ toma un valor diferente en el aire y en el acero.
Además, hay convección de calor por el flujo, de ahí el término u · ∇v anterior. Considerar
lo siguiente, que se conectará al final del programa anterior:

...
borde D (t = 0,2) {x = 1 + t; y = 0;} // agregado para tener una malla fina en el camino
malla Sh = buildmesh (C (25) + Splus (-90) + Sminus (-90) + D (200));
espacio libre Wh (Sh, P1); Wh v, vv;
int acero = Sh (0.5,0) .region, air = Sh (-1,0) .region;
espacio libre W0 (Sh, P0);
W0 k = 0.01 * ( región == aire) + 0.1 * ( región == acero);
W0 u1 = dy (psi) * ( región == aire), u2 = - dx (psi) * ( región == aire);
Wh vold = 120 * ( región == acero);
dt real = 0,05, nbT = 50;
int i;
problema térmico (v, vv, init = i, solucionador = LU) = int2d (Sh) (v * vv / dt
+ k * ( dx (v) * dx (vv) + dy (v) * dy (vv))
+ 10 * (u1 * dx (v) + u2 * dy (v)) * vv) - int2d (Sh) (vold * vv / dt);
para (i = 0; i <nbT; i ++) {
v = vold; térmico
trama (v);

Página 45
3.6. CONVECCIÓN PURA: LA COLINA GIRATORIA 45

Fíjate aquí

• cómo se identifican el acero y el aire por la región del parámetro de malla que se define cuando
buildmesh se llama y toma un valor entero correspondiente a cada componente conectado
componente de Ω;

• cómo se suman los términos de convección sin ceñir. Upwind es necesario cuando
el número de Pecley | u | L / κ es grande (aquí hay una escala de longitud típica), el factor 10 en
delante de los términos de convección es una forma rápida de multiplicar la velocidad por 10 (de lo contrario,
es demasiado lento para ver algo).

• El solucionador es la factorización LU de Gauss y cuando init = 0 la descomposición LU es


reutilizado, por lo que es mucho más rápido después de la primera iteración.

3.6 Convección pura: la colina giratoria


Resumen Aquí presentaremos dos métodos de ceñida para la convección más simple.
problema. Aprenderemos sobre Characteristics-Galerkin y Discontinuous-Galerkin Finite
Métodos de elementos.
Sea Ω el disco unitario centrado en 0; considere el campo de vector de rotación

u = [u1, u2], u 1 = y, u 2 = −x.

La convección pura por u es

https://translate.googleusercontent.com/translate_f 39/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
∂ t c + u.∇c = 0 en Ω × (0, T) c (t = 0) = c 0 en Ω.

La solución exacta c (x t , t) en el momento t en el punto x t está dada por

c (x t , t) = c 0 (x, 0)

donde x t es la trayectoria de las partículas en el flujo que comienza en el punto x en el tiempo 0. Entonces x t son soluciones de

d (t ↦ → x t )
˙x t = u (x t ), x t = 0 = x, donde ˙x t =
dt

Las EDO son reversibles y queremos la solución en el punto x en el tiempo t (no en el punto x t ) el
el punto inicial es x −t , y tenemos
c (x, t) = c 0 (x −t , 0)

El juego consiste en resolver la ecuación hasta que T = 2π, es decir para una revolución completa y para
compare la solución final con la inicial; deberían ser iguales.

Página 46
46 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

Solución mediante un método de Characteristics-Galerkin En FreeFem ++ hay un operador llamado


convecto ([u1, u2], dt, c) que calcula c ◦ X con X es el campo convecto definido por
X (x) = x dt y donde x τ es la trayectoria de las partículas en el campo de velocidad de estado estable u = [u1, u2]
comenzando en el punto x en el tiempo τ = 0, entonces x τ es la solución de la siguiente EDO:

˙x τ = u (x τ ), x τ = 0 = x.

Cuando u es constante por partes; esto es posible porque x τ es entonces una curva poligonal que
se puede calcular exactamente y la solución existe siempre cuando u está libre de divergencias; convecto
devuelve c (x df ) = C ◦ X.

Ejemplo 3.6 (convects.edp) // archivo convects.edp

borde C (t = 0, 2 * pi) {x = cos (t); y = sin (t); };


malla Th = buildmesh (C (100));
fespace Uh (Th, P1);
Uh frío, c = exp (-10 * ((x-0.3) ˆ2 + (y-0.3) ˆ2));

dt real = 0,17, t = 0;
Uh u1 = y, u2 = -x;
para (int m = 0; m <2 * pi / dt; m ++) {
t + = dt; frío = c;
c = convecto ([u1, u2], - dt, frío);
plot (c, cmm = "t =" + t + ", min =" + c []. min + ", max =" + c []. max);
}

Observación 4 Los gráficos 3D se pueden hacer agregando el calificador ”dim = 3” a la instrucción del gráfico.

El método es muy poderoso pero tiene dos limitaciones: a / no es conservador, b / puede


divergen en casos raros cuando | u | es demasiado pequeño debido a un error de cuadratura.

Solución de Discontinuous-Galerkin FEM Los métodos de Galerkin discontinuos aprovechan


de las discontinuidades de c en los bordes para construir upwind. Hay muchas formulaciones
posible. Implementaremos aquí el llamado DC dual-P 1 formulación (ver Ern [ 16] ):

∫ c n+1 - c n ∫ 1 ∫
( + u · ∇c) w + (α | n · u | - n · u) [c] w = | n · u | cw ∀w
Ω δt mi 2 E -Γ

https://translate.googleusercontent.com/translate_f 40/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
donde E es el conjunto de bordes internos y E - Γ es el conjunto de bordes de frontera donde u · n <0 (en nuestro
caso de que no existan tales bordes). Finalmente [c] es el salto de c a través de un borde con la convención
que c + se refiere al valor a la derecha del borde orientado.

Ejemplo 3.7 (convects end.edp) // archivo convects.edp


...
fespace Vh (Th, P1dc);

Vh w, ccold, v1 = y, v2 = -x, cc = exp (-10 * ((x-0.3) ˆ2 + (y-0.3) ˆ2));


u real , al = 0,5; dt = 0,05;

Página 47
3.6. CONVECCIÓN PURA: LA COLINA GIRATORIA 47

macro n () (Nx * v1 + Ny * v2) // Macro sin parámetro


problema Adual (cc, w) =
int2d (Th) ((cc / dt + (v1 * dx (cc) + v2 * dy (cc))) * w)
+ intalledges (Th) ((1- nTonEdge ) * w * (al * abs (n) -n / 2) * jump (cc))
// - int1d (Th, C) ((n <0) * abs (n) * cc * w) // no utilizado porque cc = 0 en ∂Ω -
- int2d (Th) (ccold * w / dt);

para (t = 0; t <2 * pi; t + = dt)


{
ccold = cc; Adual;
plot (cc, relleno = 1, cmm = "t =" + t + ", min =" + cc []. min + ", max =" + cc []. max);
};
real [int] viso = [- 0.2, -0.1,0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.1];
plot (c, esperar = 1, llenar = 1, ps = "convectCG.eps", viso = viso);
plot (c, esperar = 1, llenar = 1, ps = "convectDG.eps", viso = viso);

Observe las nuevas palabras clave, instancias para integrar en todos los bordes de todos los triángulos.

∑ ∫
intalledges (Th) ≡ (3,5)
T∈Th ∂T

(por lo que todos los bordes internos se ven dos veces), nTonEdge que es uno si el triángulo tiene un límite
edge y dos de lo contrario, salte para implementar [c]. Los resultados de ambos métodos se muestran en la Figura
3.6 con niveles idénticos para la línea de nivel; esto se hace con el modificador de trama viso.
Observe también la macro donde no se usa el parámetro u (pero la sintaxis necesita uno) y
que termina con un //; simplemente reemplaza el nombre n por (Nx * v1 + Ny * v2). Tan fácilmente
adivinó Nx, Ny es la normal al borde.

IsoValue IsoValue
-0,1 -0,1
0 0,5 0 0,5

0,1 0,1
0,5 0,5
0,2 0,2
0,25 0,25
0,3 0,3
0,35 0,35
0.4 0.4
0,45 0,45
0,5 0,5
0,55 0,55
0,6 0,6
0,65 0,65
0,7 0,7
0,75 0,75
0,8 0,8
0,9 0,9
1 1

Figura 3.6: La colina girada después de una revolución, a la izquierda con Características-Galerkin, en la
derecha con Discontinuous P 1 Galerkin FEM.
https://translate.googleusercontent.com/translate_f 41/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Ahora, si crees que DG es demasiado lento, prueba esto

Página 48
48 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

// el mismo DG mucho más rápido


varf aadual (cc, w) = int2d (Th) ((cc / dt + (v1 * dx (cc) + v2 * dy (cc))) * w)
+ intalledges (Th) ((1- nTonEdge ) * w * (al * abs (n) -n / 2) * jump (cc));
varf bbdual (ccold, w) = - int2d (Th) (ccold * w / dt);
matriz AA = aadual (Vh, Vh);
matriz BB = bbdual (Vh, Vh);
set (AA, init = t, solver = sparsesolver);
Vh rhs = 0;
para (t = 0; t <2 * pi; t + = dt)
{
ccold = cc;
rhs [] = BB * ccold [];
cc [] = AAˆ-1 * rhs [];
plot (cc, fill = 0, cmm = "t =" + t + ", min =" + cc []. min + ", max =" + cc []. max);
};

Observe el nuevo conjunto de palabras clave para especificar un solucionador en este marco; se usa el modificador init
para decirle al solucionador que la matriz no ha cambiado (init = true), y el parámetro de nombre es
lo mismo que en la definición del problema (ver. 6 .9) .

Los métodos de volumen finito también se pueden manejar con FreeFem ++ pero requiere programa-
ming. Por ejemplo, el método de volumen finito P 0 - P 1 de Dervieux et al se asocia a cada
P 0 función c 1 a P 0 función c 0 con valor constante alrededor de cada vértice q i igual ac 1 (q i ) en
la celda σ i formada por todas las medianas de todos los triángulos que tienen q i como vértice. Entonces el upwind es
hecho tomando valores de izquierda o derecha en la mediana:

∫ 1 ∫
(c 1n + 1 - c 1n ) + u · nc - = 0 ∀i
σ yo δt ∂σ yo

Puede programarse como

cargar "mat_dervieux"; // se debe cargar el módulo externo en C ++


borde a (t = 0, 2 * pi) {x = cos (t); y = sin (t); }
malla th = buildmesh (a (100));
fespace Vh (th, P1);

Vh vh, vold, u1 = y, u2 = -x;


Vh v = exp (-10 * ((x-0.3) ˆ2 + (y-0.3) ˆ2)), vWall = 0, rhs = 0;

dt real = 0,025;
// qf1pTlump significa que se utiliza agrupamiento de masa
problema FVM (v, vh) = int2d (th, qft = qf1pTlump) (v * vh / dt)
- int2d (th, qft = qf1pTlump) (vold * vh / dt)
+ int1d (th, a) (((u1 * N.x + u2 * Ny) <0) * (u1 * N.x + u2 * Ny) * vWall * vh)
+ rhs [];

matriz A;
MatUpWind0 (A, th, vold, [u1, u2]);

para ( int t = 0; t <2 * pi; t + = dt) {


vold = v;
rhs [] = A * vold []; FVM;

https://translate.googleusercontent.com/translate_f 42/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 49
3.7. EL SISTEMA DE ELASTICIDAD 49

plot (v, espera = 0);


};

el parámetro de agrupamiento de masa fuerza una fórmula de cuadratura con puntos de Gauss en los vértices
para hacer diagonal la matriz de masas; el sistema lineal resuelto por un gradiente conjugado
El método, por ejemplo, convergerá en una o dos iteraciones.
El lado derecho rhs se calcula mediante una función externa de C ++ MatUpWind0 (...)
que está programado como

// calcula la matriz a en un triángulo para Dervieux FVM


En t fvmP1P0 ( doble q [3] [2], // los 3 vértices de un triángulo T
doble u [2], // velocidad de convección en T
doble c [3], // la función P1 en T
doble a [3] [3], // matriz de salida
doble donde [3]) // donde> 0 significa que estamos en el límite
{
para ( int i = 0; i <3; i ++) para ( int j = 0; j <3; j ++) a [i] [j] = 0;

para ( int i = 0; i <3; i ++) {


int ip = (i + 1)% 3, ipp = (ip + 1)% 3;
doble unL = - ((q [ip] [1] + q [i] [1] -2 * q [ipp] [1]) * u [0]
- (q [ip] [0] + q [i] [0] -2 * q [ipp] [0]) * u [1]) / 6;
si (unL> 0) {a [i] [i] + = unL; a [ip] [i] - = unL;}
else {a [i] [ip] + = unL; a [ip] [ip] - = unL;}
if (donde [i] && donde [ip]) { // este es un borde limítrofe
unL = ((q [ip] [1] -q [i] [1]) * u [0] - (q [ip] [0] -q [i] [0]) * u [1]) / 2;
si (unL> 0) {a [i] [i] + = unL; a [ip] [ip] + = unL;}
}
}
return 1;
}

Debe insertarse en un archivo .cpp más grande, que se muestra en el Apéndice A, que es el módulo de carga
vinculado a FreeFem ++.

3.7 El sistema de elasticidad


Elasticidad Los objetos sólidos se deforman bajo la acción de fuerzas aplicadas: un punto en el sólido,
originalmente en (x, y, z) llegará a (X, Y, Z) después de algún tiempo; el vector u = (u 1 , u 2 , u 3 ) =
(X - x, Y - y, Z - z) se llama desplazamiento. Cuando el desplazamiento es pequeño y el
el sólido es elástico, la ley de Hooke da una relación entre el tensor de tensión σ (u) = (σ ij (u))
y el tensor de deformación ϵ (u) = ϵ ij (u)

σ ij (u) = λδ ij ∇.u + 2µϵ ij (u),

donde el símbolo de Kronecker δ ij = 1 si i = j, 0 en caso contrario, con

1 ∂u yo ∂u j
ϵ ij (u) = ( + ),
2 ∂x j ∂x i

Página 50
50 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

https://translate.googleusercontent.com/translate_f 43/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
y donde λ, µ son dos constantes que describen las propiedades mecánicas del sólido, y
ellos mismos están relacionados con las constantes más conocidas E, módulo de Young y ν, Poisson
proporción:
mi Eν
µ= ,λ= .
2 (1 + ν) (1 + ν) (1 - 2ν)

Sistema de Lamé Consideremos una viga de eje Oz y sección perpendicular Ω. La


componentes a lo largo de xey de la deformación u (x) en una sección Ω sujeta a fuerzas f perpendiculares
al eje se rigen por

−µ∆u - (µ + λ) ∇ (∇.u) = f en Ω,

donde λ, µ son los coeficientes de Lamé introducidos anteriormente.


Observación, no usamos esta ecuación porque la forma variacional asociada no
dar la condición de contorno correcta, simplemente usamos

−div (σ) = f enΩ

donde la forma de variación correspondiente es:

∫ ∫
σ (u): ϵ (v) dx - vf dx = 0;
Ω Ω

donde: denota el producto escalar tensorial, es decir, a: b = ∑ yo, j


a ij b ij .
Entonces, la forma variante se puede escribir como:

∫ ∫
λ∇.u∇.v + 2µϵ (u): ϵ (v) dx - vf dx = 0;
Ω Ω

Ejemplo Considere una placa elástica con forma de rectángulo no deformado [0,20] × [−1,1]. La
la fuerza del cuerpo es la fuerza de gravedad f y la fuerza límite g es cero en la parte inferior, superior y derecha
lados. Los lados verticales izquierdos de la viga están fijos. Las condiciones de contorno son

σ.n = g = 0 en Γ 1 , Γ 4 , Γ 3 ,
u = 0 en Γ 2

Aquí u = (u, v) tiene dos componentes.

Las dos ecuaciones anteriores están fuertemente acopladas por sus derivadas mixtas y, por lo tanto, cualquier
La solución iterativa en cada uno de los componentes es arriesgada. Es preferible utilizar FreeFem ++
enfoque del sistema y escribir:

Ejemplo 3.8 (lame.edp) // archivo lame.edp


malla Th = cuadrado (10,10, [20 * x, 2 * y-1]);
fespace Vh (Th, P2);
Vh u, v, uu, vv;
sqrt2 real = sqrt (2.);
macro épsilon (u1, u2) [dx (u1), dy (u2), (dy (u1) + dx (u2)) / sqrt2] // MOE

Página 51
3.8. EL SISTEMA DE STOKES PARA FLUIDOS 51

// la sqrt2 es porque queremos: epsilon (u1, u2) '* epsilon (v1, v2)
== ϵ (u): ϵ (v)
macro div (u, v) (dx (u) + dy (v)) // MOE

E real = 21e5, nu = 0,28, mu = E / (2 * (1 + nu));


lambda real = E * nu / ((1 + nu) * (1-2 * nu)), f = -1; //

https://translate.googleusercontent.com/translate_f 44/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
resolver cojo ([u, v], [uu, vv]) = int2d (Th) (
lambda * div (u, v) * div (uu, vv)
+ 2. * mu * ( épsilon (u, v) '* épsilon (uu, vv)))
- int2d (Th) (f * vv)
+ en (4, u = 0, v = 0);
coef real = 100;
plot ([u, v], espera = 1, ps = "lamevect.eps", coef = coef);

malla th1 = movemesh (Th, [x + u * coef, y + v * coef]);


plot (th1, espera = 1, ps = "lamedeform.eps");
dxmin real = u []. min;
dymin real = v []. min;

cout << "- dep. máx. x = "<< dxmin <<" y = "<< dymin << endl;
cout << " dep. (20,0) = "<< u (20,0) <<" "<< v (20,0) << endl;

Los resultados numéricos se muestran en la figura 3.7 y el resultado es:

- malla cuadrada: nb vértices = 121, nb triángulos = 200, nb bordes límite 40


-- Resolver : mín. -0,00174137 máx. 0,00174105
mín. -0.0263154 máx. 1.47016e-29
- dep. max x = -0,00174137 y = -0,0263154
dep. (20,0) = -1.8096e-07 -0.0263154
veces: compila 0.010219s, ejecución 1.5827s

3.8 El sistema de Stokes para fluidos


En el caso de un flujo invariante con respecto a la tercera coordenada (flujo bidimensional),
Los flujos con un número de Reynolds bajo (por ejemplo, microorganismos) satisfacen,

−∆u + ∇p = 0
∇·u=0

donde u = (u 1 , u 2 ) es la velocidad del fluido yp su presión.


La cavidad impulsada es una prueba estándar. Es una caja llena de líquido con su tapa moviéndose horizontalmente
a la velocidad uno. La presión y la velocidad deben discretizarse en un elemento fintie compatible
espacios para que se cumplan las condiciones LBB:

(u, ∇p)
sorber ≥ β | u | ∀u ∈ U h
p∈P h |p|

// archivo stokes.edp

Página 52
52 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

https://translate.googleusercontent.com/translate_f 45/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 3.7: Solución de las ecuaciones de Lamé para la elasticidad para una viga 2D desviada por su propia
peso y sujetado por su lado vertical izquierdo; el resultado se muestra con un factor de amplificación
igual a 100. Observación: el tamaño de la flecha se enlaza automáticamente, pero el color da el
longitud real

int n = 3;
malla Th = cuadrado (10 * n, 10 * n);
fespace Uh (Th, P1b); Uh u, v, uu, vv;
fespace Ph (Th, P1); Ph p, págs;

resolver stokes ([u, v, p], [uu, vv, pp]) =


int2d (Th) ( dx (u) * dx (uu) + dy (u) * dy (uu) + dx (v) * dx (vv) + dy (v) * dy (vv)
+ dx (p) * uu + dy (p) * vv + pp * ( dx (u) + dy (v))
- 1e-10 * p * pp)
+ en (1,2,4, u = 0, v = 0) + en (3, u = 1, v = 0);
plot ([u, v], p, espera = 1);

Observe, agregamos un término de estabilización -10e-10 * p * pp para fijar la parte constante de la presión.

Los resultados se muestran en la figura 3.8.

3.9 Un algoritmo de proyección para las ecuaciones de Navier-Stokes


Resumen Los flujos de fluidos requieren buenos algoritmos y buenas triangulaciones. Mostramos aquí un
ejemplo de un algoritmo complejo y / o primer ejemplo de adaptación de malla.

Un fluido viscoso incompresible satisface:

∂ t u + u · ∇u + ∇p - ν∆u = 0, ∇ · u = 0 en Ω ×] 0, T [,

u | t=0 = u 0 , u | Γ = u Γ .

Página 53
3.9. ALGORITMO DE PROYECCIÓN PARA LAS ECUACIONES DE NAVIER-STOKES 53

Figura 3.8: Solución de las ecuaciones de Stokes para el problema de la cavidad impulsada, que muestra la velocidad
campo y las líneas de nivel de presión.

Un posible algoritmo, propuesto por Chorin, es

https://translate.googleusercontent.com/translate_f 46/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

1
[u m + 1 - u m oX m ] + ∇p m - ν∆u m = 0, u | Γ = u Γ , ν∂ n u | Γ fuera =0
δt

−∆p m + 1 = −∇ · u m oX m , ∂ n p m + 1 = 0onΓ, p m + 1 = 0onΓ fuera

donde uoX (x) = u (x - u (x) δt) ya que ∂ t u + u · ∇u se aproxima por el método de la característica
terísticas, como en la sección anterior.

Usamos el algoritmo de s Chorin con condición de límite libre en la salida (es decir, p = 0, ν∂ n u = 0),
para calcular una corrección, q, a la presión.

−∆q = ∇ · u, q = 0onΓ fuera

y definir
u m + 1 = ˜u + P∇qδt, p m + 1 = p m - q

donde ˜u es el (u m + 1 , v m + 1 ) del algoritmo de Chorin, y donde P es la proyección L 2 con


agrupamiento de masa (una matriz escasa).

El escalón orientado hacia atrás La geometría es la de un canal con un escalón orientado hacia atrás
de modo que la sección de entrada sea más pequeña que la sección de salida. Esta geometría produce un fluido
zona de recirculación que debe capturarse correctamente.
Esto solo se puede hacer si la triangulación es suficientemente fina o bien adaptada al flujo.
Observación (FH), Son una dificultad técnica es el ejemplo, es la salida BC, aquí ponemos
p = 0 y ν∂ n u = 0.

Página 54
54 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

Ejemplo 3.9 (NSprojection.edp) // archivo NSprojection.edp


// Versión julio 2014,
// FH. Cambie BC en u en la salida, más simple ..
// ............
verbosidad = 0;
borde a0 (t = 1,0) {x = -2; y = t; etiqueta = 1;}
borde a1 (t = -2,0) {x = t; y = 0; etiqueta = 2;}
borde a2 (t = 0, -0,5) {x = 0; y = t; etiqueta = 2;}
borde a3 (t = 0,1) {x = 18 * tˆ1.2; y = -0,5; etiqueta = 2;}
borde a4 (t = -0.5,1) {x = 18; y = t; etiqueta = 3;}
borde a5 (t = 1,0) {x = -2 + 20 * t; y = 1; etiqueta = 4;}
int n = 1;
malla Th = buildmesh (a0 (3 * n) + a1 (20 * n) + a2 (10 * n) + a3 (150 * n) + a4 (5 * n) + a5 (100 * n));

trama (Th);
fespace Vh (Th, P1);
nu real = 0,0025, dt = 0,2; // Reynolds = 200

Vh w, u = 0, v = 0, p = 0, q = 0;

epsv real = 1e-6, epsu = 1e-6, epsp = 1e-6; // EPS CG ..

// def de Matrix dtMx y dtMy


matriz dtM1x, dtM1y;

macro BuildMat ()
{/ * para memory managenemt * /
varf vM (sin usar, v) = int2d (Th) (v);
varf vdx (u, v) = int2d (Th) (v * dx (u) * dt);
varf vdy (u, v) = int2d (Th) (v * dy (u) * dt);

real [ int ] Mlump = vM (0, Vh);


real [ int ] uno (Vh.ndof); uno = 1;

https://translate.googleusercontent.com/translate_f 47/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
real [ int ] M1 = uno ./ Mlump;
matriz dM1 = M1;
matriz Mdx = vdx (Vh, Vh);
matriz Mdy = vdy (Vh, Vh);
dtM1x = dM1 * Mdx;
dtM1y = dM1 * Mdy;
} // EOF

BuildMat

err real = 1, flujo de salida = 1;


para ( int n = 0; n <300; n ++)
{
Vh uold = u, vold = v, pold = p;

resolver pb4u (u, w, init = n, solver = CG, eps = epsu)


= int2d (Th) (u * w / dt + nu * (dx (u) * dx (w) + dy (u) * dy (w)))
- int2d (Th) ((convect ([uold, vold], - dt, uold) / dt-dx (p)) * w)
+ en (1, u = 4 * y * (1-y)) + en (2,4, u = 0); // Neuman en Gamma 3

trama (u);

resolver pb4v (v, w, init = n, solver = CG, eps = epsv)

Página 55
3.9. ALGORITMO DE PROYECCIÓN PARA LAS ECUACIONES DE NAVIER-STOKES 55

= int2d (Th) (v * w / dt + nu * (dx (v) * dx (w) + dy (v) * dy (w)))


- int2d (Th) ((convect ([uold, vold], - dt, vold) / dt-dy (p)) * w)
+ en (1,2,3,4, v = 0);

resolver pb4p (q, w, solucionador = CG, init = n, eps = epsp) = int2d (Th) (dx (q) * dx (w) + dy (q) * dy (w))
- int2d (Th) ((dx (u) + dy (v)) * w / dt) + en (3, q = 0);

// tener épsilon absoluto en el algoritmo CG.


epsv = -abs (epsv);
epsu = -abs (epsu);
epsp = -abs (epsp);

p = pold-q;
u [] + = dtM1x * q [];
v [] + = dtM1y * q [];

si (n% 50 == 49) {
Th = adaptmesh (Th, [u, v], q, err = 0.04, nbvx = 100000);
trama (Th, espera = verdadero);
BuildMat // reconstruir la alfombra.
}

err = sqrt (int2d (Th) (cuadrado (u-uold) + cuadrado (v-vold)) / Th.area);


flujo de salida = int1d (Th) ([u, v] '* [Nx, Ny]);
cout << "iter" << n << "Err L2 =" << err
<< "ordenación de flujo =" << flujo de salida << endl;
si (err <1e-3) romper;
}
afirmar (abs (flujo de salida) <2e-3); // verificación ...
plot (p, espera = 1, ps = "NSprojP.eps");
plot (u, espera = 1, ps = "NSprojU.eps");

https://translate.googleusercontent.com/translate_f 48/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 3.9: Algoritmo de proyección de Rannacher: resultado en una malla adaptada (arriba) que muestra el
presión (media) y la velocidad horizontal u en Reynolds 400.

Mostramos en la figura 3.9 los resultados numéricos obtenidos para un número de Reynolds de 400 donde
La adaptación de la malla se realiza después de 50 iteraciones en la primera malla.

Página 56
56 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

3.10 Método de Newton para las ecuaciones de Steady Navier-Stokes


El problema es encontrar el campo de velocidad u = (u i ) d
i = 1 y la presión p de un flujo que satisface en
el dominio Ω ⊂ R d (d = 2,3):

(u · ∇) u - ν∆u + ∇p = 0,
∇·u=0

donde ν es la viscosidad del fluido, ∇ = (∂ i ) d


i=1 , el producto escalar es ·, y ∆ = ∇ · ∇ con
las algunas condiciones de contorno (u se da en Γ)

La forma débil es encontrar u, p tal que para ∀v (cero en Γ), y ∀q


((u · ∇) u) .v + ν∇u: ∇v - p∇ · v - q∇ · u = 0 (3,6)
Ω

El algoritmo de Newton para resolver un problema no lineal es


Encuentre u ∈ V tal que F (u) = 0 donde F: V ↦ → V.

1. elija u 0 ∈ R n ,;

2. para (i = 0; i ¡niter; i = i + 1)

(a) resuelva DF (u i ) w i = F (u i );
(b) u yo + 1 = u yo - w yo ;

romper || w i || <ε.

Donde DF (u) es el diferencial de F en el punto u, esta es una aplicación lineal tal que:
F (u + δ) = F (u) + DF (u) δ + o (δ)
Para Navier Stokes, F y DF son:


F (u, p) = ((u · ∇) u) .v + ν∇u: ∇v - p∇ · v - q∇ · u
Ω

DF (u, p) (δu, δp) = ((δu · ∇) u) .v + ((u · ∇) δu) .v
Ω
+ ν∇δu: ∇v - δp∇ · v - q∇ · δu

Entonces el algoritmo de Newton se convirtió

Ejemplo 3.10 (NSNewton.edp) ...


para (n = 0; n <15; n ++)
{ resolver Oseen ([du1, du2, dp], [v1, v2, q]) =

https://translate.googleusercontent.com/translate_f 49/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
int2d (Th) (nu * (Grad (du1, du2) '* Grad (v1, v2))
+ UgradV (du1, du2, u1, u2) '* [v1, v2]
+ UgradV (u1, u2, du1, du2) '* [v1, v2]
- div (du1, du2) * q - div (v1, v2) * dp
- 1e-8 * dp * q // término de estabilización
)

Página 57
3.10. MÉTODO DE NEWTON PARA LAS ECUACIONES DE NAVIER STOKES ESTABLE 57

- int2d (Th) (nu * (Grad (u1, u2) '* Grad (v1, v2))
+ UgradV (u1, u2, u1, u2) '* [v1, v2]
- div (u1, u2) * q - div (v1, v2) * p
)
+ en (1, du1 = 0, du2 = 0);
u1 [] - = du1 []; u2 [] - = du2 []; p [] - = dp [];
err = du1 []. linfty + du2 []. linfty + dp []. linfty;
si (err <eps) romper ;
si (n> 3 && err> 10.) romper ; // explotar ????
}

Con el operador:

macro Grad (u1, u2) [dx (u1), dy (u1), dx (u2), dy (u2)] //


macro UgradV (u1, u2, v1, v2) [[u1, u2] '* [dx (v1), dy (v1)],
[u1, u2] '* [dx (v2), dy (v2)]] //
macro div (u1, u2) (dx (u1) + dy (u2)) //

Construimos una malla de cálculo en el exterior de un cilindro 2d.

real R = 5, L = 15;
borde cc (t = 0,2 * pi) {x = cos (t) / 2; y = sin (t) / 2; etiqueta = 1;}
frontera ce (t = pi / 2,3 * pi / 2) {x = cos (t) * R; y = sin (t) * R; etiqueta = 1;}
borde beb (tt = 0,1) {real t = ttˆ1.2; x = t * L; y = -R; etiqueta = 1;}
borde beu (tt = 1,0) {real t = ttˆ1.2; x = t * L; y = R; etiqueta = 1;}
borde beo (t = -R, R) {x = L; y = t; etiqueta = 0;}
borde bei (t = -R / 4, R / 4) {x = L / 2; y = t; etiqueta = 0;}
malla Th = buildmesh (cc (-50) + ce (30) + beb (20) + beu (20) + beo (10) + bei (10));
trama (Th);

// cuadro delimitador para la trama


func bb = [[- 1, -2], [4,2]];

/ Capucha FE Space Taylor


espacio libre Xh (Th, P2); // por volicidad
fespace Mh (Th, P1); // para presionar
Xh u1, u2, v1, v2, du1, du2, u1p, u2p;
Mh p, q, dp, pp;

// conjetura inicial con BC


u1 = (xˆ2 + yˆ2)> 2;
u2 = 0;

Finalmente usamos truco para continuar con la viscosidad ν, porque el método de Newton
la explosión debe comenzar con la viscosidad final ν

// Parámetro físico
nu real = 1./50, nufinal = 1/200. , cnu = 0,5;

// prueba de parada para Newton


eps real = 1e-6;

verbosidad = 0;
mientras (1) // Bucle de viscosidad
{ int n;
err real = 0; // errar en Newton algo ...

https://translate.googleusercontent.com/translate_f 50/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 58
58 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

... pon el nuevo algoritmo de Newton aquí

si (err <eps)
{ // converger disminuir ν (más difícil)
plot ([u1, u2], p, esperar = 1, cmm = "rey =" + 1./nu, coef = 0.3, bb = bb);
if (nu == nufinal) romper;
si (n <4) cnu = cnuˆ1.5; // convergencia rápida => cambiar más rápido
nu = max (nufinal, nu * cnu); // nueva vicosidad
u1p = u1; u2p = u2; pp = p; // guardar la solución correcta ...
}
demás
{ // aumento de explosión ν (más simple)
afirmar (cnu <0,95); // el método finalmente explota
nu = nu / cnu; // obtener el valor anterior de viscosidad
cnu = cnuˆ (1./1.5); // sin conv. => cambiar más bajo
nu = nu * cnu; // nueva viscosidad
cout << "reiniciar nu =" << nu << "Rey =" << 1./nu << "(cnu =" << cnu << "
) \ n ";
// restaurar una solución correcta ..
u1 = u1p;
u2 = u2p;
p = pp;
}
}

Figura 3.10: Malla y velocidad y presión en Reynolds 200

3.11 Un gran problema de fluidos


Un amigo de uno de nosotros en Auroville-India estaba construyendo una rampa para acceder a un aire acondicionado
habitación. Mientras visitaba el sitio de construcción, me dijo que esperaba que el aire fresco se escapara.
junto a la puerta de la habitación para deslizarse por la rampa y refrigerar los pies de los próximos visitantes.
Le dije "de ninguna manera" y decidí verificar numéricamente. Los resultados están en la portada de
este libro.
La velocidad y la presión del fluido son una solución de las ecuaciones de Navier-Stokes con variaciones

Página 59

https://translate.googleusercontent.com/translate_f 51/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
3.11. UN GRAN PROBLEMA DE FLUIDO 59

función de densidad de la temperatura.


La geometría es trapezoidal con entrada prescrita hecha de aire frío en la parte inferior y
aire caliente arriba y también las condiciones iniciales; hay flujo de salida libre, velocidad de deslizamiento en la parte superior
límite (artificial) y antideslizante en la parte inferior. Sin embargo, la temperatura acumulada de Navier-Stokes
Las ecuaciones tienen un modelo RANS k − ϵ y una aproximación de Boussinesq para la flotabilidad. Esto
viene a

∂ t θ + u∇θ −∇ · (κ m
T ∇θ) = 0
∂ t u + u∇u −∇ · (µ T ∇u) + ∇p + e (θ - θ 0 ) e 2 , ∇ · u = 0
k2
µT=cµ , κ T = κµ T
ϵ
µT
∂ t k + u∇k + ϵ −∇ · (µ T ∇k) = | ∇u + ∇u T | 2
2
ϵ2 cϵ c1
∂ t ϵ + u∇ϵ + c 2 - ∇ · (µ T ∇ϵ) = k | ∇u + ∇u T | 2 = 0 (3,7)
k cµ 2

Usamos una discretización del tiempo que preserva la positividad y usa el método de características
(X metro (x) ≈ x - u metro (x) δt)

1
(θ m + 1 - θ m ◦ X m ) −∇ · (κ m
δt T ∇θ m + 1 ) = 0
1
(u m + 1 - u m ◦ X m ) −∇ · (µ m
δt T∇u m + 1 ) + ∇p m + 1 + mi (θ m + 1 - θ 0 ) mi 2 , ∇ · u m + 1 = 0
1 µ Tm
(k m + 1 - k m ◦ X m ) + k m + 1 ϵ m −∇ · (µ m | ∇u m + ∇u mT | 2
δt km T ∇k m + 1 ) = 2
1 cϵ c1
(ϵ m + 1 - ϵ m ◦ X m ) + c 2 ϵ m + 1 ϵ m - ∇˙ (µ m k m | ∇u m + ∇u mT | 2
δt km cµ T ∇ϵ m + 1 ) = 2
k m + 12
µ Tm + 1 = c µ , κ m +T 1 = κµ m T+ 1 (3,8)
ϵ m+1

En forma variacional y con condiciones de contorno apropiadas, el problema es:

real L = 6;
borde aa (t = 0,1) {x = t; y = 0;}
borde bb (t = 0,14) {x = 1 + t; y = - 0,1 * t;}
frontera cc (t = -1,4, L) {x = 15; y = t;}
borde dd (t = 15,0) {x = t; y = L;}
borde ee (t = L, 0.5) {x = 0; y = t;}
borde ff (t = 0.5,0) {x = 0; y = t;}
int n = 8;
malla Th = buildmesh (aa (n) + bb (9 * n) + cc (4 * n) + dd (10 * n) + ee (6 * n) + ff (n));
real s0 = reloj ();

fespace Vh2 (Th, P1b); // espacio de velocidad


fespace Vh (Th, P1); // espacio de presión
fespace V0h (Th, P0); // para gradientes
Vh2 u2, v2, up1 = 0, up2 = 0;
Vh2 u1, v1;
Vh u1x = 0, u1y, u2x, u2y, vv;

reylnods reales = 500;


// cout << "Introduzca el número de Reynolds:"; cin >> reylnods;
afirmar (reylnods> 1 && reylnods <100000);

Página 60
60 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

up1 = 0;
up2 = 0;
func g = (x) * (1-x) * 4; // afluencia
Vh p = 0, q, temp1, temp = 35, k = 0,001, k1, ep = 0,0001, ep1;
V0h muT = 1, prodk, prode, kappa = 0.25e-4, estrés;
alfa real = 0, eee = 9,81 / 303, c1m = 1,3 / 0,09;

https://translate.googleusercontent.com/translate_f 52/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
real nu = 1, numu = nu / sqrt (0.09), nuep = pow (nu, 1.5) /4.1;
int i = 0, iter = 0;
dt real = 0;
Problema TEMPERATURA (temp, q) = // ecuación de temperatura
int2d (Th) (
alpha * temp * q + kappa * (dx (temp) * dx (q) + dy (temp) * dy (q)))
// + int1d (Th, aa, bb) (temp * q * 0.1)
+ int2d (Th) (-alpha * convect ([up1, up2], - dt, temp1) * q)
+ encendido (ff, temp = 25)
+ encendido (aa, bb, temp = 35);

problema kine (k, q) = // obtener la energía cinética turbulenta


int2d (Th) (
(ep1 / k1 + alfa) * k * q + muT * (dx (k) * dx (q) + dy (k) * dy (q)))
// + int1d (Th, aa, bb) (temp * q * 0.1)
+ int2d (Th) (prodk * q-alpha * convect ([up1, up2], - dt, k1) * q)
+ en (ff, k = 0.0001) + en (aa, bb, k = numu * estrés);

problema viscturb (ep, q) = // obtener la tasa de energía viscosa turbulenta


int2d (Th) (
(1,92 * ep1 / k1 + alfa) * ep * q + c1m * muT * (dx (ep) * dx (q) + dy (ep) * dy (q)
))
// + int1d (Th, aa, bb) (temp * q * 0.1)
+ int2d (Th) (prode * q-alpha * convect ([up1, up2], - dt, ep1) * q)
+ on (ff, ep = 0.0001) + on (aa, bb, ep = nuep * pow (estrés, 1,5));

resolver NS ([u1, u2, p], [v1, v2, q]) = // Navier-Stokes k-epsilon y Boussinesq
int2d (Th) (
alfa * (u1 * v1 + u2 * v2)
+ muT * (dx (u1) * dx (v1) + dy (u1) * dy (v1) + dx (u2) * dx (v2) + dy (u2) * dy (v2))
// (2 * dx (u1) * dx (v1) + 2 * dy (u2) * dy (v2) + (dy (u1) + dx (u2)) * (dy (v1) + dx (v2)))
+ p * q * (0,000001)
- p * dx (v1) - p * dy (v2)
- dx (u1) * q - dy (u2) * q
)
+ int1d (Th, aa, bb, dd) (u1 * v1 * 0.1)
+ int2d (Th) (eee * (temp-35) * v1 -alpha * convect ([up1, up2], - dt, up1) * v1
-alpha * convect ([up1, up2], - dt, up2) * v2)
+ encendido (ff, u1 = 3, u2 = 0)
+ encendido (ee, u1 = 0, u2 = 0)
+ encendido (aa, dd, u2 = 0)
+ encendido (bb, u2 = -up1 * Nx / Ny)
+ encendido (cc, u2 = 0);
plot (coef = 0.2, cmm = "[u1, u2] et p", p, [u1, u2], ps = "StokesP2P1.eps", valor = 1, espera = 1);
{
real [int] xx (21), yy (21), pp (21);
para ( int i = 0; i <21; i ++)
{
aa [i] = i / 20 .;

Página 61
3.11. UN GRAN PROBLEMA DE FLUIDO 61

xx [i] = u1 (0.5, i / 20.);


pp [i] = p (i / 20., 0,999);
}
cout << "" << yy << endl;
// plot ([xx, yy], espera = 1, cmm = "u1 x = 0.5 taza");
// plot ([yy, pp], espera = 1, cmm = "presión y = 0.999 taza");
}

dt = 0,05;
int nbiter = 3;
coefdt real = 0.25ˆ (1./nbiter);
coefcut real = 0.25ˆ (1./nbiter), corte = 0.01;
tol real = 0.5, coeftol = 0.5ˆ (1./nbiter);

https://translate.googleusercontent.com/translate_f 53/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
nu = 1. / reylnods;

para (iter = 1; iter <= nbiter; iter ++)


{
cout << "dt =" << dt << "------------------------" << endl;
alfa = 1 / dt;
para (i = 0; i <= 500; i ++)
{
up1 = u1;
up2 = u2;
temp1 = max (temp, 25);
temp1 = min (temp1,35);
k1 = k; ep1 = ep;
muT = 0,09 * k * k / ep;
NS; plot ([u1, u2], espera = 1); // Resuelve Navier-Stokes
prode = 0,126 * k * (pow (2 * dx (u1), 2) + pow (2 * dy (u2), 2) + 2 * pow (dx (u2) + dy (u1), 2)) / 2 ;
prodk = prode * k / ep * 0.09 / 0.126;
kappa = muT / 0,41;
estrés = abs (dy (u1));
vacas; plot (k, espera = 1);
viscturb; trama (ep, espera = 1);
TEMPLAR; // resuelve la ecuación de temperatura
si (! (i% 5)) {
plot (temp, value = 1, fill = true, ps = "temp _" + iter + "_" + i + ". ps");
plot (coef = 0.2, cmm = "[u1, u2] et p", p, [u1, u2], ps = "plotNS _" + iter + "_" + i + ". ps");
}
cout << "CPU" << reloj () - s0 << "s" << endl;
}

if (iter> = nbiter) break ;


Th = adaptmesh (Th, [dx (u1), dy (u1), dx (u1), dy (u2)], splitpbedge = 1,
abserror = 0, cutoff = cut, err = tol, inquire = 0, ratio = 1.5, hmin = 1. / 1000);
plot (Th, ps = "ThNS.eps");
dt = dt * coefdt;
tol = tol * coeftol;
cortar = cortar * coefcut;
}
cout << "CPU" << reloj () -s0 << "s" << endl;

Página 62
62 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

3.12 Un ejemplo con números complejos


En un horno de microondas, el calor proviene de la excitación molecular por un campo electromagnético. Para
una onda plana monocromática, la amplitud viene dada por la ecuación de Helmholtz:

βv + ∆v = 0.

Consideramos un horno rectangular donde la onda es emitida por parte de la pared superior. Entonces el
el límite del dominio está formado por una parte Γ 1 donde v = 0 y por otra parte Γ 2 = [c, d]
donde, por ejemplo, v = sin (π y − c c − d ).
Dentro de un objeto a cocinar, denotado por B, la fuente de calor es proporcional av 2 . A
equilibrio, uno tiene

−∆θ = v 2 I B , θ Γ = 0

donde I B es 1 en el objeto y 0 en cualquier otro lugar.

https://translate.googleusercontent.com/translate_f 54/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 3.11: Un horno microondas: partes real (izquierda) e imaginaria (medio) de onda y temperatura.
perature (derecha).

Los resultados se muestran en la figura 3.11. √


En el programa siguiente, β = 1 / (1 - I / 2) en el aire y 2 / (1 - I / 2) en el objeto (i = −1):

Ejemplo 3.11 (muwave.edp) // archivo muwave.edp


real a = 20, b = 20, c = 15, d = 8, e = 2, l = 12, f = 2, g = 2;
borde a0 (t = 0,1) {x = a * t; y = 0; etiqueta = 1;}
borde a1 (t = 1,2) {x = a; y = b * (t-1); etiqueta = 1;}
borde a2 (t = 2,3) {x = a * (3-t); y = b; etiqueta = 1;}
borde a3 (t = 3,4) {x = 0; y = b- (bc) * (t-3); etiqueta = 1;}
borde a4 (t = 4,5) {x = 0; y = c- (cd) * (t-4); etiqueta = 2;}
borde a5 (t = 5,6) {x = 0; y = d * (6-t); etiqueta = 1;}

borde b0 (t = 0,1) {x = a-f + e * (t-1); y = g; etiqueta = 3;}


borde b1 (t = 1,4) {x = af; y = g + l * (t-1) / 3; etiqueta = 3;}
borde b2 (t = 4,5) {x = afe * (t-4); y = l + g; etiqueta = 3;}
borde b3 (t = 5,8) {x = aef; y = l + gl * (t-5) / 3; etiqueta = 3;}
int n = 2;
malla Th = buildmesh (a0 (10 * n) + a1 (10 * n) + a2 (10 * n) + a3 (10 * n)

Página 63
3.13. CONTROL ÓPTIMO 63

+ a4 (10 * n) + a5 (10 * n) + b0 (5 * n) + b1 (10 * n) + b2 (5 * n) + b3 (10 * n));


plot (Th, espera = 1);
fespace Vh (Th, P1);
carne real = Th (afe / 2, g + l / 2). región , aire = Th (0.01,0.01). región ;
Vh R = (región-aire) / (carne-aire);

Vh < complejo > v, w;


resolver muwave (v, w) = int2d (Th) (v * w * (1 + R)
- ( dx (v) * dx (w) + dy (v) * dy (w)) * (1-0,5i))
+ en (1, v = 0) + en (2, v = sin (pi * (yc) / (cd)));
Vh vr = real (v), vi = imag (v);
plot (vr, wait = 1, ps = "rmuonde.ps", fill = true);
plot (vi, espera = 1, ps = "imuonde.ps", relleno = verdadero);

fespace Uh (Th, P1); Uh u, uu, ff = 1e5 * (vrˆ2 + viˆ2) * R;

resolver temperatura (u, uu) = int2d (Th) ( dx (u) * dx (uu) + dy (u) * dy (uu))
- int2d (Th) (ff * uu) + en (1,2, u = 0);
plot (u, espera = 1, ps = "tempmuonde.ps", relleno = verdadero);

3.13 Control óptimo


Gracias a la función BFGS es posible resolver problemas complejos de optimización no lineal
dentro de FreeFem ++. Por ejemplo, considere el siguiente problema inverso


min J= (u - u d ) 2 : - ∇ (κ (b, c, re) · ∇u) = 0, u | Γ = u Γ
b, c, d∈R
mi

https://translate.googleusercontent.com/translate_f 55/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
donde el estado deseado u d , los datos de contorno u Γ y el conjunto de observación E ⊂ Ω son todos
dado. Además, supongamos que

κ (x) = 1 + bI B (x) + cI C (x) + dI D (x) ∀x ∈ Ω

donde B, C, D son subconjuntos separados de Ω.

Para resolver este problema por el método cuasi-Newton BFGS necesitamos las derivadas de J con
con respecto a b, c, d. Tenemos notaciones autoexplicativas, si δb, δc, δd son variaciones de b, c, d tenemos


δJ ≈ 2 (u - u d ) δu, - ∇ (κ · ∇δu) ≈ ∇ (δκ · ∇u) δu | Γ = 0
mi

Obviamente, J b es igual a δJ cuando δb = 1, δc = 0, δd = 0, y así sucesivamente para J c y J d .

Todo esto se implementa en el siguiente programa

// archivo optimcontrol.edp
borde aa (t = 0, 2 * pi) { x = 5 * cos (t); y = 5 * sin (t); };
borde bb (t = 0, 2 * pi) { x = cos (t); y = sin (t); };
frontera cc (t = 0, 2 * pi) { x = -3 + cos (t); y = sin (t); };
border dd (t = 0, 2 * pi) { x = cos (t); y = -3 + sen (t); };
malla th = buildmesh (aa (70) + bb (35) + cc (35) + dd (35));

Página 64
64 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

fespace Vh (th, P1);


Vh Ib = ((xˆ2 + yˆ2) <1.0001),
Ic = (((x + 3) ˆ2 + yˆ2) <1.0001),
Id = ((xˆ2 + (y + 3) ˆ2) <1.0001),
Es decir = (((x-1) ˆ2 + yˆ2) <= 4),
ud, u, uh, du;
real [int] z (3);
problema A (u, uh) = int2d (th) ((1 + z [0] * Ib + z [1] * Ic + z [2] * Id) * (dx (u) * dx (uh)
+ dy (u) * dy (uh))) + en (aa, u = xˆ3-yˆ3);
z [0] = 2; z [1] = 3; z [2] = 4;
A; ud = u;
ofstream f ("J.txt");
func real J (real [int] & Z)
{
para (int i = 0; i <zn; i ++) z [i] = Z [i];
A; real s = int2d (th) (es decir * (u-ud) ˆ2);
f << s << " "; return s;
}

real [int] dz (3), dJdz (3);

problema B (du, uh)


= int2d (th) ((1 + z [0] * Ib + z [1] * Ic + z [2] * Id) * (dx (du) * dx (uh) + dy (du) * dy (uh) )))
+ int2d (th) ((dz [0] * Ib + dz [1] * Ic + dz [2] * Id) * (dx (u) * dx (uh) + dy (u) * dy (uh)) )
+ en (aa, du = 0);

func real [int] DJ ( real [ int ] & Z)


{
para (int i = 0; i <zn; i ++)
{ para (int j = 0; j <dz.n; j ++) dz [j] = 0;
dz [i] = 1; B;
dJdz [i] = 2 * int2d (th) (es decir, * (u-ud) * du);
}
return dJdz;
}

real [ int ] Z (3);


para ( int j = 0; j <zn; j ++) Z [j] = 1;
BFGS (J, DJ, Z, eps = 1.e-6, nbiter = 15, nbiterline = 20);
cout << "BFGS: J (z) =" << J (Z) << endl;

https://translate.googleusercontent.com/translate_f 56/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
para (int j = 0; j <zn; j ++) cout << z [j] << endl;
plot (ud, valor = 1, ps = "u.eps");

En este ejemplo, los conjuntos B, C, D, E son círculos de límites bb, cc, dd, ee son el dominio Ω
es el círculo del límite aa. El estado deseado u d es la solución de la PDE para b = 2, c =
3, d = 4. Las incógnitas se empaquetan en la matriz z. Tenga en cuenta que es necesario volver a copiar
Z en z porque una es una variable local mientras que la otra es global. El programa encontró
b = 2,00125, c = 3,00109, d = 4,00551. La figura 3.12 muestra u en convergencia y la sucesiva
evaluaciones de funciones de J. Tenga en cuenta que podría haberse utilizado un estado adjunto. Defina p por

−∇ · (κ∇p) = 2I E (u - u d ), p | Γ = 0

como consecuencia


δJ = - (∇ · (κ∇p)) δu
Ω

Página 65
3.14. UN FLUJO CON CHOQUES sesenta y cinco

IsoValue
-118,75
-106,25
-93,75
-81,25
-68,75
-56,25
-43,75
-31,25
-18,75
-6,25
6.25
18,75
31.25
43,75
56.25
68,75
81.25
93,75 45
106.25 "J.txt"
118,75

40

35

30

25

20

15

10

0
0 5 10 15 20 25 30 35

Figura 3.12: A la izquierda, las líneas de nivel de u. A la derecha las sucesivas evaluaciones de J por
BFGS (se han eliminado 5 valores por encima de 500 para facilitar la lectura)

∫ ∫
= (κ∇p · ∇δu) = - (δκ∇p · ∇u) (3,9)
Ω Ω

Luego, las derivadas se encuentran estableciendo δb = 1, δc = δd = 0 y así sucesivamente:

∫ ∫ ∫
Jb=- ∇p · ∇u, J c = - ∇p · ∇u, J d = - ∇p · ∇u
B C D

Observación Como BFGS almacena una matriz M × M donde M es el número de incógnitas, es


peligrosamente caro utilizar este método cuando la x desconocida es una función de elemento finito.
Uno debe usar otro optimizador como el NonLinear Conjugate Gradient NLCG (también un
palabra clave de FreeFem ++). Vea el archivo algo.edp en la carpeta de ejemplos.

3.14 Un flujo con choques


Las ecuaciones de Euler comprimibles deben discretizarse con volúmenes finitos o FEM con flujo
esquema up-winding pero estos no están implementados en FreeFem ++. Sin embargo aceptable
Los resultados se pueden obtener con el método de características siempre que los valores medios
f¯= 1 2 (f + + f - ) se utilizan en los choques en el esquema y, finalmente, en la adaptación de la malla.

∂ t ρ + ¯u∇ρ + ¯ρ∇ · u = 0
ρu
¯ρ (∂ t u + ∇u + ∇p = 0
¯ρ
∂ t p + ¯u∇p + (γ - 1) ¯p∇ · u = 0 (3,10)

https://translate.googleusercontent.com/translate_f 57/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Una posibilidad es acoplar u, p y luego actualizar ρ, es decir
1
(p m + 1 - p m ◦ X m ) + ∇ · u m + 1 = 0
(γ - 1) δt¯p m
¯ρ m
(u m + 1 - u m ◦ ˜X m ) + ∇p m + 1 = 0
δt
¯ρ m
ρ m+1 = ρ m ◦ X m + (p m + 1 - p m ◦ X m ) (3,11)
(γ - 1) ¯p m

Página 66
66 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

IsoValue
0.0714186
0.212634
0.35385
0.495066
0,636282
0,777498
0,918714
1.05993
1.20115
1.34236
1,48358
1.62479
1.76601
1.90722
2.04844
2.18966
2.33087
2.47209
2.6133
2.75452

Figura 3.13: Presión para un flujo de Euler alrededor de un disco a Mach 2 calculada por ( 3.11 )

Se da un resultado numérico en la Figura 3. 13 y el script FreeFem ++ es

verbosidad = 1;
int de nuevo = 1;
real x0 = 0.5, y0 = 0, rr = 0.2;
borde ccc (t = 0,2) {x = 2-t; y = 1;};
borde ddd (t = 0,1) {x = 0; y = 1-t;};
borde aaa1 (t = 0, x0-rr) {x = t; y = 0;};
círculo de borde (t = pi, 0) {x = x0 + rr * cos (t); y = y0 + rr * sin (t);}
borde aaa2 (t = x0 + rr, 2) {x = t; y = 0;};
borde bbb (t = 0,1) {x = 2; y = t;};

int m = 5; malla Th;


si (de nuevo) Th = buildmesh (ccc (5 * m) + ddd (3 * m) + aaa1 (2 * m) + círculo (5 * m)
+ aaa2 (5 * m) + bbb (2 * m));
más Th = readmesh ("Th_circle.mesh"); plot (Th, espera = 0);

dt real = 0.01, u0 = 2, err0 = 0.00625, pena = 2;


espacio libre Wh (Th, P1);
fespace Vh (Th, P1);
Wh u, v, u1, v1, uh, vh;
Vh r, rh, r1;
macro dn (u) (Nx * dx (u) + Ny * dy (u)) // def la derivada normal

si (de nuevo) {u1 = u0; v1 = 0; r1 = 1;}


else {
ifstream g ("u.txt"); g >> u1 [];
ifstream gg ("v.txt"); gg >> v1 [];

https://translate.googleusercontent.com/translate_f 58/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 67
3.15. CLASIFICACIÓN DE LAS ECUACIONES 67

ifstream ggg ("r.txt"); ggg >> r1 [];


plot (u1, ps = "eta.eps", valor = 1, espera = 1);
err0 = err0 / 10; dt = dt / 10;
}

problema eul (u, v, r, uh, vh, rh)


= int2d (Th) ((u * uh + v * vh + r * rh) / dt
+ ((dx (r) * uh + dy (r) * vh) - (dx (dcha.) * u + dy (dcha.) * v))
)
+ int2d (Th) (- (rh * convect ([u1, v1], - dt, r1) + uh * convect ([u1, v1], - dt, u1)
+ vh * convección ([u1, v1], - dt, v1)) / dt)
+ int1d (Jue, 6) (dcha. * u) // + int1d (Th, 1) (dcha. * v)
+ en (2, r = 0) + en (2, u = u0) + en (2, v = 0);

int j = 80;
para (int k = 0; k <3; k ++)
{
si (k == 20) {err0 = err0 / 10; dt = dt / 10; j = 5;}
para ( int i = 0; i <j; i ++) {
eul; u1 = u; v1 = v; r1 = abs (r);
cout << "k =" << k << "E =" << int2d (Th) (uˆ2 + vˆ2 + r) << endl;
plot (r, espera = 0, valor = 1);
}
Th = adaptmesh (Th, r, nbvx = 40000, err = err0,
abserror = 1, nbjacoby = 2, omega = 1.8, relación = 1.8, nbsmooth = 3,
splitpbedge = 1, maxsubdiv = 5, reescalado = 1);
plot (Th, espera = 0);
u = u; v = v; r = r;

savemesh (Th, "Th_circle.mesh");


ofstream f ("u.txt"); f << u [];
ofstream ff ("v.txt"); ff << v [];
ofstream fff ("r.txt"); fff << r [];
r1 = raíz cuadrada (u * u + v * v);
plot (r1, ps = "mach.eps", valor = 1);
r1 = r;
}

3.15 Clasificación de las ecuaciones


Resumen Por lo general, no es fácil determinar el tipo de sistema. Sin embargo, las aproximaciones
y los algoritmos adecuados al problema dependen de su tipo:

• Compatible con elementos finitos (condiciones LBB) para sistemas elípticos

• Diferencia finita en la variable parabólica y un ciclo de tiempo en cada subsistema elíptico


de sistemas parabólicos; mejores diagramas de estabilidad cuando los esquemas están implícitos en el tiempo.

• Upwinding, Petrov-Galerkin, Characteristics-Galerkin, Discontinuous-Galerkin, Finite


Volúmenes para sistemas hiperbólicos más, posiblemente, un ciclo de tiempo.

Cuando el sistema cambia de tipo, ¡espere dificultades (como discontinuidades de choque)!

https://translate.googleusercontent.com/translate_f 59/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 68
68 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

Ecuaciones elípticas, parabólicas e hiperbólicas Una ecuación diferencial parcial (PDE) es una
relación entre una función de varias variables y sus derivadas.
∂ϕ ∂ϕ ∂2ϕ ∂mϕ
F (ϕ (x), (X),··· , (X), (X),··· , (x)) = 0 ∀x ∈ Ω ⊂ R d .
∂x 1 ∂x d ∂x 21 ∂x mD

El rango de x sobre el que se toma la ecuación, aquí Ω, se denomina dominio de la PDE.


El índice de derivación más alto, aquí m, se llama orden. Si F y ϕ son valores vectoriales
funciones, entonces el PDE es en realidad un sistema de PDE.
A menos que se indique lo contrario, aquí por convención un PDE corresponde a un escalar valorado
F y ϕ. Si F es lineal con respecto a sus argumentos, entonces se dice que la PDE es lineal.
D
La forma general de una PDE escalar lineal de segundo orden es ∂ ϕ ∂x ∂x y A: B significa ∑
2
i j yo, j = 1
a ij b ij .

αϕ + a · ∇ϕ + B: ∇ (∇ϕ) = f en Ω⊂Rd,

donde f (x), α (x) ∈ R, a (x) ∈ R d , B (x) ∈ R d × d son los coeficientes PDE. Si los coeficientes
son independientes de x, se dice que la PDE tiene coeficientes constantes.
A un PDE asociamos una forma cuadrática, reemplazando ϕ por 1, ∂ϕ / ∂x i por z i y ∂ 2 ϕ / ∂x i ∂x j
por z i z j , donde z es un vector en R d :

α + a · z + z T Bz = f.

Si es la ecuación de una elipse (elipsoide si d ≥ 2), se dice que la PDE es elíptica; si esto es
la ecuación de una parábola o hipérbola, se dice que la PDE es parabólica o hiperbólica. Si
A ≡ 0, el grado ya no es 2 sino 1, y por razones que se verán más claramente más adelante,
todavía se dice que la PDE es hiperbólica.

Estos conceptos se pueden generalizar a sistemas, estudiando si el polinomio


El sistema P (z) asociado con el sistema PDE tiene ramas en el infinito (los elipsoides no tienen
ramas en el infinito, los paraboloides tienen uno y los hiperboloides tienen varios).
Si la PDE no es lineal, se dice que no es lineal. Se dice que son localmente elípticas,
parabólico o hiperbólico según el tipo de ecuación linealizada.
Por ejemplo, para la ecuación no lineal

∂2ϕ ∂ϕ ∂ 2 ϕ
- = 1,
∂t 2 ∂x ∂x 2
tenemos d = 2, x 1 = t, x 2 = x y su forma linealizada es:

∂2u ∂u ∂ 2 ϕ ∂ϕ ∂ 2 u
- - = 0,
∂t 2 ∂x ∂x 2 ∂x ∂x 2

que para la u desconocida es localmente elíptica si ∂ϕ ∂x


<0 y localmente hiperbólico si ∂ϕ ∂x
> 0.

Ejemplos La ecuación de Laplace es elíptica:

∂2ϕ ∂2ϕ ∂2ϕ


∆ϕ ≡ + + ··· + = f, ∀x ∈ Ω ⊂ R d .
∂x 21 ∂x 22 ∂x 2D

La ecuación de calor es parabólica en Q = Ω ×] 0, T [⊂ R d + 1 :

∂ϕ
- µ∆ϕ = f ∀x ∈ Ω ⊂ R d , ∀t ∈] 0, T [.
∂t

Página 69
3.15. CLASIFICACIÓN DE LAS ECUACIONES 69

Si µ> 0, la ecuación de onda es hiperbólica:

∂2ϕ
- µ∆ϕ = f en Q.

https://translate.googleusercontent.com/translate_f 60/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
∂t 2
La ecuación de difusión por convección es parabólica si µ = 0 e hiperbólica en caso contrario:

∂ϕ
+ a∇ϕ - µ∆ϕ = f.
∂t

La ecuación biarmónica es elíptica:

∆ (∆ϕ) = f en Ω.

Condiciones de frontera Una relación entre una función y sus derivadas no es suficiente para
definir la función. Información adicional sobre el límite Γ = ∂Ω de Ω, o en parte de Γ
es necesario.
Esta información se denomina condición de frontera. Por ejemplo,

ϕ (x) dado, ∀x ∈ Γ,

se denomina condición de frontera de Dirichlet. La condición de Neumann es

∂ϕ
(x) dado en Γ (on · B∇ϕ, dado en Γ para una PDE general de segundo orden)
En

donde n es la normal en x ∈ Γ dirigida hacia el exterior de Ω (por definición ∂ϕ En


= ∇ϕ · n).
Otra condición clásica, llamada condición de Robin (o Fourier) se escribe como:

∂ϕ
ϕ (x) + β (x) (x) dado el Γ.
En

Encontrar un conjunto de condiciones de contorno que defina un ϕ único es un arte difícil.


En general, una ecuación elíptica está bien planteada (es decir, ϕ es única) con un Dirichlet, Neumann
o condiciones de Robin en todo el límite.
Por tanto, las ecuaciones de Laplace están bien planteadas con una condición de Dirichlet o Neumann pero también con

∂ϕ
ϕ dado el Γ 1 , dado en Γ 2 , Γ 1 ∪ Γ 2 = Γ, ˙Γ 1 ∩ ˙Γ 2 = ∅.
En

Las ecuaciones parabólicas e hiperbólicas rara vez requieren condiciones de contorno en todo Γ ×] 0, T [.
Por ejemplo, la ecuación del calor está bien planteada con

ϕ dado en t = 0 y Dirichlet o Neumann o condiciones mixtas en ∂Ω.

Aquí es el momento, por lo que la primera condición se llama condición inicial. Todo el conjunto de condiciones
también se denominan afecciones de Cauchy.
La ecuación de onda está bien planteada con

∂ϕ
ϕy dado en t = 0 y Dirichlet o Neumann o condiciones mixtas en ∂Ω.
∂t

Página 70
70 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

3.16 Optimización del esquema dependiente del tiempo para la ecuación de calor
Primero, es posible definir formas variacionales y usar estas formas para construir matrices y vectores.
para hacer un script muy rápido (4 veces más rápido aquí) (vea el ejemplo Heat.edp en el capítulo 3
directorio).
Por ejemplo, resuelva el problema de conducción térmica de la sección 3.4 Debemos resolver la tem-
ecuación de peratura en Ω en un intervalo de tiempo (0, T).

∂ t u −∇ · (κ∇u) = 0inΩ × (0, T),


u (x, y, 0) = u 0 + xu 1
∂u

https://translate.googleusercontent.com/translate_f 61/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
u = 30 en Γ 24 × (0, T), κ En + α (u - u e ) = 0onΓ × (0, T). (3,12)

La formulación variacional está en L 2 (0, T; H 1 (Ω)); buscaremos u n satisfaciendo

∫ u n - u n−1 ∫
∀w ∈ V 0 ; w + κ∇u n ∇w) + α (u n - u ue ) w = 0
Ω δt Γ

donde V 0 = {w ∈ H 1 (Ω) / w | Γ = 0}. 24

Entonces, para codificar el método con las matrices A = (A ij ), M = (M ij ) y los vectores


u n , b n , b, b ”, b cl (notación si w es un vector, entonces w i es un componente del vector).

1 {b " i si yo ∈ Γ 24
u n = A −1 b n , b = b 0 + Mu n − 1 , b ”= b cl , b n
ε yo = b yo demás

Donde con 1 ε
= tgv = 10 30 :

1
ε
si i ∈ Γ 24 , y j = i
A ij = ∫ ∫
w j w i / dt + k (∇w j .∇w i ) + αw j w i demás
Ω Γ 13
1
ε
si i ∈ Γ 24 , y j = i
M ij = ∫
norte w j w i / dt más
Ω


b 0, yo = n αu ue w i
Γ 13

b cl =u0 los datos iniciales

El script de la versión rápida:

...
Vh u0 = fu0, u = u0;

Cree tres formulaciones variacionales y construya las matrices A, M.

varf vtérmico (u, v) = int2d (Th) (u * v / dt


+ k * (dx (u) * dx (v) + dy (u) * dy (v)))
+ int1d (Th, 1,3) (alpha * u * v) + on (2,4, u = 1);
varf vthermic0 (u, v) = int1d (Th, 1,3) (alfa * ue * v);
varf vMass (u, v) = int2d (Th) (u * v / dt) + en (2,4, u = 1);

Página 71
3.17. TUTORIAL PARA ESCRIBIR UN SOLVER DE STOKES TRANSITORIOS EN FORMA MATRIZ71

tgv real = 1e30;


matriz A = vtérmica (Vh, Vh, tgv = tgv, solucionador = CG);
matriz M = vMass (Vh, Vh);

Ahora, para construir el tamaño de la mano derecha, necesitamos 4 vectores.

real [int] b0 = vthermic0 (0, Vh); // parte constante de RHS


real [int] bcn = vtérmico (0, Vh); // tgv en la parte de Dirichlet
// tenemos para el nodo i: i ∈ Γ 24 ⇔ bcn [i] = 0
real [int] bcl = tgv * u0 []; // la parte de Dirichlet BC

// El bucle rápido ...


para ( t real = 0; t <T; t + = dt) {
real [ int ] b = b0; // para el RHS
b + = M * u []; // agregue la parte dependiente del tiempo
b = bcn? bcl: b; // hacer ∀i: b [i] = bcn [i]? bcl [i]: b [i];
u [] = Aˆ-1 * b; // Resolver problema lineal
trama (u);
}

https://translate.googleusercontent.com/translate_f 62/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

3.17 Tutorial para escribir un solucionador de Stokes transitorio en forma matricial


Considere el siguiente script para resolver un problema de Stokes dependiente del tiempo en una cavidad

malla Th = cuadrado (10,10);


espacio libre Vh (Th, P2), Qh (Th, P1);
Vh u, v, uu, vv, uold = 0, vold = 0;
Qh p, pp;
nu real = 0,1, T = 1., dt = 0,1;
int m, M = T / dt;
problema stokes (u, v, p, uu, vv, pp) =
int2d (Th) ((u * uu + v * vv) / dt + nu * (dx (u) * dx (uu) + dy (u) * dy (uu)
+ dx (v) * dx (vv) + dy (v) * dy (vv))
- p * pp * 1.e-6 - p * (dx (uu) + dy (vv)) - pp * (dx (u) + dy (v))
) - int2d (Th) ((uold * uu + vold * vv) / dt)
+ en (1,2,4, u = 0, v = 0) + en (3, u = 1, v = 0);

para (m = 0; m <M; m ++) {


stokes; uold = u; vold = v;
}
plot (p, [u, v], valor = verdadero, espera = verdadero, cmm = "t =" + m * dt);

Cada iteración es de hecho de la forma A [u, v, p] = B [uold, vold, pold] + b donde A, B son
matrices y b es un vector que contiene las condiciones de contorno. Los A, B, b están construidos
por

espacio libre Xh (Th, [P2, P2, P1]);


varf aa ([u, v, p], [uu, vv, pp])
= int2d (Th) ((u * uu + v * vv) / dt + nu * (dx (u) * dx (uu) + dy (u) * dy (uu)
+ dx (v) * dx (vv) + dy (v) * dy (vv))
- p * pp * 1.e-6 - p * (dx (uu) + dy (vv)) - pp * (dx (u) + dy (v))
) + en (1,2,4, u = 0, v = 0) + en (3, u = 1, v = 0);

varf bb ([uold, vold, pold], [uu, vv, pp])

Página 72
72 CAPÍTULO 3. APRENDIZAJE POR EJEMPLOS

= int2d (Th) ((uold * uu + vold * vv) / dt)


; // + en (1,2,4, uold = 0, vold = 0) + en (3, uold = 0, vold = 0);

varf bcl ([uold, vold, pold], [uu, vv, pp]) = on (1,2,4, uold = 0, vold = 0) + on (3, uold = 1, vold = 0);

matriz A = aa (Xh, Xh, solucionador = UMFPACK);


matriz B = bb (Xh, Xh);
real [int] b = bcl (0, Xh);

Tenga en cuenta que las condiciones de contorno no se especifican en bb. Eliminando el comentario "//"
haría que el compilador multiplicara los términos diagonales correspondientes a un grado de Dirichlet
de la libertad por un término muy amplio (tgv); si es así b no sería necesario, con la condición de que
uold = 1 en el límite 3 inicialmente. Tenga en cuenta también que b tiene un tgv en los nodos de Dirichlet, por
construcción, y también A.
El bucle serán

real [int] sol (Xh.ndof), aux (Xh.ndof);


para (m = 0; m <M; m ++) {
aux = B * sol; aux + = b;
sol = Aˆ-1 * aux;
}

Todavía existe una dificultad con la inicialización de sol y con la solución de sol. Para
esto necesitamos un vector temporal en X h y aquí hay una solución

Xh [w1, w2, wp] = [uold, vold, pp];


sol = w1 []; // causa también la copia de w2 y wp
para (m = 0; m <M; m ++) {

https://translate.googleusercontent.com/translate_f 63/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
aux = B * sol; aux + = b;
sol = Aˆ-1 * aux;
}
w1 [] = sol; u = w1; v = w2; p = wp;
plot (p, [u, v], valor = verdadero, espera = verdadero, cmm = "t =" + m * dt);

El equipo de freefem está de acuerdo en que la línea sol = w1 []; es misterioso ya que también copia w2 y
wp en sol. Los datos estructurados como los vectores de X h aquí no se pueden escribir componente por
componente. Por tanto, w1 = u no está permitido.

Página 73

Capítulo 4

Sintaxis

4.1 Tipos de datos


En esencia, FreeFem ++ es un compilador: su lenguaje es tipado, polimórfico, con excepciones
ción y reentrada. Cada variable debe ser declarada de un cierto tipo, en un declarativo
declaración; cada declaración está separada de la siguiente por un punto y coma ";". El idioma
permite la manipulación de tipos básicos enteros (int), reales (real), strings (string), ar-
rayos (ejemplo: real [int]), mallas de elementos finitos bidimensionales (2D) (malla), finitos 2D
espacios de elementos (fespace), funciones analíticas (func), matrices de funciones de elementos finitos
(func [tipo básico]), operadores lineales y bilineales, matrices dispersas, vectores, etc. Por ejemplo

int i, n = 20; // i, n son números enteros.


real [ int ] xx (n), yy (n); // dos matrices de tamaño n
para (i = 0; i <= 20; i ++) // que se puede utilizar en declaraciones como
{xx [i] = cos (i * pi / 10); yy [i] = sin (i * pi / 10); }

La vida de una variable es el bloque actual {...}, excepto la variable fespace, y el


las variables locales de un bloque se destruyen al final del bloque de la siguiente manera.

Ejemplo 4.1

https://translate.googleusercontent.com/translate_f 64/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

r real = 0,01;
malla Th = cuadrado (10,10); // unidad de malla cuadrada
fespace Vh (Th, P1 ); // P1 espacio de elementos finitos de lagrange
Vh u = x + exp (y);
func f = z * x + r * log (y);
plot (u, espera = verdadero);
{ // nuevo bloque
real r = 2; // no es lo mismo r
fespace Vh (Th, P1 ); // error porque Vh es un nombre global
} // fin de bloque
// aquí r de nuevo a 0.01

Las declaraciones de tipo son obligatorias en FreeFem ++; al final, esta característica es una ventaja
porque es fácil crear errores en un lenguaje con muchos tipos implícitos. El nombre de la variable
es solo una cadena alfanumérica, el carácter de subrayado "" no está permitido, porque
ser utilizado como operador en el futuro.

73

Página 74
74 CAPÍTULO 4. SINTAXIS

4.2 Lista de tipos principales


bool se utiliza para expresión lógica y control de flujo. El resultado de una comparación es un booleano
escriba como en

tonto tonto = (1 <2);

que hace que el tonto sea verdad. Se pueden construir ejemplos similares con ==, <=,> =, <,> ,! =.

int declara un entero (es decir, largo en C ++).

string declara la variable para almacenar un texto entre comillas dobles, como:

"Esta es una cadena entre comillas dobles".

real declara la variable para almacenar un número como "12.345". (es decir, doble en C ++).

complejos Números complejos, como 1 + 2i, FreeFem ++ entienden que i = −1 (es decir
complejo <doble> en C ++).

complejo a = 1 i , b = 2 + 3 i ;
cout << "a + b =" << a + b << endl ;
cout << "a - b =" << a + b << endl ;
cout << "a * b =" << a * b << endl ;
cout << "a / b =" << a / b << endl ;

Aquí está la salida;

a + b = (2,4)
a - b = (-2, -2)
a * b = (-3,2)
a / b = (0.230769,0.153846)

ofstream para declarar un archivo de salida.

ifstream para declarar un archivo de entrada.

real [int] declara una variable que almacena múltiples números reales con un índice entero.

real [ int ] a (5);


a [0] = 1; a [1] = 2; a [2] = 3,3333333; a [3] = 4; a [4] = 5;
cout << "a =" << a << endl ;

https://translate.googleusercontent.com/translate_f 65/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Esto produce la salida;

a=5 :
1 2 3.33333 4 5

real [cadena] declara una variable que almacena múltiples números reales con un índice de cadena.

string [string] declara una variable que almacena múltiples cadenas con un índice de cadena.

Página 75
4.3. VARIABLES GLOBALES 75

func define una función sin argumento, si las variables independientes son x, y. Por ejemplo

func f = cos (x) + sen (y);

Observe que el tipo de la función viene dado por el tipo de la expresión. Funciones de elevación
a una potencia numérica se hace, por ejemplo, por xˆ1, yˆ0.23.

mesh crea la triangulación, consulte la Sección 5.

fespace define un nuevo tipo de espacio de elementos finitos, consulte la Sección 6.

problema declara la forma débil de un problema diferencial parcial sin resolverlo.

solve declara un problema y lo resuelve.

varf define una forma variacional completa.

matrix define una matriz dispersa.

4.3 Variables globales


Los nombres x, y, z, label, region, P, N, nu_triangle ... son palabras reservadas que se utilizan para
vincular el lenguaje a las herramientas de elementos finitos:

x es la coordenada x del punto actual (valor real)

y es la coordenada y del punto actual (valor real)

z es la coordenada z del punto actual (valor real)

etiqueta contiene el número de etiqueta de un límite si el punto actual está en un límite, 0


de lo contrario (valor int).

región devuelve el número de región del punto actual (x, y) (valor int) y si el punto es
fuera de entonces región == notaregion donde notaregion es un entero freefem ++
constante.

P da el punto actual ( valor R 2 ). Por Px, Py, podemos obtener las componentes x, y de P
. También Pz está reservado y se puede utilizar en 3D.

N da el vector normal unitario exterior en el punto actual si está en una curva definida por
borde ( valor R 3 ). Nx y Ny son componentes xey del vector normal. Nueva Zelanda
Está reservado. .

lenEdge = | q i - q j | da la longitud del borde actual si el borde actual es [q i , q j ]

edgeOrientation = ± 1: signe de (i - j) si el borde actual es [q i , q j ]

https://translate.googleusercontent.com/translate_f 66/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

BoundaryEdge = 1 si el borde actual es el borde actual en el límite verdadero o 0 en caso contrario

Página 76
76 CAPÍTULO 4. SINTAXIS

InternalEdge = 0 si el borde actual es el borde actual en el límite verdadero o 1 en caso contrario

hTriangle da el tamaño del triángulo actual

nuTriangle da el índice del triángulo actual (valor int).

nuEdge da el índice del borde actual en el triángulo (valor int).

nTonEdge da el número de triángulos adyacentes del borde actual (entero).

área da el área del triángulo actual (valor real).

volumen dan el volumen del tetraedro actual (valor real).

cout es el dispositivo de salida estándar (el predeterminado es la consola). En MS-Windows, el estándar


La salida es solo la consola, en este momento. ostream

cin es el dispositivo de entrada estándar (el predeterminado es el teclado). (istreamvalue).

endl agrega un "final de línea" al flujo de entrada / salida.

verdadero significa "verdadero" en valor bool.

falso significa "falso" en valor bool.

pi es el valor de aproximación del valor real de π.

4.4 Comandos del sistema


Aquí se muestra cómo mostrar todos los tipos y todos los operadores y funciones de un FreeFem ++
programa:

dumptable ( cout );

Para ejecutar un comando del sistema en la cadena (no implementado en Carbon MacOS), que
devuelve el valor de la llamada al sistema.

sistema ("comando de shell"); // después de la versión 3.12-1


exec ("comando de shell");

Esto es útil para iniciar otro ejecutable desde FreeFem ++. En MS-Windows, el
ruta completa del ejecutable. Por ejemplo, si existe el comando "ls.exe" en el subdirectorio
"C: \ cygwin \ bin \", entonces debemos escribir

exec ("c: \\ cygwin \\ bin \\ ls.exe");

Otro comando útil del sistema es assert () para asegurarse de que algo sea cierto.

afirmar (versión> = 1.40);

https://translate.googleusercontent.com/translate_f 67/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 77
4.5. ARITMÉTICA 77

4.5 Aritmética
En enteros, +, -, ∗ son la suma aritmética habitual (más), resta (menos)
y multiplicación (veces), respectivamente, Los operadores / y% producen el cociente y el
resto de la división de la primera expresión por la segunda. Si el segundo número de
/ o% es cero, el comportamiento no está definido. El máximo o mínimo de dos números enteros a, b
se obtienen por max (a, b) o min (a, b). La potencia a b de dos enteros a, b se calcula mediante
escribiendo aˆb. La expresión "aritmética if" clásica de C ++ a ? b: c es igual a
el valor de la expresión b si el valor de la expresión a es verdadero en caso contrario es igual al valor de
expresión c.

Ejemplo 4.2 Cálculos con números enteros

int a = 12, b = 5;
cout << "más, menos de" << a << "y" << b << "son" << a + b << "," << ab << endl ;
cout << "multiplicación, el cociente de ellos es" << a * b << "," << a / b << endl ;
cout << "resto de la división de" << a << "por" << b << "es" << a% b << endl ;
cout << "el menos de" << a << "es" << -a << endl ;
cout << a << "más -" << b << "necesita corchete:" << a << "+ (-" << b << ") =" << a + (- b) << endl ;
cout << "max y min de" << a << "y" << b << "es" << max (a, b) << "," << min (a, b) << endl ;
cout << b << "la potencia de" << a << "es" << aˆb << endl ;
cout << "min == (a <b? a: b) es" << (a <b? a: b) << endl ;

b = 0;
cout << a << "/ 0" << "es" << a / b << endl ;
cout << a << "% 0" << "es" << a% b << endl ;

producir el siguiente resultado:

más, menos de 12 y 5 son 17, 7


multiplicación, el cociente de ellos es 60, 2
el resto de la división de 12 entre 5 es 2
el menos de 12 es -12
12 más -5 necesitan soporte: 12 + (- 5) = 7
max y min de 12 y 5 es 12,5
La quinta potencia de 12 es 248832
min == (a <b? a: b) es 5
12/0: largo largo largo
Error fatal: ExecError Div por 0 en la línea ejecutiva 9
Error de ejecución: salir

Por la relación entero ⊂ real, los operadores “+, -, ∗, /,%” y “ max , min , ˆ” son
extendido a números reales o variables. Sin embargo,% calcula el resto del entero
partes de dos números reales.
Los siguientes son ejemplos similares al ejemplo 4.2.

real a = raíz cuadrada (2.), b = pi;


cout << "más, menos de" << a << "y" << pi << "son" << a + b << "," << ab << endl ;
cout << "multiplicación, el cociente de ellos es" << a * b << "," << a / b << endl ;
cout << "resto de la división de" << a << "por" << b << "es" << a% b << endl ;
cout << "el menos de" << a << "es" << -a << endl ;
cout << a << "más -" << b << "necesita corchete:" << a << "+ (-" << b << ") =" << a + (-b) << endl ;

Página 78
78 CAPÍTULO 4. SINTAXIS

Da la siguiente salida:

https://translate.googleusercontent.com/translate_f 68/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
más, menos de 1.41421 y 3.14159 son 4.55581, -1.72738
multiplicación, el cociente de ellos es 4.44288, 0.450158
el resto de la división de 1.41421 por 3.14159 es 1
el menos de 1.41421 es -1.41421
1.41421 más -3.14159 necesita soporte: 1.41421 + (- 3.14159) = - 1.72738

Por la relación
bool ⊂ int ⊂ real ⊂ complex,

los operadores "+, -, ∗, /" y "ˆ" también son aplicables en variables de tipo complejo,
√ pero "%,
max, min ”no se puede utilizar. Números complejos como 5 + 9i, i = −1, son expresiones
√ válidas.
Con variables reales a = 2.45, b = 5.33, números complejos como a + ib y a + i 2.0 debe ser
declarado por

complejo z1 = a + b * 1i, z2 = a + sqrt (2.0) * 1i;

Las partes imaginaria y real de un número complejo z se pueden obtener con imag y real .
El conjugado de a + bi (a, b son reales) está definido por a - bi, que también se puede calcular
con el operador "conj", por conj (a + b * 1i) en FreeFem ++.
Internamente, el número complejo z = a + ib se considera como el par (a, b) de números reales a, b.
Podemos adjuntarle el punto (a, b) en el plano cartesiano donde el eje x es para el real
parte y el eje y para la parte imaginaria. El mismo punto (a, b) tiene una representación
√ con
coordenada polar (r, φ), Entonces z his también z = r (cosφ + isinφ), r = a 2 + b 2 y φ = tan −1 (b / a);
r se llama módulo y φ argumento de z. En el siguiente ejemplo, mostraremos
utilizando la programación FreeFem ++ y la fórmula de De Moivre z n = r n (cosnφ + isinnφ).

Ejemplo 4.3

real a = 2,45, b = 5,33;


complejo z1 = a + b * 1i, z2 = a + sqrt (2.) * 1i;
func string pc ( complejo z) // impresión compleja a (real) + i (imaginario)
{
cadena r = "(" + real (z);
si ( imag (z)> = 0) r = r + "+";
return r + imag (z) + "i)";
}
// impresión compleja a | z | * (cos (arg (z)) + i * sin (arg (z)))
func cadena toPolar ( complejo z)
{
return abs (z) + "* (cos (" + arg (z) + ") + i * sin (" + arg (z) + "))";
}
cout << "Salida estándar del complejo" << pc (z1) << "es el par"
<< z1 << endl;
cout << "Más, menos de" << pc (z1) << "y" << pc (z2) << "son" << pc (z1 + z2)
<< "," << pc (z1-z2) << endl;
cout << "Multiplicación, el cociente de ellos es" << pc (z1 * z2) << ","
<< pc (z1 / z2) << endl;
cout << "Parte real / imaginaria de" << pc (z1) << "es" << real (z1) << ","
<< imag (z1) << endl;
cout << "Absoluto de" << pc (z1) << "es" << abs (z1) << endl;
cout << pc (z2) << "=" << toPolar (z2) << endl;
cout << "y polar (" << abs (z2) << "," << arg (z2) << ") ="

Página 79
4.5. ARITMÉTICA 79

<< pc ( polar (abs (z2), arg (z2))) << endl;


cout << "Fórmula de Moivre:" << pc (z2) << "ˆ3 =" << toPolar (z2ˆ3) << endl;
cout << "conjugado de" << pc (z2) << "es" << pc ( conj (z2)) << endl;
cout << pc (z1) << "ˆ" << pc (z2) << "es" << pc (z1ˆz2) << endl;

Aquí está el resultado del ejemplo 4.3

La salida estándar del complejo (2.45 + 5.33i) es el par (2.45,5.33)


Además, menos de (2.45 + 5.33i) y (2.45 + 1.41421i) son (4.9 + 6.74421i), (0 + 3.91579i)
Multiplicación, el cociente de ellos es (-1.53526 + 16.5233i), (1.692 + 1.19883i)

https://translate.googleusercontent.com/translate_f 69/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
La parte real / imaginaria de (2.45 + 5.33i) es 2.45, 5.33
El absoluto de (2,45 + 5,33i) es 5,86612
(2,45 + 1,41421i) = 2,82887 * (cos (0,523509) + i * sin (0,523509))
y polar (2.82887,0.523509) = (2.45 + 1.41421i)
Fórmula de de Moivre: (2.45 + 1.41421i) ˆ3
= 22,638 * (cos (1,57053) + i * sin (1,57053))
conjugado de (2.45 + 1.41421i) es (2.45-1.41421i)
(2,45 + 5,33i) ˆ (2,45 + 1,41421i) es (8,37072-12,7078i)

También existen algunas funciones útiles (versión 3.58):

• proyección (a, b, x) = min (max (a, x), b) si a <b, min (max (b, x), a) else.

• dist (a, b) = a2+b2

• dist (a, b, c) = a2+b2+c2

• min (a, b, c)

• max (a, b, c)

• diffpos (a, b) = max (b - a, 0)

• invdiffpos (a, b) = a <b? 1 ./ (b - a): 0

• diffnp (a, b) = (a <0) & (0 <b)? (B - a): 0

• invdiffnp (a, b) = (a <0) & (0 <b)? 1 / (b - a): 0

• invdiffnp (a, b) = (a <0) & (0 <b)? 1 / (b - a): 0

• invdiff (a, b) = (- | a - b |> 10 - 30)? 1 / (b - a): 0

• invdiff (a, b, e) = (- | a - b |> e)? 1 / (b - a): 0

• intercambiar (a, b) intercambiar el valor ayb por valores numéricos.

• signo (a) = (x> 0.) - (x <0.) para d-real e int.

• signbit (a) la función matemática bitign de real e int.

• copysign (a, b) la función matemática copysign de real a.

• isNaN (a) la función matemática isNaN de real.

Página 80
80 CAPÍTULO 4. SINTAXIS

• isInf (a) la función matemática isInf de real.

• NaN () la función math nan ("") para construir un número NaN

• NaN (cadena) la función matemática nan (cadena) para construir un número NaN.

• signbit (a) la función matemática bitign de real e int.

• La función atoi (cadena) convierte la parte inicial de la cadena en una representación int.

• La función atof (cadena) convierte la parte inicial de la cadena en una representación real.
ción.

4.6 expresión de cadena


En el siguiente ejemplo, puede ver una expresión de ejemplo de cadena:
https://translate.googleusercontent.com/translate_f 70/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

cadena tt = "toto1" +1+ "- 77"; // concatenación de cadenas


cadena t1 = "0123456789";
cadena t2;
// nuevo operador
t2 = "12340005678";
t2 (4: 3) = "abcdefghijk-";
cadena t55 = t2 (4: 3);
// t2 = "12340abcdefghijk-005678";
cout << t2 << endl;
cout << "buscar abc" << t2.find ("abc") << endl;
cout << "r buscar abc" << t2.rfind ("abc") << endl;
cout << "buscar abc desde 10" << t2.find ("abc", 10) << endl;
cout << "buscar abc desde 10" << t2.rfind ("abc", 10) << endl;
cout << " "<< cadena (" abcc "). longitud << endl;
cout << "t55" << t55 << endl;
{ // agregar getline versión 3.0-6 de enero de 2009 FH
string s;
ifstream toto ("xyf");
para ( int i = 0; i <10; ++ i)
{
getline (toto, s);
cout << i << ":" << s << endl;
}
}

4.7 Funciones de una variable


Las funciones fundamentales están integradas en FreeFem ++, así como la función de potencia xˆ y
= pow (x, y) = x y ;, la función exponente exp (x) (= e x ), la función logarítmica
ción log (x) (= lnx) o log10 (x) (= log 10 x); las funciones trigonométricas sin (x),
cos (x), tan (x)
suponga ángulos medidos en radianes; la inversa de sinx, cosx, tanx
(llamada función circular o función trigonométrica inversa) como en (x) (= arcsinx),
acos (x) (= arccosx), atan (x) (= arctanx) también se implementan; el atan2 (y, x)

Página 81
4.7. FUNCIONES DE UNA VARIABLE 81

La función calcula el valor principal del arco tangente de y / x, usando los signos de ambos
argumentos para determinar el cuadrante del valor de retorno;

las funciones hiperbólicas,

sinhx = (e x - e −x ) / 2, coshx = (e x + e −x ) / 2.

y tanhx = sinhx / coshx llamado por sinh (x), cosh (x), tanh (x), asinh (x),
acosh (x) y atanh (x).
√ √
−1 [ ] −1 [ ]
pecado x = ln x+ x2+1 , aporrear x = ln x+ x2-1 .

La función real que redondea un real a un entero round (x) (resp. redondo (x))
redondea al valor integral, independientemente de la dirección de redondeo y devuelve real (resp. entero).
piso (x)se redondea al valor integral más grande no mayor que x vue como real, ceil (x) redondo
al valor integral más pequeño no menor que x; de manera similar, rint (x) devuelve el valor integral
más cercano ax (según el modo de redondeo predominante) en formato de coma flotante) y
lrint (x)devuelve un número entero. Con un have también de la función de cmath: fmod (x, y),
fmin (x, y), fmax (x, y), fdim (x, y) tales que las funciones fmod calculan el punto flotante
resto de x / y, fmin devuelve el mínimo, fmax devuelve el máximo, las funciones fdim () devuelven
la "diferencia positiva" entre sus argumentos: x - y si x> y, +0 si x ≤ y.

Funciones elementales denota para nosotros la clase de funciones presentadas anteriormente (polino-

https://translate.googleusercontent.com/translate_f 71/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
miales, exponencial, logarítmica, trigonométrica, circular) y las funciones obtenidas
de los de las cuatro operaciones aritméticas

f (x) + g (x), f (x) - g (x), f (x) g (x), f (x) / g (x)

y por composición f (g (x)), cada uno se aplicó un número finito de veces. En FreeFem ++,
por tanto, se pueden crear todas las funciones elementales. La derivada de una función elemental
La función es también una función elemental; sin embargo, la integral indefinida de un elemental
la función no siempre se puede expresar en términos de funciones elementales.

Ejemplo 4.4 El siguiente es un ejemplo donde se usa una función elemental para
construye el borde de un dominio. Cardioide

real b = 1 .;
real a = b;
func real phix ( real t)
{
return (a + b) * cos (t) -b * cos (t * (a + b) / b);
}
func real phiy ( real t)
{
return (a + b) * sin (t) -b * sin (t * (a + b) / b);
}
borde C (t = 0,2 * pi) {x = phix (t); y = phiy (t); }
malla Th = buildmesh (C (50));

Página 82
82 CAPÍTULO 4. SINTAXIS

Tomando el valor principal, podemos definir log z para z = 0 por

lnz = ln | z | + iarg z.

Usando FreeFem ++, calculamos exp (1 + 4i), sin (pi + 1i), cos (pi / 2-1i) y
log (1 + 2i), entonces tenemos

−1.77679 - 2.0572i, 1.8896710 −16 - 1.1752i,


9.4483310 −17 + 1.1752i, 0,804719 + 1,10715i.

Las funciones aleatorias se pueden definir ya que FreeFem ++ tiene una función Mersenne Twister (ver
página http://www.math.sci.hiroshima-u.ac.jp/˜m-mat/MT/emt.html para
detalle completo). Es un generador de números aleatorios muy rápido y preciso del período 2 219937 −1,
y las funciones que lo llaman son:

• randint32 () genera enteros de 32 bits sin signo.


• randint31 () genera enteros de 31 bits sin signo.
• randreal1 () genera real uniforme en [0,1] (resolución de 32 bits).

• randreal2 () genera real uniforme en [0,1) (resolución de 32 bits).


• randreal3 () genera real uniforme en (0,1) (resolución de 32 bits).
• randres53 () genera real uniforme en [0,1) con resolución de 53 bits.
• randinit (semilla) inicializa el vector de estado usando una "semilla" entera de 32 bits,
que puede ser cero.

Observación, el complemento ffrandom ((agregar carga "ffrandom") es una interfaz para aleatorio,
srandom, srandomdev generador aleatorio de funciones en el rango de 0 a (2 31 ) - 1
de la biblioteca libc de Unix (si la función srandomdev no existe, usamos una semilla
basado en la hora actual).

https://translate.googleusercontent.com/translate_f 72/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Observación, ahora todas las funciones aleatorias de gsllib ahora están interconectadas en el complemento gsl ((agregar
load "gsl") Consulte la sección D .1 de gsl para obtener más información.

Las funciones de biblioteca forman la biblioteca matemática (versión 2.17).

• las funciones j0 (x), j1 (x), jn (n, x), y0 (x), y1 (x), yn (n, x) son
las funciones de Bessel de primer y segundo tipo.
Las funciones j0 (x) y j1 (x) calculan la función de Bessel del primer tipo de
el orden 0 y el orden 1, respectivamente; la función jn (n, x) calcula el
Función de Bessel del primer tipo de orden entero n.
Las funciones y0 (x) y y1 (x) calculan la función de Bessel linealmente independiente
del segundo tipo de orden 0 y orden 1, respectivamente, para el
valor entero x (expresado como real); la función yn (n, x) calcula el Bessel
función del segundo tipo para el orden entero n para el valor entero positivo
x (expresado como real).
• la función tgamma (x) calcula la función Γ de x. lgamma (x) calcula
el logoritmo natural del valor absoluto de la función Γ de x.

Página 83
4.7. FUNCIONES DE UNA VARIABLE 83

• La función erf (x) calcula la función de error, donde erf (x) = 2 √ ∫ x exp (−t 2 ) dt.
(Pi) 0

La función erfc (x) = calcula la función de error complementario de x, es decir


erfc (x) = 1 - erf (x).
Observación, todas las funciones especiales de gsllib ahora están interconectadas en el complemento gsl ((agregar
cargar "gsl")

Función útil en C ++

• Distancia euclidiana dist (a, b) = sqrt (a 2 + b 2 ) o dist (a, b, c) = sqrt (a 2 + b 2 + c 2 )

• proyección de ξ en el segmento [a, b]: proyección (a, b, ξ) = min (max (a, ξ), b) si a <b

• proyección (a, b, x) = min (max (a, x), b) si a <b, min (max (b, x), a) else.

• min (a, b, c)

• max (a, b, c)

• diffpos (a, b) = max (b - a, 0)

• invdiffpos (a, b) = a <b? 1 ./ (b - a): 0

• diffnp (a, b) = (a <0) & (0 <b)? (B - a): 0

• invdiffnp (a, b) = (a <0) & (0 <b)? 1 / (b - a): 0

• invdiffnp (a, b) = (a <0) & (0 <b)? 1 / (b - a): 0

• invdiff (a, b) = (- | a - b |> 10 - 30)? 1 / (b - a): 0

• invdiff (a, b, e) = (- | a - b |> e)? 1 / (b - a): 0

• intercambiar (a, b) intercambiar el valor ayb por valores numéricos.

• signo (a) = (x> 0.) - (x <0.) para d-real e int.

• signbit (a) la función matemática bitign de real e int.

• copysign (a, b) la función matemática copysign de real a.

• isNaN (a) la función matemática isNaN de real.

• isInf (a) la función matemática isInf de real.

https://translate.googleusercontent.com/translate_f 73/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
• NaN () la función math nan ("") para construir un número NaN
• NaN (cadena) la función matemática nan (cadena) para construir un número NaN.

• signbit (a) la función matemática bitign de real e int.

• La función atoi (cadena) convierte la porción inicial de la cadena en int repre-


presentación.
• La función atof (cadena) convierte la parte inicial de la cadena en una representación real.
presentación.

Página 84
84 CAPÍTULO 4. SINTAXIS

4.8 Funciones de dos variables


4.8.1 Fórmula
La forma general de funciones reales de dos variables independientes a, b generalmente se escribe como
c = f (a, b). En FreeFem ++, x, y y z son palabras reservadas como se explica en la Sección 4.3.
Entonces, cuando las dos variables de la función son xey, podemos definir la función sin
su argumento, por ejemplo

func f = cos (x) + sen (y);

Observe que el tipo de función viene dado por el tipo de expresión. El operador de potencia puede ser
utilizado en funciones como xˆ1, yˆ0.23. En func, podemos escribir una función elemental
como sigue

func f = sin (x) * cos (y);


func g = (xˆ2 + 3 * yˆ2) * exp (1-xˆ2-yˆ2);
func h = max (-0.5,0.1 * log (fˆ2 + gˆ2));

La función de valor complejo crea funciones con 2 variables x, y de la siguiente manera,

malla Th = cuadrado (20,20, [- pi + 2 * pi * x, -pi + 2 * pi * y]); // ] - π, π [ 2


fespace Vh (Th, P2);
func z = x + y * 1i; // z = x + iy √
func f = imag (raíz cuadrada (z)); // f= z
func g = abs (sin (z / 10) * exp (zˆ2 / 10)); // g = | sen z / 10 exp z 2 /10 |
Vh fh = f; parcela (fh); // curvas de nivel de f
Vh gh = g; parcela (gh); // curvas de nivel de g

También llamamos a construir funciones elementales de dos variables a partir de funciones elementales f (x)
o g (y) por las cuatro operaciones aritméticas más la composición aplicadas un número finito de veces.

4.8.2 Funciones FE
Las funciones de elementos finitos también se construyen como funciones elementales mediante una fórmula aritmética.
mula que implica funciones elementales. La diferencia es que se evalúan en la declaración.
tiempo y FreeFem ++ almacena la matriz de sus valores en los lugares asociados con el grado
de libertad del tipo de elemento finito. Por oposición, las funciones elementales solo se evalúan
cuando sea necesario. Por tanto, las funciones FE no se definen sólo por su fórmula, sino también por la
malla y el elemento finito que entran en sus definiciones. Si el valor de una función FE es
solicitado en un punto que no es un grado de libertad, se utiliza una interpolación, lo que lleva a una
error de interpolación, mientras que, por el contrario, una función elemental se puede evaluar en cualquier punto
exactamente.

func f = xˆ2 * (1 + y) ˆ3 + yˆ2;


malla Th = cuadrado (20,20, [- 2 + 4 * x, -2 + 4 * y]); // cuadrado] - 2, 2 [ 2
fespace Vh (Th, P1);
Vh fh = f; // fh es la proyección de f a Vh (valor real)
func zf = (xˆ2 * (1 + y) ˆ3 + yˆ2) * exp (x + 1i * y);

https://translate.googleusercontent.com/translate_f 74/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Vh <complejo> zh = zf; // zh es la proyección de zf
// al valor complejo Vh espacio

La construcción de fh (= f h ) se explica en la Sección 6.

Página 85
4.9. ARRAYS 85

Nota 4.1 El diagrama de comando se aplica solo para funciones FE reales o complejas (2d o 3d) y
no a funciones elementales.

Las funciones con valores complejos crean funciones con 2 variables x, y de la siguiente manera,

malla Th = cuadrado (20,20, [- pi + 2 * pi * x, -pi + 2 * pi * y]); // ] - π, π [ 2


fespace Vh (Th, P2);
func z = x + y * 1i; // z = x + iy

func f = imag (raíz cuadrada (z)); // f= z
func g = abs (sin (z / 10) * exp (zˆ2 / 10)); // g = | sen z / 10 exp z 2 /10 |
Vh fh = f; parcela (fh); // La Fig. 4 0,1 isovalor de f
Vh gh = g; parcela (gh); // La Fig. 4 0,2 isovalor de g


Figura 4.1: z tiene rama Figura 4.2: | sen (z / 10) exp (z 2 /10) |

4.9 Matrices
Una matriz almacena varios objetos y hay 2 tipos de matrices: la primera es similar a
vector, es decir, matrices con índices enteros y el segundo tipo son matrices con índices de cadena.
En el primer caso, el tamaño de la matriz debe conocerse en el momento de la ejecución y la implementación
se hace con la clase KN <> y se implementan todos los operadores vectoriales de KN <>. Para
ejemplo

real [int] tab (10), tab1 (10); // 2 matriz de 10 reales


real [int] tab2; // matriz de errores sin tamaño
tab = 1.03; // establece toda la matriz en 1.03
tabulador [1] = 2,15;
cout << tab [1] << "" << tab [9] << "tamaño de la pestaña ="
<< tab.n << "min:" << tab.min << "max:" << tab.max
<< "suma:" << tab.sum << endl; //
tab.resize (12); // cambiar el tamaño de la pestaña de matriz
// a 12 conservando el primer valor
tabulador (10:11) = 3,14; // establecer valor desarmado
cout << "cambiar el tamaño de la pestaña:" << pestaña << endl;
real [cadena] tt;
tt ["+"] = 1,5;

https://translate.googleusercontent.com/translate_f 75/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 86
86 CAPÍTULO 4. SINTAXIS

cout << tt ["a"] << "" << tt ["+"] << endl;


real [int] a (5), b (5), c (5), d (5);
a = 1;
b = 2;
c = 3;
a [2] = 0;
d = (a? b: c); // para i = 0, n-1: d [i] = a [i]? b [i]: c [i],
cout << "d = (a? b: c) es" << d << endl;
d = (a? 1: c); // para i = 0, n-1: d [i] = a [i]? 1: c [i], (v2.23-1)
d = (a? b: 0); // para i = 0, n-1: d [i] = a [i]? b [i]: 0, (v2.23-1)
d = (a? 1: 0); // para i = 0, n-1: d [i] = a [i]? 0: 1, (v2.23-1)
tab.sort; // ordenar la pestaña de matriz (versión 2.18)
cout << "tabulador (después de ordenar)" << tab << endl;
int [int] ii (0: dn-1); // establecer matriz ii en 0,1, ..., dn-1 (v3.2)
d = -1: -5; // establecer d en -1, -2, .. -5 (v3.2)

sort (d, ii); // ordenar la matriz d y ii en paralelo


cout << "d" << d << "\ n ii =" << ii << endl;

produce la salida

2,15 1,03 tamaño de la pestaña = 10 mínimo: 1,03 máximo: 2,15 suma: 11,42
pestaña de cambio de tamaño: 12
1.03 2.15 1.03 1.03 1.03
1.03 1.03 1.03 1.03 1.03
3,14 3,14
0 1,5
d = (a? b: c) es 5
3 3 2 3 3
pestaña (después de ordenar) 12
1.03 1.03 1.03 1.03 1.03
1,03 1,03 1,03 1,03 2,15
3,14 3,14
d5
-5-4-3-2-1

ii = 5
4 3 2 1 0

Las matrices se pueden configurar como en matlab o scilab con el operador ::, el generador de matrices de a: c
es equivalente a a: 1: c, y la matriz establecida por a: b: c se establece en el tamaño ⌊ | (b - a) / c | + 1⌋ y el
el valor i se establece mediante a + i (b - a) / c.
Hay arreglos int, reales y complejos con, en el tercer caso, dos operadores (.in, .re) para
generar la matriz real real e imaginaria a partir de la matriz compleja (sin copia):

// versión 3.2 mai 2009


// como matlab. y scilab
{
int [int] tt (2:10); // 2,3,4,5,6,7,8,9,10
int [int] t1 (2: 3: 10); // 2,5,8,
cout << "tt (2:10) =" << tt << endl;
cout << "t1 (2: 3: 10) =" << t1 << endl;
tt = 1: 2: 5;
cout << "1.:2:5 =>" << tt << endl;
}

Página 87
4.9. ARRAYS 87

https://translate.googleusercontent.com/translate_f 76/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

{
real [int] tt (2:10); // 2,3,4,5,6,7,8,9,10
real [int] t1 (2.:3:10.); // 2,5,8,
cout << "tt (2:10) =" << tt << endl;
cout << "t1 (2: 3: 10) =" << t1 << endl;
tt = 1: 0,5: 3,999;
cout << "1.:0.5:3.999 =>" << tt << endl;
}
{
complejo [int] tt (2. + 0i: 10. + 0i); // 2,3,4,5,6,7,8,9,10
complejo [int] t1 (2.:3.:10.); // 2,5,8,
cout << "tt (2. + 0i: 10. + 0i) =" << tt << endl;
cout << "t1 (2.:3.:10.) =" << t1 << endl;
cout << "tt.re matriz de piezas reales "<< tt.re << endl;
// la matriz de la parte real de la matriz compleja
cout << "tt.im imag parte matriz "<< tt.im << endl;
// la matriz de la parte imag de la matriz compleja

La salida es:

tt (2:10) = 9
2 3 4 5 6
7 8 9 10
t1 (2: 3: 10) = 3
2 5 8
1.:2:5 => 3
1 3 5
tt (2:10) = = 9
2 3 4 5 6
7 8 9 10
t1 (2.:3:10.) = 3
2 5 8
1.:0.5:3.999 => 6
1 1,5 2 2.5 3
3,5
tt (2. + 0i: 10. + 0i) = 9
(2,0) (3,0) (4,0) (5,0) (6,0)
(7,0) (8,0) (9,0) (10,0)
t1 (2.:3.:10.); = 3
(2,0) (5,0) (8,0)

tt.re matriz de piezas reales 9


2 3 4 5 6
7 8 9 10
tt.im imag parte matriz 9
0 0 0 0 0
0 0 0 0
2

todos los operadores de matriz de enteros son:

Página 88
88 CAPÍTULO 4. SINTAXIS

int N = 5;
real [int] a (N), b (N), c (N);
a = 1;
a (0: 4: 2) = 2;
a (3: 4) = 4;
cout << "a =" << a << endl;
b = a + a;
cout << "b = a + a:" << b << endl;

https://translate.googleusercontent.com/translate_f 77/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
b + = a;
cout << "b + = a:" << b << endl;
b + = 2 * a;
cout << "b + = 2 * a:" << b << endl;
b / = 2;
cout << "b / = 2:" << b << endl;
b. * = a; // mismo b = b. * a
cout << "b. * = a; b =" << b << endl;
b ./= a; // mismo b = b ./ a
cout << "b./=a; b =" << b << endl;
c = a + b;
cout << "c = a + b: c =" << c << endl;
c = 2 * a + 4 * b;
cout << "c = 2 * a + 4b: c =" << c << endl;
c = a + 4 * b;
cout << "c = a + 4b: c =" << c << endl;
c = -a + 4 * b;
cout << "c = -a + 4b: c =" << c << endl;
c = -a-4 * b;
cout << "c = -a-4b: c =" << c << endl;
c = -ab;
cout << "c = -ab: c =" << c << endl;

c = a. * b;
cout << "c = a. * b: c =" << c << endl;
c = a ./ b;
cout << "c = a. / b: c =" << c << endl;
c = 2 * b;
cout << "c = 2 * b : c = "<< c << endl;
c = b * 2;
cout << "c = b * 2 : c = "<< c << endl;

/ * este operador no existe


c = b / 2;
cout << "c = b / 2 : c = "<< c << endl;
*/

// ---- los métodos --


cout << "|| a || _1 = "<< a.l1 << endl; //
cout << "|| a || _2 = "<< a.l2 << endl; //
cout << "|| a || _infty =" << a.linfty << endl; //
cout << "suma a_i = "<< a.sum << endl; //
cout << "max a_i = "<< a.max <<" a ["<< a.imax <<"] = "<< a [a.imax]
<< endl; //
cout << "min a_i = "<< a.min <<" a ["<< a.imin <<"] = "<< a [a.imin]
<< endl; //

cout << "a '* a = "<< (a '* a) << endl; //

Página 89
4.9. ARRAYS 89

cout << "un cuantil 0.2 =" << un.quantile (0.2) << endl; //
// mapeo de matrices
int [int] I = [2,3,4, -1,3];
b = c = -3;
b = a (I); // para (i = 0; i <bn; i ++) si (I [i]> = 0) b [i] = a [I [i]];
c (I) = a; // para (i = 0; i <In; i ++) si (I [i]> = 0) C (I [i]) = a [i];
cout << "b = a (I):" << b << "\ nc (I) = a" << c << endl;
c (I) + = a; // para (i = 0; i <In; i ++) si (I [i]> = 0) C (I [i]) + = a [i];
cout << "b = a (I):" << b << "\ nc (I) = a" << c << endl;

producir la salida

5
3 3 2 3 3

https://translate.googleusercontent.com/translate_f 78/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

== 3 3 2 3 3
a=5
2 1 2 4 4

b = a + a: 5
4 2 4 8 8

b + = a: 5
6 3 6 12 12

b + = 2 * a: 5
10 5 10 20 20

b / = 2: 5
5 2.5 5 10 10

b. * = a; b = 5
10 2.5 10 40 40

b./=a; b = 5
5 2.5 5 10 10

c = a + b: c = 5
7 3,5 7 14 14

c = 2 * a + 4b: c = 5
24 12 24 48 48

c = a + 4b: c = 5
22 11 22 44 44

c = -a + 4b: c = 5
18 9 18 36 36

c = -a-4b: c = 5
-22 -11 -22 -44 -44

c = -ab: c = 5
-7 -3,5 -7 -14 -14

Página 90
90 CAPÍTULO 4. SINTAXIS

c = a. * b: c = 5
10 2.5 10 40 40

c = a. / b: c = 5
0.4 0.4 0.4 0.4 0.4

c=2*b :c=5
10 5 10 20 20

c=b*2 :c=5
10 5 10 20 20

|| a || _1 = 13
|| a || _2 = 6.403124237
|| a || _infty = 4
suma a_i = 13
max a_i = 4 a [3] = 4
min a_i = 1 a [1] = 1
Automóvil club británico
= 41
un cuantil 0.2 = 2
b = a (I): 5
2 4 4-3 4

c (I) = a 5

https://translate.googleusercontent.com/translate_f 79/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
-3-3 2 4 2

b = a (I): 5
2 4 4-3 4

c (I) = a 5
-3-3 4 9 4

Nota 4.2 Los cuantiles son puntos tomados a intervalos regulares de la distribución acumulativa.
función de una variable aleatoria. Aquí los valores de la matriz son aleatorios.
Esta función estadística a.quantile (q) calcula v a partir de una matriz a de tamaño n para un
dado el número q ∈] 0,1 [tal que

# {i / a [i] <v} ∼ q ∗ n

es equivalente a v = a [q ∗ n] cuando la matriz a está ordenada.

Ejemplo de matriz con renumeración (versión 2.3 o mejor). La renumeración es siempre


dado por una matriz de enteros, y si un valor en la matriz es negativo, no se crea una imagen de la asignación,
por lo que no se establece el valor.

int [int] I = [2,3,4, -1,0]; // el mapeo de enteros para establecer la renumeración


b = c = -3;
b = a (I); // para (i = 0; i <bn; i ++) si (I [i]> = 0) b [i] = a [I [i]];
c (I) = a; // para (i = 0; i <In; i ++) si (I [i]> = 0) C (I [i]) = a [i];
cout << "b = a (I):" << b << "\ nc (I) = a" << c << endl;

La salida es

Página 91
4.9. ARRAYS 91

b = a (I): 5
2 4 4 -3 2

c (I) = a 5
4 -3 2 1 2

4.9.1 Matrices con dos índices enteros versus matrices


A continuación se ofrecen algunos ejemplos para transformar matrices completas en matrices dispersas.

int N = 3, M = 4;

real [int, int] A (N, M);


real [int] b (N), c (M);
b = [1,2,3];
c = [4, 5, 6, 7];

complejo [int, int] C (N, M);


complejo [int] cb = [1,2,3], cc = [10i, 20i, 30i, 40i];

b = [1,2,3];

int [int] I = [2,0,1];


int [int] J = [2,0,1,3];

A = 1; // establecer la matriz de todos


A (2, :) = 4; // la línea completa 2
A (:, 1) = 5; // la columna completa 1
A (0: N-1, 2) = 2; // establecer la columna 2

https://translate.googleusercontent.com/translate_f 80/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
A (1, 0: 2) = 3; // establecer la línea 1 de 0 a 2

cout << "A =" << A << endl;


// producto exterior
C = cb * cc ';
C + = 3 * cb * cc ';
C - = 5i * cb * cc ';
cout << "C =" << C << endl;
// esto transforma una matriz en una matriz dispersa
matriz B;
B = A;
B = A (I, J); // B (yo, j) = A (yo (yo), J (j))
B = A (Iˆ-1, Jˆ-1); // B (yo (yo), J (j)) = A (yo, j)

A = 2. * b * c '; // producto exterior


cout << "A =" << A << endl;
B = b * c '; // producto externo B (i, j) = b (i) * c (j)
B = b * c '; // producto externo B (i, j) = b (i) * c (j)
B = (2 * b * c ') (I, J); // producto externo B (i, j) = b (I (i)) * c (J (j))
B = (3. * b * c ') (Iˆ-1, Jˆ-1); // producto externo B (I (i), J (j)) = b (i) * c (j)
cout << "B = (3. * b * c ') (Iˆ-1, Jˆ-1) =" << B << endl;

Página 92
92 CAPÍTULO 4. SINTAXIS

la salida es

b = a (I): 5
2 4 4 -3 2

c (I) = a 5
4 -3 2 1 2

A=34
1 5 2 1
3 3 3 1
4 5 2 4

C=34
(-50, -40) (-100, -80) (-150, -120) (-200, -160)
(-100, -80) (-200, -160) (-300, -240) (-400, -320)
(-150, -120) (-300, -240) (-450, -360) (-600, -480)

A=34
8 10 12 14
16 20 24 28
24 30 36 42

4.9.2 Construcción y configuración de la matriz


• Para cambiar el solucionador de sistema lineal asociado a una matriz, haga

set (M, solver = sparsesolver);

El solucionador predeterminado es GMRES.

• de una forma variacional: (consulte la sección 6.12, página 195 para obtener más detalles)

varf vDD (u, v) = int2d (Thm) (u * v * 1e-10);


matriz DD = vDD (Lh, Lh);

• Para configurar desde una matriz constante

matriz A =

https://translate.googleusercontent.com/translate_f 81/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
[[0, 1, 0, 10],
[0, 0, 2, 0],
[0, 0, 0, 3],
[4,0, 0, 0]];

• Para configurar desde una matriz de bloques

matriz M = [
[Asd [0], 0 ,0 ,0 , Csd [0]],
[0 , Asd [1], 0 ,0 , Csd [1]],
[0 ,0 , Asd [2], 0 , Csd [2]],
[0 ,0 ,0 , Asd [3], Csd [3]],
[Csd [0] ', Csd [1]', Csd [2] ', Csd [3]', DD ]

Página 93
4.9. ARRAYS 93

];

// hasta ahora para empacar el lado derecho


real [int] bb = [rhssd [0] [], rhssd [1] [], rhssd [2] [], rhssd [3] [], rhsl []];
set (M, solver = sparsesolver );
xx = Mˆ-1 * bb;
[usd [0] [], usd [1] [], usd [2] [], usd [3] [], lh []] = xx; // para el despacho
// la solución en cada parte.

donde Asd y Csd son matrices de matrices (del ejemplo mortar-DN-4.edp de


ejemplos ++ - tuturial).

• Para establecer u obtener todos los índices y coeficientes de la matriz dispersa A, sean I, J, C
respectivamente dos matrices int [int] y una matriz real [int]. Las tres matrices definen
la matriz de la siguiente manera

A= ∑ C [k] M I [k], J [k] dónde M ab = (δ ia δ jb ) ij


k

uno tiene: M ab una matriz básica con el único término distinto de cero m ab = 1.

Se puede escribir [I, J, C] = A; para obtener todo el término de la matriz A (las matrices son
redimensionado automáticamente), y A = [I, J, C]; para cambiar todas las matrices de términos. Nota
que el tamaño de la matriz es n = I.max ym = J.max. Observe que yo, J es
olvidado construir una matriz diagonal, y de manera similar para los n, m de la matriz.

• renumeración de matrices

int [int] I (15), J (15); // dos matrices para renumerar


//
// el objetivo es transformar una matriz en una matriz dispersa
matriz B;
B = A; // matriz de copia A
B = A (I, J); // B (yo, j) = A (yo (yo), J (j))
B = A (Iˆ-1, Jˆ-1); // B (yo (yo), J (j)) = A (yo, j)
B. redimensionar (10,20); // cambiar el tamaño de la matriz dispersa y eliminar fuera del límite
condiciones

donde A es una matriz dada.

• matriz dispersa compleja versu real:

matriz < complejo > C = vv (Xh, Xh);


matriz R = vr (Xh, Xh);
matriz <complejo> CR = R; C = R; // crear o copiar el complejo tp de matriz real

https://translate.googleusercontent.com/translate_f 82/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
matriz
R = C.im; R = C.re; // obtener parte real o de imágenes de una matriz dispersa compleja
matriz CI = C.im, CR = C.re; // obtener imágenes reales o parte de un complejo escaso
matriz

Página 94
94 CAPÍTULO 4. SINTAXIS

4.9.3 Operaciones con matrices


Los operadores multiplicativos *, / y% se agrupan de izquierda a derecha.

• 'es la transposición derecha (unaria) para matrices, la matriz en casos reales y Hermitian
transponer en casos complejos.

•. * Es el término para denominar al operador multiplicar.

• ./ es el término para denominar al operador de división.

también hay algunos operadores compuestos:

• ˆ-1 es para resolver el sistema lineal (ejemplo: b = Aˆ-1 x)

• '* es el compuesto de transposición y producto de matriz, por lo que es el producto escalar (ex-
Amplio DotProduct real = a '* b), en caso complejo obtiene el producto Hermitian,
así que matemáticamente tenemos a '* b = a T b.

• a * b 'es el producto externo (ejemplo de matriz B = a' * b)

Ejemplo 4.5

malla Th = cuadrado (2,1);


fespace Vh (Th, P1);
Vh f, g;
f = x * y;
g = sin (pi * x);
Vh <complejo> ff, gg; // una función de elemento finito de valor complejo
ff = x * (y + 1i);
gg = exp (pi * x * 1i);
varf mat (u, v) =
int2d (Th) (1 * dx (u) * dx (v) + 2 * dx (u) * dy (v) + 3 * dy (u) * dx (v) + 4 * dy (u) * dy ( v))
+ en (1,2,3,4, u = 1);
varf mati (u, v) =
int2d (Th) (1 * dx (u) * dx (v) + 2i * dx (u) * dy (v) + 3 * dy (u) * dx (v) + 4 * dy (u) * dy ( v))
+ en (1,2,3,4, u = 1);
matriz A = esterilla (Vh, Vh); matriz <complejo> AA = mati (Vh, Vh); // un complejo
matriz dispersa

Vh m0; m0 [] = A * f [];
Vh m01; m01 [] = A '* f [];
Vh m1; m1 [] = f []. * g [];
Vh m2; m2 [] = f [] ./ g [];
cout << "f =" << f [] << endl ;
cout << "g =" << g [] << endl ;
cout << "A =" << A << endl ;
cout << "m0 =" << m0 [] << endl ;
cout << "m01 =" << m01 [] << endl ;
cout << "m1 =" << m1 [] << endl ;
cout << "m2 =" << m2 [] << endl ;
cout << "producto punto =" << f [] '* g [] << endl ;
cout << "Hermitien Product =" << ff [] '* gg [] << endl ;
cout << "Producto externo =" << (A = ff [] * gg [] ') << endl ;

https://translate.googleusercontent.com/translate_f 83/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 95
4.9. ARRAYS 95

cout << "producto exterior hermitien =" << (AA = ff [] * gg [] ') << endl ;
real [ int ] diagofA (An);
diagofA = A.diag; // obtener la diagonal de la matriz
A.diag = diagofA; // establecer la diagonal de la matriz
// versión 2.17 o mejor ---
int [ int ] I (1), J (1); real [int] C (1);
[I, J, C] = A; // obtener del término disperso de la matriz A (las matrices son
redimensionado)
cout << "I =" << I << endl;
cout << "J =" << J << endl;
cout << "C =" << C << endl;
A = [I, J, C]; // establecer una nueva matriz
matriz D = [diagofA]; // establecer una matriz diagonal D de la matriz diagofA.
cout << "D =" << D << endl;

Para el segundo caso, es solo un mapa del STL1[31] por lo que no se permiten operaciones en el vector,
excepto la selección de un artículo.
El operador de transposición o conjugación hermitiana es 'como en Matlab o Scilab, por lo que la forma de
calcular el producto escalar de dos matrices a, b es real ab = a '* b.
También se permite el cambio de tamaño de una matriz dispersa A:

A. redimensionar (10.100);

Tenga en cuenta que el nuevo tamaño puede ser mayor o menor que el anterior; todos los nuevos términos están establecidos
a cero.
En la triangulación de la Figura 2 .4 esto produce lo siguiente:

10 30 0,5 0. 30. −2,5 0.


0. 10 30 0,5 0. 0,5 −2,5
0. 0. 10 30 0. 0. 0,5
A=
0,5 0. 0. 10 30 0. 0.
−2,5 0,5 0. 0,5 10 30 0.
0. −2,5 0. 0. 0,5 10 30
T
{v} = f [] = (0 0 0 0 0.5 1)
{w} = g [] = (0 1 1.2 × 10 −16 0 1 1,2 × 10 −16 )

A * f [] = (−1,25 −2,25 0,5 0 5 × 10 29 10 30 ) T (= A {v})

A '* f [] = (−1,25 −2,25 0 0,25 5 × 10 29 10 30 ) T (= A T {v})

f []. * g [] = (0 0 0 0 0.5 1.2 × 10 −16 ) T = (v 1 w 1 ··· v M w M ) T

f [] ./ g [] = (−NaN 0 0 −NaN 0.5 8.1 × 10 15 ) T = (v 1 / w 1 ··· v M / w M ) T


f [] '* g [] = 0.5 (= {v} T {w} = {v} · {w})

La salida de la matriz I, J, C:

Yo = 18
0 0 0 1 1
1 1 2 2 3
3 4 4 4 4

1 biblioteca de plantillas estándar, ahora parte de C ++ estándar

Página 96

https://translate.googleusercontent.com/translate_f 84/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
96 CAPÍTULO 4. SINTAXIS

5 5 5
J = 18
0 1 4 1 2
4 5 2 5 0
3 0 1 3 4
1 4 5
C = 18
1e + 30 0,5 -2,5 1e + 30 0,5
0,5 -2,5 1e + 30 0,5 0,5
1e + 30 -2,5 0,5 0,5 1e + 30
-2,5 0,5 1e + 30

La salida de una matriz diagonal dispersa D (Advertencia de la interfaz fortran, los índices comienzan
en la salida en uno, pero en FreeFem ++ en el índice como en C comienzan en cero);

D = # Matriz espaciada (Morse)


# primera línea: nm (es simmético) nbcoef
# después de cada coeficiente distinto de cero: ij a_ij donde (i, j) \ in {1, ..., n} x {1, ..., m}
661 6
1 1 1.0000000000000000199e + 30
2 2 1.0000000000000000199e + 30
3 3 1.0000000000000000199e + 30
4 4 1.0000000000000000199e + 30
5 5 1.0000000000000000199e + 30
6 6 1.0000000000000000199e + 30

Nota 4.3 Los operadores ˆ-1 no se pueden utilizar para crear una matriz; lo siguiente da un error

matriz AAA = Aˆ-1;

En ejemplos ++ - load / lapack.edp se invierte una matriz completa usando la biblioteca lapack y esto
pequeña interfaz de enlace dinámico (consulte la sección C para obtener más detalles en la página 371).

cargar "lapack"
cargar "fflapack"
int n = 5;
real [int, int] A (n, n), A1 (n, n), B (n, n);
para (int i = 0; i <n; ++ i)
para (int j = 0; j <n; ++ j)
A (i, j) = (i == j)? n + 1: 1;
cout << A << endl;
A1 = Aˆ-1; // def en carga "lapack"
cout << A1 << endl;

B = 0;
para (int i = 0; i <n; ++ i)
para (int j = 0; j <n; ++ j)
para (int k = 0; k <n; ++ k)
B (yo, j) + = A (yo, k) * A1 (k, j);
cout << B << endl;
// A1 + Aˆ-1; atención ne marche pas

inv (A1); // def en la carga "fflapack"


cout << A1 << endl;

y la salida es:

Página 97
4.9. ARRAYS 97

55
6 1 1 1 1
1 6 1 1 1
1 1 6 1 1
1 1 1 6 1
1 1 1 1 6

https://translate.googleusercontent.com/translate_f 85/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

error: dgesv_ 0
55
0,18 -0,02 -0,02 -0,02 -0,02
-0.02 0.18 -0.02 -0.02 -0.02
-0,02 -0,02 0,18 -0,02 -0,02
-0,02 -0,02 -0,02 0,18 -0,02
-0,02 -0,02 -0,02 -0,02 0,18

55
1 -1.387778781e-17 -1.040834086e-17 3.469446952e-17 0
-1.040834086e-17 1 -1.040834086e-17 -2.081668171e-17 0
3.469446952e-18-5.551115123e-17 1 -2.081668171e-17 -2.775557562e-17
1.387778781e-17 -4.510281038e-17 -4.857225733e-17 1 -2.775557562e-17
-1.387778781e-17 -9.714451465e-17 -5.551115123e-17 -4.163336342e-17 1

55
6 1 1 1 1
1 6 1 1 1
1 1 6 1 1
1 1 1 6 1
1 1 1 1 6

para compilar lapack.cpp o fflapack.cpp debe tener la biblioteca lapack en su sistema


y probar en ejemplos de directorio ++ - cargar

ff-c ++ lapack.cpp -llapack


ff-c ++ fflapack.cpp -llapack

4.9.4 Otras matrices


También es posible hacer una matriz de funciones FE, con la misma sintaxis, y podemos
trátelos como una función de valor vectorial si los necesitamos. , la sintaxis para espacio o vector finito
la función es

int n = 100; // tamaño de la matriz.


Vh [ int ] wh (n); // caso escalar real
Wh [ int ] [uh, vh] (n); // caso vectorial real
Vh < complejo > [ int ] cwh (n); // caso escalar complejo
Wh < complejo > [ int ] [cuh, cvh] (n); // caso vectorial complejo
[cuh [2], cvh [2]] = [x, y]; // establecer la interpolación del índice 2.

// Matriz de Matriz
real [int] [int] V (10); //
matriz [int] B (10); //
real [int, int] [int] A (10); //

Página 98
98 CAPÍTULO 4. SINTAXIS

Ejemplo 4.6 En el siguiente ejemplo, la ecuación de Poisson se resuelve para 3 diferentes


funciones f = 1, sin (πx) cos (πy), | x − 1 || y −1 |, cuyas soluciones se almacenan en una matriz de FE
función.

malla Th = cuadrado (20,20, [2 * x, 2 * y]);


fespace Vh (Th, P1);
Vh u, v, f;
problema de Poisson (u, v) =
int2d (Th) ( dx (u) * dx (v) + dy (u) * dy (v))
+ int2d (Th) (-f * v) + en (1,2,3,4, u = 0);
Vh [ int ] uu (3); // una matriz de función FE
f = 1; // problema1
Poisson; uu [0] = u;
f = sin (pi * x) * cos (pi * y); // problema2

https://translate.googleusercontent.com/translate_f 86/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Poisson; uu [1] = u;
f = abs (x-1) * abs (y-1); // problema3
Poisson; uu [2] = u;
para ( int i = 0; i <3; i ++) // traza todas las soluciones
plot (uu [i], espera = verdadero);

4.10 Matrices de mapas


Para el segundo caso, es solo un mapa del STL2[31] por lo que no se permiten operaciones en el vector,
excepto la selección de un artículo.

mapa real [cadena]; // una matriz dinámica


para (i = 0; i <10; i = i + 1)
{
tabulador [i] = i * i;
cout << i << "" << tab [i] << "\ n";
};

mapa ["1"] = 2.0;


mapa [2] = 3,0; // 2 se convierte automáticamente en la cadena "2".

cout << "mapa [\" 1 \ "] =" << mapa ["1"] << ";" << endl ;
cout << "mapa [2] =" << mapa [2] << ";" << endl ;

4.11 Bucles
Los bucles for y while se implementan en FreeFem ++ junto con break y
continuar con las palabras clave.
En bucle for, hay tres parámetros; la INICIALIZACIÓN de una variable de control, la
CONDICIÓN para continuar, el CAMBIO de la variable de control. Si bien la CONDICIÓN es verdadera,
for-loop continuar.

2 Biblioteca de plantillas estándar, ahora parte de C ++ estándar

Página 99
4.11. LAZOS 99

para (INICIALIZACIÓN; CONDICIÓN; CAMBIO)


{BLOQUE de cálculos}

Un ejemplo a continuación muestra una suma de 1 a 10 con el resultado en suma,

int suma = 0;
para ( int i = 1; i <= 10; i ++)
suma + = yo;

El bucle while

while (CONDICIÓN) {
BLOQUE de cálculos o cambio de variables de control
}

se ejecuta repetidamente hasta que CONDITION se vuelve falsa. La suma de 1 a 10 también puede ser
calculado por while de la siguiente manera,

int i = 1, suma = 0;
mientras que (i <= 10) {
suma + = yo; i ++;
}

https://translate.googleusercontent.com/translate_f 87/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Podemos salir de un bucle en el medio de la corriente haciendo una pausa . La declaración continue pasará el
parte de continuar hasta el final del ciclo.

Ejemplo 4.7

para ( int i = 0; i <10; i = i + 1)


cout << i << "\ n";
eps real = 1;
mientras (eps> 1e-5)
{eps = eps / 2;
si (i ++ <100) se rompe ;
cout << eps << endl ;}

para (int j = 0; j <20; j ++) {


si (j <10) continuar ;
cout << "j =" << j << endl ;
}

A partir de la versión 3.43, tenemos un nuevo tipo de bucle implícito para establecer matrices, mapas y matrices dispersas.
La sintaxis es

• para [i, ai: a] para una matriz con un índice, por lo que si es real [int] a (10), entonces i = 0
a 9 y ai es una referencia a a [i], lo mismo para la [cadena] real a (10), ...

• para [i, j, aij: a] para una matriz con dos índices, así que si real [int, int] a (10,11), entonces
i = 0 a 9, j = 0 a 10 y aij es una referencia a a (i, j), lo mismo para la matriz a (10)
...

Página 100
100 CAPÍTULO 4. SINTAXIS

Ejemplo 4.8

real [ int , int ] a (10,10);


real [ int ] b (10);
para [i, bi: b] {bi = i + 1; cout << i << "" << bi << endl;}
cout << "b =" << b << endl ;
para [i, j, aij: a]
{
aij = 1./(2+i+j);
si (abs (aij) <0,2) aij = 0;
}
cout << "a =" << a << endl ;
matriz A = a;
cadena [ cadena ] ss; // un mapa
ss ["1"] = 1;
ss ["2"] = 2;
ss ["3"] = 5;
para [i, bi: ss]
bi = i + 6 + "- dddd";
cout << "ss =" << ss << endl ;
int [ cadena ] si;
si [1] = 2;
si [50] = 1;
para [i, vi: si]
{
cout << "i" << setw (3) << i << "" << setw (10) << vi << endl; //
vi = atoi (i) * 2; //
}

https://translate.googleusercontent.com/translate_f 88/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
cout << "si =" << si << endl;
para [i, j, aij: A]
{
cout << i << "" << j << "" << aij << endl;
aij = -aij;
}
cout << A << endl;

4.12 Entrada / Salida


La sintaxis de las declaraciones de entrada / salida es similar a la sintaxis de C ++. Utiliza cout , cin , endl ,
<<, >>.
Para escribir (o leer desde) un archivo, declare una nueva variable de flujo ofile ("nombre de archivo");
o ofstream ofile ("nombre de archivo", anexar); (resp. ifstream ifile ("nombre de archivo");
) y el uso de ofile (resp. ifile) como cout (resp. cin).
La palabra agregar en ofile ofstream ("nombre de archivo", agregar | binario); significa abierto
ing un archivo en modo adjunto y binario.

Nota 4.4 El archivo se cierra a la salida del bloque adjunto,

Página 101
4.12. DE ENTRADA Y SALIDA 101

Ejemplo 4.9

int i;
cout << "std-out" << endl ;
cout << "ingrese i =?";
cin >> i;
{
ofstream f ("toto.txt");
f << i << "coucou '\ n";
}; // cierra el archivo f porque la variable f es eliminar

{
ifstream f ("toto.txt");
f >> i;
}
{
ofstream f ("toto.txt", anexar);
// para agregar al archivo existente "toto.txt"
f << i << "coucou '\ n";
}; // cierra el archivo f porque la variable f es eliminar

cout << i << endl ;

Algunas funciones están disponibles para formatear la salida.

• int nold = f. precisión (n) Establece el número de dígitos impresos a la derecha del
punto decimal. Esto se aplica a todos los números de coma flotante subsiguientes escritos en ese
flujo de salida. Sin embargo, esto no hará que los "enteros" de punto flotante se impriman con un decimal.
punto. Es necesario utilizar fijo para ese efecto.

• f. Formatos científicos números de punto flotante en notación científica (d.dddEdd)

• f. fijo Se usa la notación de punto fijo (d.ddd) para números de punto flotante. Opuesto de
científico.

• f. showbase Convierte las inserciones en un formulario externo que se puede leer de acuerdo con
Convenciones léxicas de C ++ para constantes integrales. Por defecto, showbase no está configurado.

• f. noshowbase unset showbase flags

https://translate.googleusercontent.com/translate_f 89/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

• f. showpos inserta un signo más (+) en una conversión decimal de un valor integral positivo.

• f. noshowpos unset showpos flags

• f. restablece por defecto todos los indicadores anteriores (fmtflags) a la precisión de espera predeterminada.

• setw (n) Se comporta como si el ancho del miembro fuera llamado con n como argumento en la secuencia en
que se inserta como manipulador (se puede insertar en flujos de salida).

Donde f es el descriptor de flujo de salida, por ejemplo cout.


Observe que todos estos métodos, excepto el primero, devuelven el flujo f, por lo que pueden encadenarse como en

cout.scientific.showpos << 3 << endl;

Un ejemplo útil para ver el uso de alguna función en el flujo de archivos:

Página 102
102 CAPÍTULO 4. SINTAXIS

{
archivo ofstream ("f.txt", binario ); // para Windows agregue la versión binaria 3.30
expediente. precisión (16);
archivo << f [] << endl;
donde = archivo. tellp ();
archivo << 0.1;
// archivo << "" << 0.2;
cout << "donde en el archivo" << donde << endl;
archivo << "# comentario bla bla ... 0.3 \ n";
archivo << 0.2 << endl;
expediente. enjuagar ; // para vaciar el búfer del archivo
}
// Idea para omitir el comentario en un archivo ... comience con # también EOL
func comentario de omisión de ifstream ( ifstream & ff)
{

mientras (1)
{
int donde = ff. tellg (); // almacenar la posición del archivo
comentario de cadena;
ff >> comentario;
si (! ff. bueno ()) romper ;
if (comentario (0: 0) == "#") {
getline (ff, comentario);
cout << "- #" << comentario << endl;
}
else {
ff. seekg (donde); // restaurar la posición del archivo
romper ;
}
}
return ff;
}
{
archivo ifstream ("f.txt", binario ); // para windows (pb CRNL EOL translation)
cout << "donde" << archivo. seekg << endl;
expediente. seekg (donde);
archivo >> xx;
cout << "xx =" << xx << "bueno?" << archivo. bueno () << endl;
afirmar (xx == 0.1);

https://translate.googleusercontent.com/translate_f 90/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
skipcomment (archivo) >> xx;
afirmar (xx == 0.2);
expediente. seekg (0); // rebobinar ...
cout << "donde" << archivo. tellg () << "" << archivo. bueno () << endl;
archivo >> g [];
}

Página 103
4.13. PREPROCESADOR 103

4.12.1 Argumentos del script


Hay una matriz predefinida muy útil en FreeFem ++ ARGV que contiene todos los argumentos
del script utilizado en la línea de comandos. El siguiente código imprime los tres primeros de estos
argumentos:

// versión 3.8-1
para (int i = 0; i <ARGV.n; ++ i)
{
cout << ARGV [i] << endl;
}

El parámetro -Dmacroname = macrovalor de ARGV es una forma sencilla de agregar macro al


el script como en "C ++".
Y para que el argumento no se utilice en getARGV.idp incluya el archivo de script,

getARGV (n, valor predeterminado) // obtener el enésimo parámetro sin usar


// si existe (n = 1, ...)
getARGV (después, valor predeterminado) // obtener el argumento después de la cadena después de si existe

El tipo de valor predeterminado puede ser int, real, string,

4.13 preprocesador
El preprocesador maneja las directivas para la inclusión de archivos fuente (incluye "script-name.idp"),
definiciones de macros.
Hay dos tipos de macros, de tipo objeto y de función. Las macros de tipo objeto no
tomar parámetros; las macros de función similar lo hacen. La sintaxis genérica para declarar un identificador como
una macro de cada tipo es, respectivamente,

macro <identificador> () <lista de tokens de reemplazo> // EOM a // comentario para finalizar


la macro
macro <identificador> (<lista de parámetros>) <lista de tokens de reemplazo> // MOE

Un ejemplo de macro sin parámetro

macro xxx () {real i = 0; int j = 0; cout << i << "" << j << endl;} //
xxx / * reemplace xxx por la <lista de tokens de reemplazo> * /

El código FreeFem ++ asociado:

1: // macro sin parámetro


2: macro xxx {real i = 0; int j = 0; cout << i << "" << j << endl;} //
3:
4: {i real = 0; int j = 0; cout << i << "" << j << endl;}

Un ejemplo de parámetro macro

macro toto (i) i //


// parámetro de cotización los {} se eliminan
toto ({i real = 0; int j = 0; cout << i << "" << j << endl;})
// y solo se quita un nivel de {}

https://translate.googleusercontent.com/translate_f 91/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 104
104 CAPÍTULO 4. SINTAXIS

toto ({{real i = 0; int j = 0; cout << i << "" << j << endl;}})

El código FreeFem ++ creado:

6: macro toto (i) I //


8: // parámetro de comillas que \ {\} se eliminan
9: real i = 0; int j = 0; cout << i << "" << j << endl;
10: // y solo se elimina un nivel de \ {\}
11: {i real = 0; int j = 0; cout << i << "" << j << endl;}

Use una macro como parámetro de macro para transformar la matriz completa en una matriz formal como en:

real [ int , int ] CC (7,7), EE (6,3), EEps (4,4);

macro VIL6 (v, i) [v (1, i), v (2, i), v (4, i), v (5, i), v (6, i)] // MOE
macro VIL3 (v, i) [v (1, i), v (2, i)] // MOE
// aplicar v en el elemento de la matriz:
macro VV6 (v, vv) [v (vv, 1), v (vv, 2),
v (vv, 4), v (vv, 5), v (vv, 6)] // MOE
macro VV3 (v, vv) [v (vv, 1), v (vv, 2)] // MOE
// matriz tan formal para construir problema ..
func C5x5 = VV6 (VIL6, CC);
func E5x2 = VV6 (VIL3, EE);
func Eps = VV3 (VIL3, EEps);

El código FreeFem ++ creado:

16: real [int, int] CC (7,7), EE (6,3), EEps (4,4);


17:
18: macro VIL6 (v, i) [v (1, i), v (2, i), v (4, i), v (5, i), v (6, i)] // EOM
19: macro VIL3 (v, i) [v (1, i), v (2, i)] // EOM
20: // aplica v en el elemento de la matriz:
21: macro VV6 (v, vv) [v (vv, 1), v (vv, 2),
22: v (vv, 4), v (vv, 5), v (vv, 6)] // EOM
23: macro VV3 (v, vv) [v (vv, 1), v (vv, 2)] // EOM
24: // matriz tan formal para construir problema ..
25: función C5x5 =
1: [ [CC (1,1), CC (2,1), CC (4,1), CC (5,1), CC (6,1)],
[CC (1,2), CC (2,2), CC (4,2), CC (5,2), CC (6,2)],
1: [CC (1,4), CC (2,4), CC (4,4), CC (5,4), CC (6,4)],
[CC (1,5), CC (2,5), CC (4,5), CC (5,5), CC (6,5)],
[CC (1,6), CC (2,6), CC (4,6), CC (5,6), CC (6,6)] ];
26: función E5x2 =
1: [ [EE (1,1), EE (2,1)], [EE (1,2), EE (2,2)],
1: [EE (1,4), EE (2,4)], [EE (1,5), EE (2,5)],
[EE (1,6), EE (2,6)] ];
27: función Eps = [ [EEps (1,1), EEps (2,1)],
[EEps (1,2), EEps (2,2)] ];
28:

https://translate.googleusercontent.com/translate_f 92/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 105
4.13. PREPROCESADOR 105

finalmente el operador # para hacer la concatenación del parámetro: para construir la operación vectorial, como en

macro div (u) (dx (u # 1) + dy (u # 2)) // MOE


malla Th = cuadrado (2,2); fespace Vh (Th, P1);
Vh v1 = x, v2 = y;
cout << int2d (Th) (div (v)) << endl;

El código FreeFem ++ creado:

31: macro div (u) (dx (u # 1) + dy (u # 2)) // EOM


32: malla Th = cuadrado (2,2); fespace Vh (Th, P1);
33: Vh v1 = x, v2 = y;
34: cout << int2d (Jue) ( (dx (v1) + dy (v2))) << endl;

Y para terminar una prueba increíble para verificar la cotización:

macro foo (i, j, k) ijk // MOE


foo (,,) // linea vacia
foo ({int [}, {int] a (10}, {);})

el resultado:

36: macro foo (i, j, k) ijk // EOM


37: // línea vacía
38: int [int] a (10);

Para definir una macro en una macro, puede usar las dos nuevas palabras NewMacro, tecla EndMacro
palabra para establecer y cerrar la definición de macro (versión 3.11, y no bien probada).
En la versión 3.51-2, probamos en la generación de macros como #ifdef ... #endif en C ++, el
la sintaxis es:

macro AA tt //

IFMACRO (AA, tt)


// si AA == tt
cout << "AA" << Cadena de caracteres (AA) << endl;
macro f1 cas1 //
ENDIFMACRO
IFMACRO (AA, bb)
// si AA == bb
macro CAS 2 //
ENDIFMACRO

IFMACRO (DIR)
// macro DIR existe
incluir Stringification (DIR / f1.edp)
ENDIFMACRO

la salida es

Página 106
106 CAPÍTULO 4. SINTAXIS

MBP-FH3: ˜ hecht $ FreeFem ++ aa.edp -DDIR =.


- FreeFem ++ v 3.500002 (fecha Jeu 19 de enero de 2017 16:46:23 CET)
Carga: lg_fem lg_mesh lg_mesh3 valor propio

https://translate.googleusercontent.com/translate_f 93/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
1: macro AAtt //
2:
3:
1: // si AA == tt
2: cout << "AA" << Cadena de caracteres (tt) << endl;
3: macro f1cas1 //
4:
4:
5:
6:
1: // existe la macro DIR
2: incluir Stringification (./ cas1.edp) cout << "f1.edp" << endl;
3:
7: pila de tamaños + 1024 = 1072 (48)

AA tt
f1.edp
tiempos: compilar 0.003547s, ejecución 1.6e-05s, mpirank: 0
CodeAlloc: nb ptr 2604, tamaño: 340800 mpirank: 0
Ok: final normal
MBP-FH3: ˜ hecht $

Y FILE, LINE, Stringification () para obtener el número de línea y el nombre de archivo edp, agregue una cita a un pa-
rameter después de la macro generación? Como en

cout << "en" << ARCHIVO << "línea" << LÍNEA << " - '"
<< Stringification ("zzz" aa () {} + / * * / bb cc) << "'" << endl;

Observación, puede ver el ejemplo Stokes-macro2d-3d.edp en el tutorial para obtener un verdadero


uso de esta funcionalidad.

4.14 Manejo de excepciones


En la versión 2.3 de FreeFem ++, se agregó la gestión de excepciones como en C ++. Pero hoy solo
se detectan las excepciones de C ++. Tenga en cuenta que en C ++ todos los errores adjuntos a ExecError,
afirmar, salir, ... llamar a excepciones también, por lo que puede ser difícil encontrar la causa del error.
Las excepciones manejan todos los ExecError:

Ejemplo 4.10 Un ejemplo simple: captura una división por cero:

real a;
prueba {
a = 1. / 0 .;
}

Página 107
4.14. MANEJO DE EXCEPCIONES 107

atrapar (...) // en las versiones> 2.3 se pueden detectar todas las excepciones
{
cout << "Detectar un error de ejecución" << endl;
a = 0;
}

La salida es

1/0: ddd
línea actual = 3
Error de ejecución: Div por 0

https://translate.googleusercontent.com/translate_f 94/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
-- numero 1
Prueba :: catch (...) excepción
Atrapa un ExecError

Ejemplo 4.11: un ejemplo más realista con una matriz no invertible:

int nn = 5 ;
malla Th = cuadrado (nn, nn);
verbosidad = 5;
fespace Vh (Th, P1); // Espacio P1 FE
Vh uh, vh; // Función desconocida y de prueba.
func f = 1; // función del lado derecho
func g = 0; // función de condición de frontera
verdadero cpu = reloj ();
problema laplace (uh, vh, solucionador = Cholesky, tolpivot = 1e-6) = //
definición del problema
int2d (Th) (dx (uh) * dx (vh) + dy (uh) * dy (vh)) // forma bilineal
+ int2d (Th) (-f * vh) // forma lineal
;

prueba {
cout << "Pruebe Cholesky \ n";
laplace; // resolver el problema
trama (uh); // para ver el resultado
cout << "- vuelta Cholesky" << nn << "x" << nn << ":" << -cpu + reloj ()
<< "s, max =" << uh []. max << endl;
}
catch (...) { // atrapar todo
cout << "Atrapa Cholesky PB" << endl;
}

La salida es

- malla cuadrada: nb vértices = 36, nb triángulos = 50 ...


Nb de aristas en morteros = 0
Número de aristas en el límite = 20, neb = 20
Nb Morteros 0
número de aristas límite reales 20
Número de bordes = 85
Número de bordes de límites = 20 neb = 20
Número de aristas de morteros =0

Página 108
108 CAPÍTULO 4. SINTAXIS

Nb de morteros con papel Def = 0 Nb de morteros = 0 ...


Número de nodos = 36
Nb de DF = 36
Prueba Cholesky
- Cambio de malla 0 0x312e9e8
Problema (): initmat 1 VF (Galerkin discontinuo) = 0
- SizeOfSkyline = 210
- tamaño del horizonte de Matrix 196 Bytes = 1
- Galerkin discontinuo = 0 tamaño de Mat = 196 Bytes
- int en Optimizado = 1, ...
todas
- límite int Optimizado = 1, todos
ERREUR choleskypivot (35) = -1.23124e-13 <1e-06
línea actual = 28
Error de ejecución: ERREUR FATAL en ../femlib/MatriceCreuse_tpl.hpp
línea cholesky:
- número: 545
detectar un error en solve => set sol = 0 !!!!!!!

https://translate.googleusercontent.com/translate_f 95/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Prueba
Atrapa:: Cholesky
catch (...) PB
excepción

Página 109

Capítulo 5

Generación de malla

5.1 Comandos para la generación de mallas


Comencemos con las dos palabras clave importantes border y buildmesh
Todos los ejemplos de esta sección provienen de los archivos mesh.edp y tablefunction.edp.

5.1.1 Cuadrado
El comando "cuadrado" triangula el cuadrado de la unidad. La siguiente

malla Th = cuadrado (4,5);

genera una cuadrícula de 4 × 5 en el cuadrado unitario [0,1] 2 . Las etiquetas de los límites se muestran en

https://translate.googleusercontent.com/translate_f 96/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Fig. 5.1 . Para construir una cuadrícula de × m en el rectángulo [x 0 , x 1 ] × [y 0 , y 1 ], procede de la siguiente manera:

la bel = 3

etiqueta etiqueta
=4 =2

la bel = 1

Figura 5.1: Etiquetas de contorno de la malla por cuadrado (10,10)

escribir

real x0 = 1,2, x1 = 1,8;


y0 real = 0, y1 = 1;
int n = 5, m = 20;
malla Th = cuadrado (n, m, [x0 + (x1-x0) * x, y0 + (y1-y0) * y]);

109

Página 110
110 CAPÍTULO 5. GENERACIÓN DE MALLA

Nota 5.1 Agregar el parámetro con nombre flags = icase con icase:

0 producirá una malla donde todos los quads se dividen con diagonal x - y = cte

1 producirá un tipo de malla tipo bandera Union Jack.

2 producirá una malla donde todos los quads se dividen con diagonal x + y = cte (v 3.8)

3 igual que el caso 0, excepto en dos esquinas de modo que ningún triángulo con 3 vértices en el límite (v
3.8)

4 igual que en el caso 2 excepto en dos esquinas de modo que ningún triángulo con 3 vértices en el límite (v
3.8)

malla Th = cuadrado (n, m, [x0 + (x1-x0) * x, y0 + (y1-y0) * y], banderas = icase);

Agregar el parámetro con nombre label = labs cambiará los 4 números de etiqueta predeterminados a labs [i-1],
por ejemplo, int [int] labs = [11,12,13,14],
y agregar el parámetro con nombre región = 10 cambiará el número de región a 10, por
instancia (v 3.8).
Para ver todos estos maricones en acción, pruebe el archivo examples ++ / square-mesh.edp:

para ( int i = 0; i <5; ++ i)


{
int [ int ] labs = [11,12,13,14];
malla Th = cuadrado (3,3, banderas = i, etiqueta = laboratorios, región = 10);
plot (Th, espera = 1, cmm = "banderas cuadradas =" + i);
}

5.1.2 Borde
https://translate.googleusercontent.com/translate_f 97/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Los límites se definen por partes mediante curvas parametrizadas. Las piezas solo pueden cruzarse en
sus puntos finales, pero es posible unir más de dos puntos finales. Esto se puede utilizar para
estructura la malla si un área marca un borde y crea nuevas regiones dividiendo más
unos:

int superior = 1;
int otros = 2;
int inner = 3;

borde C01 (t = 0,1) {x = 0; y = -1 + t; etiqueta = superior;}


frontera C02 (t = 0,1) {x = 1,5-1,5 * t; y = -1; etiqueta = superior;}
frontera C03 (t = 0,1) {x = 1,5; y = -t; etiqueta = superior;}
borde C04 (t = 0,1) {x = 1 + 0,5 * t; y = 0; label = otros;}
frontera C05 (t = 0,1) {x = 0,5 + 0,5 * t; y = 0; label = otros;}
frontera C06 (t = 0,1) {x = 0,5 * t; y = 0; label = otros;}
borde C11 (t = 0,1) {x = 0,5; y = -0,5 * t; etiqueta = interior;}
borde C12 (t = 0,1) {x = 0,5 + 0,5 * t; y = -0,5; etiqueta = interior;}

Página 111
5.1. COMANDOS PARA LA GENERACIÓN DE MALLA 111

borde C13 (t = 0,1) {x = 1; y = -0,5 + 0,5 * t; etiqueta = interior;}

int n = 10;
gráfico (C01 (-n) + C02 (-n) + C03 (-n) + C04 (-n) + C05 (-n) + C06 (-n) +
C11 (n) + C12 (n) + C13 (n), espera = verdadero);

malla Th = malla de construcción (C01 (-n) + C02 (-n) + C03 (-n) + C04 (-n) + C05 (-n) + C06 (-n) +
C11 (n) + C12 (n) + C13 (n));

trama (Th, espera = verdadero); // figura 5.3

cout << "La parte 1 tiene un número de región" << Th (0.75, -0.25) .region << endl;
cout << "La parte 2 tiene un número de redion" << Th (0.25, -0.25) .region << endl;

Figura 5.2: Los extremos de varios bordes se cruzan Figura 5.3: Malla generada

Las palabras clave de triangulación asumen que el dominio se define como a la izquierda (resp. A la derecha)
de su límite orientado parametrizado

Γ j = {(x, y) | x = ϕ x (t), y = ϕ y (t), a j ≤ t ≤ b j }

Para comprobar la orientación de la gráfica t ↦ → (ϕ x (t), ϕ y (t)), t 0 ≤ t ≤ t 1 . Si es como en la Fig. 5. 4, entonces el


El dominio se encuentra en el área sombreada, de lo contrario, se encuentra en el lado opuesto.
La expresión general para definir una triangulación con buildmesh es

malla Mesh_Name = buildmesh (Γ 1 (m 1 ) + ··· + Γ J (m j ) OptionalParameter);


https://translate.googleusercontent.com/translate_f 98/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

donde m j son números positivos o negativos para indicar cuántos vértices deben estar en
Γj,Γ=∪J
j = 1 Γ J , y el parámetro opcional (separado con coma) puede ser

nbvx = <valor int> , para establecer el número máximo de vértices en la malla.

Fixedborder = <valor bool> , para decir si el generador de malla puede cambiar el límite
malla o no (de forma predeterminada, la malla delimitante puede cambiar; tenga en cuenta que con
condiciones de contorno (ver. 6) , puede ser peligroso.

Página 112
112 CAPÍTULO 5. GENERACIÓN DE MALLA

t=t1 t=t0
t=t1
Γj
( х = φ х ( t ), y = φ y ( t ))
t=t0 ( d φ х ( t ) / dt , d φ y ( t ) / tdt= )t 0 t=t1
(х=t,y=t)( х=t,y=-t)

Figura 5.4: Orientación del límite definido por (φ x (t), φ y (t))

La orientación de los límites se puede cambiar cambiando el signo de m j . La siguiente


El ejemplo muestra cómo cambiar la orientación. El ejemplo genera el disco unitario con un
pequeño orificio circular, y asigne "1" al disco de la unidad ("2" al círculo interior). EL limite
La etiqueta debe ser distinta de cero, pero también se puede omitir.

1: borde a (t = 0,2 * pi) {x = cos (t); y = sin (t); etiqueta = 1;}


2: borde b (t = 0,2 * pi) {x = 0,3 + 0,3 * cos (t); y = 0.3 * sin (t); etiqueta = 2;}
3: trama (a (50) + b (+30)); // para ver un diagrama de la malla del borde
4: malla Thwithouthole = buildmesh (a (50) + b (+30));
5: malla Thwithhole = malla de construcción (a (50) + b (-30));
6: plot (Thwithouthole, wait = 1, ps = "Thwithouthole.eps"); // figura 5.5
7: plot (Thwithhole, wait = 1, ps = "Thwithhole.eps"); // figura 5.6

Nota 5.2 Observe que la orientación cambia con “b (-30)” en la quinta línea. En séptima línea,
ps = "fileName" se utiliza para generar un archivo postscript con la identificación que se muestra en la figura.

Figura 5.5: malla sin agujero Figura 5.6: malla con agujero

Nota 5.3 Los bordes se evalúan solo en el momento en que se llama plot o buildmesh, por lo que
variable se definen en este momento y aquí, dado que r se cambia entre las dos llamadas de borde,
https://translate.googleusercontent.com/translate_f 99/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

El siguiente código no funcionará porque el primer borde se calculará con r = 0.3:

Página 113
5.1. COMANDOS PARA LA GENERACIÓN DE MALLA 113

real r = 1; borde a (t = 0,2 * pi) {x = r * cos (t); y = r * sin (t); etiqueta = 1;}
r = 0,3 ; borde b (t = 0,2 * pi) {x = r * cos (t); y = r * sin (t); etiqueta = 1;}
malla Thwithhole = malla de construcción (a (50) + b (-30)); // error (una trampa) porque
// los dos círculos tienen el mismo radio = 0.3

5.1.3 Multiborde
(Versión 3.30)
En algún momento puede ser útil hacer una matriz de bordes, pero desafortunadamente es incompatible
con la sintaxis FreeFem ++. Entonces, para evitar este problema, la idea es pequeña, si el número
del segmento de la discretización n es una matriz, hacemos un bucle implícito en todo el valor de
la matriz, y la variable de índice i del bucle se define después de la definición del parámetro, como en
borde a (t = 0,2 * pi; i) ....
Un primer ejemplo muy pequeño:

1: borde a (t = 0,2 * pi; i) {x = (i + 1) * cos (t); y = (i + 1) * sin (t); etiqueta = 1;}


2: int [int] nn = [10,20,30];
3: trama (a (nn)); // trazar 3 círculos con 10,20,30 puntos.

Y un ejemplo más complejo (tome del ejemplo mesh.edp) para definir un cuadrado con una pequeña
circies:

// sintaxis de múltiples bordes versión 3.30 avril 2014 ...


real [int] xx = [0,1,1,0],
yy = [0,0,1,1];
// radio, centro de los 4 círculos.
real [int] RC = [0.1, 0.05, 0.05, 0.1],
XC = [0.2,0.8,0.2,0.8],
YC = [0,2, 0,8, 0,8, 0,2];
int [int] NC = [- 10, -11, -12,13]; // enumerar el número de ± segmentos
// de los 4 círculos bordes

borde bb (t = 0,1; i)
{
// i es la variable de índice del bucle de borde múltiple
int ii = (i + 1)% 4; t1 real = 1-t;
x = xx [i] * t1 + xx [ii] * t;
y = yy [i] * t1 + yy [ii] * t;
etiqueta = 0; ;
}

frontera cc (t = 0,2 * pi; i)


{
x = RC [i] * cos (t) + XC [i];
y = RC [i] * sen (t) + YC [i];
etiqueta = i + 1;
}
int [int] nn = [4,4,5,7]; // 4 borde, con 4,4,5,7 segmento respectivamente.
plot (bb (nn), cc (NC), espera = 1);
malla th = buildmesh (bb (nn) + cc (NC));
trama (th, esperar = 1);

https://translate.googleusercontent.com/translate_f 100/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 114
114 CAPÍTULO 5. GENERACIÓN DE MALLA

5.1.4 Estructuras de datos y declaraciones de lectura / escritura para una malla


Los usuarios que quieran leer una triangulación realizada en otro lugar deberían ver la estructura del archivo
generado a continuación:

borde C (t = 0,2 * pi) {x = cos (t); y = sin (t); }


malla Th = buildmesh (C (10));
savemesh ("mesh_sample.msh");

la malla se muestra en la Fig. 5.7.

La información sobre Th se guarda en el archivo “mesh sample.msh”. cuya estructura es


que se muestra en la Tabla 5.1.
Allí n v denota el número de vértices, n t número de triángulos y n s el número de aristas
en el límite.
Para cada vértice q i , i = 1, ···, n v , denotar por (q i
x , q yyo) la coordenada xy la coordenada y.
Cada triángulo T k , k = 1, ···, 10 tiene tres vértices q k , q k , q k que están orientados en sentido contrario al reloj.
1 2 3

sabio. El límite consta de 10 líneas L i , i = 1, ···, 10 cuyos extremos son q i , q i . 1 2

2
1 En la figura de la izquierda, tenemos lo siguiente.

5
11
3
norte v = 14, norte t = 16, n s = 10
3 5

4 q 1 = (−0,309016994375, 0,951056516295)
8 13
... ... ...
12
9 2

9 q 14 = (−0,309016994375, −0,951056516295)
7 6
8
7
10 13 Los vértices de T 1 son q 9 , q 12 , q 10 .
... ... ...
15 1
12
Los vértices de T 16 son q 9 , q 10 , q 6 .
11 14 4 10
6
El borde del 1er lado L 1 son q 6 , q 5 .
... ... ...
14
13
El borde del décimo lado L 10 son q 10 , q 6 .
Figura 5.7: malla por buildmesh (C (10))

En FreeFem ++ hay muchos formatos de archivo de malla disponibles para comunicarse con otros
herramientas como emc2, modulef .. (ver Sección 12 ), La extensión de un archivo implica su formato.
Se pueden encontrar más detalles en el formato de archivo .msh en el artículo de F. Hecht ”bamg: a
generador de malla anisotrópica bidimensional ”(descargable del sitio web de FreeFem).
Se puede leer un archivo de malla en FreeFem ++ excepto que los nombres de los bordes se pierden
y solo se conservan sus números de referencia. Por lo tanto, estos bordes deben ser referenciados por el
número que corresponde a su orden de aparición en el programa, a menos que este número
se sobrescribe con la palabra clave "etiqueta". Aquí hay unos ejemplos:

piso del borde (t = 0,1) {x = t; y = 0; etiqueta = 1;}; // el cuadrado de la unidad


borde derecho (t = 0,1) {x = 1; y = t; etiqueta = 5;};
techo fronterizo (t = 1,0) {x = t; y = 1; etiqueta = 5;};

Página 115
5.1. COMANDOS PARA LA GENERACIÓN DE MALLA 115

Contenido del archivo Explicación


14 16 10 nv nt ne

https://translate.googleusercontent.com/translate_f 101/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
-0,309016994375 0,951056516295 1 q X1 q y1 etiqueta de límite = 1
0,309016994375 0,951056516295 1 q X2 q y2 etiqueta de límite = 1
··· ··· ...
-0,309016994375 -0,951056516295 1 q 14 X q y14 etiqueta de límite = 1
9 12 10 0 11 12 13 etiqueta de región = 0
5960 21 22 23 etiqueta de región = 0
···
9 10 6 0 16 1 16 2 16 3 etiqueta de región = 0
651 1 1 1 2 etiqueta de límite = 1
521 2 1 2 2 etiqueta de límite = 1
···
10 6 1 10 1 10 2 etiqueta de límite = 1

Tabla 5.1: La estructura de "mesh sample.msh"

borde izquierdo (t = 1,0) {x = 0; y = t; etiqueta = 5;};


int n = 10;
malla th = buildmesh (piso (n) + derecha (n) + techo (n) + izquierda (n));
savemesh (th, "toto.am_fmt"); // formato "Marrocco formateado"
savemesh (th, "toto.Th"); // malla de tipo "bamg"
savemesh (th, "toto.msh"); // formato freefem
savemesh (th, "toto.nopo"); // formato modulef ver [ 14 ]
malla th2 = readmesh ("toto.msh"); // lee la malla

Ejemplo 5.1 (Readmesh.edp) piso del borde (t = 0,1) {x = t; y = 0; etiqueta = 1;}; // la


unidad cuadrada
borde derecho (t = 0,1) {x = 1; y = t; etiqueta = 5;};
techo fronterizo (t = 1,0) {x = t; y = 1; etiqueta = 5;};
borde izquierdo (t = 1,0) {x = 0; y = t; etiqueta = 5;};
int n = 10;
malla th = buildmesh (piso (n) + derecha (n) + techo (n) + izquierda (n));
savemesh (th, "toto.am_fmt"); // formato "Marrocco formateado"
savemesh (th, "toto.Th"); // formato de base de datos db mesh "bamg"
savemesh (th, "toto.msh"); // formato freefem
savemesh (th, "toto.nopo"); // formato modulef ver [ 14 ]
malla th2 = readmesh ("toto.msh");
fespace femp1 (th, P1 );
femp1 f = sin (x) * cos (y), g;
{ // guardar solución
archivo ofstream ("f.txt");
archivo << f [] << endl;
} // cerrar el archivo (bloque final)
{ // leer
archivo ifstream ("f.txt");
archivo >> g [];
} // cerrar archivo de lectura (bloque final)

Página 116
116 CAPÍTULO 5. GENERACIÓN DE MALLA

fespace Vh2 (th2, P1);


Vh2 u, v;
parcela (g);
// encontrarte tal que
// u + ∆u = g en Ω,
// u = 0 en Γ 1 y ∂u En = g en Γ 2
resolver pb (u, v) =
int2d (th) (u * v - dx (u) * dx (v) -dy (u) * dy (v))
+ int2d (th) (- g * v)
∂u
+ int1d (th, 5) (g * v) // En
= g en Γ 2

https://translate.googleusercontent.com/translate_f 102/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
+ en (1, u = 0);
trama (th2, u);

5.1.5 Conectividad de malla y datos


El siguiente ejemplo explica métodos para obtener información de malla.

{ // obtener información de malla (versión 1.37)


malla Th = cuadrado (2,2);
// obtener datos de la malla
int nbtriangles = Th.nt;
área real = Th.measure, borderlen = Th.bordermeasure; // Versión 3.56
cout << "nb of Triangles =" << nbtriangles << endl;
para (int i = 0; i <nbtriangles; i ++)
para (int j = 0; j <3; j ++)
cout << i << "" << j << "Th [i] [j] ="
<< Th [i] [j] << "x =" << Th [i] [j] .x << ", y =" << Th [i] [j] .y
<< ", label =" << Th [i] [j] .label << endl;

// Th (i) devuelve el vextex i de Th


// Th [k] devuelve el triángulo k de Th

fespace femp1 (Th, P1);


femp1 Thx = x, Thy = y; // truco de obtener coordenadas de vértice
// obtener información de vértices:
int nbvertices = Th.nv;
cout << "nb de vértices =" << nbvertices << endl;
para (int i = 0; i <nbvertices; i ++)
cout << "Th (" << i << "):" // << endl;
<< Th (i) .x << "" << Th (i) .y << "" << Th (i) .label // v 2.19
<< " método antiguo: "<< Thx [] [i] <<" "<< Thy [] [i] << endl;

// método para encontrar información del punto (0.55,0.6)

int it00 = Th (0.55,0.6) .nuTriangle; // luego el número del triángulo


int nr00 = Th (0,55,0,6). región; //

// información de un triángulo
área real00 = Th [it00] .área; // nuevo en la versión 2.19
nrr00 real = Th [it00] .región; // nuevo en la versión 2.19
real nll00 = Th [it00] .label; // igual que la región en este caso.

// Hackear para obtener un triángulo que contenga los puntos x, y

Página 117
5.1. COMANDOS PARA LA GENERACIÓN DE MALLA 117

// o número de región (método antiguo)


// -------------------------------------------------- -----
fespace femp0 (Th, P0);
femp0 nuT; // una función P0 para obtener la numeración de triángulos
para (int i = 0; i <Th.nt; i ++)
nuT [] [i] = i;
femp0 nuReg = región; // una función P0 para obtener el número de región
// preguntar
int it0 = nuT (0.55,0.6); // número de triángulos que contienen Th (0.55,0,6);
int nr0 = nuReg (0.55,0.6); // número de región de Th que contiene (0.55, 0, 6);

// vertedero
// -------------------------------------------------- -----

cout << "punto (0.55,0,6): número de triángulo" << it00 << "" << it00
<< ", region =" << nr0 << "==" << nr00 << ", area K" << area00 << endl;

https://translate.googleusercontent.com/translate_f 103/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
// nuevo método para obtener información de límites y mallas adyacentes
int k = 0, l = 1, e = 1;
Th.nbe; // devuelve el número de elemento de límite
Th.be (k); // devuelve el elemento de frontera k ∈ {0, ..., T h.nbe - 1}
Th.be (k) [l]; // devuelve los vértices l ∈ {0, 1} del límite elmt k
Th.be (k) .Element; // devuelve el triángulo que contiene el límite elmt
k
Th.be (k) .whoinElement; // devuelve el número de arista del triángulo
conteniendo
// el límite elmt k
Th [k] .adj (e); // devuelve el triángulo adyacente a k por la arista e, y cambia
// el valor de e al borde correspondiente en el triángulo adyacente
Th [k] == Th [k] .adj (e) // triángulo no adyacente devuelve el mismo
Th [k]! = Th [k] .adj (e) // verdadero triángulo adyacente

cout << "conectividad de malla de impresión" << endl;


int nbelement = Th.nt;
para ( int k = 0; k <nbelement; ++ k)
cout << k << ":" << int (Th [k] [0]) << "" << int (Th [k] [1])
<< "" << int (Th [k] [2])
<< ", etiqueta" << Th [k] .label << endl;
//

para ( int k = 0; k <nbelement; ++ k)


para ( int e = 0, ee; e <3; ++ e)
// comentario truco FH: establece ee en e, y ee es cambio por método adj,
// en () para marcar la diferencia con los parámetros con nombre.
cout << k << "" << e << "<=>" << int (Th [k] .adj ((ee = e))) << "" << ee
<< "adj:" << (Th [k] .adj ((ee = e))! = Th [k]) << endl;
// nota: si k == int (Th [k] .adj (ee = e)) no elemento adyacente

int nbboundaryelement = Th.nbe;

para (int k = 0; k <nbboundaryelement; ++ k)


cout << k << ":" << Th.be (k) [0] << "" << Th.be (k) [1] << ", etiqueta"
<< Th.be (k) .label << "tria" << int (Th.be (k) .Element)

Página 118
118 CAPÍTULO 5. GENERACIÓN DE MALLA

<< "" << Th.be (k) .whoinElement << endl;


real [int] bb (4);
cuadro delimitador (Th, bb); //
// bb [0] = xmin, bb [1] = xmax, bb [2] = ymin, bb [3] = ymax
cout << "\ n cuadro delimitador xmin:" << bb [0] << "xmax:" << bb [1]
<< "ymin:" << bb [2] << "ymax:" << bb [3] << endl;
}

la salida es:

- malla cuadrada: nb vértices = 9, nb triángulos = 8, nb bordes límite 8


Nb de vértices 9, Nb de triángulos 8
Nb de aristas en el límite del usuario 8, Nb de aristas en el límite verdadero 8
número de aristas límite reales 8
nb de triángulos = 8
0 0 Th [i] [j] = 0 x = 0, y = 0, etiqueta = 4
0 1 Th [i] [j] = 1 x = 0.5, y = 0, etiqueta = 1
0 2 Th [i] [j] = 4 x = 0.5, y = 0.5, etiqueta = 0
...
6 0 Th [i] [j] = 4 x = 0.5, y = 0.5, etiqueta = 0
6 1 Th [i] [j] = 5 x = 1, y = 0.5, etiqueta = 2
6 2 Ju [i] [j] = 8 x = 1, y = 1, etiqueta = 3
7 0 Th [i] [j] = 4 x = 0.5, y = 0.5, etiqueta = 0
7 1 Ju [i] [j] = 8 x = 1, y = 1, etiqueta = 3
7 2 Ju [i] [j] = 7 x = 0.5, y = 1, etiqueta = 3
Número de nodos = 9
Nb de DF = 9

https://translate.googleusercontent.com/translate_f 104/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
- límite de la función vectorial 0 1
- límite de la función vectorial 0 1
nb de vértices = 9
Jue (0): 0 0 4 método antiguo: 0 0
Jue (1): 0.5 0 1 método antiguo: 0.5 0
...
Jue (7): 0.5 1 3 método antiguo: 0,5 1
Jue (8): 1 1 3 método antiguo: 1 1
Nb de nodos = 8
Nb de DF = 8

conectividad de malla de impresión


0: 0 1 4, etiqueta 0
1: 0 4 3, etiqueta 0
...
6: 4 5 8, etiqueta 0
7: 4 8 7, etiqueta 0
0 0 <=> 3 1 adj: 1
0 1 <=> 1 2 adj: 1
0 2 <=> 0 2 adj: 0
...
6 2 <=> 3 0 adj: 1
7 0 <=> 7 0 adj: 0
7 1 <=> 4 0 adj: 1
7 2 <=> 6 1 adj: 1
0: 0 1, etiqueta 1 tria 0 2
1: 1 2, etiqueta 1 tria 2 2
...
6: 0 3, etiqueta 4 tria 1 1

Página 119
5.1. COMANDOS PARA LA GENERACIÓN DE MALLA 119

7: 3 6, etiqueta 4 tria 5 1

cuadro delimitador xmin: 0 xmax: 1 ymin: 0 ymax: 1

La función característica real de una malla Th es chi (Th) en 2d y 3d donde

chi (Th) (P) = 1 si P ∈ Th; chi (Th) (P) = 0 si P ∈ Th; (5,1)

5.1.6 La palabra clave "triangular"


FreeFem ++ puede construir una triangulación a partir de un conjunto de puntos. Esta triangulación es una
Malla de Delaunay del casco convexo del conjunto de puntos. Puede ser útil construir una forma de malla.
una función de tabla.
Las coordenadas de los puntos y el valor de la función de tabla se definen por separado con
filas de la forma: xyf (x, y) en un archivo como:

0,51387 0,175741 0,636237


0,308652 0,534534 0,746765
0,947628 0,171736 0,899823
0,702231 0,226431 0,800819
0.494773 0.12472 0.580623
0,0838988 0,389647 0,456045
...............

https://translate.googleusercontent.com/translate_f 105/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 5.8: Malla de Delaunay del casco convexo Figura 5.9: Isovalor de la función de tabla
del punto establecido en el archivo xyf

La tercera columna de cada línea no se modifica con el comando triangular. Pero tu


puede usar este tercer valor para definir una función de tabla con filas de la forma: xyf (x, y).
El siguiente ejemplo muestra cómo hacer una malla a partir del archivo "xyf" con el formato indicado
justo arriba. El comando triangular comando use solo use 1ra y 2da filas.

malla Thxy = triangular ("xyf"); // construir la malla Delaunay del casco convexo
// los puntos están definidos por las 2 primeras columnas del archivo xyf
plot (Thxy, ps = "Thxyf.ps"); // (ver figura 5.8 )

fespace Vhxy (Thxy, P1); // crear una interpolación P1


Vhxy fxy; // la función

// leyendo la tercera fila para definir la función

Página 120
120 CAPÍTULO 5. GENERACIÓN DE MALLA

{ archivo ifstream ("xyf");


real xx, yy;
para ( int i = 0; i <fxy.n; i ++)
archivo >> xx >> yy >> fxy [] [i]; // para leer solo la tercera fila.
// xx y yy simplemente se omiten
}
gráfico (fxy, ps = "xyf.eps"); // trazar la función (ver figura 5.9 )

Una nueva forma de construir una malla es tener dos matrices, una con los valores xy otra con los valores y
valores (versión 2.23-2):

Vhxy xx = x, yy = y; // para establecer dos matrices para las x y las y


malla Th = triangular (xx [], yy []);

5.2 Espacios FEM de contorno construidos como mallas vacías


Para definir un espacio de elementos finitos en un límite, se nos ocurrió la idea de una malla sin
puntos internos (llamar malla vacía). Puede ser útil manejar multiplicadores de Lagrange en mezcla
y métodos de mortero.
Entonces, la función emptymesh elimina todos los puntos internos de una malla, excepto los puntos en
límites internos.

{ // cosas nuevas 2004 emptymesh (versión 1.40)


// - útil para construir espacio Multiplicador
// construir una malla sin punto interno
// con el mismo límite
// -----
afirmar (versión> = 1.40);
borde a (t = 0,2 * pi) {x = cos (t); y = sin (t); etiqueta = 1;}
malla Th = buildmesh (a (20));
Th = malla vacía (Th);
plot (Th, espera = 1, ps = "emptymesh-1.eps"); // ver figura 5.10
}

También es posible construir una malla vacía de una pseudo subregión con una malla vacía (Th, ssd)
utilizando el conjunto de bordes de la malla Th; una arista e está en este conjunto si con los dos triángulos adyacentes
e = t1 ∩ t2 y ssd [T1] = ssd [T2] donde ssd se refiere a la numeración de pseudoregiones de
triángulos, cuando se almacenan en una matriz int [int] de tamaño el número de triángulos.

{ // cosas nuevas 2004 emptymesh (versión 1.40)

https://translate.googleusercontent.com/translate_f 106/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
// - útil para construir espacio Multiplicador
// construir una malla sin punto interno
// del subdominio peusdo
// -----
afirmar (versión> = 1.40);
malla Th = cuadrado (10,10);
int [ int ] ssd (Th.nt);
para ( int i = 0; i <ssd.n; i ++) // construir la numeración de la pseudoregión
{ int iq = i / 2; // porque 2 triángulos por quad
int ix = iq% 10; //
int iy = iq / 10; //
ssd [i] = 1 + (ix> = 5) + (iy> = 5) * 2;

Página 121
5.3. REMEDIENDO 121

}
Th = malla vacía (Th, ssd); // construir emtpy con
// todos los bordes e = T1 ∩ T2 y ssd [T1] = ssd [T2]
plot (Th, espera = 1, ps = "emptymesh-2.eps"); // ver figura 5.11
savemesh (Th, "emptymesh-2.msh");
}

Figura 5.10: La malla vacía con límite Figura 5.11: Una malla vacía definida a partir de un
aria numeración de pseudoregión de triángulo

5.3 Remallado
5.3.1 Movemesh
Las mallas se pueden trasladar, rotar y deformar mediante movemesh; esto es útil para la elasticidad
para observar la deformación debida al desplazamiento Φ (x, y) = (Φ 1 (x, y), Φ 2 (x, y)) de la forma. Eso
también es útil para manejar problemas de límites libres o problemas de formas óptimas.
Si Ω se triangula como T h (Ω), y Φ es un vector de desplazamiento, entonces Φ (T h ) se obtiene mediante

malla Th = movemesh (Th, [Φ1, Φ2]);

A veces, la malla transformada no es válida porque algún triángulo se ha volteado (ahora tiene
área negativa) .Para detectar tales problemas, uno puede verificar el área mínima del triángulo en el
malla transformada con checkmovemesh antes de cualquier transformación real.

Ejemplo 5.2 Φ 1 (x, y) = x + k ∗ sin (y ∗ π) / 10), Φ 2 (x, y) = y + k ∗ cos (yπ) / 10) para un número grande
k> 1.

https://translate.googleusercontent.com/translate_f 107/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
verbosidad = 4;
borde a (t = 0,1) {x = t; y = 0; etiqueta = 1;};
borde b (t = 0,0.5) {x = 1; y = t; etiqueta = 1;};
borde c (t = 0,0.5) {x = 1-t; y = 0.5; etiqueta = 1;};

Página 122
122 CAPÍTULO 5. GENERACIÓN DE MALLA

borde d (t = 0.5,1) {x = 0.5; y = t; etiqueta = 1;};


borde e (t = 0.5,1) {x = 1-t; y = 1; etiqueta = 1;};
borde f (t = 0,1) {x = 0; y = 1-t; etiqueta = 1;};
func uu = sin (y * pi) / 10;
func vv = cos (x * pi) / 10;

malla Th = buildmesh (a (6) + b (4) + c (4) + d (4) + e (4) + f (6));


plot (Th, espera = 1, relleno = 1, ps = "Lshape.eps"); // ver figura 5.12
coef real = 1;
real minT0 = checkmovemesh (Th, [x, y]); // el área mínima del triángulo
mientras (1) // encontrar una malla de movimiento correcta
{
minT real = checkmovemesh (Th, [x + coef * uu, y + coef * vv]); // el área mínima del triángulo
si (minT> minT0 / 5) se rompe; // si es lo suficientemente grande
coef / = 1,5;
}

Th = movemesh (Th, [x + coef * uu, y + coef * vv]);


trazar (Th, esperar = 1, llenar = 1, ps = "movemesh.eps"); // ver figura 5.13

Figura 5.12: Forma de L Figura 5.13: forma de L movida

Nota 5.4 Considere una función u definida en una malla Th. Una declaración como Th = movemesh (Th ...)
no cambia u y, por lo tanto, la malla anterior todavía existe. Se destruirá cuando no se utilice ninguna función.
eso. Una declaración como u = u redefine u en la nueva malla Th con interpolación y por lo tanto
destruye el antiguo Th si u era la única función que lo usaba.

Ejemplo 5.3 (movemesh.edp) Ahora, damos un ejemplo de malla en movimiento con un lagrangiano
función u definida en la malla móvil.

// ejemplo simple de movemesh


malla Th = cuadrado (10,10);
fespace Vh (Th, P1);
t real = 0;
// ---

https://translate.googleusercontent.com/translate_f 108/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 123
5.4. TRIANGULACIÓN REGULAR: TRIÁNGULO 123

// el problema es cómo construir datos sin interpolación


// por lo que los datos u se mueven con la malla como puede ver en la gráfica
// ---
Vh u = y;
para (int i = 0; i <4; i ++)
{
t = i * 0,1;
Vh f = x * t;
minarea real = checkmovemesh (Th, [x, y + f]);
si (minarea> 0) // movemesh estará bien
Th = movemesh (Th, [x, y + f]);

cout << "Área mínima" << minarea << endl;

real [int] tmp (u []. n);


tmp = u []; // guarda el valor
u = 0; // para cambiar el FEspace y la malla asociada con u
u [] = tmp; // establecer el valor de u sin ninguna actualización de malla
plot (Th, u, espera = 1);
};
// En este programa, dado que u solo se define en la última malla, todos los
// las mallas anteriores se borran de la memoria.
// --------

5.4 Triangulación regular: hTriangle


Para un conjunto S, definimos el diámetro de S por

diam (S) = sup {| x - y |; x, y ∈ S}

La secuencia {T h } h ↓ 0 de Ω se llama regular si satisfacen lo siguiente:

1.
lim max {diam (T k ) | T k ∈ T h } = 0
h↓0

2. Hay un número σ> 0 independiente de h tal que

ρ (T k )
≥σ para todo T k ∈ T h
diam (T k )

donde ρ (T k ) son el diámetro del círculo inscrito de T k .

Ponemos h (T h ) = max {diam (T k ) | T k ∈ T h }, que se obtiene por

malla Th = ......;
fespace Ph (Th, P0);
Ph h = h Triángulo ;
cout << "tamaño de la malla =" << h []. max << endl ;

Página 124
124 CAPÍTULO 5. GENERACIÓN DE MALLA

https://translate.googleusercontent.com/translate_f 109/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

5.5 Adaptmesh
La función

f (x, y) = 10.0x 3 + y 3 + tan −1 [ε / (sin (5.0y) - 2.0x)] ε = 0.0001

varía bruscamente en valor y la malla inicial dada por uno de los comandos de la Sección 5.1
no puede reflejar sus fuertes variaciones.

Ejemplo 5.4

eps reales = 0,0001;


h real = 1;
hmin real = 0,05;
func f = 10.0 * xˆ3 + yˆ3 + h * atan2 (eps, sin (5.0 * y) -2.0 * x);

malla Th = cuadrado (5,5, [- 1 + 2 * x, -1 + 2 * y]);


fespace Vh (Th, P1);
Vh fh = f;
parcela (fh);
para ( int i = 0; i <2; i ++)
{
Th = adaptmesh (Th, fh);
fh = f; // se elimina la malla antigua
trama (Th, fh, espera = 1);
}

Yo nitial Primero Segundo


malla adaptación adaptación

Figura 5.14: Gráficos 3D para la malla inicial y la adaptación de la 1a y 2a malla

Página 125
5.5. ADAPTACIÓN 125

FreeFem ++ utiliza un algoritmo de mallado automático de métrica variable / Delaunay. El comando

malla ATh = adaptmesh (Th, f);

crear la nueva malla ATh adaptada al arpillera

D 2 f = (∂ 2 f / ∂x 2 , ∂ 2 f / ∂x∂y, ∂ 2 f / ∂y 2 )
https://translate.googleusercontent.com/translate_f 110/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

de una función (fórmula o función FE). La adaptación de la malla es una herramienta muy poderosa cuando
La solución de un problema varía localmente y de forma aguda.
Aquí resolvemos el problema ( 2.1 ) - (2.2), cuando f = 1 y Ω es un dominio en forma de L.

ser

bd
antes de Cristo
bf

cama y desayuno

licenciado en Letras

Figura 5.15: Dominio en forma de L y su límite Figura 5.16: Solución final después de 4 veces
nombre ario adaptación

Ejemplo 5.5 (Adapt.edp) La solución tiene la singularidad r 3/2 , r = | x - γ | en el punto γ


de la intersección de dos rectas bc y bd (vea la figura 5.15) .

borde ba (t = 0,1.0) {x = t; y = 0; etiqueta = 1;};


borde bb (t = 0,0.5) {x = 1; y = t; etiqueta = 1;};
borde bc (t = 0,0.5) {x = 1-t; y = 0.5; etiqueta = 1;};
borde bd (t = 0.5,1) {x = 0.5; y = t; etiqueta = 1;};
borde sea (t = 0.5,1) {x = 1-t; y = 1; etiqueta = 1;};
borde bf (t = 0.0,1) {x = 0; y = 1-t; etiqueta = 1;};
malla Th = buildmesh (ba (6) + bb (4) + bc (4) + bd (4) + be (4) + bf (6));
fespace Vh (Th, P1 ); // establecer espacio FE
Vh u, v; // establecer función desconocida y de prueba
func f = 1;
error real = 0,1; // nivel de error
problema de Poisson (u, v, solucionador = CG, eps = 1.0e-6) =
int2d (Th) (dx (u) * dx (v) + dy (u) * dy (v))
- int2d (Th) (f * v)
+ en (1, u = 0);
para ( int i = 0; i <4; i ++)
{
Poisson;
Th = adaptmesh (Th, u, err = error);

Página 126
126 CAPÍTULO 5. GENERACIÓN DE MALLA

error = error / 2;
};
trama (u);

Para acelerar la adaptación, el parámetro predeterminado err de adaptmesh se cambia a mano;


especifica la precisión requerida para hacer la nueva malla más fina o más gruesa.
El problema es coercitivo y simétrico, por lo que el sistema lineal se puede resolver con el conjugado
método de gradiente (solucionador de parámetros = CG con el criterio de detención en el residual, aquí
eps = 1.0e-6). Adaptmesh, la pendiente de la solución final se calcula correctamente cerca de
el punto de intersección de bc y bd como en la figura 5.16 .
Este método se describe en detalle en [13 ]. Tiene una serie de parámetros predeterminados que pueden
ser modificado :
Si f1, f2 sont des functions et thold, Thnew des maillages.

https://translate.googleusercontent.com/translate_f 111/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Thnew = adaptmesh (Thold, f1 ...);


Thnew = adaptmesh (Thold, f1, f2 ...]);
Thnew = adaptmesh (Thold, [f1, f2] ...);

Los parámetros adicionales de adaptmesh no están escritos aquí, de ahí el "..."

hmin = Tamaño mínimo del borde. (val es un real. Su valor predeterminado está relacionado con el tamaño del dominio
para ser mallado y la precisión del generador de malla).

hmax = Tamaño máximo del borde. (val es un real. Por defecto, el diámetro del dominio es
mallado)

err = nivel de error de interpolación P 1 (0.01 es el valor predeterminado).

errg = Error geométrico √relativo. Por defecto este error es 0.01, y en cualquier caso debe ser
menor que 1 / 2. Las mallas creadas con esta opción pueden tener algunos bordes más pequeños que
el -hmin debido a restricciones geométricas.

nbvx = Número máximo de vértices generados por el generador de malla (9000 es el valor predeterminado).

nbsmooth = número de iteraciones del procedimiento de suavizado (5 es el valor predeterminado).

nbjacoby = número de iteraciones en un procedimiento de suavizado durante la construcción de la métrica,


0 significa que no hay suavizado (6 es el valor predeterminado).

ratio = ratio para un suavizado prescrito en la métrica. Si el valor es 0 o menor que 1,1 no
el suavizado se realiza en la métrica (1.8 es el valor predeterminado).

Si la relación> 1,1, la velocidad de las variaciones del tamaño de la malla está limitada por log (relación). Nota:
A medida que la proporción se acerca a 1, aumenta el número de vértices generados. Esto podría ser
útil para controlar el grosor de regiones refinadas cerca de choques o capas límite.

omega = parámetro de relajación para el procedimiento de suavizado (1.0 es el valor predeterminado).

iso = Si es verdadero, fuerza a la métrica a ser isotrópica (falso es el valor predeterminado).

Página 127
5.5. ADAPTACIÓN 127

abserror = Si es falso, la métrica se evalúa utilizando el criterio de reparto equitativo de


error (falso es el valor predeterminado). En este caso, la métrica está definida por

( 1 |H| )p
M= (5,2)
err coef 2 max (Corte, | η |)

de lo contrario, la métrica se evalúa utilizando el criterio de distribución equitativa de errores. En


en este caso, la métrica está definida por

( 1 |H| )p
M= . (5,3)
err coef 2 sup (η) - inf (η)

cutoff = límite inferior para la evaluación del error relativo (1.0e-6 es el valor predeterminado).

verbosidad = nivel de mensajes informativos (se puede elegir entre 0 y ∞). También cambia
el valor de la verbosidad de la variable global (obsoleto).

inquire = Para consultar gráficamente sobre la malla (falso es el valor predeterminado).

splitpbedge = Si es verdadero, divide todos los bordes internos por la mitad con dos vértices de límite (verdadero es
el valor por defecto).

https://translate.googleusercontent.com/translate_f 112/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

maxsubdiv = Cambia la métrica de modo que la subdivisión máxima de un borde de fondo


está limitado por val (siempre limitado por 10, y 10 también es el valor predeterminado).

rescaling = si es verdadero, la función con respecto a la cual se adapta la malla se reescala a


estar entre 0 y 1 (verdadero es el valor predeterminado).

keepbackvertices = si es verdadero, intenta mantener tantos vértices de la malla original como


posible (verdadero es el valor predeterminado).

isMetric = si es verdadero, la métrica se define explícitamente (falso es el valor predeterminado). Si las 3 funciones
m 11 , m 12 , m 22 , definen directamente un campo matricial simétrico cuyo Hessiano
se calcula para definir una métrica. Si solo se da una función, entonces representa el
tamaño de malla isotrópica en cada punto.
Por ejemplo, si las derivadas parciales fxx (= ∂ 2 f / ∂x 2 ), fxy (= ∂ 2 f / ∂x∂y), fyy
(= ∂ 2 f / ∂y 2 ) se dan, podemos establecer

Th = adaptmesh (Th, fxx, fxy, fyy, IsMetric = 1, nbvx = 10000, hmin = hmin);

potencia = potencia exponente del hessiano utilizado para calcular la métrica (1 es el valor predeterminado).

thetamax = ángulo de esquina mínimo de en grados (el valor predeterminado es 10 ◦ ) donde la esquina es ABC
y el ángulo es el ángulo de los dos vectores AB, BC, (0 implica que no hay esquina, 90 implica
perp. esquina , ...).

splitin2 = valor booleano. Si es verdadero, divide todos los triángulos de la malla final en 4 sub-triángulos.

Página 128
128 CAPÍTULO 5. GENERACIÓN DE MALLA

métrica = una matriz de 3 matrices reales para establecer u obtener información de datos métricos. El tamaño de estos
tres matrices deben ser el número de vértices. Entonces, si m11, m12, m22 son tres el-
ementos relacionados con la malla a adaptar, se puede escribir: metric = [m11 [], m12 [], m22 []]
(consulte el archivo convect-apt.edp para ver un ejemplo completo)

nomeshgeneration = Si es verdadero, no se genera una malla adaptada (útil para calcular solo
métrico).

periódico = Escribiendo periódico = [[4, y], [2, y], [1, x], [3, x]]; construye un adaptado
malla periódica. La muestra construye una malla biperiódica de un cuadrado. (ver periódico finito
espacios de elementos 6 , y ver esfera.edp para un ejemplo completo)

Podemos usar el comando adaptmesh para construir una malla uniforme con un tamaño de malla constante.
Entonces, para construir una malla con un tamaño de malla constante igual
30
intentar:
a1

Ejemplo 5.6 uniformmesh.edp

malla Th = cuadrado (2,2); // tener malla inicial


plot (Th, espera = 1, ps = "cuadrado-0.eps");
Th = adaptmesh (Th, 1. / 3Al escribir
0., IsMetric = 1, nbvx = 10000); //
plot (Th, espera = 1, ps = "cuadrado-1.eps");
Th = adaptmesh (Th, 1. / 30., IsMetric = 1, nbvx = 10000); // más la única vez que
Th = adaptmesh (Th, 1. / 30., IsMetric = 1, nbvx = 10000); // límite de adaptación
maxsubdiv =
plot (Th, espera = 1, ps = "cuadrado-2.eps");

https://translate.googleusercontent.com/translate_f 113/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 5.17: Malla inicial Figura 5.18: primera iteración Figura 5.19: última iteración

5.6 Trunc
Se han introducido dos operadores para eliminar triángulos de una malla o dividirlos.
Operator trunc tiene dos parámetros

label = establece el número de etiqueta del nuevo elemento de límite (uno por defecto)

Página 129
5.7. DIVIDIDO 129

split = establece el nivel n de división de triángulos. cada triángulo se divide en n × n (uno por
defecto).

Para crear la malla Th3 donde todos los triángulos de una malla Th se dividen en 3 × 3, simplemente escriba:

malla Th3 = trunc (Th, 1, split = 3);

El ejemplo de truncmesh.edp construye toda la malla "trunc" para el soporte de la base


función del espacio Vh (cf. abs (u)> 0), dividir todos los triángulos en 5 × 5 y poner una etiqueta
número a 2 en el nuevo límite.

malla Th = cuadrado (3,3);


fespace Vh (Th, P1);
Vh u;
int i, n = un;
u = 0;
para (i = 0; i <n; i ++) // todo grado de libertad
{
u [] [i] = 1; // la función básica i
plot (u, espera = 1);
malla Sh1 = trunc (Th, abs (u)> 1.e-10, split = 5, label = 2);
plot (Th, Sh1, espera = 1, ps = "trunc" + i + ". eps"); // trazar la malla de
// el apoyo de la función
u [] [i] = 0; // Reiniciar
}

https://translate.googleusercontent.com/translate_f 114/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 5.20: malla de apoyo a la función Figura 5.21: malla de soporte de la función
P1 número 0, dividido en 5 × 5 P1 número 6, dividido en 5 × 5

5.7 Splitmesh
Otra forma de dividir triángulos de malla es usar splitmesh, por ejemplo:

{ // cosas nuevas 2004 splitmesh (versión 1.37)

Página 130
130 CAPÍTULO 5. GENERACIÓN DE MALLA

afirmar (versión> = 1.37);


borde a (t = 0,2 * pi) {x = cos (t); y = sin (t); etiqueta = 1;}
malla Th = buildmesh (a (20));
plot (Th, espera = 1, ps = "nosplitmesh.eps"); // ver figura 5.22
Th = malla dividida (Th, 1 + 5 * (cuadrado (x-0.5) + y * y));
plot (Th, espera = 1, ps = "splitmesh.eps"); // ver figura 5.23
}

Figura 5.22: malla inicial Figura 5.23: todos los triángulos de malla izquierda
ángulo es separar conforme en
int (1 + 5 * (cuadrado (x-0.5) + y * y) 2
triangulos.

5.8 Ejemplos de mallado


Ejemplo 5.7 (dos rectángulos tocándose por un lado)

borde a (t = 0,1) {x = t; y = 0;};


borde b (t = 0,1) {x = 1; y = t;};
borde c (t = 1,0) {x = t; y = 1;};
borde d (t = 1,0) {x = 0; y = t;};
borde c1 (t = 0,1) {x = t; y = 1;};
borde e (t = 0,0.2) {x = 1; y = 1 + t;};
borde f (t = 1,0) {x = t; y = 1,2;};
borde g (t = 0.2,0) {x = 0; y = 1 + t;};
int n = 1;
malla th = buildmesh (a (10 * n) + b (10 * n) + c (10 * n) + d (10 * n));
malla TH = buildmesh (c1 (10 * n) + e (5 * n) + f (10 * n) + g (5 * n));
plot (th, TH, ps = "TouchSide.esp"); // Figura 5.24

https://translate.googleusercontent.com/translate_f 115/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Ejemplo 5.8 (perfil aerodinámico NACA0012)

borde superior (t = 0,1) {x = t;

Página 131
5.8. EJEMPLOS DE MALLA 131

y = 0.17735 * sqrt (t) -0.075597 * t


- 0,212836 * (tˆ2) + 0,17363 * (tˆ3) -0,06254 * (tˆ4); }
borde inferior (t = 1,0) {x = t;
y = - (0.17735 * sqrt (t) -0.075597 * t
-0,212836 * (tˆ2) + 0,17363 * (tˆ3) -0,06254 * (tˆ4)); }
borde c (t = 0,2 * pi) {x = 0,8 * cos (t) +0,5; y = 0,8 * sin (t); }
malla Th = buildmesh (c (30) + superior (35) + inferior (35));
plot (Th, ps = "NACA0012.eps", bw = 1); // Figura 5.25

(0, 2) D
a th C
B
(0, 0)
h

gramo TH F

(0, -1 0) (1 0, -1 0)
mi

Figura 5.24: Dos rectángulos tocándose por un Figura 5.25: Perfil aerodinámico NACA0012
lado

Ejemplo 5.9 (cardioide)

real b = 1, a = b;
borde C (t = 0,2 * pi) {x = (a + b) * cos (t) -b * cos ((a + b) * t / b);
y = (a + b) * sin (t) -b * sin ((a + b) * t / b); }
malla Th = buildmesh (C (50));
plot (Th, ps = "Cardioid.eps", bw = 1); // Figura 5.26

Ejemplo 5.10 (huevo de Cassini)

borde C (t = 0,2 * pi) {x = (2 * cos (2 * t) +3) * cos (t);


y = (2 * cos (2 * t) +3) * sin (t); }
malla Th = buildmesh (C (50));
gráfico (Th, ps = "Cassini.eps", bw = 1); // Figura 5.27

Ejemplo 5.11 (por curva de Bezier cúbica)

// Una curva de Bézier cúbica que conecta dos puntos con dos puntos de control.
func real bzi ( real p0, real p1, real q1, real q2, real t)
{
devuelve p0 * (1-t) ˆ3 + q1 * 3 * (1-t) ˆ2 * t + q2 * 3 * (1-t) * tˆ2 + p1 * tˆ3;
}

real [int] p00 = [0,1], p01 = [0, -1], q00 = [- 2,0.1], q01 = [- 2, -0.5];

https://translate.googleusercontent.com/translate_f 116/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 132
132 CAPÍTULO 5. GENERACIÓN DE MALLA

Figura 5.26: Dominio con curva cardioide Figura 5.27: Dominio con curva Cassini Egg
Perímetro Perímetro

real [int] p11 = [1, -0,9], q10 = [0,1, -0,95], q11 = [0,5, -1];
real [int] p21 = [2,0,7], q20 = [3, -0,4], q21 = [4,0,5];
real [int] q30 = [0.5,1.1], q31 = [1.5,1.2];
borde G1 (t = 0,1) {x = bzi (p00 [0], p01 [0], q00 [0], q01 [0], t);
y = bzi (p00 [1], p01 [1], q00 [1], q01 [1], t); }
borde G2 (t = 0,1) {x = bzi (p01 [0], p11 [0], q10 [0], q11 [0], t);
y = bzi (p01 [1], p11 [1], q10 [1], q11 [1], t); }
borde G3 (t = 0,1) {x = bzi (p11 [0], p21 [0], q20 [0], q21 [0], t);
y = bzi (p11 [1], p21 [1], q20 [1], q21 [1], t); }
borde G4 (t = 0,1) {x = bzi (p21 [0], p00 [0], q30 [0], q31 [0], t);
y = bzi (p21 [1], p00 [1], q30 [1], q31 [1], t); }
int m = 5;
malla Th = buildmesh (G1 (2 * m) + G2 (m) + G3 (3 * m) + G4 (m));
gráfico (Th, ps = "Bezier.eps", bw = 1); // Figura 5.28

Ejemplo 5.12 (sección del motor)

real a = 6., b = 1., c = 0.5;


borde L1 (t = 0,1) {x = -a; y = 1 + b - 2 * (1 + b) * t; }
borde L2 (t = 0,1) {x = -a + 2 * a * t; y = -1-b * (x / a) * (x / a) * (3-2 * abs (x) / a);}
borde L3 (t = 0,1) {x = a; y = -1-b + (1+ b) * t; }
borde L4 (t = 0,1) {x = a - a * t; y = 0; }
borde L5 (t = 0, pi) {x = -c * sin (t) / 2; y = c / 2-c * cos (t) / 2; }
borde L6 (t = 0,1) {x = a * t; y = c; }
borde L7 (t = 0,1) {x = a; y = c + (1+ bc) * t; }
borde L8 (t = 0,1) {x = a-2 * a * t; y = 1 + b * (x / a) * (x / a) * (3-2 * abs (x) / a); }
malla Th = buildmesh (L1 (8) + L2 (26) + L3 (8) + L4 (20) + L5 (8) + L6 (30) + L7 (8) + L8 (30));
plot (Th, ps = "Engine.eps", bw = 1); // Figura 5.29

Ejemplo 5.13 (dominio con canal en forma de U)

d real = 0,1; // ancho de la forma de U


borde L1 (t = 0,1-d) {x = -1; y = -dt; }
borde L2 (t = 0,1-d) {x = -1; y = 1-t; }

Página 133

https://translate.googleusercontent.com/translate_f 117/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
5.8. EJEMPLOS DE MALLA 133

G4 L7
L5 L6
L1 L4 L3
G3 L2
L1
G1 Figura 5.29: Sección del motor

G2
Figura 5.28: Límite trazado por Bezier
curvas

borde B (t = 0,2) {x = -1 + t; y = -1; }


borde C1 (t = 0,1) {x = t-1; y = d; }
borde C2 (t = 0,2 * d) {x = 0; y = dt; }
borde C3 (t = 0,1) {x = -t; y = -d; }
borde R (t = 0,2) {x = 1; y = -1 + t; }
borde T (t = 0,2) {x = 1-t; y = 1; }
int n = 5;
malla Th = buildmesh (L1 (n / 2) + L2 (n / 2) + B (n) + C1 (n) + C2 (3) + C3 (n) + R (n) + T (n));
plot (Th, ps = "U-shape.eps", bw = 1); // Figura 5.30

Ejemplo 5.14 (dominio con corte en forma de V)

dAg real = 0,01; // ángulo de forma de V


borde C (t = dAg, 2 * pi-dAg) {x = cos (t); y = sin (t); };
real [int] pa (2), pb (2), pc (2);
pa [0] = cos (dAg); pa [1] = sin (dAg);
pb [0] = cos (2 * pi-dAg); pb [1] = sin (2 * pi-dAg);
pc [0] = 0; pc [1] = 0;
borde seg1 (t = 0,1) {x = (1-t) * pb [0] + t * pc [0]; y = (1-t) * pb [1] + t * pc [1]; };
border seg2 (t = 0,1) {x = (1-t) * pc [0] + t * pa [0]; y = (1-t) * pc [1] + t * pa [1]; };
malla Th = buildmesh (seg1 (20) + C (40) + seg2 (20));
plot (Th, ps = "V-shape.eps", bw = 1); // Figura 5.31

Ejemplo 5.15 (cara sonriente)

d real = 0,1;
int m = 5;
real a = 1,5, b = 2, c = 0,7, e = 0,01;
borde F (t = 0,2 * pi) {x = a * cos (t); y = b * sin (t); }
borde E1 (t = 0,2 * pi) {x = 0,2 * cos (t) -0,5; y = 0,2 * sin (t) +0,5; }
borde E2 (t = 0,2 * pi) {x = 0,2 * cos (t) +0,5; y = 0,2 * sin (t) +0,5; }
func real st (real t) {
return sin (pi * t) -pi / 2;
}

Página 134
134 CAPÍTULO 5. GENERACIÓN DE MALLA

T
(-ca, cb)

L1

C1 (propina, d) sеg1
C2 R

https://translate.googleusercontent.com/translate_f 118/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
C3 (consejo, -d) С sеg2
L2

(ca, cb)
B

Figura 5.30: Dominio con canal en forma de U Figura 5.31: Dominio con corte en forma de V
cambiado por d cambiado por dAg

borde C1 (t = -0.5,0.5) {x = (1-d) * c * cos (st (t)); y = (1-d) * c * sin (st (t)); }
borde C2 (t = 0,1) {x = ((1-d) + d * t) * c * cos (st (0.5)); y = ((1-d) + d * t) * c * pecado (st (0,5));}
borde C3 (t = 0.5, -0.5) {x = c * cos (st (t)); y = c * sin (st (t)); }
borde C4 (t = 0,1) {x = (1-d * t) * c * cos (st (-0,5)); y = (1-d * t) * c * sin (st (-0.5));}

borde C0 (t = 0,2 * pi) {x = 0,1 * cos (t); y = 0,1 * sin (t); }


malla Th = buildmesh (F (10 * m) + C1 (2 * m) + C2 (3) + C3 (2 * m) + C4 (3)
+ C0 (m) + E1 (-2 * m) + E2 (-2 * m));
trama (Th, ps = "SmileFace.eps", bw = 1); // ver Fig. 5.32
}

Ejemplo 5.16 (flexión de 3 puntos)

// Cuadrado para probetas dobladas en tres puntos fijadas en Fix1, Fix2


// Se cargará en Load.
real a = 1, b = 5, c = 0,1;
int n = 5, m = b * n;
borde izquierdo (t = 0,2 * a) {x = -b; y = en; }
borde Bot1 (t = 0, b / 2-c) {x = -b + t; y = -a; }
frontera Solución 1 (t = 0,2 * c) {x = -b / 2-c + t; y = -a; }
borde Bot2 (t = 0, b-2 * c) {x = -b / 2 + c + t; y = -a; }
frontera Fix2 (t = 0,2 * c) {x = b / 2-c + t; y = -a; }
borde Bot3 (t = 0, b / 2-c) {x = b / 2 + c + t; y = -a; }
borde derecho (t = 0,2 * a) {x = b; y = -a + t; }
borde Top1 (t = 0, bc) {x = bt; y = a; }
Carga de borde (t = 0,2 * c) {x = ct; y = a; }
borde Top2 (t = 0, bc) {x = -ct; y = a; }
malla Th = buildmesh (Izquierda (n) + Bot1 (m / 4) + Fix1 (5) + Bot2 (m / 2) + Fix2 (5) + Bot3 (m / 4)
+ Derecha (n) + Top1 (m / 2) + Load (10) + Top2 (m / 2));
plot (Th, ps = "ThreePoint.eps", bw = 1); // Figura 5.33

Página 135
5.9. CÓMO CAMBIAR LA ETIQUETA DE ELEMENTOS Y ELEMENTOS FRONTERIZOS DE UNA MALLA 135

T op 2 Carga T op 1
(-b, a)
E1 E2
F Izquierda Derecha

B o t1 B o t2 B o t3 (b, -a)
С4 E1 С2 F ix 1 F ix 2
С1
Figura 5.33: Dominio para flexión de tres puntos
prueba

Figura 5.32: Cara sonriente (la boca cambia


capaz)

https://translate.googleusercontent.com/translate_f 119/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

5.9 Cómo cambiar la etiqueta de elementos y elementos de borde


de una malla
El cambio de etiqueta de elementos y elementos de borde se realizará mediante el cambio de palabra clave.
Los parámetros de esta línea de comando son para un caso bidimensional y dimensional:

label = es un vector de entero que contiene un par sucesivo del antiguo número de etiqueta al
nuevo número de etiqueta.

region = es un vector de entero que contiene un par sucesivo del antiguo número de región para
nuevo número de región.

flabel = es una función entera con dado el nuevo valor de la etiqueta (versión 3.21).

fregion = es una función entera con dado el nuevo valor de la región.

Estos vectores se componen de n l pares sucesivos de números O, N donde n l es el número


(etiqueta o región) que queremos cambiar. Por ejemplo, tenemos

etiqueta = [O 1 , N 1 , ..., O n , N n ]
l l (5,4)
región = [O 1 , N 1 , ..., O n , N n ]
l l (5,5)

Un ejemplo del uso de esta función se da en "glumesh2D.edp":

Ejemplo 5.17 (glumesh2D.edp)

1:
2: malla Th1 = cuadrado (10,10);
3: malla Th2 = cuadrado (20,10, [x + 1, y]);
4: verbosidad = 3;
5: int [int] r1 = [2,0], r2 = [4,0];
6: trazar (Th1, esperar = 1);
7: Th1 = cambio (Th1, etiqueta = r1); // Cambie la etiqueta de Edges 2 en 0.
8: trama (Th1, espera = 1);
9: Th2 = cambio (Th2, etiqueta = r2); // Cambie la etiqueta de los bordes 4 en 0.

Página 136
136 CAPÍTULO 5. GENERACIÓN DE MALLA

10: malla Th = Th1 + Th2; // '' pegado '' de mallas Th1 y Th2
11: cout << "nb lab =" << int1d (Th1,1,3,4) (1./lenEdge) + int1d (Th2,1,2,3) (1./lenEdge)
12: << "==" << int1d (Th, 1,2,3,4) (1./lenEdge) << "==" << ((10 + 20) +10) * 2
<< endl;
13: trama (Th, espera = 1);
14: espacio libre Vh (Th, P1);
15: macro Grad (u) [dx (u), dy (u)]; // definición de una macro
16: Vh u, v;
17: resolver P (u, v) = int2d (Th) (Grad (u) '* Grad (v)) - int2d (Th) (v) + en (1,3, u = 0);
18: grafica (u, espera = 1);

“Pegar” malla diferente En la línea 10 del archivo anterior, el método para “pegar” malla diferente
de la misma dimensión en FreeFem ++ está utilizando. Esta función es el operador "+" entre
mallas. El método implementado necesita que el punto en la malla adyacente sea el mismo.

5.10 Malla en tres dimensiones

https://translate.googleusercontent.com/translate_f 120/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
5.10.1 cubo
De la versión (3.38-2), un nuevo cubo de función como el cuadrado de función en 2d es el simple
forma de construir un objeto cúbico, en el complemento msh3 (necesita cargar "msh3").
El siguiente código

mesh3 Th = cubo (3, 4, 5);

genera una cuadrícula de 3 × 4 × 5 en el cubo unitario [0,1] 3 .


Por defecto, la etiqueta (después de la versión 3.56-2 y para corregir de lo contrario agregue label = l6
int [int] l6 = [1,2,3,4,5,6];) son:
1. cara y = 0;
2. cara x = 1,
3. cara y = 1,
4. cara x = 0,
5. cara z = 0,
6. cara z = 1,
y el número de región es 0.
Ejemplos completos de la función this para construir una malla de cubo] - 1,1 [ 3 con la etiqueta de la cara dada
por (ix + 4 ∗ (iy + 1) + 16 ∗ (iz + 1)) donde (ix, iy, iz) es la coordenada del baricentro del
rostro actual.

cargar "msh3"
int [ int ] l6 = [37,42,45,40,25,57];
int r11 = 11;
mesh3 Th = cubo (4,5,6, [x * 2-1, y * 2-1, z * 2-1], etiqueta = l6, banderas = 3, región = r11);
cout << "volumen" << Th.measure << ", área del borde" << Th.bordermeasure << endl;
//

// Verifique la numeración de la región de la etiqueta

Página 137
5.10. MALLA EN TRES DIMENSIONES 137

int err = 0;
para (int i = 0; i <100; ++ i)
{
real s = int2d (Th, i) (1.);
real sx = int2d (Th, i) (x);
sy real = int2d (Th, i) (y);
real sz = int2d (Th, i) (z);

si (s)
{
int ix = (sx / s + 1.5), iy = (sy / s + 1.5), iz = (sz / s + 1.5),
ii = (ix + 4 * (iy + 1) + 16 * (iz + 1));
// valor de ix, iy, iz => cara mínima 0, cara máxima 2, sin cara 1
cout << "etiqueta =" << i << "s" << s << "" << ix << iy << iz
<< ":" << ii << endl;
si (i! = ii) err ++;
}
}
real volr11 = int3d (Th, r11) (1.);
cout << "vol región" << 11 << ":" << volr11 << endl;
if ((volr11 - Medida)> 1e-8) err ++;
plot (Th, relleno = 0);
cout << "nb err =" << err << endl;
afirmar (err == 0);

la salida de este script es:

Ingrese: BuildCube: 3

https://translate.googleusercontent.com/translate_f 121/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
tipo = 3 n tet Cubo = 6 / n deslizamiento 6 19
Cubo nv = 210 nt = 720 nbe = 296
Fuera: BuildCube
volumen 8, zona fronteriza 24
etiqueta = 25 s 4 110: 25
etiqueta = 37 s 4 101: 37
etiqueta = 40 s 4011: 40
etiqueta = 42 s 4211: 42
etiqueta = 45 s 4 121: 45
etiqueta = 57 s 4 112: 57
vol región 11: 8
nb err = 0
veces: compilar 0.005363s, ejecución 0.00218s, mpirank: 0
CodeAlloc: nb ptr 2856, tamaño: 352744 mpirank: 0

5.10.2 Lectura / escritura de declaraciones para una malla en 3D


En tres dimensiones, el formato de malla de archivos admitido para archivos de entrada y salida por FreeFem ++
son las extensiones .msh y .mesh. Estos formatos se describen en el capítulo sobre archivos de malla.
en dos dimensiones.

Página 138
138 CAPÍTULO 5. GENERACIÓN DE MALLA

Figura 5.34: La malla 3d del cubo de función (4,5,6, banderas = 3)

archivo de extensión .msh La estructura de los archivos con extensión .msh en 3D se da en la Tabla
5.2 . En esta estructura, n v denota el número de vértices, n tet el número de tetraedros y
n tri el número de triángulos Para cada vértice q i , i = 1, ···, n v , denotamos por (q i
x , q yyo, q yo
z ) el
la coordenada x, la coordenada y y la coordenada z. Cada tetraedro T k , k = 1, ···, n tet tiene
cuatro vértices q k , q k , q k , q k . El límite consiste en una unión de triángulos. Cada triangulo
1 2 3 4

be j , j = 1, ···, n tri tiene tres vértices q j , q j , q j .


1 2 3

nv n tet n tri
q X1 q y1 q z1 Etiqueta de vértice
q X2 q y2 q z2 Etiqueta de vértice
... ... ... ...

q Xnv q yn v q zn v Etiqueta de vértice


11 12 13 14 etiqueta de región
21 22 23 24 etiqueta de región
... ... ... ... ...

(n tet ) 1 (n tet ) 2 (n tet ) 3 (n tet ) 4 etiqueta de región


11 12 13 etiqueta de límite

https://translate.googleusercontent.com/translate_f 122/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
21 22 23 etiqueta de límite
... ... ... ...

(n t ri) 1 (n tri ) 2 (n tri ) 3 etiqueta de límite

Tabla 5.2: La estructura del formato de archivo de malla “.msh” en tres dimensiones.

archivo de extensión .mesh La estructura de datos para una malla tridimensional se compone de la
estructura de datos presentada en la Sección 12.1 y una estructura de datos para tetraedros. El tetraedro
de una malla tridimensional se evalúan utilizando el siguiente campo:

• Tetraedros
(I) NbOfTetrahedrons
(( @@ Vértice j
I , i = 1, NbOfTetrahedrons )
i , j = 1,4 ) , (I) Refφ tet

Página 139
5.10. MALLA EN TRES DIMENSIONES 139

Este campo se expresa con la notación de la Sección 12.1.

5.10.3 TeGen: un generador de malla tetraédrica


TetGen TetGen es un software desarrollado por el Dr. Hang Si del Weierstrass Institute for Applied Anal-
ysis y estocástica de Berlín en Alemania [ 41 ]. TetGen es un programa gratuito para investigación y no comercial.
usos. Para cualquier uso de licencia comercial, una licencia comercial está disponible a pedido de Hang
Si.
Este software es un generador de malla tetraédrica de un dominio tridimensional definido por su límite.
El dominio de entrada tiene en cuenta un poliédrico o un complejo lineal por partes. Este tetraédrico-
ización es una tetrahedrización de Delaunay constreñida.
El método utilizado en TetGen para controlar la calidad de la malla es un refinamiento de Delaunay debido a
Shewchuk [42 ] . La medida de calidad de este algoritmo es la relación radio-borde (consulte la Sección 1.3.1
[41 ] para más detalles). Se obtiene un límite teórico de esta relación del algoritmo de Shewchuk
para un complejo dado de vértices, segmentos restringidos y facetas de la malla de superficie, sin entrada
Ángulo de menos de 90 grados. Este límite teórico es 2.0.

El lanzamiento de Tetgen se realiza con la palabra clave tetg. Los parámetros de esta línea de comando son:

label = es un vector de entero que contiene el antiguo número de etiquetas en el índice 2i y las nuevas etiquetas
número en el índice 2i + 1 de Triángulos. Este parámetro se inicializa como etiqueta para la palabra clave
cambiar ( 5.4) .

switch = Una expresión de cadena. Esta cadena corresponde al cambio de línea de comando de Tetgen ver
Sección 3.2 de [ 41] .

nbofholes = Número de agujeros (valor predeterminado tamaño de la lista de agujeros / 3 (versión 3.11)).

holelist = Esta matriz corresponde a la lista de agujeros de la estructura de datos tetgenio [ 41 ]. Un verdadero vector de
tamaño 3 × nbofholes. En TetGen, cada agujero está asociado con un punto dentro de este dominio.
Este vector es x h
1 , y h1 , z h1 , x h2 , y h
2 , z h2 , ···, donde x h yo , yyo
h , zi hes el punto asociado con el i- ésimo
agujero.

nbofregions = Número de regiones (tamaño de la lista de regiones / 5 (versión 3.11)).

regionlist = Esta matriz corresponde a la lista de regiones de la estructura de datos tetgenio [41 ]. El atributo
y la restricción de volumen de la región se dan en este vector real de tamaño 5 × nb de regiones.
La i- ésima región está descrita por cinco elementos: coordenada x, coordenada y y coordenada z de
un punto dentro de este dominio (x i , y i , z i ); el atributo (en i ) y el volumen máximo para tetrahe-
dra (mvol i ) para esta región. El vector lista de regiones es: x 1 , y 1 , z 1 , en 1 , mvol 1 , x 2 , y 2 , z 2 , en 2 , mvol 2 , ···.

nboffacetcl = Número de restricciones de facetas tamaño de facetcl / 2 (versión 3.11)).

facetcl = Esta matriz corresponde a facetconstraintlist de la estructura de datos tetgenio [41 ]. El i th

https://translate.googleusercontent.com/translate_f 123/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
La restricción de faceta se define mediante el marcador de faceta Ref Ifc y el área máxima para caras
fc fc fc fc fc
marea I . La matriz facetcl es: Ref
1 , marea 1, Ref 2, marea 2, ···. Estos parámetros
no tiene ningún efecto si no se selecciona el interruptor q.

Parámetros del interruptor principal en TetGen:

p Tetraédrica del límite.

Página 140
140 CAPÍTULO 5. GENERACIÓN DE MALLA

q Generación de mallas de calidad. El límite de la relación radio-borde se dará después de la opción q.


De forma predeterminada, este valor es 2,0.

a Construya con las restricciones de volumen en tetraedros. Estas restricciones de volumen están definidas
con el límite del modificador q anterior o en el parámetro regionlist.

Una referencia de atributos a la región proporcionada en la lista de regiones. Las otras regiones tienen etiqueta 0.
La opción AA da una etiqueta diferente en cada región. Este interruptor funciona con la opción 'p'.
Si se usa la opción 'r', este interruptor no tiene ningún efecto.

r Reconstruye y refina una malla generada previamente. Este carácter solo se usa con el
construcción de tetgre de línea de comando.

Y Este interruptor permite conservar la malla en el límite exterior. Este interruptor debe usarse
para asegurar una malla conforme entre dos mallas adyacentes.

YY Este interruptor permite preservar la malla en el límite exterior e interior.

C TetGen está probando la consistencia de la malla del resultado.

CC La consistencia de la malla del resultado está probada por TetGen y también verifica el delaunay restringido
malla (si se selecciona el interruptor 'p') o la consistencia de Conformal Delaunay (si el interruptor 'q' está
seleccionado).

V Dar información del trabajo de TetGen. Se puede obtener más información en el 'VV' especificado
o 'VVV'.

Q Silencioso: sin salida de terminal excepto errores

M Las facetas coplanares no se fusionan.

T Establezca una tolerancia para la prueba coplanar. El valor predeterminado es 1e - 8.

d Se detectan intersecciones de facetas.

Para obtener un generador de malla tetraédrica con tetgen, necesitamos la malla de superficie de tres dimensiones
dominio. Damos ahora la línea de comando en FreeFem ++ para construir estas mallas.

palabra clave: "movemesh23" Un método sencillo para construir una superficie es colocar una
dominio en un espacio tridimensional. Esto corresponde a mover el dominio por un desplazamiento
vector de esta forma Φ (x, y) = (Φ1 (x, y), Φ2 (x, y), Φ3 (x, y)). El resultado de mover un bidimensional
La malla Th2 por este desplazamiento tridimensional se obtiene usando:

mesh3 Th3 = movemesh23 (Th2, transfo = [Φ1, Φ2, Φ3]);

Los parámetros de esta línea de comando son:

transfo = [Φ1, Φ2, Φ3] establece el vector de desplazamiento de transformación Φ (x, y) = [Φ1 (x, y), Φ2 (x, y), Φ3 (x, y)].

etiqueta = establecer etiqueta entera de triángulos

Orientación = establece la orientación entera de la malla.

https://translate.googleusercontent.com/translate_f 124/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 141
5.10. MALLA EN TRES DIMENSIONES 141

ptmerge = Una expresión real. Cuando transforma una malla, algunos puntos se pueden fusionar. Esto
Los parámetros son los criterios para definir dos puntos de fusión. Por defecto, usamos

ptmerge = 1e - 7 V ol (B),

donde B son las cajas paralelas del eje más pequeño que contienen el dominio discretizado de Ω y V ol (B)
es el volumen de esta caja.

Podemos hacer un "encolado" de mallas de superficie usando el proceso dado en la Sección 5. 9. Un ejemplo para
obtener una malla tridimensional usando la línea de comando tetg y movemesh23 se da en el
archivo tetgencube.edp.

Ejemplo 5.18 (tetgencube.edp)

// archivo tetgencube.edp
cargar "msh3"
cargar "tetgen"

real x0, x1, y0, y1;


x0 = 1 .; x1 = 2 .; y0 = 0 .; y1 = 2 * pi;
malla Thsq1 = cuadrado (5,35, [x0 + (x1-x0) * x, y0 + (y1-y0) * y]);

func ZZ1min = 0;
func ZZ1max = 1,5;
func XX1 = x;
func YY1 = y;

mesh3 Th31h = movemesh23 (Thsq1, transfo = [XX1, YY1, ZZ1max]);


mesh3 Th31b = movemesh23 (Thsq1, transfo = [XX1, YY1, ZZ1min]);

// /////////////////////////////////
x0 = 1 .; x1 = 2 .; y0 = 0 .; y1 = 1,5;
malla Thsq2 = cuadrado (5,8, [x0 + (x1-x0) * x, y0 + (y1-y0) * y]);

func ZZ2 = y;
func XX2 = x;
func YY2min = 0 .;
func YY2max = 2 * pi;

mesh3 Th32h = movemesh23 (Thsq2, transfo = [XX2, YY2max, ZZ2]);


mesh3 Th32b = movemesh23 (Thsq2, transfo = [XX2, YY2min, ZZ2]);

// /////////////////////////////////
x0 = 0 .; x1 = 2 * pi; y0 = 0 .; y1 = 1,5;
malla Thsq3 = cuadrado (35,8, [x0 + (x1-x0) * x, y0 + (y1-y0) * y]);
func XX3min = 1 .;
func XX3max = 2 .;
func YY3 = x;
func ZZ3 = y;

mesh3 Th33h = movemesh23 (Thsq3, transfo = [XX3max, YY3, ZZ3]);


mesh3 Th33b = movemesh23 (Thsq3, transfo = [XX3min, YY3, ZZ3]);

// ////////////////////////////////
mesh3 Th33 = Th31h + Th31b + Th32h + Th32b + Th33h + Th33b; // "encolado" de mallas de superficie
para obtener la superficie del cubo

https://translate.googleusercontent.com/translate_f 125/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 142
142 CAPÍTULO 5. GENERACIÓN DE MALLA

savemesh (Th33, "Th33.mesh");

// construir una malla de una caja paralela de ejes con TetGen


dominio real [int] = [1.5, pi, 0.75,145,0.0025];
mesh3 Thfinal = tetg (Th33, switch = "paAAQY", regionlist = dominio); //
Tetrahelizar el interior del cubo con tetgen
savemesh (Thfinal, "Thfinal.mesh");

// Construir una malla de medio cuerpo cilíndrico de radio interior 1. y


radio exterior 2 y altura 1,5
func mv2x = x * cos (y);
func mv2y = x * sin (y);
func mv2z = z;
mesh3 Thmv2 = movemesh3 (Thfinal, transfo = [mv2x, mv2y, mv2z]);
savemesh (Thmv2, "halfcylindricalshell.mesh")

El comando movemesh se describe en la siguiente sección.

La palabra clave "tetgtransfo" Esta palabra clave corresponde a una composición de la línea de comando tetg
y movemesh23:

tetgtransfo (Th2, transfo = [Φ1, Φ2, Φ3]), ···) = tetg (Th3surf, ···),

donde Th3surf = movemesh23 (Th2, tranfo = [Φ1, Φ2, Φ3]) y Th2 es la entrada bidimensional
malla de tetgtransfo.
Los parámetros de esta línea de comando son por un lado los parámetros:
etiqueta, cambiar, lista de regiones nboffacetcl facetcl
de la palabra clave tetg y, por otro lado, el parámetro ptmerge de la palabra clave movemesh23.

Observación: para usar tetgtransfo, la malla del resultado de movemesh23 debe ser una superficie cerrada
y definir una sola región. Por lo tanto, el parámetro regionlist se define para una región.
Puede encontrar un ejemplo de esta palabra clave en la línea del archivo "buildlayers.edp"

La palabra clave "tetgconvexhull" FreeFem ++, usando tetgen, es capaz de construir una tetraédrica
a partir de un conjunto de puntos. Esta tetraédrica es una malla de Delaunay del casco convexo del conjunto de
puntos.
Las coordenadas de los puntos se pueden inicializar de dos formas. El primero es un archivo que contiene el
coordenada de los puntos X i = (x i , y i , z i ). Estos archivos están organizados de la siguiente manera:

nv
x1 año 1 z 1
x2 y2 z2
... ... ...

x nv s nv z nv

La segunda forma es dar tres matrices que correspondan respectivamente a las coordenadas x, coordenadas y
y coordenadas z.

Los parámetros de esta línea de comando son

switch = Una expresión de cadena. Esta cadena corresponde al cambio de línea de comando de TetGen
consulte la Sección 3.2 de [ 41] .

Página 143
5.10. MALLA EN TRES DIMENSIONES 143

reftet = Una expresión entera. establecer la etiqueta de los tetraedros.

label = Una expresión entera. establecer la etiqueta de los triángulos.

https://translate.googleusercontent.com/translate_f 126/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
En el cambio de cadena, no podemos usar la opción 'p' y 'q' de tetgen.

5.10.4 Reconstruir / refinar una malla tridimensional con TetGen


Las mallas en tres dimensiones se pueden refinar usando TetGen con la línea de comando tetgreconstruction.
Los parámetros de esta palabra clave son

region = una matriz de enteros que permite cambiar el número de región de tetraedros. Esta matriz es
definido como el parámetro reftet en el cambio de palabra clave.

label = una matriz de números enteros que permite cambiar la etiqueta de los triángulos delimitadores. Esta matriz está definida
como la etiqueta del parámetro en el cambio de palabra clave.

sizevolume = una función de carrete. Esta función permite restringir el tamaño del volumen de los tetraedros en el
dominio. (vea el ejemplo 5.31 para construir una malla de adaptación 3d)

El parámetro cambia nbofregions, regionlist, nboffacetcl y facetcl de la


La línea de mando que llama a TetGen (tetg) se usa para tetgrefine.
En el parámetro switch =, el carácter 'r' debe usarse sin el carácter 'p'. Por ejemplo,
consulte el manual de TetGen [41 ] para conocer el efecto de la 'r' a otro carácter.
El parámetro regionlist permite definir una nueva restricción de volumen en la región. La etiqueta en
la lista de regiones será la etiqueta anterior de la región. Este parámetro y nbofregions no pueden
ser utilizado con el parámetro sizevolume.
Ejemplo:

Ejemplo 5.19 (refinesphere.edp) // archivo refinesphere.edp

cargar "msh3"
cargar "tetgen"
cargar "medit"

−pi
malla Th = cuadrado (10,20, [x * pi-pi / 2,2 * y * pi]); // ] 2
, frac − pi2 [×] 0, 2π [
// una parametrización de una esfera
func f1 = cos (x) * cos (y);
func f2 = cos (x) * sin (y);
func f3 = sin (x);
// partiel derivada de la parametrización DF
func f1x = sin (x) * cos (y);
func f1y = -cos (x) * sin (y);
func f2x = -sin (x) * sin (y);
func f2y = cos (x) * cos (y);
func f3x = cos (x);
func f3y = 0;
// M = DF t DF
func m11 = f1xˆ2 + f2xˆ2 + f3xˆ2;
func m21 = f1x * f1y + f2x * f2y + f3x * f3y;
func m22 = f1yˆ2 + f2yˆ2 + f3yˆ2;

func perio = [[4, y], [2, y], [1, x], [3, x]];
hh real = 0,1;

Página 144
144 CAPÍTULO 5. GENERACIÓN DE MALLA

real vv = 1 / cuadrado (hh);


verbosidad = 2;
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
plot (Th, espera = 1);

verbosidad = 2;

// construcción de la superficie de esferas


real Rmin = 1 .;
func f1min = Rmin * f1;
func f2min = Rmin * f2;

https://translate.googleusercontent.com/translate_f 127/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
func f3min = Rmin * f3;

mesh3 Th3 = movemesh23 (Th, transfo = [f1min, f2min, f3min]);

dominio real [int] = [0., 0., 0., 145,0.01];


mesh3 Th3sph = tetg (Th3, switch = "paAAQYY", nbofregions = 1, regionlist = dominio);

int [int] newlabel = [145,18];


real [int] domainrefine = [0., 0., 0., 145,0.0001];
mesh3 Th3sphrefine = tetgreconstruction (Th3sph, switch = "raAQ", reftet = newlabel,
nbofregions = 1, regionlist = domain, refinesizeofvolume = 0.0001);

int [int] newlabel2 = [145,53];


func fsize = 0.01 / ((1 + 5 * sqrt ((x-0.5) ˆ2 + (y-0.5) ˆ2 + (z-0.5) ˆ2)) ˆ3);
mesh3 Th3sphrefine2 = tetgreconstruction (Th3sph, switch = "raAQ", reftet = newlabel2,
sizeofvolume = fsize);

medit ("esfera", Th3sph);


medit ('' isotroperefine '', Th3sphrefine);
medit ("anisotroperefine", Th3sphrefine2);

5.10.5 Malla móvil en tres dimensiones


Las mallas en tres dimensiones se pueden traducir, rotar y deformar usando la línea de comando
movemesh como en el caso 2D (ver sección movemesh en el capítulo 5). Si Ω está tetraedrizado como T h (Ω),
y Φ (x, y) = (Φ1 (x, y, z), Φ1 (x, y, z), Φ3 (x, y, z)) es un vector de desplazamiento, entonces se obtiene Φ (T h )
por

mesh3 Th = movemesh (Th, [Φ1, Φ2, Φ3], ...);

Los parámetros de movemesh en tres dimensiones son

region = establece la etiqueta entera de los tetraedros. 0 por defecto.

label = establece la etiqueta de las caras del borde. Este parámetro se inicializa como etiqueta para la palabra clave
cambiar ( 5.4) .

facemerge = Una expresión entera. Cuando transforma una malla, algunas caras se pueden fusionar.
Este parámetro es igual a uno si se consideran las caras de la combinación. De lo contrario es igual a cero. Por
predeterminado, este parámetro es igual a 1.

Página 145
5.10. MALLA EN TRES DIMENSIONES 145

superficie superior

Superficie media

Superficie inferior

Figura 5.35: Ejemplo de malla de capas en tres dimensiones.

ptmerge = Una expresión real. Cuando transforma una malla, algunos puntos se pueden fusionar. Esto
Los parámetros son los criterios para definir dos puntos de fusión. Por defecto, usamos

ptmerge = 1e - 7 V ol (B),

donde B son las cajas paralelas del eje más pequeño que contienen el dominio de discreción de Ω y V ol (B)
https://translate.googleusercontent.com/translate_f 128/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
es el volumen de esta caja.

Orientación = Una expresión entera (1 por defecto), para invertir o no la orientación de tet
si no es positivo.

Un ejemplo de este comando se puede encontrar en el archivo "Poisson3d.edp" ubicado en el directorio


ejemplos ++ - 3d.

5.10.6 Malla de capas


En esta sección, presentamos la línea de comando para obtener una capa de malla: buildlayermesh. Esto
La malla se obtiene extendiendo una malla bidimensional en el eje z.
El dominio Ω 3d definido por la malla de capa es igual a Ω 3d = Ω 2d × [zmin, zmax] donde Ω 2d es el
dominio definido por la malla bidimensional, zmin y zmax son función de Ω 2d en R que define
respectivamente, la superficie inferior y la superficie superior de Ω 3d .
Para un vértice de una malla bidimensional V 2d I = (x i , y i ), introducimos el número de asociados
vértices en el eje z M i + 1. Denotamos por M el máximo de M i sobre los vértices de los dos
malla dimensional. Este valor se llama número de capas (si ∀i, M i = M, entonces hay M
capas en la malla de Ω 3d ). V 2d I vértices generados M + 1 que están definidos por

∀j = 0, ..., M, Vyo,
3d
j = (x yo , y yo , θ yo (z yo, j )),

donde (z i, j ) j = 0, ..., M son los puntos equidistantes M + 1 en el intervalo [zmin (V 2d


i ), zmáx (V 2d i )]:

zmáx (V 2d
z yo, j = j δα + zmin (V 2d δα = i) - zmin (V 2d yo ) .
i ), METRO

La función θ i , definida en [zmin (V 2d i ), zmáx (V 2d i )], viene dada por


{θ yo, 0 si z = zmin (V 2d
θ yo (z) = i ),
θ yo, j si z ∈] θ i, j − 1 , θ i, j ],

con (θ i, j ) j = 0, ..., M i son los puntos equidistantes M i + 1 en el intervalo [zmin (V 2d


i ), zmáx (V 2d i )].

Página 146
146 CAPÍTULO 5. GENERACIÓN DE MALLA

Establecer un triángulo K = (V 2d
i1 , V 2di2 , V 2di3 ) de la malla bidimensional. K está asociado con un triángulo
gle en la superficie superior (resp. en la superficie inferior) de la capa de malla: (V 3d
i1, M , V 3d
i2, M , V 3di3, M ) (resp.
(V 3d
i1,0 , V 3d
i2,0 , V 3d
i3,0 )).
También K está asociado con M elementos prismáticos de volumen que están definidos por

∀j = 0, ..., M, H j = (V 3d
i1, j , V 3di2, j , V 3di3, j , V 3d
i1, j + 1 , V 3d
i2, j + 1 , V 3d
i3, j + 1 ).

Estos elementos de volumen pueden tener algún punto combinado:


• 0 punto combinado: prisma

• 1 puntos fusionados: pirámide

• 2 puntos fusionados: tetraedros

• 3 puntos fusionados: sin elementos

Los elementos con puntos fusionados se denominan elementos degenerados. Para obtener una malla con tetrahe-
dra, descomponemos la pirámide en dos tetraedros y el prisma en tres tetraedros. Estas
Los tetraedros se obtienen cortando la cara cuadrilátera de la pirámide y el prisma con la diagonal
que tienen el vértice con el índice máximo (ver [12 ] para la reasignación de esta elección).

Los triángulos en la superficie media obtenidos con la descomposición del volumen prismático el-
Los elementos son los triángulos generados por los bordes en el borde de la malla bidimensional. La
La etiqueta de triángulos en los elementos del borde y los tetraedros se definen con la etiqueta de estas asociaciones.
elementos ados.

Los argumentos de buildlayermesh son una malla bidimensional y el número de capas M.


Los parámetros de este comando son:

https://translate.googleusercontent.com/translate_f 129/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

zbound = [zmin, zmax] donde zmin y zmax son expresiones de funciones. Estas funciones definen
la malla de la superficie inferior y la malla superior de la malla de la superficie.

coef = Una expresión de función entre [0,1]. Este parámetro se utiliza para introducir degenerados
elemento en malla. El número de puntos asociados o vértice V 2d I es la parte entera de
coef (V 2d
i ) M.

region = Este vector se utiliza para inicializar la región de tetraedros. Este vector contiene sucesivos
par del número de región 2d en el índice 2i y el número de región 3d correspondiente en el índice
2i + 1, como (5. 4). conviértete en el

labelmid = Este vector se usa para inicializar el número de etiquetas 3d de la cara vertical o media
cara forman el número de etiqueta 2d. Este vector contiene un par sucesivo del número de etiqueta 2d
en el índice 2i y el número de etiqueta 3d correspondiente en el índice 2i + 1, como ( 5.4) .

labelup = Este vector se usa para inicializar los números de etiqueta 3d de la cara superior / superior de la
Número de región 2d. Este vector contiene un par sucesivo del número de región 2d en el índice 2i
y el correspondiente número de etiqueta 3d en el índice 2i + 1, como ( 5.4) .

labeldown = Igual que el caso anterior pero para la etiqueta de la cara inferior / inferior.

Además, también agregamos parámetros de posprocesamiento que permiten mover la malla. Estos parámetros
corresponden a los parámetros transfo, facemerge y ptmerge de la línea de comando movemesh.
La región del vector, labelmid, labelup y labeldown Estos vectores se componen de n l
pares sucesivos de números O i , N l donde n l es el número (etiqueta o región) que queremos obtener.
Un ejemplo de esta línea de comando se da en buildlayermesh.edp.

Página 147
5.10. MALLA EN TRES DIMENSIONES 147

Ejemplo 5.20 (cube.idp)

cargar "medit"
cargar "msh3"
func mesh3 Cube (int [int] & NN, real [int, int] & BB, int [int, int] & L)
{
// Primero construye las 6 caras del hexágono.
real x0 = BB (0,0), x1 = BB (0,1);
y0 real = BB (1,0), y1 = BB (1,1);
real z0 = BB (2,0), z1 = BB (2,1);

int nx = NN [0], ny = NN [1], nz = NN [2];


Thx de malla = cuadrado (nx, ny, [x0 + (x1-x0) * x, y0 + (y1-y0) * y]);

int [ int ] rup = [0, L (2,1)], rdown = [0, L (2,0)],


rmid = [1, L (1,0), 2, L (0,1), 3, L (1,1), 4, L (0,0)];
mesh3 Th = buildlayers (Thx, nz, zbound = [z0, z1],
labelmid = rmid, labelup = rup,
labeldown = rdown);

volver Th;
}

El ejemplo del cubo unitario:

incluir "Cube.idp"
int [int] NN = [10,10,10]; // el número de pasos en cada dirección
real [int, int] BB = [[0,1], [0,1], [0,1]]; // cuadro delimitador
int [int, int] L = [[1,2], [3,4], [5,6]]; // la etiqueta de la cara 6
izquierda derecha,
// frente, atrás, abajo, derecha
mesh3 Th = Cubo (NN, BB, L);
medit ("Th", Th); // ver figura 5.36

El ejemplo del cono (una malla axisimétrica en un triángulo con degeneración).

Ejemplo 5.21 (cone.edp)

https://translate.googleusercontent.com/translate_f 130/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

cargar "msh3"
cargar "medit"
// cono usando capas de construcción con un triángulo
RR real = 1, HH = 1;
impuesto fronterizo (t = 0, HH) {x = t; y = 0; etiqueta = 0;};
border Hypo (t = 1,0) {x = HH * t; y = RR * t; label = 1;};
borde Vert (t = 0, RR) {x = HH; y = t; etiqueta = 2;};
int nn = 10; h real = 1./nn;
malla Th2 = buildmesh (Taxe (HH * nn) + Hypo (sqrt (HH * HH + RR * RR) * nn) + Vert (RR * nn));
plot (Th2, espera = 1); // la malla 2d

int MaxLayersT = (int (2 * pi * RR / h) / 4) * 4; // número de capas


zminT real = 0, zmaxT = 2 * pi; // altura 2 ∗ pi
func fx = y * cos (z); func fy = y * sin (z); func fz = x;
int [i nt ] r1T = [0,0], r2T = [0,0,2,2], r4T = [0,2];
// función de truco:
func deg = max (.01, y / max (x / HH, 0.4) / RR); // la función definió el
proporción

Página 148
148 CAPÍTULO 5. GENERACIÓN DE MALLA

// de capa numérica cerca del eje con referencia MaxLayersT


mesh3 Th3T = buildlayers (Th2, coef = deg, MaxLayersT,
zbound = [zminT, zmaxT], transfo = [fx, fy, fz],
facemerge = 0, region = r1T, labelmid = r2T);
medit ("cono", Th3T); // ver figura 5.37

Figura 5.36: la malla de un cubo hecho con Figura 5.37: la malla de un cono hecho con
cube.edp cone.edp

Ejemplo 5.22 (buildlayermesh.edp)

// archivo buildlayermesh.edp

cargar "msh3"
cargar "tetgen"

// Prueba 1

https://translate.googleusercontent.com/translate_f 131/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
int C1 = 99, C2 = 98; // podría ser cualquier cosa
borde C01 (t = 0, pi) {x = t; y = 0; etiqueta = 1;}
frontera C02 (t = 0,2 * pi) {x = pi; y = t; etiqueta = 1;}
borde C03 (t = 0, pi) {x = pi-t; y = 2 * pi; etiqueta = 1;}
borde C04 (t = 0,2 * pi) {x = 0; y = 2 * pi-t; etiqueta = 1;}

borde C11 (t = 0,0.7) {x = 0.5 + t; y = 2,5; etiqueta = C1;}


borde C12 (t = 0,2) {x = 1,2; y = 2,5 + t; etiqueta = C1;}
borde C13 (t = 0,0.7) {x = 1.2-t; y = 4,5; etiqueta = C1;}
borde C14 (t = 0,2) {x = 0,5; y = 4,5-t; etiqueta = C1;}

Página 149
5.11. EJEMPLOS DE MALLA 149

borde C21 (t = 0,0.7) {x = 2.3 + t; y = 2,5; etiqueta = C2;}


borde C22 (t = 0,2) { x = 3; y = 2,5 + t; etiqueta = C2;}
borde C23 (t = 0,0.7) { x = 3-t; y = 4,5; etiqueta = C2;}
borde C24 (t = 0,2) { x = 2,3; y = 4,5-t; etiqueta = C2;}

malla Th = buildmesh ( C01 (10) + C02 (10) + C03 (10) + C04 (10)
+ C11 (5) + C12 (5) + C13 (5) + C14 (5)
+ C21 (-5) + C22 (-5) + C23 (-5) + C24 (-5));

malla Ths = buildmesh ( C01 (10) + C02 (10) + C03 (10) + C04 (10)
+ C11 (5) + C12 (5) + C13 (5) + C14 (5));

// construcción de una caja con un agujero y dos regiones


func zmin = 0 .;
func zmax = 1 .;
int MaxLayer = 10;

func XX = x * cos (y);


func YY = x * sin (y);
func ZZ = z;

int [int] r1 = [0,41], r2 = [98,98, 99,99, 1,56];


int [int] r3 = [4,12]; // Los triángulos de la malla de la superficie superior
// generado por el triángulo en la región 2D de la malla Th de la etiqueta 4 como
etiqueta 12.
int [int] r4 = [4,45]; // Los triángulos de la malla de la superficie inferior
// generado por el triángulo en la región 2D de la malla Th de la etiqueta 4 como
etiqueta 45.

mesh3 Th3 = buildlayers (Th, MaxLayer, zbound = [zmin, zmax], region = r1,
labelmid = r2, labelup = r3, labeldown = r4);
savemesh (Th3, "box2region1hole.mesh");
// construcción de una esfera con TetGen
func XX1 = cos (y) * sin (x);
func YY1 = sin (y) * sin (x);
func ZZ1 = cos (x);
prueba de cadena = "paACQ";
cout << "prueba =" << prueba << endl;
mesh3 Th3sph = tetgtransfo (Ths, transfo = [XX1, YY1, ZZ1], switch = test, nbofregions = 1,
regionlist = dominio);
savemesh (Th3sph, "esfera2region.mesh");

5.11 Ejemplos de mallado


Ejemplo 5.23 (lac.edp) // archivo ”lac.edp”

cargar '' msh3 ''


int nn = 5;
borde cc (t = 0,2 * pi) {x = cos (t); y = sin (t); etiqueta = 1;}

https://translate.googleusercontent.com/translate_f 132/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
malla Th2 = buildmesh (cc (100));
fespace Vh2 (Th2, P2);

Página 150
150 CAPÍTULO 5. GENERACIÓN DE MALLA

Vh2 ux, uy, p2;


int [int] rup = [0,2], rdlow = [0,1], rmid = [1,1,2,1,3,1,4,1];
func zmin = 2-sqrt (4- (x * x + y * y));
func zmax = 2-sqrt (3.);

mesh3 Th = capas de construcción (Th2, nn,


coeff = max ((zmax-zmin) / zmax, 1./nn),
zbound = [zmin, zmax],
labelmid = rmid;
labelup = rup;
labeldown = rlow);
savemesh (Th, '' Th.meshb '');
ejecutivo ('' medit Th; Th.meshb '');

Ejemplo 5.24 (tetgenholeregion.edp) // archivo '' tetgenholeregion.edp ''


cargar "msh3"
cargar "tetgen"

−pi −pi
malla Th = cuadrado (10,20, [x * pi-pi / 2,2 * y * pi]); // ] 2 , 2
[×] 0, 2π [
// una parametrización de una esfera
func f1 = cos (x) * cos (y);
func f2 = cos (x) * sin (y);
func f3 = sin (x);
// partiel derivada de la parametrización DF
func f1x = sin (x) * cos (y);
func f1y = -cos (x) * sin (y);
func f2x = -sin (x) * sin (y);
func f2y = cos (x) * cos (y);
func f3x = cos (x);
func f3y = 0;
// M = DF t DF
func m11 = f1xˆ2 + f2xˆ2 + f3xˆ2;
func m21 = f1x * f1y + f2x * f2y + f3x * f3y;
func m22 = f1yˆ2 + f2yˆ2 + f3yˆ2;

func perio = [[4, y], [2, y], [1, x], [3, x]];
hh real = 0,1;
real vv = 1 / cuadrado (hh);
verbosidad = 2;
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
plot (Th, espera = 1);

verbosidad = 2;

// construcción de la superficie de esferas


real Rmin = 1 .;
func f1min = Rmin * f1;
func f2min = Rmin * f2;
func f3min = Rmin * f3;

mesh3 Th3sph = movemesh23 (Th, transfo = [f1min, f2min, f3min]);

real Rmax = 2 .;

https://translate.googleusercontent.com/translate_f 133/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 151
5.11. EJEMPLOS DE MALLA 151

func f1max = Rmax * f1;


func f2max = Rmax * f2;
func f3max = Rmax * f3;

mesh3 Th3sph2 = movemesh23 (Th, transfo = [f1max, f2max, f3max]);

cout << "adición" << endl;


mesh3 Th3 = Th3sph + Th3sph2;

real [int] dominio2 = [1.5,0., 0., 145,0.001,0.5,0., 0., 18,0.001];


cout << "==============================" << endl;
cout << "llamada tetgen sin agujero" << endl;
cout << "==============================" << endl;
mesh3 Th3fin = tetg (Th3, switch = "paAAQYY", nbofregions = 2, regionlist = domain2);
cout << "=============================" << endl;
cout << "terminar llamada tetgen sin agujero" << endl;
cout << "=============================" << endl;
savemesh (Th3fin, "esferacontworegion.mesh");

agujero real [int] = [0., 0., 0.];


dominio real [int] = [1.5,0., 0., 53,0.001];
cout << "=============================" << endl;
cout << "llamada tetgen con agujero "<< endl;
cout << "=============================" << endl;
mesh3 Th3finhole = tetg (Th3, switch = "paAAQYY", nbofholes = 1, holelist = hole,
nbofregions = 1, regionlist = dominio);
cout << "=============================" << endl;
cout << "terminar llamada tetgen con agujero "<< endl;
cout << "=============================" << endl;
savemesh (Th3finhole, "esfera con agujero.mesh");

5.11.1 Construye una malla 3D de un cubo con un globo


Primero, el archivo MeshSurface.idp para construir la malla de límites de una Hexaedra y de una Esfera.

func mesh3 SurfaceHex ( int [ int ] & N, real [ int , int ] & B, int [ int , int ] & L, orientación int )
{
real x0 = B (0,0), x1 = B (0,1);
y0 real = B (1,0), y1 = B (1,1);
real z0 = B (2,0), z1 = B (2,1);

int nx = N [0], ny = N [1], nz = N [2];

Thx de malla = cuadrado (ny, nz, [y0 + (y1-y0) * x, z0 + (z1-z0) * y]);


malla Thy = cuadrado (nx, nz, [x0 + (x1-x0) * x, z0 + (z1-z0) * y]);
malla Thz = cuadrado (nx, ny, [x0 + (x1-x0) * x, y0 + (y1-y0) * y]);

int [int] refx = [0, L (0,0)], refX = [0, L (0,1)]; // Xmin, Ymax enfrenta etiquetas
renumerar
int [int] refy = [0, L (1,0)], refY = [0, L (1,1)]; // Ymin, Ymax se enfrenta a labesl
renumerar
int [int] refz = [0, L (2,0)], refZ = [0, L (2,1)]; // Zmin, Zmax enfrenta etiquetas
renumerar

Página 152
152 CAPÍTULO 5. GENERACIÓN DE MALLA

mesh3 Thx0 = movemesh23 (Thx, transfo = [x0, x, y], orientación = -orientación, etiqueta = refx);
mesh3 Thx1 = movemesh23 (Thx, transfo = [x1, x, y], orientación = + orientación, etiqueta = refX);

https://translate.googleusercontent.com/translate_f 134/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
mesh3 Thy0 = movemesh23 (Thy, transfo = [x, y0, y], orientación = + orientación, etiqueta = refy);
mesh3 Thy1 = movemesh23 (Thy, transfo = [x, y1, y], orientación = -orientación, etiqueta = refY);
mesh3 Thz0 = movemesh23 (Thz, transfo = [x, y, z0], orientación = -orientación, etiqueta = refz);
mesh3 Thz1 = movemesh23 (Thz, transfo = [x, y, z1], orientación = + orientación, etiqueta = refZ);
mesh3 Th = Thx0 + Thx1 + Thy0 + Thy1 + Thz0 + Thz1;
volver Th;
}

func mesh3 Sphere ( real R, real h, int L, int orientación)


{
−pi
malla Th = cuadrado (10,20, [x * pi-pi / 2,2 * y * pi]); // ] 2
, frac − pi2 [×] 0, 2π [
// una parametrización de una esfera
func f1 = cos (x) * cos (y);
func f2 = cos (x) * sin (y);
func f3 = sin (x);
// derivado de partiel
func f1x = sin (x) * cos (y);
func f1y = -cos (x) * sin (y);
func f2x = -sin (x) * sin (y);
func f2y = cos (x) * cos (y);
func f3x = cos (x);
func f3y = 0;
// la métrica en la esfera M = DF t DF
func m11 = f1xˆ2 + f2xˆ2 + f3xˆ2;
func m21 = f1x * f1y + f2x * f2y + f3x * f3y;
func m22 = f1yˆ2 + f2yˆ2 + f3yˆ2;

func perio = [[4, y], [2, y], [1, x], [3, x]]; // para almacenar la condición periódica

real hh = h / R; // hh tamaño de malla en unir esfera


real vv = 1 / cuadrado (hh);
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
Th = adaptmesh (Th, m11 * vv, m21 * vv, m22 * vv, IsMetric = 1, periódico = perio);
int [ int ] ref = [0, L];

mesh3 ThS = movemesh23 (Th, transfo = [f1 * R, f2 * R, f3 * R], orientación = orientación, refface = ref);
return ThS;
}

La prueba de las dos funciones y la llamada al generador de malla tetgen

cargar "tetgen"
incluir "MeshSurface.idp"
hs real = 0,1; // tamaño de malla en la esfera
int [int] N = [20,20,20];
real [int, int] B = [[- 1,1], [- 1,1], [- 1,1]];
int [int, int] L = [[1,2], [3,4], [5,6]];
mesh3 ThH = SurfaceHex (N, B, L, 1);
mesh3 ThS = Esfera (0.5, hs, 7,1); // "pegar" las mallas de la superficie a la superficie
mallas de contorno

Página 153
5.12. LA SOLUCIÓN DE SALIDA FORMATOS .SOL Y .SOLB 153

mesh3 ThHS = ThH + ThS;


savemesh (ThHS, "Hex-Sphere.mesh");
exec ("ffmedit Hex-Sphere.mesh; rm Hex-Sphere.mesh"); // ver 5.38

volteto real = (hsˆ3) / 6 .;


cout << "voltet =" << voltet << endl;
real [int] domaine = [0,0,0,1, voltet, 0,0,0.7,2, voltet];

mesh3 Th = tetg (ThHS, switch = "pqaAAYYQ", nbofregions = 2, regionlist = domaine);

https://translate.googleusercontent.com/translate_f 135/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
medit ("Cubo con bola", Th); // ver 5.39

Figura 5.38: Malla de superficie del Hex Figura 5.39: La malla tet del cubo con
con esfera interna bola interna

5.12 La solución de salida formatea .sol y .solb


Con la palabra clave saveol, podemos almacenar funciones escalares, funciones FE escalares, campos vectoriales,
campos FE vectoriales, un tensor simétrico y un tensor FE simétrico. Este formato se utiliza en medit.

archivo de extensión .sol Las dos primeras líneas del archivo son

• MeshVersionFormatted 0

• Dimensión (I) tenue

Los siguientes campos comienzan con una de las siguientes palabras clave: SolAtVertices, SolAtEdges, SolAtTri-
ángulos, SolAtQuadrilaterals, SolAtTetrahedra, SolAtPentahedra, SolAtHexahedra.

Página 154
154 CAPÍTULO 5. GENERACIÓN DE MALLA

En cada campo, damos en la siguiente línea el número de elementos en las soluciones (SolAtVertices:
número de vértices, SolAtTriangles: número de triángulos, ...). En otras líneas, damos el número de
soluciones, el tipo de solución (1: escalar, 2: vector, 3: tensor simétrico). Y finalmente, damos la
valores de las soluciones sobre los elementos.
El archivo debe terminar con la palabra clave End.
El elemento real del tensor simétrico

ST 3d
xx ST 3d
xy ST 3d
xz
(ST 2d xx ST 2d
xy
)
ST 3d = ST 3d
yx ST 3d
aa ST 3d
yz ST 2d = (5,6)
ST 2d
yx ST 2d
aa
ST 3d
zx ST 3d
zy ST 3d
zz

almacenados en la extensión .sol son respectivamente ST 3d


xx , ST 3dyx , ST 3daa , ST 3dzx , ST 3dzy , ST 3dzz y ST 2d xx , ST 2dyx , ST 2daa
Un ejemplo de campo con la palabra clave SolAtTetrahedra:
• SolAtTetrahedra
(I) NbOfTetrahedrons
nbsol typesol 1 ... tiposol n
((( k ) , ∀k ∈ {1, ... nbsol} ) ∀j ∈ {1, ..., NbOfTetrahedrons} )

https://translate.googleusercontent.com/translate_f 136/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Uij , ∀i ∈ {1, ..., nbrealsol k }
dónde
• nbsol es un número entero igual al número de soluciones

• typesol k , tipo de solución número k, es

- typesol k = 1 la solución k es escalar.


- typesol k = 2 la solución k es vectorial.
- typesol k = 3 la solución k es un tensor simétrico o una matriz simétrica.
• nbrealsol k número de real para describir el número de solución k es

- nbrealsol k = 1 la solución k es escalar.


- nbrealsol k = dim la solución k es vectorial (dim es la dimensión de la solución).
- nbrealsol k = dim ∗ (dim + 1) / 2 la solución k es un tensor simétrico o simétrico
matriz.
•Uk
ij es un valor real igual al valor del componente i de la solución k en el tetraedro j en el
malla asociada.

Este campo está escrito con la notación de la Sección 12.1 . El formato .solb es el mismo que el formato .sol
pero en binario (la lectura / escritura es más rápida, el almacenamiento es menor).
Una función escalar real f1, un vector campos Φ = [Φ1, Φ2, Φ3] y un tensor simétrico ST 3d ( 5.6 ) en
los vértices de la malla tridimensional Th3 se almacenan en el archivo "f1PhiTh3.sol" usando

saveol ("f1PhiST3dTh3.sol", Th3, f1, [Φ1, Φ2, Φ3], VV3, orden = 1);

donde VV 3 = [ST 3d
xx , ST 3dyx , ST 3daa , ST 3dzx , ST 3dzy , ST 3dzz ]. Para una malla bidimensional Th, un escalar real
funciones f2, se almacena un vector campos Ψ = [Ψ1, Ψ2] y un tensor simétrico ST 2d ( 5.6 ) en triángulos
en el archivo "f2PsiST2dTh3.solb" usando

saveol ("f2PsiST2dTh3.solb", Th, f2, [Ψ1, Ψ2], VV2, orden = 0);

donde VV 2 = [ST 2d
xx , ST 2dyx , ST 2dyy ] Los argumentos de las funciones saveol son el nombre de un archivo, un
mallas y soluciones. Estos argumentos deben darse en este orden.
Los parámetros de esta palabra clave son

Página 155
5.13. MEDIT 155

order = 0 es la solución se da en el centro de gravedad de los elementos. 1 es la solución se da


en los vértices de los elementos.

En el archivo, las soluciones se almacenan en este orden: soluciones escalares, soluciones vectoriales y finalmente simétricas
soluciones tensoriales.

5.13 meditar
La palabra clave medit permite sumergir una malla sola o una malla y una o varias funciones definidas
en la malla usando medit freeware de Pascal Frey. Medit abre su propia ventana y usa OpenGL
extensamente. Naturalmente, para utilizar este comando debe estar instalado medit.
Una visualización con media de soluciones escalares f1 y f2 continuas, lineales por partes y conocidas en
los vértices de la malla Th se obtiene utilizando

medit ("sol1 sol2", Th, f1, f2, order = 1);

El primer gráfico llamado "sol1" muestra f1. Los nombres de los segundos gráficos "sol2" muestran f2.
Los argumentos de la función medit son el nombre de las diferentes escenas (separadas por un espacio) de
medit, una malla y soluciones. Cada solución está asociada a una escena. El escalar, el vector y
Las soluciones de tensor simétrico se especifican en el formato descrito en la sección que trata de la
salvaguarda palabra clave.
Los parámetros de esta línea de comando son

order = 0 es la solución se da en el centro de gravedad de los elementos. 1 es la solución se da


en los vértices de los elementos.

https://translate.googleusercontent.com/translate_f 137/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

meditff = establece el nombre del comando de ejecución de medit. De forma predeterminada, esta cadena es medit.

save = establece el nombre de un archivo .sol o .solb para guardar soluciones.

Esta línea de comando permite también representar dos mallas diferentes y soluciones sobre ellas en la misma
ventanas. La naturaleza de las soluciones debe ser la misma. Por lo tanto, podemos visualizar en la misma ventana.
los diferentes dominios en un método de descomposición de dominios, por ejemplo. Una visualización con medit
de las soluciones escalares h1 y h2 en los vértices de la malla Th1 y Th2 respectivamente se obtienen utilizando

medit ("dominio sol2", Th1, h1, Th2, h2, orden = 1);

Ejemplo 5.25 (meditddm.edp) // meditddm.edp


cargar "medit"

// Problema inicial:
// Resolución del siguiente EDP:
// −∆u s = f en Ω = {(x, y) | 1 ≤ sqrt (x 2 + y 2 ) ≥ 2}
// −∆u 1 = f1 en Ω 1 = {(x, y) | 0.5 ≤ sqrt (x 2 + y 2 ) ≥ 1.}
// u = 1 en Γ + Condición de Neumman nula en Γ 1 y en Γ 2
// Encontramos la solución u al resolver dos EDP definidos en el dominio Ω y Ω 1
// Esta solución se visualiza con medit

verbosidad = 3;

borde Gamma (t = 0,2 * pi) {x = cos (t); y = sin (t); etiqueta = 1;};

Página 156
156 CAPÍTULO 5. GENERACIÓN DE MALLA

borde Gamma1 (t = 0,2 * pi) {x = 2 * cos (t); y = 2 * sin (t); etiqueta = 2;};
borde Gamma2 (t = 0,2 * pi) {x = 0,5 * cos (t); y = 0,5 * sin (t); etiqueta = 3;};

// construcción de malla de dominio Ω


malla Th = buildmesh (Gamma1 (40) + Gamma (-40));

fespace Vh (Th, P2);


func f = sqrt (x * x + y * y);
Vh nosotros, v;
macro Grad2 (us) [dx (us), dy (us)] // MOE

problema Lap2dOmega (us, v, init = false) = int2d (Th) (Grad2 (v) '* Grad2 (us))
- int2d (Th) (f * v) + en (1, us = 1);

// Definición de EDP definida en el dominio Ω


∂u s
// −∆u s = f 1 en Ω 1 , u s = 1 en Γ 1 , En = 0 en Γ 2
Lap2dOmega;

// construcción de malla de dominio Ω 1


malla Th1 = buildmesh (Gamma (40) + Gamma2 (-40));

fespace Vh1 (Th1, P2);


func f1 = 10 * sqrt (x * x + y * y);
Vh1 u1, v1;
macro Grad21 (u1) [dx (u1), dy (u1)] // MOE

problema Lap2dOmega1 (u1, v1, init = false) = int2d (Th1) (Grad21 (v1) '* Grad21 (u1))
- int2d (Th1) (f1 * v1) + en (1, u1 = 1);
// Resolución de EDP definida en el dominio Ω 1
∂u 1
// −∆u 1 = f 1 en Ω 1 , u - 1 = 1 en Γ 1 , En = 0 en Γ 2
Lap2dOmega1;

// visualización de la solución del problema inicial


medit ("solución", Th, us, Th1, u1, order = 1, save = "testsavemedit.solb");

https://translate.googleusercontent.com/translate_f 138/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Ejemplo 5.26 (StockesUzawa.edp) // el signo de presión es correcto


afirmar (versión> 1.18);
real s0 = reloj ();
malla Th = cuadrado (10,10);
espacio libre Xh (Th, P2), Mh (Th, P1);
Xh u1, u2, v1, v2;
Mh p, q, ppp;

varf bx (u1, q) = int2d (Th) ((dx (u1) * q));


varf por (u1, q) = int2d (Th) ((dy (u1) * q));
varf a (u1, u2) = int2d (Th) (dx (u1) * dx (u2) + dy (u1) * dy (u2))
+ en (1,2,4, u1 = 0) + en (3, u1 = 1);

Xh bc1; bc1 [] = a (0, Xh);


Xh b;

matriz A = a (Xh, Xh, solucionador = CG);


matriz Bx = bx (Xh, Mh);

Página 157
5.14. MSHMET 157

matriz By = by (Xh, Mh);


Xh bcx = 1, bcy = 0;

func real [ int ] divup ( real [ int ] & pp)


{
int verbo = verbosidad;
verbosidad = 0;
b [] = Bx '* pp; b [] + = bc1 []. * bcx [];
u1 [] = Aˆ-1 * b [];
b [] = Por '* pp; b [] + = bc1 []. * bcy [];
u2 [] = Aˆ-1 * b [];
ppp [] = Bx * u1 [];
ppp [] + = Por * u2 [];
verbosidad = verbo;
return ppp [];
};
p = 0; q = 0; u1 = 0; v1 = 0;

LinearCG (divup, p [], q [], eps = 1.e-6, nbiter = 50);

divup (p []);

plot ([u1, u2], p, espera = 1, valor = verdadero, coef = 0.1);


medit ("presión de velocidad", Th, [u1, u2], p, orden = 1);

5.14 Mshmet
Mshmet es un software desarrollado por P. Frey que permite calcular una métrica anisotrópica basada en
soluciones (es decir, basadas en arpillera). Este software también puede devolver una métrica isotrópica. Además, mshmet
También puede construir una métrica adecuada para la captura de interfaces de conjuntos de niveles. La solución se puede definir
sobre mallas estructuradas / no estructuradas 2D o 3D. Por ejemplo, la solución puede ser una estimación de error.
de una solución FE.
Las soluciones para mshmet se dan como argumento. La solución puede ser una función, una función vectorial, una
tensor simétrico, una función FE, una función vectorial FE y un tensor simétrico FE. El tensor simétrico
argumento se define como este tipo de datos para el argumento datasol. Este software acepta más de
una solución.
Por ejemplo, la métrica M calculada con mshmet para la solución u definida en la malla Th es
obtenido por escrito.

https://translate.googleusercontent.com/translate_f 139/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
fespace Vh (Th, P1);
Vh u; // una función FE escalar
real [int] M = mshmet (Th, u);

Los parámetros de la palabra clave mshmet son:


• normalización = <b> realiza una normalización de toda la solución en [0,1].
• aniso = <b> construir métrica aniso si 1 (delault 0: iso)
• levelset = <b> métrica de construcción para el método de conjunto de niveles (predeterminado: falso)
• verbosidad = <l>
• nbregul = <l> número de iteraciones de regularización de soluciones dadas (por defecto 0).

Página 158
158 CAPÍTULO 5. GENERACIÓN DE MALLA

• hmin = <d>
• hmax = <d>
• err = <d> nivel de error.
• ancho = <d> el ancho
• métrica = un vector de doble. Este vector contiene una métrica inicial dada a mshmet. La
La estructura del vector métrico se describe en el siguiente párrafo.
• loptions =] un vector de número entero de tamaño 7. Este vector contiene los parámetros enteros de
mshmet (solo para expertos).
- opciones (0): normalización (por defecto 1).
- opciones (1): parámetros isotrópicos (por defecto 0). 1 para resultados métricos isotrópicos de lo contrario 0.
- opciones (2): parámetros de ajuste de nivel (por defecto 0). 1 para el nivel de construcción establecido métrica en caso contrario 0.
- opciones (3): parámetros de depuración (por defecto 0). 1 para activar el modo de depuración de lo contrario 0.
- loptions (4): nivel de verbosidad (por defecto 10).
- loptions (5): número de iteraciones de regularización de soluciones dadas (por defecto 0).
- opciones (6): parámetro previamente métrico (por defecto 0). 1 para usar otras métricas anteriores
erwise 0.

• doptions = un vector de doble de tamaño 4. Este vector contiene los parámetros reales de mshmet
(solo para expertos).
- dopciones (0): hmin: parámetros de tamaño mínimo (predeterminado 0.01).
- dopciones (1): hmax: parámetros de tamaño máximo (predeterminado 1.0).
- dopciones (2): eps: parámetros de tolerancia (por defecto 0.01).
- opciones (2): ancho: ancho relativo para el conjunto de niveles (0 <w <1) (por defecto 0.05).

El resultado de la palabra clave mshmet es un [int] real que contiene la métrica calculada por mshmet
en los diferentes vértices V i de la malla.
Con nv es el número de vértices, la estructura de este vector es

M iso = (m (V 0 ), m (V 1 ), ..., m (V nv )) t

m 11 m 12 m 13
para una métrica isotrópica m. Para un tensor simétrico métrico h = m 21 m 22 m 23
, los parámetros
m 31 m 32 m 33
la métrica es
M aniso = (H (V 0 ), ..., H (V nv )) t

donde H (V i ) es el vector de tamaño 6 definido por [m11, m21, m22, m31, m32, m33]

Ejemplo 5.27 (mshmet.edp)

cargar "mshmet"
cargar "medit"
cargar "msh3"

https://translate.googleusercontent.com/translate_f 140/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

borde a (t = 0,1.0) {x = t; y = 0; etiqueta = 1;};


borde b (t = 0,0.5) {x = 1; y = t; etiqueta = 2;};
borde c (t = 0,0.5) {x = 1-t; y = 0.5; etiqueta = 3;};

Página 159
5.15. FREEYAMS 159

borde d (t = 0.5,1) {x = 0.5; y = t; etiqueta = 4;};


borde e (t = 0.5,1) {x = 1-t; y = 1; etiqueta = 5;};
borde f (t = 0.0,1) {x = 0; y = 1-t; etiqueta = 6;};
malla Th = buildmesh (a (6) + b (4) + c (4) + d (4) + e (4) + f (6));
savemesh (Th, "th.msh");
fespace Vh (Th, P1);
Vh u, v;
error real = 0.01;
problema Problema1 (u, v, solucionador = CG, eps = 1.0e-6) =
int2d (Th, qforder = 2) (u * v * 1.0e-10 + dx (u) * dx (v) + dy (u) * dy (v))
+ int2d (Th, qforder = 2) ((xy) * v);

func zmin = 0;
func zmax = 1;
int MaxLayer = 10;
mesh3 Th3 = buildlayers (Th, MaxLayer, zbound = [zmin, zmax]);
fespace Vh3 (Th3, P2);
fespace Vh3P1 (Th3, P1);
Vh3 u3, v3;
Vh3P1 usol;
problema Problemam2 (u3, v3, solucionador = sparsesolver) =
int3d (Th3) (u3 * v3 * 1.0e-10 + dx (u3) * dx (v3) + dy (u3) * dy (v3) + dz (u3) * dz (v3))
- int3d (Th3) (v3) + en (0,1,2,3,4,5,6, u3 = 0);
Problem2;
cout << u3 []. min << "" << u3 []. max << endl;
savemesh (Th3, "metrictest.bis.mesh");
saveol ("metrictest.sol", Th3, u3);

real [int] bb = mshmet (Th3, u3);


cout << bb << endl;
para (int ii = 0; ii <Th3.nv; ii ++)
usol [] [ii] = bb [ii];
saveol ("metrictest.bis.sol", Th3, usol);

5.15 FreeYams
FreeYams es un software de adaptación de mallas de superficie desarrollado por P. Frey. Este software
es una nueva versión de ñame. La malla de superficie adaptada se construye con una métrica geométrica
campo tensorial. Este campo se basa en las propiedades intrínsecas de la superficie discreta. También esto
El software permite construir una simplificación de una malla. Esta aniquilación se basa en la Haus-
Dorff distancia entre la triangulación inicial y la actual. En comparación con los ñames de software,
FreeYams también se puede utilizar para producir triangulaciones anisotrópicas adaptadas a simulaciones de conjuntos de niveles.
ciones. Un informe técnico sobre FreeYams aún no está disponible, pero existe una documentación sobre los ñames en
http://www.ann.jussieu.fr/∼frey/software.html [ 45] .
Para llamar a FreeYams en FreeFem ++, usamos la palabra clave freeyams. Los argumentos de esta función
son la malla inicial y / o métrica. La métrica con freeyams es una función, una función FE, una
función tensorial simétrica, función tensorial simétrica FE o vector de doble. Si la métrica es
vector de doble, estos datos deben darse en parámetro métrico. De lo contrario, la métrica se da en
el argumento.
Por ejemplo, se obtiene la malla adaptada de T hinit definida por la métrica u definida como función FE
escrito.

https://translate.googleusercontent.com/translate_f 141/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 160
160 CAPÍTULO 5. GENERACIÓN DE MALLA

fespace Vh (Thinit, P1);


Vh u;
mesh3 Th = freeyams (Thinit, u);

El argumento del tensor simétrico para la palabra clave freeyams se define como este tipo de datos para datasol
argumento.

• aniso = <b> aniso o iso métrico (predeterminado 0, iso)


• mem = <l> memoria de para freeyams en Mb (delaulf -1, freeyams elige)
• hmin = <d>
• hmax = <d>

• gradación = <d>
• opción = <l>

0: optimización de malla (suavizado + intercambio)


1: diezmado + enriquecimiento adaptado a un mapa métrico. (defecto)

-1: diezmado adaptado a un mapa métrico.


2: diezmado + enriquecimiento con un método similar al de Hausdorff

-2: diezmado con un método similar al de Hausdorff


4: divide triángulos de forma recursiva.

9: Suavizado de vértices sin contracción

• ángulo de cresta = <d>


• absoluto = <b>
• verbosidad = <i>
• métrica = expresión vectorial. Este parámetro contiene la métrica en los diferentes vértices en
la malla inicial. Con nv es el número de vértices, este vector es

M iso = (m (V 0 ), m (V 1 ), ..., m (V nv )) t

m 11 m 12 m 13
para una métrica escalar m. Para un tensor simétrico métrico h = m 21 m 22 m 23
, el parámetro
m 31 m 32 m 33
La métrica de éteres es
M aniso = (H (V 0 ), ..., H (V nv )) t

donde H (V i ) es el vector de tamaño 6 definido por [m11, m21, m22, m31, m32, m33]
• loptions = un vector de número entero de tamaño 13. Este vector contiene las opciones de número entero de
FreeYams. (solo para el experto)

- loptions (0): parámetro anisotrópico (por defecto 0). Si da una métrica anisotrópica 1
de lo contrario 0.

- opciones (1): parámetro de corrección de elementos finitos (por defecto 0). 1 para ningún elemento finito
corrección de lo contrario 0.

- opciones (2): Parámetro de división de múltiples puntos conectados (predeterminado 1). 1 para dividir múltiples
múltiples puntos conectados en caso contrario 0.

Página 161
5.15. FREEYAMS 161

https://translate.googleusercontent.com/translate_f 142/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
- loptions (3): valor máximo del tamaño de la memoria en Mbytes (por defecto -1: el tamaño viene dado por
freeyams).

- loptions (4): establece el valor del componente conectado que queremos obtener. (Re-
marca: los freeyams dan un valor automático en cada componente conectado).

- loptions (5): nivel de verbosidad

- opciones (6): parámetro de creación de punto en la regla (sin mapeo) (predeterminado 0). 1 para
creando punto en la regla de lo contrario 0.

- opciones (7): verificación de validez durante el parámetro de suavizado. Este parámetro solo se usa
con optimización de suavizado de vértices sin contracción (parámetro de opción de optimización 9).
1 para Sin verificación de validez durante el suavizado; de lo contrario, 0.

- loptions (8): número de vértices deseados (predeterminado -1).

- loptions (9): número de iteraciones de optimizaciones (predeterminado 30).

- opciones (10): sin parámetro de detección (por defecto 0). 1 para detectar la cresta en la malla
de lo contrario 0. La definición de la cresta se da en las opciones de parámetro (12).

- loptions (11): sin parámetro de suavizado de vértices (predeterminado 0). 1 para suavizar los vértices
de lo contrario 0.

- opciones (12): parámetro de nivel de optimización (por defecto 0).


∗ 0: optimización de malla (suavizado + intercambio)
∗ 1: diezmado + enriquecimiento adaptado a un mapa métrico.
∗ -1: diezmado adaptado a un mapa métrico.
∗ 2: diezmado + enriquecimiento con un método similar al de Hausdorff
∗ -2: diezmado con un método similar al de Hausdorff
∗ 4: divide triángulos de forma recursiva.
∗ 9: Suavizado de vértices sin contracción

doptions = un vector de doble de tamaño 11. Este vector contiene las opciones reales de freeyams.
- dopciones (0): establece la aproximación geométrica (desviación del plano tangente) (por defecto 0.01).

- doptions (1): establece el parámetro lamda (predeterminado -1.).

- dopciones (2): establece el parámetro mu (predeterminado -1.).

- dopciones (3): establezca el valor de gradación (control de densidad de malla) (predeterminado 1.3).

- dopciones (4): establece el tamaño mínimo (hmin) (predeterminado -2.0: el tamaño se compara automáticamente
puted).

- dopciones (5): establece el tamaño máximo (hmax) (predeterminado -2.0: el tamaño se compara automáticamente
puted).

- dopciones (6): establezca la tolerancia del control de la desviación cordal (por defecto -2.0).

- dopciones (7): establece la calidad de degradación (por defecto 0.599).

- doptions (8): establece el parámetro declic (predeterminado 2.0).

- dopciones (9): establezca el parámetro de limitación de walton angular (por defecto, 45 grados).

- dopciones (10): establece la detección de cresta angular (por defecto, 45 grados).

Página 162
162 CAPÍTULO 5. GENERACIÓN DE MALLA

Ejemplo 5.28 (freeyams.edp)

cargar "msh3"
cargar "medit"
cargar "freeyams"
int nn = 20;
malla Th2 = cuadrado (nn, nn);
fespace Vh2 (Th2, P2);

https://translate.googleusercontent.com/translate_f 143/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Vh2 ux, uz, p2;
int [int] rup = [0,2], rdown = [0,1], rmid = [1,1,2,1,3,1,4,1];
zmin real = 0, zmax = 1;
mesh3 Th = capas de construcción (Th2, nn, zbound = [zmin, zmax],
reffacemid = rmid, reffaceup = rup, reffacelow = rdown);

mesh3 Th3 = freeyams (Th);


medit ("maillagesurfacique", Th3, espera = 1);

5,16 mmg3d
Mmg3d es un software de remallado 3D desarrollado por C. Dobrzynski y P. Frey
(http://www.math.u-bordeaux1.fr/∼dobj/logiciels/mmg3d.php). Para obtener una versión de esta li-
brary envía un correo electrónico a:
cecile.dobrzynski@math.ubordeaux1.fr o pascal.frey@upmc.fr.
Este software permite volver a mallar una malla inicial hecha de tetraedros. Esta malla inicial se adapta a
un campo tensorial métrico geométrico o un vector de desplazamiento (cuerpo rígido en movimiento). La métrica puede
obtenerse con mshmet (ver sección 5.14) .

Observación 5:

(a) Si no se proporciona una métrica, se calcula una métrica isotrópica analizando el tamaño de las aristas en el
malla inicial.

(b) si se da un desplazamiento, los vértices de los triángulos de superficie se mueven sin verificar la
estructura geométrica de la nueva malla superficial.

Los parámetros de mmg3d son:


• opciones = expresión vectorial. Este vector contiene los parámetros de opción de mmg3d. Es un
vector de 6 valores, con el siguiente significado:
(0) parámetros de optimización: (predeterminado 1)
0: optimización de malla.
1: adaptación con métrica (eliminación e inserción de vértices) y optimización.
-1: adaptación con métrica (eliminación e inserción de vértices) sin optimización.
4: tetraedros divididos (tenga cuidado de modificar la superficie).
9: malla móvil con optimización.
-9: malla móvil sin optimización.
(1) modo de depuración: (predeterminado 0)
1: activa el modo de depuración.
0: de lo contrario.

Página 163
5.16. MMG3D 163

(2) Especifique el tamaño del cubo por dimensión (predeterminado 64)

(3) modo de intercambio: (predeterminado 0)


1: sin bordes ni movimientos de caras.
0: de lo contrario.

(4) modo de inserción de puntos: (predeterminado 0)


1: sin división o colapso de los bordes y sin puntos de inserción.
0: de lo contrario.

(5) nivel de verbosidad (predeterminado 3)


• memoria = expresión entera. Establezca el tamaño máximo de memoria de la nueva malla en Mbytes. Por
por defecto, el número máximo de vértices, tetraedros y triángulos es respectivamente 500000,
3000 000, 100000 que representan aproximadamente una memoria de 100 Mo.
• métrica = expresión vectorial. Este vector contiene la métrica dada en mmg3d. Es un vector

https://translate.googleusercontent.com/translate_f 144/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
de
de tamaño
vértices nv
en ola6malla
nv respectivamente para una
inicial. La estructura delmétrica istrópicasey describe
vector métrico anisotrópica
en eldonde nv es el número
mshmet's
sección (sección 5.14) .
• desplazamiento = [Φ1, Φ2, Φ3] establece el vector de desplazamiento de la malla inicial
Φ (x, y) = [Φ1 (x, y), Φ2 (x, y), Φ3 (x, y)].
• displVect = establece el desplazamiento del vector en una expresión vectorial. Este vector contiene el
desplazamiento en cada punto de la malla inicial. Es un vector de tamaño 3 nv.

En "mmg3d.edp" se ofrece un ejemplo de uso de esta función:

Ejemplo 5.29 (mmg3d.edp)

// prueba mmg3d
cargar "msh3"
cargar "medit"
cargar "mmg3d"
incluir "../examples++-3d/cube.idp"

int n = 6;
int [int] Nxyz = [12,12,12];
real [int, int] Bxyz = [[0., 1.], [0., 1.], [0., 1.]];
int [int, int] Lxyz = [[1,1], [2,2], [2,2]];
mesh3 Th = Cubo (Nxyz, Bxyz, Lxyz);

isométrico real [int] (Th.nv); {


para (int ii = 0; ii <Th.nv; ii ++)
isométrico [ii] = 0,17;
}

mesh3 Th3 = mmg3d (Th, memoria = 100, métrica = isométrica);

medit ("init", Th);


medit ("isométrico", Th3);

Un ejemplo de una malla en movimiento se da en fallingspheres.edp ”:

Página 164
164 CAPÍTULO 5. GENERACIÓN DE MALLA

Ejemplo 5.30 (fallingspheres.edp) carga "msh3" carga "tetgen" carga "medit" carga "mmg3d"
incluir "MeshSurface.idp"

// construir malla de una caja (311) con 2 agujeros (300,310)

hs real = 0,8;
int [ int ] N = [4 / hs, 8 / hs, 11.5 / hs];
real [int, int] B = [[- 2,2], [- 2,6], [- 10,1.5]];
int [ int , int ] L = [[311,311], [311,311], [311,311]];
mesh3 ThH = SurfaceHex (N, B, L, 1);
mesh3 ThSg = Esfera (1, hs, 300, -1);
mesh3 ThSd = Esfera (1, hs, 310, -1); ThSd = movemesh3 (ThSd, transfo = [x, 4 + y, z]);
mesh3 ThHS = ThH + ThSg + ThSd; // encolado de mallas de superficie
medit ("ThHS", ThHS); // ver malla de superficie

volteto real = (hsˆ3) / 6 .;


dominio real [int] = [0,0, -4,1, voltet];
agujeros reales [int] = [0,0,0,0,4,0];
mesh3 Th = tetg (ThHS, switch = "pqaAAYYQ", nbofregions = 1, regionlist = domaine, nbofholes = 2, holelist = hol
medit ("Caja-con-dos-bolas", Th);
// Malla de construcción final

int [ int ] opt = [9,0,64,0,0,3]; // opciones de mmg3d ver freeem ++ doc


real [ int ] vit = [0,0, -0,3];

https://translate.googleusercontent.com/translate_f 145/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
func cero = 0 .;
func dep = vit [2];

fespace Vh (Th, P1);


macro Grad (u) [dx (u), dy (u), dz (u)] //

Vh uh, vh; // para calcular el campo de desplazamiento


Problema Lap (uh, vh, solucionador = CG) = int3d (Th) ( Grad (uh) '* Grad (vh)) // ') por
emacs
+ en (310,300, uh = dep) + en (311, uh = 0.);

para ( int it = 0; it <29; it ++) {


cout << "ITERACIÓN "<< it << endl;
Vuelta;
trama (Th, uh);
Th = mmg3d (Th, opciones = opt, desplazamiento = [cero, cero, uh], memoria = 1000);
}

5.17 Un primer proceso de adaptación de la malla de isótopos 3d


Ejemplo 5.31 (Laplace-Adapt-3d.edp)

cargar "msh3" cargar "tetgen" cargar "mshmet" cargar "medit"


// construir malla inicial
int nn = 6;
int [ int ] l1111 = [1,1,1,1], l01 = [0,1], l11 = [1,1]; // numeración de etiquetas para tener todo
etiqueta a 1

Página 165
5.18. CONSTRUYE UNA MALLA 2D A PARTIR DE UN ISOLINE 165

mesh3 Th3 = buildlayers (cuadrado (nn, nn, región = 0, etiqueta = l1111),


nn, zbound = [0,1], labelmid = l11, labelup = l01, labeldown = l01);
Th3 = trunc (Th3, (x <0,5) | (y <0,5) | (z <0,5), etiqueta = 1); // eliminar el
] 0.5, 1 [ 3 cubo
// final de la construcción de la malla inicial
fespace Vh (Th3, P1);
Vh u, v, usol, h;

macro Grad (u) [dx (u), dy (u), dz (u)] // MOE

problema Poisson (u, v, solucionador = CG) = int3d (Th3) ( Grad (u) '* Grad (v))
- int3d (Th3) (1 * v) + en (1, u = 0);

errm real = 1e-2; // nivel de error


para ( int ii = 0; ii <5; ii ++)
{
Poisson; // resuelve la ecuación de Poisson.
cout << "u min, max =" << u []. min << "" << u []. max << endl;
h = 0. ; // para cambiar el tamaño de h [] porque la malla cambia
h [] = mshmet (Th3, u, normalización = 1, aniso = 0, nbregul = 1, hmin = 1e-3, hmax = 0.3, err = errm);
cout << "h min, max =" << h []. min << "" << h []. max
<< "" << h []. n << "" << Th3.nv << endl;
plot (u, espera = 1);
errm * = 0,8; // cambiar el nivel de error
cout << "Th3" << Th3.nv <"" << Th3.nt << endl;
Th3 = tetgreconstruction (Th3, switch = "raAQ", sizeofvolume = h * h * h / 6.); // reconstruir
malla
medit ("U-adap-iso -" + ii, Th3, u, espera = 1);}

5.18 Construye una malla 2d a partir de una isolina

https://translate.googleusercontent.com/translate_f 146/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
La idea es conseguir la discretización de una isolínea a mallas fluidas, esta herramienta puede ser útil para construir
mallas de la imagen. Primero, damos un ejemplo de las mallas de isovalor 0.2 de la función analítica
√ (x - 1/2) 2 + (y - 1/2) 2 , en el cuadrado de la unidad.

Ejemplo 5.32 (isoline.edp)

cargar "isoline" // cargar el complemento "isoline"

real [ int , int ] xy (3,1); // para almacenar los puntos isoline


int [ int ] be (1); // para almacenar el comienzo, el final de un par de líneas
{ // un bloque para la gestión de la memoria
malla Th = cuadrado (10,10); // , [x * 0,5, y * 0,5]);
fespace Vh (Th, P1);
Vh u = sqrt (cuadrado (x-0.5) + cuadrado (y-0.5));
iso real = 0,2;
real [int] viso = [iso];
gráfico (u, viso = viso, Th); // para ver la línea iso

int nbc = isoline (Th, u, xy, close = 1, iso = iso, beginend = be, suavizado = 0.1);

Los parámetros de isolínea son Th la malla, la expresión u, la matriz bidimensional xy para almacenar
la lista de coordenadas de los puntos. La lista de parámetros con nombre son:

Página 166
166 CAPÍTULO 5. GENERACIÓN DE MALLA

iso = valor de la isolina a calcular (0 es el valor predeterminado)

cerrar = cerrar la línea iso con el borde (def. verdadero), agregamos la parte del borde de la malla como el
el valor es menor que el valor iso

suavizado = nb del proceso de suavizado es l r s donde l es la longitud del componente de línea actual,
r la relación, s es el valor de suavizado. El valor predeterminado de suavizado es 0.

ratio = el ratio (1 por defecto).

eps = relativo ε (ver código ??) (def 1e-10)

beginend = matriz para comenzar, finalice un par de cada una de las sublíneas (cambiar el tamaño automáticamente)

file = para guardar la curva de datos en el archivo de datos para el gráfico GNU

En la matriz xy obtienes la lista de vértices de la isolina, cada línea de conexión va de i = i c


0 , ..., yo c1 −1
con i c
0 = ser (2 ∗ c) yo c 1 = be (2 ∗ c + 1), y donde x i = xy (0, i), y i = yx (1, i), l i = xy (2, i). Aquí l i es
la longitud de la línea (el origen de la línea es el punto i c 0 ).
El sentido de la isolina es tal que la parte superior está en el tamaño izquierdo de la isolina. Así que aquí: el
mínimo es un punto 0.5,05 por lo que la curva 1 giro en el sentido de las agujas del reloj, el orden de cada componente
se clasifican de tal manera que el número de puntos por componente está disminuyendo.

cout << "nb del componente de línea = "<< nbc << endl;
cout << "n =" << xy.m << endl; // número de puntos
cout << "be =" << be << endl; // comenzar al final de cada componente

// mostrar el componente de líneas


para ( int c = 0; c <nbc; ++ c)
{
int i0 = be [2 * c], i1 = be [2 * c + 1] -1; // comienzo, final del componente de línea
cout << "Curva" << c << endl;
para (int i = i0; i <= i1; ++ i)
cout << "x =" << xy (0, i) << "y =" << xy (1, i) << "s ="
<< xy (2, i) << endl;
plot ([xy (0, i0: i1), xy (1, i0: i1)], espera = 1, viso = viso, cmm = "curva" + c);
}
} // fin de bloque para la gestión de la memoria

cout << "longitud de la última curva =" << xy (2, xy.m-1) << endl ;;

También tenemos una nueva función para parametrizar fácilmente una curva discreta definida por el par be, xy.

https://translate.googleusercontent.com/translate_f 147/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

borde Curva0 (t = 0,1) // el límite externo


{ int c = 0; // componente 0
int i0 = be [2 * c], i1 = be [2 * c + 1] -1;
P = Curva (xy, i0, i1, t); // Curva 0
etiqueta = 1;
}

borde Curva1 (t = 0,1)


{ int c = 1; // componente 1
int i0 = be [2 * c], i1 = be [2 * c + 1] -1;
P = Curva (xy, i0, i1, t); // Curva 1
etiqueta = 1;
}

Página 167
5.18. CONSTRUYE UNA MALLA 2D A PARTIR DE UN ISOLINE 167

trazar (Curve1 (100)); // mostrar curva.


malla Th = buildmesh (Curve1 (-100)); // porque
plot (Th, espera = 1); //

En segundo lugar, usamos esta idea para construir mallas a partir de la imagen, usamos los complementos ppm2rnm para leer pgm
imagen en escala de grises, y extraemos el contorno de grises al nivel 0.25.

Ejemplo 5.33 (Leman-mesh.edp)

cargar "ppm2rnm" cargar "isoline"


cadena leman = "lg.pgm"; // ver figura 5.40
AreaLac real = 580.03; // en Km 2
tamaño real = 5; // malla señor en pixel ..
Curvas reales [int, int] (3,1);
int [int] be (1);
int nc; // nb de curva
{
real [int, int] ff1 (leman); // leer imagen (figura 5.40 )
// y establecer en rect. formación
int nx = ff1.n, ny = ff1.m; // valor de gris entre 0 y 1 (oscuro)
// construya una malla cartesiana de modo que el origen esté en el lugar correcto.
malla Th = cuadrado (nx-1, ny-1, [(nx-1) * (x), (ny-1) * (1-y)]);
// advirtiendo que la numeración es de los vértices (x, y) es
// dado por i = x / nx + nx ∗ y / ny
fespace Vh (Th, P1);
Vh f1; f1 [] = ff1; // Transforme array en función de elementos finitos.
nc = isoline (Th, f1, iso = 0.25, close = 1, Curves, beginend = be, smoothing = .1, ratio = 0.5);
}
// la isolina más larga: la lac ..
int ic0 = be (0), ic1 = be (1) -1;
plot ([Curves (0, ic0: ic1), Curves (1, ic0: ic1)], espera = 1);
int NC = Curvas (2, ic1) / hsize;
borde G (t = 0,1) { P = Curva (Curvas, ic0, ic1, t); etiqueta = 1 + (x> xl) * 2 + (y <yl);}

plot (G (-NC), espera = 1);


malla Th = buildmesh (G (-NC));
plot (Th, espera = 1);
escala real = sqrt (AreaLac / Th.area);
Th = movemesh (Th, [x * escala, y * escala]); // cambiar el tamaño de la malla
cout << "Th.area =" << Th.area << "Kmˆ2" << "==" << AreaLac << " Kmˆ2 "
<< endl;
plot (Th, espera = 1, ps = "leman.eps"); // ver figura 5.41

https://translate.googleusercontent.com/translate_f 148/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 168
168 CAPÍTULO 5. GENERACIÓN DE MALLA

Figura 5.40: La imagen del leman lac


mallas
Figura 5.41: la malla de lac

https://translate.googleusercontent.com/translate_f 149/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 169

Capítulo 6

Elementos finitos

Como se indica en la Sección 2. FEM aproxima todas las funciones w como

w (x, y) ≃ w 0 φ 0 (x, y) + w 1 φ 1 (x, y) + ··· + w M − 1 φ M − 1 (x, y)

con funciones de base de elementos finitos φ k (x, y) y números w k (k = 0, ···, M - 1). Las funciones
φ k (x, y) se construyen a partir del triángulo T i k , y se denominan funciones de forma. En FreeFem ++ el
espacio de elementos finitos

V h = {w | w 0 φ 0 + w 1 φ 1 + ··· + w M − 1 φ M − 1 , w i ∈ R}

es creado fácilmente por

fespace IDspace (IDmesh, <IDFE>);

o con l pares de condiciones de contorno periódicas en 2d

fespace IDspace (IDmesh, <IDFE>,


periódico = [[la 1, sa 1], [lb 1, sb 1],
...
[la k, sa k], [lb k, sb l]]);

y en 3d

fespace IDspace (IDmesh, <IDFE>,


periódico = [[la 1, sa 1, ta 1], [lb 1, sb 1, tb 1],
...
[la k, sa k, ta k], [lb k, sb l, tb l]]);

dónde
IDspace es el nombre del espacio (por ejemplo, Vh),

IDmesh es el nombre de la malla asociada y <IDFE> es un identificador de tipo de elemento finito.

En 2D tenemos un par de condiciones de contorno periódicas, si [la i, sa i], [lb i, sb i] es un par de


int, y las 2 etiquetas la i y lb i se refieren a 2 piezas de límite para estar en equivalencia.
Si [la i, sa i], [lb i, sb i] es un par de reales, entonces sa i y sb i dan dos abscisas comunes
en la curva de dos límites, y dos puntos se identifican como uno si las dos abscisas son iguales.

En 2D, tenemos un par de condiciones de contorno periódicas, si [la i, sa i, ta i], [lb i, sb i, tb i] es


un par de int, las 2 etiquetas la i y lb i definen que las 2 partes del límite están en equivalencia.

169

Página 170

https://translate.googleusercontent.com/translate_f 150/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
170 CAPÍTULO 6. ELEMENTOS FINITOS

Si [la i, sa i, ta i], [lb i, sb i, tb i] es un par de real, entonces sa i, ta i y sb i, tb i do


dos parámetros comunes en las dos superficies límite, y dos puntos se identifican como uno si el
dos parámetros son iguales.

Observación 6 La malla 2D de los dos bordes identificados debe ser la misma, así que para estar seguro, use el parámetro
eter fixedborder = true en el comando buildmesh (ver 5.1.2) como en el ejemplo periodic2bis.edp
(ver 9.7) .

A día de hoy, los tipos conocidos de elementos finitos son:

P0, P03d elemento finito discontinuo constante a trozos (2d, 3d), los grados de libertad son los
valor del elemento baricentro.

P0 h = {v ∈ L 2 (Ω) ∣∣ para todo K ∈ T h hay α K ∈ R: v | K = α K } (6,1)

P1, P13d elemento finito continuo lineal a trozos (2d, 3d), los grados de libertad son los vértices
valores.

P1 h = {v ∈ H 1 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 1 } (6.2)

P1dc elemento finito discontinuo lineal a trozos

P1dc h = {v ∈ L 2 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 1 } (6,3)

Advertencia, debido al problema de interpolación, el grado de libertad no son los vértices sino tres
Las véctices se mueven hacia adentro con T (X) = G + .99 (X − G) donde G es el baricentro, (versión 2.24-4).

P1b, P1b3d Elemento finito continuo lineal a trozos más burbuja (2d, 3d)

El caso 2d:

P1b h = {v ∈ H 1 (Ω) ∣∣ ∀K ∈ T h v | K ∈ P 1 ⊕ Alcance {λ K (6,4)


0 λ K1 λ K2 }}

El caso 3d:

P1b h = {v ∈ H 1 (Ω) ∣∣ ∀K ∈ T h v | K ∈ P 1 ⊕ Alcance {λ0Kλ K1 λ K2 λ K3 }} (6,5)

donde λ K
i , i = 0, .., d son las funciones de coordenadas baricéntricas d + 1 del elemento K (triángulo
o tetraedro).

P1bl, P1bl3d Elemento finito continuo lineal a trozos más burbuja lineal (2d, 3d) la viñeta es
construir dividiendo el baricentro K a en el subelemento d + 1. (necesita cargar "Element_P1bl")

P2, P23d a trozos P 2 elemento finito continuo (2d, 3d),

P2 h = {v ∈ H 1 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 2 } (6,6)

donde P 2 es el conjunto de polinomios de R 2 de grados ≤ 2.

P2b a trozos P 2 elemento finito continuo más burbuja,

P2 h = {v ∈ H 1 (Ω) ∣∣ ∀K ∈ T h v | K ∈ P 2 ⊕ Alcance {λ0 Kλ K1 λ K2 }} (6,7)

Página 171
171

P2dc elemento finito discontinuo P 2 a trozos ,

P2dc h = {v ∈ L 2 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 2 } (6,8)

Advertencia, debido a un problema de interpolación, el grado de libertad no son los seis nodos P2 sino seis
los nodos se mueven hacia adentro con T (X) = G + .99 (X - G) donde G es el baricentro, (versión 2.24-4).

https://translate.googleusercontent.com/translate_f 151/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

P3 a trozos P 3 elemento finito continuo (2d) (necesita cargar "Element_P3")

P2 h = {v ∈ H 1 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 3 } (6,9)

donde P 3 es el conjunto de polinomios de R 2 de grados ≤ 3.

P3dc a trozos P 3 elemento finito discontinuo (2d) (necesita cargar "Element_P3dc")

P2 h = {v ∈ L 2 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 3 } (6,10)

donde P 3 es el conjunto de polinomios de R 2 de grados ≤ 3.

P4 a trozos P 4 elemento finito continuo (2d) (necesita cargar "Element_P4")

P2 h = {v ∈ H 1 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 4 } (6,11)

donde P 4 es el conjunto de polinomios de R 2 de grados ≤ 4.

P4dc a trozos P 4 elemento finito discontinuo (2d) (necesita cargar "Element_P4dc")

P2 h = {v ∈ L 2 (Ω) ∣∣ ∀K ∈ T h v |K ∈ P 3 } (6,12)

donde P 4 es el conjunto de polinomios de R 2 de grados ≤ 3.

P0Borde a trozos P 0 elemento finito discontinuo (2d) presente en cada borde de la malla.

P1Edge a trozos P 1 elemento finito discontinuo (2d) (necesita carga "Element_PkEdge") P 1 en


cada borde de la malla.

P2Edge a trozos P 2 elemento finito discontinuo (2d) (necesita carga "Element_PkEdge") P 2 en


cada borde de la malla.

P3Edge a trozos P 3 elemento finito discontinuo (2d) (necesita carga "Element_PkEdge") P 3 en


cada borde de la malla.

P4Edge a trozos P 4 elemento finito discontinuo (2d) (necesita carga "Element_PkEdge") P 4 en


cada borde de la malla.

P5Edge a trozos P 5 elemento finito discontinuo (2d) (necesita carga "Element_PkEdge") P 5 en


cada borde de la malla.

P2Morley a trozos P 2 elemento finito no conforme (2d) (necesita carga "Morley")

{ ∣ { v continuo en los vértices, }


P2 h = v ∈ L 2 (Ω) ∣ ∀K ∈ T h v |K ∈ P 3 , (6,13)
∣ ∂ n v continua en el medio del borde,

donde P 2 es el conjunto de polinomios de R 2 de grados ≤ 2.


Advertencia para construir la interplantación de una función u (escalar) para este elemento finito, necesitamos el
función y 2 derivadas parciales (u, u x , u y ), entonces este elemento finito vectorial con 3 componentes
(u, u x , u y ).

Página 172
172 CAPÍTULO 6. ELEMENTOS FINITOS

Vea el ejemplo bilapMorley.edp de examples ++ - load para resolver el problema de BiLaplacien:

cargar "Morley"
fespace Vh (Th, P2Morley); // el espacio de elementos finitos de Morley
macro bilaplacien (u, v) (dxx (u) * dxx (v) + dyy (u) * dyy (v) + 2. * dxy (u) * dxy (v))
// macro de aleta
real f = 1;
Vh [u, ux, uy], [v, vx, vy];

resolver bilap ([u, ux, uy], [v, vx, vy]) =


int2d (Th) (bilaplacien (u, v))
- int2d (Th) (f * v)
+ en (1,2,3,4, u = 0, ux = 0, uy = 0)

https://translate.googleusercontent.com/translate_f 152/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

HCT P 3 C 1 conforme elemento finito (2d) (necesita cargar "Element_HCT") uno 3 sub triángulos (ver-
sión 3.40).

Vamos a llamar
h la
a Tsubmalla de T h donde todos los triángulos se dividen en 3 en el baricentro.

PHCT h = { v ∈ C 1 (Ω) ∣ △
v |K ∈ P 3 } (6,14)
∣ h
∣ ∀K ∈ T

donde P 3 es el conjunto de polinomios de R 2 de grados ≤ 3. El grado de libertad es el valor


y derivada en los vértices y derivada normal un punto del borde medio de las mallas iniciales, y
gracias a [ 15] .
Advertencia para construir la interplantación de una función u (escalar) para este elemento finito, necesitamos el
función y 2 derivadas parciales (u, u x , u y ), entonces este elemento finito vectorial con 3 componentes
(u, u x , u y ) como en el elemento finito anterior.

P2BR (necesita cargar "BernadiRaugel") el elemento finito Bernadi Raugel es un elemento vectorial
(2d) con 2 componentes, Ver Bernardi, C., Raugel, G .: Análisis de algunos elementos finitos para
el problema de Stokes. Matemáticas. Comp. 44, 71 - 79 (1985). Es un FE acoplado 2d, con el
El espacio polinomial es P 2
Función de bordes de burbujas normales 1 + 3 (P 2 ) y el grado de libertad es
6 valores en de los 2 componentes en los 3 vértices y el 3 flujo en los 3 bordes Entonces el número
grados de libertad es 9.

RT0, RT03d Elemento finito Raviart-Thomas de grado 0.


El caso 2d:

{ ∣ ∣ α 1K }
RT0 h = v ∈ H (div) ∣ v | K (x, y) = ∣ α2 +βK|Xy (6,15)
∣ ∀K ∈ T h ∣ K

El caso 3d:

{ ∣ ∣ α 1K }
∣ ∣ α2 ∣X
RT0 h = v ∈ H (div) ∣ ∀K ∈ T h v | K (x, y, z) = ∣ K +βK ∣y (6,16)
∣ ∣ α 3K ∣z
∣ ∣
D
donde al escribir div w = ∑
i = 1 ∂w i / ∂x i con w = (w i ) d i=1,

{ }
H (div) = w ∈ L 2 (Ω) d ∣ ∣div w ∈ L 2 (Ω)

y donde α 1
K, α 2K , α 3K , β K son números reales.

Página 173
173

RT0Ortho Raviart-Thomas Orthogonal, o elemento finito Nedelec tipo I de grado 0 en dimensión


2
{ ∣ ∣ α 1K }
RT0Orthoh = v ∈ H (rizo) ∣ v | K (x, y) = ∣ α 2 + β K | −y X (6,17)
∣ ∀K ∈ T h ∣ K

Edge03d 3d Nedelec elemento finito o elemento de borde de grado 0.


El caso 3d:
{ ∣ ∣ α 1K ∣ β 1K }
∣ ∣ ∣ ∣X
Edge0 h = v ∈ H (rizo) ∣ ∀K ∈ T h v | K (x, y, z) = ∣ α 2K + ∣ β 2K × ∣y (6,18)
∣ ∣ α 3K ∣ β 3K ∣z
∣ ∣ ∣
∣ ∂w 2 / ∂x 3 −∂w 3 / ∂x 2
donde escribiendo curlw = ∣ ∂w 3 / ∂x 1 −∂w 1 / ∂x 3 con w = (w i ) d
∣ i=1,
∣ ∂w 1 / ∂x 2 −∂w 2 / ∂x 1

{ ∣ 2 (Ω) d }
H (rizo) = w ∈ L 2 (Ω) d ∣
∣curl w ∈ L

yα1 K, α 2K , α 3K , β 1K , β 2K , β 3K son números reales.


Edge13d (necesita cargar "Element_Mixte3d", versión 3.34) 3d Nedelec elemento finito o Edge
Elemento de grado 1.

Edge23d (necesita cargar "Element_Mixte3d", versión 3.34) 3d Nedelec elemento finito o Edge
https://translate.googleusercontent.com/translate_f 153/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Elemento de grado 2.

P1nc elemento lineal a trozos continuo en el medio del borde solo en 2D (Crouzeix-Raviart Finite
Elemento 2d).

P2pnc cuadrático a trozos más un elemento de burbuja P3 con la continuidad de los 2 momentos en cada uno
edge (versión 3.59) (necesita cargar "Element_P2pnc"

RT1 (necesita cargar "Element_Mixte", versión 3.13)

{ ∣ ∣ α 1K }
RT1 h = v ∈ H (div) ∣ α 1K , α 2K , β K ∈ P 2 1, P 0 , v | K (x, y) = ∣ α2 +βK|Xy (6,19)
∣ ∀K ∈ T h ∣ K

RT1Ortho (necesita cargar "Element_Mixte", versión 3.13, dimensión 2)

{ ∣ ∣ α 1K }
RT1 h = v ∈ H (rizo) ∣ ∣ α2 + β K | −y (6,20)
∣ ∀K ∈ T h , α 1 K , α 2K , β K ∈ P 2 1, P 0 , v | K (x, y) = X
∣ K

RT2 (necesita cargar "Element_Mixte", versión 3.59

{ ∣ ∣ α 1K }
RT2 h = v ∈ H (div) ∣ α1 ∣ α2 +βK|Xy (6.21)
K, α 2K , β K ∈ P 2 2, P 1 , v | K (x, y) =
∣ ∀K ∈ T h ∣ K

RT2Ortho (necesita cargar "Element_Mixte", versión 3.59, dimensión 2)

{ ∣ ∣ α 1K }
RT2 h = v ∈ H (rizo) ∣ ∣ α2 + β K | −y (6.22)
∣ ∀K ∈ T h , α 1 K , α 2K , β K ∈ P 2 2, P 1 , v | K (x, y) = X
∣ K

BDM1 (necesita cargar "Element_Mixte", versión 3.13, dimensión 2) el Brezzi-Douglas-Marini


Elemento finito
BDM1 h = {v ∈ H (div) ∣∣ ∀K ∈ T h v |K ∈ P 2 1 } (6.23)

Página 174
174 CAPÍTULO 6. ELEMENTOS FINITOS

BDM1Ortho (necesita cargar "Element_Mixte", versión 3.13, dimensión 2) el Brezzi-Douglas-


Marini Orthogonal también llama Nedelec de tipo II, elemento finito

BDM1Ortho h = {v ∈ H (rizo) ∣∣ ∀K ∈ T h v |K ∈ P 2 1 } (6.24)

FEQF (necesita cargar "Element_QF", versión 3.45, dimensión 2 o 3) el elemento finito para almacenar
funcionan en los puntos de cuadratura predeterminados (por lo que la cuadratura es qf5pT en 2d y es qfV5 en 3d).
para más de cuadratura tiene el siguiente elemento finito de correspondencia, fórmula de cuadratura.

• FEQF1 ↦ → qf1pT,
• FEQF2 ↦ → qf2pT,
• FEQF5 ↦ → qf5pT,
• FEQF7 ↦ → qf7pT,
• FEQF9 ↦ → qf9pT,
• FEQF13d ↦ → qfV1,
• FEQF23d ↦ → qfV2,
• FEQF53d ↦ → qfV5

Puede utilizar este elemento de optimización para almacenar y reutilizar la función con una larga
fórmula en proceso no lineal en integral.

6.1 Uso de "fespace" en 2d


Con los espacios de elementos finitos 2d

https://translate.googleusercontent.com/translate_f 154/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

X h = {v ∈ H 1 (] 0,1 [ 2 ) | ∀K ∈ T h v |K ∈ P 1 }
. .
X ph = {v ∈ X h | v (| 0 0) = v (| 1 )}
.) = v (| 1 . ), v (|
M h = {v ∈ H 1 (] 0,1 [ 2 ) | ∀K ∈ T h v |K ∈ P 2 }
αK
R h = {v ∈ H 1 (] 0,1 [ 2 ) 2 | ∀K ∈ T h v | K (x, y) = ∣∣ βK + γ K | X y}

cuando T h es una malla de 10 × 10 del cuadrado unitario] 0,1 [ 2 , solo escribimos en FreeFem ++:

malla Th = cuadrado (10,10);


fespace Xh (Th, P1 ); // FE escalar
fespace Xph (Th, P1,
periódico = [[2, y], [4, y], [1, x], [3, x]]); // FE bi-periódica
fespace Mh (Th, P2 ); // FE escalar
fespace Rh (Th, RT0 ); // FE vectorial

donde Xh, Mh, Rh expresa espacios de elementos finitos (llamados espacios FE) X h , M h , R h , respectivamente.
Para usar las funciones FE u h , v h ∈ X h , p h , q h ∈ M h y U h , V h ∈ R h , escribimos:

Xh uh, vh;
Xph uph, vph;
Mh ph, qh;
Rh [Uxh, Uyh], [Vxh, Vyh];
Xh [ int ] Uh (10); // matriz de 10 funciones en Xh

Página 175
6.2. USO DE FESPACE EN 3D 175

Rh [ int ] [Wxh, Wyh] (10); // matriz de 10 funciones en Rh.


Ancho x alto [5] (0,5; 0,5) // la sexta función en el punto (0.5, 0.5)
Ancho x alto [5] [] // la matriz del grado de libertad de la función 6.

Las funciones U h , V h tienen dos componentes, por lo que tenemos

U h = ∣∣ Uxh
Uyh y V h = ∣∣ V xh V yh

6.2 Uso de fespace en 3d


Con los espacios de elementos finitos 3d

X h = {v ∈ H 1 (] 0,1 [ 3 ) | ∀K ∈ T h v |K ∈ P 1 }

. .
X ph = {v ∈ X h | v (| 0 0) = v (| 1 )}
.) = v (| 1 . ), v (|

M h = {v ∈ H 1 (] 0,1 [ 2 ) | ∀K ∈ T h v |K ∈ P 2 }

αK
R h = {v ∈ H 1 (] 0,1 [ 2 ) 2 | ∀K ∈ T h v | K (x, y) = ∣∣ βK + γ K | X y}

cuando T h es una malla de 10 × 10 × 10 de la unidad cúbica] 0,1 [ 2 , escribimos en FreeFem ++:

mesh3 Th = buildlayers (cuadrado (10,10), 10, zbound = [0,1]);


// etiqueta: 0 arriba, 1 abajo; 2 al frente, 3 a la izquierda, 4 atrás, 5: a la derecha
fespace Xh (Th, P1 ); // FE escalar
fespace Xph (Th, P1,
periódico = [[0, x, y], [1, x, y],
[2, x, z], [4, x, z],
[3, y, z], [5, y, z]]); // FE tripartita (ver Nota 6.1 )
fespace Mh (Th, P2 ); // FE escalar
fespace Rh (Th, RT03d ); // FE vectorial

donde Xh, Mh, Rh expresa espacios de elementos finitos (llamados espacios FE) X h , M h , R h , respectivamente.
Para definir y usar funciones FE u h , v h ∈ X h y p h , q h ∈ M h y U h , V h ∈ R h , escribimos:

https://translate.googleusercontent.com/translate_f 155/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Xh uh, vh;
Xph uph, vph;
Mh ph, qh;
Rh [Uxh, Uyh, Uyzh], [Vxh, Vyh, Vyzh];
Xh [ int ] Uh (10); // matriz de 10 funciones en Xh
Rh [ int ] [Wxh, Wyh, Wzh] (10); // matriz de 10 funciones en Rh.
Ancho x alto [5] (0.5, 0.5, 0.5) // la sexta función en el punto (0.5, 0.5, 0.5)
Ancho x alto [5] [] // la matriz del grado de
libertad de la función 6.

Las funciones U h , V h tienen tres componentes, por lo que tenemos

∣ Uxh ∣ VV xh
Uh= ∣ Uyh yVh= ∣ yh
∣ Uzh ∣ V zh

Página 176
176 CAPÍTULO 6. ELEMENTOS FINITOS

Nota 6.1 Un problema serio de la condición de contorno periódica es que la malla debe ser la misma au
cara de equivalencia, el generador de malla BuildLayer dividió las caras de cada cuadrilátero con el paso diagonal
atravesando el vértice con el número máximo, por lo que para asegurarse de tener la misma malla, ambos miran periódicamente
la numeración 2D en los bordes correspondientes debe ser compatible (por ejemplo, la misma variación). Por
Por defecto, la numeración de los vértices cuadrados es correcta.
Para cambiar la numeración de la malla, puede usar la función de cambio como:

{ // para limpiar la memoria ..


int [ int ] old2new (0: Th.nv-1); // matriz establecida en 0, 1, .., nv-1
fespace Vh2 (Th, P1);
Vh2 sorder = x + y; // elija un orden que aumente en 4 bordes cuadrados con x
oy
sort (sorder [], old2new); // construir la permutación inversa
int [ int ] new2old = old2newˆ-1; // Invertir la permutación
Th = cambio (Th, renumv = new2old); change}
}

el ejemplo completo está en examples ++ - 3d / periodic-3d.edp

6.3 Elementos finitos de Lagrange


6.3.1 Elemento P0
Para cada triángulo (d = 2) o tetraedro (d = 3) T k , la función base φ k en Vh (Th, P0) está dada por

φ k (x) = 1 si (x) ∈ T k , φ k (x) = 0 si (x) ∈ T k

Si escribimos

Vh (Th, P0 ); Vh fh = f (x, y);

entonces para los vértices q k i , i = 1,2, ..d + 1 en la figura 6.1 (a), f h se construye como


fh = f h (x, y) = ∑ F( yo q k yo) φ k
d+1
k

Consulte la figura 6.3 para ver la proyección de f (x, y) = sin (πx) cos (πy) en Vh (Th, P0 ) cuando la malla Th es
una cuadrícula de 4 × 4 de [−1,1] 2 como en la figura 6.2.

6.3.2 Elemento P1
Para cada vértice q i , la función base φ i en Vh (Th, P1) viene dada por

φ yo (x, y) = una k
https://translate.googleusercontent.com/translate_f 156/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

φ yo (q yo ) = 1, yoφ +yob(qkyoj x) =+ 0c ksi


i y para (x,
yo = j y) ∈ T k ,

La función base φ k 1 (x, y) con el vértice q k 1 en la figura 6.1 (a) en el punto p = (x, y) en el triángulo T k
simplemente coinciden con las coordenadas baricéntricas λ k
1 (coordenadas del área):

área del triángulo (p, q k 2 , q k 3 )


φ k 1 (x, y) = λ k
1 (x, y) = área del triángulo (q k 1 , q k 2 , q k 3 )

Página 177
6.3. ELEMENTOS FINITOS LAGRANGIANOS 177

k1
q q 1 k

(a) (B )

kT q k
q
3
k
pag
2

k T
q 2 k
q 3 k
q 6 k
q 4 k
q 5 k

Figura 6.1: P 1 y P 2 grados de libertad en el triángulo T k

Si escribimos

Vh (Th, P1 ); Vh fh = g (xy);

luego
nv

fh = f h (x, y) = ∑ f (q yo ) φ yo (x, y)
i=1

Consulte la figura 6.4 para ver la proyección de f (x, y) = sin (πx) cos (πy) en Vh (Th, P1 ).

Figura 6.2: Malla de prueba Th para proyección Figura 6.3: proyección a Vh (Th, P0)

6.3.3 elemento P2
Para cada vértice o punto medio q i . la función base φ i en Vh (Th, P2) está dada por
F
φ yo (x, y) = una k y 2 para (x, y) ∈ T k ,
yo + b kyo x + c kyo y + d kyo x 2 + mii kxy + f j

φ yo (q yo ) = 1, φ yo (q j ) = 0 si yo = j

La función base φ k 1 (x, y) con el vértice q k 1 en la figura 6.1 (b) está definida por la coordenada baricéntrica
nates:
φ k 1 (x, y) = λ k
1 (x, y) (2λ k 1 (x, y) - 1)

y para el punto medio q k 2


φ k 2 (x, y) = 4λ k
1 (x, y) λ k4 (x, y)

https://translate.googleusercontent.com/translate_f 157/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 178
178 CAPÍTULO 6. ELEMENTOS FINITOS

Si escribimos

Vh (Th, P2 ); Vh fh = f (xy);

luego
METRO

fh = f h (x, y) = ∑ f (q i ) φ i (x, y) (suma de todo vetex o punto medio)


i=1

Consulte la figura 6.5 para ver la proyección de f (x, y) = sin (πx) cos (πy) en Vh (Th, P2 ).

Figura 6.4: proyección a Vh (Th, P1) Figura 6.5: proyección a Vh (Th, P2)

6.4 Elemento no conforme P1


Consulte [28 ] para obtener más detalles; brevemente, ahora consideramos aproximaciones no continuas, por lo que perderemos
la propiedad
w h ∈ V h ⊂ H 1 (Ω)

Si escribimos

Vh (Th, P1nc ); Vh fh = f (xy);

luego
nv

fh = f h (x, y) = ∑ f (m i ) φ i (x, y) (suma sobre todos los puntos medios)


i=1

Aquí la función base φ i asociada con el punto medio m i = (q k i + q k i + 1 ) / 2 donde q k i es el i-ésimo


punto en T k , y asumimos que j + 1 = 0 si j = 3:

φ yo (x, y) = una k
yo + b kyo x + c ki y para (x, y) ∈ T k ,
φ i (m i ) = 1, φ i (m j ) = 0 si i = j

Estrictamente hablando, ∂φ i / ∂x, ∂φ i / ∂y contienen la distribución de Dirac ρδ ∂T k . Los cálculos numéricos


ignórelos automáticamente. En [28 ], hay una prueba de la estimación

( nv ∫ ) 1/2
∑ | ∇w - ∇w h | 2 dxdy = O (h)
Tk
k=1

Las funciones base φ k tienen las siguientes propiedades.

https://translate.googleusercontent.com/translate_f 158/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 179
6.5. OTRO ESPACIO FE 179

1. Para la forma bilineal a definida en ( 2.6) satisfaga

a (φ i , φ i )> 0, a (φ yo , φ j ) ≤ 0 si yo = j
nv
∑ una (φ yo , φ k ) ≥ 0
k=1

2. f ≥ 0 ⇒ u h ≥ 0

3. Si i = j, la función base φ i y φ j son L 2 -ortogonal:



φ yo φ j dxdy = 0 si i = j
Ω

que es falso para el elemento P 1 .

Consulte la figura 6.6 para ver la proyección de f (x, y) = sin (πx) cos (πy) en Vh (Th, P1nc ). Consulte la Fig. 6.6 para
la proyección de f (x, y) = sin (πx) cos (πy) en Vh (Th, P1nc ).

Figura 6.6: proyección a Vh (Th, P1nc) Figura 6.7: proyección a Vh (Th, P1b)

6.5 Otro espacio FE


Para cada triángulo T k ∈ T h , sea λ k 1 (x, y), λ k 2 (x, y), λ k 3 (x, y) el área coordinada del triángulo
(ver Fig. 6.1 ), y poner
β k (x, y) = 27λ k 1 (x, y) λ k 2 (x, y) λ k 3 (x, y) (6,25)
llamada función de burbuja en T k . La función de burbuja tiene la característica:

1. β k (x, y) = 0 si (x, y) ∈ ∂T k .
q k1 + q k2 + q k3
2. β k (q k b ) = 1 donde q k b es el baricentro 3 .

Si escribimos

Vh (Th, P1b ); Vh fh = f (xy);

luego nv nt

fh = f h (x, y) = ∑ f (q yo ) φ yo (x, y) +∑ f (q k b ) β k (x, y)


i=1 k=1

Consulte la figura 6.7 para ver la proyección de f (x, y) = sin (πx) cos (πy) en Vh (Th, P1b ).

Página 180
180 CAPÍTULO 6. ELEMENTOS FINITOS

6.6 Función FE con valor vectorial


Las funciones de R 2 a R N con N = 1 se denominan función escalar y se denominan vector valorado cuando N> 1.
Cuando N = 2

https://translate.googleusercontent.com/translate_f 159/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

espacio libre Vh (Th, [ P0 , P1 ]);

hacer el espacio
V h = {w = (w 1 , w 2 ) | w 1 ∈ V h (T h , P 0 ), w 2 ∈ V h (T h , P 1 )}

6.6.1 Elemento Raviart-Thomas


En el elemento finito de Raviart-Thomas RT0 h , el grado de libertad son los flujos a través de los bordes e de
la malla, donde el flujo de la función f: R 2 - → R 2 es ∫ mi
fn e , n e es la unidad normal del borde e.
Esto implica una orientación de todos los bordes de la malla, por ejemplo podemos usar la numeración global
de los vértices del borde y simplemente pasamos de números pequeños a grandes.
Para calcular el flujo, usamos una cuadratura con un punto de Gauss, el punto medio del borde.
Considere un triángulo T k con tres vértices (a, b, c). Denotemos los números de los vértices por i a , i b , i c ,
y definir los tres vectores de borde e 1 , e 2 , e 3 por sgn (i b −i c ) (b − c), sgn (i c −i a ) (c − a), sgn (i a −i b ) (a − b),
Obtenemos tres funciones básicas,

sgn (yo b - yo c ) sgn (yo c - yo a ) sgn (yo a - yo b )


φ k1 = (x - a), φ k 2=
(x - b), φ k 3=
(x - c), (6,26)
2|Tk| 2|Tk| 2|Tk|

donde | T k | es el área del triángulo T k . Si escribimos

Vh (Th, RT0 ); Vh [f1h, f2h] = [f1 (xy), f2 (x, y)];

luego
nt 6

fh = f h (x, y) = ∑ ∑ n i l j l | e i l | f j l (m i l ) φ i l j l
k=1 l=1

donde n i l j l es la j l -ésima componente del vector normal n i l ,

{b + c a+c b+a }
{m 1 , m 2 , m 3 } = , ,
2 2 2

y yo l = {1,1,2,2,3,3}, j l = {1,2,1,2,1,2} con el orden de l.

n3

T
norte
2

a
B
norte
1

Figura 6.8: vectores normales de cada borde

Página 181
6.6. VECTOR VALORADO FUNCIÓN FE 181

Ejemplo 6.1 malla Th = cuadrado (2,2);


fespace Xh (Th, P1 );
fespace Vh (Th, RT0 );
Xh uh, vh;
Vh [Uxh, Uyh];
[Uxh, Uyh] = [sin (x), cos (y)]; // ok función vectorial FE
vh = xˆ2 + yˆ2; // vh
Th = cuadrado (5,5); // cambiar la malla
// Xh es inmutable
uh = xˆ2 + yˆ2; // calcular en el nuevo Xh
Uxh = x; // error: imposible configurar solo 1 componente

https://translate.googleusercontent.com/translate_f 160/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
// de una función FE de vector.
vh = Uxh; // OK
// y ahora usa la malla 5x5
// pero el espacio libre de vh es siempre la malla 2x2
trama (uh, ps = "onoldmesh.eps"); // figura 6.9
uh = uh; // hacer una interpolación de vh (antiguo) de malla 5x5
// para obtener el nuevo vh en malla 10x10.
trama (uh, ps = "onnewmesh.eps"); // figura 6.10
vh ([x-1/2, y]) = xˆ2 + yˆ2; // interpolar vh = ((x - 1/2) 2 + y 2 )

Figura 6.9: Iso vh en malla 2 × 2 Figura 6.10: Iso vh en malla 5 × 5

Para obtener el valor en un punto x = 1, y = 2 de la función FE uh, o [Uxh, Uyh], se escribe

valor real ;
valor = uh (2,4); // obtener valor = uh (2,4)
valor = Uxh (2,4); // obtener valor = Uxh (2,4)
// ------ o ------
x = 1; y = 2;
valor = uh; // obtener valor = uh (1,2)
valor = Uxh; // obtener valor = Uxh (1,2)
valor = Uyh; // obtener valor = Uyh (1,2).

Para obtener el valor de la matriz asociada a la función FE uh, se escribe

Página 182
182 CAPÍTULO 6. ELEMENTOS FINITOS

valor real = uh [] [0]; // obtener el valor del grado de libertad 0


real maxdf = uh []. max; // valor máximo del grado de libertad
int tamaño = uh.n; // el número de grado de libertad
matriz real [int] (uh.n) = uh []; // copia la matriz de la función uh

Nota 6.2 Para una función de elemento finito no escalar [Uxh, Uyh] los dos arreglos Uxh [] y Uyh []
son la misma matriz, porque el grado de libertad puede tocar más de un componente.

6.7 Un interpolador rápido de elementos finitos


En la práctica, se pueden discretizar las ecuaciones variacionales mediante el método de elementos finitos. Entonces allí
será una malla para Ω 1 y otra para Ω 2 . El cálculo de integrales de productos de
las funciones definidas en diferentes mallas es difícil. Fórmulas de cuadratura e interpolaciones de uno
Se necesitan malla a otra en puntos de cuadratura. Presentamos a continuación el operador de interpolación
que hemos utilizado y que es nuevo, según nuestro leal saber y entender. Sea T 0 h = ∪ k T 0k , T h1 = ∪ k T 1k

https://translate.googleusercontent.com/translate_f 161/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
ser dos triangulaciones de un dominio Ω. Dejar
V (T ih ) = {C 0 (Ω i ∈ P 0 }, i = 0,1
h ): f | Ti k

ser los espacios de funciones afines continuas por partes en cada triangulación.
Sea f ∈ V (T 0 h ). El problema es encontrar g ∈ V (T 1 h ) tal que

g (q) = f (q) ∀q vértice de T 1 h

Aunque este es un problema aparentemente simple, es difícil encontrar un algoritmo eficiente en la práctica.
Proponemos un algoritmo de complejidad N 1 log N 0 , donde N i es el número de vértices de
Ti
h , y que es muy rápido para la mayoría de las aplicaciones 2D prácticas.

Algoritmo
El método consta de 5 pasos. Primero se construye un quadtree que contiene todos los vértices de la malla T 0 h tal que
en cada celda terminal hay al menos uno, y como máximo 4, vértices de T 0 h .
Para cada q 1 , vértice de T 1 h hacer:

Paso 1 Encuentre la celda terminal del quadtree que contiene q 1 .

Paso 2 Encuentra el vértice más cercano q 0


ja q 1 en esa celda.

Paso 3 Elija un triángulo T 0 ∈ T h0 que tiene q 0


k j para vértice.

Paso 4 Calcule las coordenadas baricéntricas {λ j } j = 1,2,3 de q 1 en T 0 k .

• - si todas las coordenadas baricéntricas son positivas, vaya al paso 5


• - de lo contrario, si una coordenada baricéntrica λ i es negativa, reemplace T 0 por el triángulo adyacente
k
opuesto q 0
iy vaya al paso 4.
• - de lo contrario, dos coordenadas baricéntricas son negativas, así que tome una de las dos al azar y
reemplazar kT 0por el triángulo adyacente como arriba.

Página 183
6.7. UN INTERPOLADOR DE ELEMENTOS FINITOS RÁPIDO 183

Paso 5 Calcule g (q 1 ) en T 0 k por interpolación lineal de f:

g (q 1 ) = ∑ λ j f (q 0
j)
j = 1,2,3

Final

Figura 6.11: Para interpolar una función en q 0 el conocimiento del triángulo que contiene
q 0 es necesario. El algoritmo puede comenzar en q 1 ∈ T 0
ky se detiene en el límite (línea gruesa)
porque la línea q 0 q 1 no está dentro de Ω. Pero si los agujeros también están triangulados (línea punteada) entonces
el problema no surge.

https://translate.googleusercontent.com/translate_f 162/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Es necesario resolver dos problemas:
• ¿Qué pasa si q 1 no está en Ω 0? ? Luego, el Paso 5 se detendrá con un triángulo límite. Entonces agregamos un paso
h
que prueban la distancia de q 1 con los dos bordes limítrofes adyacentes y seleccionan el más cercano,
y así sucesivamente hasta que la distancia aumenta.

• ¿Qué pasa si Ω 0 ¿No es convexo y el proceso de marcha del Paso 4 se bloquea en un límite? Por
h
construcción Los generadores de malla Delaunay-Voronoı siempre triangulan el casco convexo del
vértices del dominio. Así que nos aseguramos de que esta información no se pierda cuando T 0 h , T h1 están
construido y mantenemos los triángulos que están fuera del dominio en una lista especial. Por eso
en el paso 5 podemos usar esa lista para pasar sobre los agujeros si es necesario.

Nota 6.3 En algún momento, en casos excepcionales, el proceso de interpolación pierde algún punto, podemos cambiar el
algoritmo de búsqueda a través del método de búsqueda de variables globales

searchMethod = 0; // valor predeterminado para el algoritmo de búsqueda rápida


searchMethod = 1; // algoritmo de búsqueda seguro, use la fuerza bruta en caso de faltar
punto
// (la advertencia puede ser muy costosa en el caso de un punto de lote de un dominio externo)
searchMethod = 2; // usa siempre la fuerza bruta muy muy cara

Nota 6.4 El paso 3 requiere una matriz de punteros de modo que cada vértice apunte a un triángulo del
triangulación.

Página 184
184 CAPÍTULO 6. ELEMENTOS FINITOS

Nota 6.5 El operador = es el operador de interpolación de FreeFem ++, la función finita continua
Las relaciones se extienden por continuidad al exterior del dominio. Prueba el siguiente ejemplo

Ths de malla = cuadrado (10,10);


Thg de malla = cuadrado (30,30, [x * 3-1, y * 3-1]);
plot (Ths, Thg, ps = "solapaTh.eps", espera = 1);
fespace Ch (Ths, P2); fespace Dh (Ths, P2dc);
fespace Fh (Thg, P2dc);
Ch us = (x-0.5) * (y-0.5);
Dh frente a = (x-0,5) * (y-0,5);
Fh ug = nosotros, vg = vs;
trama (us, ug, espera = 1, ps = "us-ug.eps"); // ver figura 6.12
plot (vs, vg, wait = 1, ps = "vs-vg.eps"); // ver figura 6.13

Figura 6.12: Ampliación de un FE- Figura 6.13: Extensión de FE- discontinua


función función, ver advertencia 6

https://translate.googleusercontent.com/translate_f 163/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

6.8 Palabras clave: Problema y solución


Para FreeFem ++, un problema debe presentarse en forma variacional, por lo que necesitamos una forma bilineal a (u, v),
se debe agregar una forma lineal l (f, v) y posiblemente una forma de condición de contorno.

problema P (u, v) =
a (u, v) - l (f, v)
+ (condición de contorno);

Nota 6.6 Cuando desee formular el problema y resolverlo al mismo tiempo, puede utilizar
el keywork resuelve.

Página 185
6.8. PALABRAS CLAVE: PROBLEMA Y SOLUCIÓN 185

6.8.1 Forma débil y condición de contorno


Para presentar los principios de las Formulaciones Variacionales o también llamadas formas débiles de las PDE, permítanos
tome un problema modelo: una ecuación de Poisson con la condición de frontera de Dirichlet y Robin.
El problema es: Encuentre una función real definida en el dominio Ω de R d (d = 2,3) tal que

∂u
−∇. (Κ∇u) = f, en Ω, au + κ = b en Γ r , u = g en Γ d (6,27)
En
dónde

• si d = 2 entonces ∇. (Κ∇u) = ∂ x (κ∂ x u) + ∂ y (κ∂ y u) con ∂ x u = ∂u y ∂ y u = ∂u


∂x ∂y

• si d = 3 entonces ∇. (Κ∇u) = ∂ x (κ∂ x u) + ∂ y (κ∂ y u) + ∂ z (κ∂ z u) con ∂ x u = ∂u , ∂ y u = ∂u y,


∂x ∂y

∂ z u = ∂u∂z

• el borde Γ = ∂Ω se divide en Γ d y Γ n de manera que Γ d ∩ Γ n = ∅ y Γ d ∪ Γ n = ∂Ω,

• κ es una función positiva dada, tal que ∃κ 0 ∈ R, 0 <κ 0 ≤ κ.

• una función no negativa dada,

• una función dada.

Nota 6.7 Ésta es la condición de frontera de Neumann bien conocida si a = 0 y si Γ d está vacío. En
En este caso, la función aparece en el problema solo por sus derivadas, por lo que se define solo hasta un
constante (si u es una solución, entonces u + c también es una solución).

Sea va una función de prueba regular nula en Γ d , por integración por partes obtenemos

∫ ∫ ∫ ∂u ∫
- ∇. (Κ∇u) v dω = κ∇v.∇u dω - vκ dγ, = fv dω (6,28)
Ω Ω Γ En Ω

∂v ∂v ∂v ∂v ∂v
donde si d = 2 el ∇v.∇u = ( ∂u ∂x ∂x
+ ∂u∂y ∂y
), donde si d = 3 el ∇v.∇u = ( ∂u ∂x ∂x
+ ∂u∂y ∂y
+ ∂u∂z ∂z
),
y donde n es el unitario fuera de lo normal de Γ.
Ahora notamos que κ ∂u En = −au + b en Γ r y v = 0onΓ d y Γ = Γ d ∪ Γ n así

∫ ∂u ∫ ∫
- vκ = auv - bv
Γ En Γr Γr

El problema se convierte en:


Encuentre u ∈ V g = {w ∈ H 1 (Ω) / w = g en Γ d } tal que

∫ ∫ ∫ ∫
κ∇v.∇u dω + auv dγ = fv dω + bv dγ, ∀v ∈ V 0 (6,29)
Ω Γr Ω Γr

https://translate.googleusercontent.com/translate_f 164/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
donde V 0 = {v ∈ H 1 (Ω) / v = 0onΓ d }
Excepto en el caso de las condiciones de Neumann en todas partes, el problema ( 6.29 ) está bien planteado cuando
κ ≥ κ 0 > 0.

Nota 6.8 Si solo tenemos la condición de frontera de Neumann, el álgebra lineal nos dice que la mano derecha
El lado debe ser ortogonal al núcleo del operador para que exista la solución. Una forma de escribir
la condición de compatibilidad es:
∫ ∫
f dω + b dγ = 0
Ω Γ

Página 186
186 CAPÍTULO 6. ELEMENTOS FINITOS

y una forma de fijar la constante es resolver para u ∈ H 1 (Ω) tal que:

∫ ∫ ∫
εuv dω + κ∇v.∇u dω = fv dω + bv dγ, ∀v ∈ H 1 (Ω) (6,30)
Ω Ω Γr

donde ε es un pequeño parámetro (∼ κ 10 −10 | Ω | d ).

Observe que si la solución es de orden 1 ε


entonces la condición de compatibilidad no está satisfecha; de lo contrario,
obtén la solución tal que ∫ Ω
u = 0, también puede agregar un multiplicador de Lagrange para resolver la matemática real
Problema maical como en los ejemplos ++ - tutorial / Laplace-lagrange-mult.edp example.

En FreeFem ++, el problema bidimensional ( 6.29 ) se convierte en

problema Pw (u, v) =
int2d (Th) (kappa * (dx (u) * dx (v) + dy (u) * dy (v))) // ∫ κ∇v.∇u dω
Ω
+ int1d (Th, gn) (a * u * v) // ∫ auv dγ
Γr

- int2d (Th) (f * v) // ∫ Ω
fv dω
- int1d (Th, gn) (b * v) // ∫ Γr bv dγ
+ en (gd) (u = g); // u = g en Γ d

donde Th es una malla del dominio bidimensional Ω, y gd y gn son respectivamente el límite


etiqueta del límite Γ d y Γ n .
Y el problema tridimensional ( 6.29 ) se convierte en

macro Grad (u) [dx (u), dy (u), dz (u)] // EOM: definición de la macro 3d Grad
problema Pw (u, v) =
int3d (Th) (kappa * (Grad (u) '* Grad (v))) // ∫ Ω
κ∇v.∇u dω
+ int2d (Th, gn) (a * u * v) // ∫ Γ r auv dγ
- int3d (Th) (f * v) // ∫ fv dω
Ω
- int2d (Th, gn) (b * v) // ∫ bv dγ
Γr
+ en (gd) (u = g); // u = g en Γ d

donde Th es una malla del dominio tridimensional Ω, y gd y gn son respectivamente el límite


etiqueta del límite Γ d y Γ n .

6.9 Parámetros que afectan la resolución y el problema


Los parámetros son funciones FE reales o complejas, el número n de parámetros es par (n = 2 ∗ k),
los k primeros parámetros de función son desconocidos y los k últimos son funciones de prueba.

Nota 6.9 Si las funciones son parte del vectoriel FE, entonces debe dar todas las funciones del
FE vectorial en el mismo orden (ver el problema de laplaceMixte por ejemplo).

Nota 6.10 No mezcle la función FE de parámetros complejos y reales.

Error: 1 No se implementa la mezcla de fespace con diferentes condiciones de contorno periódicas. Entonces
Todos los espacios de elementos finitos utilizados para funciones de prueba o desconocidas en un problema, deben tener el mismo
tipo de condición de límite periódica o ninguna condición de límite periódica. No se da un mensaje limpio
y el resultado es impredecible, lo siento.

https://translate.googleusercontent.com/translate_f 165/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Los parámetros son:

Página 187
6.10. DEFINICIÓN DEL PROBLEMA 187

solucionador = LU, CG, Crout, Cholesky, GMRES, sparsesolver, UMFPACK ...


El solucionador predeterminado es sparsesolver (es igual a UMFPACK si no hay otro solucionador esparcido
definido) o se establece en LU si no hay disponible un solucionador disperso directo. El modo de almacenamiento de la matriz.
del sistema lineal subyacente depende del tipo de solucionador elegido; para LU la matriz
es la línea del cielo no simétrica, para Crout la matriz es simétrica con la línea del cielo, para Cholesky la
la matriz es definida positiva simétrica de la línea del cielo, para CG la matriz es positiva simétrica escasa,
y para GMRES, sparsesolver o UMFPACK la matriz es escasa.

eps = una expresión real. ε establece la prueba de parada para los métodos iterativos como CG. Tenga en cuenta que si ε es
negativo, entonces la prueba de parada es:

|| Hacha - b || <| ε |

si es positivo, la prueba de parada es

|ε|
|| Hacha - b || <
|| Ax 0 - b ||

init = expresión booleana, si es falsa o 0 se reconstruye la matriz. Tenga en cuenta que si la malla
cambia la matriz también se reconstruye.

precon = nombre de una función (por ejemplo, P) para configurar el preacondicionador. El prototipo del
la función P debe ser

func real [ int ] P ( real [ int ] & xx);

tgv = Valor enorme (10 30 ) utilizado para implementar las condiciones de contorno de Dirichlet, consulte la página 190 para obtener una descripción
ción.

tolpivot = establece la tolerancia del pivote en UMFPACK (10 −1 ) y, LU, Crout, Cholesky factorisa-
ción (10 −20 ).

tolpivotsym = establece la tolerancia del símbolo pivote en UMFPACK

estrategia = establece la estrategia UMFPACK de enteros (0 por defecto).

6.10 Definición del problema


Debajo de v está la función desconocida y w es la función de prueba.
Después del signo "=", se pueden encontrar sumas de:

• identificador (es); Este es el nombre dado anteriormente a la (s) forma (s) variacional (es) (tipo varf) para posibles
reutilizar.
Observe que el nombre en el "varf" de la función de prueba desconocida se ha olvidado, simplemente
usó el orden en la lista de argumentos para recordar el nombre como en una función C ++, vea la nota 6.15,

• los términos de la forma bilineal en sí: si K es una función dada,

• parte bilineal para mallas 3d Th


- int3d (Th) (K * v * w) = ∑ Kvw
T
T∈Th

https://translate.googleusercontent.com/translate_f 166/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 188
188 CAPÍTULO 6. ELEMENTOS FINITOS


- int3d (Th, 1) (K * v * w) = ∑ Kvw
T
T∈Th, T⊂Ω 1


- int3d (Th, conjunto de niveles = phi) (K * v * w) = ∑ Kvw
T, φ <0
T∈Th


- int3d (Th, l, levelset = phi) (K * v * w) = ∑ Kvw
T, φ <0
T∈Th, T⊂Ω l


- int2d (Th, 2,5) (K * v * w) = ∑ Kvw
(∂T∪Γ) ∩ (Γ 2 ∪Γ 5 )
T∈Th


- int2d (Th, 1) (K * v * w) = ∑ Kvw
T
T∈Th, T⊂Ω 1

∑ ∫
- int2d (Th, 2,5) (K * v * w) = Kvw
(∂T∪Γ) ∩ (Γ 2 ∪Γ 5 )
T∈Th

∑ ∫
- int2d (Th, conjunto de niveles = phi) (K * v * w) = Kvw
T, φ = 0
T∈Th


- int2d (Th, l, levelset = phi) (K * v * w) = ∑ Kvw
T, φ = 0
T∈Th, T⊂Ω l


- caras intactas (Th) (K * v * w) = ∑ Kvw
∂T
T∈Th


- caras intactas (Th, 1) (K * v * w) = ∑ Kvw
∂T
T∈Th, T⊂Ω 1

- Contribuyen a la matriz dispersa de tipo matriz que, ya sea declarada explícitamente


o no está construido por FreeFem ++.

• parte bilineal para mallas 2D Th

∑ ∫
- int2d (Th) (K * v * w) = Kvw
T
T∈Th


- int2d (Th, 1) (K * v * w) = ∑ Kvw
T
T∈Th, T⊂Ω 1


- int2d (Th, conjunto de niveles = phi) (K * v * w) = ∑ Kvw
T, φ <0
T∈Th

∑ ∫
- int2d (Th, l, levelset = phi) (K * v * w) = Kvw
T, φ <0
T∈Th, T⊂Ω l


- int1d (Th, 2,5) (K * v * w) = ∑ Kvw
(∂T∪Γ) ∩ (Γ 2 ∪Γ 5 )
T∈Th

∑ ∫
- int1d (Th, 1) (K * v * w) = Kvw
T
T∈Th, T⊂Ω 1


- int1d (Th, 2,5) (K * v * w) = ∑ Kvw
(∂T∪Γ) ∩ (Γ 2 ∪Γ 5 )
T∈Th

Página 189
6.10. DEFINICIÓN DEL PROBLEMA 189


- int1d (Th, conjunto de niveles = phi) (K * v * w) = ∑ Kvw
T, φ = 0
T∈Th

https://translate.googleusercontent.com/translate_f 167/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

- int1d (Th, l, levelset = phi) (K * v * w) = ∑ Kvw
T, φ = 0
T∈Th, T⊂Ω l


- intalledges (Th) (K * v * w) = ∑ Kvw
∂T
T∈Th


- ingresos (Th, 1) (K * v * w) = ∑ Kvw
∂T
T∈Th, T⊂Ω 1

- Contribuyen a la matriz dispersa de tipo matriz que, ya sea declarada explícitamente


o no está construido por FreeFem ++.

• el lado derecho de la PDE en 3d, los términos de la forma lineal: para funciones dadas K, f:

∑ ∫
- int3d (Th) (K * w) = Kw
T
T∈Th

∑ ∫
- int3d (Th, l) (K * w) = Kw
T
T∈Th, T∈Ω l

∑ ∫
- int3d (Th, conjunto de niveles = phi) (K * w) = Kw
T, φ <0
T∈Th


- int3d (Th, l, levelset = phi) (K * w) = ∑ Kw
T, φ <0
T∈Th, T⊂Ω l

∑ ∫
- int2d (Th, 2,5) (K * w) = Kw
(∂T∪Γ) ∩ (Γ 2 ∪Γ 5 )
T∈Th


- int2d (Th, nivel = phi) (K * w) = ∑ Kw
T, φ = 0
T∈Th


- int2d (Th, l, levelset = phi) (K * w) = ∑ Kw
T, φ = 0
T∈Th, T⊂Ω l

∑ ∫
- intallfaces (Th) (f * w) = fw
∂T
T∈Th

- un vector de tipo real [int]

• el lado derecho de la PDE en 2d, los términos de la forma lineal: para funciones dadas K, f:

∑ ∫
- int2d (Th) (K * w) = Kw
T
T∈Th


- int2d (Th, l) (K * w) = ∑ Kw
T
T∈Th, T∈Ω l

∑ ∫
- int2d (Th, nivel = phi) (K * w) = Kw
T, φ <0
T∈Th


- int2d (Th, l, levelset = phi) (K * w) = ∑ Kw
T, φ <0
T∈Th, T⊂Ω l

Página 190
190 CAPÍTULO 6. ELEMENTOS FINITOS


- int1d (Th, 2,5) (K * w) = ∑ Kw
(∂T∪Γ) ∩ (Γ 2 ∪Γ 5 )
T∈Th


- int1d (Th, nivel = phi) (K * w) = ∑ Kw
T, φ = 0
T∈Th

∑ ∫
- int1d (Th, l, levelset = phi) (K * w) = Kw
T, φ = 0
T∈Th, T⊂Ω l

∑ ∫
- intalledges (Th) (f * w) = fw

https://translate.googleusercontent.com/translate_f 168/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
T∈Th ∂T

- un vector de tipo real [int]

• Los términos de la condición de contorno:

- Una forma escalar "on" (para Dirichlet): en (1, u = g)


El significado es para todos los grados de libertad i del límite referido por "1", la diagonal
término de la matriz a ii = tgv con el terrible valor de geant tgv (= 10 30 por defecto) y
el lado derecho b [i] = ”(Π h g) [i]” × tgv, donde ”(Π h g) g [i]” es el nodo límite
valor dado por la interpolación de g.
observación, si tgv <0 entonces ponemos a 0 todos los términos de la línea i en la matriz, excepto la diagonal
término a ii = 1, y b [i] = ”(Π h g) [i]”. (versión ¿3.10).

- Una forma vectorial "on" (para Dirichlet): en (1, u1 = g1, u2 = g2) Si tiene vector
elemento finito torial como RT0, los 2 componentes están acoplados, por lo que tiene: b [i] =
”(Π h (g1, g2)) [i]” × tgv, donde Π h es el interpolante vectorial de elementos finitos.

- una forma lineal en Γ (para Neumann en 2d) -int1d (Th)) (f * w) o -int1d (Th, 3)) (
f * w)

- una forma bilineal en Γ o Γ 2 (para Robin en 2d) int1d (Th)) (K * v * w) o int1d (Th, 2)) (
K * v * w).

- una forma lineal en Γ (para Neumann en 3d) -int2d (Th)) (f * w) o -int2d (Th, 3)) (
f * w)

- una forma bilineal en Γ o Γ 2 (para Robin en 3d) int2d (Th)) (K * v * w) o int2d (Th, 2)) (
K * v * w).

Nota 6.11

• Si es necesario, los diferentes tipos de términos en la suma pueden aparecer más de una vez.

• la malla integral y la malla asociada a la función de prueba o función desconocida pueden ser diferentes
diferente en el caso de la forma lineal.

• Nx, Ny y Nz son los componentes normales.

Importante: no es posible escribir en la misma integral la parte lineal y la parte bilineal tal
como en int1d (Th) (K * v * w - f * w).

Página 191
6.11. INTEGRACION NUMERICA 191

6.11 Integración numérica


Sea D un dominio acotado de N dimensiones. Para un polinomio arbitrario f de grado r, si podemos
encontrar puntos particulares (en cuadratura) ξ j , j = 1, ···, J en D y constantes (en cuadratura) ω j tales que

L

f (x) = ∑ c l f (ξ l ) (6,31)
D
l=1

entonces tenemos una estimación de error (ver Crouzeix-Mignot (1984)), y luego existe una constante
C> 0 tal que,

∣∫ L ∣
∣ ∑ ∣
∣ f (x) - ω l f (ξ l ) ∣ ≤ C | D | h r + 1 (6,32)
∣ D ∣
∣ l=1 ∣

para cualquier función r + 1 veces continuamente diferenciable f en D, donde h es el diámetro de D y


| D | su medida (un punto en el segmento [q i q j ] se da como

https://translate.googleusercontent.com/translate_f 169/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

{(x, y) | x = (1 - t) q yo
x+ tq j x , y = (1 - t) q yo y+ tq j y , 0 ≤ t ≤ 1}).
nt
Para un dominio Ω h = ∑ k=1 T k , T h = {T k }, podemos calcular la integral sobre Γ h = ∂Ω h por


f (x) ds = int1d (Th) (f)
Γh

= int1d (Th, qfe = *) (f)


= int1d (Th, qforder = *) (f)

donde * representa el nombre de la fórmula de cuadratura o la precisión (orden) de la fórmula de Gauss.

Fórmula de cuantificación en un borde


L (qfe =) qforder = punto en [q i q j ] (= t) ωl exacto en P k , k =
1 qf1pE 2 1/2 | q yo q j | 1
2 qf2pE 3 (1 ± √1 / 3) / 2 | q yo q j | / 2 3
3 qf3pE 6 (1 ± √3 / 5) / 2 (18/5) | q yo q j | 5
1/2 (18/8) | q yo q j |
√ √ √
525 + 70 30 18− 30
4 qf4pE 8 (1 ± ) / 2. | q yo q j | 7
√ 35 √ 72

525−70 30 18+ 30
(1 ± ) / 2. | q yo q j |
√ 35

72

245 + 14 70 322-13 70
5 qf5pE 10 (1 ± 21
)/2 1800
| q yo q j | 9
64
| q yo q j |
√ 1/2 √
225

245-14 70 322 + 13 70
(1 ± 21
)/2 1800
| q yo q j |
2 qf1pElump 2 0 | q yo q j | / 2 1
+1 | q yo q j | / 2

donde | q yo q j | es la longitud del segmento q i q j . Para una parte Γ 1 de Γ h con la etiqueta "1", podemos calcular
la integral sobre Γ 1 por


f (x, y) ds = int1d (Th, 1) (f)
Γ1

= int1d (Th, 1, qfe = qf2pE) (f)

Página 192
192 CAPÍTULO 6. ELEMENTOS FINITOS

Las integrales sobre Γ 1 , Γ 3 están dadas por



f (x, y) ds = int1d (Th, 1,3) (f)
Γ 1 ∪Γ 3

Para cada triángulo T k = [q k 1 q k 2 q k 3 ], el punto P (x, y) en T k se expresa mediante la coordenada del área como
P (ξ, η):
∣ 1 q k 1X qyk 1 ∣ ∣ 1 X y ∣ ∣ 1 q k 1X qyk 1 ∣ ∣ 1 q k 1X q yk 1 ∣
1 ∣ ∣ ∣ ∣ ∣ ∣ ∣ ∣
|Tk|= ∣ 1 q k 2X qyk 2 ∣∣ D 1 = ∣∣ 1 q k 2X q yk 2 ∣ D 2 = ∣ 1 X y ∣∣ D 3 = ∣∣ 1 q k 2X q yk 2 ∣∣
2 ∣∣ ∣ ∣



∣ 1 q k3
∣ 1 q k 3X qyk 3 ∣ ∣ 1 q k 3X q yk3
∣ ∣ X qyk 3 ∣∣ ∣ 1
∣ X y ∣∣
1 1 1
ξ= D1/|Tk| η= D2/|Tk| entonces 1 - ξ - η = D3/|Tk|
2 2 2
nt
Para un dominio bidimensional o un borde de dominio tridimensional Ω h = ∑ k=1 T k , T h = {T k },
podemos calcular la integral sobre Ω h por

f (x, y) = int2d (Th) (f)
Ωh

= int2d (Th, qft = *) (f)


= int2d (Th, qforder = *) (f)

donde * representa el nombre de la fórmula de cuadratura o el orden de la fórmula de Gauss.

Fórmula cuantitativa en un triángulo


L qft = qforder = punto en T k ωl exacto en P k , k =
1 qf1pT 2 ( 13 , 13 ) |Tk| 1
3 qf2pT 3 (1 ,1 ) |Tk|/3 2
2 2

https://translate.googleusercontent.com/translate_f 170/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
( 12 , 0) |Tk|/3
(0, 1 ) |Tk|/3
2
7 qf5pT 6 (1 ,1 ) 0,225 |Tk| 5
√ 3 3 √ √
( 6− 15 15 ) (155− 15) | T k |
21
, 6− 21 1200
√ √ √
( 6− 15 15 ) (155− 15) | T k |
21
, 9 + 221 1200
√ √ √
( 9+2 15 15 ) (155− 15) | T k |
21 , 6− 21 1200
√ √ √
( 6+ 15 15 ) (155+ 15) | T k |
21
, 6+ 21 1200
√ √ √
( 6+ 15 15 ) (155+ 15) | T k |
21
, 9-2 21 1200
√ √ √
( 9-2 15 15 ) (155+ 15) | T k |
21 , 6+ 21 1200

3 qf1pTlump (0,0) |Tk|/3 1


(1,0) |Tk|/3
(0,1) |Tk|/3
9 qf2pT4P1 (1 ,3 ) | T k | / 12 1
4 4
(3 ,1 ) | T k | / 12
4 4
(0, 1 ) | T k | / 12
4
(0, 3 ) | T k | / 12
4
( 1 , 0) | T k | / 12
4
( 3 , 0) | T k | / 12
4
(1 ,1 ) |Tk|/6
4 4
(1 ,1 ) |Tk|/6
4 2
(1 ,1 ) |Tk|/6
2 4
15 qf7pT 8 ver [ 43] para más detalles 7
21 qf9pT 10 ver [ 43] para más detalles 9

Página 193
6.11. INTEGRACION NUMERICA 193

nt
Para un dominio tridimensional Ω h = ∑ k=1 T k , T h = {T k }, podemos calcular la integral sobre Ω h
por


f (x, y) = int3d (Th) (f)
Ωh

= int3d (Th, qfV = *) (f)


= int3d (Th, qforder = *) (f)

donde * representa el nombre de la fórmula de cuadratura o el orden de la fórmula de Gauss.

Fórmula de cuadatura en un tetraedro


L qfV = qforder = punto en T k ∈ R 3 ωl exacto en P k , k =
1 qfV1 2 (1,1 ,1 ) |Tk| 1
4 4 4
4 qfV2 3 G4 (0,58 ..., 0,13 ..., 0,13 ...) |Tk|/4 2
14 qfV5 6 G4 (0,72 ..., 0,092 ..., 0,092 ...) 0,073 ... | T k | 5
G4 (0,067 ..., 0,31 ..., 0,31 ...) 0,11 ... | T k |
G6 (0,45 ..., 0,045 ..., 0,45 ...) 0,042 ... | T k |
4 qfV1lump G4 (1,0,0) |Tk|/4 1

Donde G4 (a, b, b) tal que a + 3b = 1 es el conjunto de los cuatro puntos en coordenada baricéntrica

{(a, b, b, b), (b, a, b, b), (b, b, a, b), (b, b, b, a)}

y donde G6 (a, b, b) tal que 2a + 2b = 1 es el conjunto de los seis puntos en coordenada baricéntrica

{(a, a, b, b), (a, b, a, b), (a, b, b, a), (b, b, a, a), (b, a, b, a) , (b, a, a, b)}.

Nota 6.12 Estas fórmulas de cuadratura tetraédrica provienen de http://www.cs.kuleuven.be/


˜nines / research / ecf / mtables.html

https://translate.googleusercontent.com/translate_f 171/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Nota 6.13 Por defecto, usamos la fórmula que es exacta para polinomios de grado 5 en triángulos.
o bordes (en negrita en tres tablas).

Esto es posible agregar fórmulas de cuadratura propias con el uso del complemento "qf11to25" en el segmento,
triángulo o tetraedro. Las fórmulas de cuadratura en la dimensión D son una matriz bidimensional de tamaño
N q × (D + 1) tal que el valor D + 1 de la fila i = 0, ..., N p - 1 son w i , x i
1 , ..., x i D donde
D
w i es el peso del punto de cuadratura, y 1 - ∑ , x yo
k = 1 x yok 1 , ..., x i D es la coordenada baricéntrica
el punto de cuadratura.

// solo para prueba ... (versión 3.19-1)


cargar "qf11to25" // complemento de carga

// Cuadratura en segmento
real [int, int] qq1 = [
[0.5,0],
[0.5,1]];

QF1 qf1 (1, qq1); // def de las fórmulas de cuadratura qf1 en el segmento
// observación:
// 1 es el orden de la cuadratura exacta para polinomas de grado <1)

Página 194
194 CAPÍTULO 6. ELEMENTOS FINITOS

// Cuadratura sobre triángulo


real [int, int] qq2 = [
[1./3,0,0],
[1./3.,1,0],
[1./3.,0,1]];

QF2 qf2 (1, qq2); // def de fórmulas de cuadratura qf2 en triángulo


// observación:
// 1 es el orden de la cuadratura exacta para polinomas de grado <1)
// entonces debe tener = ⇒ ∑ w i = 1

// Cuadratura en tetraedro
real [int, int] qq3 = [
[1./4,0,0,0],
[1./4.,1,0,0],
[1./4.,0,1,0],
[1./4.,0,0,1]];

QF3 qf3 (1, qq3); // def de las fórmulas de cuadratura qf3 en get.
// observación:
// 1 es el orden de la cuadratura exacta para polinomas de grado <1)

// verificación en 1d final 2d ..
real I1 = int1d (Th, qfe = qf1) (xˆ2);
real I1l = int1d (Th, qfe = qf1pElump) (xˆ2);

real I2 = int2d (Th, qft = qf2) (xˆ2);


real I2l = int2d (Th, qft = qf1pTlump) (xˆ2);

cout << I1 << "==" << I1l << endl;


cout << I2 << "==" << I2l << endl;
afirmar (abs (I1-I1l) <1e-10);
afirmar (abs (I2-I2l) <1e-10);

la salida es

1,67 == 1,67
0.335 == 0.335

https://translate.googleusercontent.com/translate_f 172/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

6.12 Forma variacional, matriz dispersa, vector de datos PDE


En FreeFem ++ es posible definir formas variacionales y usarlas para construir matrices y vectores
y almacenarlos para acelerar el script (aquí 4 veces más rápido).
Por ejemplo, resolvamos el problema de conducción térmica de la sección 3.4.
La formulación variacional está en L 2 (0, T; H 1 (Ω)); buscaremos u n satisfaciendo

∫ u n - u n−1 ∫
∀w ∈ V 0 ; w + κ∇u n ∇w) + α (u n - u ue ) w = 0
Ω δt Γ

donde V 0 = {w ∈ H 1 (Ω) / w | Γ 24 = 0}.

Página 195
6.12. FORMA VARIACIONAL, MATRIZ ESPARTA, VECTOR DE DATOS PDE 195

Entonces, para codificar el método con las matrices A = (A ij ), M = (M ij ), y los vectores u n , b n , b, b ”, b cl


(notación si w es un vector, entonces w i es un componente del vector).

−1 1 {b " i si yo ∈ Γ 24
un=A bn, b = b 0 + Mu n − 1 , b ”= b cl , b n (6,33)
ε yo = b yo si no ∈ Γ 24

Donde con 1 ε
= tgv = 10 30 :

1
ε
si yo ∈ Γ 24 , yj = yo
A ij = ∫ ∫ (6,34)
w j w i / dt + k (∇w j .∇w i ) + αw j w i de lo contrario, si i ∈ Γ 24 , orj = i
Ω Γ 13
1
ε
si yo ∈ Γ 24 , yj = yo
M ij = ∫ (6,35)
w j w i / dt de lo contrario si i ∈ Γ 24 , orj = i
Ω

b 0, yo = αu ue w i (6,36)
Γ 13

b cl =u0 los datos iniciales (6,37)

// archivo Thermal-Fast.edp en examples ++ - tutorial

func fu0 = 10 + 90 * x / 6;
func k = 1.8 * (y <0.5) +0.2;
ue real = 25., alfa = 0,25, T = 5, dt = 0,1;

malla Th = cuadrado (30,5, [6 * x, y]);


fespace Vh (Th, P1);

Vh u0 = fu0, u = u0;

Cree tres formulaciones variacionales y construya las matrices A, M.

varf vtérmico (u, v) = int2d (Th) (u * v / dt + k * (dx (u) * dx (v) + dy (u) * dy (v)))
+ int1d (Th, 1,3) (alpha * u * v) + on (2,4, u = 1);

varf vthermic0 (u, v) = int1d (Th, 1,3) (alfa * ue * v);

varf vMass (u, v) = int2d (Th) (u * v / dt) + en (2,4, u = 1);

tgv real = 1e30;


matriz A = vtérmica (Vh, Vh, tgv = tgv, solucionador = CG);
matriz M = vMass (Vh, Vh);

Ahora, para construir el tamaño de la mano derecha, necesitamos 4 vectores.

real [int] b0 = vthermic0 (0, Vh); // parte constante de la RHS


real [int] bcn = vtérmico (0, Vh); // tgv en el nodo límite de Dirichlet (! = 0)
// tenemos para el nodo i: i ∈ Γ 24 ⇔ bcn [i] = 0

https://translate.googleusercontent.com/translate_f 173/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
real [int] bcl = tgv * u0 []; // la parte de condición de contorno de Dirichlet

Página 196
196 CAPÍTULO 6. ELEMENTOS FINITOS

Nota 6.14 La condición de frontera se implementa mediante penalización y el vector bcn contiene la
contribución de la condición de contorno u = 1, por lo que para cambiar la condición de contorno, tenemos que
multiplicar el vector bc [] por el valor actual f de la nueva condición de frontera término por término con el
operador. *. Sección 9. 6.2 Ejemplos ++ - tutorial / StokesUzawa.edp da un ejemplo real de
usando todas estas características.

Y la nueva versión del algoritmo es ahora:

ofstream ff ("datos térmicos");


para (t real = 0; t <T; t + = dt) {
real [int] b = b0; // para el RHS
b + = M * u []; // agregue la parte dependiente del tiempo
// bloquear parte del límite:
b = bcn? bcl: b; // hacer ∀i: b [i] = bcn [i]? bcl [i]: b [i];
u [] = Aˆ-1 * b;
ff << t << "" << u (3,0.5) << endl;
trama (u);
}
para (int i = 0; i <20; i ++)
cout << dy (u) (6.0 * i / 20.0,0.9) << endl;
plot (u, fill = true, wait = 1, ps = "thermic.eps");

Nota 6.15 Las funciones que aparecen en la forma variacional son formales y locales a la definición de varf.
nición, lo único importante es el orden en la lista de parámetros, como en

varf vb1 ([u1, u2], q) = int2d (Th) ((dy (u1) + dy (u2)) * q) + int2d (Th) (1 * q);
varf vb2 ([v1, v2], p) = int2d (Th) ((dy (v1) + dy (v2)) * p) + int2d (Th) (1 * p);

Para construir la matriz A a partir de la parte bilineal, la forma variacional a de tipo varf simplemente escribe:

A = a (Vh, Wh [, ...]);
// dónde
// Vh es "fespace" para los campos desconocidos con un número correcto de componentes
// Wh es "espacio libre" para los campos de prueba con un número correcto de componentes

Los posibles parámetros nombrados en "[, ...]" son

solucionador = LU, CG, Crout, Cholesky, GMRES, sparsesolver, UMFPACK ...


El solucionador predeterminado es GMRES.
El modo de almacenamiento de la matriz del sistema lineal subyacente depende del tipo de
solucionador elegido; para LU la matriz no es simétrica en la línea del cielo, para Crout la matriz es en el cielo
línea simétrica, para Cholesky la matriz es simétrica positiva definida en la línea del cielo, para CG la
matriz es escasa simétrica positiva, y para GMRES, sparsesolver o UMFPACK la matriz
es escaso.

factorizar = si es verdadero, entonces haga la factorización matricial para LU, Cholesky o Crout, el valor predeterminado
Es falso.

eps = una expresión real. ε establece la prueba de parada para los métodos iterativos como CG. Tenga en cuenta que si ε es
negativo, entonces la prueba de parada es:

|| Hacha - b || <| ε |

https://translate.googleusercontent.com/translate_f 174/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 197
6.12. FORMA VARIACIONAL, MATRIZ ESPARTA, VECTOR DE DATOS PDE 197

si es positivo, la prueba de parada es

|ε|
|| Hacha - b || <
|| Ax 0 - b ||

precon = nombre de una función (por ejemplo, P) para configurar el preacondicionador. El prototipo del
la función P debe ser

func real [ int ] P ( real [ int ] & xx);

tgv = Valor enorme (10 30 ) utilizado para implementar las condiciones de contorno de Dirichlet.

tolpivot = establece la tolerancia del pivote en UMFPACK (10 - 1) y, LU, Crout, Cholesky factori-
sation (10 −20 ).

tolpivotsym = establece la tolerancia del símbolo pivote en UMFPACK

estrategia = establece la estrategia UMFPACK de enteros (0 por defecto).

Nota 6.16 La línea de la matriz correspondiente al espacio Wh y la columna de la matriz


correspondiente al espacio Vh.

Para construir el vector dual b (de tipo real [int]) a partir de la parte lineal de la forma variacional a, simplemente

real b (Vh.ndof);
b = a (0, Vh);

Un primer ejemplo para calcular el área de cada triángulo K de la malla Th, simplemente haz:

fespace Nh (Th, P0); // la función espacial constante / triángulo


Nh areaK;
varf varea (no utilizado, chiK) = int2d (Th) (chiK);
etaK [] = varea (0, Ph);

Efectivamente, las funciones básicas del espacio Nh, son la función característica del elemento de Th,
y la numeración es la numeración del elemento, por lo que por construcción:

∫ ∫
etaK [i] = 1 | K yo = 1;
K yo

Ahora, podemos usar esto para calcular indicadores de error como en los ejemplos AdaptResidualErrorIndi-
cator.edp en ejemplos de directorio ++ - tutorial.
Primero en calcular una aproximación continua a la función h ”tamaño de malla de densidad” de la malla
Th.

fespace Vh (Th, P1);


Vh h;
recuento real [int] (Th.nv);
varf vmeshsizen (u, v) = intalledges (Th, qfnbpE = 1) (v);
varf vedgecount (u, v) = intalledges (Th, qfnbpE = 1) (v / lenEdge);
// cálculo del tamaño de la malla
// -----------------------------
count = vedgecount (0, Vh); // número de arista / vértice

Página 198
198 CAPÍTULO 6. ELEMENTOS FINITOS

https://translate.googleusercontent.com/translate_f 175/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
h [] = vmeshsizen (0, Vh); // suma longitud borde / vértice
h [] = h [] ./ cuenta; // longitud media borde / vértice

Para calcular el indicador de error para la ecuación de Poisson:

∫ ∫ Uh
ηK= h2 he|[ ]|2
K| (f + ∆u h ) | 2 + En
K ∂K

donde h K es el tamaño del borde más largo (hTriangle), h e es el tamaño del borde actual (lenEdge),
n lo normal.

fespace Nh (Th, P0); // la función espacial contante / triángulo


Nh etak;
varf vetaK (sin usar, chiK) =
intalledges (Th) (chiK * lenEdge * square (jump (Nx * dx (u) + Ny * dy (u))))
+ int2d (Th) (chiK * cuadrado (hTriángulo * (f + dxx (u) + dyy (u))));

etak [] = vetaK (0, Ph);

Agregamos optimización automática de expresiones por defecto, si esta optimización crea problemas, puede
eliminarse con la palabra clave optimizar como en el siguiente ejemplo:,

varf a (u1, u2) = int2d (Th, optimizar = 0) (dx (u1) * dx (u2) + dy (u1) * dy (u2))
+ en (1,2,4, u1 = 0) + en (3, u1 = 1);

o también puede realizar una optimización y eliminar la marca estableciendo optimizar = 2 (versión 3.38).
Observación, es posible construir una matriz de interpolación, como en el siguiente ejemplo:

malla TH = cuadrado (3,4);


malla th = cuadrado (2,3);
malla Th = cuadrado (4,4);

fespace VH (TH, P1);


fespace Vh (th, P1);
espacio libre Wh (Th, P1);

matriz B = interpolar (VH, Vh); // construir matriz de interpolación Vh-> VH


matriz BB = interpolar (Wh, Vh); // construir matriz de interpolación Vh-> Wh

y después de algunas operaciones en matrices dispersas están disponibles, por ejemplo

int N = 10;
real [int, int] A (N, N); // una matriz completa
real [int] a (N), b (N);
A = 0;
para (int i = 0; i <N; i ++)
{
A (yo, yo) = 1 + yo;
si (i + 1 <N) A (yo, yo + 1) = - yo;
a [i] = i;
}
b = A * b;
cout << "xxxx \ n";
matriz dispersaA = A;
cout << sparseA << endl;
sparseA = 2 * sparseA + sparseA ';

Página 199
6.13. MATRIZ DE INTERPOLACIÓN 199

sparseA = 4 * sparseA + sparseA * 5;


matriz sparseB = sparseA + sparseA + sparseA; ;
cout << "sparseB =" << sparseB (0,0) << endl;

6.13 Matriz de interpolación


También es posible almacenar la matriz de un operador de interpolación lineal de un espacio de elementos finitos
https://translate.googleusercontent.com/translate_f 176/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
V h a otro W h para interpolar (W h , V h , ...) una función. Tenga en cuenta que el finito continuo
las funciones se extienden por continuidad fuera del dominio.
Los parámetros nombrados de la función interpolar son:

inside = establezca true para crear una extensión cero.

t = establecer verdadero para obtener la matriz transpuesta

op = establece un número entero escrito a continuación

0 el valor predeterminado e interpolar la función


1 interpolar la ∂ x
2 interpolar la ∂ y
3 interpolar la ∂ z

U2Vc = establece cuál es el componente de W h vienen en V h en el proceso de interpolación en una matriz int así
el tamaño de la matriz es el número de componente de W h , si el put −1 entonces el componente se establece en
0, como en el siguiente ejemplo: (por defecto, el número de componente no cambia).

fespace V4h (Th4, [P1, P1, P1, P1]);


fespace V3h (Th, [P1, P1, P1]);
int [ int ] u2vc = [1,3, -1]; // -1 => poner cero en el componente
matriz IV34 = interpolar (V3h, V4h, interior = 0, U2Vc = u2vc); // V3h <- V4h
V4h [a1, a2, a3, a4] = [1,2,3,4];
V3h [b1, b2, b3] = [10,20,30];
b1 [] = IV34 * a1 [];

Entonces aquí tenemos: b1 == 2, b2 == 4, b3 == 0. .

Ejemplo 6.2 (mat interpol.edp)

malla Th = cuadrado (4,4);


malla Th4 = cuadrado (2,2, [x * 0,5, y * 0,5]);
plot (Th, Th4, ps = "ThTh4.eps", espera = 1);
fespace Vh (Th, P1); fespace Vh4 (Th4, P1);
espacio libre Wh (Th, P0); espacio libre Wh4 (Th4, P0);

matriz IV = interpolar (Vh, Vh4); // aquí la función es


// extendido por la continuidad
cout << "IV Vh <-Vh4" << IV << endl;
Vh v, vv; Vh4 v4 = x * y;
v = v4; vv [] = IV * v4 []; // aquí v == vv =>
real [int] diff = vv [] - v [];
cout << "|| v - vv || =" << diff.linfty << endl;
afirmar (diff.linfty <= 1e-6);

Página 200
200 CAPÍTULO 6. ELEMENTOS FINITOS

matriz IV0 = interpolar (Vh, Vh4, interior = 1); // aquí la función es


// extendido por cero
cout << "IV Vh <-Vh4 (dentro = 1)" << IV0 << endl;
matriz IVt0 = interpolar (Vh, Vh4, inside = 1, t = 1);
cout << "IV Vh <-Vh4ˆt (inside = 1)" << IVt0 << endl;
matriz IV4t0 = interpolar (Vh4, Vh);
cout << "IV Vh4 <-Vhˆt" << IV4t0 << endl;
matriz IW4 = interpolar (Wh4, Wh);
cout << "IV Wh4 <-Wh" << IW4 << endl;
matriz IW4V = interpolar (Wh4, Vh);
cout << "IV Wh4 <-Vh" << IW4 << endl;

Construya la matriz de interpolación A en una matriz de puntos (xx [j], yy [j]), i = 0,2 aquí

a yo j = dop (w yo
c (xx [j], yy [j]))

https://translate.googleusercontent.com/translate_f 177/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
donde w i es la función básica de elementos finitos, c el número de componente, dop el tipo de operador diff
como en op def.

real [int] xx = [. 3, .4], yy = [. 1, .4];


int c = 0, dop = 0;
matriz Ixx = interpolar (Vh, xx, yy, op = dop, composante = c);
cout << Ixx << endl;
Vh ww;
real [int] dd = [1,2];
ww [] = Ixx * dd;

Ejemplo 6.3 (schwarz2.edp)


A continuación se muestra cómo implementar con una matriz de interpolación un algoritmo de descomposición de dominio.
Ritmo basado en el método de Schwarz con condiciones de Robin.
Dada una partición no superpuesta ¯Ω = ¯Ω 0 ∪ ¯Ω 1 con Ω 0 ∩ Ω 1 = ∅, Σ: = ¯Ω 0 ∩ ¯Ω 1 el algoritmo es

∂ (u 1 - u 0 )
−∆u i = f en Ω i , i = 0,1, + α (u 1 - u 0 ) = 0 en Σ.
En

Lo mismo en forma variacional es:

∫ ∫
∫ ∇u i · ∇v + αu yo v = fv
Ω yo
Σ Ω yo
∫ ∫
- (∇u j · ∇v - fv) + αu j v, ∀v ∈ H 1
0 (Ω), i, j = [0,1] ∪ [1,0]
Ωj Σ

Para discretizar con el espacio triangular de elementos finitos lagrangianos P 1 V h simplemente reemplace H 1 0 (Ω) por
V h (Ω 0 ) ∪ V h (Ω 1 ). Entonces la dificultad es calcular ∫ Ωj
∇u j · ∇v cuando v es una función básica de V h (Ω i ),
i = j. Se hace de la siguiente manera (con Γ = ∂Ω)

// del archivo schwarz2.edp


espacio libre Vh0 (Th [0], P1), Vh1 (Th [1], P1);
Vh0 u0 = 0; Vh1 u1 = 0;

macro grad (u) [dx (u), dy (u)] //


varf a (u, v) = int2d (Th [i]) (grad (u) '* grad (v)) + int1d (Th [i], Interface) (alpha * u * v)
+ activado (Gamma, u = 0);
varf b (u, v) = int2d (Th [i]) (f * v) + on (Gamma, u = 0);

Página 201
6.14. CONECTIVIDAD DE ELEMENTOS FINITOS 201

varf du1dn (u, v) = - int2d (Th [1]) (grad (u1) '* grad (v) -f * v) + int1d (Th [1], Sigma) (alpha * u1 * v)
+ activado (Gamma, u = 0);
varf du0dn (u, v) = - int2d (Th [0]) (grad (u0) '* grad (v) -f * v) + int1d (Th [0], Sigma) (alpha * u0 * v)
+ activado (Gamma, u = 0);

matriz I01 = interpolar (Vh1, Vh0);


matriz I10 = interpolar (Vh0, Vh1);

matriz [ int ] A (2);


A [0] = a (Vh0, Vh0);
A [1] = a (Vh1, Vh1);

para ( int iter = 0; iter <Niter; iter ++)


{
// Resolver el [0]
{
real [ int ] b0 = b (0, Vh0);
real [ int ] Du1dn = du1dn (0, Vh1);
real [ int ] Tdu1dn (Vh0.ndof); Tdu1dn = I01 '* Du1dn;
b0 + = Tdu1dn;
u0 [] = A [0] ˆ-1 * b0;
}
// Resolver el [1]
{
real [ int ] b1 = b (0, Vh1);

https://translate.googleusercontent.com/translate_f 178/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
real [ int ] Du0dn = du0dn (0, Vh0);
real [ int ] Tdu0dn (Vh1.ndof); Tdu0dn = I10 '* Du0dn;
b1 + = Tdu0dn;
u1 [] = A [1] ˆ-1 * b1;
}
plot (u0, u1, cmm = "iter =" + iter);
}

6.14 Conectividad de elementos finitos


Aquí, mostramos cómo obtener información sobre un espacio de elementos finitos W h (T n , ∗), donde “*” puede ser P1,
P2, P1nc, etc.

• Wh.nt da el número de elementos de W h

• Wh.ndof da el número de grados de libertad o desconocido

• Wh.ndofK da el número de grados de libertad en un elemento

• Wh (k, i) da el número de i-ésimo grados de libertad del elemento k.

Vea el siguiente ejemplo:

Ejemplo 6.4 (FE.edp) malla Th = cuadrado (5,5);


espacio libre Wh (Th, P2);
cout << "nb de grado de libertad : "<< Wh.ndof << endl;
cout << "nb de grado de libertad / ELEMENTO:" << Wh.ndofK << endl;
int k = 2, kdf = Wh.ndofK ;; // elemento 2

Página 202
202 CAPÍTULO 6. ELEMENTOS FINITOS

cout << "df del elemento" << k << ":";


para ( int i = 0; i <kdf; i ++) cout << Wh (k, i) << "";
cout << endl ;

La salida es:

Número de nodos = 121


Nb de DF = 121
FESpace: Gibbs: horizonte antiguo = 5841 horizonte nuevo = 1377
nb de grado de libertad : 121
nb de grado de libertad / ELEMENTO: 6
df del elemento 2:78 95 83 87 79 92

https://translate.googleusercontent.com/translate_f 179/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 203

Capítulo 7

Visualización

Los resultados creados por el método de elementos finitos pueden ser un gran conjunto de datos, por lo que es muy importante
hazlos fáciles de entender. Hay dos formas de visualización en FreeFem ++: Una, la predeterminada
vista, soporta el dibujo de mallas, isovalores de funciones FE reales y de campos vectoriales, todo por
el diagrama de comando (consulte la Sección 7. 1 a continuación). Con fines de publicación, FreeFem ++ puede almacenar estos
trazados como archivos postscript.
Otro método es utilizar herramientas externas, por ejemplo, gnuplot (ver Sección 7.2) , medit (ver Sección
7.3 ) usando el sistema de comando para ejecutarlos y / o guardar los datos en archivos de texto.

7.1 Trazar
Con el comando plot, se pueden mostrar mallas, isovalores de funciones escalares y campos vectoriales.
Los parámetros del comando de trazado pueden ser, mallas, funciones FE reales, matrices de 2 FE reales
funciones, matrices de dos matrices de doble, para trazar respectivamente una malla, una función, un campo vectorial o
una curva definida por las dos matrices de double.

Nota 7.1 La longitud de una flecha siempre está obligada a estar en [5 ‰, 5%] del tamaño de la pantalla, para ver
algo (de lo contrario, solo se verá como un puercoespín).

Los parámetros son

esperar = expresión booleana para esperar o no (por defecto, no esperar). Si es cierto, esperamos un evento de teclado.
o evento del mouse, responden a un evento con los siguientes caracteres

entrar intenta mostrar la trama

https://translate.googleusercontent.com/translate_f 180/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
p parcela anterior (10 parcelas guardadas)
? muestra esta ayuda

+, - acercar / alejar alrededor del cursor 3/2 veces


= restablecer vue
r refrescar gráfico
teclas especiales arriba, abajo, izquierda, derecha para traducir

3 teclas de gráfico de cambio 3d / 2d:

z, Z) zoom focal unzoom


Interruptor H, h aumenta o disminuye la escala Z del gráfico
movimiento del mouse

203

Página 204
204 CAPÍTULO 7. VISUALIZACIÓN

- botón izquierdo rotar


- zoom del botón derecho (ctrl + botón en mac)
- botón derecho + alt tanslate (alt + ctrl + botón en mac)

a, A aumentar o disminuir el tamaño de la flecha

B cambiar entre mostrar mallas de borde o no

yo, actualizo o no: el límite mínimo / máximo de las funciones a la ventana

n, N disminuyen o aumentan el número de matriz de valores iso


b cambiar entre trazado en blanco y negro o en color

g cambiar entre trazado en gris o en color

f cambiar entre llenado iso o línea iso

l cambio entre iluminación o no

v cambiar entre mostrar o no el valor numérico de los colores

m cambiar entre mostrar o no mallas

w volcado de ventana en el archivo ffglutXXXX.ppm

* mantener / desmantelar el punto de vista para la próxima trama


k datos complejos / cambiar el tipo de vista

ESC cierra el proceso de gráficos antes de la versión 3.22, después de que no hay forma de cerrar.
de lo contrario no hagas nada.

ps = expresión de cadena para el nombre del archivo para guardar el gráfico en posdata (lo siento, no guardar de 3d
gráfico)

coef = el tamaño de la flecha del vector entre la unidad de la flecha y la unidad del dominio.

fill = color de relleno entre isovalores (obligatorio del elemento finito P0).

cmm = expresión de cadena para escribir la ventana gráfica en

valor = para trazar el valor de las isolíneas y el valor de las flechas vectoriales.

Aspectratio = boolean para asegurarse de que la relación de aspecto de la trama se mantenga o no.

bb = matriz de 2 matrices (como [[0.1,0.2], [0.5,0.6]]), para establecer el cuadro delimitador y especificar una
vista parcial donde la caja definida por los dos puntos de esquina [0.1,0.2] y [0.5,0.6].

nbiso = (int) establece el número de isovalores (20 por defecto)

nbarrow = (int) establece el número de colores de los valores de flecha (20 por defecto)

viso = establece la matriz de isovalores (una matriz real [int] de valores crecientes)

https://translate.googleusercontent.com/translate_f 181/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

varrow = establece la matriz de valores de flechas de color (una matriz real [int])

bw = (bool) establece o no la trama en color blanco y negro.

gray = (bool) establece o no la trama en color gris.

Página 205
7.1. GRÁFICO 205

hsv = (matriz de flotante) al color definido del valor 3 * n en el modelo de color HSV declarado, por ejemplo, por

colores [int] reales = [h1, s1, v1, ..., hn, vn, vn];

donde hi, si, vi es el i-ésimo color para definir la tabla de colores.

boundary = (bool) para trazar o no el límite del dominio (verdadero por defecto).

dim = (int) establece el dim del gráfico 2d o 3d (2 por defecto)

add = <b> No utilizado

prev = <b> establece el estado gráfico predeterminado en el estado anterior

ech = <d> No utilizado

ZScale = <d> No utilizado

WhiteBackground = <b> No utilizado

OpaqueBorders = <b> No utilizado

BorderAsMesh = <b> No utilizado

ShowMeshes = <b> No utilizado

ColorScheme = <l> No utilizado

ArrowShape = <l> No utilizado

ArrowSize = <d> No utilizado

ComplexDisplay = <l> No utilizado

LabelColors = <b> No utilizado

ShowAxes = <b> No utilizado

CutPlane = <b> No utilizado

CameraPosition = No utilizado

CameraFocalPoint = No utilizado

CameraViewUp = No utilizado

CameraViewAngle = <d> No utilizado

CameraClippingRange = No utilizado

CutPlaneOrigin = No utilizado

CutPlaneNormal = No utilizado

WindowIndex = establece la ventana de saturación para la visualización de gráficos de múltiples ventanas.

https://translate.googleusercontent.com/translate_f 182/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 206
206 CAPÍTULO 7. VISUALIZACIÓN

Por ejemplo:

real [ int ] xx (10), yy (10);


malla Th = cuadrado (5,5);
fespace Vh (Th, P1 );
Vh uh = x * x + y * y, vh = -yˆ2 + xˆ2;
int i;
// calcular un corte
para (i = 0; i <10; i ++)
{
x = i / 10 .; y = i / 10 .;
xx [i] = i;
aa [i] = uh; // valor de uh en el punto (i / 10., i / 10.)
}
plot (Th, uh, [uh, vh], valor = verdadero, ps = "tres.eps", espera = verdadero); // figura 7.1
// zoom en el cuadro definido por los dos puntos de esquina [0.1,0.2] y [0.5,0.6]
plot (uh, [uh, vh], bb = [[0.1,0.2], [0.5,0.6]],
esperar = verdadero, gris = 1, relleno = 1, valor = 1, ps = "threeg.eps"); // figura 7.2
plot ([xx, yy], ps = "likegnu.eps", espera = verdadero); // figura 7.3

IsoValue IsoValue
0,05 -0,105263
0,15 0.0526316
0,25 0.157895
0,35 0,263158
0,45 0.368421
0,55 0,473684
0,65 0.578947
0,75 0,684211
0,85 0,789474
0,95 0.894737
1.05 1
1,15 1.10526
1,25 1.21053
1,35 1.31579
1,45 1,42105
1,55 1.52632
1,65 1,63158
1,75 1.73684
1,85 1.84211
1,95 2.10526

Valor de Vec Valor de Vec


0 0
0,1 0,1
0,2 0,2
0,3 0,3
0.4 0.4
0,5 0,5
0,6 0,6
0,7 0,7
0,8 0,8
0,9 0,9
1 1
1.1 1.1
1.2 1.2
1.3 1.3
1.4 1.4
1,5 1,5
1,6 1,6
1,7 1,7
1.8 1.8
1,9 1,9

Figura 7.1: malla, isovalor y vector Figura 7.2: ampliación en gris del isovalor,
y vector

Para cambiar la tabla de colores y elegir el valor de la línea iso puede hacer:

// de: http://en.wikipedia.org/wiki/HSV_color_space
// El modelo HSV (tono, saturación, valor),
// define un espacio de color en términos de tres componentes constituyentes:
//
// Espacio de color HSV como rueda de colores 7.4
// Matiz, el tipo de color (como rojo, azul o amarillo):
// Varía de 0-360 (pero normalizado a 0-100% en algunas aplicaciones aquí)
// Saturación, la "vitalidad" del color: varía de 0 a 100%
// Cuanto menor es la saturación de un color, más "grisáceo" está presente.
// y cuanto más descolorido aparecerá el color.
// Valor, el brillo del color:
// Varía de 0 a 100%

Página 207

https://translate.googleusercontent.com/translate_f 183/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
7.1. GRÁFICO 207

Figura 7.3: Traza un corte de uh. Tenga en cuenta que se puede obtener un refinamiento del mismo en
combinación con gnuplot

//
real [int] colorhsv = [ // modelo de color hsv
4./6., 1, 0.5, // azul oscuro
4./6., 1, 1, // azul
5./6., 1, 1, // magenta
1, 1., 1, // rojo
1, 0,5, 1 // luz roja
];
viso real [int] (31);

para (int i = 0; i <viso.n; i ++)


viso [i] = i * 0,1;

trazar (uh, viso = viso (0: viso.n-1), valor = 1, llenar = 1, esperar = 1, hsv = colorhsv);

IsoValue
-0
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
1.4
1,5
1,6
1,7
1.8
1,9
2
2.1
2.2
2.3
2.4
2.5
2.6
2,7
2.8
2.9
3

Figura 7.4: cilindro de color hsv Figura 7.5: isovalor con otra tabla de colores

Página 208
208 CAPÍTULO 7. VISUALIZACIÓN

7.2 enlace con gnuplot


El ejemplo 3 .2 muestra cómo generar un gráfico gnu a partir de un archivo FreeFem ++. Presentemos aquí otro
técnica que tiene la ventaja de estar en línea, es decir, no es necesario salir de FreeFem ++ para
generar un gráfico gnu. Pero esto funciona solo si gnuplot1 está instalado y solo en una computadora Unix.
Agregue al ejemplo anterior:

https://translate.googleusercontent.com/translate_f 184/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

{ // archivo para gnuplot


ofstream gnu ("plot.gp");
para (int i = 0; i <= n; i ++)
{
gnu << xx [i] << "" << yy [i] << endl;
}
} // el archivo plot.gp está cerca porque la variable gnu es eliminar

// para llamar al comando gnuplot y esperar 5 segundos (gracias al comando unix)


// y hacer un diagrama de posdata
exec ("echo 'plot \" plot.gp \ "wl \
pausa 5 \
establecer posdata de término \
establecer salida \ "gnuplot.eps \" \
replot \
salir '| gnuplot ");

2
"plot.gp"

1,5

0,5

0
0 5 10 15 20

Figura 7.6: Traza un corte de uh con gnuplot

7.3 enlace con medit


Como se dijo anteriormente, medit 2 es un paquete de visualización gratuito de Pascal Frey que utiliza OpenGL. Entonces puedes
ejecute el siguiente ejemplo.

Observación: Ahora el software medit está incluido en FreeFem ++ con el nombre ffmedit.
Ahora con la versión 3.2 o mejor

cargar "medit"
malla Th = cuadrado (10,10, [2 * x-1,2 * y-1]);
fespace Vh (Th, P1);
Vh u = 2-x * xy * y;
medit ("mm", Th, u);

1http://www.gnuplot.info/

2http://www-rocq.inria.fr/gamma/medit/medit.html

Página 209
7.3. ENLACE CON MEDIT 209

https://translate.googleusercontent.com/translate_f 185/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 7.7: diagrama de medit

Antes:

malla Th = cuadrado (10,10, [2 * x-1,2 * y-1]);


fespace Vh (Th, P1);
Vh u = 2-x * xy * y;
savemesh (Th, "mm", [x, y, u * .5]); // guardar el archivo mm.points y mm.faces
// para meditar
// construir un archivo mm.bb
{
archivo ofstream ("mm.bb");
archivo << "2 1 1" << u []. n << "2 \ n";
para ( int j = 0; j <u []. n; j ++)
archivo << u [] [j] << endl;
}
// llamar al comando medit
exec ("ffmedit mm");
// limpiar archivos en unix OS
exec ("rm mm.bb mm. caras mm. puntos ");

Página 210
210 CAPÍTULO 7. VISUALIZACIÓN

https://translate.googleusercontent.com/translate_f 186/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 211

Capítulo 8

Algoritmos y optimización

El ejemplo completo está en el archivo algo.edp.

8.1 gradiente conjugado / GMRES


Supongamos que queremos resolver el problema de Euler (aquí x no tiene nada que ver con la variable reservada
para la primera coordenada en FreeFem ++): encuentre x ∈ R n tal que

(∂J )
∇J (x) = (X) =0 (8,1)
∂x i

donde J es un funcional (para minimizar, por ejemplo) de R n a R.


Si la función es convexa, podemos usar el gradiente conjugado para resolver el problema, y solo necesitamos
la función (llamada dJ, por ejemplo) que calcula ∇J, por lo que los parámetros son el nombre de ese
función con prototipo

https://translate.googleusercontent.com/translate_f 187/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
func real [ int ] dJ ( real [ int ] & xx);
que calculan ∇J, y un vector x de tipo (por supuesto, el número 20 se puede cambiar)
real [ int ] x (20);
para inicializar el proceso y obtener el resultado.

Dado un valor inicial x (0) , un número máximo i max de iteraciones y una tolerancia de error 0 <ϵ <1:
Pon x = x (0) y escribe

NLCG (∇J, x, precon = M, nbiter = i max , eps = ϵ, stop = stopfunc);

dará la solución de x de ∇J (x) = 0. Podemos omitir los parámetros precon, nbiter, eps,
detener. Aquí M es el precondicionador cuyo valor predeterminado es la matriz de identidad. La prueba de parada es

∇J (x) P ≤ ϵ ∇J (x (0) ) P

Escribiendo el valor negativo en eps =, es decir,

NLCG (∇J, x, precon = M, nbiter = i max , eps = −ϵ);

podemos usar la prueba de parada


∇J (x) 2
P≤ ϵ
Los parámetros de estas tres funciones son:

nbiter = establece el número de iteraciones (por defecto 100)

211

Página 212
212 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

precon = establecer la función del preacondicionador (P por ejemplo) por defecto es la identidad, comentar el
el prototipo es func real [int] P ( real [ int ] & x).

eps = establece el valor de la prueba de parada ε (= 10 −6 por defecto) si es positivo, entonces prueba relativa || ∇J (x) || P ≤
ε || ∇J (x 0 ) || P , de lo contrario, la prueba absoluta es || ∇J (x) || 2
P ≤ | ε |.

veps = establece y devuelve el valor de la prueba de parada, si es positivo, prueba relativa || ∇J (x) || P ≤
ε || ∇J (x 0 ) || P , de lo contrario, la prueba absoluta es || ∇J (x) || 2
P ≤ | ε |. El valor de retorno es menos
la prueba de parada real (observación: es útil en bucle).

stop = stopfunc agregue su función de prueba para detener antes (después de la versión 3.31). El prototipo del
la función stopfunc es

func bool stopfunc ( int iter, real [ int ] u, real [ int ] g)

donde u es la solución actual yg el gradiente actual no preacondicionado.

Ejemplo 8.1 (algo.edp) Para una función b dada, encontremos el minimizador u del funcional

1∫ ∫
J (u) = f (| ∇u | 2 ) - ub
2 Ω Ω
X 1
f (x) = ax + x - ln (1 + x), f (x) = a + , f (x) =
1+x (1 + x) 2

bajo la condición de contorno u = 0 en ∂Ω.

func real J (real [int] & u)


{
Vh w; w [] = u; // copiar la matriz u en la función de elementos finitos w
real r = int2d (Th) (0.5 * f (dx (w) * dx (w) + dy (w) * dy (w)) - b * w);
cout << "J (u) =" << r << "" << u.min << "" << u.max << endl;
return r;
}
// -----------------------

Vh u = 0; // el valor actual de la solución


Ph alfa; // de la tienda df (| ∇u | 2 )

https://translate.googleusercontent.com/translate_f 188/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
int iter = 0;
alfa = df (dx (u) * dx (u) + dy (u) * dy (u)); // mejoramiento

func real [int] dJ ( real [ int ] & u)


{
int verbo = verbosidad; verbosidad = 0;
Vh w; w [] = u; // copiar la matriz u en la función de elementos finitos w
alfa = gl (dx (w) * dx (w) + dy (w) * dy (w)); // mejoramiento
varf au (uh, vh) = int2d (Th) (alpha * (dx (w) * dx (vh) + dy (w) * dy (vh)) - b * vh)
+ en (1,2,3,4, uh = 0);
u = au (0, Vh);
verbosidad = verbo;
return u; // advirtiendo que no hay retorno de la matriz local
}

Página 213
8.1. GRADIENTE CONJUGADO / GMRES 213

Queremos construir también un precondicionador C con la resolución del problema: encuentre u h ∈ V 0h tal que
∫ ∫
∀v h ∈ V 0h , α∇u h .∇v h = bv h
Ω Ω

donde α = f (| ∇u | 2 ). * /

varf alap (uh, vh) = int2d (Th) (alpha * (dx (uh) * dx (vh) + dy (uh) * dy (vh)))
+ en (1,2,3,4, uh = 0);

varf amass (uh) = int2d (Th) (uh * vh) + on (1,2,3,4, uh = 0);

acumulación de matriz = alap (Vh, Vh, solucionador = CG); //


matriz Alap = alap (Vh, Vh, solucionador = Cholesky, factorizar = 1); //

// la función de preacondicionador
func real [ int ] C ( real [ int ] & u)
{
real [ int ] w = u;
u = Alapˆ-1 * w;
return u; // sin retorno de la variable de matriz local
}

/ * Para resolver el problema, hacemos 10 iteraciones del gradiente conjugado, recalculamos la precondición
y reinicie el gradiente conjugado: * /

verbosidad = 5;
int conv = 0;
eps real = 1e-6;
para ( int i = 0; i <20; i ++)
{
conv = NLCG (dJ, u [], nbiter = 10, precon = C, veps = eps); //
if (conv) break ; // si convergen romper bucle
alfa = df (dx (u) * dx (u) + dy (u) * dy (u)); // recalcular la optimización alfa
Alap = alap (Vh, Vh, solucionador = Cholesky, factorizar = 1);
cout << "reiniciar con nuevo precondicionador" << conv
<< "eps =" << eps << endl;
}

plot (u, espera = 1, cmm = "solución con NLCG");

Para una matriz A simétrica positiva dada, considere la forma cuadrática


1
J (x) = x T Ax - b T x
2
entonces J (x) se minimiza mediante la solución x de Ax = b. En este caso, podemos usar la función
LinearCG

AffineCG (A, x, precon = M, nbiter = i max , eps = ± ϵ, stop = stp);

https://translate.googleusercontent.com/translate_f 189/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Si A no es simétrico, podemos utilizar el algoritmo GMRES (residuo mínimo generalizado) mediante

AffineGMRES (A, x, precon = M, nbiter = i max , eps = ± ϵ);


Además, podemos usar la versión no lineal del algoritmo GMRES (la J funcional es simplemente convexa)

AffineGMRES (∇J, x, precon = M, nbiter = i max , eps = ± ϵ);

Para obtener más información sobre estos algoritmos, consulte [19 ] [Capítulo IV, 1.3].

Página 214
214 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

8.2 Algoritmos para optimización sin restricciones


Dos algoritmos de COOOL a paquete [32 ] están interconectados con el método de Newton Raphson (llamada
Newton) y el método BFGS. Estos dos están disponibles directamente en FreeFem (no dinámicos
enlace para cargar). Tenga cuidado con estos algoritmos, porque su implementación utiliza matrices completas.
También proporcionamos varios algoritmos de optimización de la biblioteca NLopt [47 ] , así como una interfaz
para la implementación de Hansen de CMAES (una versión MPI de esta también está disponible). Estos ultimos
los algoritmos se pueden encontrar como enlaces dinámicos en el ejemplo ++ - carpeta de carga como ff-NLopt y
Archivos CMA ES (CMA ES MPI del ejemplo ++ - carpeta mpi para la versión mpi).

8.2.1 Ejemplo de utilización para BFGS o CMAES

real [int] b (10), u (10);


func real J ( real [int] & u)
{
real s = 0;
para ( int i = 0; i <un; i ++)
s + = (i + 1) * u [i] * u [i] * 0.5 - b [i] * u [i];
cout << "J =" << s << "u =" << u [0] << "" << u [1] << "... \ n";
return s;
}

// el graduado de J (esta es una versión afín (el RHS está en)


func real [int] DJ ( real [int] & u)
{
para ( int i = 0; i <un; i ++)
u [i] = (i + 1) * u [i] -b [i];
return u; // retorno de la variable global ok
};

b = 1; u = 2; // establecer el lado derecho y el gesto inicial


BFGS (J, dJ, u, eps = 1.e-6, nbiter = 20, nbiterline = 20);
cout << "BFGS: J (u) =" << J (u) << endl;

Usar la estrategia de evolución de CMA es casi lo mismo, excepto que, como es una operación libre derivada
timizer, el argumento dJ se omite y hay algunos otros parámetros nombrados para controlar el
comportamiento del algoritmo. Con la misma función objetivo que la anterior, un ejemplo de utilización
sería (consulte cmaes-VarIneq.edp para obtener un ejemplo completo):

cargar "ff-cmaes"
... // define J, u y todo aquí
min real = cmaes (J, u, stopTolFun = 1e-6, stopMaxIter = 3000);
cout << "el valor mínimo es" << min << "para u =" << u << endl ;

Este algoritmo trabaja con una distribución multivariante normal en el espacio de parámetros e intenta
Adaptar su matriz de covarianza utilizando la información proporcionada por las sucesivas evaluaciones de funciones.
(ver [48 ] para más detalles). Por lo tanto, se pueden pasar algunos parámetros específicos para controlar el inicio
distribución, tamaño de las generaciones de la muestra, etc ... Los parámetros nombrados para esto son los siguientes:

seed = Semilla para generador de números aleatorios (val es un número entero). Ningún valor especificado conducirá a una
inicialización de semilla basada en reloj.

https://translate.googleusercontent.com/translate_f 190/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 215
8.3. IPOPT 215

initialStdDev = Valor de las desviaciones estándar de la matriz de covarianza inicial (val es un


verdadero). Si se pasa el valor σ, la matriz de covarianza inicial se establecerá en σI. Lo esperado
La distancia inicial entre la X inicial y el argmin debe ser aproximadamente initialStdDev. Defecto
es 0,3.

initialStdDevs = Igual que el anterior excepto que el argumento es una matriz que permite establecer un valor
de la desviación estándar inicial para cada parámetro. Entradas que difieren en varios órdenes de
Debe evitarse la magnitud (si no puede ser, intente reescalar el problema).

stopTolFun = Detiene el algoritmo si las diferencias de los valores de la función son menores que la pasada,
el valor predeterminado es 10-12 .

stopTolFunHist = Detiene el algoritmo si las diferencias de valores de función de los mejores valores son menores
que el pasado, el valor predeterminado es 0 (sin usar).

stopTolX = Criterios de parada activados si los tamaños de paso en el espacio de parámetros son más pequeños que este
valor real, el valor predeterminado es 0.

stopTolXFactor = Criterios de detención activados cuando la desviación estándar aumenta más de


este valor. El valor predeterminado es 10 3 .

stopMaxFunEval = Detiene el algoritmo cuando se han realizado evaluaciones de la función stopMaxFunEval


hecho. Establecido en 900 (n + 3) 2 de forma predeterminada, donde n es la dimensión del espacio de los parámetros.

stopMaxIter = Entero que detiene la búsqueda cuando se han muestreado las generaciones stopMaxIter.
No se utiliza de forma predeterminada.

popsize = Valor entero utilizado para cambiar el tamaño de la muestra. El valor predeterminado es 4 + ⌊3 ln (n) ⌋, consulte [ 48]
para más detalles. El aumento del tamaño de la población suele mejorar las capacidades de búsqueda global.
a costa de una reducción lineal como máximo de la velocidad de convergencia con respecto al tamaño de estallido.

paramFile = Este parámetro de tipo de cadena permite al usuario pasar todos los parámetros usando un ex-
tern como en el código original de Hansen. Más parámetros relacionados con el algoritmo CMA-ES pueden
cambiarse con este archivo. Se puede encontrar una muestra en los ejemplos ++ - load / ffCMAES /
carpeta con el nombre initials.par. Tenga en cuenta que los parámetros pasados al CMAES
La función en el script FreeFem se ignorará si se proporciona un archivo de parámetros de entrada.

8.3 IPOPT
El paquete ff-Ipopt es una interfaz para el optimizador IPOPT [49 ] . IPOPT es una biblioteca de software
para optimización restringida, no lineal y a gran escala. La información detallada al respecto se encuentra en [49 ] y
https://projects.coin-or.org/Ipopt. Se implementa un método de punto interior primal-dual
junto con búsquedas de líneas basadas en métodos de filtro. IPOPT necesita un solucionador lineal simétrico disperso directo. Si
su versión de FreeFem ha sido compilada con la etiqueta --enable-downlad, automáticamente
estar vinculado con una versión secuencial de MUMPS. Una alternativa a MUMPS sería descargar el
Subrutinas HSL ( consulte http://www.coin-or.org/Ipopt/documentation/node16.html)
y colóquelos en el directorio /ipopt/Ipopt-3.10.2/ThirdParty/HSL de FreeFem ++
carpeta de descargas antes de compilar.

https://translate.googleusercontent.com/translate_f 191/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 216
216 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

8.3.1 Breve descripción del algoritmo


En esta sección, damos un breve vistazo a las matemáticas subyacentes de IPOPT. Para un mas profundo
introducción sobre métodos interiores para la optimización suave no lineal, se puede consultar [50 ], o [49]
para obtener más elementos específicos de IPOPT. IPOPT está diseñado para realizar la optimización tanto para la igualdad
y problemas limitados por la desigualdad. Sin embargo, las desigualdades no lineales se reorganizan antes de
comienzo del proceso de optimización con el fin de restringir el panel de restricciones no lineales a
los del tipo de igualdad. Cada uno de desigualdad no lineal se transforma en un par de simples
restricción de desigualdad limitada e igualdad no lineal mediante la introducción de tantas variables de holgura
según sea necesario: c i (x) ≤ 0 se convierte en c i (x) + s i = 0 y s i ≤ 0, donde s i se suma a las variables iniciales
de los problemas x i . Por lo tanto, por conveniencia, asumiremos que el problema de minimización no
contener cualquier restricción de desigualdad no lineal. Significa que, dada una función f: R n ↦ → R, queremos
encontrar :
x 0 = argmin f (x)
x∈V (8,2)
con V = {x ∈ R n | c (x) = 0 y x l ≤ x ≤ x u }
Donde c: R n → R m y x l , x u ∈ R n y las desigualdades se mantienen por componentes. La función f también
ya que las restricciones c deberían ser dos veces diferenciables de forma continua.
Como método de barrera, los algoritmos de puntos interiores intentan encontrar un punto de Karush-Kuhn-Tucker para ( 8.2 )
resolviendo una secuencia de problemas, sin restricciones con respecto a las restricciones de desigualdad, de la
formulario :
para un µ> 0 dado, encuentre x µ = argmin B (x, µ) (8,3)
x∈R n | c (x) = 0

norte metro

Donde µ es un número real positivo y B (x, µ) = f (x) - µ ∑ ln (x u, i - x i ) - µ ∑ ln (x yo - x l, yo ).


i=1 i=1
Las restricciones de igualdad restantes se manejan con el método de multiplicadores de Lagrange habitual. Si el
secuencia de parámetros de barrera µ convergen a 0, la intuición sugiere que la secuencia de minimizadores
de (8.3 ) convergen a un minimizador restringido local de (8.2). Para un µ dado, (8.3) se resuelve hallando
(x µ , λ µ ) ∈ R n × R m tal que:
metro

∇B (x µ , µ) + ∑ λ µ, i ∇c i (x µ ) = ∇B (x µ , µ) + J c (x µ ) T λ µ = 0 yc (x µ ) = 0 (8,4)
i=1

Las derivaciones para ∇B solo son válidas para las variables x, de modo que:

µ / (x u, 1 - x 1 ) µ / (x 1 - x l, 1 )
∇B (x, µ) = ∇f (x) + ... ...
-
µ / (x u, n - x n ) µ / (x norte - x l, n )

Si llamamos respectivamente a z u (x, µ) = (µ / (x u, 1 - x 1 ), ..., µ / (x u, n - x n )) y z l (x, µ) el otro vector


que aparece en la ecuación anterior, entonces el óptimo (x µ , λ µ ) satisface:

∇f (x µ ) + J c (x µ ) T λ µ + z u (x µ , µ) - z l (x µ , µ) = 0 yc (x µ ) = 0 (8,5)

En esta ecuación, los vectores z l y z u parecen jugar el papel de multiplicadores de Lagrange para el
desigualdades de límites simples, y de hecho, cuando µ → 0, convergen hacia algún Lagrange adecuado
multiplicadores para las condiciones KKT, siempre que se cumplan algunos supuestos técnicos (véase [ 50] ).
La ecuación 8.5 se resuelve aplicando un método de Newton para encontrar una solución de (8.4) para cada
de los valores decrecientes de µ. También se tienen en cuenta algunas condiciones de orden 2 para evitar conversiones.
gencia al maximizador local, consulte [ 50 ] para obtener precisión sobre ellos. En los algoritmos IP más clásicos, el
El método de Newton se aplica directamente a ( 8.4) . En la mayoría de los casos, esto es ineficaz debido a la frecuente
putación de puntos inviables. Estas dificultades se evitan en los métodos de puntos interiores Primal-Dual.

Página 217
8.3. IPOPT 217

donde ( 8.4 ) se transforma en un sistema extendido donde z u y z l se tratan como incógnitas y


los problemas de barrera son encontrar (x, λ, z u , z l ) ∈ R n × R m × R n × R n tal que:

∇f (x) + J do (x) T λ + z u - z l =0

https://translate.googleusercontent.com/translate_f 192/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
c (x) = 0
(8,6)
(X u - X) z u - µe = 0
(X - X l ) z l - µe = 0

Donde si a es un vector de R n , A denota la matriz diagonal A = (a i δ ij ) 1≤i, j≤n ye ∈ R n =


(1,1, ..., 1). Resolver este sistema no lineal por los métodos de Newton se conoce como
método de puntos interiores duales. También en este caso, hay más detalles disponibles en [50 ]. Implementación más actual
introducen características para globalizar la capacidad de convergencia del método, esencialmente
agregando algunos pasos de búsqueda de línea al algoritmo de Newton, o usando regiones de confianza. Para el fin
pose de IPOPT, esto se logra mediante un método de búsqueda de línea de filtro, cuyos detalles se pueden encontrar
en [?].
Se pueden encontrar más características específicas de IPOPT o detalles de implementación en [49 ] . Solo retendremos
que IPOPT es un método inteligente de Newton para resolver problemas de optimización restringida, con
capacidades de convergencia debido a un método de búsqueda de línea robusto (en el sentido de que el algoritmo
convergencia sin importar el inicializador). Debido al método de Newton subyacente, la optimización
El proceso requiere expresiones de todas las derivadas hasta el orden 2 de la función de aptitud, así como
los de las limitaciones. Para problemas cuyas matrices de arpillera son difíciles de calcular o conducir a
matrices densas de alta dimensión, es posible utilizar una aproximación BFGS de estos objetos en
el costo de una tasa de convergencia mucho más lenta.

8.3.2 IPOPT en FreeFem ++


La llamada al optimizador de IPOPT en un script FreeFem ++ se realiza con la función IPOPT incluida
en la biblioteca dinámica ff-Ipopt. IPOPT está diseñado para resolver problemas de minimización restringida
en la forma :

encontrar x 0 = argmin f (x)


x∈R n
{∀i ≤ n, x lb (límites simples) (8,7)
St yo ≤
x yo ≤ x ub I
∀i ≤ m, c lb (funciones de restricciones)
yo ≤ c yo (x) ≤ c ub I

Donde ub y lb significan "límite superior" y "límite inferior". Si para algún i, 1 ≤ i ≤ m tenemos


c lb
i = c ub i , significa que c i es una restricción de igualdad y una de desigualdad si c lb yo <c ub yo .
Hay diferentes formas de pasar la función de aptitud y las limitaciones. El más general es
defina las funciones usando la palabra clave func. Cualquier matriz devuelta debe ser escasa (tipo
matriz, no real [int, int]):

func real J ( real [ int ] & X) {...} // Función Fitness, devuelve un escalar
func real [ int ] gradJ ( real [ int ] & X) {...} // El degradado es un vector

func real [int] C ( real [ int ] & X) {...} // Restricciones


func matrix jacC ( real [ int ] & X) {...} // Restricciones jacobianas

Advertencia 1: en la versión actual de FreeFem ++, devolviendo un objeto de matriz local a una función
bloquear conduce a resultados indefinidos. Para cada función de retorno de matriz dispersa que defina, un extern
El objeto de matriz debe ser declarado, cuya función asociada se sobrescribirá y regresará en cada llamada.
Aquí hay un ejemplo de jacC:

matrix jacCBuffer; // solo declarar, no es necesario definir todavía

Página 218
218 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

func matrix jacC ( real [ int ] & X)


{
... // llenar jacCBuffer
return jacCBuffer;
}

Advertencia 2: IPOPT requiere la estructura de cada matriz en la inicialización del algoritmo. Algunos
pueden ocurrir errores si las matrices no son constantes y se construyen con la matriz A = [I, J, C]
sintaxis, o con una matriz completa intermedia (real [int, int]), porque cualquier coeficiente nulo es
descartados durante la construcción de la matriz dispersa. También es el caso al hacer matrices
combinaciones lineales, para las cuales cualquier coeficiente cero resultará en la supresión de la matriz de
la combinación. Hay algunos controles disponibles para evitar estos problemas. Verifique los parámetros nombrados

https://translate.googleusercontent.com/translate_f 193/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
descripciones (checkindex, structhess y structjac pueden ayudar). Recomendamos encarecidamente utilizar
varf tanto como sea posible para la forja matricial.

La función de retorno de la arpillera es algo diferente porque tiene que ser la arpillera del la-
metro

función grangiana: (x, σ f , λ) ↦ → σ f ∇ 2 f (x) + ∑ λ i ∇ 2 c i (x) donde λ ∈ R my σ ∈ R. Tu arpillera


i=1
La función debería tener el siguiente prototipo:

matrix hessianLBuffer; // solo para tenerlo en cuenta


func matrix hessianL ( real [ int ] & X, real sigma, real [ int ] & lambda) {...}

Si las funciones de restricciones son todas afines, o si solo hay restricciones de límites simples o no
restricción en absoluto, la arpillera lagrangiana es igual a la función de aptitud arpillera, entonces se puede omitir
los parámetros sigma y lambda:

matrix hessianJBuffer;
func matrix hessianJ ( real [ int ] & X) {...} // Prototipo de arpillera cuando
las limitaciones son afines

Cuando se definen estas funciones, IPOPT se llama de esta manera:

real [ int ] Xi = ...; // punto de partida


IPOPT (J, gradJ, hessianL, C, jacC, Xi, / * algunos parámetros con nombre * /);

Si se omite la arpillera, la interfaz le dirá a IPOPT que use la aproximación (L) BFGS (puede
también puede habilitarse con un parámetro con nombre, ver más adelante). Límites simples o problemas sin restricciones
no requieren la parte de restricciones, por lo que las siguientes expresiones son válidas:

IPOPT (J, gradJ, C, jacC, Xi, ...); // IPOPT con BFGS


IPOPT (J, gradJ, hessianJ, Xi, ...); // Newton IPOPT sin restricciones
IPOPT (J, gradJ, Xi, ...); // BFGS, sin restricciones

Los límites simples se pasan usando los parámetros con nombre lb y ub, mientras que los límites de las restricciones son
pasó con los clb y cub. La ilimitación en algunas direcciones se puede lograr utilizando
los valores 1e 19 y −1e 19 que IPOPT reconoce como + ∞ y −∞:

real [ int ] xlb (n), xub (n), clb (m), cub (m);
... // llenar las matrices ...
IPOPT (J, gradJ, hessianL, C, jacC, Xi, lb = xlb, ub = xub, clb = clb, cub = cub, / * alguna otra
parámetros con nombre * /);

Página 219
8.3. IPOPT 219

P2 función de aptitud y función de restricciones afines: En el caso de que la función de aptitud o


La función de restricciones se puede expresar respectivamente en las siguientes formas:

∀x ∈ R norte , f (x) = 1 2 〈Eje, x〉 + 〈segundo, x〉 (A, segundo) ∈ M norte, norte (R) × R norte
o, C (x) = Ax + b (A, b) ∈ M norte, metro (R) × R m

donde A y b son constantes, es posible pasar directamente el par (A, b) en lugar de definir 3 (o
2) funciones. También indica a IPOPT que algunos objetos son constantes y que deben ser
evaluado solo una vez, evitando así múltiples copias de la misma matriz. La sintaxis es:

// Restricciones afines con función de aptitud "estándar"


matriz A = ...; // Parte lineal de las restricciones
real [ int ] b = ...; // Parte constante de las restricciones
IPOPT (J, gradJ, hessianJ, [A, b], Xi, / * límites y parámetros con nombre * /);
// [b, A] también funcionaría ... Scatterbrains mimos ...

Tenga en cuenta que si define las restricciones de esta manera, no contribuyen a la arpillera, por lo que la
hessian solo debe tomar un real [int] como argumento.

// Restricciones afines y función de fitness P2:

https://translate.googleusercontent.com/translate_f 194/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
matriz A = ...; // Matriz de forma bilineal
real [ int ] b = ...; // Contribución lineal af
matriz Ac = ...; // Parte lineal de las restricciones
real [ int ] bc = ...; // Parte constante de las restricciones
IPOPT ([A, b], [Ac, bc], Xi, / * límites y parámetros con nombre * /);

Si tanto las funciones de objetivo como las de restricciones se dan de esta manera, se activa automáticamente el IPOPT
Opción de algoritmo mehrotra (mejor para programación lineal y cuadrátrica de acuerdo con
documentación). De lo contrario, esta opción solo se puede configurar a través del archivo de opciones (consulte el
sección de parámetros).
Un caso espurio es el de definir f de esta manera mientras se usan funciones estándar para la
restricciones:

matriz A = ...; // Matriz de forma bilineal


real [ int ] b = ...; // Contribución lineal af
func real [int] C ( real [ int ] & X) {...} // Restricciones
func matrix jacC ( real [ int ] & X) {...} // Restricciones jacobianas
IPOPT ([A, b], C, jacC, Xi, / * límites y parámetros con nombre * /);

De hecho, al pasar [A, b] para definir f, la arpillera lagrangiana se construye automáticamente


tiene la constante x ↦ → Una función, sin forma de agregar posibles restricciones contribuciones, lo que lleva
a derivadas incorrectas de segundo orden. Entonces, un problema debe definirse así en solo dos casos:
1) las restricciones no son lineales pero desea usar el modo BFGS (luego agregue bfgs = 1 al nombre
parámetro), 2) las restricciones son afines, pero en este caso, ¿por qué no pasarlas de la misma manera?
Aquí hay algunas otras definiciones válidas del problema (casos en los que f es puramente cuadrática o lineal
forma, o C una función lineal pura, etc ...):

// F-A cuadrático puro es una matriz:


IPOPT (A, / * restricciones args * /, Xi, / * límites y parámetros con nombre * /);
// Puro lineal f - bia real [int]:
IPOPT (b, / * restricciones args * /, Xi, / * límites y parámetros con nombre * /);
// restricciones lineales - Ac es una matriz
IPOPT (/ * fitness func args * /, Ac, Xi, / * límites y parámetros con nombre * /);

Página 220
220 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

Valor devuelto: la función IPOPT devuelve un código de error de tipo int. Se obtiene un valor cero
cuando el algoritmo tiene éxito y los valores positivos reflejan el hecho de que IPOPT encuentra menores
nubes. Los valores negativos revelan casos más problemáticos. Las etiquetas de retorno IPOPT asociadas son
enumerados en la tabla siguiente. La documentación en pdf de IPOPT proporciona una descripción más precisa de
estos devuelven el estado:

Éxito Fracasos
0 Resolver exitosamente -1 Se excedieron las iteraciones máximas
1 Resuelto a un nivel aceptable -2 Restauración fallida
2 Problema inviable detectado -3 Error en el cálculo del paso
3 La dirección de búsqueda se vuelve demasiado pequeña -4 Máximo CpuTime excedido
4 Iteraciones divergentes
5 Parada solicitada por el usuario
6 Punto factible encontrado
Problemas de definición de problemas Errores críticos
-10 grados de libertad insuficientes -100 excepción irrecuperable
-11 Definición de problema no válida -101 Excepción no Ipopt lanzada
-12 Opción no válida -102 Memoria insuficiente
-13 Número no válido detectado -199 Error interno

Parámetros con nombre: los parámetros con nombre disponibles en esta interfaz son los que pensamos
los más sujetos a variaciones de una optimización a otra, además de algunas que son de interfaz
específico. Aunque, como se puede ver en http://www.coin-or.org/Ipopt/documentation/
node59.html, hay muchos parámetros que se pueden cambiar dentro de IPOPT, lo que afecta al
comportamiento del algoritmo. Estos parámetros aún se pueden controlar colocando un archivo de opciones en el
directorio de ejecución. Tenga en cuenta que la documentación en pdf de IPOPT puede proporcionar más información que
la versión en línea mencionada anteriormente para ciertos parámetros. Los parámetros disponibles en el script

https://translate.googleusercontent.com/translate_f 195/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
están :

lb , ub : real [int] para los límites simples superior e inferior de las variables de búsqueda, debe ser de tamaño
n (dimensión del espacio de búsqueda). Si dos componentes del mismo índice en estas matrices son iguales, entonces
la variable de búsqueda correspondiente es fija. Por defecto, IPOPT eliminará cualquier variable fija
del proceso de optimización y siempre use el valor fijo al llamar a funciones. Puede
cambiarse usando el parámetro fixedvar.

clb , cub : real [int] de tamaño m (número de restricciones) para límites de restricciones inferiores y superiores.
La igualdad entre dos componentes del mismo índice i en clb y cub refleja una con-
esfuerzo.

structjacc : Pasar la mayor estructura posible (índices de coeficientes no nulos) de la


restricciones jacobianas bajo la forma [I, J] donde I y J son dos matrices de enteros. Si no
definida, se utiliza la estructura de las restricciones jacobianas, evaluadas en Xi (no hay problema si el
jacobian es constante o siempre se define con el mismo varf, peligroso si es con triplete
matriz o si se trata de una matriz completa).

structhess : Igual que el anterior pero para la función de arpillera (no se usa si f es P2 o menos y las restricciones
son afines). Aquí nuevamente, tenga en cuenta que es la arpillera de la función lagrangiana (que
es igual a la arpillera de f solo si las restricciones son afines). Si no se da una estructura con
este parámetro, la arpillera lagrangiana se evalúa en el punto de partida, con σ = 1 y
λ = (1,1, ..., 1) (es seguro si todas las restricciones y función de aptitud de las arpilleras son constantes o
construir con varf, y aquí de nuevo menos confiable si se construye con una matriz triple o una matriz completa).

Página 221
8.3. IPOPT 221

checkindex : un bool que activa una búsqueda dicotómica de índice cuando se copian matrices de
FreeFem funciona con arreglos IPOPT. Se utiliza para evitar la coincidencia de índices incorrecta cuando algunos
FreeFem elimina los coeficientes nulos de las matrices. No solucionará los problemas
que surge cuando se ha dado una estructura demasiado pequeña en la inicialización del algoritmo.
Habilitado por defecto (excepto en los casos en los que todas las matrices son obviamente constantes).

warmstart : si se establece en verdadero, las restricciones variables duales λ y los límites simples variables duales
se inicializan con los valores de las matrices que se pasan a los parámetros con nombre lm, lz y uz (ver
debajo).

lm : real [int] de tamaño m, que se utiliza para obtener los valores finales de las variables duales de restricciones
λ y / o inicializarlos en caso de un inicio en caliente (la matriz pasada también se actualiza a la última
valores de variables duales al final del algoritmo).

lz , uz : real [int] de tamaño n para obtener los valores finales y / o inicializar (en caso de inicio en caliente)
variables duales asociadas a límites simples.

tol : tolerancia de convergencia real para el algoritmo, el valor predeterminado es 10 −8 .

maxiter : int, número máximo de iteraciones con 3000 como valor predeterminado.

maxcputime : valor real, duración máxima del tiempo de ejecución. El valor predeterminado es 10 6 (casi 11 días y un
mitad).

bfgs : bool que habilita o no la aproximación BFGS (de bajo almacenamiento) de la arpillera lagrangiana. Eso
se establece en falso de forma predeterminada, a menos que no haya forma de calcular la arpillera con las funciones
que se han pasado a IPOPT.

derivativetest : se utiliza para realizar una comparación de las derivadas dadas a IPOPT con finite
cálculo de diferencias. Los posibles valores de cadena son: "ninguno" (predeterminado), "primer orden",
"segundo orden" y "sólo de segundo orden". La tolerancia de error derivada asociada
se puede cambiar a través del archivo de opciones. Uno no debería preocuparse por ningún error dado por él antes
haber intentado, y fallado, realizar una primera optimización.

dth : Parámetro de perturbación para los cálculos de la prueba derivada con diferencias finitas. Establecido por
predeterminado a 10 −8 .

dttol : valor de tolerancia para la detección de error de prueba derivada (valor predeterminado desconocido todavía, tal vez

https://translate.googleusercontent.com/translate_f 196/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
10 −5 ).

optfile : parámetro de cadena para especificar el nombre de archivo de la opción IPOPT. IPOPT buscará un
Archivo ipopt.opt de forma predeterminada. Las opciones establecidas en el archivo sobrescribirán las definidas en FreeFem
texto.

printlevel : un int para controlar el nivel de impresión de salida de IPOPT, establecido en 5 por defecto, el posible
los valores son de 0 a 12. Una descripción de la información de salida está disponible en el pdf
documentación de IPOPT.

fixedvar : cadena para la definición de límites simples restricciones de igualdad tratamiento: uso
"hacer parámetro" (valor predeterminado) para simplemente eliminarlos del proceso de optimización
(las funciones siempre se evaluarán con el valor fijo para esas variables), "hacer restricción"
para tratarlos como cualquier otra restricción o "relajar límites" para relajar la fijación de restricciones de límite.

mustrategy : una cadena para elegir la estrategia de actualización del parámetro de barrera µ. Las dos posibilidades
Las etiquetas ble son "monótonas", para usar la estrategia monótona (Fiacco-McCormick), o "adaptativas"
(Configuración predeterminada).

Página 222
222 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

muinit : valor positivo real para la inicialización del parámetro de barrera. Solo es relevante cuando
mustrategy se ha establecido en monótono.

pivtol : valor real para establecer la tolerancia de pivote para el solucionador lineal. Un número menor gira para
escasez, un mayor número de pivotes para la estabilidad. El valor debe estar en el intervalo [0,1] y es
establecido en 10 −6 de forma predeterminada.

brf : Factor de relajación de límites: antes de iniciar la optimización, los límites dados por el usuario son
relajado. Esta opción establece el factor para esta relajación. Si se establece en cero, entonces los límites
la relajación está deshabilitada. Este real tiene que ser positivo y su valor predeterminado es 10 −8 .

objvalue : un identificador de una variable de tipo real para obtener el último valor de la función objetivo
(mejor valor en caso de éxito).

mumin : Valor mínimo para el parámetro de barrera µ, un real con 10 −11 como valor predeterminado.

linesearch : un valor booleano que deshabilita la búsqueda de líneas cuando se establece en falso. La búsqueda de línea es
activado por defecto. Cuando está deshabilitado, el método se convierte en un algoritmo estándar de Newton.
otro, el sistema dual primario. La convergencia global ya no está asegurada, lo que significa
que muchos inicializadores podrían llevar a iteraciones divergentes. Pero por otro lado, puede ser útil
al intentar capturar un mínimo local preciso sin tener un proceso fuera de control
haciendo que la iteración sea capturada por algún otro casi óptimo.

8.4 Algunos ejemplos breves usando IPOPT


Ejemplo 8.2 (IpoptVI.edp) Un ejemplo muy simple que consiste en, dadas dos funciones f y g (de
1∫ ∫
multado en Ω ⊂ R 2 ), minimizando J (u) = | ∇u | 2 - fu, con u ≤ g casi en todas partes:
2 Ω Ω

cargar "ff-Ipopt"; // cargar la interfaz


int nn = 20; // calidad de la malla
malla Th = cuadrado (nn, nn); // construir una malla cuadrada
fespace Vh (Th, P1); // espacio de elementos finitos

func f = 1 .; // función rhs


real r = 0,03, s = 0,1; // algunos parámetros para g
func g = r - r / 2 * exp (-0,5 * ( cuadrado ( x -0,5) + cuadrado ( y -0,5)) / cuadrado (s));
// g es constante menos un gaussiano

macro Grad (u) [ dx (u), dy (u)] // el operador de gradiente


varf vP (u, v) = int2d (Th) (Grad (u) '* Grad (v)) - int2d (Th) (f * v);

Aquí construimos la matriz y el segundo miembro asociado al funcional para minimizar de una vez por
todas. A continuación, se utiliza la sintaxis [A, b] de la función de aptitud para pasarla a IPOPT.

https://translate.googleusercontent.com/translate_f 197/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

matriz A = vP (Vh, Vh, solucionador = CG);


real [ int ] b = vP (0, Vh);

Usamos límites simples para imponer la condición de frontera u = 0 en ∂Ω, así como la condición u ≤ g.

Vh lb = -1.e19; // inferior-ilimitado en el interior


Vh ub = g; // delimitado superior por g en el interior
varf vGamma (u, v) = on (1,2,3,4, u = 1);

Página 223
8.4. ALGUNOS EJEMPLOS BREVES DE USO DE IPOPT 223

real [ int ] onGamma = vGamma (0, Vh);


ub [] = onGamma? 0.: ub []; // hacer cumplir la condición de límite
lb [] = onGamma? 0.: lb [];

Vh u = 0; // punto de partida
IPOPT ([A, b], u [], lb = lb [], ub = ub []); // resolver el problema
plot (u, espera = 1);

Ejemplo 8.3 (IpoptVI2.edp) Sea Ω un dominio de R 2 , f 1 , f 2 ∈ L 2 (Ω) y g 1 , g 2 ∈ L 2 (∂Ω) cuatro


funciones dadas con g 1 ≤ g 2 casi en todas partes. Definimos el espacio:

V = {(v 1 , v 2 ) ∈ H 1 (Ω) 2 ; v 1 | ∂Ω = g 1 , v 2 | ∂Ω = g 2 , v 1 ≤ v 2 ae}

así como el funcional J: H 1 (Ω) 2 - → R:

1 ∫ ∫ 1 ∫ ∫
J (v 1 , v 2 ) = | ∇v 1 | 2 - f 1 contra 1 + | ∇v 2 | 2 - f 2 contra 2
2 Ω Ω 2 Ω Ω

El problema consiste en encontrar (numéricamente) dos funciones (u 1 , u 2 ) = argmin J (v 1 , v 2 ).


(v 1 , v 2 ) ∈V

cargar "ff-IpOpt";

malla Th = cuadrado (10,10);


espacio libre Vh (Th, [P1, P1]);
espacio libre Wh (Th, [P1]);
int iter = 0;

func f1 = 10; // lados derechos


func f2 = -15;
func g1 = -0,1; // Funciones de condiciones de contorno
func g2 = 0,1;

mientras (++ iter) // bucle de adaptación de malla


{
macro Grad (u) [ dx (u), dy (u)] // macro degradado
varf vP ([u1, u2], [v1, v2]) = int2d (Th) (Grad (u1) '* Grad (v1) + Grad (u2)' * Grad (v2))
- int2d (Th) (f1 * v1 + f2 * v2);

matriz A = vP (Vh, Vh); // Matriz de funciones de fitness ...


real [ int ] b = vP (0, Vh); // y forma lineal

int [ int ] II1 = [0], II2 = [1]; // Matriz de restricciones


matriz C1 = interpolar (Wh, Vh, U2Vc = II1);
matriz C2 = interpolar (Wh, Vh, U2Vc = II2);
matriz CC = -1 * C1 + C2; // u2 - u1> 0
Wh cl = 0; // restricciones límites inferiores (sin límites superiores)

// Condiciones de borde
varf vGamma ([u1, u2], [v1, v2]) = en (1,2,3,4, u1 = 1, u2 = 1);
real [ int ] onGamma = vGamma (0, Vh);
Vh [ub1, ub2] = [g1, g2];
Vh [lb1, lb2] = [g1, g2];

https://translate.googleusercontent.com/translate_f 198/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
ub1
lb1 [][]==onGamma?
onGamma?lb1
ub1[]:
[]:-1e19;
1e19; // Ilimitado en interior

Página 224
224 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

Figura 8.1: Aproximación numérica de la desigualdad variacional

Vh [u1, u2] = [0,0]; // punto de partida

IPOPT ([b, A], CC, u1 [], lb = lb1 [], ub = ub1 [], clb = cl []);

plot (u1, u2, espera = 1, nbiso = 60, dim = 3);


if (iter> 1) break ;
Th = adaptmesh (Th, [u1, u2], err = 0.004, nbvx = 100000);
}

8.5 Superficie mínima restringida 3D con IPOPT


8.5.1 Expresiones de área y volumen
Este ejemplo tenía como objetivo resolver numéricamente algunos problemas de superficie mínima restringida con el
Algoritmo IPOPT. Restringimos a C k (k ≥ 1), superficies cerradas, esféricamente parametrizables, es decir
superficies S tales que:

ρ (θ, φ)
∃ρ ∈ C k ([0,2π] × [0, π]) | S = X= 0
, (θ, φ) ∈ [0,2π] × [0, π]
0

Donde los componentes se expresan en el sistema de coordenadas esféricas. Llamemos a Ω el [0,2π] ×


[0, π] conjunto de parámetros angulares. Para excluir las formas autocruzadas y abiertas, lo siguiente
se hacen suposiciones sobre ρ:

ρ ≥ 0 y ∀φ, ρ (0, φ) = ρ (2π, φ)

Para una función dada ρ, la primera forma fundamental (la métrica) de la superficie definida tiene lo siguiente
representación matricial:

(ρ 2 sin 2 (φ) + (∂ θ ρ) 2 ∂ θ ρ∂ φ ρ )
G= (8,8)
∂ θ ρ∂ φ ρ ρ 2 + (∂ φ ρ) 2

Esta métrica se usa para expresar el área de la superficie. Sea g = det (G), entonces tenemos:

∫ ∫ √ ∫ √
A (ρ) = ∂θX∧∂φX= g= ρ 2 (∂ θ ρ) 2 + ρ 4 sin 2 (φ) + ρ 2 (∂ φ ρ) 2 sin 2 (φ) dθdφ (8,9)
Ω Ω Ω

https://translate.googleusercontent.com/translate_f 199/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 225
8.5. SUPERFICIE MÍNIMA RESTRINGIDA EN 3D CON IPOPT 225

El volumen del espacio encerrado dentro de la forma es más fácil de expresar:

∫ ∫ ρ (θ, φ) 1∫
V (ρ) = r 2 sin (φ) drdθdφ = ρ 3 pecado (φ) dθdφ (8,10)
Ω 0 3 Ω

8.5.2 Derivados
Para utilizar un algoritmo de optimización de puntos interiores basado en newton, se debe poder evaluar
las derivadas de A y V con respecto a rho. Respecto al área tenemos el siguiente resultado:

∫ 1 d¯g (ρ) (v)


∀v ∈ C 1 (Ω), 〈dA (ρ), v〉 = √ dθdφ
Ω 2 gramo

Donde ¯g es la aplicación que mapea el campo escalar (θ, φ) ↦ → g (θ, φ) a ρ. Esto lleva a lo siguiente
expresión, fácil de transponer en un script freefem usando:


∀v ∈ C 1 (Ω), 〈dA (ρ), v〉 = (2ρ 3 sin 2 (φ) + ρ (∂ θ ρ) 2 + ρ (∂ φ ρ) 2 sin 2 (φ)) v
Ω
∫ (8,11)
+ ρ 2 ∂ θ ρ∂ θ v + ρ 2 ∂ φ ρsin 2 (φ) ∂ φ v
Ω

Con un enfoque similar, se puede derivar una expresión para derivadas de segundo orden. Aunque com
portado sin dificultades específicas, los cálculos detallados son tediosos, el resultado es que estos derivados
se puede escribir usando una matriz B de 3 × 3 cuyos coeficientes se expresan en términos de ρ y sus derivadas
con respecto a θ y φ, tal que:

v

∀ (w, v) ∈ C 1 (Ω), re 2 A (ρ) (w, v) = (w ∂ θ w ∂ φ w) B ∂θv (8.12)
Ω
dθdφ
∂φv

Derivar las derivadas de la función de volumen es nuevamente una tarea más sencilla. Inmediatamente obtenemos lo siguiente
expresiones:

∀v, 〈dV (ρ), v〉 = ρ 2 pecado (φ) v dθdφ
Ω
∫ (8,13)
∀w, v, d 2 V (ρ) (w, v) = 2ρsin (φ) wv dθdφ
Ω

8.5.3 El problema y su guión:


El código completo está disponible en IpoptMinSurfVol.edp. Proponemos resolver el siguiente problema
:

Ejemplo 8.4 Dada una función positiva ρ objeto continuo a trozos, y un escalar V max > V (ρ objeto ),
encuentre ρ 0 tal que:

ρ 0 = argmin A (ρ), st ρ 0 ≥ ρ objeto y V (ρ 0 ) ≤ V max


ρ∈C 1 (Ω)

Si ρ objeto es la parametrización esférica de la superficie de un objeto tridimensional (dominio) O, puede


ser interpretado como encontrar la superficie con un área mínima que encierra el objeto con un máximo dado
volumen. Si V max está cerca de V (ρ objeto ), también debería ser ρ 0 y ρ objeto . Con valores más altos de V max , ρ
debe estar más cerca de la superficie mínima no restringida que rodea O que se obtiene tan pronto como

Página 226
226 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

3
V máx. ≥ 4 πρ objeto
3 ∞ (suficiente pero no necesario).

https://translate.googleusercontent.com/translate_f 200/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
También podría ser interesante resolver el mismo problema con la restricción V (ρ 0 ) ≥ V min que conduce
a una esfera cuando V min ≥ 1 6 πdiam (O) 3 y avanzar hacia la solución del problema sin restricciones
a medida que V min disminuye.

Comenzamos mallando el dominio [0,2π] × [0, π], luego se define un espacio periódico de elementos finitos P1.

cargar "msh3";
cargar "medit";
cargar "ff-Ipopt";

int np = 40; // parámetro de calidad de malla inicial


malla Th = cuadrado (2 * np, np, [2 * pi * x, pi * y]);

fespace Vh (Th, P1 , periódico = [[2, y], [4, y]]);


Vh forma de inicio = 5; // forma inicial

Creamos algunas funciones de elementos finitos cuyas matrices subyacentes se utilizarán para almacenar los valores de
variables duales asociadas a todas las restricciones para reinicializar el algoritmo con él en el
caso en el que utilizamos la adaptación de malla. Al hacerlo, el algoritmo casi se reiniciará con la precisión
nivel que alcanzó antes de la adaptación de la malla, ahorrando así muchas iteraciones.

Vh uz = 1., lz = 1 .; // Variable dual de límites simples


real [int] lm = [1]; // variable dual para restricción de volumen

Luego, sigue el ciclo de adaptación de malla y una función de renderizado, Plot3D, usando malla 3D para
mostrar la forma que se pasa con medit (el procedimiento movemesh23 a menudo se bloquea cuando se llama
con formas irregulares).

int nadapt = 1;
para ( int kkk = 0; kkk <nadapt; ++ kkk) // Bucle de adaptación de malla
{

int iter = 0; // las iteraciones cuentan


func sin2 = cuadrado ( sin (y)); // una función que se utilizará a menudo

func int Plot3D ( real [ int ] & rho, string cmm, bool ffplot) {...} // ver el .edp
expediente

Aquí están las funciones relacionadas con el cálculo del área y su forma derivada, de acuerdo con
ecuaciones 8.9 y 8.11:

func área real ( real [ int ] & X)


{
Vh rho;
rho [] = X;
Vh rho2 = cuadrado (rho);
Vh rho4 = cuadrado (rho2);
real res = int2d (Th) ( sqrt (rho4 * sin2
+ rho2 * cuadrado ( dx (rho))
+ rho2 * sin2 * cuadrado ( dy (rho)))
);
++ iter;

Página 227
8.5. SUPERFICIE MÍNIMA RESTRINGIDA EN 3D CON IPOPT 227

plot (rho, ... / * algunos parámetros * / ...);


return res;
}

func real [ int ] GradArea ( real [ int ] & X) // El gradiente


{
Vh rho, rho2;
rho [] = X;
rho2 [] = cuadrado (X);
Vh sqrtPsi, alfa; // Psi es realmente det (G)

https://translate.googleusercontent.com/translate_f 201/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
{ // algunas optimizaciones
Vh dxrho2 = dx (rho) * dx (rho), dyrho2 = dy (rho) * dy (rho);
sqrtPsi = sqrt (rho2 * rho2 * sin2 + rho2 * dxrho2 + rho2 * dyrho2 * sin2);
alfa = 2. * rho2 * rho * sin2 + rho * dxrho2 + rho * dyrho2 * sin2;
}
varf dSurface (u, v) =
int2d (Th) (1./sqrtPsi* (alpha * v + rho2 * dx (rho) * dx (v) + rho2 * dy (rho) * sin2 * dy (v)));
real [ int ] grad = dSurface (0, Vh);
graduado de regreso ;
}

La función que devuelve la arpillera del área para una forma determinada es un poco borrosa, por lo que no mostraremos
aquí toda la definición de los coeficientes de la ecuación 8.12 , se pueden encontrar en el archivo edp.

matriz arpilleraA; // El búfer de matriz global

func matrix HessianArea ( real [ int ] & X)


{
Vh rho, rho2;
rho [] = X;
rho2 = cuadrado (rho);
Vh sqrtPsi, sqrtPsi3, C00, C01, C02, C11, C12, C22, A;
{
... // definición de las funciones anteriores
}
varf d2Area (w, v) =
int2d (Th) (
1./sqrtPsi * (A * w * v + 2 * rho * dx (rho) * dx (w) * v + 2 * rho * dx (rho) * w * dx (v)
+ 2 * rho * dy (rho) * sin2 * dy (w) * v + 2 * rho * dy (rho) * sin2 * w * dy (v)
+ rho2 * dx (w) * dx (v) + rho2 * sin2 * dy (w) * dy (v))
+ 1./sqrtPsi3 * (C00 * w * v + C01 * dx (w) * v + C01 * w * dx (v) + C02 * dy (w) * v
+ C02 * w * dy (v) + C11 * dx (w) * dx (v)
+ C12 * dx (w) * dy (v) + C12 * dy (w) * dx (v) + C22 * dy (w) * dy (v))
); // fin de int2d y varf
hessianA = d2Area (Vh, Vh);
return hessianA;
}

Y las funciones relacionadas con el volumen:

func real Volume ( real [ int ] & X)


{
Vh rho;
rho [] = X;
Vh rho3 = rho * rho * rho;
res real = 1./3.* int2d (Th) (rho3 * sin (y));

Página 228
228 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

return res;
}

func real [ int ] GradVolume ( real [int] & X)


{
Vh rho;
rho [] = X;
varf dVolume (u, v) = int2d (Th) (rho * rho * sin (y) * v);
real [ int ] grad = dVolume (0, Vh);
graduado de regreso ;
}

matricial hessianV; // buffer


func matriz HessianVolume ( real [ int ] & X)
{
Vh rho;
rho [] = X;
varf d2Volume (w, v) = int2d (Th) (2 * rho * sin (y) * v * w);

https://translate.googleusercontent.com/translate_f 202/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
hessianV = d2Volume (Vh, Vh);
return hessianV;
}

Si queremos usar el volumen como una función de restricción, debemos envolverlo y sus derivadas en alguna
Funciones de FreeFem ++ que devuelven los tipos adecuados. No se realiza en las funciones anteriores en
caso en el que se quiera utilizarlo como función de fitness. La arpillera lagrangiana también hay que envolverla
dado que el Volumen no es lineal con respecto a ρ, tiene algunas derivadas de segundo orden no nulas.

func real [ int ] ipVolume ( real [ int ] & X) { real [ int ] vol = [Volume (X)]; return vol;}

matriz mdV; // buffer


func matriz ipGradVolume ( real [ int ] & X)
{ // transforma un vector en una matriz dispersa
real [ int , int ] dvol (1, Vh.ndof);
dvol (0,:) = GradVolume (X);
mdV = dvol;
return mdV;
}

matriz HLagrangian; // buffer


func matrix ipHessianLag ( real [ int ] & X, real objfact, real [ int ] & lambda)
{
HLagrangiano = objfact * HessianArea (X) + lambda [0] * HessianVolume (X);
return HLagrangian;
}

La función ipGradVolume podría traer algunos problemas durante el proceso de optimización porque
el vector de gradiente se transforma en una matriz dispersa, por lo que se descartará cualquier coeficiente nulo. Nosotros
aquí están obligados a darle a IPOPT la estructura a mano y usar el parámetro con nombre checkindex
para evitar una mala indexación durante las copias. Este gradiente es realmente denso, no hay razón para que
componentes para ser constantemente cero:

// estructura escasa de un vector denso


int [ int ] gvi (Vh.ndof), gvj = 0: Vh.ndof-1;
gvi = 0; // solo una linea

Página 229
8.5. SUPERFICIE MÍNIMA RESTRINGIDA EN 3D CON IPOPT 229

Estas dos matrices se pasarán a IPOPT con structjacc = [gvi, gvj]. El último restante
las cosas son la definición de límites. Los límites inferiores simples deben ser iguales a los componentes del
3
Proyección P1 del objeto ρ . Y elegimos α ∈ [0,1] para establecer V max en (1 - α) V (ρ objeto ) + α 4 3
πρ objeto ∞

e real = 0.1, r0 = 0.25, rr = 2-r0;


E real = 1 ./ (e * e), RR = 1 ./ (rr * rr);
// Un disco con sangría
func disc1 = sqrt (1./(RR+(E-RR)* cos (y) * cos (y))) * (1 + 0.1 * cos (9 * x));
// Casi un disco estándar
func disc2 = sqrt (1./(RR+(E-RR)* cos (x) * cos (x) * sin2));
Vh lb = max (disco1, disco2); // pegar las partes del objeto
real Vobj = Volumen (lb []); // volumen del objeto
real Vnvc = 4./3.* pi * pow (lb []. linfty, 3); // V para sin restricción de volumen
alfa real = 0,1;
Plot3D (lb [], "objeto_dentro", 0);
real [ int ] clb = 0., cub = [(1-alpha) * Vobj + alpha * Vnvc];

Llamando a IPOPT:

IPOPT (Área, GradArea, ipHessianLag,


ipVolume, ipGradVolume, rc [], // funciones y punto de partida
ub = ub [], lb = lb [], clb = clb, cub = cub, // límites simples y límites de volumen
checkindex = 1, structjacc = [gvi, gvj], // para copias de matrices seguras
maxiter = kkk <nadapt-1? 40: 150, // óptimo preciso solo para la última malla
iteración de adaptación

https://translate.googleusercontent.com/translate_f 203/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
inicio en caliente = kkk, lm = lm, uz = uz [], lz = lz [], // manejo de inicio en caliente
tol = 0,00001);

Plot3D (rc [], "Forma_en _" + kkk, 0); // muestra la solución actual

Por último, antes de cerrar el bucle de adaptación de la malla, tenemos que realizar dicha adaptación. La
la malla se adapta con respecto al campo vectorial X = (ρ, 0,0) (en coordenadas esféricas), no
directamente con respecto a ρ, de lo contrario la verdadera curvatura de la forma 3D no estaría bien tomada
en cuenta.

si (kkk <nadapt-1)
{
Th = adaptmesh (Th,
rc * cos (x) * sin (y), // X
rc * sin (x) * sin (y), // Y
rc * cos (y), // Z
nbvx = 50000,
periódico = [[2, y], [4, y]]); // mantiene la peridicidad de la malla
trama (Th);
forma de inicio = rc; // interpolación de formas en la nueva malla
uz = uz; // interpolación de variables duales
lz = lz;
} // terminara si
} // es de bucle de adaptación de malla

Aquí hay algunas imágenes de las superficies resultantes obtenidas para valores decrecientes de α (y una ligera
objeto más complicado que dos discos ortogonales). Recuperamos el objeto encerrado cuando α = 0
:

Página 230
230 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

8.6 Los optimizadores nlOpt


El paquete ff-NLopt proporciona una interfaz FreeFem a la biblioteca gratuita / de código abierto para aplicaciones no lineales.

https://translate.googleusercontent.com/translate_f 204/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Optimización, facilitando así el uso de varias rutinas de optimización gratuitas diferentes (restringidas o no)
disponible en línea junto con el solucionador de PDE. Todos los algoritmos están bien documentados en [ 47] , por lo que
aquí no se encontrará información exhaustiva sobre sus especificidades matemáticas y
se centrará en la forma en que se llaman en un script FreeFem. Uno que necesita información detallada sobre
estos algoritmos deben visitar dicha cita donde se da una descripción de cada uno de ellos, así como
tantos enlaces bibliográficos. La mayor parte del algoritmo basado en gradientes de nlOpt utiliza una matriz completa
aproximación de la arpillera, por lo que si está planeando resolver un problema a gran escala, nuestro consejo sería
Sería utilizar el optimizador IPOPT que definitivamente los superará. Finalmente, un ejemplo de uso puede ser
que se encuentra en el directorio examples ++ - load / con el nombre VarIneq2.edp
Todas las funciones de nlOpt se denominan así:

cargar "ff-NLopt"
... // defina J, u, y tal vez grad (J), algunas restricciones, etc.
min real = nloptXXXXXX (J, u, // parte inevitable
grad = <nombre del graduado (J)>, // si es necesario
lb = // matriz de límites inferiores
ub = // matriz de límites superiores
... // algunos argumentos opcionales:
// nombres de funciones de restricciones,

Página 231
8.6. LOS OPTIMIZADORES NLOPT 231

// criterios de parada,
// algo. parámetros específicos,
// etc ...
);

XXXXXX se refiere a la etiqueta del algoritmo (no necesariamente de 6 caracteres). u es la posición inicial
(una matriz de tipo [int] real) que será sobreescrito por el algoritmo, siendo el valor al final
el argmin encontrado. Y como de costumbre, J es una función que toma una matriz de tipo real [int] como argumento y
devolviendo un real. grad, lb y ub son argumentos "medio opcionales", en el sentido de que son
Obligatorio para algunas rutinas pero no para todas.
Los posibles parámetros con nombre opcionales son los siguientes, tenga en cuenta que no todos los
gorithm s (algunos no admiten restricciones, o un tipo de restricciones, algunos están basados en gradientes
y otros son libres de derivados, etc ...). Se puede consultar la tabla después de la descripción de los parámetros para
compruebe cuáles son los parámetros nombrados admitidos por un algoritmo específico. Usando un no admitido
El parámetro no detendrá el trabajo del compilador y rara vez interrumpe el tiempo de ejecución, simplemente será ignorado. Que
dicho, cuando es obvio que está utilizando mal una rutina, recibirá un mensaje de advertencia en tiempo de ejecución (por
ejemplo, si pasa un gradiente a un algoritmo libre derivado, o establece la población de un algoritmo no genético
uno, etc ...). En la siguiente descripción, n representa la dimensión del espacio de búsqueda.

Parámetros semi-opcionales:

grad = El nombre de la función que calcula el gradiente de la función de costo (prototipo


debe ser real [int] → real [int], tanto el argumento como el resultado deben tener el tamaño
norte). Esto es necesario tan pronto como se involucre un método basado en gradientes, ignorado si se define en
un contexto libre derivado.

lb / ub = Matrices de límites superior e inferior (tipo real [int]) de tamaño n. Se utiliza para definir el
límites dentro de los cuales la variable de búsqueda puede moverse. Necesario para algunos algoritmos,
opcional o no compatible con otros.

subOpt : Solo habilitado para el método Lagrangiano aumentado y MLSL que necesitan un sub-
optimizador para que funcione. Simplemente pase la etiqueta del algoritmo local deseado con un
cuerda.

Parámetros relacionados con las restricciones (opcional, sin usar si no se especifica):

IConst / EConst : permite pasar el nombre de una función que implementa alguna desigualdad
(resp. igualdad) restricciones en el espacio de búsqueda. El tipo de función debe ser real [int]
→ real [int] donde el tamaño de la matriz devuelta es igual al número de restricciones
(del mismo tipo - significa que todas las restricciones se calculan en un vector

https://translate.googleusercontent.com/translate_f 205/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
función). Para mezclar las restricciones de desigualdad e igualdad en una misma minimización
intento, se deben definir y pasar dos funciones vectoriales. Ver ejemplo por
más detalles sobre cómo deben implementarse estas restricciones.

gradIConst / gradEConst : Úselo para proporcionar las restricciones de desigualdad (resp. igualdad) gra-
dient. Estas son funciones de tipo real [int] → real [int, int]. Asumiendo que tenemos
definió una función de restricción (ya sea desigualdad o igualdad) con restricciones p, el tamaño
de la matriz devuelta por su gradiente asociado debe ser p × n (la i-ésima línea de la
matrix es el gradiente de la i-ésima restricción). Es necesario en un contexto basado en gradientes.
tan pronto como una función de restricción de desigualdad o igualdad se pasa al optimizador y
ignorado en todos los demás casos.

Página 232
232 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

tolIConst / tolEConst : valores de tolerancia para cada restricción. Esta es una matriz de tamaño
igual al número de restricciones de desigualdad (respectivamente igualdad). Valor predeterminado os establecido en
10 -12 para cada restricción de cualquier tipo.

Criterios de detención:

stopFuncValue : Hace que el algoritmo finalice cuando la función objetivo alcanza este valor real.
valor.

stopRelXTol : detiene el algoritmo cuando el relativo se mueve en cada dirección de la búsqueda


el espacio es más pequeño que este valor real.

stopAbsXTol : detiene el algoritmo cuando se mueve en cada dirección del espacio de búsqueda
es menor que el valor correspondiente en esta matriz real [int].

stopRelFTol : detiene el algoritmo cuando la variación relativa de la función objetivo es


menor que este valor real.

stopAbsFTol : detiene el algoritmo cuando la variación de la función objetivo es menor


que este valor real.

stopMaxFEval : detiene el algoritmo cuando el número de evaluaciones de aptitud alcanza este


valor entero.

stopTime : detiene el algoritmo cuando el tiempo de otpimización en segundos excede este real
valor. Este no es un máximo estricto: el tiempo puede excederlo ligeramente, dependiendo de
el algoritmo y qué tan lenta es la evaluación de su función.

Tenga en cuenta que cuando se utiliza un método AUGLAG o MLSL, el meta-algoritmo y el sub-
El algoritmo puede tener diferentes criterios de terminación. Por tanto, para algoritmos de este tipo, el
Se han definido los siguientes parámetros con nombre (solo agregando el prefijo SO - para el Sub-Optimizador)
para establecer la condición final del sub-algoritmo (el meta usa los de arriba):
SOStopFuncValue, SOStopRelXTol, y así sucesivamente ... Si estos no se utilizan, el sub-
optimizer utilizará los de la rutina maestra.

Otros parámetros con nombre:

popSize : número entero utilizado para cambiar el tamaño de la muestra para los métodos de búsqueda estocástica.
El valor predeterminado es una heurística peculiar del algoritmo elegido.

SOPopSize : Igual que el anterior, pero cuando la búsqueda estocástica se pasa a un metaalgoritmo.

nGradStored : el número (tipo entero) de gradientes para "recordar" de la anterior


Pasos de optimización: aumentar esto aumenta los requisitos de memoria, pero puede acelerar
convergencia. Se establece en un valor heurístico de forma predeterminada. Si se usa con AUGLAG o MLSL,
solo afectará al algoritmo subsidiario dado.

https://translate.googleusercontent.com/translate_f 206/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
La siguiente tabla resume las principales características de cada algoritmo, proporcionando las más importantes
información importante sobre qué características son compatibles con qué algoritmo y cuáles son los
argumentos inevitables que necesitan. Se pueden encontrar más detalles en [ 47] .

Página 233
8.6. LOS OPTIMIZADORES NLOPT 233

Degradado Restricciones Sub-


Etiqueta de identificación Nombre completo Límites Estocástico
-Basado Optar
Igualdad Desigualdad

DIRECTO División de rectángulos ●


DIRECTL
División localmente sesgada
rectángulos ●
DIRECTLRand
Aleatorizado localmente sesgado
dividir rectángulos ●
DIRECTNoScal División de rectángulos, sin escala

DIRECTLNoScal
División localmente sesgada
rectángulos - sin escala ●
DIRECTLRandNoScal División aleatoria localmente sesgada

rectángulos - sin escala



OrigDIRECT
La división original de Glabonsky
rectángulos ● ✔
OrigDIRECTL
Original Glabonsky's localmente
rectángulos divisorios sesgados ● ✔
StoGO
Estocástico (?) Global
Mejoramiento ●●
StoGORand
Estocástico aleatorio (?)
Optimización global ●●
LBFGS BFGS de bajo almacenamiento

PRÁCTICA

Eje principal

Var1
Memoria limitada desplazada de rango 1
métrica variable ●
Var2
Memoria limitada desplazada de rango 2
métrica variable ●
TNewton Newton truncado ●
TNewtonRestart
Descenso más empinado reiniciando
Newton truncado ●
TNewtonPregundo
BFGS preacondicionado
Newton truncado ●
TNewtonReiniciarPregundo BFGS preacondicionado truncado
Newton con el descenso más empinado reiniciando

CRS2
Búsqueda aleatoria controlada con
mutación local ✔ ●
MMA Método de movimiento de las asíntotas
✔ ● ✔
Optimización restringida por
COBYLA
aproximaciones lineales ✔ ✔ ✔
NEWUOA NEWUOA

NEWUOA para acotado


NEWUOABound
mejoramiento


NelderMead Nelder-Mead simplex

Sbplx

Subplejo

BOBYQA

BOBYQA

ISRES
Clasificación estocástica mejorada
estrategia de evolución ✔ ● ✔ ✔
SLSQP
Mínimo cuadrado secuencial
programación cuadrática ✔ ● ✔ ✔
MLSL Enlace único de varios niveles
✔ ● ● ●
MLSLLDS
Multinivel de baja discrepancia
enlace simple ✔ ● ● ●
AUGLAG
Restricciones aumentadas
lagrangiano ✔ ● ✔ ✔ ●
AUGLAGEQ
Aumento de las restricciones de igualdad
lagrangiano ✔ ● ✔ ✔ ●
Leyenda: ✔ Compatible y opcional
Compatible yedopcional
y opcional

Debe ser compatible


ser compatible
y opcional
yrted
opcional,
y opcional,
puedepuede
pcional, mayo
✔ DebeSin
conducir
serembargo,
compatible
a un
Sin
conduce
comportamiento
embargo,
a uncomportamiento
comportamiento
aviour
extraño
aunque.extraño.
puaj.
extraño.
Characteristi intrínseca
Característica característica
intrínseca deldel
rística
algalgoritmo
del algoritmo
e algoritmo
que luego necesitan
necesita
Necesito
uno
unauno
o más
ouno
más
uoinevitables
más inevitables
es inevitable

● parámetro para
ter trabajar
algoritmo, el
lam,
to work (para
población
tamaño
(fo k stochast
el tamaño
de lade
(para
estocástico
estocástico
población
ellatamaño
población
hastic
ade lasiempre
pulación
ize siempre
hasiempre
tiene tiene
un valor predeterminado,
Su valor, entonces
ellos
entonces
Oye,funcionarán
entonces
w funcionará
en
si es
trabajosisies
es
omitido) D)
Para rutinas con
inesalg
sub
consubsidiaria
algoritmos
algoritmos
subsidiarios
subsidiarios
y algoritmos

●/✔
solo, indica que
indica
th correspo
el que el correspondiente
en el correspondiente
respondiendo
la característica
dependerá
dependerá
del sub-
nd
de en
del chos
el sub- sub elegido
optimizador. r.

https://translate.googleusercontent.com/translate_f 207/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 234
234 CAPÍTULO 8. ALGORITMOS Y OPTIMIZACIÓN

8.7 Optimización con MPI


La única forma rápida de utilizar los algoritmos presentados anteriormente en una arquitectura paralela radica en
paralelizar la función de costo utilizada (que es en la mayoría de los casos de la vida real, la parte costosa de la
algoritmo). De alguna manera, proporcionamos una versión paralela del algoritmo CMA-ES. La paralelización
El principio es el trivial de los algoritmos evolutivos / genéticos: en cada iteración, la función de costo tiene que
ser evaluados N veces sin ninguna dependencia en absoluto, estos N cálculos se distribuyen igualmente
a cada proceso. Llamar a la versión MPI de CMA-ES es casi lo mismo que llamar a su secuencial
versión (se puede encontrar un ejemplo completo de uso en el archivo cmaes-mpi-VarIneq.edp):

cargar "mpi-cmaes"
... // define J, u y todo aquí
min real = cmaesMPI (J, u, stopTolFun = 1e-6, stopMaxIter = 3000);
cout << "el valor mínimo es" << min << "para u =" << u << endl ;

Si el tamaño de la población no se cambia usando el parámetro popsize, usará el valor heurístico


ligeramente cambiado para ser igual al múltiplo mayor más cercano del tamaño del comunicador utilizado
por el optimizador. FreeFem mpicommworld se utiliza de forma predeterminada. El usuario puede especificar el suyo
Comunicador MPI con el parámetro nombrado "comm =", consulte la sección MPI de este manual para
más información sobre comunicadores en FreeFem ++.

Página 235

https://translate.googleusercontent.com/translate_f 208/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Capítulo 9

Modelos matemáticos

Resumen Este capítulo profundiza en una serie de problemas que FreeFem ++ puede resolver. Es
un complemento del capítulo 3 que fue solo una introducción. Se invita a los usuarios a contribuir para hacer
esta base de datos de problemas crece.

9.1 Problemas estáticos


9.1.1 Película de jabón
Nuestro punto de partida aquí será el modelo matemático para encontrar la forma de la película de jabón que es
pegado al anillo en el plano xy

C = {(x, y); x = costo, y = sint, 0 ≤ t ≤ 2π}.

Suponemos que la forma de la película está descrita por el gráfico (x, y, u (x, y)) del desplazamiento vertical
u (x, y) (x 2 + y 2 <1) bajo una presión vertical p en términos de fuerza por unidad de área y una tensión inicial
µ en términos de fuerza por unidad de longitud.

Considere el "avión pequeño" ABCD, A: (x, y, u (x, y)), B: (x, y, u (x + δx, y)), C: (x, y, u (x + δx, y + δy))
y D: (x, y, u (x, y + δy)). Denote por n (x, y) = (n x (x, y), n y (x, y), n z (x, y)) el vector normal de
la superficie z = u (x, y). Vemos que la fuerza vertical debida a la tensión µ que actúa a lo largo del borde
AD es −µn x (x, y) δy y la fuerza vertical que actúa a lo largo del borde AD es

( ∂n x )
µn x (x + δx, y) δy ≃ µ n x (x, y) + δx (x, y) δy.
∂x

De manera similar, para las aristas AB y DC tenemos

T u(x+dx,y+dy)
u(x,y+δy)
T
T

(¶u/¶x)dx
u(x,y) T u(x+dx,y)

−µn y (x, y) δx, µ (n y (x, y) + ∂n y / ∂y) (x, y) δx.

235

Página 236
236 CAPÍTULO 9. MODELOS MATEMÁTICOS

La fuerza en la dirección vertical sobre la superficie ABCD debida a la tensión µ viene dada por

µ (∂n x / ∂x) δxδy + T (∂n y / ∂y) δyδx.

Suponiendo pequeños desplazamientos, tenemos

νx = (∂u / ∂x) / √ 1+ (∂u / ∂x) 2 + (∂u / ∂y) 2 ≃ ∂u / ∂x,

νy = (∂u / ∂y) / √ 1+ (∂u / ∂x) 2 + (∂u / ∂y) 2 ≃ ∂u / ∂y.

https://translate.googleusercontent.com/translate_f 209/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Dejando δx → dx, δy → dy, tenemos el equilibrio del desplazamiento vertical de la película de jabón en
ABCD por p
µdxdy∂ 2 u / ∂x 2 + µdxdy∂ 2 u / ∂y 2 + pdxdy = 0.

Usando el operador de Laplace ∆ = ∂ 2 / ∂x 2 + ∂ 2 / ∂y 2 , podemos encontrar el desplazamiento virtual escribir el


siguiente
−∆u = f en Ω (9,1)

donde f = p / µ, Ω = {(x, y); x 2 + y 2 <1}. La ecuación de Poisson (2 .1) aparece también en electrostática.
tomando la forma de f = ρ / ϵ donde ρ es la densidad de carga, ϵ la constante dieléctrica yu se llama
como potencial electrostático. La película de jabón está pegada al anillo ∂Ω = C, entonces tenemos el límite
condición
u = 0 en ∂Ω (9,2)

Si la fuerza es la gravedad, para simplificar, asumimos que f = −1.

Ejemplo 9.1 (un tutorial.edp)

1: borde a (t = 0,2 * pi) {x = cos (t); y = sin (t); etiqueta = 1;};


2:
3: disco de malla = buildmesh (a (50));
4: trazar (disco);
5: fespace femp1 (disco, P1);
6: femp1 u, v;
7: func f = -1;
8: problema laplace (u, v) =
9: int2d (disco) ( dx (u) * dx (v) + dy (u) * dy (v)) // forma bilineal
10: - int2d (disco) (f * v) // forma lineal
11: + en (1, u = 0); // condición de frontera
12: función = (xˆ2 + yˆ2-1) / 4; // ue: solución exacta
13: laplace;
14: femp1 err = u - ue;
15 :
16: plot (u, ps = "aTutorial.eps", valor = verdadero, espera = verdadero);
17: plot (err, value = true, wait = true);
18:
19: cout << "error L2 =" << sqrt ( int2d (disco) (errˆ2)) << endl ;
20: cout << "error H10 =" << sqrt ( int2d (disco) ((dx (u) -x / 2) ˆ2)
21: + int2d (disco) ((dy (u) -y / 2) ˆ2)) << endl ;
22:
23: disco = adaptmesh (disco, u, err = 0.01);
24: plot (disco, espera = 1);
25:
26: laplace;
27:
28: plot (u, valor = verdadero, espera = verdadero);
29: err = u - ue; // convertirse en función FE en malla adaptada

Página 237
9.1. PROBLEMAS ESTÁTICOS 237

30: plot (err, value = true, wait = true);


31: cout << "error L2 =" << sqrt ( int2d (disco) (errˆ2)) << endl;
32: cout << "error H10 =" << sqrt ( int2d (disco) (( dx (u) -x / 2) ˆ2)
33: + int2d (disco) (( dy (u) -y / 2) ˆ2)) << endl;

IsoValue
-0,243997
-0,231485
-0,218972
-0,206459
-0,193947
-0,181434
-0,168921
-0,156409
-0,143896
-0,131383
-0,11887
-0,106358
-0.0938451
-0.0813324
-0.0688198
-0.0563071
-0.0437944
-0.0312817
-0.018769
-0,00625634

https://translate.googleusercontent.com/translate_f 210/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Figura 9.2: una vista lateral de u

Figura 9.1: isovalor de u

En la línea 19, la estimación del error L 2 entre la solución exacta u e ,

(∫ ) 1/2
u h - u e 0, Ω = | u h - u e | 2 dxdy
Ω

y de la línea 20 a la línea 21, la estimación seminorme del error H 1

(∫ ) 1/2
| u h - u e | 1, Ω = | ∇u h - ∇u e | 2 dxdy
Ω

se realizan en la malla inicial. Los resultados son u h −u e 0, Ω = 0.000384045, | u h −u e | 1, Ω = 0,0375506.


Después de la adaptación, tenemos u h - u e 0, Ω = 0.000109043, | u h - u e | 1, Ω = 0,0188411. Entonces el
La solución numérica se mejora mediante la adaptación de la malla.

9.1.2 Electrostática
Suponemos que no existe una distribución de carga independiente de la corriente y del tiempo. Entonces el electrico
el campo E satisface

divE = ρ / ϵ, curlE = 0 (9,3)

donde ρ es la densidad de carga y ϵ se llama permitividad del espacio libre. De la segunda ecuación
en (9.3 ), podemos introducir el potencial electrostático tal que E = −∇φ. Luego tenemos Poisson's
ecuación −∆φ = f, f = −ρ / ϵ. Ahora obtenemos la línea equipotencial que es la curva de nivel de φ,
cuando no hay cargos excepto conductores {C i } 1, ···, K . Supongamos que K conductores C 1 , ···, C K
dentro de un recinto C 0 . Cada uno se mantiene a un potencial electrostático ϕ i . Asumimos que el
el recinto C0 se mantiene en potencial 0. Para conocer ϕ (x) en cualquier punto x del dominio Ω,
debe resolver
−∆ϕ = 0 en Ω, (9,4)

Página 238
238 CAPÍTULO 9. MODELOS MATEMÁTICOS

norte
donde Ω es el interior de C 0 menos los conductores C i , y Γ es el límite de Ω, es decir ∑
yo = 0 C yo .
Aquí g es cualquier función de x igual a ϕ i en C i y a 0 en C 0 . La ecuación de límite es una reducción
formulario para:
ϕ = ϕ i en C i , i = 1 ... N, ϕ = 0 en C 0 . (9,5)

Ejemplo 9.2 Primero damos la información geométrica; C 0 = {(x, y); x 2 + y 2 = 5 2 }, C 1 =


1 1
{(x, y):
0,3 2 (x - 2) 2 + 1 3 2 y 2 = 1}, C 2 = {(x, y): 0,3 2 (x + 2) 2 + 1 3 2 y 2 = 1}. Sea Ω el
disco encerrado por C 0 con los agujeros elípticos encerrados por C 1 y C 2 . Tenga en cuenta que C 0 se describe
en sentido contrario a las agujas del reloj, mientras que los orificios elípticos se describen en el sentido de las agujas del reloj, porque el límite debe ser
orientado de modo que el dominio computacional esté a su izquierda.

// un círculo con centro en (0, 0) y radio 5


borde C0 (t = 0,2 * pi) {x = 5 * cos (t); y = 5 * sin (t); }
borde C1 (t = 0,2 * pi) {x = 2 + 0,3 * cos (t); y = 3 * sin (t); }
borde C2 (t = 0,2 * pi) {x = -2 + 0,3 * cos (t); y = 3 * sin (t); }

malla Th = buildmesh (C0 (60) + C1 (-50) + C2 (-50));


plot (Th, ps = "electroMesh"); // figura 9.3
fespace Vh (Th, P1); // P1 FE-espacio
Vh uh, vh; // Función desconocida y de prueba.

https://translate.googleusercontent.com/translate_f 211/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
problema Electro (uh, vh) = // definición del problema
int2d (Th) (dx (uh) * dx (vh) + dy (uh) * dy (vh)) // bilineal
+ encendido (C0, uh = 0) // condición de frontera en C 0
+ encendido (C1, uh = 1) // +1 voltio en C 1
+ en (C2, uh = -1); // -1 voltio en C 2

Electro; // resolver el problema, ver figura 9.4 para la solución


plot (uh, ps = "electro.eps", espera = verdadero); // figura 9.4

Figura 9.3: Disco con dos orificios elípticos Figura 9.4: Líneas equipotenciales, donde C 1 es
ubicado en el lado derecho

Página 239
9.1. PROBLEMAS ESTÁTICOS 239

9.1.3 Aerodinámica
Consideremos un perfil de ala S en un flujo uniforme. El infinito estará representado por un gran círculo Γ ∞ .
Como anteriormente, debemos resolver

∆ϕ = 0 en Ω, ϕ | S = c, ϕ | Γ ∞ = u ∞1x - u ∞2x (9,6)

donde Ω es el área ocupada por el fluido, u ∞ es la velocidad del aire en el infinito, c es una constante de
ser determinado de modo que ∂ n ϕ sea continuo en el borde de salida P de S (el llamado Kutta-Joukowski
condición). La sustentación es proporcional a c. Para encontrar c usamos un método de superposición. Como todas las ecuaciones en
( 9.6 ) son lineales, la solución ϕ c es una función lineal de c

ϕ c = ϕ 0 + cϕ 1 , (9,7)

donde ϕ 0 es una solución de (9. 6) con c = 0 y ϕ 1 es una solución con c = 1 y velocidad cero en el infinito.
Con estos dos campos calculados, determinaremos c al requerir la continuidad de ∂ϕ / ∂n en el
borde de fuga. Una ecuación para la superficie superior de un NACA0012 (este es un perfil de ala clásico en
aerodinámica; la parte trasera del ala se llama borde de fuga) es:

y = 0,17735 x - 0.075597x - 0.212836x 2 + 0.17363x 3 - 0.06254x 4 . (9,8)

Tomando un ángulo de incidencia α tal que tanα = 0.1, debemos resolver

−∆ϕ = 0 en Ω, ϕ | Γ 1 = y - 0.1x, ϕ | Γ 2 = c, (9,9)

donde Γ 2 es el perfil del ala y Γ 1 es una aproximación de infinito. Uno encuentra c resolviendo:

−∆ϕ 0 = 0 enΩ, ϕ 0 | Γ 1 = y - 0.1x, ϕ 0 | Γ 2 = 0, (9,10)


−∆ϕ 1 = 0 enΩ, ϕ 1 | Γ 1 = 0, ϕ 1 | Γ 2 = 1. (9,11)

La solución ϕ = ϕ 0 + cϕ 1 nos permite encontrar c escribiendo que ∂ n ϕ no tiene salto en el borde de salida
P = (1,0). Tenemos ∂nϕ - (ϕ (P + ) - ϕ (P)) / δ donde P + es el punto justo encima de P en la dirección
normal al perfil a una distancia δ. Por lo tanto, el salto de ∂ n ϕ es (ϕ 0 | P + + c (ϕ 1 | P + - 1)) + (ϕ 0 | P - +
https://translate.googleusercontent.com/translate_f 212/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
c (ϕ 1 | P - - 1)) dividido por δ porque la normal cambia de signo entre las superficies inferior y superior.
Por lo tanto
ϕ 0 | P+ + ϕ 0 | P-
c=- , (9,12)
(ϕ 1 | P + + ϕ 1 | P - - 2)
que se puede programar como:

ϕ 0 (0.99,0.01) + ϕ 0 (0.99, −0.01)


c=- . (9,13)
(ϕ 1 (0.99,0.01) + ϕ 1 (0.99, −0.01) - 2)

Ejemplo 9.3 // Cálculo del flujo potencial alrededor de un perfil aerodinámico NACA0012.
// El método de descomposición se utiliza para aplicar la condición de Joukowski.
// La solución se busca en la forma psi0 + beta psi1 y beta es
// ajustado de modo que la presión sea continua en el borde de fuga

borde a (t = 0,2 * pi) {x = 5 * cos (t); y = 5 * sin (t); }; // se aproxima al infinito

borde superior (t = 0,1) {x = t;


y = 0.17735 * sqrt (t) -0.075597 * t
- 0,212836 * (tˆ2) + 0,17363 * (tˆ3) -0,06254 * (tˆ4); }
borde inferior (t = 1,0) {x = t;

Página 240
240 CAPÍTULO 9. MODELOS MATEMÁTICOS

y = - (0.17735 * sqrt (t) -0.075597 * t


-0,212836 * (tˆ2) + 0,17363 * (tˆ3) -0,06254 * (tˆ4)); }
borde c (t = 0,2 * pi) {x = 0,8 * cos (t) +0,5; y = 0,8 * sin (t); }

esperar = verdadero ;
Zoom de malla = buildmesh (c (30) + superior (35) + inferior (35));
malla Th = buildmesh (a (30) + superior (35) + inferior (35));
fespace Vh (Th, P2); // Espacio P1 FE
Vh psi0, psi1, vh; // Función desconocida y de prueba.
fespace ZVh (Zoom, P2);

resolver Joukowski0 (psi0, vh) = // definición del problema


int2d (Th) (dx (psi0) * dx (vh) + dy (psi0) * dy (vh)) // forma bilineal
+ encendido (a, psi0 = y-0.1 * x) // formulario de condición de límite
+ encendido (superior, inferior, psi0 = 0);
plot (psi0);

resolver Joukowski1 (psi1, vh) = // definición del problema


int2d (Th) (dx (psi1) * dx (vh) + dy (psi1) * dy (vh)) // forma bilineal
+ encendido (a, psi1 = 0) // formulario de condición de límite
+ encendido (superior, inferior, psi1 = 1);

gráfico (psi1);

// continuidad de la presión en el borde de fuga


beta real = psi0 (0.99,0.01) + psi0 (0.99, -0.01);
beta = -beta / (psi1 (0,99,0,01) + psi1 (0,99, -0,01) -2);

Vh psi = beta * psi1 + psi0;


gráfico (psi);
ZVh Zpsi = psi;
gráfico (Zpsi, bw = verdadero);
ZVh cp = -dx (psi) ˆ2 - dy (psi) ˆ2;
parcela (cp);
ZVh Zcp = cp;
plot (Zcp, nbiso = 40);

https://translate.googleusercontent.com/translate_f 213/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 9.5: isovalor de cp = - (∂ x ψ) 2 - (∂ y ψ) 2 Figura 9.6: Zoom de cp

Página 241
9.1. PROBLEMAS ESTÁTICOS 241

9.1.4 Estimación de errores


Hay estimaciones famosas entre el resultado numérico u h y la solución exacta u del problema
2.1 y 2.2: Si las triangulaciones {T h } h ↓ 0 es regular (ver Sección 5. 4), entonces tenemos las estimaciones

| ∇u - ∇u h | 0, Ω ≤ C 1 hora (9,14)
u - u h 0, Ω ≤C2h2 (9,15)

con constantes C 1 , C 2 independientes de h, si u está en H 2 (Ω). Se sabe que u ∈ H 2 (Ω) si Ω es convexo.


En esta sección verificamos (9.14 ) y (9.15). Captaremos el error numérico si usamos el
derivada, por lo que usaremos lo siguiente para ( 9.14) .

∫ ∫ ∫
| ∇u - ∇u h | 2 dxdy = ∇u · ∇ (u - 2u h ) dxdy + ∇u h · ∇u h dxdy
Ω Ω Ω

∫ ∫
= f (u - 2u h ) dxdy + fu h dxdy
Ω Ω

Las constantes C 1 , C 2 dependen de T h y f, por lo que las encontraremos por FreeFem ++. En general, nosotros
no puede obtener la solución u como funciones elementales (vea la Sección 4.8 ) incluso si las funciones espeticas son
adicional. En lugar de la solución exacta, aquí usamos la solución aproximada u 0 en V h (T h , P 2 ), h ∼ 0.

Ejemplo 9.4

1: malla Th0 = cuadrado (100,100);


2: espacio libre V0h (Th0, P2);
3: V0h u0, v0;
4: función f = x * y; // sin (pi * x) * cos (pi * y);
5:
6: resuelva Poisson0 (u0, v0) =
7: int2d (Th0) ( dx (u0) * dx (v0) + dy (u0) * dy (v0)) // forma bilineal
8: - int2d (Th0) (f * v0) // forma lineal
9: + en (1,2,3,4, u0 = 0); // condición de frontera
10:
11: trama (u0);
12:
13: real [int] errL2 (10), errH1 (10);
14:
15: para ( int i = 1; i <= 10; i ++) {
dieciséis : malla Th = cuadrado (5 + i * 3,5 + i * 3);
17: fespace Vh (Th, P1);
18: fespace Ph (Th, P0);
19: Ph h = h Triángulo; // obtener el tamaño de todos los triángulos
20: Vh u, v;
21: resolver Poisson (u, v) =
22: int2d (Th) (dx (u) * dx (v) + dy (u) * dy (v)) // forma bilineal
23: - int2d (Th) (f * v) // forma lineal
24: + en (1,2,3,4, u = 0); // condición de frontera
25: V0h uu = u;
26: errL2 [i-1] = sqrt ( int2d (Th0) ((uu - u0) ˆ2)) / h []. maxˆ2;
27: errH1 [i-1] = sqrt ( int2d (Th0) (f * (u0-2 * uu + uu))) / h []. max;
28:}

https://translate.googleusercontent.com/translate_f 214/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
29: cout << "C1 =" << errL2.max << "(" << errL2.min << ")" << endl;
30: cout << "C2 =" << errH1.max << "(" << errH1.min << ")" << endl;

Podemos adivinar que C 1 = 0.0179253 (0.0173266) y C 2 = 0.0729566 (0.0707543), donde los números
dentro de los paréntesis son mínimos en el cálculo.

Página 242
242 CAPÍTULO 9. MODELOS MATEMÁTICOS

9.1.5 Condiciones de contorno periódicas


Ahora resolvemos la ecuación de Poisson

−∆u = sin (x + π / 4.) ∗ cos (y + π / 4.)

en el cuadrado] 0,2π [ 2 bajo la condición de contorno bi-periódica u (0, y) = u (2π, y) para todo y y u (x, 0) =
u (x, 2π) para todo x. Estas condiciones de contorno se logran a partir de la definición de los períodos finitos
espacio de elementos.

Ejemplo 9.5 (periodic.edp)

malla Th = cuadrado (10,10, [2 * x * pi, 2 * y * pi]);


// definió el espacio festivo con condición periódica
// etiqueta: 2 y 4 son el lado izquierdo y derecho con y la curva de abscisas
// 1 y 2 son el lado inferior y superior con x la curva de abscisas
fespace Vh (Th, P2, periódico = [[2, y], [4, y], [1, x], [3, x]]);
Vh uh, vh; // Función desconocida y de prueba.
func f = sin (x + pi / 4.) * cos (y + pi / 4.); // función del lado derecho

problema laplace (uh, vh) = // definición del problema


int2d (Th) (dx (uh) * dx (vh) + dy (uh) * dy (vh)) // forma bilineal
+ int2d (Th) (-f * vh) // forma lineal
;

laplace ; // resolver la trama del problema (uh); // para ver el resultado


plot (uh, ps = "period.eps", valor = verdadero);

IsoValue
-0,441699
-0,391928
-0,342157
-0,292387
-0,242616
-0,192845
-0,143075
-0.0933038
-0.0435331
0,00623761
0.0560083
0.105779
0.15555
0.20532
0.255091
0.304862
0.354633
0.404403
0.454174
0.503945

Figura 9.7: El isovalor de la solución u con condición de contorno periódica

La condición periódica no requiere necesariamente límites paralelos. El ejemplo 9.6 da tal


ejemplo.

Ejemplo 9.6 (periodic4.edp)

r real = 0,25;
// un diamante con un agujero

https://translate.googleusercontent.com/translate_f 215/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 243
9.1. PROBLEMAS ESTÁTICOS 243

borde a (t = 0,1) {x = -t + 1; y = t; etiqueta = 1;};


borde b (t = 0,1) {x = -t; y = 1-t; etiqueta = 2;};
borde c (t = 0,1) {x = t-1; y = -t; etiqueta = 3;};
borde d (t = 0,1) {x = t; y = -1 + t; etiqueta = 4;};
borde e (t = 0,2 * pi) {x = r * cos (t); y = -r * sin (t); etiqueta = 0;};
int n = 10;
malla Th = buildmesh (a (n) + b (n) + c (n) + d (n) + e (n));
plot (Th, espera = 1);
r2 real = 1,732;
func abs = sqrt (xˆ2 + yˆ2);
// advertencia de condición periódica:
// lado ayc
// en el lado a (etiqueta 1) x ∈ [0, 1] o x - y ∈ [−1, 1]
// en el lado c (etiqueta 3) x ∈ [−1, 0] o x - y ∈ [−1, 1]
// por lo que la abscisa común puede ser respectivamente x y x + 1
// o puede probar la abscisa curvilina x - y y x - y
// 1 primera forma
// fespace Vh (Th, P2, periódico = [[2,1 + x], [4, x], [1, x], [3,1 + x]]);
// 2 segunda vía
fespace Vh (Th, P2, periódico = [[2, x + y], [4, x + y], [1, xy], [3, xy]]);

Vh uh, vh;

func f = (y + x + 1) * (y + x-1) * (y-x + 1) * (yx-1);


real intf = int2d (Th) (f);
real mTh = int2d (Th) (1);
real k = intf / mTh;
problema laplace (uh, vh) =
int2d (Th) (dx (uh) * dx (vh) + dy (uh) * dy (vh)) + int2d (Th) ((kf) * vh);
laplace;
plot (uh, espera = 1, ps = "perio4.eps");

Figura 9.8: El isovalor de la solución u para ∆u = ((y + x) 2 + 1) ((y - x) 2 + 1) - k, en Ω y


∂ n u = 0 en el hoyo, y con dos condiciones de límite periódicas en el borde externo

Otro ejemplo sin borde igual, solo para ver si el código funciona.

Página 244

https://translate.googleusercontent.com/translate_f 216/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
244 CAPÍTULO 9. MODELOS MATEMÁTICOS

Ejemplo 9.7 (periodic4bis.edp)

// condición de contorno irregular.


// para construir la frontera AB
macro LINEBORDER (A, B, lab) border A # B (t = 0,1) {real t1 = 1.-t;
x = A # x * t1 + B # x * t; y = A # y * t1 + B # y * t; etiqueta = laboratorio;} // MOE
// calcular || AB || a = (ax, ay) et B = (bx, by)
macro dist (ax, ay, bx, by) sqrt (cuadrado ((ax) - (bx)) + cuadrado ((ay) - (by))) // MOE
macro Grad (u) [dx (u), dy (u)] // MOE

Ax real = 0,9, Ay = 1; real Bx = 2, By = 1;


Cx real = 2,5, Cy = 2,5; real Dx = 1, Dy = 2;
gx real = (Ax + Bx + Cx + Dx) / 4 .; gy real = (Ay + By + Cy + Dy) / 4 .;

LINEBORDER (A, B, 1)
LINEBORDER (B, C, 2)
LINEBORDER (C, D, 3)
LINEBORDER (D, A, 4)

int n = 10;

real l1 = dist (Ax, Ay, Bx, By);


real l2 = dist (Bx, By, Cx, Cy);
real l3 = dist (Cx, Cy, Dx, Dy);
real l4 = dist (Dx, Dy, Ax, Ay);
func s1 = dist (Ax, Ay, x, y) / l1; // absisse en AB = || AX || / || AB ||
func s2 = dist (Bx, By, x, y) / l2; // absisse en BC = || BX || / || BC ||
func s3 = dist (Cx, Cy, x, y) / l3; // absisse en CD = || CX || / || CD ||
func s4 = dist (Dx, Dy, x, y) / l4; // absisse en DA = || DX || / || DA ||

malla Th = buildmesh (AB (n) + BC (n) + CD (n) + DA (n), límite fijo = 1); //

verbosidad = 6; // para ver el valor de la abscisa, vierta la condición periódica.


fespace Vh (Th, P1, periódico = [[1, s1], [3, s3], [2, s2], [4, s4]]);
verbosidad = 1;
Vh u, v;
cc real = 0;
cc = int2d (Th) ((x-gx) * (y-gy) -cc) /Th.area;
cout << "compatibilidad =" << int2d (Th) ((x-gx) * (y-gy) -cc) << endl;

resolver Poisión (u, v) = int2d (Th) (Grad (u) '* Grad (v) + 1e-10 * u * v)
-int2d (Th) (10 * v * ((x-gx) * (y-gy) -cc));
plot (u, espera = 1, valor = 1);

Ejemplo 9.8 (Period-Poisson-cube-ballon.edp)

verbosidad = 1;
cargar "msh3"
cargar "tetgen"
cargar "medit"

bool buildTh = 0;

Página 245
9.1. PROBLEMAS ESTÁTICOS 245

mesh3 Th;
prueba { // una forma de construir una vez la malla y leer si el archivo existe.
Th = readmesh3 ("Th-hex-sph. Mesh ");
}
catch (...) {buildTh = 1;}
if (buildTh) {

https://translate.googleusercontent.com/translate_f 217/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
...
poner la página de ejemplo de código // 5.11. 1151
sin la primera línea
}

fespace Ph (Th, P0);


verbosidad = 50;
fespace Vh (Th, P1, periódico = [[3, x, z], [4, x, z], [1, y, z], [2, y, z], [5, x, y], [6, x, y]]); //
detrás y delante
verbosidad = 1;
Ph reg = región ;

cout << "centro =" << reg (0,0,0) << endl ;


cout << "exterieur =" << reg (0,0,0.7) << endl ;

macro Grad (u) [dx (u), dy (u), dz (u)] // MOE

Vh uh, vh;
real x0 = 0.3, y0 = 0.4, z0 = 06;
func f = sin (x * 2 * pi + x0) * sin (y * 2 * pi + y0) * sin (z * 2 * pi + z0);
gn real = 1 .;
real cf = 1;
problema P (uh, vh) =
int3d (Jue, 1) (Grad (uh) '* Grad (vh) * 100)
+ int3d (Jue, 2) (Grad (uh) '* Grad (vh) * 2)
+ int3d (Th) (vh * f)
;
PAG;
plot (uh, espera = 1, nbiso = 6);
medit (" uh ", Th, uh);

9.1.6 Problemas de Poisson con condición de frontera mixta


Aquí consideramos la ecuación de Poisson con condiciones de contorno mixtas: Para funciones dadas f y
g, te encuentras de tal manera que

−∆u = f en Ω
u = g en Γ D , ∂u / ∂n = 0 en Γ N (9,16)

donde Γ D es una parte de la Γ límite y Γ N = Γ \ Γ D . La solución u tiene la singularidad en


los puntos {γ 1 , gamma 2 } = Γ D ∩ Γ N . Cuando Ω = {(x, y); −1 <x <1, 0 <y <1}, Γ N = {(x, y); −1 ≤
x <0, y = 0}, Γ D = ∂Ω \ Γ N , la singularidad aparecerá en γ 1 = (0,0), γ 2 (−1,0), y u tiene la
expresión
u = K yo u S + u R , u R ∈ H 2 (cerca de γ i ), i = 1,2
1/2
con constantes K i . Aquí u S = r j sin (θ j / 2) por la coordenada polar local (r j , θ j en γ j tal que
(r 1 , θ 1 ) = (r, θ). En lugar del sistema de coordenadas poler (r, θ), usamos que r = sqrt (x2 + y2) y
θ = atan2 (y, x) en FreeFem ++.

Página 246
246 CAPÍTULO 9. MODELOS MATEMÁTICOS

https://translate.googleusercontent.com/translate_f 218/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 9.10:
Figura 9.9: vista del isovalor de superficie de ver el corte de la solución uh con ffmedit
solución periódica uh

Ejemplo 9.9 Suponga que f = −2 × 30 (x 2 + y 2 ) y g = u e = 10 (x 2 + y 2 ) 1/4 sin ([tan −1 (y / x)] / 2) +


30 (x 2 y 2 ), donde u e S es la solución exacta.

1: borde N (t = 0,1) {x = -1 + t; y = 0; etiqueta = 1; };


2: borde D1 (t = 0,1) {x = t; y = 0; etiqueta = 2;};
3: borde D2 (t = 0,1) {x = 1; y = t; etiqueta = 2; };
4: borde D3 (t = 0,2) {x = 1-t; y = 1; etiqueta = 2;};
5: borde D4 (t = 0,1) {x = -1; y = 1-t; etiqueta = 2; };
6:
7: malla T0H = buildmesh (N (10) + D1 (10) + D2 (10) + D3 (20) + D4 (10));
8: trazar (T0h, esperar = verdadero);
9: espacio libre V0h (T0h, P1);
10: V0h u0, v0;
11:
12: función f = -2 * 30 * (xˆ2 + yˆ2); // función dada
13: // el término singular de la solución es K * us (K: constante)
14: func us = sin (atan2 (y, x) / 2) * sqrt (sqrt (xˆ2 + yˆ2));
15: K real = 10 .;
16: func ue = K * us + 30 * (xˆ2 * yˆ2);
17:
18: resuelve Poisson0 (u0, v0) =
19: int2d (T0h) (dx (u0) * dx (v0) + dy (u0) * dy (v0)) // forma bilineal
20: - int2d (T0h) (f * v0) // forma lineal
21: + en (2, u0 = ue); // condición de frontera
22:
23: // adaptación por el término singular
24: malla Th = adaptmesh (T0h, us);
25: para ( int i = 0; i <5; i ++)
26: {
27: malla Th = adaptmesh (Th, us);
28:};

Página 247
9.1. PROBLEMAS ESTÁTICOS 247

29:
30: espacio libre Vh (Th, P1);
31: Vh u, v;
32: resuelve Poisson (u, v) =
33: int2d (Th) (dx (u) * dx (v) + dy (u) * dy (v)) // forma bilineal
34: - int2d (Th) (f * v) // forma lineal
35: + en (2, u = ue); // condición de frontera
36:
37: / * grafica la solución * /
38: plot (Th, ps = "adaptDNmix.ps");
39: trama (u, espera = verdadero);
40:
41: Vh uue = ue;
42: H1e real = sqrt ( int2d (Th) (dx (uue) ˆ2 + dy (uue) ˆ2 + uueˆ2));
43:
44: / * calcular la norma H1 Sobolev * /
45: Vh err0 = u0 - ue;
46: Vh err = u - ue;
47: Vh H1err0 = int2d (Th) (dx (err0) ˆ2 + dy (err0) ˆ2 + err0ˆ2);
48: Vh H1err = int2d (Th) (dx (err) ˆ2 + dy (err) ˆ2 + errˆ2);
49: cout << "Error relativo en la primera malla" << int2d (Th) (H1err0) / H1e << endl ;
50: cout << "Error relativo en malla adaptativa" << int2d (Th) (H1err) / H1e << endl;

De la línea 24 a la 28, la adaptación de mallas se realiza utilizando la base del término singular. En 42

https://translate.googleusercontent.com/translate_f 219/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
línea, H1e = u e 1, Ω se calcula. En las 2 últimas líneas se calculan los errores relativos, es decir,

u0
h - u e 1, Ω / H1e = 0,120421
tu un
h - u e 1, Ω / H1e = 0.0150581

donde u 0 h es la solución numérica en T0h y u a h ¿Estás en este programa?

9.1.7 Poisson con elemento finito mixto


Aquí consideramos la ecuación de Poisson con problemas de valores de frontera mixtos: Para funciones dadas
f, g d , g n , encuentre p tal que

−∆p = 1 en Ω
p=gd en Γ D , ∂p / ∂n = g n en Γ N (9,17)

donde Γ D es una parte de la Γ límite y Γ N = Γ \ Γ D .


La formulación mixta es: encuentre pyu tal que

∇p + u = 0 en Ω
∇.u = f en Ω
p=gd en Γ D , ∂un = g n .n en Γ N (9,18)

donde g n es un vector tal que g n .n = g n .


La formulación variante es,

∀v ∈ V 0 , ∫ p∇.v + vv = g d v.n
Ω
Γd


∀q ∈ P ∫ q∇.u = qf
Ω
Ω

∂un = g n .n en Γ N (9,19)

Página 248
248 CAPÍTULO 9. MODELOS MATEMÁTICOS

donde los espacios funcionales son:

2 (Ω), 2 (Ω) 2 , ∇.v ∈ L 2 (Ω)}


P=L V = H (div) = {v ∈ L

y
V 0 = {v ∈ V; vn = 0 en Γ N }.
Para escribir, el ejemplo de FreeFem ++, solo tenemos que elegir los espacios de elementos finitos. aquí V
el espacio se discretiza con el elemento finito de Raviart-Thomas RT0 y P se discretiza mediante la constante finita
elemento P0.

Ejemplo 9.10 (LaplaceRT.edp)

malla Th = cuadrado (10,10);


fespace Vh (Th, RT0);
fespace Ph (Th, P0);
func gd = 1 .;
func g1n = 1 .;
func g2n = 1 .;

Vh [u1, u2], [v1, v2];


Ph p, q;

problema laplaceMixte ([u1, u2, p], [v1, v2, q],


solucionador = GMRES, eps = 1.0e-10,
tgv = 1e30, dimKrylov = 150)
=
int2d (Th) (p * q * 1e-15 // este término está aquí para ser sur
// que todas las submatrices son inversibles (requisito de LU)
+ u1 * v1 + u2 * v2 + p * (dx (v1) + dy (v2)) + (dx (u1) + dy (u2)) * q)
+ int2d (Th) (q)

https://translate.googleusercontent.com/translate_f 220/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
- int1d (Th, 1,2,3) (gd * (v1 * Nx + v2 * Ny)) // en Γ D
+ en (4, u1 = g1n, u2 = g2n); // en Γ N

laplaceMixte;

plot ([u1, u2], coef = 0.1, wait = 1, ps = "lapRTuv.eps", value = true);


plot (p, fill = 1, wait = 1, ps = "laRTp.eps", value = true);

9.1.8 Indicador de adaptación métrica y error residual


Hacemos una adaptación de malla métrica y calculamos el indicador de error residual clásico η T en el elemento
T para el problema de Poisson.

Ejemplo 9.11 (adaptindicatorP2.edp) Primero, resolvemos el mismo problema que en un ejemplo anterior.

1: borde ba (t = 0,1.0) {x = t; y = 0; etiqueta = 1;}; // ver Fig, 5.15


2: borde bb (t = 0,0.5) {x = 1; y = t; etiqueta = 2;};
3: borde bc (t = 0,0.5) {x = 1-t; y = 0.5; etiqueta = 3;};
4: borde bd (t = 0.5,1) {x = 0.5; y = t; etiqueta = 4;};
5: borde sea (t = 0.5,1) {x = 1-t; y = 1; etiqueta = 5;};
6: borde bf (t = 0.0,1) {x = 0; y = 1-t; etiqueta = 6;};

Página 249
9.1. PROBLEMAS ESTÁTICOS 249

7: malla Th = buildmesh (ba (6) + bb (4) + bc (4) + bd (4) + be (4) + bf (6));


8: savemesh (Th, "th.msh");
9: espacio libre Vh (Th, P2);
10: espacio libre Nh (Th, P0);
11: Vh u, v;
12: Nh rho;
13: viso real [int] (21);
14: para ( int i = 0; i <viso.n; i ++)
15 : viso [i] = 10.ˆ (+ (i-16.) / 2.);
16: error real = 0,01;
17: función f = (xy);
18: problema Probem1 (u, v, solucionador = CG, eps = 1.0e-6) =
19: int2d (Th, qforder = 5) (u * v * 1.0e-10 + dx (u) * dx (v) + dy (u) * dy (v))
20: + int2d (Th, qforder = 5) (-f * v);
21: / *************

Ahora, el indicador de error local η T es:


1
2

Uh
ηT= + ∑ h e || [ ] || L2 2 (e)
h 2T || f + ∆u h || 2 L 2 (T)
∂n k
e∈E K

donde h T es el borde más largo de T, E T es el conjunto del borde T que no está en Γ = ∂Ω, n T es la unidad exterior
normal a K, h e es la longitud del borde e, [g] es el salto de la función g a través del borde (valor izquierdo
menos el valor correcto).
Por supuesto, podemos usar una forma variacional para calcular η 2
T , con función de prueba función constante en
cada triángulo.

29: ************* /
30:
31: indicador varf2 (uu, chiK) =
32: intalledges (Th) (chiK * lenEdge * square (jump (Nx * dx (u) + Ny * dy (u))))
33: + int2d (Th) (chiK * cuadrado (hTriángulo * (f + dxx (u) + dyy (u))));
34: para (int i = 0; i <4; i ++)
35: {
36: Probem1;
37: cout << u []. min << "" << u []. max << endl;
38: plot (u, espera = 1);
39: cout << "indicador2" << endl;
40:

https://translate.googleusercontent.com/translate_f 221/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
41: rho [] = indicador2 (0, Nh);
42: rho = raíz cuadrada (rho);
43: cout << "rho = min "<< rho []. min <<" max = "<< rho []. max << endl ;
44: plot (rho, fill = 1, wait = 1, cmm = "indicador de densidad", ps = "rhoP2.eps",
valor = 1, viso = viso, nbiso = viso.n);
45: plot (Th, espera = 1, cmm = "Malla", ps = "ThrhoP2.eps");
46: Th = adaptmesh (Th, [dx (u), dy (u)], err = error, anisomax = 1);
47: plot (Th, espera = 1);
48: u = u;
49: rho = rho;
50: error = error / 2;
51:};

Si el método es correcto, esperamos ver los gráficos con una función casi constante η en su
computadora como en la figura 9.11.

Página 250
250 CAPÍTULO 9. MODELOS MATEMÁTICOS

densidad del indicador Malla


IsoValue
1e-08
3.16228e-08
1e-07
3.16228e-07
1e-06
3.16228e-06
1e-05
3.16228e-05
0,0001
0.000316228
0,001
0,00316228
0,01
0.0316228
0,1
0.316228
1
3.16228
10
31.6228
100

Figura 9.11: Densidad del indicador de error con métrica isotrópica P 2

9.1.9 Adaptación mediante indicador de error residual


En el ejemplo anterior calculamos el indicador de error, ahora lo usamos, para adaptar la malla.
El nuevo tamaño de malla viene dado por las siguientes fórmulas:

h n (x)
h n + 1 (x) =
f n (η K (x))

donde η n (x) es el nivel de error en el punto x dado por el indicador de error local, h n es la “malla anterior
tamaño ”, y f n es una función de usuario definida por f n = min (3, max (1/3, η n / η ∗
n )) donde η ∗ n = media (η n ) c,
yc es un coeficiente de usuario generalmente cercano a uno.

Ejemplo 9.12 (AdaptResidualErrorIndicator.edp)


Primero, un cálculo macro MeshSize para obtener un tamaño de malla P 1 como el promedio de la longitud del borde.

// macro el obtener el tamaño de malla actual


// parámetro
// en: La malla
// Vh P1 fespace en Th
// fuera :
// h: el conjunto finito de elementos finitos Vh para el tamaño de malla actual
macro cálculo de tamaño de malla (Th, Vh, h)
{/ * Th malla Vh P1 espacio de elementos finitos
h el valor del tamaño de malla P1 * /

https://translate.googleusercontent.com/translate_f 222/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
recuento real [int] (Th.nv);
/ * tamaño de malla (lenEdge = integral (e) 1 ds) * /
varf vmeshsizen (u, v) = intalledges (Th, qfnbpE = 1) (v);
/ * número de vértice de borde / par * /
varf vedgecount (u, v) = intalledges (Th, qfnbpE = 1) (v / lenEdge);
/*
cálculo del tamaño de la malla
----------------------------- * /

Página 251
9.1. PROBLEMAS ESTÁTICOS 251

count = vedgecount (0, Vh);


h [] = 0 .;
h [] = vmeshsizen (0, Vh);
cout << "count min =" << count.min << "" << count.max << endl;
h [] = h [] ./ cuenta;
cout << "- tamaño de malla encuadernado =" << h []. min << "" << h []. max << endl;
} // fin de macro MeshSizecomputation

Una segunda macro para remallar según el nuevo tamaño de malla.

// macro para remallar según el indicador de residual


// en:
// La malla
// Ph P0 fespace en Th
// Vh P1 fespace en Th
// vindicador el varf de para evaluar el indicador a 2
// coef en etameam ..
// ------

macro ReMeshIndicator (Th, Ph, Vh, vindicator, coef)


{
Vh h = 0;
/ * evalúa el tamaño de la malla * /
Computación MeshSize (Th, Vh, h);
Ph etak;
etak [] = vindicador (0, Ph);
etak [] = sqrt (etak []);
etastar real = coef * (etak []. sum / etak []. n);
cout << "etastar =" << etastar << "suma =" << etak []. suma << "" << endl;

/ * aquí etaK es discontinuo


utilizamos la proyección P1 L2 con agrupamiento de masa. * /

Vh fn, sigma;
varf veta (sin usar, v) = int2d (Th) (etak * v);
varf vun (sin usar, v) = int2d (Th) (1 * v);
fn [] = veta (0, Vh);
sigma [] = vun (0, Vh);
fn [] = fn [] ./ sigma [];
fn = max (min (fn / etastar, 3.), 0,3333);

/ * nuevo tamaño de malla * /


h = h / fn;
/ * plot (h, espera = 1); * /
/ * construye la nueva malla * /
Th = adaptmesh (Th, IsMetric = 1, h, splitpbedge = 1, nbvx = 10000);
}

Omitimos la construcción de la malla, vea el ejemplo anterior,

// Definición de espacio FE ---


fespace Vh (Th, P1); // para el tamaño de la malla y la solución
fespace Ph (Th, P0); // para el indicador de error

hinit real = 0,2; // tamaño de malla inicial


Vh h = hinit; // la función FE para el tamaño de la malla
// para construir una malla con un tamaño de malla dado: meshsize

https://translate.googleusercontent.com/translate_f 223/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 252
252 CAPÍTULO 9. MODELOS MATEMÁTICOS

Th = adaptmesh (Th, h, IsMetric = 1, splitpbedge = 1, nbvx = 10000);


plot (Th, espera = 1, ps = "RRI-Th-init.eps");
Vh u, v;

func f = (xy);

problema de Poisson (u, v) =


int2d (Th, qforder = 5) (u * v * 1.0e-10 + dx (u) * dx (v) + dy (u) * dy (v))
- int2d (Th, qforder = 5) (f * v);

indicador varf2 (no utilizado, chiK) =


intalledges (Th) (chiK * lenEdge * square (jump (Nx * dx (u) + Ny * dy (u))))
+ int2d (Th) (chiK * cuadrado (hTriángulo * (f + dxx (u) + dyy (u))));

para (int i = 0; i <10; i ++)


{
u = u;
Poisson;
plot (Th, u, espera = 1);
cc real = 0,8;
si (i> 5) cc = 1;
ReMeshIndicator (Th, Ph, Vh, indicador2, cc);
plot (Th, espera = 1);
}

IsoValue IsoValue
5.89664e-05 -123.488
0.000111887 -123.476
0.000147167 -123.464
0.000182447 -123.452
0.000217727 -123,44
0.000253008 -123.428
0.000288288 -123.416
0.000323568 -123.404
0.000358848 -123.392
0.000394129 -123,38
0.000429409 -123,368
0.000464689 -123,356
0.000499969 -123,344
0.000535249 -123,332
0.00057053 -123,32
0.00060581 -123.308
0.00064109 -123.296
0.00067637 -123.284
0.000711651 -123.272
0.000799851 -123,26

Figura 9.12: el indicador de error con isotrópico P 1 , la malla y el isovalor de la solución

9.2 Elasticidad
Considere una placa elástica con forma no deformada Ω ×] - h, h [en R 3 , Ω ⊂ R 2 . Por la deformación
mación de la placa, asumimos que un punto P (x 1 , x 2 , x 3 ) se mueve a P (ξ 1 , ξ 2 , ξ 3 ). El vector

https://translate.googleusercontent.com/translate_f 224/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 253
9.2. ELASTICIDAD 253

u = (u 1 , u 2 , u 3 ) = (ξ 1 - x 1 , ξ 2 - x 2 , ξ 3 - x 3 ) se llama vector de desplazamiento. Por la deformación


mación, el segmento de línea x, x + τ∆x se mueve aproximadamente ax + u (x), x + τ∆x + u (x + τ∆x) para
pequeño τ, donde x = (x 1 , x 2 , x 3 ), ∆x = (∆x 1 , ∆x 2 , ∆x 3 ). Ahora calculamos la razón entre dos
segmentos
η (τ) = τ −1 | ∆x | −1 (| u (x + τ∆x) - u (x) + τ∆x | - τ | ∆x |)

entonces tenemos (ver p. ej. [ 21, p.32])

∂u k ∂u k (∂u yo ∂u j )
lim η (τ) = (1 + 2e ij ν i ν j ) 1/2 - 1, 2e ij = + +
τ→0 ∂x i ∂x j ∂x j ∂x i

donde ν i = ∆x i | ∆x | −1 . Si la deformación es pequeña, entonces podemos considerar que

(∂u k / ∂x i ) (∂u k / ∂x i ) ≈ 0

y lo siguiente se llama tensor de deformación pequeña

1 (∂u yo ∂u j )
ε ij (u) = +
2 ∂x j ∂x i

El tensor e ij se llama tensor de deformación finito.


Considere el plano pequeño ∆Π (x) centrado en x con la dirección normal unitaria n = (n 1 , n 2 , n 3 ), entonces
la superficie en ∆Π (x) en x es
(σ 1j (x) norte j , σ 2j (x) norte j , σ 3j (x) norte j )

donde σ ij (x) se llama tensor de tensión en x. La ley de Hooke es el supuesto de una relación lineal entre
σ ij y ε ij como
σ ij (x) = c ijkl (x) ε ij (x)

con la simetría c ijkl = c jikl , c ijkl = c ijlk , c ijkl = c klij .


Si el tensor de Hooke c ijkl (x) no depende de la elección del sistema de coordenadas, el material se llama
isotrópico en x. Si c ijkl es constante, el material se llama homogéneo. En isotrópico homogéneo
caso, hay constantes de Lamé λ, µ (ver p. ej. [ 21, p.43]) que satisfacen

σ ij = λδ ij divu + 2µε ij (9,20)

donde δ ij es el delta de Kronecker. Suponemos que la placa elástica está fija en Γ D ×] - h, h [, Γ D ⊂


∂Ω. Si la fuerza del cuerpo f = (f 1 , f 2 , f 3 ) se da en Ω ×] - h, h [y la fuerza superficial g se da en
Γ N ×] - h, h [, Γ N = ∂Ω \ Γ D , entonces la ecuación de equilibrio se da de la siguiente manera:

−∂ j σ ij = f yo en Ω ×] - h, h [, i = 1,2,3 (9.21)
σ ij n j = g yo en Γ N ×] - h, h [, u i = 0 enΓ D ×] - h, h [, i = 1,2,3 (9.22)

Ahora explicamos la elasticidad simple.

Deformación simple: en el extremo de la placa, se cumple la condición de contacto u 3 = 0, g 3 =. En este caso, nosotros
puede suponer que f 3 = g 3 = u 3 = 0 y u (x 1 , x 2 , x 3 ) = u (x 1 , x 2 ) para todo −h <x 3 <h.

Esfuerzo simple: se supone que el cilindro es muy delgado y no está sujeto a carga en los extremos x 3 = ± h,
es decir,
σ 3i = 0, x 3 = ± h, i 1,2,3

La suposición lleva a que σ 3i = 0 en Ω ×] - h, h [y u (x 1 , x 2 , x 3 ) = u (x 1 , x 2 ) para todos


−h <x 3 <h.

Página 254
254 CAPÍTULO 9. MODELOS MATEMÁTICOS

Esfuerzo simple generalizado: el cilindro no está sujeto a carga en x 3 = ± h. Introduciendo la media


valores con respecto al espesor,

1 ∫h

https://translate.googleusercontent.com/translate_f 225/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
u yo (x 1 , x 2 ) = 2 h −h u (x 1 , x 2 , x 3 ) dx 3

y derivamos u 3 ≡ 0. De manera similar, definimos los valores medios f, g de la fuerza del cuerpo y
fuerza superficial, así como los valores medios ε ij y σ ij de los componentes de tensión y deformación,
respectivamente.

En lo que sigue omitimos las líneas superiores de u, f, g, ε ij y ε ij . Entonces obtenemos una ecuación similar de
equilibrio dado en (9.21 ) reemplazando Ω ×] - h, h [con Ω y cambiando i = 1,2. En el caso del avión
estrés, σ ij = λ ∗ δ ij divu + 2µε ij , λ ∗ = (2λµ) / (λ + µ).
Las ecuaciones de elasticidad se escriben naturalmente en forma variacional para el vector de desplazamiento.
u (x) ∈ V como
∫ ∫ ∫
[2µϵ ij (u) ϵ ij (v) + λϵ ii (u) ϵ jj (v)] = f·v+ g · v, ∀v ∈ V
Ω Ω Γ

donde V es el subespacio cerrado lineal de H 1 (Ω) 2 .

Ejemplo 9.13 (Beam.edp) Considere una placa elástica con forma de rectángulo sin deformar] 0,10 [×] 0,2 [.
La fuerza del cuerpo es la fuerza de gravedad f y la fuerza límite g es cero en el lado superior e inferior. En
los dos lados verticales de la viga están fijos.

// una viga de pesaje sentada en un

int viga inferior = 2;


borde a (t = 2,0) {x = 0; y = t; etiqueta = 1;}; // haz izquierdo
borde b (t = 0,10) {x = t; y = 0; etiqueta = viga inferior;}; // parte inferior de la viga
borde c (t = 0,2) {x = 10; y = t; etiqueta = 1;}; // haz derecho
borde d (t = 0,10) {x = 10-t; y = 2; etiqueta = 3;}; // viga superior
E real = 21,5;
sigma real = 0,29;
mu real = E / (2 * (1 + sigma));
lambda real = E * sigma / ((1 + sigma) * (1-2 * sigma));
gravedad real = -0,05;
malla th = buildmesh (b (20) + c (5) + d (20) + a (5));
fespace Vh (th, [P1, P1]);
Vh [uu, vv], [w, s];
cout << "lambda, mu, gravedad =" << lambda << "" << mu << "" << gravedad << endl;
// deformación de una viga por su propio peso
sqrt2 real = sqrt (2.); // ver el ejemplo 3.8 de lame.edp
macro épsilon (u1, u2) [dx (u1), dy (u2), (dy (u1) + dx (u2)) / sqrt2] // MOE
macro div (u, v) (dx (u) + dy (v)) // MOE

resolver bb ([uu, vv], [w, s]) =


int2d (th) (
lambda * div (w, s) * div (uu, vv)
+ 2. * mu * ( épsilon (w, s) '* épsilon (uu, vv))
)
+ int2d (th) (-gravedad * s)
+ En (1, uu = 0, vv = 0)
;

plot ([uu, vv], espera = 1);

Página 255
9.2. ELASTICIDAD 255

plot ([uu, vv], wait = 1, bb = [[- 0.5,2.5], [2.5, -0.5]]);


malla th1 = movemesh (th, [x + uu, y + vv]);
plot (th1, espera = 1);

Ejemplo 9.14 (beam-3d.edp) Considere una caja elástica con forma de paralelepípedo no deformado] 0,5 [×] 0,1 [×] 0,1 [.
La fuerza del cuerpo es la fuerza de gravedad f y la fuerza de contorno g es cero en todas las caras excepto una
cara vertical izquierda donde se fija la viga.

https://translate.googleusercontent.com/translate_f 226/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
incluir "cube.idp"
int [ int ] Nxyz = [20,5,5];
real [ int , int ] Bxyz = [[0., 5.], [0., 1.], [0., 1.]];
int [ int , int ] Lxyz = [[1,2], [2,2], [2,2]];
mesh3 Th = Cubo (Nxyz, Bxyz, Lxyz);

E real = 21,5e4, sigma = 0,29;


mu real = E / (2 * (1 + sigma));
lambda real = E * sigma / ((1 + sigma) * (1-2 * sigma));
gravedad real = -0,05;

espacio libre Vh (Th, [P1, P1, P1]);


Vh [u1, u2, u3], [v1, v2, v3];
cout << "lambda, mu, gravedad =" << lambda << "" << mu << "" << gravedad << endl;

sqrt2 real = sqrt (2.);


macro épsilon (u1, u2, u3) [dx (u1), dy (u2), dz (u3), (dz (u2) + dy (u3)) / sqrt2,
(dz (u1) + dx (u3)) / sqrt2, (dy (u1) + dx (u2)) / sqrt2] // MOE
macro div (u1, u2, u3) (dx (u1) + dy (u2) + dz (u3)) // MOE

resolver Cojo ([u1, u2, u3], [v1, v2, v3]) =


int3d (Th) (
lambda * div (u1, u2, u3) * div (v1, v2, v3)
+ 2. * mu * (épsilon (u1, u2, u3) '* épsilon (v1, v2, v3)) // ')
)
- int3d (Th) (gravedad * v3)
+ en (1, u1 = 0, u2 = 0, u3 = 0)
;
dmax real = u1 []. max;
cout << "desplazamiento máximo =" << dmax << endl;
coef real = 0,1 / dmax;
int [ int ] ref2 = [1,0,2,0];
mesh3 Thm = movemesh3 (Th, transfo = [x + u1 * coef, y + u2 * coef, z + u3 * coef], etiqueta = ref2);
Thm = cambio (Thm, etiqueta = ref2);
plot (Th, Thm, espera = 1, cmm = "coef amplificación =" + coef); // ver fig ??

Página 256
256 CAPÍTULO 9. MODELOS MATEMÁTICOS

9.2.1 Mecánica de fracturas


Considere la placa con la grieta cuya forma no deformada es una curva Σ con los dos bordes γ 1 , γ 2 .
Suponemos que el tensor de tensión σ ij es el estado de la tensión de la placa con respecto a (x, y) ∈ Ω Σ = Ω \ Σ. Aquí
Ω significa la forma no deformada de la placa elástica sin grietas. Si la parte Γ N del límite
∂Ω es fijo y se da una carga L = (f, g) ∈ L 2 (Ω) 2 × L 2 (Γ N ) 2 , entonces el desplazamiento u es el
minimizador de la energía potencial funcional

∫ ∫
E (v; L, Ω Σ ) = {w (x, v) - f · v} - g·v
ΩΣ ΓN

sobre el espacio funcional V (Ω Σ ),

V (Ω Σ ) = {v ∈ H 1 (Ω Σ ) 2 ; v = 0 en Γ D = ∂Ω \ Γ N },

donde w (x, v) = σ ij (v) ε ij (v) / 2,

σ ij (v) = C ijkl (x) ε kl (v), ε ij (v) = (∂v i / ∂x j + ∂v j / ∂x i ) / 2, (C ijkl : tensor de Hooke).

Si la elasticidad es isotrópica homogénea, entonces el desplazamiento u (x) se descompone en un

https://translate.googleusercontent.com/translate_f 227/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
vecindario U k de γ k como en (ver p. ej. [ 22] )
2
1/2
u (x) = ∑ K l (γ k ) rk SC (9,23)
kl (θ k ) + u k, R (x) para x ∈ Ω Σ ∩ U k , k = 1,2
l=1

con u k, R ∈ H 2 (Ω Σ ∩ U k ) 2 , donde U k , k = 1,2 son vecindarios abiertos de γ k tales que ∂L 1 ∩ U 1 =


γ 1 , ∂L m ∩ U 2 = γ 2 , y

1 1 [[2κ - 1] cos (θ k / 2) - cos (3θ k / 2) ]


S k1
C
(θ k ) = , (9,24)
4µ (2π) 1/2 - [2κ + 1] sin (θ k / 2) + sin (3θ k / 2)
1 1 [- [2κ - 1] sin (θ k / 2) + 3 sin (3θ k / 2) ]
SC .
k2 (θ k ) = 4µ (2π) 1/2 - [2κ + 1] cos (θ k / 2) + cos (3θ k / 2)

donde µ es el módulo de elasticidad cortante, κ = 3−4ν (ν es la relación de Poisson) para la deformación plana y
κ = 3 −1ν+ ν para el estrés del avión.
Los coeficientes K 1 (γ i ) y K 2 (γ i ), que son parámetros importantes en la mecánica de la fractura, son
llamados factores de intensidad de tensión del modo de apertura (modo I) y del modo deslizante (modo II),
respectivamente.
Por simplicidad, consideramos la siguiente grieta simple

Ω = {(x, y): −1 <x <1, −1 <y <1}, Σ = {(x, y): −1 ≤ x ≤ 0, y = 0}

con una sola punta de fisura γ = (0,0). Desafortunadamente, FreeFem ++ no puede tratar el crack, por lo que usamos el
modificación del dominio con canal en forma de U (ver Fig. 5.30 ) con d = 0.0001. El indeformable
crack Σ es aproximado por

Σd = {(x, y): −1 ≤ x ≤ −10 ∗ d, −d ≤ y ≤ d}


∪ {(x, y): −10 ∗ d ≤ x ≤ 0, −d + 0.1 ∗ x ≤ y ≤ d - 0.1 ∗ x}

y Γ D = R en la figura 5.30 . En este ejemplo, usamos tres técnicas:

• Interpolador rápido de elementos finitos desde la malla Th a Zoom para escalar cerca de γ.

Página 257
9.2. ELASTICIDAD 257

• Después de obtener el vector de desplazamiento u = (u, v), observaremos la deformación del


agrietarse cerca de γ de la siguiente manera,

Placa de malla = movemesh (Zoom, [x + u, y + v]);


trama (placa);

• La adaptabilidad es una técnica importante aquí, porque se produce una gran singularidad en γ como se muestra
en ( 9,23) .

El primer ejemplo crea deformación en modo I por la fuerza de superficie opuesta en B y T en el


dirección vertical de Σ, y el desplazamiento se fija en R.
En un laboratorio, los ingenieros de fracturas utilizan fotoelasticidad para hacer visible el campo de tensión, que muestra la
diferencia de estrés principal


σ1-σ2= (σ 11 - σ 22 ) 2 + 4σ 2 12 (9,25)

donde σ 1 y σ 2 son las tensiones principales. En el modo de apertura, la fotoelasticidad hace simétrica
patrón concentrado en γ.

Ejemplo 9.15 (Apertura de la grieta, K 2 (γ) = 0) {CrackOpen.edp}


d real = 0,0001;
int n = 5;
cb real = 1, ca = 1, propina = 0.0;
borde L1 (t = 0, ca-d) {x = -cb; y = -dt; }
borde L2 (t = 0, ca-d) {x = -cb; y = ca-t; }
borde B (t = 0,2) {x = cb * (t-1); y = -ca; }
borde C1 (t = 0,1) {x = -ca * (1-t) + (tip-10 * d) * t; y = d; }
borde C21 (t = 0,1) {x = (punta-10 * d) * (1-t) + punta * t; y = d * (1-t); }

https://translate.googleusercontent.com/translate_f 228/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
borde C22 (t = 0,1) {x = (punta-10 * d) * t + punta * (1-t); y = -d * t; }
borde C3 (t = 0,1) {x = (tip-10 * d) * (1-t) -ca * t; y = -d; }
borde C4 (t = 0,2 * d) {x = -ca; y = -d + t; }
borde R (t = 0,2) {x = cb; y = cb * (t-1); }
borde T (t = 0,2) {x = cb * (1-t); y = ca; }
malla Th = buildmesh (L1 (n / 2) + L2 (n / 2) + B (n)
+ C1 (n) + C21 (3) + C22 (3) + C3 (n) + R (n) + T (n));
cb = 0,1; ca = 0,1;
plot (Th, espera = 1);
Zoom de malla = malla de construcción (L1 (n / 2) + L2 (n / 2) + B (n) + C1 (n)
+ C21 (3) + C22 (3) + C3 (n) + R (n) + T (n));
trazar (Zoom, esperar = 1);
E real = 21,5;
sigma real = 0,29;
mu real = E / (2 * (1 + sigma));
lambda real = E * sigma / ((1 + sigma) * (1-2 * sigma));
espacio libre Vh (Th, [P2, P2]);
fespace zVh (Zoom, P2);
Vh [u, v], [w, s];
resolver problema ([u, v], [w, s]) =
int2d (Th) (
2 * mu * (dx (u) * dx (w) + ((dx (v) + dy (u)) * (dx (s) + dy (w))) / 4)
+ lambda * (dx (u) + dy (v)) * (dx (w) + dy (s)) / 2
)
- int1d (Th, T) (0.1 * (4-x) * s) + int1d (Th, B) (0.1 * (4-x) * s)
+ en (R, u = 0) + en (R, v = 0); // reparado
;

Página 258
258 CAPÍTULO 9. MODELOS MATEMÁTICOS

zVh Sx, Sy, Sxy, N;


para ( int i = 1; i <= 5; i ++)
{
Placa de malla = movemesh (Zoom, [x + u, y + v]); // deformación cerca de γ
Sx = lambda * (dx (u) + dy (v)) + 2 * mu * dx (u);
Sy = lambda * (dx (u) + dy (v)) + 2 * mu * dy (v);
Sxy = mu * (dy (u) + dx (v));
N = 0,1 * 1 * raíz cuadrada ((Sx-Sy) ˆ2 + 4 * Sxyˆ2); // diferencia de estrés principal
si (i == 1) {
plot (Plate, ps = "1stCOD.eps", bw = 1); // Figura 9.13
plot (N, ps = "1stPhoto.eps", bw = 1); // Figura 9.13
} más si (i == 5) {
plot (Plate, ps = "LastCOD.eps", bw = 1); // Figura 9.14
plot (N, ps = "LastPhoto.eps", bw = 1); // Figura 9.14
romper ;
}
Th = adaptmesh (Th, [u, v]);
Problema;
}

Figura 9.13: Desplazamiento abierto de grietas Figura 9.14: DQO y diferencia de tensión principal
(COD) y diferencia de tensión principal en el diferencia en la última malla adaptativa
primera malla

Es difícil crear una deformación en modo II por la fuerza cortante opuesta en B y T que se observa

https://translate.googleusercontent.com/translate_f 229/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
en un laboratorio. Entonces usamos la fuerza cortante del cuerpo a lo largo de Σ, es decir, la componente x f 1 del cuerpo
la fuerza f está dada por

f 1 (x, y) = H (y - 0.001) ∗ H (0.1 - y) - H (−y - 0.001) ∗ H (y + 0.1)

donde H (t) = 1 si t> 0; = 0 si t <0.

Ejemplo 9.16 (Deslizamiento de grietas, K 2 (γ) = 0) (use la misma malla Th)


cb = 0,01; ca = 0,01;
Zoom de malla = malla de construcción (L1 (n / 2) + L2 (n / 2) + B (n) + C1 (n)
+ C21 (3) + C22 (3) + C3 (n) + R (n) + T (n));
(utilice el mismo módulo de elasticidad y Vh de espacio de FE)
fespace Vh1 (Th, P1);
Vh1 fx = ((y> 0,001) * (y <0,1)) - ((y <-0,001) * (y> -0,1));

resolver problema ([u, v], [w, s]) =


int2d (Th) (

Página 259
9.3. PROBLEMAS ESTÁTICOS NO LINEALES 259

2 * mu * (dx (u) * dx (w) + ((dx (v) + dy (u)) * (dx (s) + dy (w))) / 4)


+ lambda * (dx (u) + dy (v)) * (dx (w) + dy (s)) / 2
)
- int2d (Th) (fx * w)
+ en (R, u = 0) + en (R, v = 0); // reparado
;

para ( int i = 1; i <= 3; i ++)


{
Placa de malla = movemesh (Zoom, [x + u, y + v]); // deformación cerca de γ
Sx = lambda * (dx (u) + dy (v)) + 2 * mu * dx (u);
Sy = lambda * (dx (u) + dy (v)) + 2 * mu * dy (v);
Sxy = mu * (dy (u) + dx (v));
N = 0,1 * 1 * raíz cuadrada ((Sx-Sy) ˆ2 + 4 * Sxyˆ2); // diferencia de estrés principal
si (i == 1) {
plot (Plate, ps = "1stCOD2.eps", bw = 1); // Figura 9.16
plot (N, ps = "1stPhoto2.eps", bw = 1); // Figura 9.15
} más si (i == 3) {
plot (Plate, ps = "LastCOD2.eps", bw = 1); // Figura 9.16
plot (N, ps = "LastPhoto2.eps", bw = 1); // Figura 9.16
rotura;
}
Th = adaptmesh (Th, [u, v]);
Problema;
}

Figura 9.15: (COD) y diferencia de tensión principal Figura 9.16: DQO y diferencia de tensión principal
ferencia en la primera malla diferencia en la última malla adaptativa

9.3 Problemas estáticos no lineales

https://translate.googleusercontent.com/translate_f 230/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Aquí nos proponemos resolver el siguiente problema académico no lineal de minimización de un funcional
∫ 1
J (u) = f (| ∇u | 2 ) - u ∗ b
Ω 2

donde u es función de H 1
0 (Ω) yf definido por
X 1
f (x) = a ∗ x + x - ln (1 + x), f (x) = a + , f (x) =
1+x (1 + x) 2

Página 260
260 CAPÍTULO 9. MODELOS MATEMÁTICOS

9.3.1 Algoritmo de Newton-Raphson


Ahora, resolvemos el problema de Euler ∇J (u) = 0 con el algoritmo de Newton-Raphson, es decir,

)) ∗ ∇J (u n )
u norte + 1 = u norte - (∇ 2 J (u norte −1

Primero introducimos las dos formas variacionales vdJ y vhJ para calcular respectivamente ∇J y ∇ 2 J

// método de Newton-Raphson para resolver dJ (u) = 0;


//

∂dJ
u n+1 = u n - ( ) −1 ∗ dJ (u n )
∂u yo

// ---------------------------------------------
Ph dalpha; // para almacenar la optimización 2f (| ∇u | 2 )

// la forma variacional de evaluar dJ = ∇J


// --------------------------------------
// dJ = f '() * (dx (u) * dx (vh) + dy (u) * dy (vh)
varf vdJ (uh, vh) = int2d (Th) (alpha * (dx (u) * dx (vh) + dy (u) * dy (vh)) - b * vh)
+ en (1,2,3,4, uh = 0);

// la forma variacional de evaluar ddJ = ∇ 2 J


// hJ (uh, vh) = f '() * (dx (uh) * dx (vh) + dy (uh) * dy (vh)
// + 2 * f '' () (dx (u) * dx (uh) + dy (u) * dy (uh)) * (dx (u) * dx (vh) +
dy (u) * dy (vh))
varf vhJ (uh, vh) = int2d (Th) (alpha * (dx (uh) * dx (vh) + dy (uh) * dy (vh))
+ dalpha * (dx (u) * dx (vh) + dy (u) * dy (vh)) * (dx (u) * dx (uh) + dy (u) * dy (uh)))
+ en (1,2,3,4, uh = 0);

// el algoritmo de Newton
Vh v, w;
u = 0;
para (int i = 0; i <100; i ++)
{
alpha = df (dx (u) * dx (u) + dy (u) * dy (u)); // mejoramiento
dalpha = 2 * ddf (dx (u) * dx (u) + dy (u) * dy (u)); // mejoramiento
v [] = vdJ (0, Vh); // v = ∇J (u)
real res = v [] '* v []; // el producto escalar
cout << i << "residuˆ2 =" << res << endl;
si (res <1e-12) se rompe ;
matriz H = vhJ (Vh, Vh, factorizar = 1, solucionador = LU); //
w [] = Hˆ-1 * v [];
u [] - = w [];
}
plot (u, espera = 1, cmm = "solución con Newton-Raphson");

Observación: Este ejemplo está en el archivo Newton.edp de examples ++ - directorio tutorial.

https://translate.googleusercontent.com/translate_f 231/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 261
9.4. PROBLEMAS DE EIGENVALUE 261

9.4 Problemas de valores propios


Esta sección depende de su instalación de FreeFem ++; necesita haber compilado (ver README arpack),
ARPACK. Esta herramienta está disponible en FreeFem ++ si la palabra "valor propio" aparece en la línea "Cargar:",
como:

- FreeFem ++ v1.28 (fecha jueves 26 de diciembre 10:56:34 CET 2002)


archivo: LapEigenValue.edp
Carga: lg_fem lg_mesh valor propio

Esta herramienta se basa en arpack ++ 1, la versión orientada a objetos del paquete ARPACK eigenvalue
[ 1] .
La función EigenValue calcula el valor propio generalizado de Au = λBu. El cambio-invertir
El método se usa por defecto, con sigma = σ el cambio del método. La matriz OP se define con
A − σB. El valor de retorno es el número de valores propios convergentes (puede ser mayor que el número
de valores propios solicitados nev =)

int k = Valor propio (OP, B, nev =, sigma =);

donde la matriz OP = A - σB con un solucionador y condición de contorno, y la matriz B.


A partir de la versión 3.31 también hay una interfaz funcional:

int k = EigenValue (n, FOP1, FB, nev =, sigma =);

donde n es el tamaño del problema, y los operadores ahora se definen a través de funciones, definiendo
respectivamente el producto matricial de OP −1 y B, como en

int n = OP1.n;
func real [int] FOP1 (real [int] & u) {real [int] Au = OPˆ-1 * u; return Au;}
func real [int] FB (real [int] & u) {real [int] Au = B * u; return Au;}

Si desea un control más preciso sobre el método empleado en ARPACK, puede especificar qué modo
ARPACK funcionará con (mode =, consulte la documentación de ARPACK). Los operadores necesarios para la
El modo elegido se puede pasar a través de los parámetros opcionales A =, A1 =, B =, B1 = (ver más abajo).

• modo = 1: modo regular para resolver Au = λu

int k = EigenValue (n, A = FOP, modo = 1, nev =);

donde la función FOP define el producto matricial de A

• modo = 2: modo inverso regular para resolver Au = λBu

int k = EigenValue (n, A = FOP, B = FB, B1 = FB1, modo = 2, nev =);

donde las funciones FOP, FB y FB1 definen respectivamente el producto matricial de A, B y


B −1
• modo = 3: modo Shift-invertido para resolver Au = λBu

int k = EigenValue (n, A1 = FOP1, B = FB, modo = 3, sigma = sigma, nev =);

donde las funciones FOP1 y FB definen respectivamente el producto matricial de OP −1 = (A -


σB) −1 y B

1http://www.caam.rice.edu/software/ARPACK/

https://translate.googleusercontent.com/translate_f 232/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 262
262 CAPÍTULO 9. MODELOS MATEMÁTICOS

También puede especificar qué subconjunto de valores propios desea calcular (cuál =). El valor predeterminado
es cuál = “LM”, para valores propios con mayor magnitud. "SM" es para la magnitud más pequeña, "LA" para
el valor algebraico más grande, "SA" para el valor algebraico más pequeño y "BE" para ambos extremos del espectro.

Observación: Para problemas complejos, debe utilizar la palabra clave complexEigenValue en lugar de
EigenValue al pasar operadores a través de funciones.

Nota 9.1 Condición de frontera y problemas de valores propios


La condición de límite de bloqueo (Dirichlet) se realiza con una penalización exacta, por lo que ponemos 1e30 = tgv en
el término diagonal del grado de libertad bloqueado (véase la ecuación (6.33 )). Así que toma el límite de Dirichlet
condición solo en A y no en B. porque resolvemos w = OP - 1 ∗ B ∗ v.
Si pones bloqueo (Dirichlet) condición de frontera en la matriz B (con obra clave en ) se obtiene pequeña
modos espurios (10 −30 ), debido a la condición de límite, pero si olvida la condición de límite de bloqueo
en la matriz B (no hay trabajo de teclas "en") se obtienen enormes modos espurios (10 30 ) asociados a estos límites
condiciones. Calculamos solo el modo pequeño, por lo que obtenemos el bueno en este caso.

sym = el problema es simétrico (todos los valores propios son reales)

nev = el número de valores propios deseados (nev) cerca del cambio.

valor = la matriz para almacenar la parte real de los valores propios

ivalue = la matriz para almacenar la imag. parte de los valores propios

vector = la matriz de funciones FE para almacenar los vectores propios

rawvector = una matriz de tipo real [int, int] para almacenar vectores propios por columna. (hasta la versión
2-17).
Para problemas reales no simétricos, los vectores propios complejos se dan como dos vectores consecutivos,
por tanto, si los valores propios k y k + 1 son valores propios conjugados complejos, el k-ésimo vector contendrá el
parte real y el k + 1 ° vector la parte imaginaria del conjugado complejo correspondiente
vectores propios.

tol = la precisión relativa con la que se van a determinar los valores propios;

sigma = el valor de cambio;

maxit = el número máximo de iteraciones permitidas;

ncv = el número de vectores Arnoldi generados en cada iteración de ARPACK;

mode = el modo computacional usado por ARPACK (ver arriba);

que = el subconjunto solicitado de valores propios (ver arriba).

Ejemplo 9.17 (lapEignenValue.edp) En el primer ejemplo, calculamos los valores propios y los valores propios
vectores del problema de Dirichlet en el cuadrado Ω =] 0, π [ 2 .
El problema es encontrar: λ y ∇u λ en R × H 1
0 (Ω)

∫ ∫
∇u λ ∇v = λ uv ∀v ∈ H 1
0 (Ω)
Ω Ω

Página 263
9.4. PROBLEMAS DE EIGENVALUE 263

Los valores propios exactos son λ n, m = (n 2 + m 2 ), (n, m) ∈ N ∗ 2 con los vectores propios asociados son
u m, n = sin (nx) ∗ sin (mi).

https://translate.googleusercontent.com/translate_f 233/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Usamos el modo de cambio inverso generalizado de la biblioteca arpack ++, para encontrar 20 valores propios y
vectores propios cercanos al valor de desplazamiento σ = 20.

// Cálculo del valor propio y del vector propio del


// Problema de Dirichlet en el cuadrado] 0, π [ 2
// ----------------------------------------
// usamos el modo de cambio inverso
// el cambio se da con el sigma real
// -------------------------------------
// encuentre λ y u λ ∈ H 1 0 (Ω) tal que:
∫ ∫
// ∇u λ ∇v = λ u λ v, ∀v ∈ H 1
0 (Ω)
Ω Ω
verbosidad = 10;
malla Th = cuadrado (20,20, [pi * x, pi * y]);
fespace Vh (Th, P2 );
Vh u1, u2;

sigma real = 20; // valor del turno

// OP = A - sigma B; // la matriz desplazada


varf op (u1, u2) = int2d (Th) (dx (u1) * dx (u2) + dy (u1) * dy (u2) - sigma * u1 * u2)
+ en (1,2,3,4, u1 = 0); // Condición de frontera

varf b ([u1], [u2]) = int2d (Th) (u1 * u2); // sin condición de contorno ver nota
9.1
matriz OP = op (Vh, Vh, solucionador = Crout, factorizar = 1); // solucionador de crout porque el
matriz no positiva
matriz B = b (Vh, Vh, solucionador = CG, eps = 1e-20);

// comentario importante:
// la condición de contorno se realiza con penalización exacta:
// ponemos 1e30 = tgv en el término diagonal del grado de libertad de bloqueo.
// Así que tome la condición de límite de Dirichlet solo en una forma variacional
// y no en b forma variacional.
// porque resolvemos w = OP - 1 ∗ B ∗ v

int nev = 20; // número de valor propio calculado cercano a sigma

real [int] ev (nev); // para almacenar el valor propio nev


Vh [int] eV (nev); // para almacenar el nev autovector

int k = EigenValue (OP, B, sym = true, sigma = sigma, value = ev, vector = eV,
tol = 1e-10, maxit = 0, ncv = 0);

// tol = la tolerancia
// maxit = la iteración máxima ver arpack doc.
// ncv ver arpack doc. http://www.caam.rice.edu/software/ARPACK/
// el valor de retorno es el número de valor propio convergente.

para ( int i = 0; i <k; i ++)


{
u1 = eV [i];
real gg = int2d (Th) (dx (u1) * dx (u1) + dy (u1) * dy (u1));
mm real = int2d (Th) (u1 * u1);

Página 264
264 CAPÍTULO 9. MODELOS MATEMÁTICOS

cout << "----" << i << "" << ev [i] << "err ="
<< int2d (Th) (dx (u1) * dx (u1) + dy (u1) * dy (u1) - (ev [i]) * u1 * u1) << "---" << endl;
plot (eV [i], cmm = "Vector propio" + i + "valeur =" + ev [i], esperar = 1, valor = 1);
}

El resultado de este ejemplo es:

Nb de aristas en morteros = 0

https://translate.googleusercontent.com/translate_f 234/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Número
Número de aristas
de nodos en el límite = 80, neb = 80
= 1681
Nb de DF = 1681
Problema de valor propio simétrico real: A * x - B * x * lambda

Gracias a la clase ARPACK ++ ARrcSymGenEig


Problema de valor propio simétrico real: A * x - B * x * lambda
Modo de cambio e inversión sigma = 20

Dimensión del sistema : 1681


Número de valores propios 'solicitados': 20
Número de valores propios 'convergentes': 20
Número de vectores Arnoldi generados: 41
Número de iteraciones tomadas :2

Autovalores:
lambda [1]: 5.0002
lambda [2]: 8.00074
lambda [3]: 10.0011
lambda [4]: 10.0011
lambda [5]: 13.002
lambda [6]: 13.0039
lambda [7]: 17.0046
lambda [8]: 17.0048
lambda [9]: 18.0083
lambda [10]: 20.0096
lambda [11]: 20.0096
lambda [12]: 25.014
lambda [13]: 25.0283
lambda [14]: 26.0159
lambda [15]: 26.0159
lambda [16]: 29.0258
lambda [17]: 29.0273
lambda [18]: 32.0449
lambda [19]: 34.049
lambda [20]: 34.0492

---- 0 5.0002 err = -0.000225891 ---


---- 1 8.00074 err = -0.000787446 ---
---- 2 10.0011 err = -0.00134596 ---
---- 3 10.0011 err = -0.00134619 ---
---- 4 13.002 err = -0.00227747 ---
---- 5 13.0039 err = -0.004179 ---
---- 6 17.0046 err = -0.00623649 ---
---- 7 17,0048 err = -0,00639952 ---

Página 265
9.5. PROBLEMAS DE EVOLUCIÓN 265

---- 8 18.0083 err = -0.00862954 ---


---- 9 20.0096 err = -0.0110483 ---
---- 10 20.0096 err = -0.0110696 ---
---- 11 25.014 err = -0.0154412 ---
---- 12 25.0283 err = -0.0291014 ---
---- 13 26.0159 err = -0.0218532 ---
---- 14 26.0159 err = -0.0218544 ---
---- 15 29.0258 err = -0.0311961 ---
---- 16 29.0273 err = -0.0326472 ---
---- 17 32.0449 err = -0.0457328 ---
---- 18 34.049 err = -0.0530978 ---
---- 19 34.0492 err = -0.0536275 ---

Vector propio 11 valeur = 25.014 Eigen Vector 12 valeur = 25.0283


IsoValue IsoValue
-0,809569 -0.807681
-0,724351 -0,722662
-0,639134 -0,637643
-0,553916 -0,552624
-0,468698 -0,467605
-0,38348 -0,382586
-0,298262 -0,297567
-0,213045 -0,212548
-0.127827 -0,127529
-0.0426089 -0.0425095
0.0426089 0.0425095
0.127827 0.127529
0.213045 0.212548
0.298262 0.297567
0.38348 0.382586
0,468698 0,467605

https://translate.googleusercontent.com/translate_f 235/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
0.553916 0.552624
0,639134 0,637643
0,724351 0,722662
0,809569 0.807681

Figura 9.17: Isovalor del undécimo vector propio Figura 9.18: Isovalor del 12 ° vector propio
u 4,3 - u 3,4 u 4,3 + u 3,4

9.5 Problemas de evolución


FreeFem ++ también resuelve problemas de evolución como la ecuación del calor:

∂u
- µ∆u = f en Ω ×] 0, T [, (9,26)
∂t
u (x, 0) = u 0 (x) en Ω; (∂u / ∂n) (x, t) = 0 en ∂Ω ×] 0, T [.

con un coeficiente de viscosidad positivo µ y condiciones de contorno de Neumann homogéneas. Solucionamos


( 9.26 ) por FEM en el espacio y diferencias finitas en el tiempo. Usamos la definición de la derivada parcial
de la solución en la derivada del tiempo,

∂u u (x, y, t) - u (x, y, t - τ)
(x, y, t) = lim
∂t τ→0 τ

Página 266
266 CAPÍTULO 9. MODELOS MATEMÁTICOS

lo que indica que u m (x, y) = u (x, y, mτ) satisfará aproximadamente

∂u u m (x, y) - u m − 1 (x, y)
(x, y, mτ) ≃
∂t τ

La discretización temporal de la ecuación de calor ( 9.27) es la siguiente:

u m+1 - u m
- µ∆u m + 1 = f m + 1 en Ω (9,27)
τ
u 0 (x) = u 0 (x) en Ω; ∂u m + 1 / ∂n (x) = 0 en ∂Ω, para todo m = 0, ···, [T / τ],

que es el llamado método de Euler hacia atrás para ( 9.27 ). Para obtener la formulación variacional, multiplique
con la función de prueba v ambos lados de la ecuación:

∫ ∫
{u m + 1 v - τ∆u m + 1 v} = {u m + τf m + 1 } v.
Ω Ω

Por el teorema de la divergencia, tenemos

∫ ∫ ∫
{u m + 1 v + τ∇u m + 1 · ∇v} - τ (∂u m + 1 / ∂n) v = {u m v + τf m + 1 v}.
Ω ∂Ω Ω

Por la condición de frontera ∂u m + 1 / ∂n = 0, se sigue que

∫ ∫
{u m + 1 v + τ∇u m + 1 · ∇v} - {u m v + τf m + 1 v} = 0. (9,28)
Ω Ω

Usando la identidad de arriba, podemos calcular la aproximación de elementos finitos u m de ti m en un


https://translate.googleusercontent.com/translate_f 236/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
h
de manera paso a paso con respecto a t.

Ejemplo 9.18 Ahora resolvemos el siguiente ejemplo con la solución exacta u (x, y, t) = tx 4 .

∂u
- µ∆u = x 4 - µ12tx 2 en Ω ×] 0,3 [, Ω =] 0,1 [ 2
∂t
u (x, y, 0) = 0 en Ω, u | ∂Ω = t ∗ x 4

// ecuación de calor ∂ t u = −µ∆u = x 4 - µ12tx 2


malla Th = cuadrado (16,16);
fespace Vh (Th, P1);

Vh u, v, uu, f, g;
dt real = 0,1, mu = 0,01;
problema dHeat (u, v) =
int2d (Th) (u * v + dt * mu * ( dx (u) * dx (v) + dy (u) * dy (v)))
+ int2d (Th) (- uu * v - dt * f * v)
+ en (1,2,3,4, u = g);

t real = 0; // empezar desde t = 0


uu = 0; // u (x, y, 0) = 0
para ( int m = 0; m <= 3 / dt; m ++)
{
t = t + dt;
f = xˆ4-mu * t * 12 * xˆ2;
g = t * xˆ4;

Página 267
9.5. PROBLEMAS DE EVOLUCIÓN 267

dHeat;
plot (u, espera = verdadero);
uu = u;
cout << "t =" << t << "Lˆ2-Error =" << sqrt ( int2d (Th) ((ut * xˆ4) ˆ2)) << endl ;
}

En la última declaración, el error L 2 ∣ (∫ 2 ) 1/2


se calcula en t = mτ, τ = 0.1. En t = 0,1,
∣u - tx 4 ∣ ∣Ω

el error es 0.000213269. Los errores aumentan con my 0.00628589 en t = 3.


La iteración del Euler hacia atrás ( 9.28) se realiza mediante el bucle for (consulte la Sección 4.11).

Nota 9.2 La matriz de rigidez en el bucle se usa una y otra vez. Reutilizaciones de soporte de FreeFem ++
de matriz de rigidez.

9.5.1 Teoría matemática sobre aproximaciones en diferencia de tiempo.


En esta sección, mostramos la ventaja de los esquemas implícitos. Sea V, H el espacio de Hilbert separable
y V es denso en H. Sea a una forma bilineal continua sobre V × V con coercitividad y simetría.
Entonces √a (v, v) se vuelve equivalente a la norma v de V.
Problema Ev (f, Ω): Para una f ∈ L 2 (0, T; V), u 0 ∈ H

D
(u (t), v) + una (u (t), v) = (f (t), v) ∀v ∈ V`` ae t ∈ [0, T] (9,29)
dt
u (0) = u 0

donde V es el espacio dual de V. Entonces, hay una solución única u ∈ L ∞ (0, T; H) ∩ L 2 (0, T; V).
Denotemos el paso de tiempo por τ> 0, N T = [T / τ]. Para la discretización, ponemos u n = u (nτ) y
considere la diferencia de tiempo para cada θ ∈ [0,1]

1 ( u n + θ , φ yo)
(u n + 1 - u n = 〈F norte + θ , φ yo〉 (9.30)
τ h h, φi) + a h

i = 1, ···, m, n = 0, ···, N T
u hn + θ = θu n h+ 1 + (1 - θ) u n
h, f norte + θ = θf norte + 1 + (1 - θ) f norte

https://translate.googleusercontent.com/translate_f 237/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
La fórmula ( 9.30 ) es el esquema de Euler hacia adelante si θ = 0, esquema de Crank-Nicolson si θ = 1/2, el
esquema de Euler hacia atrás si θ = 1.
Vectores desconocidos u n = (u 1 h , ···, u M h ) T en

un
h (x) = un 1 φ 1 (x) + ··· + u n m φ m (x), un 1, ···, u n m∈ R
se obtienen al resolver la matriz

(M + θτA) u n + 1 = {M - (1 - θ) τA} u n + τ {θf n + 1 + (1 - θ) f n } (9,31)


M = (m ij ), m ij = (φ j , φ i ), A = (a ij ), a ij = a (φ j , φ i )

Consulte [ 27, págs. 70-75] para conocer la solubilidad de (9.31). La estabilidad de (9.31) está en [27, Teorema 2.13]:

Sean {T h } h ↓ 0 triangulaciones regulares (vea la Sección 5. 4). Entonces hay un numero


c 0 > 0 independiente de h tal que,

1 { | u 0| 2 + τ ∑ n−1 }
θ ∈ [0,1 / 2)
|un
δ h k=0fk+θ2 Vh
(9,32)
h| 2≤ n−1
| u h0 | 2 + τ ∑ θ ∈ [1 / 2,1]
k=0fk+θ2 Vh

si se cumple lo siguiente:

Página 268
268 CAPÍTULO 9. MODELOS MATEMÁTICOS

1. Cuando θ ∈ [0,1 / 2), entonces podemos dar un paso de tiempo τ de tal manera que

2 (1 - δ)
τ< h2 (9,33)
(1 - 2θ) c 2 0

para δ ∈ arbitrario (0,1).

2. Cuando 1/2 ≤ θ ≤ 1, podemos tomar τ arbitrariamente.

Ejemplo 9.19

malla Th = cuadrado (12,12);


fespace Vh (Th, P1);
fespace Ph (Th, P0);

Ph h = h Triángulo; // tamaños de malla para cada triángulo


tau real = 0,1, theta = 0;
func real f ( real t) {
devuelve xˆ2 * (x-1) ˆ2 + t * (- 2 + 12 * x - 11 * xˆ2 - 2 * xˆ3 + xˆ4);
}
ofstream out ("err02.csv"); // archivo para almacenar cálculos
out << "tamaño de malla =" << h []. max << ", paso de tiempo =" << tau << endl ;
para ( int n = 0; n <5 / tau; n ++) \\
out << n * tau << ",";
out << endl ;
Vh u, v, oldU;
Vh f1, f0;
problema aTau (u, v) =
int2d (Th) (u * v + theta * tau * (dx (u) * dx (v) + dy (u) * dy (v) + u * v))
- int2d (Th) (oldU * v - (1-theta) * tau * (dx (oldU) * dx (v) + dy (oldU) * dy (v) + oldU * v))
- int2d (Th) (tau * (theta * f1 + (1-theta) * f0) * v);

while (theta <= 1.0) {


t real = 0, T = 3; // de t = 0 a T
oldU = 0; // u (x, y, 0) = 0
out << theta << ",";
para ( int n = 0; n <T / tau; n ++) {
t = t + tau;
f0 = f (n * tau); f1 = f ((n + 1) * tau);
aTau;
oldU = u;

https://translate.googleusercontent.com/translate_f 238/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
trama (u);
Vh uex = t * xˆ2 * (1-x) ˆ2; // sol exacto = tx 2 (1 - x) 2
Vh err = u - uex; // err = FE-sol - exacto
out << abs (err []. max) / abs (uex []. max) << ","; // err L ∞ (Ω) / u ex L ∞ (Ω)
}
out << endl;
theta = theta + 0,1;
}

Podemos ver en la figura 9.19 que u n h (θ) se vuelve inestable en θ = 0.4, y las cifras se omiten en el caso
θ <0,4.

Página 269
9.5. PROBLEMAS DE EVOLUCIÓN 269

Figura 9.19: max x∈Ω | u n


h (θ) - u ex (nτ) | / max x∈Ω | u ex (nτ) | en n = 0,1, ···, 29

9.5.2 Convección
La ecuación hiperbólica

∂ t u + α · ∇u = f; para una función α con valores vectoriales, (9,34)

aparece con frecuencia en problemas científicos, por ejemplo en las ecuaciones de Navier-Stokes, en la Convección-
Ecuación de difusión, etc.
En el caso del espacio unidimensional, podemos encontrar fácilmente la solución general (x, t) ↦ → u (x, t) =
u 0 (x - αt) de la siguiente ecuación, si α es constante,

∂ t u + α∂ x u = 0, u (x, 0) = u 0 (x), (9,35)

porque ∂ t u + α∂ x u = −α ˙u 0 + a ˙u 0 = 0, donde ˙u 0 = du 0 (x) / dx. Incluso si α no es constante, el


La construcción se basa en principios similares. Se comienza con la ecuación diferencial ordinaria (con
la convención de que α se prolonga por cero aparte de (0, L) × (0, T)):

X˙ (τ) = + α (X (τ), τ), τ ∈ (0, t) X (t) = x

En esta ecuación τ es la variable y x, t son parámetros, y denotamos la solución por X x, t (τ).


Entonces se observa que (x, t) → v (X (τ), τ) en τ = t satisface la ecuación

∂ t v + α∂ x v = ∂ t X ˙v + a∂ x X ˙v = 0

y por la definición ∂ t X = ˙X = + α y ∂ x X = ∂ x x en τ = t, porque si τ = t tenemos X (τ) = x.


Por tanto, la solución general de (9.35 ) es el valor de la condición de frontera en X x, t (0), es decir
u (x, t) = u 0 (X x, t (0)) donde X x, t (0) está en el eje x, u (x, t) = u 0 (X x, t (0)) si X x, t (0) está en el eje
de t.
En una dimensión superior Ω ⊂ R d , d = 2,3, la ecuación para la convección se escribe

∂ t u + α · ∇u = 0inΩ × (0, T)

donde a (x, t) ∈ R d . FreeFem ++ implementa el método Characteristic-Galerkin para convección

https://translate.googleusercontent.com/translate_f 239/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
operadores. Recuerde que la ecuación ( 9.34) se puede discretizar como
Du du dX
= f es decir (X (t), t) = f (X (t), t) donde (t) = α (X (t), t)
Dt dt dt

Página 270
270 CAPÍTULO 9. MODELOS MATEMÁTICOS

donde D es el operador derivado total. Entonces, un buen esquema es un paso de convección hacia atrás por
el método de Características-Galerkin
1
(u m + 1 (x) - u m (X m (x))) = f m (x) (9,36)
τ

donde X m (x) es una aproximación de la solución en t = mτ de la ecuación diferencial ordinaria

dX
(t) = α m (X (t)), X ((m + 1) τ) = x.
dt

donde α m (x) = (α 1 (x, mτ), α 2 (x, mτ)). Porque, por la expansión de Taylor, tenemos

D
∑ ∂u m ∂X i
u m (X (mτ)) = u m (X ((m + 1) τ)) - τ (X ((m + 1) τ)) ((m + 1) τ) + o (τ)
∂x i ∂t
i=1

= u m (x) - τα m (x) · ∇u m (x) + o (τ) (9,37)

donde X i (t) son el i-ésimo componente de X (t), u m (x) = u (x, mτ) y usamos la regla de la cadena y
x = X ((m + 1) τ). De (9, 37), se sigue que

u m (X m (x)) = u m (x) - τα m (x) · ∇u m (x) + o (τ). (9,38)

También aplicamos la expansión de Taylor para t ↦ → u m (x - α m (x) t), 0 ≤ t ≤ τ, entonces

u m (x - ατ) = u m (x) - τα m (x) · ∇u m (x) + o (τ).

Poniendo
convección (α, −τ, u m ) ≈ u m (x - α m τ),

podemos obtener la aproximación

u m (X m (x)) ≈ convecto ([a m


1, una2 ],m - τ, u m ) por X m ≈ x ↦ → x - τ [a m 1 (x), una2m(x)]).

Un problema de convección clásico es el de la “campana giratoria” (citado de [ 19 ] [p.16]). Sea Ω


el disco unitario centrado en 0, con su centro girando con rapidez α 1 = y, α 2 = −x Consideramos el
problema ( 9.34) con f = 0 y la condición inicial u (x, 0) = u 0 (x), es decir, de ( 9.36 )

u m + 1 (x) = u m (X m (x)) ≈ convección (α, −τ, u m ).

La solución exacta es u (x, t) = u (X (t)) donde X es igual a x girado alrededor del origen en un ángulo
θ = −t (girar en sentido horario). Entonces, si u 0 en una perspectiva 3D parece una campana, entonces u tendrá exactamente
la misma forma, pero girada en la misma cantidad. El programa consiste en resolver la ecuación
hasta T = 2π, es decir para una revolución completa y comparar la solución final con la inicial;
deberían ser iguales.

Ejemplo 9.20 (convect.edp) border C (t = 0, 2 * pi) {x = cos (t); y = sin (t); }; // la


circulo unitario
malla Th = buildmesh (C (70)); // triangula el disco
fespace Vh (Th, P1);
Vh u0 = exp (-10 * ((x-0.3) ˆ2 + (y-0.3) ˆ2)); // dale 0

dt real = 0,17, t = 0; // hora de caminar


Vh a1 = -y, a2 = x; // velocidad de rotacion
Vh u; // u m+1
para ( int m = 0; m <2 * pi / dt; m ++) {

https://translate.googleusercontent.com/translate_f 240/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 271
9.5. PROBLEMAS DE EVOLUCIÓN 271

t + = dt;
u = convecto ([a1, a2], - dt, u0); // u m + 1 = u m (X m (x))
u0 = u; // m ++
plot (u, cmm = "t =" + t + ", min =" + u []. min + ", max =" + u []. max, espera = 0);
};

Nota 9.3 El esquema de convección es incondicionalmente estable, luego la campana se vuelve cada vez más baja (la
el máximo de u 37 es 0.406 como se muestra en la figura 9.21) .

convección: t = 0, min = 1.55289e-09, max = 0.983612 convección: t = 6.29, min = 1.55289e-09, max = 0.40659m = 37

Figura 9.20: u 0 = e −10 ((x − 0.3) 2+ (y − 0.3) 2 ) Figura 9.21: La campana en t = 6.29

9.5.3 Ecuación de Black-Scholes 2D para una opción de venta europea


En finanzas matemáticas, una opción sobre dos activos se modela mediante ecuaciones de Black-Scholes en dos
variables espaciales (véase, por ejemplo, Wilmott et al [ 44] o Achdou et al [3]).

2 2
(σ 1 x) ∂ 2 u (σ 2 años ) ∂ 2 u
∂tu+ + (9,39)
2 ∂x 2 2 ∂y 2
∂2u ∂u ∂u
+ ρxy + rS 1 + rS 2 - rP = 0
∂x∂y ∂x ∂y

que se integrará en (0, T) × R + × R + sujeto a, en el caso de una venta

+
u (x, y, T) = (K - max (x, y)) . (9,40)

Es posible que las condiciones límite para este problema no sean tan fáciles de determinar. Como en el unidimensional
caso de que la PDE contenga condiciones de contorno en el eje x 1 = 0 y en el eje x 2 = 0, a saber
dos ecuaciones de Black-Scholes unidimensionales impulsadas respectivamente por los datos u (0, + ∞, T) y
u (+ ∞, 0, T). Estos se contabilizarán automáticamente porque están integrados en el PDE.
Entonces, si no hacemos nada en la forma variacional (es decir, si tomamos una condición de frontera de Neumann en estos
dos ejes en la forma fuerte) no habrá ninguna perturbación en estos. Al infinito en una de las variables,
como en 1D, tiene sentido imponer u = 0. Tomamos

σ 1 = 0.3, σ 2 = 0.3, ρ = 0.3, r = 0.05, K = 40, T = 0.5 (9,41)

Página 272
272 CAPÍTULO 9. MODELOS MATEMÁTICOS

https://translate.googleusercontent.com/translate_f 241/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Se utiliza un esquema de Euler implícito y se realiza una adaptación de malla cada 10 pasos de tiempo. Tener
un esquema incondicionalmente estable, los términos de primer orden son tratados por la característica Galerkin
método, que, aproximadamente, se aproxima

∂u ∂u ∂u 1
+a1 +a2 ≈ (u n + 1 (x) - u n (x - ατ)) (9,42)
∂t ∂x ∂y τ

Ejemplo 9.21 [BlackSchol.edp]

// archivo BlackScholes2D.edp
int m = 30, L = 80, LL = 80, j = 100;
sigx real = 0.3, sigy = 0.3, rho = 0.3, r = 0.05, K = 40, dt = 0.01;
malla th = cuadrado (m, m, [L * x, LL * y]);
fespace Vh (th, P1);

Vh u = max (K-max (x, y), 0.);


Vh xveloc, yveloc, v, uold;

para ( int n = 0; n * dt <= 1.0; n ++)


{
if (j> 20) {th = adaptmesh (th, u, verbosity = 1, abserror = 1, nbjacoby = 2,
err = 0.001, nbvx = 5000, omega = 1.8, ratio = 1.8, nbsmooth = 3,
splitpbedge = 1, maxsubdiv = 5, reescalado = 1);
j = 0;
xveloc = -x * r + x * sigxˆ2 + x * rho * sigx * sigy / 2;
yveloc = -y * r + y * sigyˆ2 + y * rho * sigx * sigy / 2;
u = u;
};
uold = u;
resolver eq1 (u, v, init = j, solucionador = LU) = int2d (th) (u * v * (r + 1 / dt)
+ dx (u) * dx (v) * (x * sigx) ˆ2 / 2 + dy (u) * dy (v) * (y * sigy) ˆ2 / 2
+ ( dy (u) * dx (v) + dx (u) * dy (v)) * rho * sigx * sigy * x * y / 2)
- int2d (th) (v * convect ([xveloc, yveloc], dt, w) / dt) + on (2,3, u = 0);

j = j + 1;
};
plot (u, espera = 1, valor = 1);

Los resultados se muestran en la Fig. 9.21) .

9.6 Ecuación de Navier-Stokes


9.6.1 Stokes y Navier-Stokes
Las ecuaciones de Stokes son: para un f ∈ L 2 (Ω) 2 dado ,

−∆u + ∇p = f }
en Ω (9,43)
∇·u =0

donde u = (u 1 , u 2 ) es el vector de velocidad yp la presión. Por simplicidad, elijamos Dirichlet


condiciones de contorno en la velocidad, u = u Γ en Γ.

Página 273
9.6. ECUACIÓN DE NAVIER-STOKES 273

IsoValue
-1.99835
0,999173
2.99752
4.99587
6.99421
8,99256
10.9909
12.9893
14.9876
16.9859
18.9843
20,9826
22.981
24.9793
26.9777
28.976
30,9744
32,9727
34.9711
39.9669

https://translate.googleusercontent.com/translate_f 242/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 9.23: La línea de nivel del europeo


Figura 9.22: La triangulación adaptada opción de venta de basquet

En Temam [Teorema 2.2], hay una forma débil de ( 9.43 ): Encuentre v = (v 1 , v 2 ) ∈ V (Ω)

V (Ω) = {w ∈ H 1
0 (Ω) 2 | divw = 0}
que satisfacen
2
∑ ∫ ∫
∇u yo · ∇v yo = f · w para todo v ∈ V
i=1 Ω Ω

Aquí se usa la existencia p ∈ H 1 (Ω) tal que u = ∇p, si



u · v = 0 para todo v ∈ V
Ω

Otra forma débil se deriva de la siguiente manera: Ponemos


{ ∣ ∫ }
V=H1 q ∈ L 2 (Ω) ∣∣ q=0
0 (Ω) 2 ; W=
∣ Ω

Multiplicando la primera ecuación en (9. 43) con v ∈ V y la segunda con q ∈ W, subsecuentemente


integración sobre Ω, y una aplicación de la fórmula de Green, tenemos
∫ ∫ ∫
∇u · ∇v - divv p = f·v
Ω Ω Ω

divuq = 0
Ω

Esto produce la forma débil de (9.43 ): Encuentre (u, p) ∈ V × W tal que

a (u, v) + b (v, p) = (f, v) (9,44)


b (u, q) = 0 (9,45)

Página 274
274 CAPÍTULO 9. MODELOS MATEMÁTICOS

para todo (v, q) ∈ V × W, donde

2
∫ ∫
a (u, v) = ∇u · ∇v = ∑ ∇u i · ∇v i (9,46)
Ω Ω
i=1


b (u, q) = - divuq (9,47)
Ω

Ahora, consideramos espacios de elementos finitos V h ⊂ V y W h ⊂ W, y asumimos la siguiente base


funciones

V h = V h × V h , V h = {v h | v h = v 1 φ 1 + ··· + v M V φ M V },
W h = {q h | q h = q 1 ϕ 1 + ··· + q M W ϕ M W }

La forma débil discreta es: Encuentre (u h , p h ) ∈ V h × W h tal que

https://translate.googleusercontent.com/translate_f 243/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
a (u h , v h ) + b (v h , p) = (f, v h ), ∀v h ∈ V h (9,48)
b (u h , q h ) = 0, ∀q h ∈ W h

Nota 9.4 Suponga que:

1. Hay una constante α h > 0 tal que

2
a (v h , v h ) ≥ αv h 1, Ω para todo v h ∈ Z h

dónde
Z h = {v h ∈ V h | b (w h , q h ) = 0 para todo q h ∈ W h }

2. Hay una constante β h > 0 tal que

b (v h , q h )
sorber ≥ β h q h 0, Ω para todo q h ∈ W h
v h∈ V h v h 1, Ω

Entonces tenemos una solución única (u h , p h ) de (9.48 ) que satisface

( )
u - u h 1, Ω + p - p h 0, Ω ≤ C inf u - v h 1, Ω + inf p - q h 0, Ω
v h∈ V h q h ∈W h

con una constante C> 0 (véase, por ejemplo, [25 , Teorema 10.4]).

Denotemos que


A = (A ij ), A ij = ∇φ j · ∇φ yo i, j = 1, ···, MV (9,49)
Ω

∫ ∫
B = (Bx ij , Por ij ), Bx ij = - ∂φ j / ∂x ϕ i Por ij = - ∂φ j / ∂y ϕ i
Ω Ω

i = 1, ···, M W ; j = 1, ···, M V

entonces ( 9.48) está escrito por

(AB ∗ ) (U h ) (F h )
= (9,50)
B 0 {p h } 0

Página 275
9.6. ECUACIÓN DE NAVIER-STOKES 275

dónde

(A 0 ) ∗ {Bx T } {{u 1, h } } {{∫ f1φi} }


Ω
A= B = Uh= Fh=
0A Por T {u 2, h } {∫ Ω
f2φi}

Método de penalización: este método consiste en reemplazar (9.48 ) por un problema más regular: Encontrar
(v ϵh , p hϵ ) ∈ V h × ˜W h satisfactorio

a (u ϵh , v h ) + b (v h , p ϵh ) = (f, v h ), ∀v h ∈ V h
(9,51)
b (u hϵ , q h ) - ϵ (p ϵh , q h ) = 0, ∀q h ∈ ˜W h

donde ˜W h ⊂ L 2 (Ω). Formalmente, tenemos

divu ϵ
h= ϵp ϵ h

y el correspondiente problema algebraico

(AB ∗ ) (U ϵ h
) (F h )
=
B −ϵI {p hϵ } 0

Nota 9.5 Podemos eliminar p ϵ h = (1 / ϵ) BU ϵ h para obtener



(A + (1 / ϵ) B B) U ϵ (9,52)
h= Fϵ h

https://translate.googleusercontent.com/translate_f 244/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Dado que la matriz A + (1 / ϵ) B ∗ B es simétrica, definida positiva y escasa, ( 9.52 ) se puede resolver mediante
técnica conocida. Hay una constante C> 0 independiente de ϵ tal que

uh-uϵ
h 1, Ω + ph- pϵ h 0, Ω ≤ Cϵ
(ver, por ejemplo, [25 , 17.2])

Ejemplo 9.22 (Cavity.edp) El problema de flujo de la cavidad impulsada se resuelve primero en cero número de Reynolds
(Flujo de Stokes) y luego en Reynolds 100. La fórmula de presión de velocidad se usa primero y luego
el cálculo se repite con la formulación de vorticidad de la función de flujo.
Resolvemos el problema de la cavidad impulsada mediante el método de penalización (9.51 ) donde u Γ · n = 0 y u Γ · s = 1
en el límite superior y cero en cualquier otro lugar (n es la unidad normal a Γ y s la unidad tangente a Γ).
La malla está construida por

malla Th = cuadrado (8,8);

Usamos una técnica clásica de elementos de Taylor-Hood para resolver el problema:

La velocidad se aproxima con P 2 FE ( espacio X h ), y la presión se aproxima con


el P 1 FE (M h espacio),

dónde
X h = {v ∈ H 1 (] 0,1 [ 2 ) ∣∣ ∀K ∈ T h v |K ∈ P 2 }

y
M h = {v ∈ H 1 (] 0,1 [ 2 ) ∣∣ ∀K ∈ T h v |K ∈ P 1 }

Los espacios y funciones FE están construidos por

Página 276
276 CAPÍTULO 9. MODELOS MATEMÁTICOS

espacio libre Xh (Th, P2 ); // definición del espacio de componentes de velocidad


fespace Mh (Th, P1 ); // definición del espacio de presión
Xh u2, v2;
Xh u1, v1;
Mh p, q;

El operador de Stokes se implementa como una solución de sistema para la velocidad (u1, u2) y la presión p.
La función de prueba para la velocidad es (v1, v2) yq para la presión, por lo que la forma variacional ( 9.48 )
en lenguaje freefem es:

resolver Stokes (u1, u2, p, v1, v2, q, solucionador = Crout) =


int2d (Th) ((dx (u1) * dx (v1) + dy (u1) * dy (v1)
+ dx (u2) * dx (v2) + dy (u2) * dy (v2))
- p * q * (0,000001)
- p * dx (v1) - p * dy (v2)
- dx (u1) * q - dy (u2) * q
)
+ en (3, u1 = 1, u2 = 0)
+ en (1,2,4, u1 = 0, u2 = 0); // consulte la Sección 5.1.1 para las etiquetas 1, 2, 3, 4

Cada desconocido tiene sus propias condiciones de contorno.

Si se requieren las líneas de corriente, se pueden calcular encontrando ψ tal que rotψ = u o mejor,

−∆ψ = ∇ × u

Xh psi, phi;

resolver líneas de corriente (psi, phi) =


int2d (Th) (dx (psi) * dx (phi) + dy (psi) * dy (phi))

https://translate.googleusercontent.com/translate_f 245/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
+ int2d (Th) (-phi * (dy (u1) -dx (u2)))
+ en (1,2,3,4, psi = 0);

Ahora se resuelven las ecuaciones de Navier-Stokes

∂u
+ u · ∇u - ν∆u + ∇p = 0, ∇ · u = 0
∂t
con las mismas condiciones de contorno y con condiciones iniciales u = 0.
Esto se implementa utilizando el operador de convección convect para el término ∂u ∂t + u · ∇u, dando un
discretización en el tiempo
1
τ (u n + 1 - u n ◦ X n ) - ν∆u n + 1 + ∇p n + 1 = 0,
(9,53)
∇ · u n+1 =0

El término u n ◦X n (x) ≈ u n (x − u n (x) τ) será calculado por el operador "convect", por lo que obtenemos

int i = 0;
nu real = 1. / 100 .;
dt real = 0,1;
alfa real = 1 / dt;

Página 277
9.6. ECUACIÓN DE NAVIER-STOKES 277

Xh up1, up2;

problema NS (u1, u2, p, v1, v2, q, solucionador = Crout, init = i) =


int2d (Th) (
alfa * (u1 * v1 + u2 * v2)
+ nu * (dx (u1) * dx (v1) + dy (u1) * dy (v1)
+ dx (u2) * dx (v2) + dy (u2) * dy (v2))
- p * q * (0,000001)
- p * dx (v1) - p * dy (v2)
- dx (u1) * q - dy (u2) * q
)
+ int2d (Th) (-alpha *
convect ([up1, up2], - dt, up1) * v1 -alpha * convect ([up1, up2], - dt, up2) * v2)
+ en (3, u1 = 1, u2 = 0)
+ en (1,2,4, u1 = 0, u2 = 0)
;

para (i = 0; i <= 10; i ++)


{
up1 = u1;
up2 = u2;
NS;
si (! (i% 10)) // trazar cada 10 iteraciones
plot (coef = 0.2, cmm = "[u1, u2] yp", p, [u1, u2]);
};

Observe que las matrices de rigidez se reutilizan (palabra clave init = i)

9.6.2 Algoritmo de Uzawa y gradientes conjugados


Solucionamos el problema de Stokes sin penalización. El método iterativo clásico de Uzawa es descrito por
el algoritmo (consulte, por ejemplo, [25 , 17.3], [34, 13] o [35, 13]):

Inicializar: Sea p 0 h ser un elemento elegido arbitrariamente de L 2 (Ω).

Calcular u h : Una vez p n h es conocido, v hn es la solución de


−1
un (f h - B ∗ pn
h= A h)

Avance p h : Sea p n + 1 h ser definido por


p n+1 = p n h

https://translate.googleusercontent.com/translate_f 246/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
h h+ ρ n Bu n
Hay una constante α> 0 tal que α ≤ ρ n ≤ 2 para cada n, entonces u n h converge a la solución u h ,
y luego Bv n h
→ 0 como n → ∞ de Advance p h . Este método en general converge con bastante lentitud.
Primero definimos malla y la aproximación de Taylor-Hood. Entonces X h es el espacio de velocidades, y M h
es el espacio de presión.

Ejemplo 9.23 (StokesUzawa.edp)

malla Th = cuadrado (10,10);


espacio libre Xh (Th, P2 ), Mh (Th, P1 );
Xh u1, u2, v1, v2;
Mh p, q, ppp; // ppp es una presión de trabajo

Página 278
278 CAPÍTULO 9. MODELOS MATEMÁTICOS

varf bx (u1, q) = int2d (Th) (- (dx (u1) * q));


varf por (u1, q) = int2d (Th) (- (dy (u1) * q));
varf a (u1, u2) = int2d (Th) (dx (u1) * dx (u2) + dy (u1) * dy (u2))
+ en (3, u1 = 1) + en (1,2,4, u1 = 0);
// Observación: poner el sobre (3, u1 = 1) antes en (1,2,4, u1 = 0)
// porque queremos cero en la intersección%

matriz A = a (Xh, Xh, solucionador = CG);


matriz Bx = bx (Xh, Mh); // B = (Bx por)
matriz By = by (Xh, Mh);

Xh bc1; bc1 [] = a (0, Xh); // contribución de la condición de contorno en u1


Xh bc2; bc2 = O; // sin contribución de condición de contorno en u2
Xh b;

p hn → BA −1 (−B p hn ) = −divu h se realiza como la función divup.

func real [ int ] divup ( real [ int ] & pp)


{
// calcular u1 (pp)
b [] = Bx '* pp; b [] * = - 1; b [] + = bc1 []; u1 [] = Aˆ-1 * b [];
// calcular u2 (pp)
b [] = Por '* pp; b [] * = - 1; b [] + = bc2 []; u2 [] = Aˆ-1 * b [];
// u n = A −1 (Bx T p n Por T p n ) T
ppp [] = Bx * u1 []; // ppp = Bxu 1
ppp [] + = Por * u2 []; // + Byu 2
return ppp [];
};

Llame ahora al algoritmo de gradiente conjugado:

p = 0; q = 0; // p0
h= 0
LinearCG (divup, p [], eps = 1.e-6, nbiter = 50); // p hn + 1 = p n h
n+1 h+ Bu n
// si n> 50 o | p h
-pn
h | ≤ 10 −6 , luego el final del ciclo.
divup (p []); // calcular la solución final

plot ([u1, u2], p, espera = 1, valor = verdadero, coef = 0.1);

9.6.3 NSUzawaCahouetChabart.edp
En este ejemplo resolvemos la ecuación de Navier-Stokes más allá de un cilindro con el algoritmo de Uzawa
preacondicionado por el método Cahouet-Chabart (ver [36] para todos los detalles).
La idea del preacondicionador es que en un dominio periódico, todos los operadores diferenciales conmutan y
el algoritmo de Uzawa llega a resolver el operador lineal ∇. ((αId + ν∆) −1 ∇, donde Id es el
operador de identidad. Entonces, el preacondicionador sugerido es α∆ −1 + νId.

Para implementar esto, hacemos

https://translate.googleusercontent.com/translate_f 247/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Ejemplo 9.24 (NSUzawaCahouetChabart.edp)

real D = 0,1, H = 0,41;


cx0 real = 0,2, cy0 = 0,2; // centro de cil.
real xa = 0,15, ya = 0,2, xe = 0,25, ye = 0,2;

Página 279
9.6. ECUACIÓN DE NAVIER-STOKES 279

frontera fr1 (t = 0,2.2) {x = t; y = 0; etiqueta = 1;}


borde fr2 (t = 0, H) {x = 2,2; y = t; etiqueta = 2;}
frontera fr3 (t = 2.2,0) {x = t; y = H; etiqueta = 1;}
borde fr4 (t = H, 0) {x = 0; y = t; etiqueta = 1;}
borde fr5 (t = 2 * pi, 0) {x = cx0 + D * sin (t) / 2; y = cy0 + D * cos (t) / 2; etiqueta = 3;}
int nn = 15;

malla Th = buildmesh (fr1 (5 * nn) + fr2 (nn) + fr3 (5 * nn) + fr4 (nn) + fr5 (-nn * 3));
Um real = 1,5; // velocidad máxima (Rey 100)
func Ub = Um * 2. / 3 .;
nu real = 1e-3;
Rey real = Ub * D / nu;
// Condición de frontera
func U1 = 4. * Um * y * (Hy) / (H * H);
func U2 = 0.;

T real = 2, t = 0;
dt real = D / nn / Um; // CFL = 1
cout << "dt =" << dt << endl;
alfa real = 1 / dt, epspq = 1e-10;

fespace Mh (Th, [P1]);


espacio libre Xh (Th, [P2]);
fespace Wh (Th, [P1dc]);
macro grad (u) [dx (u), dy (u)] //
macro div (u1, u2) (dx (u1) + dy (u2)) //

varf von1 ([u1, u2, p], [v1, v2, q]) = en (3, u1 = 0, u2 = 0) + en (1, u1 = U1, u2 = U2);

// observación: el valor 100 en la siguiente línea se ajusta manualmente, porque es gratis


salida.
varf vA (p, q) = int2d (Th) ((grad (p) '* grad (q))) + int1d (Th, 2) (100 * p * q);

varf vM (p, q) = int2d (Th, qft = qf2pT) (p * q) + en (2, p = 0);

varf vu ([u1], [v1]) = int2d (Th) (alpha * (u1 * v1) + nu * (grad (u1) '* grad (v1)))
+ en (1,3, u1 = 0);
varf vu1 ([p], [v1]) = int2d (Th) (p * dx (v1));
varf vu2 ([p], [v1]) = int2d (Th) (p * dy (v1));

matriz pAM = vM (Mh, Mh, solucionador = UMFPACK);


matriz pAA = vA (Mh, Mh, solucionador = UMFPACK);
matriz AU = vu (Xh, Xh, solucionador = UMFPACK);
matriz B1 = vu1 (Mh, Xh);
matriz B2 = vu2 (Mh, Xh);
Xh u1, u2;
Mh p;
varf vonu1 ([u1], [v1]) = en (1, u1 = U1) + en (3, u1 = 0);
varf vonu2 ([u1], [v1]) = en (1, u1 = U2) + en (3, u1 = 0);

real [ int ] brhs1 = vonu1 (0, Xh);

https://translate.googleusercontent.com/translate_f 248/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 280
280 CAPÍTULO 9. MODELOS MATEMÁTICOS

real [ int ] brhs2 = vonu2 (0, Xh);

varf vrhs1 (uu, vv) = int2d (Th) ( convect ([u1, u2], - dt, u1) * vv * alpha) + vonu1;
varf vrhs2 (v2, v1) = int2d (Th) ( convect ([u1, u2], - dt, u2) * v1 * alpha) + vonu2;

Las funciones para definir Uzawa y la parte del preacondicionador.

func real [ int ] JUzawa ( real [ int ] y pp)


{
real [ int ] b1 = brhs1; b1 + = B1 * pp;
real [ int ] b2 = brhs2; b2 + = B2 * pp;
u1 [] = AUˆ-1 * b1;
u2 [] = AUˆ-1 * b2;
pp = B1 '* u1 [];
pp + = B2 '* u2 [];
pp = -pp;
volver pp;
}

func real [int] Precon ( real [ int ] & p)


{
real [ int ] pa = pAAˆ-1 * p;
real [ int ] pm = pAMˆ-1 * p;
real [ int ] pp = alpha * pa + nu * pm;
volver pp;
}

El bucle en el tiempo. Advertencia con la prueba de parada del gradiente conjugado, porque partimos del
solución anterior y al final la solución anterior está cerca de la solución final, no tome un relativo
detener la prueba hasta el primer residuo, realizar una prueba de parada absoluta (aquí negativo)

verbosidad = 0;
p = 0;

Wh w; // para almacenar vorticidad ..

eps real = 1e-6;


int ndt = T / dt;
para ( int i = 0; i <ndt; ++ i)
{
brhs1 = vrhs1 (0, Xh);
brhs2 = vrhs2 (0, Xh);
int res = LinearCG (JUzawa, p [], precon = Precon, nbiter = 100, verbosidad = 10, veps = eps);
afirmar (res == 1);
eps = -abs (eps);
w = -dy (u1) + dx (u2);
plot (w, fill = 1, wait = 0, nbiso = 40);

dt = min (dt, Tt);


t + = dt;
si (dt <1e-10 * T) se rompe;
}
plot (w, fill = 1, wait = 0, nbiso = 40, ps = "NScahouetChabart"); // ver fig. 9.24

Página 281

https://translate.googleusercontent.com/translate_f 249/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
9,7. DESIGUALDAD VARIACIONAL 281

cout << "u1 max" << u1 []. linfty


<< "u2 max" << u2 []. linfty
<< "p max =" << p []. max << endl;

Figura 9.24: La vorticidad en Reynolds número 100 por vez 2s con el Cahouet-Chabart
método.

9.7 Desigualdad variacional


Presentamos un ejemplo clásico de desigualdad variacional.
Denotemos C = {u ∈ H 1
0 (Ω), u ≤ g}
El problema es :

1 ∫ ∫
u = arg min J (u) = ∇u.∇u - fu
u∈C 2 Ω Ω

donde f y g tienen función.


La solución es una proyección sobre la convexa C de f ⋆ para el producto escalar ((v, w)) = ∫ Ω
∇v.∇w de
H1 fv, ∀v ∈ H 1
0 (Ω) donde f ⋆ es la solución de ((f ⋆ , v)) = ∫ Ω 0 (Ω). La proyección sobre un convexo satisface
claramente ∀v ∈ C, ((u - v, u - ˜ ≤ 0, y después de expandir, obtenemos la desigualdad clásica
f))

∫ ∫
∀v ∈ C, ∇ (u - v) ∇u ≤ (u - v) f.
Ω Ω

También podemos reescribir el problema como un problema de punto de silla.


Encuentre λ, u tal que:

1 ∫ ∫ ∫
max min L (u, λ) = ∇u.∇u - fu + λ (u - g) +
λ∈L 2 (Ω), λ≥0 u∈H 1
0 (Ω)
2 Ω Ω Ω

donde ((u - g) + = max (0, u - g)


Este problema del punto silla es equivalente a encontrar u, λ tal que:

∫ ∫
∇u.∇v + λv + dω = fu, ∀v ∈ H 1
0 (Ω)
Ω Ω
(9,54)

µ (u - g) + = 0, ∀µ ∈ L 2 (Ω), µ ≥ 0, λ ≥ 0,
Ω

Un algoritmo para resolver el problema anterior es:

1. k = 0, y elija, λ 0 pertenecen a H −1 (Ω)

2. bucle en k = 0, .....

Página 282
282 CAPÍTULO 9. MODELOS MATEMÁTICOS

(a) establecer I k = {x ∈ Ω / λ k + c ∗ (u k + 1 - g) ≤ 0}
(b) V g, k + 1 = {v ∈ H 1
0 (Ω) / v = g en I k },
(c) V 0, k + 1 = {v ∈ H 1
0 (Ω) / v = 0 en I k },

(d) Encuentre u k + 1 ∈ V g, k + 1 y λ k + 1 ∈ H −1 (Ω) tal que

∫ ∫
https://translate.googleusercontent.com/translate_f 250/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
∫ ∫
∇u k + 1 .∇v k + 1 dω = fv k + 1 , ∀v k + 1 ∈ V 0, k + 1
Ω Ω

<λ k + 1 , v> = ∇u k + 1 .∇v - fv dω
Ω

donde <,> es el soporte de dualidad entre H 1


0 (Ω) y H −1 (Ω), y c es una penalización
constante (suficientemente grande).

Puede encontrar todas las matemáticas sobre este algoritmo en [ 38] .


Ahora, cómo hacer eso en FreeFem ++
El ejemplo completo es:

Ejemplo 9.25 (VI.edp)

malla Th = cuadrado (20,20);


eps real = 1e-5;
fespace Vh (Th, P1); // Espacio P1 FE
int n = Vh.ndof; // número de Grado de libertad
Vh uh, uhp; // solución y anterior
Vh Ik; // para definir el conjunto donde se alcanza el contenido.
real [int] rhs (n); // para almacenar el lado derecho de la ecuación
real c = 1000; // el parámetro de penalización del algoritmo
func f = 1; // función del lado derecho
func fd = 0; // Función de condición de contorno de Dirichlet
Vh g = 0,05; // la función discreta g

real [int] Aii (n), Aiin (n); // para almacenar la diagonal de la versión matrix 2

tgv real = 1e30; // un valor enorme para la penalización exacta


// de condición de frontera
// la forma variatonal del problema:
varf a (uh, vh) = // definición del problema
int2d (Th) (dx (uh) * dx (vh) + dy (uh) * dy (vh)) // forma bilineal
- int2d (Th) (f * vh) // forma lineal
+ en (1,2,3,4, uh = fd); // formulario de condición de límite

// dos versiones de la matriz del problema


matriz A = a (Vh, Vh, tgv = tgv, solucionador = CG); // uno cambiando
matriz AA = a (Vh, Vh, solucionador: GC); // uno para calcular residual

// la construcción de matriz de masa:


varf vM (uh, vh) = int2d (Th) (uh * vh);
matriz M = vM (Vh, Vh); // para hacer un cálculo rápido de la norma L 2 : sqrt (
u '* (w = M * u))

Aii = A.diag; // obtener la diagonal de la matriz (aparece en la versión 1.46-1)

rhs = a (0, Vh, tgv = tgv);

Página 283
9,8. DESCOMPOSICIÓN DE DOMINIOS 283

Ik = 0;
uhp = -tgv; // el valor anterior es
Vh lambda = 0;
para (int iter = 0; iter <100; ++ iter)
{
real [int] b (n); b = rhs; // obtener una copia del lado derecho
real [int] Ak (n); // el complementario de Ik (! Ik = (Ik-1))
// Hoy el operador Ik- 1. no está implementado, así que lo hacemos:
Ak = 1 .; Ak - = Ik []; // construir Ak =! Yo
// agregando una nueva condición de bloqueo en by en la diagonal if (Ik == 1)
b = Ik []. * g []; b * = tgv; b - = Ak. * rhs;
Aiin = Ik [] * tgv; Aiin + = Ak. * Aii; // establecer Aii = tgv i ∈ Ik
A.diag = Aiin; // establecer la diagonal de la matriz (aparece en la versión 1.46-1)
conjunto (A, solucionador = CG); // importante cambiar el preacondicionamiento para resolver
uh [] = Aˆ-1 * b; // resolver el problema con más condiciones de bloqueo

https://translate.googleusercontent.com/translate_f 251/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
lambda [] = AA * uh []; // calcular el residual (rápido con matriz)
lambda [] + = rhs; // comentario rhs = - ∫ fv

Ik = (lambda + c * (g- uh)) <0 .; // el nuevo valor de bloqueo

plot (Ik, wait = 1, cmm = "lock set", value = 1, ps = "VI-lock.eps", fill = 1);
plot (uh, espera = 1, cmm = "uh", ps = "VI-uh.eps");
// truco para calcular la norma L 2 de la variación (método rápido)
real [int] diff (n), Mdiff (n);
diff = uh [] - uhp [];
Mdiff = M * diff;
err real = sqrt (Mdiff '* diff);
cout << "|| u_ {k = 1} - u_ {k} || _2" << err << endl;
si (err <eps) romper ; // detener la prueba
uhp [] = uh []; // establecer la solución anterior
}
savemesh (Th, "mm", [x, y, uh * 10]); // para meditar la trama

Observe que, como puede ver en este ejemplo, algunos vectores o operadores matriciales no están implementados, por lo que
una forma es omitir la expresión y usamos el operador + =, - = para fusionar el resultado.

9.8 Descomposición de dominio


Presentamos, tres ejemplos clásicos, de técnica de descomposición de dominios: primero, algoritmo de Schwarz
con superposición, segundo algoritmo de Schwarz sin superposición (también llamado complemento de Shur), y
Por último, mostramos cómo usar el gradiente conjugado para resolver el problema de límites del complemento de Shur.

9.8.1 Esquema de superposición de Schwarz


Resolver
−∆u = f, enΩ = Ω 1 ∪ Ω 2 u|Γ=0

el algoritmo de Schwarz se ejecuta así

−∆u n +1 1 = f en Ω 1 u 1n + 1 | Γ 1 = u n 2
−∆u n +2 1 = f en Ω 2 u 2n + 1 | Γ 2 = u n 1

donde Γ i es el límite de Ω i y con la condición de que Ω 1 ∩ Ω 2 = ∅ y que u i sean cero en


iteración 1.

Página 284
284 CAPÍTULO 9. MODELOS MATEMÁTICOS

Aquí tomamos Ω 1 como un cuadrilátero, Ω 2 un disco y aplicamos el algoritmo comenzando desde cero.

Figura 9.25: Las 2 mallas superpuestas TH y th

Ejemplo 9.26 (Schwarz-superposición.edp)

https://translate.googleusercontent.com/translate_f 252/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

int inside = 2; // límite interior


int fuera = 1; // límite exterior
borde a (t = 1,2) {x = t; y = 0; etiqueta = exterior;};
borde b (t = 0,1) {x = 2; y = t; etiqueta = exterior;};
borde c (t = 2,0) {x = t; y = 1; etiqueta = exterior;};
borde d (t = 1,0) {x = 1-t; y = t; etiqueta = interior;};
borde e (t = 0, pi / 2) {x = cos (t); y = sin (t); etiqueta = interior;};
borde e1 (t = pi / 2, 2 * pi) {x = cos (t); y = sin (t); etiqueta = exterior;};
int n = 4;
malla th = buildmesh (a (5 * n) + b (5 * n) + c (10 * n) + d (5 * n));
malla TH = buildmesh (e (5 * n) + e1 (25 * n));
trama (th, TH, espera = 1); // para ver las 2 mallas

La definición de espacio y problema es:

fespace vh (th, P1 );
fespace VH (TH, P1 );
vh u = 0, v; VH U, V;
int i = 0;

problema PB (U, V, init = i, solucionador = Cholesky) =


int2d (TH) (dx (U) * dx (V) + dy (U) * dy (V))
+ int2d (TH) (-V) + encendido (adentro, U = u) + encendido (afuera, U = 0);
problema pb (u, v, init = i, solucionador = Cholesky) =
int2d (th) (dx (u) * dx (v) + dy (u) * dy (v))
+ int2d (th) (-v) + encendido (adentro, u = U) + encendido (afuera, u = 0);

El ciclo de cálculo:

para (i = 0; i <10; i ++)


{
PB;
pb;

Página 285
9,8. DESCOMPOSICIÓN DE DOMINIOS 285

plot (U, u, espera = verdadero);


};

Figura 9.26: Isovalores de la solución en la iteración 0 y la iteración 9

9.8.2 Esquema de no superposición de Schwarz


Resolver
−∆u = f enΩ = Ω 1 ∪ Ω 2 u | Γ = 0,

el algoritmo de Schwarz para la descomposición de dominios sin superposición de ejecuciones como esta

https://translate.googleusercontent.com/translate_f 253/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 9.27: Las dos mallas TH y th sin superposición

Introduzcamos Γ i es común el límite de Ω 1 y Ω 2 y Γ i


e = ∂Ω yo \ Γ yo .
El problema encuentra λ tal que (u 1 | Γ i = u 2 | Γ i ) donde u i es la solución del siguiente problema de Laplace:

−∆u i = f en Ω i u i | Γ yo = λ u yo | Γ yo mi = 0

Para resolver este problema, simplemente hacemos un ciclo con upgradeλ con

(u 1 - u 2 )
λ=λ±
2

Página 286
286 CAPÍTULO 9. MODELOS MATEMÁTICOS

donde el signo + o - de ± se elige para tener convergencia.

Ejemplo 9.27 (Schwarz-no-superposición.edp)

// schwarz1 sin superposición


int inside = 2;
int fuera = 1;
borde a (t = 1,2) {x = t; y = 0; etiqueta = exterior;};
borde b (t = 0,1) {x = 2; y = t; etiqueta = exterior;};
borde c (t = 2,0) {x = t; y = 1; etiqueta = exterior;};
borde d (t = 1,0) {x = 1-t; y = t; etiqueta = interior;};
borde e (t = 0, 1) {x = 1-t; y = t; etiqueta = interior;};
borde e1 (t = pi / 2, 2 * pi) {x = cos (t); y = sin (t); etiqueta = exterior;};
int n = 4;
malla th = buildmesh (a (5 * n) + b (5 * n) + c (10 * n) + d (5 * n));
malla TH = buildmesh (e (5 * n) + e1 (25 * n));
plot (th, TH, espera = 1, ps = "schwarz-no-u.eps");
fespace vh (th, P1);
fespace VH (TH, P1);
vh u = 0, v; VH U, V;
vh lambda = 0;
int i = 0;

problema PB (U, V, init = i, solucionador = Cholesky) =


int2d (TH) (dx (U) * dx (V) + dy (U) * dy (V))
+ int2d (TH) (-V)
+ int1d (TH, interior) (lambda * V) + encendido (exterior, U = 0);
problema pb (u, v, init = i, solucionador = Cholesky) =
int2d (th) (dx (u) * dx (v) + dy (u) * dy (v))
+ int2d (th) (-v)
+ int1d (th, interior) (- lambda * v) + encendido (fuera, u = 0);

para (i = 0; i <10; i ++)


{
PB;
pb;

https://translate.googleusercontent.com/translate_f 254/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
lambda = lambda - (uU) / 2;
plot (U, u, espera = verdadero);
};

gráfico (U, u, ps = "schwarz-no-u.eps");

9.8.3 Schwarz-gc.edp
Resolver
−∆u = f enΩ = Ω 1 ∪ Ω 2 u | Γ = 0,

el algoritmo de Schwarz para la descomposición de dominios sin superposición de ejecuciones como esta
Introduzcamos Γ i es común el límite de Ω 1 y Ω 2 y Γ i
e= ∂Ω yo \ Γ yo .

Página 287
9,8. DESCOMPOSICIÓN DE DOMINIOS 287

Figura 9.28: Isovalores de la solución en la iteración 0 y la iteración 9 sin superposición

El problema encuentra λ tal que (u 1 | Γ i = u 2 | Γ i ) donde u i es la solución del siguiente problema de Laplace:

−∆u i = f en Ω i u i | Γ yo = λ u yo | Γ yo mi = 0

La versión de este ejemplo utiliza el complemento Shur. El problema de la frontera se resuelve con un
método de gradiente conjugado.
Primero, construimos los dos dominios

Ejemplo 9.28 (Schwarz-gc.edp)

// Schwarz sin superposición (complemento de Shur de Neumann a Dirichet)


CPU real = reloj ();
int inside = 2;
int fuera = 1;

borde Gamma1 (t = 1,2) {x = t; y = 0; etiqueta = exterior;};


borde Gamma2 (t = 0,1) {x = 2; y = t; etiqueta = exterior;};
borde Gamma3 (t = 2,0) {x = t; y = 1; etiqueta = exterior;};

border GammaInside (t = 1,0) {x = 1-t; y = t; etiqueta = interior;};

borde GammaArc (t = pi / 2, 2 * pi) {x = cos (t); y = sin (t); etiqueta = exterior;};


int n = 4;
// construir la malla de Ω 1 y Ω 2
malla Th1 = buildmesh (Gamma1 (5 * n) + Gamma2 (5 * n) + GammaInside (5 * n) + Gamma3 (5 * n));
malla Th2 = buildmesh (GammaInside (-5 * n) + GammaArc (25 * n));
gráfico (Th1, Th2);

// definido el espacio 2 FE

https://translate.googleusercontent.com/translate_f 255/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
fespace Vh1 (Th1, P1), Vh2 (Th2, P1);

Nota 9.6 Es imposible definir una función solo en una parte del límite, por lo que la función lambda
debe estar definido en todos los dominios Ω 1 como

Vh1 lambda = 0; // tomar λ ∈ V h1

Página 288
288 CAPÍTULO 9. MODELOS MATEMÁTICOS

El problema de los dos Poisson:

Vh1 u1, v1; Vh2 u2, v2;


int i = 0; // para la optimización de la factorización
problema Pb2 (u2, v2, init = i, solucionador = Cholesky) =
int2d (Th2) (dx (u2) * dx (v2) + dy (u2) * dy (v2))
+ int2d (Th2) (-v2)
+ int1d (Th2, interior) (- lambda * v2) + encendido (afuera, u2 = 0);
problema Pb1 (u1, v1, init = i, solucionador = Cholesky) =
int2d (Th1) (dx (u1) * dx (v1) + dy (u1) * dy (v1))
+ int2d (Th1) (-v1)
+ int1d (Th1, interior) (+ lambda * v1) + encendido (exterior, u1 = 0);

o, definimos una matriz de borde, porque la función lambda no es cero dentro del dominio Ω 1 :

varf b (u2, v2, solucionador = CG) = int1d (Th1, interior) (u2 * v2);
matriz B = b (Vh1, Vh1, solucionador = CG);

La función del problema de límites,



λ-→ (u 1 - u 2 ) v 1
Γ yo

func real [ int ] BoundaryProblem (real [int] & l)


{
lambda [] = l; // hacer que la función FE forme l
Pb1; Pb2;
i ++; // sin refactorización i! = 0
v1 = - (u1-u2);
lambda [] = B * v1 [];
return lambda [];
};

Nota 9.7 La diferencia entre las dos notaciones v1 y v1 [] es: v1 es el elemento finito
función y v1 [] es el vector en la base canónica de la función de elementos finitos v1.

Vh1 p = 0, q = 0;
// resuelve el problema con el gradiente conjugado
LinearCG (BoundaryProblem, p [], eps = 1.e-6, nbiter = 100);
// calcular la solución final, porque CG trabaja con incremento
Problema de límite (p []); // resolver de nuevo para tener la derecha u1, u2

cout << "- tiempo de CPU schwarz-gc:" << reloj () - cpu << endl;
trama (u1, u2); // gráfico

https://translate.googleusercontent.com/translate_f 256/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 289
9,9. PROBLEMA ACOPLADO FLUIDO / ESTRUCTURAS 289

9.9 Problema de acoplamiento de fluidos / estructuras


Este problema involucra el sistema de elasticidad Lamé y el sistema Stokes para fluidos viscosos con
velocidad u y presión p:

- ∆u + ∇p = 0, ∇ · u = 0, en Ω, u = u Γ en Γ = ∂Ω

donde u Γ es la velocidad de los límites. La fuerza que el fluido aplica a los límites es la
estrés normal
h = (∇u + ∇u T ) n - pn

Los sólidos elásticos sujetos a fuerzas se deforman: un punto en el sólido, en (x, y) va a (X, Y) después. Cuando el
vector de desplazamiento v = (v 1 , v 2 ) = (X - x, Y - y) es pequeño, la ley de Hooke relaciona el tensor de tensión σ
dentro del sólido al tensor de deformación ϵ:

1 ∂v i ∂v j
σ ij = λδ ij ∇.v + 2µϵ ij , ϵ ij = ( + )
2 ∂x j ∂x i

donde δ es el símbolo de Kronecker y donde λ, µ son dos constantes que describen la medida del material
propiedades canicas en términos del módulo de elasticidad y módulo de Young.
Las ecuaciones de elasticidad se escriben naturalmente en forma variacional para el vector de desplazamiento.
v (x) ∈ V como
∫ ∫ ∫
[2µϵ ij (v) ϵ ij (w) + λϵ ii (v) ϵ jj (w)] = g·w+ h · w, ∀w ∈ V
Ω Ω Γ

Los datos son la fuerza de gravedad gy la tensión en la frontera h.

Ejemplo 9.29 (fluidStruct.edp) En nuestro ejemplo, el sistema Lamé y el sistema Stokes están acoplados
por un límite común en el que la tensión del fluido crea un desplazamiento del límite y, por lo tanto,
cambia la forma del dominio donde se integra el problema de Stokes. La geometría es la de
una cavidad impulsada verticalmente con una tapa elástica. La tapa es una viga con peso por lo que se deformará por
su propio peso y por el estrés normal debido a la reacción del fluido. La cavidad es el cuadrado de 10 × 10
y la tapa es un rectángulo de altura l = 2.

Una viga se asienta sobre una caja llena de fluido que gira porque el lado vertical izquierdo tiene una velocidad. El haz
se dobla por su propio peso, pero la presión del fluido modifica la flexión.
El desplazamiento de flexión de la viga viene dado por (uu, vv) cuya solución se da de la siguiente manera.

// Interacción fluido-estructura para una viga de pesaje asentada sobre un


// cavidad cuadrada llena de un fluido.

int viga inferior = 2; // etiqueta de la viga inferior


borde a (t = 2,0) {x = 0; y = t; etiqueta = 1;}; // haz izquierdo
borde b (t = 0,10) {x = t; y = 0; etiqueta = viga inferior;}; // parte inferior de la viga
borde c (t = 0,2) {x = 10; y = t; etiqueta = 1;}; // haz derecho
borde d (t = 0,10) {x = 10-t; y = 2; etiqueta = 3;}; // viga superior
E real = 21,5;
sigma real = 0,29;
mu real = E / (2 * (1 + sigma));
lambda real = E * sigma / ((1 + sigma) * (1-2 * sigma));
gravedad real = -0,05;
malla th = buildmesh (b (20) + c (5) + d (20) + a (5));
fespace Vh (th, P1 );
Vh uu, w, vv, s, fuerza de fluido = 0;

https://translate.googleusercontent.com/translate_f 257/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 290
290 CAPÍTULO 9. MODELOS MATEMÁTICOS

cout << "lambda, mu, gravedad =" << lambda << "" << mu << "" << gravedad << endl ;
// deformación de una viga por su propio peso
resolver bb ([uu, vv], [w, s]) =
int2d (th) (
lambda * div (w, s) * div (uu, vv)
+ 2. * mu * ( épsilon (w, s) '* épsilon (uu, vv))
)
+ int2d (th) (-gravedad * s)
+ En (1, uu = 0, vv = 0)
+ fuerza fluida [];
;

plot ([uu, vv], espera = 1);


malla th1 = movemesh (th, [x + uu, y + vv]);
plot (th1, espera = 1);

Luego, la ecuación de Stokes para fluidos a baja velocidad se resuelve en el cuadro debajo de la viga, pero la viga tiene
deformado la caja (ver borde h):

// Stokes en el cuadrado b, e, f, g conducido cavite en el lado izquierdo g


borde e (t = 0,10) {x = t; y = -10; etiqueta = 1; }; // fondo
borde f (t = 0,10) {x = 10; y = -10 + t; etiqueta = 1; }; // derecho
borde g (t = 0,10) {x = 0; y = -t; etiqueta = 2;}; // izquierda
borde h (t = 0,10) {x = t; y = vv (t, 0) * (t> = 0,001) * (t <= 9,999);
etiqueta = 3;}; // parte superior de la cavidad deformada

malla sh = buildmesh (h (-20) + f (10) + e (10) + g (10));


plot (sh, espera = 1);

Usamos el gradiente conjugado de Uzawa para resolver el problema de Stokes como en el ejemplo de la Sección 9.6.2

espacio libre Xh (sh, P2), Mh (sh, P1);


Xh u1, u2, v1, v2;
Mh p, q, ppp;

varf bx (u1, q) = int2d (sh) (- (dx (u1) * q));

varf por (u1, q) = int2d (sh) (- (dy (u1) * q));

varf Lap (u1, u2) = int2d (sh) (dx (u1) * dx (u2) + dy (u1) * dy (u2))
+ en (2, u1 = 1) + en (1,3, u1 = 0);

Xh bc1; bc1 [] = Vuelta (0, Xh);


Xh brhs;

matriz A = Lap (Xh, Xh, solucionador = CG);


matriz Bx = bx (Xh, Mh);
matriz By = by (Xh, Mh);
Xh bcx = 0, bcy = 1;

func real [ int ] divup ( real [ int ] & pp)


{
int verbo = verbosidad;
verbosidad = 0;
brhs [] = Bx '* pp; brhs [] + = bc1 []. * bcx [];

Página 291
9,9. PROBLEMA ACOPLADO FLUIDO / ESTRUCTURAS 291

u1 [] = Aˆ-1 * brhs [];


brhs [] = Por '* pp; brhs [] + = bc1 []. * bcy [];
u2 [] = Aˆ-1 * brhs [];

https://translate.googleusercontent.com/translate_f 258/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
ppp [] = Bx * u1 [];
ppp [] + = Por * u2 [];
verbosidad = verbo;
return ppp [];
};

haz un bucle en el problema de los dos

para ( paso = 0; paso <2; ++ paso)


{
p = 0; q = 0; u1 = 0; v1 = 0;

LinearCG (divup, p [], eps = 1.e-3, nbiter = 50);


divup (p []);

Ahora la viga sentirá la restricción de tensión del fluido:

Vh sigma11, sigma22, sigma12;


Vh uu1 = uu, vv1 = vv;

sigma11 ([x + uu, y + vv]) = (2 * dx (u1) -p);


sigma22 ([x + uu, y + vv]) = (2 * dy (u2) -p);
sigma12 ([x + uu, y + vv]) = (dx (u1) + dy (u2));

que viene como una condición de contorno para el PDE de la viga:

resolver bbst ([uu, vv], [w, s], init = i) =


int2d (th) (
lambda * div (w, s) * div (uu, vv)
+ 2. * mu * ( épsilon (w, s) '* épsilon (uu, vv))
)
+ int2d (th) (-gravedad * s)
+ int1d (th, viga inferior) (-coef * ( sigma11 * Nx * w + sigma22 * Ny * s
+ sigma12 * (Ny * w + Nx * s)))
+ en (1, uu = 0, vv = 0);
plot ([uu, vv], espera = 1);
err real = sqrt ( int2d (th) ((uu-uu1) ˆ2 + (vv-vv1) ˆ2));
cout << "Erreur L2 =" << err << "---------- \ n";

Observe que la matriz generada por bbst se reutiliza (consulte init = i). Finalmente deformamos la viga

th1 = movemesh (th, [x + 0.2 * uu, y + 0.2 * vv]);


plot (th1, espera = 1);
} // fin de bucle

Página 292
292 CAPÍTULO 9. MODELOS MATEMÁTICOS
[u1, u2], p
IsoValue
-2,62541
-2,26528
-1.90515
-1,54503
-1.1849
-0,824776
-0,46465
-0,104524
0.255603
0,615729
0.975855
1.33598
1.69611
2.05623
2.41636
2.77649
3.13661
3.49674
3.85686
4.21699

Valor de Vec
0 0,0499861
0.0999722
0.149958
0.199944
0.249931
0.299917
0.349903
0.399889
0,449875
0.499861
0.549847
0.599833
0,649819
0,699806
0,749792
0,799778
0.849764
0.89975
0,949736

https://translate.googleusercontent.com/translate_f 259/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 9.29: Velocidad y presión del fluido (izquierda) y vector de desplazamiento (centro) del
estructura y geometría desplazada (derecha) en la interacción fluido-estructura de un lado blando y
una cavidad conducida

9.10 Problema de transmisión


Considere una placa elástica cuyo desplazamiento cambia verticalmente, que se compone de tres placas de
diferentes materiales, soldados entre sí. Sea Ω i , i = 1,2,3 el dominio ocupado por i-ésimo material
con tensión µ i (ver Sección 9.1. 1). El dominio computacional Ω es el interior de Ω 1 ∪ Ω 2 ∪ Ω 3 .
El desplazamiento vertical u (x, y) se obtiene de

−µ yo ∆u = f en Ω yo (9,55)
µ i ∂ n u | Γ yo = −µ j ∂ n u | Γ j en Ω i ∩ Ω j si 1 ≤ i <j ≤ 3 (9,56)

donde ∂ n u | Γ i denota el valor de la derivada normal ∂ n u en el límite Γ i del dominio Ω i .


Introduciendo la función característica χ i de Ω i , es decir,

χ i (x) = 1 si x ∈ Ω i ; χ yo (x) = 0 si x ∈ Ω yo (9,57)

podemos reescribir fácilmente (9. 55) y (9.56) a la forma débil. Aquí asumimos que u = 0onΓ = ∂Ω.
Problema Transmisión: Para una función f dada, encuentre u tal que

a (u, v) = l (f, v) para todo v ∈ H 1 (9,58)


0 (Ω)
∫ ∫
a (u, v) = µ∇u · ∇v, l (f, v) = fv
Ω Ω

donde µ = µ 1 χ 1 + µ 2 χ 2 + µ 3 χ 3 . Aquí notamos que µ se convierte en la función discontinua.


Con disipación, y en equilibrio térmico, la ecuación de temperatura es:
Este ejemplo explica la definición y manipulación de región, es decir, subdominios del conjunto
dominio.
Considere este dominio en forma de L con 3 diagonales como límites internos, definiendo 4 subdominios:

// ejemplo usando la palabra clave region


// construir una malla con 4 regiones (subdominios)

Página 293
9.10. PROBLEMA DE TRANSMISIÓN 293

borde a (t = 0,1) {x = t; y = 0;};


borde b (t = 0,0.5) {x = 1; y = t;};
borde c (t = 0,0.5) {x = 1-t; y = 0.5;};
borde d (t = 0.5,1) {x = 0.5; y = t;};
borde e (t = 0.5,1) {x = 1-t; y = 1;};
borde f (t = 0,1) {x = 0; y = 1-t;};
// límite interno
borde i1 (t = 0,0.5) {x = t; y = 1-t;};
borde i2 (t = 0,0.5) {x = t; y = t;};
borde i3 (t = 0,0.5) {x = 1-t; y = t;};

malla th = buildmesh (a (6) + b (4) + c (4) + d (4) + e (4) +


f (6) + i1 (6) + i2 (6) + i3 (6));
fespace Ph (th, P0); // funciones / elemento discontinuos constantes
fespace Vh (th, P1); // P 1 funciones continuas / elemento

Ph reg = región; // definió la función P 0 asociada al número de región


plot (reg, fill = 1, wait = 1, value = 1);

IsoValue IsoValue
-0,315789 1
0.157895 1
0,473684 1

https://translate.googleusercontent.com/translate_f 260/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
0,789474 1
1.10526 1
1,42105 1
1.73684 1
2.05263 1
2.36842 1
2.68421 1
3 1
3.31579 1
3.63158 1
3.94737 1
4.26316 1
4.57895 1
4.89474 1
5.21053 1
5.52632 1
6.31579 1

Figura 9.30: la función reg Figura 9.31: la función nu

region es una palabra clave de FreeFem ++ que de hecho es una variable que depende de la posición actual
(no es una función hoy, use Ph reg = region; para establecer una función). Este valor de variable devuelto
es el número del subdominio de la posición actual. Este número está definido por "buildmesh"
que escanea mientras construye la malla todos sus componentes conectados. Entonces, para obtener el número de una región
que contiene un punto particular uno hace:

int nupper = reg (0.4,0.9); // obtener el número de región del punto (0.4,0.9)
int nlower = reg (0.9,0.1); // obtener el número de región del punto (0.4,0.1)
cout << "nlower" << nlower << ", nupper =" << nupper << endl;
// definió las funciones características de la región superior e inferior
Ph nu = 1 + 5 * (región == nlower) + 10 * (región == nupper);

Página 294
294 CAPÍTULO 9. MODELOS MATEMÁTICOS

plot (nu, fill = 1, wait = 1);

Esto es particularmente útil para definir funciones discontinuas como podría ocurrir cuando una parte de
el dominio es el cobre y el otro es el hierro, por ejemplo.
Teniendo esto en cuenta procedemos a resolver una ecuación de Laplace con coeficientes discontinuos (ν es 1, 6
y 11 a continuación).

Ph nu = 1 + 5 * (región == nlower) + 10 * (región == nupper);


plot (nu, fill = 1, wait = 1);
vuelta problema (u, v) = int2d (th) (nu * (dx (u) * dx (v) * dy (u) * dy (v)))
+ int2d (-1 * v) + en (a, b, c, d, e, f, u = 0);
trama (u);

IsoValue
0.000900259
0,00270078
0,0045013
0,00630181
0,00810233
0,00990285
0.0117034
0.0135039
0.0153044
0.0171049
0.0189054
0.020706
0.0225065
0.024307
0.0261075
0.027908
0.0297086
0.0315091
0.0333096
0.0351101

https://translate.googleusercontent.com/translate_f 261/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Figura 9.32: el isovalor de la solución u

Página 295
9.11. PROBLEMA DE LÍMITE LIBRE 295

9.11 Problema de límite libre


El dominio Ω se define con:

real L = 10; // longueur du domaine


h real = 2,1; // hauteur du bord gauche
h1 real = 0,35; // hauteur du bord droite

// maillage d'un tapeze


borde a (t = 0, L) {x = t; y = 0;}; // abajo: Γ a
borde b (t = 0, h1) {x = L; y = t;}; // derecha: Γ b
borde f (t = L, 0) {x = t; y = t * (h1-h) / L + h;}; // superficie libre: Γ f
borde d (t = h, 0) {x = 0; y = t;}; // izquierda: Γ d

int n = 4;
malla Th = buildmesh (a (10 * n) + b (6 * n) + f (8 * n) + d (3 * n));
plot (Th, ps = "dTh.eps");

Figura 9.33: La malla del dominio Ω

El problema de los límites libres es:


Encuentre u y Ω tales que:

−∆u = 0 en Ω
u=y en Γ b
∂u
=0 en Γ d ∪ Γ a
En
∂u q

https://translate.googleusercontent.com/translate_f 262/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
En = K n x y u = y en Γ f
Usamos un método de punto fijo; Ω 0 = Ω
En dos pasos, primero resolvemos el siguiente problema clásico:

−∆u = 0 en Ω n
u = y en Γ n B
∂u
= 0 en Γ n D
∪ Γ na
En
u = y en Γ n F

La formulación variacional es:


encuentre u en V = H 1 (Ω n ), tal que u = y en Γ n B yΓn F


∇u∇u = 0, ∀u ∈ V con u = 0onΓ n
Ωn
b∪ ΓnF

y en segundo lugar para construir una deformación de dominio F (x, y) = [x, y - v (x, y)]

Página 296
296 CAPÍTULO 9. MODELOS MATEMÁTICOS

donde v es la solución del siguiente problema:

−∆v = 0 en Ω n
v=0 en Γ na
∂v
=0 en Γ nB ∪ Γ nD
En
∂v ∂u q
= - nx en Γ nF
En En K
La formulación variacional es:
encuentre v en V, tal que v = 0onΓ n a

∫ ∫ ∂u q
∇v∇v = ( - n x ) v, ∀v ∈ V con v = 0onΓ n a
Ωn Γ nF En K

Finalmente el nuevo dominio Ω n + 1 = F (Ω n )

Ejemplo 9.30 (freeboundary.edp) La implementación de FreeFem ++: es:

q real = 0,02; // entrante de flujo


K real = 0,5; // permeabilité

fespace Vh (Th, P1);


int j = 0;

Vh u, v, uu, vv;

problema Pu (u, uu, solucionador = CG) = int2d (Th) (dx (u) * dx (uu) + dy (u) * dy (uu))
+ en (b, f, u = y);

problema Pv (v, vv, solucionador = CG) = int2d (Th) (dx (v) * dx (vv) + dy (v) * dy (vv))
+ en (a, v = 0) + int1d (Th, f) (vv * ((q / K) * Ny- (dx (u) * N.x + dy (u) * Ny)));

errv real = 1;
erradap real = 0,001;
verbosidad = 1;
while (errv> 1e-6)
{
j ++;
Pu;
Pv;
plot (Th, u, v, espera = 0);
errv = int1d (Th, f) (v * v);
coef real = 1;

https://translate.googleusercontent.com/translate_f 263/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
//
real mintcc = checkmovemesh (Th, [x, y]) / 5 .;
ceca real = checkmovemesh (Th, [x, yv * coef]);

si (mint <mintcc || j% 10 == 0) { // mesh to bad => remeshing


Th = adaptmesh (Th, u, err = erradap);
mintcc = checkmovemesh (Th, [x, y]) / 5 .;
}

mientras (1)

Página 297
9.12. ELASTICIDAD NO LINEAL (NOLINEAR-ELAS.EDP) 297

{
ceca real = checkmovemesh (Th, [x, yv * coef]);

si (menta> mentacc) se rompe;

cout << "min | T]" << mint << endl;


coef / = 1,5;
}

Th = movemesh (Th, [x, y-coef * v]); // cálculo de la deformación


cout << "\ n \ n" << j << "------------ errv =" << errv << "\ n \ n";

}
gráfico (Th, ps = "d_Thf.eps");
plot (u, espera = 1, ps = "d_u.eps");

Figura 9.34: La solución final en el nuevo dominio Ω 72

Figura 9.35: La malla adaptada del dominio Ω 72

9.12 Elasticidad no lineal (nolinear-elas.edp)


El problema de la elasticidad no lineal es: encuentre el desplazamiento (u 1 , u 2 ) minimizando J

∫ ∫
minJ (u 1 , u 2 ) = f (F2) - Pau2
Ω Γp

donde F2 (u 1 , u 2 ) = A (E [u 1 , u 2 ], E [u 1 , u 2 ]) y A (X, Y) es un símbolo bilineal. forma positiva con respeto


dos matrices X, Y. donde f es una función C 2 dada , y E [u 1 , u 2 ] = (E ij ) i = 1,2, j = 1,2 es el Green-Saint
Tensor de deformación de Venant definido con:


https://translate.googleusercontent.com/translate_f 264/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Mi yoj = 0.5 ((∂ yo u j + ∂ j u yo ) + ∂ yo u k × ∂ j u)k
k

Página 298
298 CAPÍTULO 9. MODELOS MATEMÁTICOS

Denote u = (u 1 , u 2 ), v = (v 1 , v 2 ), w = (w 1 , w 2 ).
Entonces, el diferencial de J es

∫ ∫
DJ (u) (v) = DF2 (u) (v) f (F2 (u))) - Pav2
Γp

donde DF2 (u) (v) = 2 A (DE [u] (v), E [u]) y DE es el primer diferencial de E.
El diferencial de segundo orden es

D 2 J (u) ((v), (w)) = DF2 (u) (v) DF2 (u) (w) f (F2 (u)))


+ D 2 F2 (u) (v, w) f (F2 (u)))

dónde

D 2 F2 (u) (v, w) = 2 A (D 2 E [u] (v, w), E [u]) + 2 A (DE [u] (v), DE [u] (w )).

y D 2 E es el segundo diferencial de E.

Entonces todas las notaciones se pueden definir con macros:

macro EL (u, v) [dx (u), (dx (v) + dy (u)), dy (v)] // es [ϵ 11 , 2ϵ 12 , ϵ 22 ]

macro ENL (u, v) [


(dx (u) * dx (u) + dx (v) * dx (v)) * 0.5,
(dx (u) * dy (u) + dx (v) * dy (v)) ,
(dy (u) * dy (u) + dy (v) * dy (v)) * 0.5] // EOM ENL

macro dENL (u, v, uu, vv) [(dx (u) * dx (uu) + dx (v) * dx (vv)),
(dx (u) * dy (uu) + dx (v) * dy (vv) + dx (uu) * dy (u) + dx (vv) * dy (v)),
(dy (u) * dy (uu) + dy (v) * dy (vv))] //

macro E (u, v) (EL (u, v) + ENL (u, v)) // es [E 11 , 2E 12 , E 22 ]


macro dE (u, v, uu, vv) (EL (uu, vv) + dENL (u, v, uu, vv)) //
macro ddE (u, v, uu, vv, uuu, vvv) dENL (uuu, vvv, uu, vv) //
macro F2 (u, v) (E (u, v) '* A * E (u, v)) //
macro dF2 (u, v, uu, vv) (E (u, v) '* A * dE (u, v, uu, vv) * 2.) //
macro ddF2 (u, v, uu, vv, uuu, vvv) (
(dE (u, v, uu, vv) '* A * dE (u, v, uuu, vvv)) * 2.
+ (E (u, v) '* A * ddE (u, v, uu, vv, uuu, vvv)) * 2. ) // MOE

El método de Newton es
elija n = 0, y u O , v O el desplazamiento inicial

• círculo:

• encontrar (du, dv): solución de

D 2 J (u n , v n ) ((w, s), (du, dv)) = DJ (u n , v n ) (w, s), ∀w, s

• un = un - du, vn = vn - dv

• hasta que (du, dv) pequeño sea suficiente

https://translate.googleusercontent.com/translate_f 265/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 299
9.12. ELASTICIDAD NO LINEAL (NOLINEAR-ELAS.EDP) 299

La forma de implementar este algoritmo en FreeFem ++ es usar una herramienta macro para implementar A y F2,
f, f, f.
Una macro es como en el preprocesador ccp de C ++, pero esto comienza por macro y el final de la macro.
la definición está antes del comentario //. En este caso, la macro es muy útil porque el tipo de
El parámetro se puede cambiar. Y es fácil hacer una diferenciación automática.

Figura 9.36: El dominio deformado

// modelo de elasticidad no lineal

// para problemas de hiper elasticidad


// -----------------------------
macro f (u) ((u) * 0.5) // fin de macro
macro df (u) (0,5) // fin de macro
macro ddf (u) (0) // fin de macro

// - du caouchouc --- (ver las notas de Herve Le Dret.)


// -------------------------------
mu real = 0.012e5; // kg / cm 2
lambda real = 0,4e5; // kg / cm 2
//
// σ = 2µE + λtr (E) Id
// A (u, v) = σ (u): E (v)
//
// (ab)
// ( antes de Cristo )
//
// tr * Id: (a, b, c) -> (a + c, 0, a + c)
// entonces la matriz asociada es:
// (1 0 1)
// (0 0 0)
// (1 0 1)
// ------------------ v
real a11 = 2 * mu + lambda;
real a22 = mu; // porque [0, 2 ∗ t12, 0] A [0, 2 ∗ s12, 0] =
// = 2 ∗ mu ∗ (t12 ∗ s12 + t21 ∗ s21) = 4 ∗ mu ∗ t12 ∗ s12
real a33 = 2 * mu + lambda;
real a12 = 0;
real a13 = lambda;
real a23 = 0;
// parte simétrica
real a21 = a12;
real a31 = a13;
real a32 = a23;

Página 300
300 CAPÍTULO 9. MODELOS MATEMÁTICOS

// la matriz A.

https://translate.googleusercontent.com/translate_f 266/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
f unc A = [[a11, a12, a13], [a21, a22, a23], [a31, a32, a33]];

Pa real = 1e2; // una presión de 100 Pa


// ----------------

int n = 30, m = 10;


malla Th = cuadrado (n, m, [x, .3 * y]); // etiqueta: 1 abajo, 2 derecha, 3 arriba, 4 izquierda;
int inferior = 1, derecha = 2, superior = 3, izquierda = 4;

trama (Th);

fespace Wh (Th, P1dc);


espacio libre Vh (Th, [P1, P1]);
fespace Sh (Th, P1);

Wh e2, fe2, dfe2, ddfe2; // mejoramiento


Wh ett, ezz, err, erz; // mejoramiento

Vh [uu, vv], [w, s], [un, vn];


[un, vn] = [0,0]; // inicialización
[uu, vv] = [0,0];

varf vmass ([uu, vv], [w, s], solucionador = CG) = int2d (Th) (uu * w + vv * s);
matriz M = vmass (Vh, Vh);
problema NonLin ([uu, vv], [w, s], solucionador = LU) =
int2d (Th, qforder = 1) ( // (D 2 J (des)) parte
dF2 (un, vn, uu, vv) * dF2 (un, vn, w, s) * ddfe2
+ ddF2 (un, vn, w, s, uu, vv) * ddfe2
)
- int1d (Jue, 3) (Pa * s)
- int2d (Th, qforder = 1) ( // (DJ (des)) parte
dF2 (un, vn, w, s) * dfe2 )
+ encendido (derecha, izquierda, uu = 0, vv = 0);
;
// Método de Newton
// ---------------
Sh u1, v1;
para (int i = 0; i <10; i ++)
{
cout << "Bucle" << i << endl;
e2 = F2 (un, vn);
dfe2 = df (e2);
ddfe2 = ddf (e2);
cout << "e2 max" << e2 []. max << ", min" << e2 []. min << endl;
cout << "de2 max" << dfe2 []. max << ", min" << dfe2 []. min << endl;
cout << "dde2 max" << ddfe2 []. max << ", min" << ddfe2 []. min << endl;
NonLin; // calcular [uu, vv] = (D 2 J (un)) −1 (DJ (un))

Página 301
9.13. MATERIALES NEO-HOOKEAN COMPRESIBLES: SOLUCIONES COMPUTACIONALES 301

w [] = M * uu [];
real res = sqrt (w [] '* uu []); // norma L 2 de [uu, vv]
u1 = uu;
v1 = vv;
cout << "Lˆ2 residual =" << res << endl;
cout << "u1 min =" << u1 []. min << ", u1 max =" << u1 []. max << endl;
cout << "v1 min =" << v1 []. min << ", v2 max =" << v1 []. max << endl;
plot ([uu, vv], espera = 1, cmm = "uu, vv");
un [] - = uu [];

https://translate.googleusercontent.com/translate_f 267/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
plot ([un, vn], espera = 1, cmm = "desplazamiento");
si (res <1e-5) se rompe;
}

plot ([un, vn], espera = 1);


malla th1 = movemesh (Th, [x + un, y + vn]);
plot (th1, espera = 1); // ver figura 9.36

9.13 Materiales Neo-Hookeanos comprimibles: Computacional


Soluciones
Autor: Alex Sadovsky mailsashas@gmail.com

9.13.1 Notación
En lo que sigue, los símbolos u, F, B, C, σ denotan, respectivamente, el campo de desplazamiento, la deformación
gradiente de deformación, el tensor de deformación de Cauchy-Green izquierdo B = FF T , el tensor de deformación de Cauchy-Green derecho
C = F T F, y el tensor de tensiones de Cauchy. También introducimos los símbolos I 1 : = tr C y J: = detF.
Se hará uso de la identidad
∂J −1
= JC (9,59)
∂C

El símbolo I denota el tensor de identidad. El símbolo Ω 0 denota la configuración de referencia del


cuerpo a deformar. El volumen de la unidad en la configuración de referencia (resp., Deformado) se indica
dV (resp., dV 0 ); estos dos están relacionados por

dV = JdV 0 ,

que permite que una integral sobre Ω que implica la tensión de Cauchy T se reescriba como una integral de la
Esfuerzo de Kirchhoff κ = JT sobre Ω 0 .

Referencias recomendadas
Para una exposición de la elasticidad no lineal y del álgebra tensorial y lineal subyacente, ver [ 39] .
Para un análisis matemático avanzado del método de elementos finitos, consulte [ 40 ]. Una explicación
de la formulación de elementos finitos de un problema de valor límite elastostático no lineal, consulte http: //
www.engin.brown.edu/courses/en222/Notes/FEMfinitestrain/FEMfinitestrain.
htm.

Página 302
302 CAPÍTULO 9. MODELOS MATEMÁTICOS

9.13.2 Un material comprimible neo-hookeano


Teoría constitutiva y medidas de tensión tangente La función de densidad de energía de deformación es
dada por
µ
W= (I 1 - tr I - 2 lnJ) (9,60)
2
(ver [37 ], fórmula (12)).
El segundo tensor de tensión de Piola-Kirchoff correspondiente está dado por

∂W −1
Sn:= (F n ) = µ (I - C ) (9,61)
∂E
El énfasis de Kirchhoff, entonces, es
κ = FSF T = µ (B - I) (9,62)
El tensor de tensión de Kirchhoff tangente en F n que actúa sobre δF n + 1 es, en consecuencia,

∂κ
(F n ) δF n + 1 = µ [F n (δF n + 1 ) T + δF n + 1 (F n ) T ] (9,63)
∂F

https://translate.googleusercontent.com/translate_f 268/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

La forma débil del BVP en ausencia de fuerzas corporales (externas) El Ω 0 que somos
considerando es un anillo elíptico, cuyo límite consta de dos elipses concéntricas (cada una permitida
ser un círculo como un caso especial), con los ejes mayores paralelos. Sea P la carga de tensión muerta
(tracción) en una porción ∂Ω t
0 (= la elipse interior) del límite ∂Ω 0 . En el resto del límite,
prescribimos desplazamiento cero.
La formulación débil del problema del valor en la frontera es

0=∫ κ [F]: {(∇ ⊗ w) (F) −1 } }


Ω0
-∫ ∂Ω t 0
PAGN̂· 0

Por brevedad, en el resto de esta sección asumimos P = 0. Sin embargo, el código FreeFem ++ proporcionado,
no se basa en esta suposición y permite un valor y una dirección generales de P.
Dada una aproximación de Newton u n del campo de desplazamiento u que satisface el BVP, buscamos el
corrección δu n + 1 para obtener una mejor aproximación

u n + 1 = u n + δu n + 1

resolviendo la formulación débil

0=∫ Ω0
κ [F n + δF n + 1 ]: {(∇ ⊗ w) (F n + δF n + 1 ) −1 } - ∫ ∂Ω 0
PAGN̂· 0
{ }
=∫ Ω0
κ [F n ] + ∂κ∂F [F n ] δF n + 1 : {(∇ ⊗ w) (F n + δF n + 1 ) −1 }
{ }
=∫ κ [F n ] + ∂κ∂F [F n ] δF n + 1 : {(∇ ⊗ w) (F −1
Ω0 n+ F −2 n δF n + 1 )}
para todas las funciones de prueba w,
=∫ κ [F n ]: {(∇ ⊗ w) F −1 norte
}
Ω0
-∫ κ [F n ]: {(∇ ⊗ w) (F −2
Ω0 n δF n + 1 )}
{ ∂κ } }
+∫ Ω0 ∂F
[F n ] δF n + 1 : {(∇ ⊗ w) F −1 norte

(9,64)
donde nos hemos llevado
δF n + 1 = ∇ ⊗ δu n + 1
Nota: Contrariamente al uso de notación estándar, el símbolo δ aquí no tiene contexto variacional. Por δ
nos referimos simplemente a un incremento en el sentido del método de Newton. El papel de un virtual variacional
el desplazamiento aquí es interpretado por w.

Página 303
9.14. MODOS DE GALERÍA SUSURRANTES 303

9.13.3 Un enfoque para la implementación en FreeFem ++


El archivo asociado es examples ++ - tutorial / nl-elast-neo-Hookean.edp.
Introduciendo la notación similar a un código, donde una cadena en <> debe leerse como un símbolo, el individuo
componentes del tensor
∂κ
<Tanque>: = [F n ] δF n + 1 (9,65)
∂F
se implementará como las macros <TanK11>, <T anK12>, ....
Los componentes individuales de las cantidades tensoriales

D 1 : = F n (δF n + 1 ) T + δF n + 1 (F n ) T ,
−T
D2:=F
n δF n + 1 ,
−2
D 3 : = (∇ ⊗ w) F
n δF n + 1 ,

y
−1
D 4 : = (∇ ⊗ w) F
n,

se implementará como macros

<d1Aux11>, <d1Aux12>, ..., <d1Aux22>,


<d2Aux11>, <d2Aux12>, ..., <d2Aux22>
, (9,66)
<d3Aux11>, <d3Aux12>, ..., <d3Aux22>
<d4Aux11>, <d4Aux12>, ..., <d4Aux22>

respectivamente.
En la notación anterior, el término de tensión de Kirchhoff tangente se convierte en
https://translate.googleusercontent.com/translate_f 269/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

∂κ
(F n ) δF n + 1 = µ D 1 (9,67)
∂F

mientras que la formulación débil de BVP adquiere la forma

0=∫ Ω0
κ [F n ]: D 4
-∫ Ω0 κ [F n ]: D 3 para todas las funciones de prueba w (9,68)
{ ∂κ }
+∫ Ω0 ∂F [F n ] δF n + 1 :D4

9.14 Modos de galería de susurros


Escrito por IS Grudinin.
En el modo de galería susurrante (WGM), los resonadores, que suelen ser esferas o discos, electromagnéticos
El campo está atrapado por reflejos internos totales del límite. Los modos de tales resonadores son
se distingue por su volumen compacto y registra factores de alta calidad (Q) en una amplia gama de frecuencias.
Las aplicaciones modernas de tales resonadores incluyen microondas y cavidades ópticas para relojes atómicos,
Optomecánica de cavidades, óptica no lineal y cuántica. Las soluciones analíticas para los modos WG son solo
disponible para un número limitado de geometrías idealizadas, como esfera o elipsoide. Desde resonador
Las dimensiones suelen ser mucho más grandes que la longitud de onda óptica, aplicación directa de 3D numérico
El dominio del tiempo de diferencia finita (FDTD) o los métodos de elementos finitos (FEM) no son prácticos. Es
posible resolver la ecuación de onda vectorial reduciéndola a un caso bidimensional tomando
simetría axial en cuenta. Tal reducción conduce a un sistema de 3 ecuaciones a resolver en un
Sección 2D “ρ - z” de un resonador. Consulte [ 51] para obtener una derivación detallada y [52] para una
ejemplo de uso de FreeFem ++ para calcular WGM.

Página 304
304 CAPÍTULO 9. MODELOS MATEMÁTICOS

9.14.1 Ecuación de onda para los WGM


Dado que el campo eléctrico es discontinuo en la superficie de un dieléctrico y el campo magnético típicamente no lo es,
derivamos nuestras ecuaciones para el campo magnético. El campo eléctrico se puede derivar fácilmente en un futuro.
etapa de E = i ωϵ 0
ˆΕ −1 ∇ × H. Siguiendo un procedimiento estándar que comienza con las ecuaciones de Maxwell
derivamos una ecuación de onda en un medio anisotrópico de un solo eje como un cristal óptico:

∇ × (ˆϵ −1 ∇ × H) - k 2 (9,69)
0H - α∇ (∇ · H) = 0
Aquí k 0 = ω / c es el número de onda, α es el término de penalización agregado para combatir las soluciones FEM falsas.
Para un medio anisotrópico de un solo eje con ∂ˆϵ / ∂φ = 0 en un sistema cilíndrico de coordenadas tenemos:

ϵρ 00
ˆΕ = 0ϵρ 0
.
00ϵz

Ahora asumimos la simetría axial de nuestros campos electromagnéticos e insertamos una unidad imaginaria delante
del H φ para permitir que todos los componentes del campo sean números reales y también para tener en cuenta el cambio de fase
de este componente H (ρ, φ, z) = {H ρ (ρ, z), iH φ (ρ, z), H z (ρ, z)} × e imφ .
Escribimos la ecuación de onda (9. 69) explícitamente en coordenadas cilíndricas, obteniendo así un conjunto de
tres ecuaciones diferenciales para el dominio Ω dadas por la sección transversal del resonador y algo de espacio
fuera de:

A 1 {H tρ , H tφ , H tz } = 0 (9,70)
A 2 {H t
ρ, H tφ , H tz } = 0
A 3 {H t
ρ, H tφ , H tz } = 0
Las soluciones numéricas de estas ecuaciones y las condiciones de contorno se pueden encontrar con FreeFem ++
si escribimos el sistema en forma débil o integral.

9.15 Formulación débil


En general, para obtener los enunciados integrales o "débiles" equivalentes al sistema (9.70 ) y al límite
condiciones formamos un producto escalar escalar entre una función de prueba de campo magnético arbitrario H t =
{H t
https://translate.googleusercontent.com/translate_f 270/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
ρ,
H tφde, H } y los componentes
dominio la tzsección transversal delderesonador
nuestra ecuación vectorial
Ω (y su límite paraAlas
1 , A 2 , A 3 , e integrar sobre el
condiciones de contorno):

(H t (9,71)
ρA1+ Ht φA2+ Ht zA3) dΩ
Ω

Podemos reducir el orden de las derivadas parciales en esta integral usando la fórmula de Green para
integración por partes. Por ejemplo:
∫ ∂2Hz ∫ ∂H t z ∂H z ∮ ∂H z
H tz dΩ = - dΩ + H tz n ρ dΓ (9,72)
∂ρ 2 ∂ρ ∂ρ ∂ρ
Ω Ω

Así, convirtiendo las ecuaciones (9 .70) obtenemos una expresión grande para la forma débil (ver [1])

9.15.1 Un ejemplo de esfera dieléctrica con FreeFem ++


Ahora calculamos la frecuencia de modo fundamental para una esfera de sílice fundida. La esfera tiene 36
micrómetro de diámetro, el índice de refracción es 1,46, la condición de límite es el magnético
wall (que en realidad se puede omitir ya que se mantiene automáticamente). El ejemplo se puede encontrar en
ejemplos ++ - valor propio / WGM-esfera.edp en la distribución.

Página 305

Capítulo 10

MPI versión paralela

Aquí se realiza un primer intento de paralelización de FreeFem ++ con mpi . Una interfaz ampliada
con MPI se ha agregado a FreeFem ++ versión 3.5, (consulte la documentación de MPI para conocer la función
nacionalidad del idioma en http://www.mpi-forum.org/docs/mpi21-report.pdf) .

10.1 palabras clave MPI


Se utilizan las siguientes palabras clave y conceptos:

mpiComm para definir un mundo de comunicación

mpiGroup para definir un grupo de procesadores en el mundo de la comunicación

mpiRequest para definir una equest para esperar el final de la comunicación

10.2 constantes MPI


mpisize El número total de procesos,

mpirank el número de identificación de mi proceso actual en {0, ..., mpisize - 1},

mpiUndefined La constante MPI_Undefined,

mpiAnySource La constante MPI_ANY_SOURCE,

mpiCommWorld La constante MPI_COMM_WORLD,

... y todas las palabras clave de MPI Op para el operador de reducción:


https://translate.googleusercontent.com/translate_f 271/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

mpiMAX, mpiMIN, mpiSUM, mpiPROD, mpiLAND, mpiLOR, mpiLXOR, mpiBAND,


mpiBXOR.

10.3 Constructor MPI

int [ int ] proc1 = [1,2,3], proc2 = [0,4];


mpiGroup grp (procs); // configurar MPI Group para proc 1,2,3 en MPI COMM WORLD

305

Página 306
306 CAPÍTULO 10. VERSIÓN PARALELO MPI

mpiGroup grp1 (comm, proc1); // configurar MPI Group para proc 1,2,3 en com
mpiGroup grp2 (grp, proc2); // establecer MPI Group en grp union proc1

mpiComm comm = mpiCommWorld; // establecer un MPI Comm en MPI COMM WORLD


mpiComm ncomm (mpiCommWorld, grp); // establecer el formulario de comunicación MPI grp
// MUNDO COMUNICADO DE MPI
mpiComm ncomm (comm, color, clave); // MPI_Comm_split (MPI_Comm comm,
// int color, int key, MPI_Comm * ncomm)
mpiComm nicomm (procesador (local_comm, local_leader),
procesador (peer_comm, peer_leader), etiqueta);
// compilar MPI_INTERCOMM_CREATE (local_comm, local_leader, peer_comm,
// líder_remoto, etiqueta y nicomm)
mpiComm ncomm (intercomunicador, altura); // construir usando
// MPI_Intercomm_merge (intercomunicador, alto y ncomm)
mpiRequest rq; // definido un MPI_Request
mpiRequest [ int ] arq (10); // definió una matriz de 10 MPI_Request

10.4 Funciones MPI

mpiSize (comm); // devuelve el tamaño de comm (int)


mpiRank (comm); // devuelve el rango en comm (int)

procesador (i) // devolver el procesador i sin solicitud en MPI_COMM_WORLD


procesador (mpiAnySource) // devolver el procesador a cualquier fuente
// sin solicitud en MPI_COMM_WORLD
procesador (i, comm) // devolver el procesador i sin Resquest en la comunicación
procesador (comm, i) // devolver el procesador i sin Resquest en la comunicación
procesador (i, rq, comm) // devolver el procesador i con Resquest rq en com
procesador (i, rq) // devolver el procesador i con Resquest rq en
// MPI_COMM_WORLD
bloque de procesador (i) // devolver el procesador i en MPI_COMM_WORLD
// en modo bloque para comunicación sincrónica
bloque de procesador (mpiAnySource) // devolver el procesador a cualquier fuente
// en MPI_COMM_WORLD en modo bloque para comunicación sincrónica
bloque de procesador (i, comm) // devolver el procesador i en comm en modo bloque

mpiBarrier (comm); // hacer una barrera MPI en la comunicación del comunicador,


mpiWait (rq); // esperar de solicitud,
mpiWaitAll (arq); // esperar agregar de la matriz de solicitud,
mpiWtime (); // devuelve MPIWtime en segundo (real),
mpiWtick (); // devuelve MPIWTick en segundo (real),

donde un procesador es solo un rango entero, puntero a MPI_comm y puntero a MPI_Request,


y el bloque de procesador con un MPI_Request especial.

10.5 operador del comunicador MPI

https://translate.googleusercontent.com/translate_f 272/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
estado int ; (10) << a << b;
procesador // // enviar a, bpara obtener el estado
asincrónicamente MPI de enviar
al proceso 1, / recibir
procesador (10) >> a >> b; // recibir a, b sincrónicamente del proceso 10,
difusión (procesador (10, comm), a); // transmisión desde el procesador

Página 307
10.6. EJEMPLO DE SCHWARZ EN PARALELO 307

// de com a otro procesador de comunicaciones


estado = Enviar (procesador (10, comm), a); // enviar sincrónicamente
Recv}
// al proceso 10 los datos a
status = Recv (procesador (10, comm), a); // recibir sincrónicamente
// del proceso 10 los datos a;
estado = Isend (procesador (10, comm), a); // enviar asincrónicamente a
// el proceso 10, los datos a sin solicitud
estado = Isend (procesador (10, rq, comm), a); // enviar de forma asincrónica a a
// el proceso 10, los datos a con solicitud
estado = Irecv (procesador (10, rq), a); // recibir sincrónicamente de
// el proceso 10, los datos a;
status = Irecv (procesador (10), a); // Error
// Error de forma asincrónica sin solicitud.
difusión ( procesador (comm, a)); // Transmitir a todos los procesos de comunicación

donde el tipo de datos de a puede ser del tipo int, real, complex, int [int], double [int],
complex [int], int [int, int], double [int, int], complex [int, int], mesh, mesh3,
mesh [int], mesh3 [int], matrix, matrix <complejo>

procesador (10, rq) << a; // enviar de forma asincrónica al proceso 10


// los datos a con solicitud
procesador (10, rq) >> a; // recibir asincrónicamente del proceso 10
// los datos a con solicitud

Si a, b son matrices o matrices completas de int, real o compleja, podemos usar las siguientes funciones MPI:

mpiAlltoall (a, b [, comm]);


mpiAllgather (a, b [, comm]);
mpiGather (a, b, procesador (..));
mpiScatter (a, b, procesador (..));
mpiReduce (a, b, procesador (..), mpiMAX);
mpiAllReduce (a, b, comm, mpiMAX);
mpiReduceScatter (a, b, comm, mpiMAX);

Vea los ejemplos ++ - mpi / essai.edp para probar toda esta funcionalidad y gracias a Guy-Antoine
Atenekeng Kahou, por su ayuda para codificar esta interfaz.

10.6 Ejemplo de Schwarz en paralelo


Este ejemplo es una reescritura del ejemplo schwarz-superposición en la sección 9 .8.1.

[ejemplos ++ - mpi] Hecht% lamboot


LAM 6.5.9 / MPI 2 C ++ / ROMIO - Universidad de Indiana
[ejemplos ++ - mpi] hecht% mpirun -np 2 FreeFem ++ - mpi schwarz-c.edp

// una nueva versión de codificación c, método de schwarz en paralelo


// con 2 proc.
// -------------------------------
// F.Hecht diciembre de 2003
// ----------------------------------
// para probar la instrucción de transmisión
// y matriz de malla

https://translate.googleusercontent.com/translate_f 273/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 308
308 CAPÍTULO 10. VERSIÓN PARALELO MPI

// agregar agregar la prueba de parada


// ---------------------------------

if (mpisize! = 2) {
cout << "lo siento, número de procesadores! = 2" << endl;
salir (1);}
verbosidad = 3;
int interior = 2;
int exterior = 1;
borde a (t = 1,2) {x = t; y = 0; etiqueta = exterior;};
borde b (t = 0,1) {x = 2; y = t; etiqueta = exterior;};
borde c (t = 2,0) {x = t; y = 1; etiqueta = exterior;};
borde d (t = 1,0) {x = 1-t; y = t; etiqueta = interior;};
borde e (t = 0, pi / 2) {x = cos (t); y = sin (t); etiqueta = interior;};
borde e1 (t = pi / 2, 2 * pi) {x = cos (t); y = sin (t); etiqueta = exterior;};
int n = 4;
mesh [int] Th (mpisize);
si (mpirank == 0)
Th [0] = buildmesh (a (5 * n) + b (5 * n) + c (10 * n) + d (5 * n));
demás
Th [1] = buildmesh (e (5 * n) + e1 (25 * n));

difusión ( procesador (0), Th [0]);


difusión ( procesador (1), Th [1]);

fespace Vh (Th [mpirank], P1);


fespace Vhother (Th [1-mpirango], P1);

Vh u = 0, v;
Vhother U = 0;
int i = 0;

problema pb (u, v, init = i, solucionador = Cholesky) =


int2d (Th [mpirank]) (dx (u) * dx (v) + dy (u) * dy (v))
- int2d (Th [mpirank]) (v)
+ encendido (interior, u = U) + encendido (exterior, u = 0);

para (i = 0; i <20; i ++)


{
cout << mpirank << "looP" << i << endl;
pb;
// enviar u al otro proceso, recibir en U
procesador (rango de 1 mpi) << u []; procesador (rango de 1 mpi) >> U [];
err0 real , err1;
err0 = int1d (Th [mpirank], interior) (cuadrado (Uu));
// enviar err0 al otro proceso, recibir en err1
procesador (1-mpirank) << err0; procesador (rango de 1 mpi) >> err1;
err real = sqrt (err0 + err1);
cout << "err =" << err << "err0 =" << err0
<< ", err1 =" << err1 << endl;
si (err <1e-3) romper ;
};
si (mpirank == 0)
gráfico (u, U, ps = "uU.eps");

Página 309
10.6. EJEMPLO DE SCHWARZ EN PARALELO 309

https://translate.googleusercontent.com/translate_f 274/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
10.6.1 Ejemplo de Schwarz paralelo verdadero
Esta es una explicación de los dos ejemplos de script ++ - mpi / MPIGMRES [2] D.edp, un par-
alelo con una complejidad casi independiente del número de procesos (con una precondicionamiento de cuadrícula gruesa)
cionador).
Gracias a F. Nataf.

Para resolver el siguiente problema de Poisson en el dominio Ω con límite Γ en L 2 (Ω):

−∆u = f, en Ω, y u = g en Γ,
1

donde f y g son dos funciones dadas de L 2 (Ω) y de H 2 (Γ),

Introduzcamos (π i ) i = 1, .., N p una partición regular de la unidad de Ω, qed:

Np

π yo ∈ C 0 (Ω): π yo ≥ 0 y ∑ π yo = 1.
i=1

Denote Ω i el subdominio que es el soporte de la función π i y también denote Γ i el límite de


Ωi.
El método de Schwarz paralelo es Sea l = 0 el iterador y un huésped inicial u 0 respetando el límite
condición (es decir, u| Γ0 = g).

∀i = 1 .., N p : −∆u l (10,1)


i= f, en Ω i , y u l i= u l en Γ i \ Γ, u l i= g en Γ i ∩ Γ
Np
u l + 1 = ∑ i = 1 π yo uI l (10,2)

Después de la discretización con el método de elementos finitos de Lagrange, con una malla compatible T hi de Ω i , i.
e., existe una malla global T h tal que T hi se incluye en T h . Denotemos:

• V hi el espacio de elementos finitos correspondiente al dominio Ω i ,

• N hi es el conjunto del grado de libertad σ k


i,

• N Γi es el conjunto del grado de libertad de V hi en el límite Γ i de Ω i ,


Hola

•σk
i (v h ) es el valor del grado de libertad k,
Γ yo
• V 0hi = {v h ∈ V hi : ∀k ∈ N
Hola, σk yo (v h ) = 0},
• la expresión condicional a? b: c se define como en C del lenguaje C ++ por

{si a es verdadero, devuelve b


a? b: c ≡ .
si no regresa c

Observe que nunca usamos el espacio de elementos finitos asociado al dominio completo Ω porque es demasiado caro.

Tenemos que definir un operador para construir el algoritmo anterior:


Denotamos u l h | yo la restricción de u l h en V hi , por lo que el problema discreto en Ω i del problema (10 .1) es encontrar
Γ yo
u Hola
l ∈ V hi tal que: donde g k Hola.
i es el valor de g asociado al grado de libertad k ∈ N
En FreeFem ++, se puede escribir has con U es el vector correspondiente a u l h | yo y el vector
l
U1 es el vector correspondiente a u Hola es la solución de:

real [int] U1 (Ui.n);

Página 310
310 CAPÍTULO 10. VERSIÓN PARALELO MPI

real [int] b = onG. * U;


b = onG? b: Bi;
U1 = Aiˆ-1 * b;

donde onG [i] = (i ∈ Γ i \ Γ)? 1: 0, y Bi el lado derecho del problema, se definen por

fespace Whi (Thi, P2); // def del espacio de elementos finitos.

https://translate.googleusercontent.com/translate_f 275/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
varf
varf vPb (U,(U,
vPbon V)V)
= int3d (Thi)U(grad
= en (10, = 1) +(U)
en'*(1,grad
U =(V))
0); + int3d (Thi) (F * V) + en (1, U = g) + en (10, U = GRAMO);
matriz Ai = vPb (Whi, Whi, solver = sparsesolver);
real [int] onG = vPbon (0, Whi);
real [int] Bi = vPb (0, Whi);

donde la etiqueta FreeFem ++ de Γ es 1 y la etiqueta de Γ i \ Γ es 10.

Para construir la parte de transferencia / actualización correspondiente a la ecuación ( 10.2) en el proceso i, llamemos njpart
el número la vecindad del dominio de Ω i (es decir: π j no es 0 de Ω i ), lo almacenamos en una matriz jpart
de tamaño njpart todo este barrio. Introduzcamos dos arreglos de matriz, Smj [j] para definir
el vector para enviar desde i al proceso de vecindad de ja, y la matriz rMj [j] a after para reducir
con dominio del vecindario j.
Entonces, la parte de transferencia y actualización calcula v i = π i u i + ∑ j∈J πi j u j y se puede escribir FreeFem ++
función de actualización:

Func bool Update ( real [ int ] & ui, real [ int ] & vi)
{ int n = jpart.n;
for ( int j = 0; j <njpart; ++ j) Usend [j] [] = sMj [j] * ui;
mpiRequest [int] rq (n * 2);
para (int j = 0; j <n; ++ j) Irecv (procesador (jpart [j], comm, rq [j]), Ri [j] []);
para (int j = 0; j <n; ++ j) Isend (procesador (jpart [j], comm, rq [j + n]), Si [j] []);
para (int j = 0; j <n * 2; ++ j) int k = mpiWaitAny (rq);
// aplique la partición local de la unidad.
vi = Pii * ui; // establecer en π i u i
para ( int j = 0; j <njpart; ++ j) vi + = rMj [j] * Vrecv [j] []; // sumar π j u j
devuelve verdadero ; }

donde el búfer está definido por:

InitU (njpart, Whij, Thij, aThij, Usend) // definido el búfer de envío


InitU (njpart, Whij, Thij, aThij, Vrecv) // definido el búfer revc

con la siguiente definición de macro:

macro InitU (n, Vh, Th, aTh, U) Vh [int] U (n); para ( int j = 0; j <n; ++ j) {Th = aTh [j]; U [j] = 0;}
//

Primer algoritmo de gmres : puede acelerar fácilmente el algoritmo de punto fijo utilizando un GMRES paralelo
algoritmo después de la introducción el siguiente subdominio del operador afín A i Ω i .

func real [ int ] DJ0 ( real [ int ] & U) {


real [int] V (Un) , b = onG. * U;
b = onG? b: Bi;
V = Aiˆ-1 * b;
Actualizar (V, U);

Página 311
10.6. EJEMPLO DE SCHWARZ EN PARALELO 311

V - = U; return V; }

Donde el algoritmo MPIGMRES o MPICG paralelo es solo una forma simple de resolver en paralelo el
siguiendo A i x i = b i , i = 1, .., N p simplemente cambiando el producto escalar mediante la reducción del producto escalar local
de todo el proceso con el siguiente código MPI:

plantilla < clase R> R ReduceSum1 ( R s, MPI_Comm * comm)


{ R r = 0;
MPI_Allreduce (& s, & r, 1, MPI_TYPE < R > :: TYPE (), MPI_SUM, * comm);
return r; }

Esto se hace en la herramienta de biblioteca dinámica MPIGC.

Segundo algoritmo de gmres : utilice el algoritmo scharwz como preacondicionador del método básico de GMRES para
resolviendo el problema paralelo.

https://translate.googleusercontent.com/translate_f 276/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
func real [ int ] DJ (real [int] & U) // el problema original
{
++ kiter;
real [int] V (Un);
V = Ai * U;
V = onGi? 0 .: V; // eliminar término límite ...
return V;
}

func real [int] PDJ (real [int] & U) // el preacondicionador


{
real [ int ] V (Un);
real [ int ] b = onG? 0.: U;
V = Aiˆ-1 * b;
Actualizar (V, U);
return U;
}

Tercer algoritmo de gmres : agregue un solucionador grueso al algoritmo anterior


Primero construya una cuadrícula gruesa en el procesador 0, y el

matriz AC, Rci, Pci; //


si (mpiRank (comm) == 0)
AC = vPbC (VhC, VhC, solucionador = sparsesolver); // el problema de la corase

Pci = interpolar (Whi, VhC); // la proyección en cuadrícula gruesa.


Rci = Pci '* Pii; // la cuadrícula de restricción en el proceso i con la partición π i

func bool CoarseSolve ( real [ int ] & V, real [int] & U, mpiComm & comm)
{
// resolver el problema burdo
real [ int ] Uc (Rci.n), Bc (Uc.n);
Uc = Rci * U;
mpiReduce (Uc, Bc, procesador (0, comm), mpiSUM);
si (mpiRank (comm) == 0)
Uc = ACˆ-1 * Bc;
difusión (procesador (0, comm), Uc);
V = Pci * Uc;
}

Página 312
312 CAPÍTULO 10. VERSIÓN PARALELO MPI

El nuevo precondtionner

func real [int] PDJC ( real [ int ] & U) //


{ // Precon C1 = Precon //, C2 precon Grueso
// Idea: F. Nataf.
// 0 ˜ (I C1A) (I-C2A) => I ˜ - C1AC2A + C1A + C2A
// Nueva Prec P = C1 + C2 - C1AC2 = C1 (I- A C2) + C2
// (C1 (I- A C2) + C2) Uo
// V = - C2 * Uo
// ....
real [int] V (Un);
CoarseSolve (V, U, comm);
V = -V; // -C2 * Uo
U + = Ai * V; // U = (IA C2) Uo
real [ int ] b = onG? 0.: U;
U = Aiˆ-1 * b; // (C1 (I -A C2) Uo
V = U -V; //
Actualizar (V, U);
return U;
}

El código de los 4 algoritmos:

https://translate.googleusercontent.com/translate_f 277/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
epss reales = 1e-6;
int rgmres = 0;
si (gmres == 1)
{
rgmres = MPIAffineGMRES (DJ0, u [], veps = epss, nbiter = 300, comm = comm,
dimKrylov = 100, verbosidad = ipart? 0: 50);
real [int] b = onG. * u [];
b = onG? b: Bi;
v [] = Aiˆ-1 * b;
Actualizar (v [], u []);
}
más si (gmres == 2)
rgmres = MPILinearGMRES (DJ, precon = PDJ, u [], Bi, veps = epss, nbiter = 300, comm = comm
, dimKrylov = 100, verbosidad = ipart? 0: 50);
más si (gmres == 3)
rgmres = MPILinearGMRES (DJ, precon = PDJC, u [], Bi, veps = epss, nbiter = 300, comm = comm,
dimKrylov = 100, verbosidad = ipart? 0: 50);
demás // algo Shwarz para demostración ...
para ( int iter = 0; iter <10; ++ iter)
....

Tenemos todos los ingredientes para resolver en paralelo si tenemos et las particiones de la unidad. Para construir esto

partición que hacemos: el paso inicial en el proceso 1 tp construir una malla gruesa, T h del dominio completo, y
construya la constante de la función π de partición igual a i en cada subdominio O i , i = 1, .., N p , de la cuadrícula
con el particionador gráfico de Metis [?] y en cada proceso i en 1 .., N p do

1. Difusión desde el proceso 1, la malla T h (llamar a Thii en el script FreeFem ++) y la función π,

2. Observe que la función característica 1I O i del dominio O i , está definida por (π = i)? 1: 0,

Página 313
10.6. EJEMPLO DE SCHWARZ EN PARALELO 313

3. llamemos al Π 2 h el espacio de la función constante de elementos finitos por


P (resp.
∗ Π 2 V ) el L 2 en P ∗
elemento en T h (resp. V ∗ h el espacio del elemento finito continuo afín por elemento en
T h ∗ ). y construir en paralelo el π i y Ω i , tal que O i ⊂ Ω i donde O i = sup ((Π 2
V Π 2C ) m 1I O i ),
ym es un tamaño de superposición en la malla gruesa (generalmente uno),
(esto se hace en la función AddLayers (Thii, suppii [], nlayer, phii []); elegimos un
función π ∗ i= (Π 2 1 Π 20 ) m 1I O i por lo que la partición de la unidad se define simplemente por
π I∗
π yo = (10,3)
∑ Nj =p 1 π j∗

El conjunto J i de vecindad del dominio Ω i , y la versión local en V hi se pueden definir como


array jpart y njpart con:

Vhi pii = π ∗ I ; Vhi [int] pij (npij); // partición local de 1 = pii + ∑ j


pij [j]

int [ int ] jpart (npart); int njpart = 0;


Vhi sumphi = π ∗ I ;
para ( int i = 0; i < npart ; ++ i)
si (i! = ipart) {
si (int3d (Thi) (π ∗ j )> 0) {
pij [njpart] = π ∗
j;
sumphi [] + = pij [njpart] [];
jpart [njpart ++] = i;}}}
pii [] = pii [] ./ sumphi [];
para (int j = 0; j <njpart; ++ j) pij [j] [] = pij [j] [] ./ sumphi [];
jpart .resize (njpart);


4. Llamamos T h
ij la parte de submalla de T hi donde π j no son cero. y tanque a la función
trunc para construir esta matriz,

https://translate.googleusercontent.com/translate_f 278/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

para ( int jp = 0; jp <njpart; ++ jp)


aThij [jp] = trunc (Thi, pij [jp]> 1e-10, etiqueta = 10);

5. En este paso tenemos todo en la malla gruesa, por lo que podemos construir la malla fina final dividiendo
todas las mallas: Thi, Thij [j], Thij [j] con la función de malla trunc FreeFem ++ que no
restricción y deslizamiento.

6. La construcción de las matrices send / recv sMj y rMj: se puede hacer con este código:

mesh3 Thij = Thi; // mallas variables


fespace Whij (Thij, Pk); // variable fespace ..
matriz Pii; Whi wpii = pii; Pii = wpii []; // Matriz diagonal
correspondiente × π i
matriz [int] sMj (njpart), rMj (njpart); // M enviar / rendir caso.
para (int jp = 0; jp <njpart; ++ jp)
{ int j = jpart [jp];
Thij = aThij [jp]; // cambiar malla para cambiar Whij, Whij
matriz I = interpolar (Whij, Whi); // Whij <- Whi
sMj [jp] = I * Pii; // Whi -> s Whij
rMj [jp] = interpolar (Whij, Whi, t = 1); }} // Whij -> Whi

Página 314
314 CAPÍTULO 10. VERSIÓN PARALELO MPI

Para construir una aplicación que no sea mala, agregué la variable de cambio de código tout del valor del parámetro con
el siguiente código

incluir "getARGV.idp"
verbosidad = getARGV ("- vv", 0);
int vdebug = getARGV ("- d", 1);
int ksplit = getARGV ("- k", 10);
int nloc = getARGV ("- n", 25);
cadena sff = getARGV ("- p,", "");
int gmres = getARGV ("- gmres", 3);
bool dplot = getARGV ("- dp", 0);
int nC = getARGV ("- N", max (nloc / 10,4));

Y pequeño incluir para hacer gráfico en paralelo de distribuir la solución del vector u en la malla T h con
la siguiente interfaz:

incluir "MPIplot.idp"
func bool plotMPIall (mesh & Th, real [int] & u, string cm)
{PLOTMPIALL (malla, Pk, Th, u, {cmm = cm, nbiso = 20, fill = 1, dim = 3, value = 1}); return 1;}

comentar que {cmm = cm, ... = 1} en el argumento macro es una forma de citar el argumento macro, por lo que
el argumento es cmm = cm, ... = 1.

https://translate.googleusercontent.com/translate_f 279/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 315

Capítulo 11

Solucionadores dispersos paralelos

Los solucionadores dispersos en paralelo utilizan varios procesadores para resolver sistemas lineales de ecuaciones. Como secuencial,
Los solucionadores lineales paralelos pueden ser directos o iterativos. En FreeFem ++ ambos están disponibles.

11.1 Uso de solucionadores dispersos paralelos en FreeFem ++


Recordamos que los parámetros del solucionador se definen en los siguientes comandos: solve, problem,
conjunto (parámetro de ajuste de una matriz) y en la construcción de la matriz correspondiente a un
forma bilineal. En estos comandos, el solucionador de parámetros debe establecerse en sparsesolver para
solucionador disperso paralelo. Hemos agregado especificar parámetros a estas líneas de comando para paralelo.
solucionadores escasos. Estos son

• lparams: vector de parámetros enteros (l es para el tipo c ++ long)

• dparams: vector de parámetros reales

• sparams: parámetros de cadena

• datafilename: nombre del archivo que contiene los parámetros del solucionador

Los siguientes cuatro parámetros son solo para solucionadores directos y son vectores. Estos parámetros permiten
usuario para preprocesar la matriz (consulte la sección anterior sobre el solucionador directo disperso para obtener más información).

• permr: permutación de filas (vector entero)

• permc: permutación de columna o permutación de fila inversa (vector entero)

• escalador: escalamiento de filas (vector real)

• scalec: escala de columna (vector real)

Hay dos posibilidades para controlar los parámetros del solucionador. El primer método define parámetros con
lparams, dparams y sparams en archivo .edp. El segundo lee los parámetros del solucionador de un
archivo de datos. El nombre de este archivo se especifica mediante datafilename. Si lparams, dparams, sparams
o el usuario no proporciona el nombre del archivo de datos, se utiliza el valor predeterminado del solucionador.

https://translate.googleusercontent.com/translate_f 280/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Para usar el solucionador paralelo en FreeFem ++, necesitamos cargar la biblioteca dinámica correspondiente a este
solucionador. Por ejemplo, para usar el solucionador MUMPS como solucionador paralelo en FreeFem, escriba en el archivo .edp load
”MUMPS FreeFem”.
Si las bibliotecas no están cargadas, se cargará el solucionador disperso predeterminado (el solucionador disperso predeterminado es
UMFPACK). La tabla 11.1 da este nuevo valor para las diferentes bibliotecas.

315

Página 316
316 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

solucionador disperso predeterminado


Bibliotecas verdadero complejo
MUMPS FreeFem paperas paperas
real SuperLU DIST FreeFem Solucionador anterior de SuperLU DIST
complejo SuperLU DIST FreeFem solucionador anterior SuperLU DIST
pastix real FreeFem pastix solucionador anterior
pastix complejo FreeFem solucionador anterior pastix
caderas FreeFem caderas solucionador anterior
hypre FreeFem hypre solucionador anterior
parms FreeFem parms solucionador anterior

Tabla 11.1: Solucionador disperso predeterminado para aritmética real y compleja cuando cargamos un paralelo
biblioteca de solucionador disperso

También agregamos funciones (ver Tabla 11.2) sin parámetro para cambiar el solucionador disperso predeterminado en el
Archivo .edp. Para usar estas funciones, necesitamos cargar la biblioteca correspondiente al solucionador. Un ejemplo
de usar diferentes solucionadores dispersos paralelos para el mismo problema se da en testdirectsolvers.edp
(ejemplo de directorio + + −mpi).

solucionador disperso predeterminado


función verdadero complejo
defaulttoMUMPS () paperas paperas
realdefaulttoSuperLUdist () Solucionador anterior de SuperLU DIST
complexdefaulttoSuperLUdist () solucionador anterior SuperLU DIST
realdefaultopastix () pastix solucionador anterior
complexdefaulttopastix () solucionador anterior pastix
defaulttohips () caderas solucionador anterior
defaulttohypre () hypre solucionador anterior
defaulttoparms () parms solucionador anterior

Tabla 11.2: Funciones que permiten cambiar el solucionador disperso predeterminado por real y complejo
aritmética y el resultado de estas funciones

Ejemplo 11.1 (testdirectsolvers.edp)

cargar "../src/solver/MUMPS_FreeFem"
// solucionador predeterminado: real-> MUMPS, complejo -> MUMPS
cargar "../src/solver/real_SuperLU_DIST_FreeFem"
// solucionador predeterminado: real-> SuperLU DIST, complex -> MUMPS
cargar "../src/solver/real_pastix_FreeFem"
// solucionador predeterminado: real-> pastix, complex -> MUMPS

// resolviendo con pastix


{
matriz A =
[[1, 2, 2, 1, 1],
[2, 12, 0, 10, 10],
[2, 0, 1, 0, 2],
[1, 10, 0, 22, 0.],

https://translate.googleusercontent.com/translate_f 281/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 317
11.1. USO DE SOLUCIONADORES ESPAROS EN PARALELO EN FREEFEM ++ 317

[1, 10, 2, 0., 22]];

real [int] xx = [1,32,45,7,2], x (5), b (5), di (5);


b = A * xx;
cout << "b =" << b << endl;
cout << "xx =" << xx << endl;

set (A, solver = sparsesolver, datafilename = "ffpastix_iparm_dparm.txt");


cout << "solución de resolución" << endl;
x = Aˆ-1 * b;
cout << "b =" << b << endl;
cout << "x =" << endl; cout << x << endl;
di = xx-x;
si (mpirank == 0) {
cout << "x-xx =" << endl; cout << "Linf" << di.linfty << "L2" << di.l2 << endl;
}
}

// resolviendo con SuperLU DIST


realdefaulttoSuperLUdist ();
// solucionador predeterminado: real-> SuperLU DIST, complex -> MUMPS
{
matriz A =
[[1, 2, 2, 1, 1],
[2, 12, 0, 10, 10],
[2, 0, 1, 0, 2],
[1, 10, 0, 22, 0.],
[1, 10, 2, 0., 22]];

real [int] xx = [1,32,45,7,2], x (5), b (5), di (5);


b = A * xx;
cout << "b =" << b << endl;
cout << "xx =" << xx << endl;

set (A, solver = sparsesolver, datafilename = "ffsuperlu_dist_fileparam.txt");


cout << "solución de resolución" << endl;
x = Aˆ-1 * b;
cout << "b =" << b << endl;
cout << "x =" << endl; cout << x << endl;
di = xx-x;
si (mpirank == 0) {
cout << "x-xx =" << endl; cout << "Linf" << di.linfty << "L2" << di.l2 << endl;
}
}

// resolviendo con MUMPS


defaulttoMUMPS ();
// solucionador predeterminado: real-> MUMPS, complejo -> MUMPS
{
matriz A =
[[1, 2, 2, 1, 1],
[2, 12, 0, 10, 10],
[2, 0, 1, 0, 2],
[1, 10, 0, 22, 0.],
[1, 10, 2, 0., 22]];

Página 318

https://translate.googleusercontent.com/translate_f 282/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
318 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

real [int] xx = [1,32,45,7,2], x (5), b (5), di (5);


b = A * xx;
cout << "b =" << b << endl;
cout << "xx =" << xx << endl;

set (A, solver = sparsesolver, datafilename = "ffmumps_fileparam.txt");


cout << "solución de resolución" << endl;
x = Aˆ-1 * b;
cout << "b =" << b << endl;
cout << "x =" << endl; cout << x << endl;
di = xx-x;
si (mpirank == 0) {
cout << "x-xx =" << endl; cout << "Linf" << di.linfty << "L2" << di.l2 << endl;
}
}

11.2 Solucionador directo disperso


En esta sección, presentamos los escasos solucionadores directos interconectados con FreeFem ++.

11.2.1 Solucionador de MUMPS


MUltifrontal Massively Parallel Solver (MUMPS) es una biblioteca gratuita [?,?,?]. Este paquete resuelve
sistema lineal de la forma A x = b donde A es una matriz cuadrada dispersa con un método directo. La
La matriz cuadrada considerada en MUMPS puede ser asimétrica, simétrica positiva definida o
simétrico general. El método implementado en MUMPS es un método directo basado en un multifrontal
Acercarse [?]. Construye una factorización directa A = LU, A = L t DL dependiendo de la simetría
de la matriz A. MUMPS utiliza las siguientes bibliotecas: BLAS [?], BLACS y ScaLAPACK [?].

Observación 7 MUMPS no resuelve un sistema lineal con una matriz rectangular.

Instalación de MUMPS Para MUMPS usados en FreeFem ++, debe instalar MUMPS
paquete en su computadora. MUMPS está escrito en Fortran 90. La versión paralela está construida
utilizando MPI [?] para el paso de mensajes y BLAS [?,?], BLACS y ScaLAPACK [?]. Por lo tanto, un
Se necesita el compilador fortran, y MPI, BLAS, BLACS y ScaLAPACK. Un procedimiento de instalación
para obtener este paquete se da en el archivo README COMPILE en el directorio src / solver de
FreeFem ++.

Creación de la interfaz de biblioteca de MUMPS para FreeFem ++ : La interfaz de MUMPS para FreeFem ++
se da en el archivo MUMPS freefem.cpp (directorio src / solver /). Esta interfaz funciona con la versión
3.8.3 y 3.8.4 de MUMPS. Para utilizar MUMPS en FreeFem ++, necesitamos la biblioteca correspondiente
a esta interfaz. Una descripción para obtener esta biblioteca se da en el archivo README COMPILE en el
directorio src / solucionador de FreeFem ++. Recordamos aquí el procedimiento. Vaya al directorio src / solver
en el paquete FreeFem ++. Edite el archivo makefile-sparsesolver.inc en su sistema: sección de comentarios
1, línea de comentario correspondiente a las bibliotecas BLAS, BLACS, ScaLAPACK, Metis, scotch en la sección
2 y comentar en la Sección 3 el párrafo correspondiente al solucionador MUMPS. Y luego escribe make
paperas en una ventana terminal.
Ahora damos una breve descripción de los parámetros MUMPS antes de describir el método para llamar
MUMPS en FreeFem ++.

Página 319
11.2. SOLUCIONADOR DIRECTO ESPARO 319

Parámetros MUMPS: Hay cuatro parámetros de entrada en MUMPS (ver [?]). Dos enteros
SYM y PAR, un vector de número entero de tamaño 40 INCTL y un vector de real de tamaño 15 CNTL. El primero
El parámetro da el tipo de matriz: 0 para matriz asimétrica, 1 para matriz positiva simétrica
y 2 para simétrico general. El segundo parámetro definido si el procesador host funciona durante el
factorización y resuelve los pasos: PAR = 1 procesador host funcionando y PAR = 0 procesador host no
trabajando. El parámetro INCTL y CNTL es el parámetro de control de MUMPS. Los vectores
https://translate.googleusercontent.com/translate_f 283/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
ICNTL y CNTL en MUMPS se convierte con índice 1 como vector en fortran. Una breve descripción de
todos los parámetros de ICNTL y CNTL se dan en ffmumps fileparam.txt. Para obtener más detalles, consulte el
guía de usuario [?].
Describimos ahora algunos elementos de los principales parámetros de ICNTL para MUMPS.

Parámetro de la matriz de entrada La matriz de entrada se controla mediante los parámetros ICNTL (5) e IC-
NTL (18). El formato de matriz (resp. Patrón de matriz y entradas de matriz) están controlados por INCTL (5)
(resp. INCTL (18)). Los diferentes valores de ICNTL (5) son 0 para formato ensamblado y 1 para elemento
formato. En la versión actual de Freefem ++, consideramos que la matriz FE o la matriz se almacena en
formato ensamblado. Por lo tanto, INCTL (5) se trata como valor 0. La opción principal para ICNTL (18):
INCLTL (18) = 0 centralmente en el procesador host, ICNTL (18) = 3 distribuyó el patrón de matriz de entrada
y las entradas (opción recomendada para la matriz distribuida por el desarrollador de MUMPS). Por otro
valores de ICNTL (18) consulte la guía del usuario de MUMPS. Estos valores también se pueden utilizar en FreeFem ++
.
La opción predeterminada implementada en FreeFem ++ es ICNTL (5) = 0 e ICNTL (18) = 0.

Parámetro de preprocesamiento Se define la matriz preprocesada A p que se factorizará efectivamente


por
A p = PD r AQ c D c P t

donde P es la matriz de permutación, Q c es la permutación de la columna, D r y D c son la matriz diagonal


para el escalado de filas y columnas, respectivamente. La estrategia de ordenación para obtener P está controlada por parámetros
eter ICNTL (7). La permutación de cero diagonal libre Q c se controla mediante el parámetro ICNTL (6).
La escala de filas y columnas se controla mediante el parámetro ICNTL (18). Estas opciones están conectadas
y también fuertemente relacionado con ICNTL (12) (ver documentación sobre paperas para más detalles [?]). La
Los parámetros permr, scaler y scalec en FreeFem ++ permiten dar matriz de permutación (P), fila
escala (D r ) y escala de columna (D c ) del usuario respectivamente.

Llamar a MUMPS en FreeFem ++ Para llamar a MUMPS en FreeFem ++, necesitamos cargar el dy-
biblioteca namic MUMPS freefem.dylib (MacOSX), MUMPS freefem.so (Unix) o MUMPS freefem.dll
(Windows). Esto se hace escribiendo load ”MUMPS freefem” en el archivo .edp. Te damos ahora los dos
métodos para dar la opción de solucionador MUMPS en FreeFem ++.

Los parámetros del solucionador se definen en el archivo .edp: en este método, necesitamos dar los parámetros
lparams y dparams. Estos parámetros se definen para MUMPS por

lparams [0] = SYM,


lparams [1] = PAR,
∀i = 1, ..., 40, lparams [i + 1] = ICNTL (i).

∀i = 1, ..., 15, dparams [i - 1] = CNTL (i).

Página 320
320 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Lectura de los parámetros del solucionador en un archivo: La estructura del archivo de datos para MUMPS en FreeFem ++ es:
parámetro de primera línea SYM y parámetro de segunda línea PAR y en la siguiente línea el valor diferente
de los vectores ICNTL y CNTL. Un ejemplo de este archivo de parámetros se da en ffmumpsfileparam.txt.

0 / * SYM :: 0 para matriz no simétrica, 1 para simétrica definida positiva


matriz y 2 matrices simétricas generales * /
1 / * PAR :: 0 el host no funciona durante la factorización y resuelve los pasos, 1
host trabajando durante la factorización y resuelve los pasos * /
-1 / * ICNTL (1) :: flujo de salida para mensaje de error * /
-1 / * ICNTL (2) :: salida para impresión de diagnóstico, estática y mensaje de advertencia
*/
-1 / * ICNTL (3) :: para información global * /

https://translate.googleusercontent.com/translate_f 284/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
0 / * ICNTL (4) :: Nivel de impresión para mensaje de error, advertencia y diagnóstico
*/
0 / * ICNTL (5) :: formato matricial: 0 formato ensamblado, 1 formato elemental.
*/
7 / * ICNTL (6) :: opción de control para permutar y / o escalar la matriz
en fase de análisis * /
3 / * ICNTL (7) :: estrategia de orden dinámica: AMD, AMF, metis, pord scotch * /
77 / * ICNTL (8) :: Estrategia de escalado de filas y columnas * /
1 / * ICNTL (9) :: 0 resolver Ax = b, 1 resolver el sistema transpuesto Aˆt x =
b: el parámetro no se considera en la versión actual de freefem ++ * /
0 / * ICNTL (10) :: número de pasos de refinamiento iterativo * /
0 / * ICNTL (11) :: estática relacionada con el sistema lineal según ICNTL (9)
*/
1 / * ICNTL (12) :: estrategia de ordenación restringida para matriz simétrica general
*/
0 / * ICNTL (13) :: método para controlar la división de la matriz frontal de la raíz
*/
20 / * ICNTL (14) :: aumento porcentual en el espacio de trabajo estimado (predeterminado
20%) * /
0 / * ICNTL (15) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (16) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (17) :: no se utiliza en esta versión de MUMPS * /
3 / * ICNTL (18) :: método para dado: patrón de matriz y entradas de matriz
:*/
0 / * ICNTL (19) :: método para devolver la matriz de complemento de Schur * /
0 / * ICNTL (20) :: forma del lado derecho (0 forma densa, 1 forma dispersa):
el parámetro se establecerá en 0 para freefem ++ * /
0 / * ICNTL (21) :: 0, 1 solución distribuida mantenida: el parámetro no se considera
en la versión actual de freefem ++ * /
0 / * ICNTL (22) :: controla la instalación dentro / fuera del núcleo (OOC) * /
0 / * ICNTL (23) :: tamaño máximo de la memoria de trabajo en Megabyte que MUMPS
puede asignar por procesador en funcionamiento * /
0 / * ICNTL (24) :: controla la detección de pivote nulo * /
0 / * ICNTL (25) :: controla el cálculo de una base de espacio nulo * /
0 / * ICNTL (26) :: Este parámetro solo es significativo con la opción Schur
(ICNTL (19) no es cero). : el parámetro no se considera en la versión actual de freefem ++
*/
-8 / * ICNTL (27) (parámetro experimental sujeto a cambios en la próxima versión
de MUMPS): controla el factor de bloqueo para múltiples lados derechos durante el
fase de solución: el parámetro no se considera en la versión actual de freefem ++
*/

Página 321
11.2. SOLUCIONADOR DIRECTO ESPARO 321

0 / * ICNTL (28) :: no se utiliza en esta versión de MUMPS * /


0 / * ICNTL (29) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (30) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (31) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (32) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (33) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (34) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (35) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (36) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (37) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (38) :: no se utiliza en esta versión de MUMPS * /
1 / * ICNTL (39) :: no se utiliza en esta versión de MUMPS * /
0 / * ICNTL (40) :: no se utiliza en esta versión de MUMPS * /
0,01 / * CNTL (1) :: umbral relativo para pivote numérico * /
1e-8 / * CNTL (2) :: criterios de detención para el refinamiento iterativo * /
-1 / * CNTL (3) :: umbral para la detección de pivote nulo * /
-1 / * CNTL (4) :: determina el umbral para pivotamiento parcial * /
0.0 / * CNTL (5) :: fijación para pivotes nulos * /
0 / * CNTL (6) :: no se utiliza en esta versión de MUMPS * /
0 / * CNTL (7) :: no se utiliza en esta versión de MUMPS * /

https://translate.googleusercontent.com/translate_f 285/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

0 / * CNTL (8) :: no se utiliza en esta versión de MUMPS * /


0 / * CNTL (9) :: no se utiliza en esta versión de MUMPS * /
0 / * CNTL (10) :: no se utiliza en esta versión de MUMPS * /
0 / * CNTL (11) :: no se utiliza en esta versión de MUMPS * /
0 / * CNTL (12) :: no se utiliza en esta versión de MUMPS * /
0 / * CNTL (13) :: no se utiliza en esta versión de MUMPS * /
0 / * CNTL (14) :: no se utiliza en esta versión de MUMPS * /
0 / * CNTL (15) :: no se utiliza en esta versión de MUMPS * /

Si no se proporciona ningún parámetro del solucionador, usamos la opción predeterminada del solucionador MUMPS.

ejemplo Un ejemplo simple de llamar a MUMPS en FreeFem ++ con estos dos métodos se da en
el archivo testsolver MUMPS.edp en el directorio examples ++ - mpi.

11.2.2 Solucionador distribuido SuperLU


El paquete SuperLU DIST [?,?] Resuelve sistemas lineales usando factorización LU. Es un científico gratuito
biblioteca bajo licencia BSD. El sitio web de este proyecto es http://crd.lbl.gov/∼xiaoye/SuperLU. Esto
La biblioteca proporciona funciones para manejar matrices cuadradas o rectangulares en aritmética real y compleja.
El método implementado en SuperLU DIST es un método supernodal [?]. Nueva versión de este paquete
incluye una factorización simbólica paralela [?]. Esta biblioteca científica está escrita en C y MPI para
comunicaciones.

Instalación de SuperLU DIST: Para utilizar SuperLU DIST en FreeFem ++, debe instalar
Paquete SuperLU DIST. Necesitamos la biblioteca MPI y ParMetis para hacer esta compilación. Una instalación
El procedimiento de instalación para obtener este paquete se da en el archivo README COMPILE en el directorio
src / solver / del paquete FreeFem ++.

Página 322
322 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Creación de la biblioteca de la interfaz SuperLU DIST para FreeFem ++ : la interfaz FreeFem ++


a SuperLU DIST para aritmética real (o compleja) se da en el archivo
real SuperLU DIST FreeFem.cpp (resp. complejo SuperLU DIST FreeFem.cpp). Estos archivos están en
el directorio src / solver /. Estas interfaces son compatibles con la versión 3.2.1 de SuperLU DIST.
Para usar SuperLU DIST en FreeFem ++, necesitamos bibliotecas correspondientes a estas interfaces. A
La descripción para obtener estas bibliotecas se encuentra en el archivo README COMPILE en el directorio
src / solucionador de FreeFem ++. Recordamos aquí el procedimiento. Vaya al directorio src / solver en
Paquete FreeFem ++. Edite el archivo makefile-sparsesolver.inc en su sistema: sección de comentarios
1, línea de comentario correspondiente a las bibliotecas BLAS, Metis, ParMetis en la Sección 2 y comentario en
En la sección 3, el párrafo correspondiente al solucionador SuperLU DIST. Y simplemente escriba make rsludist (resp.
make csludist) en la terminal para obtener la biblioteca dinámica de la interfaz de forma real (resp. compleja)
aritmética.
Ahora damos una breve descripción de los parámetros de SuperLU DIST antes de describir el método para llamar
SuperLU DIST en FreeFem ++.

Parámetros SuperLU DIST: Describimos ahora algunos parámetros de SuperLU DIST. El Su-
La biblioteca perLU DIST utiliza un grupo de procesos lógicos 2D. Esta cuadrícula de proceso es especificada por nprow (process
fila) y npcol (columna de proceso) tal que N p = nprow npcol donde N p es el número de todos los procesos
asignado para SuperLU DIST.
Los parámetros de la matriz de entrada se controlan mediante "matriz =" en sparams para parámetros internos o en
la tercera línea del archivo de parámetros. Los diferentes valores son
matriz = ensamblado La matriz global está disponible en todos los procesos.
matriz = distribuida global la matriz global se distribuye entre todo el proceso
matriz = distribuida la matriz de entrada está distribuida (aún no implementada)
Los argumentos de opción de SuperLU DIST se describen en la sección Rutina invocable de usuarios de [?].
El parámetro Fact y TRANS se especifican en las interfaces FreeFem ++ para SuperLU DIST durante
los diferentes pasos. Por este motivo, no se considera el valor dado por el usuario para esta opción.

https://translate.googleusercontent.com/translate_f 286/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
La factorización LU se calcula en SuperLU DIST en la matriz A p .

A p = P c P r D r AD c P t C

donde P c y P r es la matriz de permutación de filas y columnas respectivamente, D r y D c son diagonales


matriz para el escalado de filas y columnas, respectivamente. El argumento de opción RowPerm (resp. ColPerm)
controlar la matriz de permutación de fila (o columna). D r y D c está controlado por el parámetro
DiagScale. El parámetro permr, permc, scaler y scalec en FreeFem ++ se proporciona para proporcionar
permutación de fila, permutación de columna, escala de fila y escala de columna del usuario respectivamente.
Los otros parámetros para la factorización de LU son ParSymFact y ReplaceTinyPivot. El paralelo
La factorización simbólica funciona sólo con la potencia de dos procesos y necesita el orden ParMetis [?].
El argumento de opción predeterminado de SuperLU DIST se proporciona en el archivo ffsuperlu dist fileparam.txt.

Llamar a SuperLU DIST en FreeFem ++ Para llamar a SuperLU DIST en FreeFem ++, necesitamos
cargar la biblioteca dinámica corresponde a la interfaz. Esto hecho por la siguiente carga de línea ”superlu real
DIST FreeFem ”(carga resp." Complex superlu DIST FreeFem ") para aritmética real (resp. Compleja)
metics en el archivo .edp.

Los parámetros del solucionador se definen en el archivo .edp: Para llamar a SuperLU DIST con el parámetro interno,
utilizó los parámetros sparams. El valor de los parámetros de SuperLU DIST en sparams está definido por

Página 323
11.2. SOLUCIONADOR DIRECTO ESPARO 323

sparams = ”nprow = 1, npcol = 1, matrix = distribuidogloba, Fact = DOFACT, Equil = NO,


ParSymbFact = NO, ColPerm = MMD EN MÁS A, RowPerm = LargeDiag,
DiagPivotThresh = 1.0, IterRefine = DOBLE, Trans = NOTRANS,
ReplaceTinyPivot = NO, SolveInitialized = NO, PrintStat = NO, DiagScale = NOEQUIL ”
Este valor corresponde al parámetro del archivo ffsuperlu dist fileparam.txt. Si un parámetro es
no especificado por el usuario, tomamos el valor predeterminado de SuperLU DIST.

Lectura de los parámetros del solucionador en un archivo: la estructura del archivo de datos para SuperLU DIST en FreeFem ++
se proporciona en el archivo ffsuperlu dist fileparam.txt (valor predeterminado de la interfaz FreeFem ++).

1 / * nprow: valor entero */


1 / * npcol: valor entero */
distribuido global / * entrada de matriz: ensamblada, distribuida global, distribuida
*/
DOFACT / * Hecho: DOFACT, SamePattern, SamePattern_SameRowPerm,
FACTORADO * /
NO / * Equil: NO, SI * /
NO / * ParSymbFact: NO, SÍ * /
MMD_AT_PLUS_A / * ColPerm: NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A, PARMETIS,
MY_PERMC * /
LargeDiag / * RowPerm: NOROWPERM, LargeDiag, MY_PERMR * /
1.0 / * DiagPivotThresh: valor real * /
DOBLE / * IterRefine: NOREFINE, SINGLE, DOBLE, EXTRA * /
NOTRANOS / * Trans : NOTRANS, TRANS, CONJ * /
NO / * ReemplazarTinyPivot: NO, SÍ * /
NO / * SolveInitialized: NO, SÍ * /
NO / * RefineInitialized: NO, SÍ * /
NO / * PrintStat: NO, SÍ * /
NOEQUIL / * DiagScale: NOEQUIL, FILA, COL, AMBOS * /

Si no se proporciona ningún parámetro de solucionador, usamos la opción predeterminada del solucionador SuperLU DIST.

Ejemplo 11.2 Un ejemplo simple de llamar a SuperLU DIST en FreeFem ++ con estos dos métodos

https://translate.googleusercontent.com/translate_f 287/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
se da en el archivo testsolver superLU DIST.edp en el directorio examples ++ - mpi.

11.2.3 Solucionador de Pastix


Pastix (paquete de matriz Parallel Sparse) es una biblioteca científica gratuita bajo licencia CECILL-C. Esto
El paquete resuelve un sistema lineal disperso con métodos iterativos de ILU (k) directos y en bloque. Este solucionador
se puede aplicar a una matriz real o compleja con un patrón simétrico [?].

Instalación de Pastix: para utilizar Pastix en FreeFem ++, debe instalar el paquete pastix en
primero. Para compilar este paquete, necesitamos un compilador de fortran 90, un pedido de scotch [?] O Metis [?]
biblioteca y MPI. Un procedimiento de instalación para obtener este paquete se da en el archivo .src / solver /
README COMPILE en la sección pastix del paquete FreeFem ++.

Página 324
324 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Creación de una biblioteca de interfaz pastix para FreeFem ++ : la interfaz FreeFem ++ para pastix
se da en el archivo real pastix FreeFem.cpp (resp. complex pastix FreeFem.cpp) para real (resp.complex)
aritmética. Esta interfaz es compatible con la versión 2200 de pastix y está diseñada para un
matriz global. También hemos implementado interfaz para matrices distribuidas. Para usar pastix en
FreeFem ++, necesitamos la biblioteca correspondiente a esta interfaz. Una descripción para obtener este
La biblioteca se encuentra en el archivo README COMPILE en el directorio src / solver de FreeFem ++. Nosotros
recuerde aquí el procedimiento. Vaya al directorio src / solver en el paquete FreeFem ++. Edita el archivo
makefile-sparsesolver.inc a su sistema: sección de comentario 1, línea de comentario correspondiente a
bibliotecas BLAS, METIS y SCOTCH en la Sección 2 y comentar en la Sección 3 el párrafo
correspondiente al solucionador de pastix. Y simplemente escriba make rpastix (resp. Make cpastix) en la terminal
para obtener la biblioteca dinámica de interfaz para aritmética real (o compleja).
Ahora damos una breve descripción de los parámetros de pastix antes de describir el método para llamar a pastix
en FreeFem ++.

Parámetros de Pastix: El parámetro de matriz de entrada de FreeFem ++ depende de la interfaz pastix.


matriz = ensamblada para matriz no distribuida. Es el mismo parámetro para SuperLU DIST. Allí
Hay cuatro parámetros en Pastix: iparm, dparm, perm e invp. Estos parámetros son respectivamente
los parámetros enteros (vector de tamaño 64), parámetros reales (vector de tamaño 64), matriz de permutación
y matriz de permutación inversa respectivamente. los vectores iparm y dparm se describen en [?]. La
Los parámetros permr y permc en FreeFem ++ se proporcionan para dar una matriz de permutación y una
matriz de permutación del usuario respectivamente.

Parámetros del solucionador definidos en el archivo .edp: Para llamar a Pastix en FreeFem ++ en este caso, necesitamos
especifique los parámetros lparams y dparams. Estos parámetros están definidos por

∀i = 0, ..., 63, lparams [i] = iparm [i].

∀i = 0, ..., 63, dparams [i] = dparm [i].

Leer los parámetros del solucionador en un archivo: la estructura del archivo de datos para los parámetros de pastix en
FreeFem ++ es: parámetros de estructura de primera línea de la matriz y en la línea siguiente el valor de
vectores iparm y dparm en este orden.

ensamblado / * entrada de matriz :: ensamblado, distribuido global y distribuido * /


iparm [0]
iparm [1]
...
...
iparm [63]

https://translate.googleusercontent.com/translate_f 288/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
dparm [0]
dparm [1]
...
...
dparm [63]

Un ejemplo de este parámetro de archivo se da en ffpastix iparm dparm.txt con una descripción de estos
parámetros. Este archivo se obtiene con el archivo de ejemplo iparm.txt y dparm.txt incluido en el

Página 325
11.3. SOLUCIONADOR ITERATIVO ESPARO PARALELO 325

matriz cuadrada matriz rectangular


solucionador directo sym patrón sym unsym sym patrón sym unsym
SuperLU DIST sí sí sí sí sí sí
PAPERAS sí sí sí No No No
pastix sí sí No No No No

Tabla 11.3: Tipo de matriz utilizada por los diferentes solucionadores dispersos directos

paquete pastix.

Si no se proporciona ningún parámetro de solucionador, usamos la opción predeterminada de pastix solver.

Ejemplo: Un ejemplo simple de llamar a pastix en FreeFem ++ con estos dos métodos se da en
el archivo testsolver pastix.edp en el directorio examples ++ - mpi.

En la tabla 11.3, recordamos las diferentes matrices consideradas en los diferentes solucionadores directos.

11.3 Solucionador iterativo disperso paralelo


En cuanto a los solucionadores iterativos, hemos elegido pARMS [?], HIPS [?] Y Hypre [?]. Cada software
implementa un tipo diferente de preacondicionador paralelo. Entonces, pARMS implementa dominio algebraico
tipo de preacondicionador de descomposición como el aditivo Schwartz [?] y el método de interfaz [?]; tiempo
HIPS implementa factorización incompleta jerárquica [?] Y finalmente HYPRE implementa multinivel
los preacondicionadores son AMG (Algebraic MultiGrid) [?] y paralelo aproximado inverso [?].

Para utilizar uno de estos programas en FreeFem ++, debe instalarlo independientemente de FreeFem ++
. También es necesario instalar la biblioteca de comunicación MPI que es esencial para la comunicación.
entre los procesadores y, en algunos casos, gráficos de partición de software como METIS [?] o Scotch
[?].
Todos estos preacondicionadores se utilizan con aceleradores de métodos subespaciales de Krylov. Subespacio de Krylov
Los métodos son métodos iterativos que consisten en encontrar una solución x del sistema lineal Ax = b dentro
el espacio afín x 0 + K m imponiendo que b − Ax⊥L m , donde K m es el subespacio de dimensión de Krylov
m definido por K m = {r 0 , Ar 0 , A 2 r 0 , ..., A m − 1 r 0 } y L m es otro subespacio de dimensión m que
depende del tipo de subespacio de Krylov. Por ejemplo, en GMRES, L m = AK m .

Realizamos una interfaz que es fácil de usar, de modo que la llamada de estos diferentes softwares en
FreeFem ++ se realiza de la misma manera. Solo tiene que cargar el solucionador y luego especificar el
parámetros para aplicar a los solucionadores específicos. En el resto de este capítulo, cuando hablamos de Krylov
métodos subespaciales nos referimos a uno entre GMRES, CG y BICGSTAB.

11.3.1 solucionador de pARMS


pARMS (Solver multinivel algebraico paralelo) es un software desarrollado por Youssef Saad y al.
en la Universidad de Minnesota [?]. Este software está especializado en la resolución de grandes dispersos no
sistemas de ecuaciones lineales simétricos. Los solucionadores desarrollados en pARMS son el tipo de subespacio de Krylov. Eso
consta de variantes de GMRES como FGMRES (GMRES flexible), DGMRES (GMRES desinflado) [?]
y BICGSTAB. pARMS también implementa un preacondicionador paralelo como RAS (aditivo restringido
Schwarz) [?] Y preacondicionador tipo complemento Schur [?].

https://translate.googleusercontent.com/translate_f 289/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 326
326 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Todos estos preacondicionadores paralelos se basan en el principio de descomposición de dominios. Por lo tanto, la
la matriz A se divide en submatrices A i (i = 1, ..., p) donde p representa el número de particiones
uno necesita. La unión de A i forma la matriz original. Se obtiene la solución del sistema global
resolviendo los sistemas locales en A i (ver [?]). Por lo tanto, se hace una distinción entre iteraciones en A
y las iteraciones locales en A i . Para resolver el problema local en A i hay varios preacondicionadores como
ilut (LU incompleto con umbral), iluk (LU incompleto con nivel de relleno) y ARMS (Algebraico
Solucionador recursivo multinivel). Pero para usar pAMRS en FreeFem ++, primero debe instalar pAMRS.

Instalación de pARMS Para instalar pARMS, primero debe descargar el paquete pARMS en
[?]. Una vez que se completa la descarga, debe descomprimir el paquete pARMS y seguir la instalación
procedimiento descrito en el archivo README para crear la biblioteca libparms.a.

Uso de pARMS como interfaz para FreeFem ++ Antes de llamar al solucionador de pARMS dentro de FreeFem ++
, debe compilar el archivo parms FreeFem.cpp para crear una biblioteca dinámica parms FreeFem.so. A
Haga esto, vaya al directorio src / solver de FreeFem ++, edite el archivo makefileparms.inc para
especificar las siguientes variables:

DIR PARMS: Directorio de pARMS


LAS PARMAS INCLUYEN: Directorio para encabezado de pARMS
METIS: Directorio METIS
METIS LIB: Biblioteca METIS
MPI: Directorio MPI
MPI INCLUYE: Encabezados MPI
FREEFEM: Directorio FreeFem ++
FREEFEM INCLUYE: encabezado FreeFem ++ para un solucionador lineal disperso
LIBBLAS: Biblioteca Blas
Después de eso, en la línea de comando escriba make parms para crear parms FreeFem.so.
Como es habitual en FreeFem ++, mostraremos con ejemplos cómo llamar a pARMS en FreeFem ++. Allí
hay tres formas de hacer esto:

Ejemplo 1: Parámetros predeterminados Este ejemplo proviene de la guía del usuario de FreeFem ++ [?] En
pagina 12.

Ejemplo 11.3

1: cargar parms_freefem // Dígale a FreeFem que usará pARMS


2: borde C (t = 0,2 * pi ) { x = cos (t); y = sin (t); etiqueta = 1;}
3: malla Th = buildmesh (C (50));
4: espacio libre Vh (Th, P2 );
5: Vh u, v;
6: función f = x * y;
7: problema de Poisson (u, v, solver = sparsesolver) = // la parte bilineal usará
8: int2d (Th) ( dx (u) * dx (v) + dy (u) * dy (v)) // un solucionador escaso, en este
PARMAS DE CASO
9: - int2d (Th) (f * v) // lado derecho
10: + en (1, u = 0); // Condición de frontera de Dirichlet
11:
12: CPU real = reloj ();
13: Poisson; // RESUELVE EL PDE
14: trama (u);
15: cout << "tiempo de CPU =" << reloj () - cpu << endl ;

https://translate.googleusercontent.com/translate_f 290/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 327
11.3. SOLUCIONADOR ITERATIVO ESPARO PARALELO 327

En la línea 1 del ejemplo 11 .3 cargamos en memoria la librería dinámica pARMS con interfaz FreeFem ++
. Después de esto, en la línea 7 especificamos que la forma bilineal será resuelta por el último solucionador lineal disperso
cargar en la memoria que, en este caso, es pARMS.
El parámetro utilizado en pARMS en este caso es el predeterminado ya que el usuario no tiene que
proporcionar cualquier parámetro.
A continuación, se muestran algunos parámetros predeterminados:
solucionador = FGMRES, dimensión de Krylov = 30, máximo de Krylov = 1000, tolerancia para la convergencia = 1e−
08. (ver el libro de Saad [?] Para comprender todos estos parámetros).
precondicionador = Additif Schwarz restringido [?], Dimensión interior de Krylov = 5, Máximo de interior
Dimensión de Krylov = 5, preacondicionador interno = ILUK.

Para especificar los parámetros que se aplicarán al solucionador, el usuario puede dar un vector entero para
parámetros enteros y vectores reales para parámetros reales o proporcionar un archivo que contenga esos
parámetros.

Ejemplo 2: el usuario especifica parámetros dentro de dos vectores Consideremos Navier Stokes
ejemplo 11 .4 . En este ejemplo resolvemos sistemas lineales provenientes de la discretización de Navier Stokes
ecuación con pARMS. Los parámetros del solucionador los especifica el usuario.

El ejemplo 11.4 (Stokes.edp) incluye "manual.edp"


incluir "incluye.edp";
incluir "mesh_with_cylinder.edp";
incluir "bc_poiseuille_in_square.edp";
incluir "fe_functions.edp";
0: cargar parms_FreeFem
1: int [int] iparm (16); real [int] dparm (6);
2: int , ii;
3: para (ii = 0; ii <16; ii ++) {iparm [ii] = - 1;} para (ii = 0; ii <6; ii ++) dparm [ii] = - 1,0;
4: espacio libre Vh (Th, [P2, P2, P1]);
5: iparm [0] = 0;
6: varf Stokes ([u, v, p], [ush, vsh, psh], { solver = sparsesolver}) =
int2d (Th) (nu * (dx (u) * dx (ush) + dy (u) * dy (ush) + dx (v) * dx (vsh) + dy (v) * dy (vsh))
- p * psh * (1.e-6) // p épsilon
- p * (dx (ush) + dy (vsh)) // + dx (p) * ush + dy (p) * vsh
- (dx (u) + dy (v)) * psh // psh div (u)
)
+ encendido (cilindro, infwall, supwall, u = 0., v = 0.) + encendido (entrada, u = uc, v = 0); // Bdy
condiciones
7: matriz AA = Stokes (VVh, VVh);
8: set (AA, solver = sparsesolver, lparams = iparm, dparams = dparm); // Establecer pARMS como
solucionador lineal
9: real [int] bb = Stokes (0, VVh); real [int] sol (AA.n);
10: sol = AAˆ-1 * bb;

Necesitamos dos vectores para especificar los parámetros del solucionador lineal. En la línea 1 del ejemplo 11.4 ,
han declarado estos vectores (int [int] iparm (16); real [int] dparm (6);). En la línea 3 hemos inicializado
estos vectores por valores negativos. Hacemos esto porque todos los valores de los parámetros en pARMS son positivos
y si no cambia los valores negativos de una entrada de este vector, el valor predeterminado será
colocar. En las tablas (tablas 11.4 y 11.5), tenemos el significado de las diferentes entradas de estos vectores.
Ejecutamos el ejemplo 11 .4 en el grupo paradent de Grid5000 e informamos los resultados en la tabla 11.8.

Página 328
328 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Entradas de iparm Significados de cada entrada


Métodos subespaciales de Krylov.
iparm [0]
Los valores diferentes para estos parámetros se especifican en la tabla 11.6
Preacondicionador.
https://translate.googleusercontent.com/translate_f 291/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
iparm [1] Los diferentes preacondicionadores para estos parámetros se especifican en la tabla 11.7.
iparm [2] Dimensión subespacial de Krylov en iteración externa: valor predeterminado 30
iparm [3] Máximo de iteraciones en iteración externa: valor predeterminado 1000
iparm [4] Número de nivel en brazos cuando se usa.
iparm [5] Dimensión del subespacio de Krylov en iteración interna: valor predeterminado 3
iparm [6] Máximo de iteraciones en iteración interna: valor predeterminado 3
Simétrica (= 1 para simétrica) o matriz asimétrica:
iparm [7]
valor predeterminado 0 (matriz asimétrica)
iparm [8] Tamaño de superposición entre diferentes subdominios: valor predeterminado 0 (sin superposición)
iparm [9] Escale la matriz de entrada o no: valor predeterminado 1 (la matriz debe ser escala)
iparm [10] Tamaño de bloque en brazos cuando se usa: valor predeterminado 20
iparm [11] lfil0 (ilut, iluk y arms): valor predeterminado 20
iparm [12] lfil para la constante de complemento de Schur: valor predeterminado 20
iparm [13] lfil para la constante de complemento de Schur: valor predeterminado 20
iparm [14] Multicolor o no en ILU cuando se usa: valor predeterminado 1
iparm [15] Iteración interna: valor predeterminado 0
Imprimir mensaje al resolver: predeterminado 0 (sin impresión de mensaje).
iparm [16] 0: no se imprime ningún mensaje,
1: Información de convergencia como número de iteraciones y residuales,
2: sincronización para un paso diferente como preacondicionador
3: Imprime toda la información.

Tabla 11.4: Significado de las variables correspondientes de lparams por ejemplo 11.4

Entradas de dparm Significados de cada entrada


dparm [0] precisión para iteración externa: valor predeterminado 1e-08
dparm [1] precisión para iteración interna: valor predeterminado 1e-2
dparm [2] tolerancia utilizada para el dominio diagonal:: valor predeterminado 0.1
dparm [3] tolerancia a la caída droptol0 (ilut, iluk y arms): valor predeterminado 1e-2
dparm [4] droptol para el complemento de Schur constante: valor predeterminado 1e-2
dparm [5] droptol para el complemento de Schur constante: valor predeterminado 1e-2

Tabla 11.5: Significados de las variables correspondientes de dparams, por ejemplo 11.4

Valores de iparm [0] métodos subespaciales de Krylov


0 FGMRES (GMRES flexible)
1 DGMRES (GMRES desinflado)
2 BICGSTAB

Tabla 11.6: Krylov Solvers en pARMS

Página 329
11.3. SOLUCIONADOR ITERATIVO ESPARO PARALELO 329

Valores de iparm [1] Preacondicionadores


El tipo de preacondicionadores es
0
preacondicionador de Schwartz aditivo con ilu0 como preacondicionador local,
el tipo de preacondicionador es
1
preacondicionador Schwartz aditivo con iluk como preacondicionador local,
el tipo de preacondicionador es
2
preacondicionador Schwartz aditivo con ilut como preacondicionador local,
el tipo de preacondicionador es
3
preacondicionador Schwartz aditivo con brazos como preacondicionador local,

https://translate.googleusercontent.com/translate_f 292/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
4 el tipo de preacondicionador es
Preacondicionador del complemento Schur izquierdo con ilu0 como preacondicionador local,
el tipo de preacondicionador es
5
Preacondicionador del complemento Schur izquierdo con ilut como preacondicionador local,
el tipo de preacondicionador es
6
Preacondicionador del complemento Schur izquierdo con iluk como preacondicionador local,
el tipo de preacondicionador es
7
Preacondicionador del complemento Schur izquierdo con brazos como preacondicionador local,
el tipo de preacondicionador es
8
Preacondicionador de complemento Schur derecho con ilu0 como preacondicionador local,
el tipo de preacondicionador es
9
Preacondicionador de complemento Schur derecho con ilut como preacondicionador local,
el tipo de preacondicionador es
10
Preacondicionador de complemento Schur derecho con iluk como preacondicionador local,
el tipo de preacondicionador es
11
Preacondicionador de complemento Schur derecho con brazos como preacondicionador local,
el tipo de preacondicionador es
12
sch gilu0, preacondicionador de complemento Schur con ilu0 global
el tipo de preacondicionador es
13
Preacondicionador SchurSymmetric GS

Tabla 11.7: Preacondicionadores en pARMS

n = 471281 nnz = 13 × 10 6 Te = 571,29


notario público
añadir (iluk) schur (iluk)
liendre hora liendre hora
4 230 637,57 21 557,8
8 240 364.12 22 302.25
dieciséis247 212.07 24 167,5
32 261 111.16 25 81,5

Tabla 11.8: Convergencia y tiempo para resolver el sistema lineal del ejemplo 11.4

Página 330
330 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

norte tamaño de la matriz


nnz número de entradas no nulas dentro de la matriz
liendre número de iteraciones para la convergencia
tiempo Tiempo de convergencia
Te Es hora de construir una matriz de elementos finitos.
notario público
número de procesador

Tabla 11.9: Leyenda de la tabla 11.8

En este ejemplo, arreglamos el tamaño de la matriz (en términos de elemento finito, arreglamos la malla) y aumentamos el
número de procesadores utilizados para resolver el sistema lineal. Vimos eso, cuando el número de procesadores
aumenta, el tiempo para resolver la ecuación lineal disminuye, incluso si aumenta el número de iteraciones.
Esto prueba que, utilizando pARMS como solucionador de sistemas lineales provenientes de la discretización de parciales
La ecuación diferencial en FreeFem ++ puede reducir drásticamente el tiempo total de simulación.

11.3.2 Interfaz con HIPS

https://translate.googleusercontent.com/translate_f 293/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
HIPS (Hierarchical Iterative Parallel Solver) es una biblioteca científica que proporciona un sistema paralelo eficiente.
solucionador iterativo para sistemas lineales dispersos muy grandes. HIPS está disponible como software gratuito en la
Licencia CeCILL-C. La interfaz que nos dimos cuenta es compatible con la versión 1.2 beta.rc4 de HIPS.
HIPS implementa dos clases de solucionador que son la clase iterativa (GMRES, PCG) y la Di-
clase rect. En cuanto a los preacondicionadores, HIPS implementa un tipo de ILU multinivel. Para más
Para obtener información sobre esos preacondicionadores, consulte [?,?].

Instalación de HIPS Para instalar HIPS, primero descargue el paquete HIPS en [?], Descomprímalo y
vaya al directorio de origen de HIPS. La instalación de HIPS depende de la máquina. Por ejemplo,
para instalar HIPS en un clúster de Linux, copie el archivo Makefile Inc Examples / makefile.inc.gnu en el
directorio raíz de HIPS con el nombre makefile.inc. Después de esto, edite makefile.inc para establecer valores de
diferentes variables y tipos hacen todos.

Uso de HIPS como interfaz para FreeFem ++ Antes de llamar al solucionador de HIPS dentro de FreeFem ++
, debe compilar el archivo hips FreeFem.cpp para crear la biblioteca dinámica hips FreeFem.so. Para hacer esto,
muévase al directorio src / solver de FreeFem ++ y edite el archivo makefile.inc para especificar lo siguiente
bajando variables:

DIR DE CADERAS: Directorio de HIPS


LAS CADERAS INCLUYEN: -I $ (HIPS DIR) / SRC / INCLUDE: Directorio para encabezados HIPS
DIR LIB: -L $ (HIPS DIR) / LIB: directorio de Librairies
LIBHIPSSEQUENTIAL: $ (HIPS DIR) /LIB/libhipssequential.a: biblioteca de utilidades HIPS
LIBHIPS: $ (HIPS DIR) /LIB/libhips. A: biblioteca HIPS
FREEFEM: Directorio FreeFem ++
FREEFEM INCLUYE: Encabezados FreeFem para un solucionador lineal disperso
METIS: Directorio METIS
METIS LIB: Biblioteca METIS
MPI: Directorio MPI
MPI INCLUYE: Encabezados MPI
Después de especificar todas las variables, en la línea de comando en el directorio src / solver escriba make hips to
crear caderas FreeFem.so.

Página 331
11.3. SOLUCIONADOR ITERATIVO ESPARO PARALELO 331

Al igual que con pARMS, la llamada de HIPS en FreeFem ++ se puede realizar de tres formas diferentes. Nosotros
presentará solo un ejemplo donde el usuario especifica los parámetros a través de palabras clave lparams
y dparams.

Laplacian 3D resolver con HIPS Consideremos el ejemplo 3D Laplacian dentro de FreeFem ++


paquete donde después de la discretización queremos resolver la ecuación lineal con Hips. El ejemplo 11.5 es
Laplacian3D usando Hips como solucionador lineal. Primero cargamos el solucionador de Hips en la línea 2. De la línea 4 a la 15,
especificar los parámetros para el solucionador de caderas y en la línea 46 del ejemplo 11.5 establecemos estos parámetros
en el solucionador lineal.
En la Tabla 11.10 se informan los resultados de la ejecución del ejemplo 11.5 en Cluster Paradent de Grid5000. Nosotros
puede ver en este ejemplo en ejecución la eficiencia del paralelismo.

Ejemplo 11.5 (Laplacian3D.edp) 1: cargar "msh3"


2: carga "hips_FreeFem" // cargar biblioteca
3: int nn = 10, iii;
4: int [int] iparm (14);
5: real [int] dparm (6);
6: para (iii = 0; iii <14; iii ++) iparm [iii] = - 1;
7: para (iii = 0; iii <6; iii ++) dparm [iii] = - 1;
8: iparm [0] = 0; // usar solucionador iterativo
9: iparm [1] = 1; // PCG como método de Krylov
10: iparm [4] = 0; // La matriz es simétrica
11: iparm [5] = 1; // Los patrones también son simétricos
12: iparm [9] = 1; // Matriz de escala
13: dparm [0] = 1e-13; // Tolerancia a la convergencia
14: dparm [1] = 5e-4; // Umbral en ILUT
15: dparm [2] = 5e-4; // Umbral para preacondicionador Schur

https://translate.googleusercontent.com/translate_f 294/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
16: malla Th2 = cuadrado (nn, nn);
17: espacio libre Vh2 (Th2, P2);
18: Vh2 ux, uz, p2;
19: int [int] rup = [0,2], rdown = [0,1], rmid = [1,1,2,1,3,1,4,1];
20: zmin real = 0, zmax = 1;
21: mesh3 Th = capas de construcción (Th2, nn,
zbound = [zmin, zmax],
reffacemid = rmid,
reffaceup = rup,
reffacelow = rdown);
22: savemesh (Th, "copie.mesh");
23: mesh3 Th3 ("copie.mesh");
24: espacio libre Vh (Th, P2);
25: func ue = 2 * x * x + 3 * y * y + 4 * z * z + 5 * x * y + 6 * x * z + 1;
26: func uex = 4 * x + 5 * y + 6 * z;
27: func uey = 6 * y + 5 * x;
28: func uez = 8 * z + 6 * x;
29: función f = -18. ;
30: Vh uhe = ue; //
31: cout << "uhe min:" << uhe []. Min << "max:" << uhe []. Max << endl;
32: Vh u, v;
33: macro Grad3 (u) [dx (u), dy (u), dz (u)] // MOE
34: varf va (u, v) = int3d (Th) (Grad3 (v) '* Grad3 (u)) // ') para emacs
+ int2d (Jue, 2) (u * v)
- int3d (Th) (f * v)
- int2d (Jue, 2) (ue * v + (uex * Nx + uey * Ny + uez * Nz) * v)
+ en (1, u = ue);

Página 332
332 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

n = 4 × 10 6 nnz = 118 × 10 6 Te = 221,34


notario público liendre hora
8 190 120,34
dieciséis 189 61.08
32 186 31,70
64 183 23.44

Tabla 11.10: Iteraciones y tiempos de resolución del sistema lineal del ejemplo 11.5

35: CPU real = reloj ();


36: matriz Aa;
37: Aa = va (Vh, Vh);
38: varf l (sin usar, v) = int3d (Th) (f * v);
39: Vh F; F [] = va (0, Vh);
40: if (mpirank == 0) {
cout << "Taille" << Aa.n << endl;
cout << "No ceros" << Aa.nbcoef << endl;
}
41: si (mpirank == 0)
42: cout << "TIEMPO DE CPU PARA FORMAR MATRIZ =" << reloj () - cpu << endl;
43: set (Aa, solver = sparsesolver, dparams = dparm, lparams = iparm); // Establecer caderas
como solucionador lineal
44: u [] = Aaˆ-1 * F [];

La leyenda de la tabla 11 .10 se da en la tabla 11.9.

11.3.3 Interfaz con HYPRE


HYPRE (preacondicionador de alto nivel) es un conjunto de preacondicionadores en paralelo desarrollado en Lawrence
Laboratorio Nacional de Livermore [?].
Hay dos clases principales de preacondicionadores desarrollados en HYPRE: AMG (Algebraic MultiGrid)
y Parasails (Paralelo Escaso Aproximado Inverso).

https://translate.googleusercontent.com/translate_f 295/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Ahora, suponga que queremos resolver Ax = b. En el corazón de AMG hay una serie de progresivamente
representaciones más gruesas (más pequeñas) de la matriz A. Dada una aproximación x a la solución x,
considere resolver la ecuación residual Ae = r para encontrar el error e, donde r = b − Ax. Un fundamental
El principio de AMG es que es un error algebraicamente suave. Para reducir la suavidad algebraica
Además de los errores, deben representarse mediante una ecuación de defecto más pequeña (rejilla gruesa residual
ecuación) A c e c = r c , que es más barata de resolver. Después de resolver esta ecuación burda, la solución es
luego interpolado en una cuadrícula fina representada aquí por la matriz A. La calidad de AMG depende de la
elección de operadores de engrosamiento e interpolación.
La inversa aproximada dispersa se aproxima a la inversa de una matriz A por una matriz dispersa M.
Una idea técnica para construir la matriz M es minimizar la norma de Frobenuis de la matriz residual
Yo - MA. Para obtener más detalles sobre las técnicas de este preacondicionador, consulte [?].
HYPRE implementa tres solucionadores subespaciales de Krylov: GMRES, PCG y BiCGStab.

Instalación de HYPRE Para instalar HYPRE, primero descargue el paquete HYPRE en [?], Descomprima
y vaya al directorio fuente de HYPRE / src y haga ./configure para configurar Hypre. Después de este
simplemente escriba make all para crear libHYPRE.a.

Página 333
11.3. SOLUCIONADOR ITERATIVO ESPARO PARALELO 333

Entradas de iparm Significados de cada entrada


Uso de estrategia para resolver
iparm [0]
(Iterativo = 0 o Híbrido = 1 o Directo = 2). Los valores predeterminados son: iterativos
Métodos de Krylov.
iparm [1]
Si iparm [0] = 0, indique el tipo de métodos de Krylov: 0 para GMRES, 1 para PCG
iparm [2] Máximo de iteraciones en iteración externa: valor predeterminado 1000
iparm [3] Dimensión subespacial de Krylov en iteración externa: valor predeterminado 40
Simétrico (= 0 para simétrico) y 1 para matriz asimétrica:
iparm [4]
valor predeterminado 1 (matriz asimétrica)
iparm [5] El patrón de la matriz es simétrico o no: valor predeterminado 0
iparm [6] Tipo de partición de la matriz de entrada: valor predeterminado 0
Número de nivel que usa el relleno localmente consistente de HIPS:
iparm [7]
Valor predeterminado 2
La numeración en la matriz de índices comenzará en 0 o 1:
iparm [8]
Valor predeterminado 0
iparm [9] Matriz de escala. Valor predeterminado 1
Reordenar el uso dentro de los subdominios para reducir el relleno:
iparm [10]
Úselo solo para iterativo. Valor predeterminado 1
Número de incógnitas por nodo en el gráfico de patrón de matriz distinto de cero:
iparm [11]
Valor predeterminado 1
Este valor se utiliza para establecer el número de veces que
iparm [12]
La normalización se aplica a la matriz: Predeterminado 2.
iparm [13] Nivel de información impresa durante la resolución: Predeterminado 5.
iparm [14] HIPS DOMSIZE Tamaño del subdominio

Tabla 11.11: Significados de lparams correspondientes a la interfaz HIPS

dparm [0] HIPS PREC: Norma residual relativa: Predeterminado = 1e-9


dparm [1] HIPS DROPTOL0: umbral numérico en ILUT para dominio interior
(importante: establecer 0.0 en HÍBRIDO: Predeterminado = 0.005)
HIPS DROPTOL1: Umbral numérico en ILUT para
dparm [2]
Preacondicionador Schur: Predeterminado = 0,005
dparm [3] HIPS DROPTOLE: umbral numérico para el acoplamiento entre el
nivel interior y Schur: Por defecto 0.005

https://translate.googleusercontent.com/translate_f 296/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
dparm [4] HIPS AMALG: Umbral numérico para el acoplamiento entre el
nivel interior y Schur: Predeterminado = 0.005
dparm [5] HIPS DROPSCHUR: Umbral numérico para el acoplamiento entre el
nivel interior y Schur: Predeterminado = 0.005

Tabla 11.12: Significados de dparams correspondientes a la interfaz HIPS

Página 334
334 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Usando HYPRE como interfaz para FreeFem ++ Antes de llamar al solucionador HYPRE dentro de FreeFem ++
, debe compilar el archivo hypre FreeFem.cpp para crear la biblioteca dinámica hypre FreeFem.so. A
haga esto, vaya al directorio src / solver de FreeFem ++, edite el archivo makefile.inc para especificar
las siguientes variables:
HYPRE DIR: Directorio de HYPRE
HYPRE INCLUYE = -I $ (HYPRE DIR) src / hypre / include /:
Directorio para encabezado de HYPRE
HYPRE LIB = -L $ (HIPS DIR) / src / lib / -lHYPRE: Biblioteca Hypre
FREEFEM: Directorio FreeFem ++
FREEFEM INCLUYE: encabezado FreeFem para un solucionador lineal disperso
METIS: Directorio METIS
METIS LIB: Biblioteca METIS
MPI: Directorio MPI
MPI INCLUYE: Encabezados MPI
Al igual que con pARMS, la llamada de HIPS en FreeFem ++ se puede realizar de tres maneras. Lo haremos
presentar solo un ejemplo donde el usuario especifica sus parámetros a través de palabras clave lparams y
dparams.

Laplacian 3D resuelve con HYPRE Consideremos nuevamente el ejemplo 3D Laplacian en el interior


Paquete FreeFem ++ donde después de la discretización queremos resolver la ecuación lineal con Hypre.
El ejemplo 11 .6 es el Laplacian3D usando Hypre como solucionador lineal. El ejemplo 11.6 es lo mismo que 11.5,
por lo que solo mostramos aquí las líneas donde configuramos algunos parámetros de Hypre.
Primero cargamos el solucionador de Hypre en la línea 2. De la línea 4 a la 15 especificamos los parámetros a establecer
Hypre solver y en la línea 43 establecemos los parámetros para Hypre solver.
Cabe señalar que el significado de las entradas de estos vectores es diferente al de Hips.
En el caso de HYPRE, el significado de las diferentes entradas de los vectores iparm y dparm se dan en
tablas 11.13 a 11.17.

En mesa ?? Se informan los resultados de ejecutar el ejemplo 11. 6 en Cluster Paradent de Grid5000. Nosotros
puede ver en este ejemplo en ejecución la eficiencia del paralelismo, en particular cuando se utilizan AMG como
preacondicionador.

Ejemplo 11.6 (Laplacian3D.edp) 1: cargar "msh3"


2: carga "hipre_FreeFem" // cargar librairie
3: int nn = 10, iii;
4: int [int] iparm (20);
5: real [int] dparm (6);
6: para (iii = 0; iii <20; iii ++) iparm [iii] = - 1;
7: para (iii = 0; iii <6; iii ++) dparm [iii] = - 1;
8: iparm [0] = 2; // PCG como método krylov
9: iparm [1] = 0; // AMG como preacondicionador 2: si ParaSails
10: iparm [7] = 7; // Interpolación
11: iparm [9] = 6; // Tipo AMG Coarsen
12: iparm [10] = 1; // Tipo de medida
13: iparm [16] = 2; // Schwarz aditivo tan suave
13: dparm [0] = 1e-13; // Tolerancia a la convergencia
14: dparm [1] = 5e-4; // Umbral
15: dparm [2] = 5e-4; // factor de truncamiento
.
.

https://translate.googleusercontent.com/translate_f 297/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
.

Página 335
11.4. DESCOMPOSICIÓN DE DOMINIOS 335

43: set (Aa, solver = sparsesolver, dparams = dparm, lparams = iparm);

Identificación del solucionador:


iparms [0]
0: BiCGStab, 1: GMRES, 2: PCG. Por defecto = 1
Identificación del preacondicionador:
iparms [1]
0: BOOMER AMG, 1: PILUT, 2: Parasails, 3: Schwartz Predeterminado = 0
iparms [2] Máximo de iteración: Predeterminado = 1000
iparms [3] Krylov subespacio dim: Predeterminado = 40
iparms [4] Nivel de información de impresión de Solver: Predeterminado = 2
iparms [5] Registro del solucionador: Predeterminado = 1
iparms [6] Criterios de detención de Solver solo para BiCGStab: Predeterminado = 1
dparms [0] Tolerancia de convergencia: Predeterminado = 1.0e - 11

Tabla 11.13: Definiciones de entradas comunes de vectores iparms y dparms para cada preconfiguración.
ditioner en HYPRE

11.3.4 Conclusión
Con las diferentes ejecuciones que se presentan aquí, queríamos ilustrar la ganancia en el tiempo cuando aumentamos
el número de procesadores utilizados para las simulaciones. Vimos que en todos los casos el tiempo para el
La construcción de la matriz de elementos finitos es constante. Esto es normal porque hasta ahora esta fase
es secuencial en FreeFem ++. Por el contrario, las fases para resolver el sistema lineal son paralelas. Nosotros
vimos en varios ejemplos presentados aquí que cuando aumentamos el número de procesadores, en general
disminuimos el tiempo empleado para resolver los sistemas lineales. Pero esto no es cierto en todos los casos. En varios
En el caso de que aumentemos el número de procesadores, el tiempo de convergencia también aumenta. Existen
dos razones principales para esto. Primero, el aumento de procesadores puede conducir al aumento del volumen de
intercambiaron datos entre procesadores, aumentando consecuentemente el tiempo para resolver los sistemas lineales.
Además, en los preacondicionadores del tipo de dominio de descomposición, el número de procesadores generalmente
corresponde al número de subdominios. En los métodos de subdominio, generalmente cuando aumentamos el
número de subdominios disminuimos la calidad de convergencia del preacondicionador. Esto puede aumentar
el tiempo empleado para resolver ecuaciones lineales.
Para terminar con esto, debemos tener en cuenta que el buen uso de los preacondicionadores interconectados en FreeFem ++ es
empírico, porque es difícil saber cuál es un buen precondicionador para algún tipo de problemas.
Aunque, la eficiencia de los preacondicionadores a veces depende de cómo se establezcan sus parámetros. Para
Por esta razón, recomendamos al usuario que preste atención al significado de los parámetros en la guía del usuario.
de los solucionadores iterativos interconectados en FreeFem ++.

11.4 Descomposición de dominios


En la sección anterior, vimos que las fases para construir una matriz son secuenciales. Una estrategia
construir la matriz en paralelo es dividir geométricamente el dominio en subdominios. En cada
subdominio construimos una submatriz local y después de eso ensamblamos cada submatriz para formar la
matriz global.
Podemos utilizar esta técnica para resolver pde directamente en el dominio Ω. En este caso, en todos los subdominios
tienes que definir condiciones de contorno artificiales para formar ecuaciones consistentes en todos los subdominios.
Después de esto, resuelve la ecuación en cada subdominio y define una estrategia para obtener el global
solución.

https://translate.googleusercontent.com/translate_f 298/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 336
336 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

iparms [7] Tipo de interpolación AMG: Predeterminado = 6


Especifica el uso de GSMG - geométricamente
iparms [8]
engrosamiento e interpolación suaves: Predeterminado = 1
iparms [9] Tipo coarsen AMG: Predeterminado = 6
Define si medidas locales o globales
iparms [10]
se utilizan: Predeterminado = 1
iparms [11] Tipo de ciclo AMG: Predeterminado = 1
iparms [12] Tipo AMG más suave: Predeterminado = 1
iparms [13] Número AMG de niveles para suavizadores: Predeterminado = 3
iparms [14] AMG número de barridos para suavizadores: Predeterminado = 2
iparms [15] Número máximo de niveles de redes múltiples: Predeterminado = 25
Define qué variante del método de Schwartz se utiliza:
0: método de Schwartz multiplicativo híbrido (sin superposición a través de los límites del procesador)
1: método de Schwartz aditivo híbrido (sin superposición entre los límites del procesador)
iparms [16]
2: método de Schwartz aditivo
3: método de Schwartz multiplicativo híbrido (con superposición a través de los límites del procesador)
Predeterminado = 1
iparms [17] Tamaño del sistema de PDE: Predeterminado = 1
iparms [18] Superposición para el método Schwarz: Predeterminado = 1
Tipo de dominio utilizado para el método Schwarz
0: cada punto es un dominio
iparms [19]
1: cada nodo es un dominio (solo de interés en "sistemas" AMG)
2: cada dominio se genera por aglomeración (predeterminado)
dparms [1] Umbral de fuerza AMG: Predeterminado = 0,25
dparms [2] Factor de truncamiento para la interpolación: Predeterminado = 1e-2
Establece un parámetro para modificar la definición.
dparms [3]
de fuerza para las porciones diagonales dominantes de la matriz: Predeterminado = 0,9
Define un parámetro de suavizado para el método de Schwartz aditivo
dparms [3]
Predeterminado = 1.

Tabla 11.14: Definiciones de otras entradas de iparms y dparms si el preacondicionador es BOOMER


AMG

iparms [7] Tamaño de fila en ILUT paralelo: Predeterminado = 1000


iparms [8] Establece el número máximo de iteraciones: Predeterminado = 30
dparms [1] Tolerancia de caída en ILUT paralelo: Predeterminado = 1e-5

Tabla 11.15: Definiciones de otras entradas de iparms y dparms si el preacondicionador es PILUT

Página 337
11.4. DESCOMPOSICIÓN DE DOMINIOS 337

https://translate.googleusercontent.com/translate_f 299/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
iparms [7] Número de niveles en paralelo disperso Inverso aproximado: Predeterminado = 1
Parámetro simétrico para el preacondicionador de ParaSails:
0: problema no simétrico y / o indefinido, y preacondicionador no simétrico
iparms [8]
1: problema de SPD y preacondicionador de SPD (factorizado)
2: precondicionador no simétrico, de problema definido y SPD (factorizado)
Predeterminado = 0
Parámetros de filtros: el parámetro de filtro se utiliza para
dparms [1] Deje caer pequeños nonzeros en el preacondicionador, para reducir
el costo de aplicar el preacondicionador: Predeterminado = 0.1
dparms [2] Parámetro de umbral: Predeterminado = 0,1

Tabla 11.16: Definiciones de otras entradas de iparms y dparms si el preacondicionador es ParaSails

Define qué variante del método de Schwartz se utiliza:


0: método de Schwartz multiplicativo híbrido (sin superposición a través de los límites del procesador)
1: método de Schwartz aditivo híbrido (sin superposición entre los límites del procesador)
iparms [7]
2: método de Schwartz aditivo
3: método de Schwartz multiplicativo híbrido (con superposición a través de los límites del procesador)
Predeterminado = 1
iparms [8] Superposición para el método Schwartz: Predeterminado = 1
Tipo de dominio utilizado para el método Schwartz
0: cada punto es un dominio
iparms [9]
1: cada nodo es un dominio (solo de interés en "sistemas" AMG)
2: cada dominio se genera por aglomeración (predeterminado)

Tabla 11.17: Definiciones de otras entradas de iparms y dparms si el preacondicionador es Schwartz

n = 4 × 10 6 nnz = 13 × 10 6 Te = 571,29
notario público AMG
liendre hora
8 6 1491,83
dieciséis 5 708.49
32 4 296.22
64 4 145,64

Tabla 11.18: Convergencia y tiempo para resolver el sistema lineal del ejemplo 11.4

Página 338
338 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

En términos de programación paralela para FreeFem ++, con MPI, esto significa que el usuario debe estar
capaz de dividir los procesadores disponibles para la computación en subgrupos de procesadores y también debe ser
capaz de realizar diferentes tipos de comunicaciones en el script FreeFem ++. Aquí hay un envoltorio de algunos
Funciones MPI.

11.4.1 Comunicadores y grupos


Grupos
mpiGroup grpe (mpiGroup gp, KN <long>): crea un grupo MPI a partir de un grupo existente gp por

https://translate.googleusercontent.com/translate_f 300/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
vector dado
Comunicadores
Communicators es un objeto MPI abstracto que permite al usuario MPI comunicarse a través del grupo de
procesadores. Los comunicadores pueden ser intracomunicadores (involucra a un solo grupo) o intercomunicadores
(involucra a dos grupos). Cuando no especifiquemos tipo de comunicador será Intracomunicadores

mpiComm cc (mpiComm comm, mpiGroup gp): crea un nuevo comunicador. comm comunicación
tor (asa), grupo gp que es un subconjunto del grupo de comm (asa). Devolver nuevo comunicador

mpiComm cc (mpiGroup gp): Igual que el constructor anterior, pero la comunicación predeterminada aquí es MPI COMM WORLD.
mpiComm cc (mpiComm comm, int color, int key): crea nuevos comunicadores basados en colores
y clave. Este constructor se basa en la rutina de división MPI Comm de MPI.
mpiComm cc (MPIrank p, int key): Mismo constructor que el anterior. Aquí los colores y las comunicaciones
definido en MPIrank. Este constructor se basa en la rutina de división MPI Comm de MPI.

Ejemplo 11.7 (commsplit.edp) 1: int color = mpiRank (comm)% 2;


2: mpiComm ccc (procesador (color, comm), 0);
3: mpiComm qpp (comm,);
4: mpiComm cp (cc, color, 0);

mpiComm cc (mpiComm comm, int high): crea un intracomunicador a partir de un intercomunicador


colina. intercomunicador comm, alto Se utiliza para ordenar los grupos dentro del comm (lógico) al crear
el nuevo comunicador. Este constructor se basa en la rutina de fusión MPI Intercomm de MPI.
mpiComm cc (MPIrank p1, MPIrank p2, etiqueta int): este constructor crea un intercomunicador
de dos intracomunicadores. p1 definió el comunicador local (intra) y el rango en las comunicaciones locales de
líder (a menudo 0) mientras que p2 definía el comunicador remoto y el rango en la comunicación entre pares del líder remoto
(a menudo 0). etiqueta Etiqueta de mensaje para usar en la construcción del intercomunicador. Este constructor se basa en
Crear intercomunicador MPI.

Ejemplo 11.8 (merge.edp) 1: mpiComm comm, cc;


2: int color = mpiRank (comm)% 2;
3: int rk = mpiRank (comm);
4: int tamaño = mpiSize (comm);
4: cout << "Valores de color" << color << endl;
5: mpiComm ccc (procesador ((rk <tamaño / 2), comm), rk);
6: mpiComm cp (cc, color, 0);
7: int rleader;
8: if (rk == 0) {rleader = size / 2; }
9: más si (rk == tamaño / 2) {rleader = 0;}

Página 339
11.4. DESCOMPOSICIÓN DE DOMINIOS 339

10: else {líder = 3; }


11: mpiComm qqp (procesador (0, ccc), procesador (rleader, comm), 12345);
12: int aaa = mpiSize (ccc);
13: cout << "número de procesador" << aaa << endl;

11.4.2 Proceso
En FreeFem ++ ajustamos el proceso MPI por el procesador de llamadas de función que crea FreeFem ++ interno
llamada de objeto MPIrank. Esto significa que no utilice MPIrank en el script FreeFem ++.
procesador (int rk): Mantiene el rango del proceso dentro del objeto MPIrank. El rango está dentro de MPI COMM WORLD.
procesador (int rk, mpiComm cc) y procesador (mpiComm cc, int rk) rango de proceso dentro de la comunidad
cator cc.
procesador (int rk, mpiComm cc) y procesador (mpiComm cc, int rk) rango de proceso dentro de la comunidad
cator cc.
procesadorblock (int rk): esta función es exactamente la misma que la de procesador (int rk) pero se usa en caso de

https://translate.googleusercontent.com/translate_f 301/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
de bloquear la comunicación.
procesadorblock (int rk, mpiComm cc): esta función es exactamente la misma que la de procesador (int
rk, mpiComm cc) pero use un punto de sincronización.

11.4.3 Comunicadores de puntos a puntos


En FreeFem ++ puede llamar puntos MPI a funciones de comunicación de puntos.
Enviar (procesador (int rk, mpiComm cc), Data D): Bloqueo del envío de datos D al procesador de rango rk
comunicador interior cc. Tenga en cuenta que los datos D pueden ser: int, real, complex, int [int], real [int], complex [int],
Malla, Malla3, Matriz.
Recv (procesador (int rk, mpiComm cc), Data D): Recibe los datos D del proceso de rango rk en
municator cc. Tenga en cuenta que los datos D pueden ser: int, real, complex, int [int], real [int], complex [int], Mesh,
Mesh3, Matrix y deben ser del mismo tipo que el envío correspondiente.
Isend (procesador (int rk, mpiComm cc), Data D): envío sin bloqueo de Data D al procesador de rango rk
comunicador interior cc. Tenga en cuenta que los datos D pueden ser: int, real, complex, int [int], real [int], complex [int],
Malla, Malla3, Matriz.
Recv (procesador (int rk, mpiComm cc), Data D): Recibir correspondiente al envío.

11.4.4 Operaciones globales


En FreeFem ++ puede llamar a funciones de comunicación global MPI.
broadcast (procesador (int rk, mpiComm cc), Data D): Process rk Broadcast Data D a todos los procesos en
comunicador lateral cc. Tenga en cuenta que los datos D pueden ser: int, real, complex, int [int], real [int], complex [int],
Malla, Malla3, Matriz.

broadcast (procesador (int rk), Data D): Process rk Broadcast Data D a todos los procesos internos
MUNDO DE COMUNICACIÓN DE MPI. Tenga en cuenta que los datos D pueden ser: int, real, complex, int [int], real [int], complex [int],
Malla, Malla3, Matriz.

mpiAlltoall (Datos a, Datos b): Envía datos a de todos a todos los procesos. El búfer de recepción es de datos b. Esto
se realiza dentro del comunicador MPI COMM WORLD.

Página 340
340 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

mpiAlltoall (Datos a, Datos b, mpiComm cc): Envía datos a de todos a todos los procesos. Recibir búfer
es Datos b. Esto se hace dentro del comunicador cc.

mpiGather (Datos a, Datos b, procesador (mpiComm, int rk): Recopila valores Datos a de
un grupo de procesos. El proceso de rango rk obtiene datos en el comunicador rk. Esta función es como
Reunión de MPI

mpiAllgather (Data a, Data b): recopila datos a de todos los procesos y los distribuye a todos en Data
B. Esto se hace dentro del comunicador MPI COMM WORLD. Esta función es como MPI Allgather

mpiAllgather (Data a, Data b, mpiComm cc): recopila los datos a de todos los procesos y los distribuye
a todos en Datos b. Esto se hace dentro del comunicador cc. Esta función es como MPI Allgather

mpiScatter (Datos a, Datos b, procesador (int rk, mpiComm cc)): Envía Datos a desde un proceso con
clasifica rk a todos los demás procesos del grupo representado por el comunicador mpiComm cc.

mpiReduce (Datos a, Datos b, procesador (int rk, mpiComm cc), MPI Op op), Reduce valores Datos a
sobre todos los procesos a un solo valor. Datos b sobre el proceso de rango rk y comunicador cc. Operación
el uso en reducir es: MPI Op op que puede ser: mpiMAX, mpiMIN, mpiSUM, mpiPROD, mpiLAND,
mpiLOR, mpiLXOR, mpiBAND, mpiBXOR, mpiMAXLOC, mpiMINLOC.
Tenga en cuenta que, para todas las operaciones globales, solo int [int] y real [int] son los tipos de datos que se tienen en cuenta en
FreeFem ++.

11.5 solucionadores HPDDM


https://translate.googleusercontent.com/translate_f 302/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Los ejemplos correspondientes se encuentran en el directorio examples ++ - hpddm. Problemas reales valorados
(difusión, calor, elasticidad y Stokes) y problemas complejos valorados (Maxwell y Helmholtz) son
dado en 2D y 3D. Detallamos aquí el problema de la elasticidad 3D y el 3D dependiente del tiempo.
problema de calor.

Ejemplo 11.9 (elasticidad-3d.edp) Se define un problema de elasticidad tridimensional. El solucionador es


un método de descomposición de dominios. Los métodos de descomposición de dominios son un marco natural para
computadoras allel. Los scripts en el directorio examples ++ - hpddm se ejecutan en equipos multinúcleo
(de 2 a decenas de miles de núcleos). Recuerde que, como en cualquier código MPI, el número de MPI
Los procesos, mpisize, se dan en la línea de comandos a través de la opción -np. Nos centramos en el guión
elasticity-3d.edp pero los otros scripts tienen la misma estructura. La línea de comando para ejecutar
el ejemplo de cuatro procesos con visualización ffglut es:

ff-mpirun -np 4 elasticidad-3d.edp -glut ffglut

39 int [ int ] arrayIntersection; // rangos de subdominios vecinos


int [ int ] [ int ] restrictionIntersection (0); // renumeración de local a vecinos
real [ int ] D; // partición de la unidad
{
43 meshN ThGlobal = cube (10 ∗ getARGV ( ”−global” , 5), getARGV ( ”−global” , 5), ← ↪
↩ → getARGV ( ”−global” , 5), [10 ∗ x, y, z], etiqueta = LL); // malla global
build (Th, ThBorder, ThGlobal, fakeInterface, s, superposición, D, arrayIntersection, ← ↪
↩ → restricciónIntersección, Wh, Pk, comm, excluido, 3)
}

Página 341
11,5. SOLUCIONADORES HPDDM 341

47 f real = −9000,0;
deformación real = 100,0;
joven real = 2.0e11; // acero
poisson real = 0,35;
51 tmp real = 1,0 + poisson;
mu real = Joven / (2,0 ∗ tmp);
lambda real = Young ∗ poisson / (tmp ∗ (1.0 - 2.0 ∗ poisson));
reales [ int ] rhs; // lado derecho local
55 matriz < real > Mat; // operador local
{ // forma débil local
meshN ThAugmented = Th + ThBorder;
varf vPb (def (u), def (v)) = intN (ThAumentado) (lambda ∗ div (u) ∗ div (v) + 2.0 ∗ mu ∗ ← ↪
↩ → (épsilon (u) '∗ épsilon (v))) + intN (ThAumentado) (f ∗ vC) + en (1, u = 0.0, uB = 0.0, uC ← ↪
↩ → = 0.0);
59 fespace WhAugmented (ThAugmented, Pk);
Mat = vPb (WhAumentado, WhAumentado, tgv = −1);
real [ int ] rhsFull = vPb (0, WhAumentado, tgv = −1);
matriz R = interpolar (Wh, WhAumentado);
63 renumerar (Mat, R, rhsFull, rhs);
}
ThBorder = cubo (1, 1, 1, [x, y, z]);

67 dschwarz A (Mat, arrayIntersection, restrictionIntersection, escala = D);

Listado 11.1: hpddm / elasticity-3d.edp

La macro construcción es de particular interés ya que maneja la distribución de datos entre los mpisize
MPI procesa con los siguientes pasos:

• la malla inicial ThGlobal está dividida por el proceso 0 en submallas mpisize

• la partición se transmite a todos los procesos i para 0 <i <mpisize. A partir de entonces, todas las tareas
son paralelos.

• cada proceso crea la submalla local Th (si el factor de refinamiento se define mediante la opción
-split es mayor que 1, cada borde local se divide en s sub-bordes, lo que da como resultado cada elemento

https://translate.googleusercontent.com/translate_f 303/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
dividido en 2 elementos en 2D y 3 elementos en 3D) de modo que la colección de estos
submeshes es una descomposición de dominios superpuestos de una malla refinada. El número de extra
Las capas agregadas a la partición inicial se supervisan mediante la opción -overlap.

• se crean estructuras de conectividad

- D es la diagonal de la partición local de la unidad (ver más abajo § 11.5.2 para más detalles)

- arrayIntersection es la lista de vecinos del subdominio actual


- Para j en arrayIntersection, restrictionIntersection [j] es la lista de
grados de libertad que pertenecen a la intersección del subdominio actual con su
vecino j.

Luego, se usa la formulación variacional vPb de un problema de elasticidad tridimensional


para ensamblar una matriz local Mat. Esta matriz junto con D, arrayIntersection y
restrictionIntersection son argumentos para el constructor de la matriz distribuida A.
Esto es suficiente para resolver el problema con un método de Schwarz aditivo de un nivel que puede ser
ASM o RAS.

Página 342
342 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Para algunos problemas, es interesante utilizar condiciones de interfaz optimizadas. Cuando hay muchos
subdominios, generalmente es rentable agregar un segundo nivel al solucionador. Las opciones se establecen en la secuela
del guión:

set (A, sparams = ”−hpddm método schwarz ras −hpddm schwarz corrección gruesa balanceada ← ↪
↩ → −hpddm variante derecha −hpddm verbosidad 1 −hpddm geneo nu 10 ” );

Listado 11.2: hpddm / elasticity-3d.edp

En la línea anterior, la primera opción selecciona el ras del preacondicionador de un nivel (las opciones posibles son
ras, oras, soras, asm, osm o none), la segunda opción selecciona la fórmula de corrección para el
segundo nivel aquí equilibrado (las opciones posibles son desinflado, aditivo o equilibrado),
La tercera opción selecciona el preacondicionamiento correcto, la cuarta es el nivel de verbosidad de HPDDM (diferente
del de FreeFem ++), el quinto imprime todas las opciones posibles de HPPDM y el último
especifica el número de grados aproximados de libertad por subdominio del espacio aproximado GENEO. Todas
otras opciones de la hoja de referencia de la biblioteca HPDDM [ 6] se pueden seleccionar a través de la función FreeFem ++
colocar.

En la última parte del script, el sistema lineal global se resuelve mediante el método de descomposición de dominios.
definido anteriormente.

Wh < real > def (u); // solución local

if (Opt.n> 0) // métodos optimizados de Schwarz


109 DDM (A, u [], rhs, excluido = excluido, ret = ret, O = Opt);
demás
u [] = A −1 ∗ rhs;

113 real [ int ] err (u []. N);


err = A ∗ u []; // producto vector matriz global
err - = rhs;

117 plotMPI (Th, u [], "Solución global" , Pk, def, real , 3, 1)


plotMPI (Th, err, "Global residual" , Pk, def, real , 3, 1)
alfa real = 2000,0;
meshN ThMoved = movemesh3 (Th, transfo = [x + alpha ∗ u, y + alpha ∗ uB, z + alpha ∗ uC]);
121 u [] = mpirango;
plotMPI (ThMoved, u [], "Solución global movida" , Pk, def, real , 3, 1)

Listado 11.3: hpddm / elasticity-3d.edp

https://translate.googleusercontent.com/translate_f 304/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

11.5.1 Problema dependiente del tiempo


Ejemplo 11.10 (heat-3d.edp) Un problema de calor tridimensional

∂u
- ∆u = 1, u (0, ·): = 0 en Ω.
∂t

está discretizado por un esquema de Euler implícito. En cada paso de tiempo n, buscaremos u n (x, y, z) que satisfaga
para todo w ∈ H 1 (Ω):
∫ u n - u n−1 ∫
w + ∇u n ∇w = w, u 0 : = 0 en Ω.
Ω δt Ω

Página 343
11,5. SOLUCIONADORES HPDDM 343

de modo que en cada paso de tiempo un sistema lineal

(M + dt ∗ K) u norte [] = M ∗ u norte − 1 [] + δt ∗ F

se resuelve mediante un método de descomposición de dominios donde M es la matriz de masa y K es la rigidez


matriz. Para ahorrar esfuerzos computacionales, el precondicionador del método de descomposición de dominios
se construye solo una vez y luego se reutiliza para todas las soluciones posteriores con la matriz A: = M + dt ∗ K.
El producto vectorial de matriz distribuida con matriz M se realiza mediante la llamada a la función dmv usando
la partición de unidad asociada a la matriz A.

90 set (A, sparams = ”−hpddm reuse preconditioner = 1” );


Wh < real > def (u) = init (0.0); // solución local
para ( int i = 0; i <iMax; ++ i) {
real [ int ] newRhs (rhs.n);
94 dmv (A, M, u [], newRhs); // newRhs = M ∗ u []
newRhs + = rhs;

if (Opt.n> 0) // métodos optimizados de Schwarz


98 DDM (A, u [], newRhs, excluido = excluido, ret = ret, O = Opt);
demás
u [] = A −1 ∗ newRhs;

102 plotMPI (Th, u [], "Solución global" , Pk, def, real , 3, 0)


}

Listado 11.4: hpddm / heat-3d.edp

11.5.2 Vectores distribuidos en HPDDM


Damos aquí algunas sugerencias sobre la forma en que los vectores se distribuyen entre los procesos np cuando se usa
FreeFem ++ interconectado con HPDDM. El conjunto de grados de libertad N se descompone en np
conjuntos superpuestos (N i ) 1≤i≤np . Un proceso MPI está a cargo de cada subconjunto. Sea n: = #N el número
número de grados de libertad del espacio global de elementos finitos. Sea R i el operador de restricción
de R n a R #N i . También hemos definido matrices diagonales locales D i ∈ R #N i × R #N i de modo que
tener una partición de unidad a nivel algebraico:
notario público

U= ∑ RT ∀U∈Rn. (11,1)
iDiRiU
i=1

En realidad, un vector global U actually R n no se almacena. Más bien, se almacena de forma distribuida. Cada
el proceso i, 1 ≤ i ≤ N, almacena el vector local U i : = R i U ∈ R #N i .
Es importante asegurarse de que el resultado de todos los operadores de álgebra lineal aplicados a esta representación
son coherentes.
Como ejemplo, considere el producto escalar de dos vectores distribuidos U, V ∈ R n . Utilizando la
partición de unidad (11.1 ), tenemos:
notario público notario público
( )
(U, V) = U ∑ RT = ∑ (R i U, D i R i V)
yo D yo R yo V
i=1 i=1

https://translate.googleusercontent.com/translate_f 305/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
notario público

= ∑ (U yo , D yo V yo ).
i=1

Página 344
344 CAPÍTULO 11. SOLUCIONADORES ESPAROS EN PARALELO

Por tanto, la fórmula del producto escalar es:


notario público

(U, V) = ∑ (R i U, D i R i V).
i=1

Los productos escalares locales se realizan al mismo tiempo. Por lo tanto, la implementación es paralela a excepción de
la suma que corresponde a una llamada MPI Reduce a través de los procesos np MPI. Tenga en cuenta también que el
La implementación se basa en el conocimiento de una partición de unidad para que la sintaxis de FreeFem ++ sea
dscalprod (D, u, v).

Un procedimiento axpy y ← αx + y para x, y ∈ R n y α ∈ R se implementa fácilmente al mismo tiempo para


vectores distribuidos en la forma:

y yo ← αx yo + y yo , ∀ 1 ≤ yo ≤ np.

El producto del vector matricial está más involucrado y los detalles se dan en el libro de SIAM Introducción
a los métodos de descomposición de dominios: algoritmos, teoría e implementación paralela [7] e incluso
se dan más detalles en el manuscrito de doctorado de P. Jolivet.

https://translate.googleusercontent.com/translate_f 306/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 345

Capítulo 12

Archivos de malla

12.1 Estructura de datos de malla de archivos


La estructura de datos de malla, salida de un algoritmo de generación de malla, se refiere a los datos geométricos
estructura y en algún caso a otra estructura de datos de malla.
En este caso, los campos son

• MeshVersionFormatted 0

• Dimensión (I) tenue

• Vértices (I) NbOfVertices

(( (R) x j

i ,
j = 1, tenue ) , (I) Refφ v i , i = 1, NbOfVertices )
• Bordes (I) NbOfEdges

( @@ Vértice 1
i, @@ Vértice 2 yo , (yo) refφ e
i , i = 1, NbOfEdges )
• Triángulos (I) NbOfTriangles

(( @@ Vértice j

i ,
j = 1,3 , (I) Refφ t ) i , i = 1, NbOfTriangles )
• Cuadriláteros (I) NbOfQuadrilaterals

(( @@ Vértice j

i , j = 1,4 ) , (I) Refφ t i , i = 1, NbOfQuadrilaterals )


• Geometría
(C *) FileNameOfGeometricSupport

- VertexOnGeometricVertex
(I) NbOfVertexOnGeometricVertex
( @@ Vértice i, @@ Vértice
geo
I , i = 1, NbOfVertexOnGeometricVertex )
- EdgeOnGeometricEdge
(I) NbOfEdgeOnGeometricEdge
( @@ Borde i, @@ Borde
I
geo
, i = 1, NbOfEdgeOnGeometricBorde )
• CrackedEdges (I) NbOfCrackedEdges

( @@ Borde , @@ Borde
1
yo
, i = 1, NbOfCrackedBordes )
i
2

345

Página 346
346 CAPÍTULO 12. ARCHIVOS DE MALLA

https://translate.googleusercontent.com/translate_f 307/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Cuando la malla actual se refiere a una malla anterior, tenemos además
• MeshSupportOfVertices
(C *) FileNameOfMeshSupport

- VertexOnSupportVertex
(I) NbOfVertexOnSupportVertex
( @@ Vértice i, @@ Vértice
suplir
I , i = 1, NbOfVertexOnSupportVertex )
- VertexOnSupportEdge
(I) NbOfVertexOnSupportEdge
( @@ Vértice i, @@ Borde I
suplir
, (R) u
suplir
I , i = 1, NbOfVertexOnSupportEdge )
- VertexOnSupportTriangle
(I) NbOfVertexOnSupportTriangle
( @@ Vértice i, @@ Tria
suplir
I , (R) u
suplir
I , (R) v
suplir
I ,
i = 1, NbOfVertexOnSupportTriangle )
- VertexOnSupportQuadrilaterals
(I) NbOfVertexOnSupportQuadrilaterals
( @@ Vértice i,
suplir
@@ Cuádruple
I , (R) u
suplir
I , (R) v
suplir
I ,
i = 1, NbOfVertexOnSupportQuadrilaterals )

12.2 bb Tipo de archivo para soluciones de tienda


El archivo está formateado de tal manera que:
2 nbsol nbv 2
((U ij , ∀i ∈ {1, ..., nbsol}), ∀j ∈ {1, ..., nbv})
dónde

• nbsol es un número entero igual al número de soluciones.

• nbv es un número entero igual al número de vértice.

• U ij es un valor real igual al valor de la solución i en el vértice j en la malla asociada


fondo si es un archivo leído, generado si es un archivo de escritura.

12.3 Tipo de archivo BB para soluciones de tienda


El archivo está formateado de tal manera que:
2 n tiposol 1 ... tiposol n nbv 2
((( U k
ij , ∀i ∈ {1, ..., typesol k }), ∀k ∈ {1, ... n}) ∀j ∈ {1, ..., nbv})
dónde

• n es un número entero igual al número de soluciones

• typesol k , tipo de solución número k, es

Página 347
12.4. ARCHIVO MÉTRICO 347

- typesol k = 1 la solución k es escalar (1 valor por vértice)


- typesol k = 2 la solución k es vectorial (2 valores por desconocido)

- typesol k = 3 la solución k es una matriz simétrica de 2 × 2 (3 valores por vértice)


- typesol k = 4 la solución k es una matriz de 2 × 2 (4 valores por vértice)

• nbv es un número entero igual al número de vértices

https://translate.googleusercontent.com/translate_f 308/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

•Uk
ij es un valor real igual al valor del componente i de la solución k en el vértice j en el
fondo de malla asociado si es un archivo de lectura, generado si es un archivo de escritura.

12.4 Archivo métrico


Un archivo métrico puede ser de dos tipos, isotrópico o anisotrópico.
la lima isotrópica es tal que
nbv 1
h i ∀i ∈ {1, ..., nbv}
dónde

• nbv es un número entero igual al número de vértices.

• h i es el tamaño de malla deseado cerca del vértice i en la malla de fondo, la métrica es M i =


h −2
i Id, donde Id es la matriz de identidad.

El anisótropo métrico
nbv 3
a11 yo , a21 yo , a22 yo ∀i ∈ {1, ..., nbv}
dónde

• nbv es un número entero igual al número de vértices,

• a11 i , a12 i , a22 i es métrica M i = ( a11 i a12 i ) que definen el tamaño de malla deseado en un
a12 yo a22 yo √
proximidad del vértice i tal que h en la dirección u ∈ R 2 es igual a | u | / u · M i u,
donde · es el producto escalar en R 2 , y | · | es la norma clásica.

12.5 Lista de mallas AM FMT, AMDBA


La malla solo está compuesta por triángulos y se puede definir con la ayuda de lo siguiente
dos enteros y cuatro matrices:

nbt es el número de triángulos.

nbv es el número de vértices.

nu (1: 3,1: nbt) es una matriz entera que da los tres números de vértice
en sentido antihorario para cada triángulo.

Página 348
348 CAPÍTULO 12. ARCHIVOS DE MALLA

c (1: 2, nbv) es una matriz real que da las dos coordenadas de cada vértice.

refs (nbv) es una matriz de enteros que da los números de referencia de los vértices.

reft (nbv) es una matriz de enteros que da los números de referencia de los triángulos.

Archivos AM FMT En fortran, los archivos am fmt se leen de la siguiente manera:

abierto (1, archivo = 'xxx.am_fmt', formulario = 'formateado', estado = 'antiguo')


leer (1, *) nbv, nbt
leer (1, *) ((nu (i, j), i = 1,3), j = 1, nbt)
leer (1, *) ((c (i, j), i = 1,2), j = 1, nbv)
leer (1, *) (reft (i), i = 1, nbt)
leer (1, *) (refs (i), i = 1, nbv)
cerrar (1)

https://translate.googleusercontent.com/translate_f 309/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Archivos AM En fortran, los archivos am se leen de la siguiente manera:

open (1, archivo = 'xxx.am', formulario = 'sin formato', estado = 'antiguo')


leer (1, *) nbv, nbt
leer (1) ((nu (i, j), i = 1,3), j = 1, nbt),
Y ((c (i, j), i = 1,2), j = 1, nbv),
Y (reft (i), i = 1, nbt),
Y (referencias (i), i = 1, nbv)
cerrar (1)

Archivos AMDBA En fortran, los archivos amdba se leen de la siguiente manera:

abierto (1, archivo = 'xxx.amdba', formulario = 'formateado', estado = 'antiguo')


leer (1, *) nbv, nbt
leer (1, *) (k, (c (i, k), i = 1,2), refs (k), j = 1, nbv)
leer (1, *) (k, (nu (i, k), i = 1,3), reft (k), j = 1, nbt)
cerrar (1)

Archivos msh Primero, agregamos las nociones de bordes de límites

nbbe es el número de borde de límite.

nube (1: 2,1: nbbe) es una matriz entera que da los dos números de vértice

refbe (1: nbbe) es una matriz entera que da los dos números de vértice
En fortran, los archivos msh se leen de la siguiente manera:

abierto (1, archivo = 'xxx.msh', formulario = 'formateado', estado = 'antiguo')


leer (1, *) nbv, nbt, nbbe
leer (1, *) ((c (i, k), i = 1,2), refs (k), j = 1, nbv)
leer (1, *) ((nu (i, k), i = 1,3), reft (k), j = 1, nbt)
leer (1, *) ((ne (i, k), i = 1,2), refbe (k), j = 1, nbbe)
cerrar (1)

Página 349
12.5. LISTA DE MALILLAS AM FMT, AMDBA 349

Archivos ftq En fortran, los archivos ftq se leen de la siguiente manera:

abierto (1, archivo = 'xxx.ftq', formulario = 'formateado', estado = 'antiguo')


leer (1, *) nbv, nbe, nbt, nbq
leer (1, *) (k (j), (nu (i, j), i = 1, k (j)), reft (j), j = 1, nbe)
leer (1, *) ((c (i, k), i = 1,2), refs (k), j = 1, nbv)
cerrar (1)

donde si k (j) = 3 entonces el elemento j es un triángulo y si k = 4 el elemento j es un


cuadrilátero.

https://translate.googleusercontent.com/translate_f 310/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 350
350 CAPÍTULO 12. ARCHIVOS DE MALLA

https://translate.googleusercontent.com/translate_f 311/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 351

Capítulo 13

Adición de un nuevo elemento finito

13.1 Algunas notaciones


Para una función f que toma valor en R N , N = 1,2, ···, definimos la aproximación de elementos finitos Π h f
apagado. Denotemos el número de grados de libertad del elemento finito por NbDoF. Luego
la i-ésima base ω K I (i = 0, ···, N bDoF - 1) del espacio de elementos finitos tiene la j-ésima componente ω K ij
para j = 0, ···, N - 1.
El operador Π h se llama interpolador del elemento finito. Tenemos la identidad ω K
yo = Π h ω K yo .
Formalmente, el interpolador Π h se construye mediante la siguiente fórmula:
kPi − 1

Πhf= ∑ α k f j k (P p k ) ω Kyo k (13,1)


k=0

donde P p es un conjunto de puntos npP i,


En la fórmula (13 .1) , la lista p k , j k , i k depende solo del tipo de elemento finito (no de la
elemento), pero el coeficiente α k puede depender del elemento.
Ejemplo 1: con el elemento finito escalar clásico de Lagrange, tenemos kPi = npPi = NbOfNode y
• P p es el punto de los puntos nodales

• el α k = 1, porque tomamos el valor de la función en el punto P k

• p k = k, j k = k porque tenemos un nodo por función.

• j k = 0 porque N = 1

Ejemplo 2: El elemento finito de Raviart-Thomas:

https://translate.googleusercontent.com/translate_f 312/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
αK
RT0 h = {v ∈ H (div) / ∀K ∈ T h v | K (x, y) = ∣∣ βK + γ K | X y} (13,2)

Los grados de libertad son el flujo a través de un borde e de la malla, donde el flujo de la función
f: R 2 - → R 2 es ∫ mi
fn e , n e es la unidad normal del borde e (esto implica una orientación de todos los bordes
de la malla, por ejemplo, podemos usar la numeración global de los vértices del borde y simplemente vamos a
número pequeño a grande).
Para calcular este flujo, usamos una fórmula de cuadratura con un punto, el punto medio del borde.
Considere un triángulo T con tres vértices (a, b, c). Denotemos los números de los vértices por i a , i b , i c , y
definir los tres vectores de borde e 0 , e 1 , e 2 por sgn (i b −i c ) (b − c), sgn (i c −i a ) (c − a), sgn (i a −i b ) (a − b),
Las tres funciones básicas son:
sgn (yo b - yo c ) sgn (yo c - yo a ) sgn (yo a - yo b )
ωK (x - a), ω K (x - b), ω K (x - c), (13,3)
0= 2|T| 1= 2|T| 2= 2|T|

351

Página 352
352 CAPÍTULO 13. ADICIÓN DE UN NUEVO ELEMENTO FINITO

donde | T | es el área del triángulo T.


Entonces tenemos N = 2, kPi = 6; npPi = 3; y:

• P p = { b+c , a +2c , b +2a }


2

• α 0 = −e 0
2 , α 1 = e 0 1 , α 2 = −e 1 2, α 3 = e 1 1 , α 4 = −e 2 2 , α 5 = e 2 1 (efectivamente, el vector (−e m 2, e m1 )
es ortogonal al borde e m = (e m
1 , e m2 ) con una longitud igual al lado del borde o igual
a∫
e m 1).

• i k = {0,0,1,1,2,2},

• p k = {0,0,1,1,2,2}, j k = {0,1,0,1,0,1,0,1}.

13.2 ¿Qué clase agregar?


Agregue el archivo FE ADD.cpp en el directorio src / femlib, por ejemplo, primero para inicializar:

#include "error.hpp"
#include "rgraph.hpp"
usando el espacio de nombres std;
#include "RNM.hpp"
#include "fem.hpp"
#include "FESpace.hpp"
#include "AddNewFE.h"

espacio de nombres Fem2D {

Luego agregue una clase que derive para TypeOfFE público como:

clase TypeOfFE_RTortho: public TypeOfFE {public:


static int Data []; // algunos números
TypeOfFE_RTortho ():
TypeOfFE (0 + 3 + 0, // nb grado de libertad del elemento
2, // dimensión N de FE vectorial (1 si FE escalar)
Datos, // los datos de la matriz
1, // nb de subdivisión para trazar
1, // nb de elemento subfinito (generalmente 1)
6, // número kPi de coef para construir el interpolador ( 13.1 )
3, // número npP i del punto de integración para construir el interpolador
0 // una matriz para almacenar el coef α k para construir el interpolador
// aquí esta matriz no es constante, así que tenemos
// para reconstruir para cada elemento.
)
{
const R2 Pt [] = {R2 (0.5,0.5), R2 (0.0,0.5), R2 (0.5,0.0)};
// el conjunto de Point en ˆK
para (int p = 0, kk = 0; p <3; p ++) {
P_Pi_h [p] = Pt [p];

https://translate.googleusercontent.com/translate_f 313/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
parapij_alpha
(int j = 0;[kk
j <2;
++]j ++)
= IPJ (p, p, j); }} // definición de i k , p k , j k en ( 13.1 )

void FB (const bool * watdd, const Mesh & Th, const Triangle & K,
const R2 & PHat, RNMK_ & val) const;

Página 353
13.2. ¿QUÉ CLASE AGREGAR? 353

void Pi_h_alpha (const baseFElement & K, KN_ <doble> & v) const;

};

donde los datos de la matriz se forman con la concatenación de cinco matrices de tamaño NbDoF y una matriz de
tamaño N.
Esta matriz es:

int TypeOfFE_RTortho :: Data [] = {

// para cada gl 0,1,3:


3,4,5, // el apoyo del nodo del df
0,0,0, // el número del df en el nodo
0,1,2, // el nodo del df
0,0,0, // los gl provienen de los cuales FE (generalmente 0)
0,1,2, // que son de df en sub FE
0,0}; // para cada componente j = 0, N - 1 da la sub FE asociada

donde el soporte es un número 0,1,2 para soporte de vértice, 3,4,5 para soporte de borde y finalmente 6 para
soporte de elementos.
La función para definir la función ω K
yo , esta función devuelve el valor de todas las funciones básicas
o estas derivadas en la matriz val, calculadas en el punto PHat en el triángulo de referencia correspondiente
al punto R2 P = K (Phat); en el triángulo actual K.
El índice i, j, k de la matriz val (i, j, k) correspondiente a:

i es el número de función básica en el elemento finito i ∈ [0, N oF [

j es el valor del componente j ∈ [0, N [

k es el tipo de valor calculado f (P), dx (f) (P), dy (f) (P), ... i ∈ [0, último tipo de operación [. Observación
para la optimización, este valor se calcula solo si whatd [k] es verdadero y la numeración está definida
con

enum operatortype {op_id = 0,


op_dx = 1, op_dy = 2,
op_dxx = 3, op_dyy = 4,
op_dyx = 5, op_dxy = 5,
op_dz = 6,
op_dzz = 7,
op_dzx = 8, op_dxz = 8,
op_dzy = 9, op_dyz = 9
};
const int last_operatortype = 10;

La función de forma:

void TypeOfFE_RTortho :: FB (const bool * whatd, const Mesh & Th, const Triangle &
K,
const R2 y PHat, RNMK_ & val) const
{ //
R2 P (K (PHat));
R2 A (K [0]), B (K [1]), C (K [2]);
R l0 = 1-Px-Py, l1 = Px, l2 = Py;
afirmar (val.N ()> = 3);
afirmar (val.M () == 2);

https://translate.googleusercontent.com/translate_f 314/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 354
354 CAPÍTULO 13. ADICIÓN DE UN NUEVO ELEMENTO FINITO

val = 0;
Ra = 1 ./ (2 * K.area);
Ra0 = K.EdgeOrientation (0) * a;
R a1 = K.EdgeOrientation (1) * a;
R a2 = K.EdgeOrientation (2) * a;

// ------------
si (qué [op_id]) // valor de la función
{
afirmar (val.K ()> op_id);
RN_ f0 (val ('.', 0,0)); // valor primer componente
RN_ f1 (val ('.', 1,0)); // valor segundo componente
f1 [0] = (Px-Ax) * a0;
f0 [0] = - (Py-Ay) * a0;

f1 [1] = (Px-Bx) * a1;


f0 [1] = - (Py-By) * a1;

f1 [2] = (Px-Cx) * a2;


f0 [2] = - (Py-Cy) * a2;
}
// ----------------
si (qué [op_dx]) // valor del dx de la función
{
afirmar (val.K ()> op_dx);
val (0,1, op_dx) = a0;
val (1,1, op_dx) = a1;
val (2,1, op_dx) = a2;
}
si (qué [op_dy])
{
afirmar (val.K ()> op_dy);
val (0,0, op_dy) = -a0;
val (1,0, op_dy) = -a1;
val (2,0, op_dy) = -a2;
}

para ( int i = op_dy; i <last_operatortype; i ++)


si (qué [op_dx])
afirmar (op_dy);

La función para definir el coeficiente α k :

vacío TypeOfFE_RT :: Pi_h_alpha (const baseFElement & K, KN_ <double> & v) const
{
const Triángulo & T (KT);

para (int i = 0, k = 0; i <3; i ++)


{
R2 E (T.Edge (i));
R signe = T.EdgeOrientation (i);
v [k ++] = signe * Ey;
v [k ++] = - signe * Ex;
}

Página 355

https://translate.googleusercontent.com/translate_f 315/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
13.2. ¿QUÉ CLASE AGREGAR? 355

Ahora, solo necesitamos agregar un nuevo trabajo clave en FreeFem ++, bidireccional, con enlace estático o dinámico
así que al final del archivo, agregamos:

Con el enlace dinámico es muy simple (consulte la sección C del apéndice), solo agregue antes del final de FEM2d
espacio de nombres agregar:

estático TypeOfFE_RTortho The_TypeOfFE_RTortho; //


AddNewFE estático ("RT0Ortho", The_TypeOfFE_RTortho);
} // Espacio de nombres FEM2d

Pruebe con el comando "./load.link" en los ejemplos ++ - load / y vea BernardiRaugel.cpp o


Morley.cpp nuevos ejemplos de elementos finitos.

De lo contrario, con enlace estático (solo para expertos), agregue

// deja que las 2 variables globales


estático TypeOfFE_RTortho The_TypeOfFE_RTortho; //
// ----- el nombre en freefem ----
estático ListOfTFE typefemRTOrtho ("RT0Ortho", & The_TypeOfFE_RTortho); //

// el enlace con FreeFem ++ no funciona con la biblioteca estática .a


// FH así que agregue un nombre externo para llamar en init static FE
// (ver el final de FESpace.cpp)
void init_FE_ADD () {};
// --- final --
} // Espacio de nombres FEM2d

Para reforzar la carga de este nuevo elemento finito, tenemos que agregar las dos nuevas líneas cerca del final.
de archivos src / femlib / FESpace.cpp como:

// Problema correcto del enlace de la biblioteca estática con el nuevo archivo make
vacío init_static_FE ()
{ // lista de otros archivos FE. o
extern void init_FE_P2h ();
init_FE_P2h ();
extern void init_FE_ADD (); // nueva línea 1
init_FE_ADD (); // nueva línea 2
}

y ahora tienes que cambiar el archivo MAKE.


Primero, crear a expediente
FE ADD.cpp contendiente todo esto código, como en expediente
src / femlib / Element P2h.cpp, después de modificar Makefile.am agregando el nombre
de su archivo a la variable EXTRA DIST como:

# Makefile usando Automake + Autoconf


# ----------------------------------
# $ Id $

# Esto no está compilado como una biblioteca separada porque su


# No se han resuelto las interconexiones con otras bibliotecas.

Página 356
356 CAPÍTULO 13. ADICIÓN DE UN NUEVO ELEMENTO FINITO

EXTRA_DIST = BamgFreeFem.cpp BamgFreeFem.hpp CGNL.hpp CheckPtr.cpp \


ConjuguedGradrientNL.cpp DOperator.hpp Drawing.cpp Element_P2h.cpp \
Element_P3.cpp Element_RT.cpp fem3.hpp fem.cpp fem.hpp FESpace.cpp \
FESpace.hpp FESpace-v0.cpp FQuadTree.cpp FQuadTree.hpp gibbs.cpp \
glutdraw.cpp gmres.hpp MatriceCreuse.hpp MatriceCreuse_tpl.hpp \
https://translate.googleusercontent.com/translate_f 316/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
MeshPoint.hpp mortar.cpp mshptg.cpp QuadratureFormular.cpp \
QuadratureFormular.hpp RefCounter.hpp RNM.hpp RNM_opc.hpp RNM_op.hpp \
RNM_tpl.hpp FE_ADD.cpp

y hacerlo en el directorio raíz de freefem ++

autoreconf
./reconfigure
fabricar

Para la compilación de codewarrior, agregue el archivo en el proyecto y elimine la bandera en el enlazador de panal PPC
FreeFEm ++ Configuración del indicador de código de inicialización estático de zona muerta.

Página 357

Apéndice A

Tabla de notaciones

https://translate.googleusercontent.com/translate_f 317/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Aquí se explican las expresiones matemáticas y los comandos correspondientes de FreeFem ++.

A.1 Generalidades
δ ij delta de Kronecker (0 si i = j, 1 si i = j para enteros i, j)

∀ para todos

∃ existen

es decir, eso es

Ecuación diferencial parcial PDE (con condiciones de contorno)

∅ el conjunto vacío

N el conjunto de números enteros (a ∈ N ⇔ int a); "Int" significa un entero largo dentro de FreeFem ++

R el conjunto de números reales (a ∈ R ⇔ real a); doble dentro de FreeFem ++

C el conjunto de números complejos (a ∈ C ⇔ complejo a); complejo¡doble¿

R d espacio euclidiano d-dimensional

A.2 Conjuntos, mapeos, matrices, vectores


Sean E, F, G tres conjuntos y un subconjunto de E.

{x ∈ E | P} el subconjunto de E que consta de los elementos que poseen la propiedad P

E ∪ F el conjunto de elementos pertenecientes a E o F

E ∩ F el conjunto de elementos pertenecientes a E y F

E \ A el conjunto {x ∈ E | x ∈ A}

E + FE ∪ F con E ∩ F = ∅

357

Página 358
358 APÉNDICE A. TABLA DE NOTAS

E × F el producto cartesiano de E y F

E n la n-ésima potencia de E (E 2 = E × E, E n = E × E n − 1 )

f: E → F la forma de mapeo E en F, es decir, E x ↦ → f (x) ∈ F

I E o I el mapeo de identidad en E, es decir, I (x) = x ∀x ∈ E

f ◦ g para f: F → G yg: E → F, E x ↦ → (f ◦ g) (x) = f (g (x)) ∈ G (ver Sección ??)

f | A la restricción de f: E → F al subconjunto A de E

{a k } vector de columna con componentes a k

(a k ) vector fila con componentes a k

(a k ) T denota la transpuesta de una matriz (a k ), y es {a k }

{a ij } matriz con componentes a ij , y (a ij ) T = (a ji )

https://translate.googleusercontent.com/translate_f 318/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

A.3 Números
Para dos números reales a, b

[a, b] es el intervalo {x ∈ R | a ≤ x ≤ b}

] a, b] es el intervalo {x ∈ R | a <x ≤ b}

[a, b [es el intervalo {x ∈ R | a ≤ x <b}

] a, b [es el intervalo {x ∈ R | a <x <b}

A.4 Cálculo diferencial


∂f / ∂x la derivada parcial de f: R d → R con respecto ax ( dx (f))

∇f el gradiente de f: Ω → R, es decir, ∇f = (∂f / ∂x, ∂f / ∂y)

divf o ∇.f la divergencia de f: Ω → R d , es decir, divf = ∂f 1 / ∂x + ∂f 2 / ∂y

∆f el laplaciano de f: Ω → R, es decir, ∆f = ∂ 2 f / ∂x 2 + ∂ 2 f / ∂y 2

Página 359
A.5. Mallas 359

A.5 Mallas
Ω generalmente denota un dominio en el que se define PDE

Γ denota el límite de Ω, es decir, Γ = ∂Ω ( borde de palabra clave , consulte la Sección 5.1.2 )

L h la triangulación de Ω, es decir, el conjunto de triángulos T k , donde h representa el tamaño de malla (palabra clave
mesh , buildmesh , consulte la Sección 5 )

n t el número de triángulos en T h (obtenga Th.nt, vea "mesh.edp")

Ω h denota el dominio aproximado Ω h = ∪ n t


k=1 T k de Ω. Si Ω es un dominio poligonal, entonces
será Ω = Ω h

Γ h el límite de Ω h

n v el número de vértices en T h (obtener por Th.nv)

n ser el número de elemento de frontera en T h (obtener por Th.nbe)

| Ω h | la medida (área o volumen) en T h (obtener por Th. medida)

| ∂Ω h | la medida del borde (longitud o área) en T h (obtener Th.bordermeasure)

h min el tamaño de borde mínimo de T h (obtener por Th.hmin)

h max el tamaño máximo del borde de T h (obtener por Th.hmax)

[q i q j ] el segmento que conecta q i y q j

q k , q k , q k los vértices de un triángulo T k con dirección anti-reloj (obtén la coordenada de q k


1 2 3 j

https://translate.googleusercontent.com/translate_f 319/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
por (Th [k-1] [j-1] .x, Th [k-1] [j-1] .y))
I Ω el conjunto {i ∈ N | q yo ∈ Γ h }

A.6 Espacios de elementos finitos


{ ∣ ∫ }
L 2 (Ω) el conjunto w (x, y) ∣∣ | w (x, y) | 2 dxdy <∞
∣ Ω

(∫ ) 1/2
norma: w 0, Ω = | w (x, y) | 2 dxdy
Ω


producto escalar: (v, w) = vw
Ω

{ ∣ ∫ }
H 1 (Ω) el conjunto w ∈ L 2 (Ω) ∣∣ (| ∂w / ∂x | 2 + | ∂w / ∂y | 2 ) dxdy <∞
∣ Ω

norma: w 1, Ω = (w 2 ) 1/2
0, Ω + ∇u 2 0.Ω

Página 360
360 APÉNDICE A. TABLA DE NOTAS

{ ∣ ∫ ∂ |α|w }
H m (Ω) el conjunto w ∈ L 2 (Ω) ∣∣ ∈ L 2 (Ω) ∀α = (α 1 , α 2 ) ∈ N 2 , | α | = α 1 + α 2
∣ Ω ∂x α ∂y α
1 2

∑ ∫
producto escalar: (v, w) 1, Ω = D α vD α w
Ω
| α | ≤m

H1
0 (Ω) el conjunto {w ∈ H 1 (Ω) | u = 0 en Γ}
L 2 (Ω) 2 indica L 2 (Ω) × L 2 (Ω), y también H 1 (Ω) 2 = H 1 (Ω) × H 1 (Ω)

V h denota el espacio de elementos finitos creado por " fespace Vh (Th, *)" en FreeFem ++ (ver
Sección 6 para "*")

Π h f la proyección de la función f en V h (" func f = xˆ2 * yˆ3; Vh v = f;" significa


v = Π h f)

{v} para la función FE v en V h significa el vector columna (v 1 , ···, v M ) T si v = v 1 φ 1 + ··· + v M φ M ,


que se muestra por “ fespace Vh (Th, P2); Vh v; cout << v [] << endl; ”

https://translate.googleusercontent.com/translate_f 320/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 361

apéndice B

Gramática

B.1 La gramática del bisonte

comienzo: entrada ENDOFFILE ;

aporte: instrucciones;

instrucciones: instrucción
| instrucciones instrucción ;

list_of_id_args:
| identificación
| id '=' no_comma_expr
| ID de FESPACE
| type_of_dcl id
| type_of_dcl '&' id
| '[' list_of_id_args ']'
| list_of_id_args ',' id
| list_of_id_args ',' '[' list_of_id_args ']'
| list_of_id_args ',' id '=' no_comma_expr
| list_of_id_args ',' ID de FESPACE
| list_of_id_args ',' type_of_dcl id
| list_of_id_args ',' type_of_dcl '&' id;

list_of_id1: id
| list_of_id1 ',' id ;

id: ID | FESPACE ;

list_of_dcls: IDENTIFICACIÓN
| ID '=' no_comma_expr

https://translate.googleusercontent.com/translate_f 321/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
| ID '(' lista_parámetros ')'
| lista_de_dcls ',' lista_de_dcls;

lista_parámetros:
no_set_expr
| ID DE FESPACE
| ID '=' no_set_expr

361

Página 362
362 APÉNDICE B. GRAMÁTICA

| lista_parámetros ',' no_set_expr


| lista_parámetros ',' id '=' no_set_expr;

type_of_dcl: TIPO
| TIPO '[' TIPO ']';

ID_space:
IDENTIFICACIÓN
| ID '[' no_set_expr ']'
| ID '=' no_set_expr
| '[' list_of_id1 ']'
| '[' list_of_id1 ']' '[' no_set_expr ']'
| '[' list_of_id1 ']' '=' no_set_expr;

ID_array_space:
ID '(' no_set_expr ')'
| '[' lista_de_id1 ']' '(' no_set_expr ')';

fespace: FESPACE ;

spaceIDa: ID_array_space
| spaceIDa ',' ID_array_space;

spaceIDb: ID_espacio
| spaceIDb ',' ID_space;

spaceIDs: fespace spaceIDb


| fespace '[' TYPE ']' spaceIDa ;

fespace_def: ID '(' lista_parámetros ')';

fespace_def_list: fespace_def
| fespace_def_list ',' fespace_def;

declaración: type_of_dcl list_of_dcls ';'


| 'fespace' fespace_def_list ';'
| spaceIDs ';'
| ID DE FUNCIÓN '=' Expr ';'
| FUNCIÓN type_of_dcl ID '(' list_of_id_args ')' '{'
instrucciones'}'
| ID DE FUNCIÓN '(' list_of_id_args ')' '=' no_comma_expr ';'
;

empezar: '{' ;
final: '}';

en bucle: 'por' ;
while_loop: 'mientras';

instrucción: ';'
| 'incluir' STRING
| "cargar" STRING
| Expr ';'
| declaración
| instrucción for_loop '(' Expr ';' Expr ';' Expr ')'

https://translate.googleusercontent.com/translate_f 322/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 363
B.1. LA GRAMÁTICA DE BISON 363

| while_loop '(' Expr ')' instrucción


| 'si' '(' Expr ')' instrucción
| 'si' '(' Expr ')' instrucción instrucción ELSE
| comenzar las instrucciones terminar
| ID de 'borde' border_expr
| 'frontera' IDENTIFICACIÓN
'[' matriz ']' ';'
| 'rotura' ';'
| 'Seguir' ';'
| 'return' Expr ';' ;

bornes: '(' ID '=' Expr ',' Expr ')';

border_expr: instrucción llevada;

Expr: no_comma_expr
| Expr ',' Expr;

unop: '-'
| '+'
| '!'
| '++'
| '-';

no_comma_expr:
no_set_expr
| no_set_expr '=' no_comma_expr
| no_set_expr '+ =' no_comma_expr
| no_set_expr '- =' no_comma_expr
| no_set_expr '* =' no_comma_expr
| no_set_expr '/ =' no_comma_expr
| no_set_expr '. * =' no_comma_expr
| no_set_expr './=' no_comma_expr;

no_set_expr:
no_ternary_expr
| no_ternary_expr '?' no_set_expr ':' no_set_expr;

no_ternary_expr:
unary_expr
| no_ternary_expr '*' no_ternary_expr
| no_ternary_expr '. *' no_ternary_expr
| no_ternary_expr './' no_ternary_expr
| no_ternary_expr '/' no_ternary_expr
| no_ternary_expr '%' no_ternary_expr
| no_ternary_expr '+' no_ternary_expr
| no_ternary_expr '-' no_ternary_expr
| no_ternary_expr '<<' no_ternary_expr
| no_ternary_expr '>>' no_ternary_expr
| no_ternary_expr 'y' no_ternary_expr
| no_ternary_expr '&&' no_ternary_expr
| no_ternary_expr '|' no_ternary_expr
| no_ternary_expr '||' no_ternary_expr

https://translate.googleusercontent.com/translate_f 323/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 364
364 APÉNDICE B. GRAMÁTICA

| no_ternary_expr '<' no_ternary_expr


| no_ternary_expr '<=' no_ternary_expr
| no_ternary_expr '>' no_ternary_expr
| no_ternary_expr '> =' no_ternary_expr
| no_ternary_expr '==' no_ternary_expr
| no_ternary_expr '! =' no_ternary_expr;

sub_script_expr:
no_set_expr
| ':'
| no_set_expr ':' no_set_expr
| no_set_expr ':' no_set_expr ':' no_set_expr;

parámetros:
| no_set_expr
| FESPACE
| id '=' no_set_expr
| sub_script_expr
| parámetros ',' FESPACE
| parámetros ',' no_set_expr
| parámetros ',' id '=' no_set_expr;

formación: no_comma_expr
| matriz ',' no_comma_expr;

unary_expr:
pow_expr
| unop pow_expr% prec UNARY;

pow_expr: primario
| primario 'ˆ' unary_expr
| primario '_' unary_expr
| primario '' ; // transponer

primario:
IDENTIFICACIÓN
| LNUM
| DNUM
| CNUM
| CUERDA
| primario '(' parámetros ')'
| primario '[' Expr ']'
| primario '[' ']'
| primario '.' IDENTIFICACIÓN
| primario '++'
| primario '--'
| TIPO '(' Expr ')';
| '(' Expr ')'
| '[' matriz ']';

Página 365
B.2. LOS TIPOS DE IDIOMAS Y EL REPARTO 365

B.2 Los tipos de lenguajes y reparto

B.3 Todos los operadores


https://translate.googleusercontent.com/translate_f 324/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

- CG, escriba: <TypeSolveMat>


- Cholesky, escriba: <TypeSolveMat>
- Crout, escriba: <TypeSolveMat>
- GMRES, escriba: <TypeSolveMat>
- LU, escriba: <TypeSolveMat>
- LinearCG, tipo: <Polymorphic> operador ():
( <largo>: <Polimórfico>, <KN <doble> *>, <KN <doble> *>)

- N, tipo: <Fem2D :: R3>


- NoUseOfWait, escriba: <bool *>
- P, tipo: <Fem2D :: R3>
- P0, tipo: <Fem2D :: TypeOfFE>
- P1, tipo: <Fem2D :: TypeOfFE>
- P1nc, tipo: <Fem2D :: TypeOfFE>
- P2, tipo: <Fem2D :: TypeOfFE>
- RT0, tipo: <Fem2D :: TypeOfFE>
- RTmodif, tipo: <Fem2D :: TypeOfFE>
- abs, tipo: operador <Polimórfico> ():
( <doble>: <doble>)

- acos, tipo: <Polimórfico> operador ():


( <doble>: <doble>)

- acosh, tipo: <Polimórfico> operador ():


( <doble>: <doble>)

- adaptmesh, tipo: <Polymorphic> operador ():


( <Fem2D :: Malla>: <Fem2D :: Malla> ...)

- agregar, escriba: <std :: ios_base :: openmode>


- asin, tipo: <Polimórfico> operador ():
( <doble>: <doble>)

- asinh, tipo: <Polimórfico> operador ():


( <doble>: <doble>)

- atan, tipo: <Polimórfico> operador ():


( <doble>: <doble>)
( <doble>: <doble>, <doble>)

- atan2, tipo: <Polimórfico> operador ():


( <doble>: <doble>, <doble>)

- atanh, tipo: <Polimórfico> operador ():


( <doble>: <doble>)

Página 366
366 APÉNDICE B. GRAMÁTICA

- buildmesh, tipo: <Polymorphic> operador ():


( <Fem2D :: Malla>: <E_BorderN>)

- buildmeshborder, tipo: <Polimórfico> operador ():


( <Fem2D :: Malla>: <E_BorderN>)

- cin, escriba: <istream>


- reloj, tipo: <Polimórfico>
( <doble>: )

https://translate.googleusercontent.com/translate_f 325/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
- conj, tipo: <Polimórfico> operador ():
( <complejo>: <complejo>)

- convecto, tipo: <Polimórfico> operador ():


( <doble>: <E_Array>, <doble>, <doble>)

- cos, tipo: <Polimórfico> operador ():


( <doble>: <doble>)
( <complejo>: <complejo>)

- cosh, tipo: <Polimórfico> operador ():


( <doble>: <doble>)
( <complejo>: <complejo>)

- cout, escriba: <ostream>


- dumptable, tipo: <Polymorphic> operador ():
( <ostream>: <ostream>)

- dx, tipo: <Polimórfico> operador ():


( <LinearComb <MDroit, C_F0 >>: <LinearComb <MDroit, C_F0 >>)
( <doble>: <estándar :: par <FEbase <doble> *, int >>)
( <LinearComb <MGauche, C_F0 >>: <LinearComb <MGauche, C_F0 >>)

- dy, tipo: <Polimórfico> operador ():


( <LinearComb <MDroit, C_F0 >>: <LinearComb <MDroit, C_F0 >>)
( <doble>: <estándar :: par <FEbase <doble> *, int >>)
( <LinearComb <MGauche, C_F0 >>: <LinearComb <MGauche, C_F0 >>)

- endl, escriba: <char>


- ejecutivo, tipo: <Polimórfico> operador ():
( <largo>: <cadena>)

- salir, escriba: <Polymorphic> operator ():


( <largo>: <largo>)

- exp, escriba: <Polimórfico> operador ():


( <doble>: <doble>)
( <complejo>: <complejo>)

Página 367
B.3. TODOS LOS OPERADORES 367

- falso, escriba: <bool>


- imag, tipo: <Polimórfico> operador ():
( <doble>: <complejo>)

- int1d, tipo: <Polimórfico> operador ():


( <CDomainOfIntegration>: <Fem2D :: Malla> ...)

- int2d, tipo: <Polimórfico> operador ():


( <CDomainOfIntegration>: <Fem2D :: Malla> ...)

- intalledges, tipo: <Polymorphic>


operador (:
( <CDomainOfIntegration>: <Fem2D :: Malla> ...)

- salto, tipo: <Polimórfico>


operador (:
( <LinearComb <MDroit, C_F0 >>: <LinearComb <MDroit, C_F0 >>)
( <doble>: <doble>)
( <complejo>: <complejo>)

https://translate.googleusercontent.com/translate_f 326/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
( <LinearComb <MGauche, C_F0 >>: <LinearComb <MGauche, C_F0 >>)

- etiqueta, escriba: <largo *>


- registro, tipo: <Polimórfico> operador ():
( <doble>: <doble>)
( <complejo>: <complejo>)

- log10, tipo: <Polimórfico> operador ():


( <doble>: <doble>)

- max, tipo: <Polimórfico> operador ():


( <doble>: <doble>, <doble>)
( <largo>: <largo>, <largo>)

- significa, tipo: <Polimórfico>


operador (:
( <doble>: <doble>)
( <complejo>: <complejo>)

- min, tipo: operador <Polimórfico> ():


( <doble>: <doble>, <doble>)
( <largo>: <largo>, <largo>)

- movemesh, tipo: <Polimórfico> operador ():


( <Fem2D :: Malla>: <Fem2D :: Malla>, <E_Array> ...)

- norma, tipo: <Polimórfica>


operador (:
( <doble>: <estándar :: complejo <doble>>)

- nuTriangle, escriba: <largo>

Página 368
368 APÉNDICE B. GRAMÁTICA

- nuEdge, escriba: <largo>


- activado, escriba: <Polimórfico> operador ():
( <BC_set <doble>>: <largo> ...)

- otro lado, tipo: <Polimórfico>


operador (:
( <LinearComb <MDroit, C_F0 >>: <LinearComb <MDroit, C_F0 >>)
( <LinearComb <MGauche, C_F0 >>: <LinearComb <MGauche, C_F0 >>)

- pi, escriba: <doble>


- trama, tipo: <Polimórfica> operador ():
( <largo>: ...)

- pow, tipo: <Polimórfico> operador ():


( <doble>: <doble>, <doble>)
( <complejo>: <complejo>, <complejo>)

- qf1pE, escriba: <Fem2D :: QuadratureFormular1d>


- qf1pT, escriba: <Fem2D :: QuadratureFormular>
- qf1pTlump, tipo: <Fem2D :: QuadratureFormular>
- qf2pE, escriba: <Fem2D :: QuadratureFormular1d>
- qf2pT, escriba: <Fem2D :: QuadratureFormular>
- qf2pT4P1, escriba: <Fem2D :: QuadratureFormular>
- qf3pE, escriba: <Fem2D :: QuadratureFormular1d>
- qf5pT, escriba: <Fem2D :: QuadratureFormular>

https://translate.googleusercontent.com/translate_f 327/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
- readmesh, tipo: <Polymorphic> operador ():
( <Fem2D :: Malla>: <cadena>)

- real, tipo: <Polimórfico> operador ():


( <doble>: <complejo>)

- región, tipo: <largo *>


- savemesh, escriba: <Polymorphic> operator ():
( <Fem2D :: Malla>: <Fem2D :: Malla>, <cadena> ...)

- pecado, tipo: <Polimórfico> operador ():


( <doble>: <doble>)
( <complejo>: <complejo>)

- sinh, tipo: <Polimórfico> operador ():


( <doble>: <doble>)
( <complejo>: <complejo>)

- sqrt, tipo: <Polimórfico> operador ():


( <doble>: <doble>)
( <complejo>: <complejo>)

- cuadrado, tipo: <Polimórfico> operador ():


( <Fem2D :: Malla>: <largo>, <largo>)

Página 369
B.3. TODOS LOS OPERADORES 369

( <Fem2D :: Malla>: <largo>, <largo>, <E_Array>)

- bronceado, tipo: <Polimórfico> operador ():


( <doble>: <doble>)

- verdadero, escriba: <bool>


- trunc, tipo: <Polimórfico> operador ():
( <Fem2D :: Malla>: <Fem2D :: Malla>, <bool>)

- verbosidad, tipo: <largo *>


- espera, escribe: <bool *>
- x, escriba: <doble *>
- y, escriba: <doble *>
- z, escriba: <doble *>

https://translate.googleusercontent.com/translate_f 328/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 370
370 APÉNDICE B. GRAMÁTICA

https://translate.googleusercontent.com/translate_f 329/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 371

Apéndice C

Enlace dinámico

Ahora, es posible agregar funcionalidades integradas en FreeFem ++ en los tres entornos


nents Linux, Windows y MacOS X 10.3 o más reciente. Es una buena idea probar primero el ejemplo
load.edp en el directorio example ++ - load.
Necesitará instalar un compilador c ++ (generalmente compilador g ++ / gcc) para compilar su
función.

Windows Instale el entorno cygwin o mingw

MacOs Instale las herramientas de desarrollo xcode en el DVD de Apple

Linux / Unix Instale el compilador correcto (gcc por ejemplo)

Ahora, suponga que se encuentra en una ventana de shell (una ventana cygwin en Windows) en el
ejemplo de directorio ++ - cargar. Observar que en el subdirectorio incluir están todos los
FreeFem ++ incluye archivo para hacer el enlace con FreeFem ++.

Nota C.1 Si intenta cargar dinámicamente un archivo con el comando load "xxx"

• En Unix (Linux o MacOs), el archivo xxx.so se cargará, por lo que debe


ya sea en el directorio de búsqueda de la rutina dlopen (ver la variable de entorno
$ LD_LIBRARY_PATH o en el directorio actual, y el sufijo ".so" o el prefijo
"./" se agrega automáticamente.

• En Windows, se cargará el archivo xxx.dll, por lo que debe estar en loadLibary


directorio de búsqueda que incluye el directorio de la aplicación,

La compilación de su módulo: el script ff-c ++ compila y hace el enlace con


FreeFem ++, pero tenga cuidado, el script no tiene forma de saber si intenta compilar para un
entorno Windows puro o para un entorno cygwin para construir el módulo de carga bajo
cygwin debe agregar el parámetro -cygwin.

C.1 Un primer ejemplo myfunction.cpp


Lo siguiente define una nueva función llamada myfunction sin parámetro, pero usando el

https://translate.googleusercontent.com/translate_f 330/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
x, y valor actual.

371

Página 372
372 APÉNDICE C. VÍNCULO DINÁMICO

#include <iostream>
#include <cfloat>
usando el espacio de nombres std;
#include "error.hpp"
#include "AFunction.hpp"
#include "rgraph.hpp"
#include "RNM.hpp"
#include "fem.hpp"
#include "FESpace.hpp"
#include "MeshPoint.hpp"

usando el espacio de nombres Fem2D;


doble myfunction (pila de pila)
{
// para obtener datos de FreeFem ++
MeshPoint & mp = * MeshPointStack (pila); // la estructura para obtener x, y, normal,
valor
doble x = mp.Px; // obtener el valor x actual
doble y = mp.Py; // obtener el valor de y actual
// cout << "x =" << x << "y =" << y << endl;
devolver sin (x) * cos (y);
}

Ahora el problema es construir el enlace con FreeFem ++, para hacer eso necesitamos dos clases,
uno para llamar a la función myfunction
Toda expresión evaluable de FreeFem ++ debe ser una estructura / clase C ++ que se derive de E F0.
Por defecto esta expresión no depende de la posición de la malla, pero si derivan de
E F0mps la expresión depende de la posición de la malla, y para más detalles ver [ 17] .

// Una clase construye el enlace con FreeFem ++


// generalmente esta clase ya está en AFunction.hpp
// pero desafortunadamente, no tengo una función simple sin parámetro
// en FreeFem ++ dependiendo de la malla,
plantilla <clase R>
class OneOperator0s: public OneOperator {

// la clase que definió una evaluó una nueva función


// Debe desviarse de E F0 si es independiente de la malla
// o de E F0mps si depende de la malla
clase E_F0_F: public E_F0mps {public:
typedef R (* func) (Pila de pila);
func f; // el puntero a la función mi función
E_F0_F (func ff): f (ff) {}
// la evaluación del operador en FreeFem ++
Operador AnyType () (Pila de pila) const { return SetAny <R> (f (pila));}

};

typedef R (* func) (Pila);


func f;
publico :
// la función que construye el código de bytes FreeFem ++
E_F0 * código ( const basicAC_F0 &) const { return new E_F0_F (f);}
// el constructor para decir ff es una función sin parámetro

https://translate.googleusercontent.com/translate_f 331/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 373
C.1. UN PRIMER EJEMPLO MYFUNCTION.CPP 373

// y devolviendo una R
OneOperator0s (func ff): OneOperator (map_type [typeid (R) .name ()]), f (ff) {}
};

Para finalizar debemos agregar esta nueva función en la tabla FreeFem ++, para ello incluimos:

void init () {
Global.Add ("mifunción", "(", nuevo OneOperator0s <doble> (mifunción));
}
LOADFUNC (init);

Se llamará automáticamente en el momento del módulo de carga.

Para compilar y vincular, use el script ff-c ++:

% ff-c ++ myfunction.cpp
g ++ -c -g -Incluido myfunction.cpp
g ++ -bundle -undefined dynamic_lookup -g myfunction.o -o ./myfunction.dylib

Para, pruebe el ejemplo simple en Linux o MacOS, haga

% FreeFem ++ - nw load.edp
- FreeFem ++ v 1.4800028 (fecha martes 4 de octubre 11:56:46 CEST 2005)
archivo: load.edp
Carga: lg_fem lg_mesh valor propio UMFPACK
1: // Ejemplo de carga de función dinámica
2: // --------------------------------
3: // Id: freefem + + doc.tex, v1.1102010 / 06/0411: 27: 24hechtExp
4:
5: carga "myfunction"

carga: mi función
cargar: dlopen (./ myfunction) = 0xb01cc0

6: malla Th = cuadrado (5,5);


7: espacio libre Vh (Th, P1);
8: Vh uh = mi función (); // advertencia no olvides ()
9: cout << uh []. Min << "" << uh []. Max << endl;
10: pila de tamaños + 1024 = 1240 (216)

- malla cuadrada: nb vértices = 36, nb triángulos = 50, nb bordes límite


20
Nb de aristas en morteros = 0
Número de aristas en el límite = 20, neb = 20
Número de nodos = 36
Nb de DF = 36
0 0.841471
veces: compilar 0.05s, ejecución -3.46945e-18s
CodeAlloc: nb ptr 1394, tamaño: 71524
Bien: en un fini Normalement

En Windows, inicie FreeFem ++ con el mouse (o ctrl O) en el ejemplo.

Página 374
374 APÉNDICE C. VÍNCULO DINÁMICO

C.2 Ejemplo: Transformada rápida discreta de Fourier

https://translate.googleusercontent.com/translate_f 332/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Esto agregará FFT a FreeFem ++, tomado de http://www.fftw.org/. Descargar
e instale bajo descargar / incluir solo vaya a descargar / fftw y trymake.

La 1D dfft (transformada rápida discreta de Fourier) para una matriz simple f de tamaño n está definida por el
siguiente fórmula
n−1

dfft (f, ε) k = ∑ f yo e ε2πikj / n


j=0

El DFFT 2D para una matriz de tamaño N = n × m es

m−1 n−1

dfft (f, m, ε) k + nl = ∑ ∑ f yo + nj e ε2πi (kj / n + lj / m)


j=0 j=0

Observación: el valor n viene dado por el tamaño (f) / m, y la numeración es el orden de las filas principales.

Entonces, el DFFT
√ discreto clásico es ˆf = dfft (f, −1) / ny la dFFT inversa f =
dfft (ˆf, 1) / norte

Observación: el operador 2D de Laplace es

m−1 n−1

f (x, y) = 1 / ∑
norte ∑ fˆyo + nj e ε2πi (xj + yj)
j=0 j=0

y tenemos
f k + nl = f (k / n, l / m)

Entonces
∆f
̂ kl = - ((2π) 2 ((˜k) 2 + (˜l) 2 )) f kl

donde ˜k = k si k ≤ n / 2 si no ˜k = k - n y ˜l = l si l ≤ m / 2 si no ˜l = l - m.
Y para tener una función real, necesitamos que todos los modos sean simétricos alrededor de cero, por lo que nym
debe ser extraño.

Compilar para construir una nueva biblioteca

% ff-c ++ dfft.cpp ../download/install/lib/libfftw3.a -I ../ descargar / instalar / incluir


exportar MACOSX_DEPLOYMENT_TARGET = 10.3
g ++ -c -Iinclude -I ../ descargar / instalar / incluir dfft.cpp
g ++ -bundle -undefined dynamic_lookup dfft.o -o ./dfft.dylib ../download/install/lib/libfftw3.a

Probar ,

- FreeFem ++ v 1.4800028 (fecha lunes 10 de octubre 16:53:28 EEST 2005)


archivo: dfft.edp
Carga: lg_fem cadna lg_mesh valor propio UMFPACK
1: // Ejemplo de carga de función dinámica
2: // --------------------------------
3: // Id: freefem + + doc.tex, v1.1102010 / 06/0411: 27: 24hechtExp
4: // Transformada discreta rápida de Fourier
5: // -------------------------------
6: carga "dfft" lood: init dfft

Página 375
C.2. EJEMPLO: TRANSFORMACIÓN RÁPIDA DISCRETA DE FOURIER 375

carga: dlopen (dfft.dylib) = 0x2b0c700

7:
8: int nx = 32, ny = 16, N = nx * ny;
9: // advirtiendo que el espacio de Fourier no es exactamente el cuadrado de unión debido a
condiciones periódicas
10: malla Th = cuadrado (nx-1, ny-1, [(nx-1) * x / nx, (ny-1) * y / ny]);
11: // en guerra la numeración es de los vértices (x, y) es
12: // dado por i = x / nx + nx ∗ y / ny
13:

https://translate.googleusercontent.com/translate_f 333/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
14:
15 :espacio libre Vh (Th, P1);
16: func f1 = cos (2 * x * 2 * pi) * cos (3 * y * 2 * pi);
17: Vh <complejo> u = f1, v;
18: Vh w = f1;
19:
20:
21: Vh ur, ui;
22: // en dfft la matriz n, m está en orden de fila mayor ann matriz n, m es
23: // almacenar j + m * i (la transposición de la numeración cuadrada)
24: v [] = dfft (u [], ny, -1);
25: u [] = dfft (v [], ny, + 1);
26: u [] / = complejo (N);
27: v = f1-u;
28: cout << "diff =" << v []. Max << "" << v []. Min << endl;
29: afirmar (norma (v []. Max) <1e-10 && norma (v []. Min) <1e-10);
30: // ------- un ejemplo más difícil ----
31: // Lapacien en FFT
32: // −∆u = f con condición biperiódica
33: func f = cos (3 * 2 * pi * x) * cos (2 * 2 * pi * y); //
34: func ue = + (1 ./ (cuadrado (2 * pi) * 13.)) * Cos (3 * 2 * pi * x) * cos (2 * 2 * pi * y); //

35: Vh < complejo > ff = f;


36: Vh < complejo > fhat;
37: fhat [] = dfft (ff [], ny, -1);
38:
39: Vh < complejo > wij;
40: // advertencia de hecho tomamos el modo entre -nx / 2, nx / 2 y -ny / 2, ny / 2
41: // gracias al operador?:
42: wij = cuadrado (2. * pi) * (cuadrado ((x <0.5? X * nx: (x-1) * nx))
+ cuadrado ((y <0,5? y * ny: (y-1) * ny)));
43: wij [] [0] = 1e-5; // para eliminar div / 0
44: fhat [] = fhat [] ./ wij []; //
45: u [] = dfft (fhat [], ny, 1);
46: u [] / = complejo (N);
47: ur = real (u); // la solución
48: w = real (ue); // la solución exacta
49: plot (w, ur, value = 1, cmm = "ue ", espera = 1);
50: w [] - = ur []; // arreglo sub
51: err real = abs (w []. Max) + abs (w []. Min);
52: cout << "err =" << err << endl;
53: afirmar (err <1e-6);
54: pila de tamaños + 1024 = 3544 (2520)

---------- CheckPtr: ----- ejecución de inicio ------ NbUndelPtr 2815 Alloc: 111320
NbPtr 6368

Página 376
376 APÉNDICE C. VÍNCULO DINÁMICO

- malla cuadrada: nb vértices = 512, nb triángulos = 930, nb bordes límite


92
Nb de aristas en morteros = 0
Número de aristas en el límite = 92, neb = 92
Número de nodos = 512
Nb de DF = 512
0x2d383d8 -1 16 512 n: 16 m: 32
dfft 0x402bc08 = 0x4028208 n = 16 32 signo = -1
--- --- --- 0x2d3ae08 1 16512 n: 16 m: 32
dfft 0x4028208 = 0x402bc08 n = 16 32 signo = 1
--- --- --- diff = (8.88178e-16,3.5651e-16) (-6.66134e-16, -3.38216e-16)
0x2d3cfb8 -1 16512 n: 16 m: 32
dfft 0x402de08 = 0x402bc08 n = 16 32 signo = -1
--- --- --- 0x2d37ff8 1 16512 n: 16 m: 32
dfft 0x4028208 = 0x402de08 n = 16 32 signo = 1
--- --- --- err = 3.6104e-12
veces: compila 0.13s, ejecución 2.05s
---------- CheckPtr: ----- finalizar la ejecución - ------ NbUndelPtr 2815 Alloc:
111320 NbPtr 26950

https://translate.googleusercontent.com/translate_f 334/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
CodeAlloc: nb ptr 1693, tamaño: 76084
Bien: en un fini Normalement
CheckPtr: el número de puntero de recuperación es 2748 último 114
CheckPtr: memoria máxima utilizada 228.531 kbytes Recuperación de memoria
105020

C.3 Módulo de carga para el método de volumen finito P0-P1 de Dervieux


el archivo edp asociado es examples ++ - load / convect dervieux.edp

// Implementación de P1-P0 FVM-FEM


// -------------------------------------------------- -------------------
// Id: freefem + + doc.tex, v1.1102010 / 06/0411: 27: 24hechtExp
// compilar y vincular con ff-c ++ mat dervieux.cpp (es decir, el nombre del archivo
sin .cpp)
#include <iostream>
#include <cfloat>
#include <cmath>
usando el espacio de nombres std;
#include "error.hpp"
#include "AFunction.hpp"
#include "rgraph.hpp"
#include "RNM.hpp"
// eliminar el problema de incluir
#undef HAVE_LIBUMFPACK
#undef HAVE_CADNA
#include "MatriceCreuse_tpl.hpp"
#include "MeshPoint.hpp"
#include "lgfem.hpp"
#include "lgsolver.hpp"
#include "problem.hpp"

clase MatrixUpWind0: public E_F0mps { public :


typedef Matrice_Creuse <R> * Resultado;

Página 377
C.3. MÓDULO DE CARGA PARA EL MÉTODO DE VOLUMEN FINITO P0-P1 DE DERVIEUX 377

Expresión emat, expTh, expc, expu1, expu2;


MatrixUpWind0 ( const basicAC_F0 y argumentos)
{
args.SetNameParam ();
emat = args [0]; // la expresión matricial
expTh = a <pmesh> (args [1]); // a la expresión para obtener la malla
expc = CastTo <doble> (args [2]); // la expresión para obtener c (debe ser un
doble)
// una expresión de matriz [a, b]
const E_Array * a = dynamic_cast <const E_Array *> ((Expresión) args [3]);
if (a-> size ()! = 2) CompileError ("sintaxis: MatrixUpWind0 (Th, rhi, [u1, u2])");
int err = 0;
expu1 = CastTo < doble > ((* a) [0]); // primer exp de la matriz (debe ser un
doble)
expu2 = CastTo < doble > ((* a) [1]); // segundo exp de la matriz (debe ser un
doble)
}

˜MatrixUpWind0 () {
}

estático ArrayOfaType typeargs ()


{ return ArrayOfaType (atype <Matrice_Creuse <R> *> (),
atype <pmesh> (), atype <double> (), atype <E_Array> ());}
static E_F0 * f ( const basicAC_F0 & args) {return new MatrixUpWind0 (args);}

Operador AnyType () (Pila s) const ;

https://translate.googleusercontent.com/translate_f 335/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

};

En t fvmP1P0 ( doble q [3] [2], doble u [2], doble c [3], doble a [3] [3], doble
donde [3])
{ // calcula la matriz a en un triángulo para el
Dervieux FVM
para (int i = 0; i <3; i ++) para (int j = 0; j <3; j ++) a [i] [j] = 0;

para (int i = 0; i <3; i ++) {


int ip = (i + 1)% 3, ipp = (ip + 1)% 3;
doble unL = - ((q [ip] [1] + q [i] [1] -2 * q [ipp] [1]) * u [0]
- (q [ip] [0] + q [i] [0] -2 * q [ipp] [0]) * u [1]) / 6;
si (unL> 0) {a [i] [i] + = unL; a [ip] [i] - = unL;}
else {a [i] [ip] + = unL; a [ip] [ip] - = unL;}
if (donde [i] && donde [ip]) { // este es un borde limítrofe
unL = ((q [ip] [1] -q [i] [1]) * u [0] - (q [ip] [0] -q [i] [0]) * u [1]) / 2;
si (unL> 0) {a [i] [i] + = unL; a [ip] [ip] + = unL;}
}
}
return 1;
}

// la rutina de evaluación
AnyType MatrixUpWind0 :: operator () (Pila de pila) const
{
Matrice_Creuse <R> * sparse_mat = GetAny <Matrice_Creuse <R> *> ((* emat) (pila));
MatriceMorse <R> * amorse = 0;
MeshPoint * mp (MeshPointStack (pila)), mps = * mp;

Página 378
378 APÉNDICE C. VÍNCULO DINÁMICO

Malla * pTh = GetAny <pmesh> ((* expTh) (pila));


ffassert (pTh);
Malla y Th (* pTh);
{
mapa <par <int, int>, R> Aij;
KN <doble> cc (Th.nv);
doble infini = DBL_MAX;
cc = infini;
para (int it = 0; it <Th.nt; it ++)
para (int iv = 0; iv <3; iv ++)
{
int i = Th (it, iv);
si (cc [i] == infini) { // si nuset el conjunto
mp-> setP (& Th, it, iv);
cc [i] = GetAny <doble> ((* expc) (pila));
}
}

para (int k = 0; k <Th.nt; k ++)


{
const Triángulo & K (Th [k]);
const Vértice & A (K [0]), & B (K [1]), & C (K [2]);
R2 Pt (1./3.,1./3.);
R u [2];
MeshPointStack (pila) -> conjunto (Th, K (Pt), Pt, K, K.lab);
u [0] = GetAny <R> ((* expu1) (pila));
u [1] = GetAny <R> ((* expu2) (pila));

int ii [3] = {Th (A), Th (B), Th (C)};


doble q [3] [2] = {{Ax, Ay}, {Bx, By}, {Cx, Cy}}; // coordenadas
de 3 vértices (entrada)
doble c [3] = {cc [ii [0]], cc [ii [1]], cc [ii [2]]};
doble a [3] [3], donde [3] = {A.lab, B.lab, C.lab};
si (fvmP1P0 (q, u, c, a, donde))
{
para (int i = 0; i <3; i ++)

https://translate.googleusercontent.com/translate_f 336/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
para (int j = 0; j <3; j ++)
si (fabs (a [i] [j])> = 1e-30)
{Aij [make_pair (ii [i], ii [j])] + = a [i] [j];
}
}
}
amorse = new MatriceMorse <R> (Th.nv, Th.nv, Aij, falso);
}
sparse_mat-> pUh = 0;
sparse_mat-> pVh = 0;
sparse_mat-> A.master (amorso);
sparse_mat-> typemat = (amorse-> n == amorse-> m)? TypeSolveMat (TypeSolveMat :: GMRES)
: TypeSolveMat (TypeSolveMat :: NONESQUARE); // ninguna matriz cuadrada (morse)
* mp = mps;

if (verbosidad> 3) { cout << "End Build MatrixUpWind:" << endl;}

return sparse_mat;
}

Página 379
C.4. MÁS SOBRE AÑADIR UN NUEVO ELEMENTO FINITO 379

void init ()
{
cout << "lood: init Mat Chacon" << endl;
Global.Add ("MatUpWind0", "(", nuevo OneOperatorCode <MatrixUpWind0> ());
}

LOADFUNC (init);

C.4 Más sobre la adición de un nuevo elemento finito


Primero lea la sección 13 del apéndice, agregamos dos nuevos ejemplos de elementos finitos en el
ejemplos de directorio ++ - load.

El elemento de Bernardi-Raugel El elemento finito de Bernardi-Raugel está destinado a resolver el


Ecuaciones de Navier Stokes en formulación u, p; el espacio de velocidad P br
K es mínimo para probar el
condición inf-sup con presión constante a trozos por triángulo.
El espacio de elementos finitos V h es

V h = {u ∈ H 1 (Ω) 2 ; ∀K ∈ T h , u | K ∈ P br
K }

dónde
P br
K = tramo {λ K yo e k } yo = 1,2,3, k = 1,2 ∪ {λ K yo λ Kyo + 1 ni K+ 2 } i = 1,2,3
con notación 4 = 1,5 = 2 y donde λ K I son las coordenadas baricéntricas del triángulo K,
(e k ) k = 1,2 la base canónica de R 2 y n K
k la normal exterior del triángulo K opuesto al vértice
k.

// El elemento finito P2BR: el elemento finito Bernadi Raugel


// F. Hecht, diciembre de 2005
// -------------
// Ver Bernardi, C., Raugel, G .: Análisis de algunos elementos finitos para la
Problema de Stokes. Matemáticas. Comp. 44, 71 - 79 (1985).
// Es un FE acoplado 2d
// el espacio polinomial es P1 2 + 3 normales función de bordes de burbujas (P 2 )
// el grado de libertad es 6 valores en de los 2 componentes en el 3
vértices
// y el 3 fundente en los 3 bordes
// Entonces 9 grados de libertad y N = 2.

https://translate.googleusercontent.com/translate_f 337/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
// ----------------------- archivos relacionados:
// para comprobar y validar: testFE.edp
// para obtener un ejemplo real: NSP2BRP0.edp
// -------------------------------------------------- ----------

// -----------------------
#include "error.hpp"
#include "AFunction.hpp"
#include "rgraph.hpp"
usando el espacio de nombres std;
#include "RNM.hpp"
#include "fem.hpp"

Página 380
380 APÉNDICE C. VÍNCULO DINÁMICO

#include "FESpace.hpp"
#include "AddNewFE.h"

espacio de nombres Fem2D {

clase TypeOfFE_P2BRLagrange: public TypeOfFE {public:


static int Data [];

TypeOfFE_P2BRLagrange (): TypeOfFE (6 + 3 + 0,


2,
Datos,
4,
1,
6 + 3 * (2 + 2), // nb coef para construir interpolación
9, // np punto para construir interpolación
0)
{
.... // para ver la fuente por mucho tiempo
}
void FB (const bool * whatd, const Mesh & Th, const Triangle & K, const R2
& P, RNMK_ & val) const;
vacío TypeOfFE_P2BRLagrange :: Pi_h_alpha (const baseFElement & K, KN_ <doble>
& v) const;
};
// en qué nu df en el nodo nodo de df
int TypeOfFE_P2BRLagrange :: Data [] = {
0,0, 1,1, 2,2, 3,4,5,
0,1, 0,1, 0,1, 0,0,0,
0,0, 1,1, 2,2, 3,4,5,
0,0, 0,0, 0,0, 0,0,0,
0,1, 2,3, 4,5, 6,7,8,
0,0
};

vacío TypeOfFE_P2BRLagrange :: Pi_h_alpha (const baseFElement & K, KN_ <double> & v)


constante
{
const Triángulo & T (KT);
int k = 0;
// coef pour les 3 sommets fois le 2 composantes
para (int i = 0; i <6; i ++)
v [k ++] = 1;
// integración sur les aretes
para (int i = 0; i <3; i ++)
{

R2 N (T.Edge (i) .perp ());


N * = T.EdgeOrientation (i) * 0.5;
v [k ++] = Nx;
v [k ++] = Ny;
v [k ++] = Nx;
v [k ++] = Ny;

https://translate.googleusercontent.com/translate_f 338/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
}
}

Página 381
C.4. MÁS SOBRE AÑADIR UN NUEVO ELEMENTO FINITO 381

vacío TypeOfFE_P2BRLagrange :: FB (const bool * whatd, const Mesh &, const


Triángulo & K, const R2 & P, RNMK_ & val) const
{
.... // para ver la fuente por mucho tiempo
}
// ---- cocinar para agregar el elemento finito a la mesa freefem --------
// una variable estática para definir el elemento finito
estático TypeOfFE_P2BRLagrange P2LagrangeP2BR;
// ahora agregando FE en la tabla FreeFem ++
estático AddNewFE P2BR ("P2BR", & P2LagrangeP2BR);
// --- finalizar la cocción
} // finalizar el espacio de nombres FEM2d

Una forma de comprobar el elemento finito.

cargar "BernadiRaugel"
// una macro la derivada numérica de cálculo
macro DD (f, hx, hy) ((f (x1 + hx, y1 + hy) -f (x1-hx, y1-hy)) / (2 * (hx + hy))) //
malla Th = cuadrado (1,1, [10 * (x + y / 3), 10 * (yx / 3)]);

real x1 = 0,7, y1 = 0,9, h = 1e-7;


int it1 = Th (x1, y1) .nuTriangle;

fespace Vh (Th, P2BR);

Vh [a1, a2], [b1, b2], [c1, c2];

para (int i = 0; i <Vh.ndofK; ++ i)


cout << i << "" << Vh (0, i) << endl;
para (int i = 0; i <Vh.ndofK; ++ i)
{
a1 [] = 0;
int j = Vh (it1, i);
a1 [] [j] = 1; // funciones básicas
plot ([a1, a2], espera = 1);

[b1, b2] = [a1, a2]; // haz la interpolación

c1 [] = a1 [] - b1 [];

cout << "---------" << i << "" << c1 []. max << "" << c1 []. min << endl;
cout << "a =" << a1 [] << endl;
cout << "b =" << b1 [] << endl;
afirmar (c1 []. max <1e-9 && c1 []. min> -1e-9); // compruebe si el
la interpolación es correcta

// comprobar la derivada y la derivada numérica

cout << "dx (a1) (x1, y1) =" << dx (a1) (x1, y1) << "==" << DD (a1, h, 0) <<
endl;
afirmar (abs (dx (a1) (x1, y1) -DD (a1, h, 0)) <1e-5);
afirmar (abs (dx (a2) (x1, y1) -DD (a2, h, 0)) <1e-5);

https://translate.googleusercontent.com/translate_f 339/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 382
382 APÉNDICE C. VÍNCULO DINÁMICO

afirmar (abs (dy (a1) (x1, y1) -DD (a1,0, h)) <1e-5);
afirmar (abs (dy (a2) (x1, y1) -DD (a2,0, h)) <1e-5);

Un ejemplo real usando este elemento finito, solo una pequeña modificación de NSP2P1.edp
ejemplos, solo el comienzo es el cambio a

cargar "BernadiRaugel"

real s0 = reloj ();


malla Th = cuadrado (10,10);
fespace Vh2 (Th, P2BR);
fespace Vh (Th, P0);
Vh2 [u1, u2], [up1, up2];
Vh2 [v1, v2];

Y la instrucción de la trama también se cambia porque la presión es constante y no podemos


graficar isovalores de funciones constantes pacíficas.

El elemento Morley Vea el ejemplo bilapMorley.edp.

C.5 Agregar un nuevo solucionador disperso


Advirtiendo que la interfaz del solucionador disperso se ha reescrito por completo en la versión 3.2, por lo que
La sección es obsoleta, el ejemplo en son correctos /
Aquí sólo se ofrece un bosquejo rápido del código; para obtener más detalles, consulte el código .cpp de SuperLU.cpp
o NewSolve.cpp.
Primero los archivos de inclusión:

# include <iostream>
usando el espacio de nombres std;

# incluye "rgraph.hpp"
# incluye "error.hpp"
# incluye "AFunction.hpp"

// #include "lex.hpp"
# include "MatriceCreuse_tpl.hpp"
# incluye "slu_ddefs.h"
# incluye "slu_zdefs.h"

Un pequeño controlador de plantilla para unificar la versión doble y compleja.

plantilla <clase R> estructura SuperLUDriver


{

};

plantilla <> estructura SuperLUDriver < doble >


{

Página 383
C.5. AÑADIR UN NUEVO SOLUCIONADOR ESPARO 383

https://translate.googleusercontent.com/translate_f 340/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
.... versión doble
};

plantilla <> struct SuperLUDriver < Complex >


{
.... Versión compleja
};

Para obtener el valor de la matriz, solo tenemos que señalar que la matriz Morse, el almacenamiento, es el
El formato SLU NR es el almacenamiento de filas comprimidas, esta es la transposición de la columna comprimida
almacenamiento.
Entonces, si AA es un MatriceMorse, lo tiene con notación SuperLU.

n = AA.n;
m = AA.m;
nnz = AA.nbcoef;
a = AA. a;
asub = AA.cl;
xa = AA.lg;
options.Trans = TRANS;

Dtype_t R_SLU = SuperLUDriver <R> :: R_SLU_T ();


Create_CompCol_Matrix (& A, m, n, nnz, a, asub, xa, SLU_NC, R_SLU, SLU_GE);

Para obtener información vectorial, para resolver el solucionador lineal x = A −1 b

Solucionador de vacíos ( const MatriceMorse <R> & AA, KN_ <R> & x, const KN_ <R> & b) const
{
....
Create_Dense_Matrix (& B, m, 1, b, m, SLU_DN, R_SLU, SLU_GE);
Create_Dense_Matrix (& X, m, 1, x, m, SLU_DN, R_SLU, SLU_GE);
....
}

Las dos funciones BuildSolverSuperLU, para cambiar la variable de resolución dispersa predeterminada
DefSparseSolver < doble > :: solucionador

MatriceMorse <doble> :: VirtualSolver *


BuildSolverSuperLU (DCL_ARG_SPARSE_SOLVER (doble, A))
{
if (verbosidad> 9)
cout << "BuildSolverSuperLU <doble>" << endl;
devolver nuevo SolveSuperLU <double> (* A, ds.strategy, ds.tgv, ds.epsilon, ds.tol_pivot, ds.tol_pivot_sy
}

MatriceMorse <Complejo> :: VirtualSolver *


BuildSolverSuperLU (DCL_ARG_SPARSE_SOLVER (Complex, A))
{
if (verbosidad> 9)
cout << "BuildSolverSuperLU <Complejo>" << endl;
devolver nuevo SolveSuperLU <Complejo> (* A, ds.strategy, ds.tgv, ds.epsilon, ds.tol_pivot, ds.tol_pivot_sym
}

Página 384
384 APÉNDICE C. VÍNCULO DINÁMICO

El enlace a FreeFem ++

class Init { public :


En eso();
};

Para establecer el 2 solucionador disperso predeterminado doble y complejo:

https://translate.googleusercontent.com/translate_f 341/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
DefSparseSolver < doble > :: SparseMatSolver SparseMatSolver_R; ;
DefSparseSolver <Complejo> :: SparseMatSolver SparseMatSolver_C;

Para guardar el tipo de solucionador predeterminado

TypeSolveMat :: TSolveMat TypeSolveMatdefaultvalue = TypeSolveMat :: defaultvalue;

Para restablecer el solucionador predeterminado, llame a esta función:

bool SetDefault ()
{
si (verbosidad> 1)
cout << "SetDefault escaso a predeterminado" << endl;
DefSparseSolver < doble > :: solver = SparseMatSolver_R;
DefSparseSolver <Complejo> :: solver = SparseMatSolver_C;
TypeSolveMat :: defaultvalue = TypeSolveMat :: SparseSolver;
}

Para configurar el solucionador predeterminado en superLU, llame a esta función:

bool SetSuperLU ()
{
si (verbosidad> 1)
cout << "Establecer el solucionador disperso predeterminado en SuperLU" << endl;
DefSparseSolver < doble > :: solver = BuildSolverSuperLU;
DefSparseSolver <Complejo> :: solver = BuildSolverSuperLU;
TypeSolveMat :: defaultvalue = TypeSolveMatdefaultvalue;
}

Para agregar una nueva función / nombre predeterminado solucionador, defaulttoSuperLUin FreeFem ++, y
establezca el solucionador predeterminado en el nuevo solucionador., simplemente haga:

void init ()
{

SparseMatSolver_R = DefSparseSolver < doble > :: solucionador;


SparseMatSolver_C = DefSparseSolver < Complejo > :: solucionador;

si (verbosidad> 1)
cout << "\ n Agregar: SuperLU, defaultsolver defaultsolverSuperLU" << endl;
TypeSolveMat :: defaultvalue = TypeSolveMat :: SparseSolver;
DefSparseSolver < doble > :: solver = BuildSolverSuperLU;
DefSparseSolver < Complejo > :: solver = BuildSolverSuperLU;
// probar si el nombre "defaultsolver" existe en freefem ++
if (! Global.Find ("defaultsolver"). NotNull ())
Global.Add ("defaultsolver", "(", nuevo OneOperator0 <bool> (SetDefault));
Global.Add ("defaulttoSuperLU", "(", nuevo OneOperator0 <bool> (SetSuperLU));
}

Página 385
C.5. AÑADIR UN NUEVO SOLUCIONADOR ESPARO 385

LOADFUNC (init);

Para compilar superlu.cpp, simplemente haga:

1. descargue el paquete SuperLu 3.0 y haga

rizo http://crd.lbl.gov/˜xiaoye/SuperLU/superlu_3.0.tar.gz -o superlu_3.0.t


tar xvfz superlu_3.0.tar.gz
ir al directorio SuperLU_3.0
$ EDITOR make.inc
fabricar

2. En el directorio, incluya hacer para tener una versión correcta del encabezado SuperLu debido a un error en

https://translate.googleusercontent.com/translate_f 342/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
caso de inclusión de versión doble y compleja en el mismo archivo.

tar xvfz ../SuperLU_3.0-include-ff.tar.gz

Daré uno correcto para compilar con freefm ++.

Para compilar el archivo de carga FreeFem ++ de SuperLu con freefem, algunos encuentran como:

ff-c ++ SuperLU.cpp -L $ HOME / trabajo / LinearSolver / SuperLU_3.0 / -lsuperlu_3.0

Y para probar el ejemplo simple:


Un ejemplo:

cargar "SuperLU"
verbosidad = 2;
para (int i = 0; i <3; ++ i)
{
// si i == 0 entonces solucionador de SuperLu
// i == 1 luego solucionador de GMRES
// i == 2 luego solucionador predeterminado
{
matriz A =
[[0, 1, 0, 10],
[0, 0, 2, 0],
[0, 0, 0, 3],
[4,0, 0, 0]];
real [int] xx = [4,1,2,3], x (4), b (4);
b = A * xx;
cout << b << "" << xx << endl;
set (A, solver = sparsesolver);
x = Aˆ-1 * b;
cout << x << endl;
}

{
matriz <complejo> A =
[[0, 1i, 0, 10],

Página 386
386 APÉNDICE C. VÍNCULO DINÁMICO

[0, 0, 2i, 0],


[0, 0, 0, 3i],
[4i, 0, 0, 0]];
complejo [int] xx = [4i, 1i, 2i, 3i], x (4), b (4);
b = A * xx;
cout << b << "" << xx << endl;
set (A, solver = sparsesolver);
x = Aˆ-1 * b;
cout << x << endl;
}
if (i == 0) defaulttoGMRES ();
if (i == 1) defaultsolver ();
}

Para probar, haga por ejemplo:

FreeFem ++ SuperLu.edp

https://translate.googleusercontent.com/translate_f 343/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 387

Apéndice D

Enchufar

D.1 gsl
La interfaz con de gsl spline está disponible a partir de la versión 3.47
los siete tipos de spline son

0 gslinterpcspline (tipo predeterminado de spline)

1 gslinterpakima

2 gslinterpsteffen

3 gslinterpillar lineal

4 gslinterppolynomial

5 gslinterpcsplineperiodic

6 gslinterpakimaperiodic
https://translate.googleusercontent.com/translate_f 344/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Un breve ejemplo de ala dada toda la sintaxis:

int n = 10;
real [ int , int ] dspline (2, n + 1); // puntos de datos para definir la spline
para (int i = 0; i <= n; ++ i) // establecer punto de datos
{
real xx = cuadrado (real (i) / n);
yy real = sin (xx * pi * 2);
dspline (0, i) = xx;
dspline (1, i) = aa;
}
gslspline spline1 (gslinterpcspline, dspline); // def el spline1
gslspline spline11 (dspline); // def el spline11
gslspline spline2 (gslinterpsteffen, dspline); // def el spline2
gslspline spline3 (gslinterpcspline, dspline (0, :) ,, dspline (1, :)); // def
gslspline spline33 (dspline (0, :) ,, dspline (1, :)); // def el spline3
spline1 = spline2 ; // copiar y cambiar en spline1 en spline2
t real = 1;
real s1 = spline1 (t); // eval la función spline1 en t
ds1 real = spline1 .d (t); // evalúa la derivación de la función spline1 en t
dds1 real = spline1 .dd (t); // eval la derivación 2 de la función spline1 en t

387

Página 388
388 APÉNDICE D. PLUGIN

Esto puede resultar útil para crear funciones a partir del valor de los datos.

La lista de todas las funciones gsl y el nombre freefem tienen el mismo nombre sin.

• gsl cdf ugaussiano P (a) ↦ → gslcdfugaussianP (a)


• gsl cdf ugaussian Q (a) ↦ → gslcdfugaussianQ (a)
• gsl cdf ugaussian Pinv (a) ↦ → gslcdfugaussianPinv (a)
• gsl cdf ugaussian Qinv (a) ↦ → gslcdfugaussianQinv (a)
• gsl cdf gaussiano P (a, b) ↦ → gslcdfgaussianP (a, b)
• gsl cdf gaussiano Q (a, b) ↦ → gslcdfgaussianQ (a, b)
• gsl cdf gaussian Pinv (a, b) ↦ → gslcdfgaussianPinv (a, b)
• gsl cdf gaussian Qinv (a, b) ↦ → gslcdfgaussianQinv (a, b)
• gsl cdf gamma P (a, b, c) ↦ → gslcdfgammaP (a, b, c)
• gsl cdf gamma Q (a, b, c) ↦ → gslcdfgammaQ (a, b, c)
• gsl cdf gamma Pinv (a, b, c) ↦ → gslcdfgammaPinv (a, b, c)
• gsl cdf gamma Qinv (a, b, c) ↦ → gslcdfgammaQinv (a, b, c)
• gsl cdf cauchy P (a, b) ↦ → gslcdfcauchyP (a, b)
• gsl cdf cauchy Q (a, b) ↦ → gslcdfcauchyQ (a, b)
• gsl cdf cauchy Pinv (a, b) ↦ → gslcdfcauchyPinv (a, b)
• gsl cdf cauchy Qinv (a, b) ↦ → gslcdfcauchyQinv (a, b)
• gsl cdf laplace P (a, b) ↦ → gslcdflaplaceP (a, b)
• gsl cdf laplace Q (a, b) ↦ → gslcdflaplaceQ (a, b)
• gsl cdf laplace Pinv (a, b) ↦ → gslcdflaplacePinv (a, b)
• gsl cdf laplace Qinv (a, b) ↦ → gslcdflaplaceQinv (a, b)
• gsl cdf rayleigh P (a, b) ↦ → gslcdfrayleighP (a, b)
• gsl cdf rayleigh Q (a, b) ↦ → gslcdfrayleighQ (a, b)
• gsl cdf rayleigh Pinv (a, b) ↦ → gslcdfrayleighPinv (a, b)
• gsl cdf rayleigh Qinv (a, b) ↦ → gslcdfrayleighQinv (a, b)
• gsl cdf chisq P (a, b) ↦ → gslcdfchisqP (a, b)
• gsl cdf chisq Q (a, b) ↦ → gslcdfchisqQ (a, b)
• gsl cdf chisq Pinv (a, b) ↦ → gslcdfchisqPinv (a, b)
• gsl cdf chisq Qinv (a, b) ↦ → gslcdfchisqQinv (a, b)
• gsl cdf exponencial P (a, b) ↦ → gslcdfexponentialP (a, b)
• gsl cdf exponencial Q (a, b) ↦ → gslcdfexponentialQ (a, b)
• Pinv exponencial de CDF de GSL (a, b) ↦ → gslcdfexponentialPinv (a, b)
• gsl CDF exponencial Qinv (a, b) ↦ → gslcdfexponentialQinv (a, b)
• gsl cdf exppow P (a, b, c) ↦ → gslcdfexppowP (a, b, c)
• gsl cdf exppow Q (a, b, c) ↦→
https://translate.googleusercontent.com/translate_f 345/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
• gsl cdf tdist P (a, b) gslcdfexppowQ
↦ → gslcdftdistP (a, b) (a, b, c)
• gsl cdf tdist Q (a, b) ↦ → gslcdftdistQ (a, b)
• gsl cdf tdist Pinv (a, b) ↦ → gslcdftdistPinv (a, b)
• gsl cdf tdist Qinv (a, b) ↦ → gslcdftdistQinv (a, b)
• gsl cdf fdist P (a, b, c) ↦ → gslcdffdistP (a, b, c)
• gsl cdf fdist Q (a, b, c) ↦ → gslcdffdistQ (a, b, c)
• gsl cdf fdist Pinv (a, b, c) ↦ → gslcdffdistPinv (a, b, c)
• gsl cdf fdist Qinv (a, b, c) ↦ → gslcdffdistQinv (a, b, c)
• gsl cdf beta P (a, b, c) ↦ → gslcdfbetaP (a, b, c)
• gsl cdf beta Q (a, b, c) ↦ → gslcdfbetaQ (a, b, c)
• gsl cdf beta Pinv (a, b, c) ↦ → gslcdfbetaPinv (a, b, c)
• gsl cdf beta Qinv (a, b, c) ↦ → gslcdfbetaQinv (a, b, c)

Página 389
D.1. GSL 389

• gsl cdf flat P (a, b, c) ↦ → gslcdfflatP (a, b, c)


• gsl cdf flat Q (a, b, c) ↦ → gslcdfflatQ (a, b, c)
• gsl cdf plano Pinv (a, b, c) ↦ → gslcdfflatPinv (a, b, c)
• gsl cdf flat Qinv (a, b, c) ↦ → gslcdfflatQinv (a, b, c)
• gsl cdf lognormal P (a, b, c) ↦ → gslcdflognormalP (a, b, c)
• gsl cdf lognormal Q (a, b, c) ↦ → gslcdflognormalQ (a, b, c)
• gsl cdf lognormal Pinv (a, b, c) ↦ → gslcdflognormalPinv (a, b, c)
• Qinv lognormal de CDF de GSL (a, b, c) ↦ → gslcdflognormalQinv (a, b, c)
• gsl cdf gumbel1 P (a, b, c) ↦ → gslcdfgumbel1P (a, b, c)
• gsl cdf gumbel1 Q (a, b, c) ↦ → gslcdfgumbel1Q (a, b, c)
• gsl cdf gumbel1 Pinv (a, b, c) ↦ → gslcdfgumbel1Pinv (a, b, c)
• gsl cdf gumbel1 Qinv (a, b, c) ↦ → gslcdfgumbel1Qinv (a, b, c)
• gsl cdf gumbel2 P (a, b, c) ↦ → gslcdfgumbel2P (a, b, c)
• gsl cdf gumbel2 Q (a, b, c) ↦ → gslcdfgumbel2Q (a, b, c)
• gsl cdf gumbel2 Pinv (a, b, c) ↦ → gslcdfgumbel2Pinv (a, b, c)
• gsl cdf gumbel2 Qinv (a, b, c) ↦ → gslcdfgumbel2Qinv (a, b, c)
• gsl cdf weibull P (a, b, c) ↦ → gslcdfweibullP (a, b, c)
• gsl cdf weibull Q (a, b, c) ↦ → gslcdfweibullQ (a, b, c)
• gsl cdf weibull Pinv (a, b, c) ↦ → gslcdfweibullPinv (a, b, c)
• gsl cdf weibull Qinv (a, b, c) ↦ → gslcdfweibullQinv (a, b, c)
• gsl cdf pareto P (a, b, c) ↦ → gslcdfparetoP (a, b, c)
• gsl cdf pareto Q (a, b, c) ↦ → gslcdfparetoQ (a, b, c)
• gsl cdf pareto Pinv (a, b, c) ↦ → gslcdfparetoPinv (a, b, c)
• gsl cdf pareto Qinv (a, b, c) ↦ → gslcdfparetoQinv (a, b, c)
• gsl cdf logística P (a, b) ↦ → gslcdflogisticP (a, b)
• gsl cdf logístico Q (a, b) ↦ → gslcdflogisticQ (a, b)
• gsl cdf logistic Pinv (a, b) ↦ → gslcdflogisticPinv (a, b)
• Qinv logístico gsl cdf (a, b) ↦ → gslcdflogisticQinv (a, b)
• gsl cdf binomial P (a, b, c) ↦ → gslcdfbinomialP (a, b, c)
• binomio Gsl CDF Q (a, b, c) ↦ → gslcdfbinomialQ (a, b, c)
• gsl cdf poisson P (a, b) ↦ → gslcdfpoissonP (a, b)
• gsl cdf poisson Q (a, b) ↦ → gslcdfpoissonQ (a, b)
• gsl cdf geométrico P (a, b) ↦ → gslcdfgeometricP (a, b)
• gsl cdf geométrico Q (a, b) ↦ → gslcdfgeometricQ (a, b)
• gsl cdf binomio negativo P (a, b, c) ↦ → gslcdfnegativebinomialP (a, b, c)
• gsl cdf binomio negativo Q (a, b, c) ↦ → gslcdfnegativebinomialQ (a, b, c)
• gsl cdf pascal P (a, b, c) ↦ → gslcdfpascalP (a, b, c)
• gsl cdf pascal Q (a, b, c) ↦ → gslcdfpascalQ (a, b, c)
• gsl corrió bernoulli pdf (a, b) ↦ → gslranbernoullipdf (a, b)
• gsl ejecutó beta (a, b, c) ↦→ gslranbeta (a, b, c)
• gsl ejecutó beta pdf (a, b, c) ↦ → gslranbetapdf (a, b, c)
• gsl corrió pdf binomial (a, b, c) ↦ → gslranbinomialpdf (a, b, c)
• gsl corrió exponencial (a, b) ↦ → gslranexponencial (a, b)
• gsl corrió pdf exponencial (a, b) ↦ → gslranexponentialpdf (a, b)
• gsl ejecutó exppow (a, b, c) ↦ → gslranexppow (a, b, c)

https://translate.googleusercontent.com/translate_f 346/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
•• gsl
gsl ejecutó exppow
corrió cauchy (a,pdf
b) (a, b, c) ↦ → gslranexppowpdf (a, b, c)
↦ → gslrancauchy (a, b)
• gsl corrió cauchy pdf (a, b) ↦ → gslrancauchypdf (a, b)
• gsl corrió chisq (a, b) ↦ → gslranchisq (a, b)
• gsl corrió chisq pdf (a, b) ↦ → gslranchisqpdf (a, b)

Página 390
390 APÉNDICE D. PLUGIN

• gsl corrió erlang (a, b, c) ↦ → gslranerlang (a, b, c)


• gsl ejecutó erlang pdf (a, b, c) ↦ → gslranerlangpdf (a, b, c)
• gsl corrió fdist (a, b, c) ↦ → gslranfdist (a, b, c)
• gsl ejecutó fdist pdf (a, b, c) ↦ → gslranfdistpdf (a, b, c)
• gsl corrió plano (a, b, c) ↦ → gslranflat (a, b, c)
• gsl ejecutó un pdf plano (a, b, c) ↦ → gslranflatpdf (a, b, c)
• gsl corrió gamma (a, b, c) ↦ → gslrangamma (a, b, c)
• gsl corrió gamma int (a, b) ↦ → gslrangammaint (a, b)
• gsl corrió gamma pdf (a, b, c) ↦ → gslrangammapdf (a, b, c)
• gsl corrió gamma mt (a, b, c) ↦ → gslrangammamt (a, b, c)
• gsl corrió gamma knuth (a, b, c) ↦ → gslrangammaknuth (a, b, c)
• gsl corrió gaussiano (a, b) ↦ → gslrangaussian (a, b)
• gsl corrió método de la relación gaussiana (a, b) ↦ → gslrangaussianratiomethod (a, b)
• gsl corrió zigurat gaussiano (a, b) ↦ → gslrangaussianziggurat (a, b)
• gsl ejecutó pdf gaussiano (a, b) ↦ → gslrangaussianpdf (a, b)
• gsl corrió ugaussian (a) ↦ → gslranugaussian (a)
• Método de razón de ugaussian de gsl (a) ↦ → método gslranugaussianratiomethod (a)
• gsl ejecutó pdf ugaussiano (a) ↦ → gslranugaussianpdf (a)
• gsl corrió cola gaussiana (a, b, c) ↦ → gslrangaussiantail (a, b, c)
• gsl corrió pdf de cola gaussiana (a, b, c) ↦ → gslrangaussiantailpdf (a, b, c)
• gsl corrió cola ugaussiana (a, b) ↦ → gslranugaussiantail (a, b)
• gsl ejecutó un pdf de cola ugaussiana (a, b) ↦ → gslranugaussiantailpdf (a, b)
• gsl corrió landau (a) ↦→ gslranlandau (a)
• gsl corrió landau pdf (a) ↦ → gslranlandaupdf (a)
• gsl ejecutó pdf geométrico (a, b) ↦ → gslrangeometricpdf (a, b)
• gsl corrió gumbel1 (a, b, c) ↦ → gslrangumbel1 (a, b, c)
• gsl ejecutó gumbel1 pdf (a, b, c) ↦ → gslrangumbel1pdf (a, b, c)
• gsl ejecutó gumbel2 (a, b, c) ↦ → gslrangumbel2 (a, b, c)
• gsl ejecutó gumbel2 pdf (a, b, c) ↦ → gslrangumbel2pdf (a, b, c)
• gsl corrió logístico (a, b) ↦ → gslranlogistic (a, b)
• gsl corrió pdf logístico (a, b) ↦ → gslranlogisticpdf (a, b)
• gsl corrió lognormal (a, b, c) ↦ → gslranlognormal (a, b, c)
• gsl ejecutó un pdf lognormal (a, b, c) ↦ → gslranlognormalpdf (a, b, c)
• gsl corrió pdf logarítmico (a, b) ↦ → gslranlogarithmicpdf (a, b)
• gsl corrió pdf binomial negativo (a, b, c) ↦ → gslrannegativebinomialpdf (a, b, c)
• gsl ejecutó pascal pdf (a, b, c) ↦ → gslranpascalpdf (a, b, c)
• gsl corrió pareto (a, b, c) ↦ → gslranpareto (a, b, c)
• gsl corrió pareto pdf (a, b, c) ↦ → gslranparetopdf (a, b, c)
• gsl ejecutó poisson pdf (a, b) ↦ → gslranpoissonpdf (a, b)
• gsl corrió rayleigh (a, b) ↦ → gslranrayleigh (a, b)
• gsl corrió rayleigh pdf (a, b) ↦ → gslranrayleighpdf (a, b)
• gsl corrió rayleigh tail (a, b, c) ↦ → gslranrayleightail (a, b, c)
• gsl corrió rayleigh tail pdf (a, b, c) ↦ → gslranrayleightailpdf (a, b, c)
• gsl ran tdist (a, b) ↦ → gslrantdist (a, b)
• gsl corrió tdist pdf (a, b) ↦ → gslrantdistpdf (a, b)
• gsl corrió laplace (a, b) ↦ → gslranlaplace (a, b)
• gsl corrió laplace pdf (a, b) ↦ → gslranlaplacepdf (a, b)
• impuesto ejecutado gsl (a, b, c) ↦ → gslranlevy (a, b, c)
• gsl ejecutó weibull (a, b, c) ↦ → gslranweibull (a, b, c)
• gsl ejecutó weibull pdf (a, b, c) ↦ → gslranweibullpdf (a, b, c)

https://translate.googleusercontent.com/translate_f 347/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 391
D.1. GSL 391

• gsl sf airy Ai (a, b) ↦ → gslsfairyAi (a, b)


• gsl sf airy Bi (a, b) ↦ → gslsfairyBi (a, b)
• gsl sf airy Ai en escala (a, b) ↦ → gslsfairyAiscaled (a, b)
• gsl sf airy Bi escala (a, b) ↦ → gslsfairyBiscaled (a, b)
• gsl sf airy Ai deriv (a, b) ↦ → gslsfairyAideriv (a, b)
• gsl sf airy Bi deriv (a, b) ↦ → gslsfairyBideriv (a, b)
• gsl sf airy Ai derivado en escala (a, b) ↦ → gslsfairyAiderivscaled (a, b)
• gsl sf airy Bi derivado a escala (a, b) ↦ → gslsfairyBiderivscaled (a, b)
• gsl sf airy zero Ai (a) ↦ → gslsfairyzeroAi (a)
• gsl sf airy zero Bi (a) ↦ → gslsfairyzeroBi (a)
• gsl sf airy zero Ai deriv (a) ↦ → gslsfairyzeroAideriv (a)
• gsl sf airy zero Bi deriv (a) ↦ → gslsfairyzeroBideriv (a)
• gsl sf bessel J0 (a) ↦ → gslsfbesselJ0 (a)
• gsl sf bessel J1 (a) ↦ → gslsfbesselJ1 (a)
• gsl sf bessel Jn (a, b) ↦ → gslsfbesselJn (a, b)
• gsl sf bessel Y0 (a) ↦ → gslsfbesselY0 (a)
• gsl sf bessel Y1 (a) ↦ → gslsfbesselY1 (a)
• gsl sf bessel Yn (a, b) ↦ → gslsfbesselYn (a, b)
• gsl sf bessel I0 (a) ↦ → gslsfbesselI0 (a)
• gsl sf bessel I1 (a) ↦ → gslsfbesselI1 (a)
• gsl sf bessel en (a, b) ↦ → gslsfbesselIn (a, b)
• gsl sf bessel I0 escalado (a) ↦ → gslsfbesselI0scaled (a)
• gsl sf bessel I1 escala (a) ↦ → gslsfbesselI1scaled (a)
• gsl sf bessel en escala (a, b) ↦ → gslsfbesselInscaled (a, b)
• gsl sf bessel K0 (a) ↦ → gslsfbesselK0 (a)
• gsl sf bessel K1 (a) ↦ → gslsfbesselK1 (a)
• gsl sf bessel Kn (a, b) ↦ → gslsfbesselKn (a, b)
• gsl sf bessel K0 en escala (a) ↦ → gslsfbesselK0scaled (a)
• gsl sf bessel K1 en escala (a) ↦ → gslsfbesselK1scaled (a)
• gsl sf bessel Kn escalado (a, b) ↦ → gslsfbesselKnscaled (a, b)
• gsl sf bessel j0 (a) ↦ → gslsfbesselj0 (a)
• gsl sf bessel j1 (a) ↦ → gslsfbesselj1 (a)
• gsl sf bessel j2 (a) ↦ → gslsfbesselj2 (a)
• gsl sf bessel jl (a, b) ↦ → gslsfbesseljl (a, b)
• gsl sf bessel y0 (a) ↦ → gslsfbessely0 (a)
• gsl sf bessel y1 (a) ↦ → gslsfbessely1 (a)
• gsl sf bessel y2 (a) ↦ → gslsfbessely2 (a)
• gsl sf bessel yl (a, b) ↦ → gslsfbesselyl (a, b)
• gsl sf bessel i0 escalado (a) ↦ → gslsfbesseli0scaled (a)
• gsl sf bessel i1 escala (a) ↦ → gslsfbesseli1scaled (a)
• gsl sf bessel i2 escalado (a) ↦ → gslsfbesseli2scaled (a)
• gsl sf bessel il escala (a, b) ↦ → gslsfbesselilscaled (a, b)
• gsl sf bessel k0 escalado (a) ↦ → gslsfbesselk0scaled (a)
• gsl sf bessel k1 escalado (a) ↦ → gslsfbesselk1scaled (a)
• gsl sf bessel k2 escalado (a) ↦ → gslsfbesselk2scaled (a)
• gsl sf bessel kl escalado (a, b) ↦ → gslsfbesselklscaled (a, b)
• gsl sf bessel Jnu (a, b) ↦ → gslsfbesselJnu (a, b)
• gsl sf bessel Ynu (a, b) ↦ → gslsfbesselYnu (a, b)
• gsl sf bessel Inu escalado (a, b) ↦ → gslsfbesselInuscaled (a, b)
• gsl sf bessel Inu (a, b) ↦ → gslsfbesselInu (a, b)

Página 392

https://translate.googleusercontent.com/translate_f 348/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
392 APÉNDICE D. PLUGIN
• gsl sf bessel Knu escalado (a, b) ↦ → gslsfbesselKnuscaled (a, b)
• gsl sf bessel Knu (a, b) ↦ → gslsfbesselKnu (a, b)
• gsl sf bessel lnKnu (a, b) ↦ → gslsfbessellnKnu (a, b)
• gsl sf bessel zero J0 (a) ↦ → gslsfbesselzeroJ0 (a)
• gsl sf bessel zero J1 (a) ↦ → gslsfbesselzeroJ1 (a)
• gsl sf bessel cero Jnu (a, b) ↦ → gslsfbesselzeroJnu (a, b)
• gsl sf clausen (a) ↦ → gslsfclausen (a)
• gsl sf hydrogenicR 1 (a, b) ↦ → gslsfhydrogenicR1 (a, b)
• gsl sf dawson (a) ↦ → gslsfdawson (a)
• gsl sf debye 1 (a) ↦ → gslsfdebye1 (a)
• gsl sf debye 2 (a) ↦ → gslsfdebye2 (a)
• gsl sf debye 3 (a) ↦ → gslsfdebye3 (a)
• gsl sf debye 4 (a) ↦ → gslsfdebye4 (a)
• gsl sf debye 5 (a) ↦ → gslsfdebye5 (a)
• gsl sf debye 6 (a) ↦ → gslsfdebye6 (a)
• gsl sf dilog (a) ↦ → gslsfdilog (a)
• gsl sf multiplicar (a, b) ↦ → gslsfmultiply (a, b)
• gsl sf ellint Kcomp (a, b) ↦ → gslsfellintKcomp (a, b)
• gsl sf ellint Ecomp (a, b) ↦ → gslsfellintEcomp (a, b)
• gsl sf ellint Pcomp (a, b, c) ↦ → gslsfellintPcomp (a, b, c)
• gsl sf ellint Dcomp (a, b) ↦ → gslsfellintDcomp (a, b)
• gsl sf ellint F (a, b, c) ↦ → gslsfellintF (a, b, c)
• gsl sf ellint E (a, b, c) ↦ → gslsfellintE (a, b, c)
• gsl sf ellint RC (a, b, c) ↦ → gslsfellintRC (a, b, c)
• gsl sf erfc (a) ↦ → gslsferfc (a)
• gsl sf log erfc (a) ↦ → gslsflogerfc (a)
• gsl sf erf (a) ↦ → gslsferf (a)
• gsl sf erf Z (a) ↦ → gslsferfZ (a)
• gsl sf erf Q (a) ↦ → gslsferfQ (a)
• peligro gsl sf (a) ↦ → gslsfhazard (a)
• gsl sf exp (a) ↦ → gslsfexp (a)
• gsl sf exp mult (a, b) ↦ → gslsfexpmult (a, b)
• gsl sf expm1 (a) ↦ → gslsfexpm1 (a)
• gsl sf exprel (a) ↦ → gslsfexprel (a)
• gsl sf exprel 2 (a) ↦ → gslsfexprel2 (a)
• gsl sf exprel n (a, b) ↦ → gslsfexpreln (a, b)
• gsl sf expint E1 (a) ↦ → gslsfexpintE1 (a)
• gsl sf expint E2 (a) ↦ → gslsfexpintE2 (a)
• gsl sf expint En (a, b) ↦ → gslsfexpintEn (a, b)
• gsl sf expint E1 escalado (a) ↦ → gslsfexpintE1scaled (a)
• gsl sf expint E2 escalado (a) ↦ → gslsfexpintE2scaled (a)
• gsl sf expint En escala (a, b) ↦ → gslsfexpintEnscaled (a, b)
• gsl sf expint Ei (a) ↦ → gslsfexpintEi (a)
• gsl sf expint Ei en escala (a) ↦ → gslsfexpintEiscaled (a)
• gsl sf Shi (a) ↦ → gslsfShi (a)
• gsl sf Chi (a) ↦ → gslsfChi (a)
• gsl sf expint 3 (a) ↦ → gslsfexpint3 (a)
• gsl sf Si (a) ↦ → gslsfSi (a)
• gsl sf Ci (a) ↦ → gslsfCi (a)
• gsl sf atanint (a) ↦ → gslsfatanint (a)

Página 393
D.1. GSL 393

• gsl sf fermi dirac m1 (a) ↦ → gslsffermidiracm1 (a)


• gsl sf fermi dirac 0 (a) ↦ → gslsffermidirac0 (a)
• gsl sf fermi dirac 1 (a) ↦ → gslsffermidirac1 (a)
• gsl sf fermi dirac 2 (a) ↦ → gslsffermidirac2 (a)
• gsl sf fermi dirac int (a, b) ↦ → gslsffermidiracint (a, b)
• gsl sf fermi dirac mhalf (a) ↦ → gslsffermidiracmhalf (a)

https://translate.googleusercontent.com/translate_f 349/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
• mitad gsl sf fermi dirac (a) ↦ → gslsffermidirachalf (a)
• gsl sf fermi dirac 3half (a) ↦ → gslsffermidirac3half (a)
• gsl sf fermi dirac inc 0 (a, b) ↦ → gslsffermidiracinc0 (a, b)
• gsl sf lngamma (a) ↦ → gslsflngamma (a)
• gsl sf gamma (a) ↦ → gslsfgamma (a)
• gsl sf gammastar (a) ↦ → gslsfgammastar (a)
• gsl sf gammainv (a) ↦ → gslsfgammainv (a)
• gsl sf taylorcoeff (a, b) ↦ → gslsftaylorcoeff (a, b)
• hecho de gsl sf (a) ↦ → gslsffact (a)
• gsl sf doble hecho (a) ↦ → gslsfdoublefact (a)
• gsl sf lnfact (a) ↦ → gslsflnfact (a)
• gsl sf lndoublefact (a) ↦ → gslsflndoublefact (a)
• gsl sf Inchoose (a, b) ↦ → gslsflnchoose (a, b)
• gsl sf elegir (a, b) ↦ → gslsfchoose (a, b)
• gsl sf lnpoch (a, b) ↦ → gslsflnpoch (a, b)
• gsl sf poch (a, b) ↦ → gslsfpoch (a, b)
• gsl sf pochrel (a, b) ↦ → gslsfpochrel (a, b)
• gsl sf gamma inc Q (a, b) ↦ → gslsfgammaincQ (a, b)
• gsl sf gamma inc P (a, b) ↦ → gslsfgammaincP (a, b)
• gsl sf gamma inc (a, b) ↦ → gslsfgammainc (a, b)
• gsl sf lnbeta (a, b) ↦ → gslsflnbeta (a, b)
• gsl sf beta (a, b) ↦ → gslsfbeta (a, b)
• gsl sf beta inc (a, b, c) ↦ → gslsfbetainc (a, b, c)
• gsl sf gegenpoly 1 (a, b) ↦ → gslsfgegenpoly1 (a, b)
• gsl sf gegenpoly 2 (a, b) ↦ → gslsfgegenpoly2 (a, b)
• gsl sf gegenpoly 3 (a, b) ↦ → gslsfgegenpoly3 (a, b)
• gsl sf gegenpoly n (a, b, c) ↦ → gslsfgegenpolyn (a, b, c)
• gsl sf hyperg 0F1 (a, b) ↦ → gslsfhyperg0F1 (a, b)
• gsl sf hyperg 1F1 int (a, b, c) ↦ → gslsfhyperg1F1int (a, b, c)
• gsl sf hyperg 1F1 (a, b, c) ↦ → gslsfhyperg1F1 (a, b, c)
• gsl sf hyperg U int (a, b, c) ↦ → gslsfhypergUint (a, b, c)
• gsl sf hyperg U (a, b, c) ↦ → gslsfhypergU (a, b, c)
• gsl sf hyperg 2F0 (a, b, c) ↦ → gslsfhyperg2F0 (a, b, c)
• gsl sf laguerre 1 (a, b) ↦ → gslsflaguerre1 (a, b)
• gsl sf laguerre 2 (a, b) ↦ → gslsflaguerre2 (a, b)
• gsl sf laguerre 3 (a, b) ↦ → gslsflaguerre3 (a, b)
• gsl sf laguerre n (a, b, c) ↦ → gslsflaguerren (a, b, c)
• gsl sf lambert W0 (a) ↦ → gslsflambertW0 (a)
• gsl sf lambert Wm1 (a) ↦ → gslsflambertWm1 (a)
• gsl sf legendre Pl (a, b) ↦ → gslsflegendrePl (a, b)
• gsl sf legendre P1 (a) ↦→ gslsflegendreP1 (a)
• gsl sf legendre P2 (a) ↦→ gslsflegendreP2 (a)
• gsl sf legendre P3 (a) ↦→ gslsflegendreP3 (a)
• gsl sf legendre Q0 (a) ↦→ gslsflegendreQ0 (a)

Página 394
394 APÉNDICE D. PLUGIN

• gsl sf legendre Q1 (a) ↦ → gslsflegendreQ1 (a)


• gsl sf legendre Ql (a, b) ↦ → gslsflegendreQl (a, b)
• gsl sf legendre Plm (a, b, c) ↦ → gslsflegendrePlm (a, b, c)
• gsl sf legendre sphPlm (a, b, c) ↦ → gslsflegendresphPlm (a, b, c)
• Tamaño de matriz gsl sf legendre (a, b) ↦ → gslsflegendrearraysize (a, b)
• mitad gsl sf cónicaP (a, b) ↦ → gslsfconicalPhalf (a, b)
• gsl sf cónicoP mhalf (a, b) ↦ → gslsfconicalPmhalf (a, b)
• gsl sf cónicoP 0 (a, b) ↦ → gslsfconicalP0 (a, b)
• gsl sf cónicoP 1 (a, b) ↦ → gslsfconicalP1 (a, b)
• gsl sf cónicoP sph reg (a, b, c) ↦ → gslsfconicalPsphreg (a, b, c)
• gsl sf conicalP cyl reg (a, b, c) ↦ → gslsfconicalPcylreg (a, b, c)
• gsl sf legendre H3d 0 (a, b) ↦ → gslsflegendreH3d0 (a, b)
• gsl sf legendre H3d 1 (a, b) ↦ → gslsflegendreH3d1 (a, b)

https://translate.googleusercontent.com/translate_f 350/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
•• gsl
gsl sf
sf legendre
log (a) H3d (a, b, ↦
c) ↦ → gslsflegendreH3d (a, b, c)
→ gslsflog (a)
• gsl sf log abs (a) ↦ → gslsflogabs (a)
• gsl sf log 1plusx (a) ↦ → gslsflog1plusx (a)
• gsl sf log 1plusx mx (a) ↦ → gslsflog1plusxmx (a)
• gsl sf pow int (a, b) ↦ → gslsfpowint (a, b)
• gsl sf psi int (a) ↦ → gslsfpsiint (a)
• gsl sf psi (a) ↦ → gslsfpsi (a)
• gsl sf psi 1piy (a) ↦ → gslsfpsi1piy (a)
• gsl sf psi 1 int (a) ↦ → gslsfpsi1int (a)
• gsl sf psi 1 (a) ↦ → gslsfpsi1 (a)
• gsl sf psi n (a, b) ↦ → gslsfpsin (a, b)
• sincrotrón gsl sf 1 (a) ↦ → gslsfsynchrotron1 (a)
• sincrotrón gsl sf 2 (a) ↦ → gslsfsynchrotron2 (a)
• transporte gsl sf 2 (a) ↦ → gslsftransport2 (a)
• transporte gsl sf 3 (a) ↦ → gslsftransport3 (a)
• transporte gsl sf 4 (a) ↦ → gslsftransport4 (a)
• transporte gsl sf 5 (a) ↦ → gslsftransport5 (a)
• gsl sf sin (a) ↦ → gslsfsin (a)
• gsl sf cos (a) ↦ → gslsfcos (a)
• gsl sf hypot (a, b) ↦ → gslsfhypot (a, b)
• gsl sf sinc (a) ↦ → gslsfsinc (a)
• gsl sf lnsinh (a) ↦ → gslsflnsinh (a)
• gsl sf lncosh (a) ↦ → gslsflncosh (a)
• gsl sf restricción de ángulo symm (a) ↦ → gslsfanglerestrictsymm (a)
• gsl sf ángulo restringido pos (a) ↦ → gslsfanglerestrictpos (a)
• gsl sf zeta int (a) ↦ → gslsfzetaint (a)
• gsl sf zeta (a) ↦ → gslsfzeta (a)
• gsl sf zetam1 (a) ↦ → gslsfzetam1 (a)
• gsl sf zetam1 int (a) ↦ → gslsfzetam1int (a)
• gsl sf hzeta (a, b) ↦ → gslsfhzeta (a, b)
• gsl sf eta int (a) ↦ → gslsfetaint (a)
• gsl sf eta (a) ↦ → gslsfeta (a)

D.2 ffrandom

Página 395
D.3. CÓDIGO DE ACOPLAMIENTO CON FREEFEM ++ 395

plugin para linux randow functons el rango es generador aleatorio en el rango de 0 a


(2 31 ) - 1

cargar "ffrandom"
srandomdev (); // establece una verdadera semilla de ramdom ..
// advirtiendo debajo de la ventana esto
// cambie la semilla por randinit (random ())) para que todos
// La función aleatoria freefem ++ es cambiada ..
int maxrang = 2ˆ31-1;
cout << "rango máximo" << maxrang << endl;
cout << aleatorio () << endl;
cout << aleatorio () << endl;
cout << aleatorio () << endl;
aleatorio (10);
cout << aleatorio () << endl;
cout << aleatorio () << endl;
cout << aleatorio () << endl;

Código de acoplamiento D.3 con FreeFem ++


https://translate.googleusercontent.com/translate_f 351/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

La idea es simplemente intentar utilizar la comunicación entre procesos utilizando la memoria compartida POSIX en
Linux.
Construimos una pequeña biblioteca libff-mmap-semaphore.cy libff-mmap-semaphore.h
para facilitar la interfaz

mmap: asigna memoria o asigna archivos o dispositivos a la memoria

El semáforo permite que los procesos y los hilos sincronicen sus acciones.

Un semáforo es un número entero cuyo valor nunca puede caer por debajo de cero. Dos op-
Las funciones se pueden realizar en semáforos: incremente el valor del semáforo en uno.
(sem post); y disminuya el valor del semáforo en uno (sem espera). Si el valor de
un semáforo es actualmente cero, luego una operación de espera sem se bloqueará hasta que el valor
se vuelve mayor que cero.

La función de la biblioteca Primero la interfaz del semáforo para realizar la sincronización.

• typedef struct FF_P_sem * ff_Psem; el puntero a la estructura de datos

• ff_Psem ffsem_malloc (); malloc una estructura de datos vacía

• void ffsem_del (ff_Psem sem); limpiar y liberar el puntero

• void ffsem_destroy (ff_Psem sem); limpiar, cerrar la estructura de datos

• void ffsem_init0 (ff_Psem sem); hacer una estructura de datos vacía correcta

• void ffsem_init (ff_Psem sem, const char * nmm, int crea); crear
o usa un nuevo semáforo

Página 396
396 APÉNDICE D. PLUGIN

• largo ffsem_post (ff_Psem sem); bloqueado, el valor del semáforo se incrementa


Mented, y todos los hilos que están esperando en el semáforo se despiertan.

• long ffsem_wait (ff_Psem sem); El semáforo al que hace referencia sem está bloqueado.
Al llamar a sem wait (), si el valor del semáforo es cero, el hilo de llamada
bloquear hasta que se obtenga el bloqueo o hasta que la llamada sea interrumpida por una señal. Alternativamente,
la función sem_trywait () fallará si el semáforo ya está bloqueado, en lugar de
bloqueo en el semáforo.

• long ffsem_trywait (ff_Psem p);

En segundo lugar, la función mmap

• typedef struct FF_P_mmap * ff_Pmmap; el puntero a la estructura de datos

• ff_Psem ffmmap_malloc (); malloc una estructura de datos vacía

• void ffmmap_del (ff_Pmmap p); limpiar y liberar el puntero

• void ffmmap_destroy (ff_Pmmap p); limpiar, cerrar la estructura de datos

• void ffmmap_init0 (ff_Pmmap p); hacer una estructura de datos vacía correcta

• long ffmmap_msync (ff_Pmmap p, long off, long ln); llamada escribe modi-
Fied páginas enteras de nuevo al sistema de archivos y actualiza la hora de modificación del archivo. Solo
Se examinarán las páginas que contengan las ubicaciones sucesivas addr y len-1.

• void ffmmap_init (ff_Pmmap p, const char * nmm, long len); hacer al-
localizar la memoria o mapear archivos o dispositivos en la memoria

• long ffmmap_read (ff_Pmmap p, void * t, size_t n, size_t off); leer


https://translate.googleusercontent.com/translate_f 352/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

n bytes del mmap en la memoria desactivada en el puntero t.

• long ffmmap_write (ff_Pmmap p, void * t, size_t n, size_t off);


escriba n bytes en el mmap en la memoria desactivada en el puntero t.

La función correspondiente de freefem ++

• Pmmap sharedata (nombre de archivo, 1024); nuevo tipo para almacenar la información de mmap de
name store in string filename with 1024 es el tamaño de la zona y el archivo de datos compartidos.

• Psemaphore smff ("ff-esclavo", creat); nuevo tipo para almacenar el semáforo del nombre
ff-slave donde creat es un booleano para crear o usar un semáforo existente.

• Wait (sem) El semáforo al que hace referencia sem está bloqueado. Al llamar
Espere (sem), si el valor del semáforo es cero, el hilo de llamada bloqueará un-
hasta que se adquiere el bloqueo o hasta que la llamada es interrumpida por una señal. Alterna-
tivamente, la función trywait (sem) fallará si el semáforo es
ya bloqueado, en lugar de bloquear en el semáforo.

• Post (sem) El semáforo al que hace referencia sem está desbloqueado, el


El valor del semáforo se incrementa, y todos los hilos que
están esperando en el semáforo se despiertan.

Página 397
D.3. CÓDIGO DE ACOPLAMIENTO CON FREEFEM ++ 397

• Leer (compartir datos, compensación, datos); leer los datos variables del
colocar offset en sharedata mmap.

• Escritura (compartir datos, compensación, datos); escribir los datos de la variable en el


colocar offset en sharedata mmap.

El ejemplo completo:
el archivo ffmaster.c C

#incluya "libff-mmap-semaphore.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
ff_Psem sem_ff, sem_c; // el semáforo para mutex
int main (int argc, const char ** argv)
{
int debug = 0;
ff_Pmmap shd;
doble cff, rff;
estado largo;
if (argc> 1) debug = atoi (argv [1]);
ff_mmap_sem_verb = depurar;

sem_ff = ffsem_malloc ();


sem_c = ffsem_malloc ();
shd = ffmmap_malloc ();

ffsem_init (sem_ff, "ff-esclavo", 1);


ffsem_init (sem_c, "ff-master", 1);
ffmmap_init (shd, "datos compartidos", 1024);

estado = 1;
ffmmap_write (shd, & estado, tamaño de (estado), 8);
ffmmap_msync (shd, 0,32);

char ff [1024];

https://translate.googleusercontent.com/translate_f 353/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
sprintf (ff, "FreeFem ++ ffslave.edp -nw -ns -v% d &", depurar);
sistema (ff); // Lauch FF ++ en lote no graphique
if (debug) printf ("cc: antes de esperar \ n");

if (debug) printf ("cc: antes de esperar 0 ff \ n");


ffsem_wait (sem_ff);

para (int i = 0; i <10; ++ i)


{
printf ("iter:% d \ n", i);
cff = 10 + i;
ffmmap_write (shd, & cff, sizeof (cff), 0);
ffsem_post (sem_c);

Página 398
398 APÉNDICE D. PLUGIN

if (debug) printf ("cc: antes de esperar 2 \ n");


ffsem_wait (sem_ff);
ffmmap_read (shd, & rff, tamaño de (rff), 16);
printf ("iter =% d rff =% f \ n", i, rff);
}
estado = 0; // Aleta
ffmmap_write (shd, & estado, tamaño de (estado), 8);
ffsem_post (sem_c);
printf ("Fin Master \ n");
ffsem_wait (sem_ff);
ffsem_del (sem_ff);
ffsem_del (sem_c);
ffmmap_del (shd);
return 0;
}

el archivo de script ffslave.edp freefem ++

cargar "ff-mmap-semaphore"
Psemaphore smff ("ff-esclavo", 0);
Psemaphore smc ("ff-master", 0);
Pmmap sharedata ("datos compartidos", 1024);
if (verbosidad <4) verbosidad = 0;
malla Th = cuadrado (10,10);
fespace Vh (Th, P1);
Vh u, v;
int [int] Lab = [1,2,3,4];

macro grad (u) [dx (u), dy (u)] //

int status = 1;
cout << "estado =" << estado << endl;
real cff, rff;
problema Pb (u, v) = int2d (Th) (grad (u) '* grad (v)) - int2d (Th) (cff * v) + on (Lab, u = 0);
if (verbosidad> 9) cout << "ff: before ff post \ n";
Publicar (smff); // desbloquear master fin init

mientras (1)
{
if (verbosidad> 9) cout << "ff: before ff wait \ n";
Espere (smc); // espera de cint ecriture ok
Leer (compartir datos, 0, cff);
Leer (compartir datos, 8, estado);

cout << ".. ff" << cff << "" << estado << endl;

https://translate.googleusercontent.com/translate_f 354/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
si
Pb;(estado <= 0) romper;
rff = int2d (Th) (u * u);
cout << "** ff" << cff << "" << rff << endl;

Escribir (sharedata, 16, rff);


Publicar (smff); // desbloquear cc
}

Página 399
D.3. CÓDIGO DE ACOPLAMIENTO CON FREEFEM ++ 399

Publicar (smff); // espera de cint


cout << "Fin FreeFem ++" << endl;

Para probar este ejemplo de acoplamiento del programa c y el script freemfem ++, haga lo siguiente:

cc -c libff-mmap-semaphore.c
cc ffmaster.c -o ffmaster libff-mmap-semaphore.o -g
# crear el complemento freefem ++
ff-c ++ -auto ff-mmap-semaphore.cpp
# lanzar la prueba
./ffmaster
La salida:
broche: ejemplos ++ - cargar hecht $ ./ffmaster
len 1024 tamaño 1024
len 1024 tamaño 1024
estado = 1
iter: 0
.. ff 10 1
** ff 10 0.161797
iter = 0 rff = 0.161797
iter: 1
.. ff 11 1
...
iter: 9
.. ff 19 1
** ff 19 0.584086
iter = 9 rff = 0.584086
Maestro de aletas
.. ff 19 0
Fin FreeFem ++
broche: ejemplos ++ - cargar hecht $

https://translate.googleusercontent.com/translate_f 355/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 400
400 APÉNDICE D. PLUGIN

https://translate.googleusercontent.com/translate_f 356/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Página 401

Licencia LGPL FreeFem ++

Este es el software FreeFem ++. Los programas en él fueron mantenidos por


• Frédéric hecht <Frederic.Hecht@upmc.fr>

• Jacques Morice <morice@ann.jussieu.fr>

Todos sus programas excepto los archivos que provienen del software COOOL (archivos en el directorio src / Algo)
y el archivo mt19937ar.cpp que puede ser redistribuido bajo los términos de GNU
LICENCIA PÚBLICA GENERAL MENOR Versión 2.1, febrero de 1999
TÉRMINOS Y CONDICIONES DE LA LICENCIA PÚBLICA GENERAL MENOR GNU PARA COPIA
ING, DISTRIBUCIÓN Y MODIFICACIÓN
0. Este Acuerdo de licencia se aplica a cualquier biblioteca de software u otro programa que contenga un
aviso colocado por el titular de los derechos de autor u otra parte autorizada diciendo que puede ser distribuido
bajo los términos de esta Licencia Pública General Reducida (también llamada "esta Licencia"). Cada
al titular de la licencia se le llama "usted".
Una "biblioteca" significa una colección de funciones de software y / o datos preparados para ser
convenientemente vinculado con programas de aplicación (que utilizan algunas de esas funciones y datos) para
forma ejecutables.
La "Biblioteca", a continuación, se refiere a cualquier biblioteca de software o trabajo que se haya distribuido
bajo estos términos. Un "trabajo basado en la biblioteca" significa la biblioteca o cualquier derivado
obra bajo la ley de derechos de autor: es decir, una obra que contiene la Biblioteca o una parte de ella,
ya sea textualmente o con modificaciones y / o traducido directamente a otro idioma
calibre. (En adelante, la traducción se incluye sin limitación en el término "modificación").
"Código fuente" para un trabajo significa la forma preferida del trabajo para realizar modificaciones en
eso. Para una biblioteca, el código fuente completo significa todo el código fuente de todos los módulos que contiene,
más cualquier archivo de definición de interfaz asociado, más los scripts utilizados para controlar la compilación y
instalación de la biblioteca.
Las actividades distintas de la copia, distribución y modificación no están cubiertas por esta Licencia;
están fuera de su alcance. El acto de ejecutar un programa utilizando la biblioteca no está restringido,
y la salida de dicho programa se cubre sólo si su contenido constituye un trabajo basado en
la Biblioteca (independiente del uso de la Biblioteca en una herramienta para escribirla). Si eso es
verdadero depende de lo que haga la biblioteca y de lo que haga el programa que usa la biblioteca.
1. Puede copiar y distribuir copias textuales del código fuente completo de la biblioteca como
lo recibe, en cualquier medio, siempre que lo publique de manera visible y adecuada
en cada copia, un aviso de derechos de autor apropiado y una renuncia de garantía; mantener intactos todos los
avisos que se refieren a esta Licencia y a la ausencia de garantía; y distribuir una copia
de esta Licencia junto con la Biblioteca.
Puede cobrar una tarifa por el acto físico de transferir una copia y, a su elección, puede
ofrecer protección de garantía a cambio de una tarifa.

401

Página 402
402 APÉNDICE D. PLUGIN

2. Puede modificar su copia o copias de la Biblioteca o cualquier parte de ella, formando así una
trabajar basado en la Biblioteca, y copiar y distribuir dichas modificaciones o trabajar bajo la
términos de la Sección 1 anterior, siempre que también cumpla con todas estas condiciones:
a) El trabajo modificado debe ser en sí mismo una biblioteca de software.
https://translate.googleusercontent.com/translate_f 357/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
b) Debe hacer que los archivos modificados lleven avisos prominentes que indiquen que cambió
los archivos y la fecha de cualquier cambio.
c) Debe hacer que la totalidad del trabajo tenga licencia sin cargo para todos los terceros.
bajo los términos de esta Licencia.
d) Si una instalación en la Biblioteca modificada se refiere a una función o una tabla de datos que se deben suministrar
por un programa de aplicación que utiliza la facilidad, que no sea como un argumento pasado cuando el
se invoca la instalación, entonces debe hacer un esfuerzo de buena fe para asegurarse de que, en caso de
La aplicación no proporciona dicha función o tabla, la instalación aún funciona y realiza
cualquier parte de su propósito sigue siendo significativa.
(Por ejemplo, una función en una biblioteca para calcular raíces cuadradas tiene un propósito que
infatigablemente bien definido independientemente de la aplicación. Por lo tanto, la subsección 2d requiere que
Cualquier función o tabla proporcionada por la aplicación utilizada por esta función debe ser opcional: si el
la aplicación no lo proporciona, la función de raíz cuadrada aún debe calcular raíces cuadradas).
Estos requisitos se aplican a la obra modificada en su conjunto. Si secciones identificables de eso
El trabajo no se deriva de la Biblioteca y puede considerarse razonablemente independiente y
obras independientes en sí mismas, esta Licencia y sus términos no se aplican a esas secciones
cuando los distribuye como obras independientes. Pero cuando distribuye las mismas secciones que
parte de un todo que es una obra basada en la Biblioteca, la distribución del todo debe
estar en los términos de esta Licencia, cuyos permisos para otros licenciatarios se extienden a todo el
todo, y por lo tanto a todas y cada una de las partes independientemente de quién lo haya escrito.
Por lo tanto, esta sección no tiene la intención de reclamar derechos o impugnar sus derechos sobre el trabajo escrito
enteramente por usted; más bien, la intención es ejercer el derecho a controlar la distribución de
obras derivadas o colectivas basadas en la Biblioteca.
Además, la mera agregación de otro trabajo no basado en la Biblioteca con la Biblioteca
(o con un trabajo basado en la Biblioteca) en un volumen de un medio de almacenamiento o distribución
no incluir el otro trabajo bajo el alcance de esta Licencia.
3. Puede optar por aplicar los términos de la Licencia Pública General GNU ordinaria en lugar de
esta Licencia a una copia determinada de la Biblioteca. Para hacer esto, debe modificar todos los avisos que
referirse a esta Licencia, para que se refieran a la Licencia Pública General GNU ordinaria, versión
2, en lugar de a esta Licencia. (Si una versión más reciente que la versión 2 del GNU General ordinario
Ha aparecido una licencia pública, entonces puede especificar esa versión en su lugar si lo desea).
realizar cualquier otro cambio en estos avisos.
Una vez que se realiza este cambio en una copia determinada, es irreversible para esa copia, por lo que el
La Licencia Pública General GNU se aplica a todas las copias posteriores y trabajos derivados realizados
de esa copia.
Esta opción es útil cuando desea copiar parte del código de la biblioteca en un programa.
eso no es una biblioteca.
4. Puede copiar y distribuir la Biblioteca (o una parte o un derivado de ella, según la Sección 2)
en código objeto o en forma ejecutable según los términos de las Secciones 1 y 2 anteriores siempre que
lo acompaña con el código fuente completo legible por máquina correspondiente, que
deben distribuirse según los términos de las Secciones 1 y 2 anteriores en un medio habitualmente
utilizado para el intercambio de software.
Si la distribución del código objeto se realiza ofreciendo acceso para copiar desde un lugar designado,

Página 403
D.3. CÓDIGO DE ACOPLAMIENTO CON FREEFEM ++ 403

luego ofrecer acceso equivalente para copiar el código fuente desde el mismo lugar satisface el
requisito de distribuir el código fuente, aunque los terceros no estén obligados a
copie la fuente junto con el código objeto.
5. Un programa que no contiene ningún derivado de ninguna parte de la biblioteca, pero que está diseñado para
trabajar con la biblioteca al ser compilado o vinculado con ella, se denomina "trabajo que utiliza el
Biblioteca". Tal trabajo, de forma aislada, no es un trabajo derivado de la Biblioteca, y por lo tanto
queda fuera del alcance de esta Licencia.
Sin embargo, vincular un "trabajo que utiliza la biblioteca" con la biblioteca crea un ejecutable que
es un derivado de la biblioteca (porque contiene partes de la biblioteca), en lugar de un
"Obra que utiliza la biblioteca". Por lo tanto, el ejecutable está cubierto por esta Licencia. Sección 6
establece los términos para la distribución de dichos ejecutables.
https://translate.googleusercontent.com/translate_f 358/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
Cuando un "trabajo que usa la biblioteca" usa material de un archivo de encabezado que es parte del
Biblioteca, el código objeto del trabajo puede ser un trabajo derivado de la Biblioteca, aunque
el código fuente no lo es. Si esto es cierto es especialmente importante si el trabajo se puede vincular
sin la Biblioteca, o si la obra es en sí misma una biblioteca. El umbral para que esto sea cierto no es
definido con precisión por la ley.
Si un archivo de objeto de este tipo utiliza solo parámetros numéricos, diseños de estructura de datos y descriptores de acceso,
y pequeñas macros y pequeñas funciones en línea (diez líneas o menos de longitud), luego el uso de la
El archivo de objeto no tiene restricciones, independientemente de si es legalmente un trabajo derivado. (Ejecutables
que contengan este código de objeto más partes de la Biblioteca aún se incluirán en la Sección 6.)
De lo contrario, si el trabajo es un derivado de la Biblioteca, puede distribuir el código objeto para
el trabajo bajo los términos de la Sección 6. Cualquier ejecutable que contenga ese trabajo también cae bajo
Sección 6, estén o no vinculadas directamente con la propia Biblioteca.
6. Como excepción a las secciones anteriores, también puede combinar o vincular una "obra que utilice
la Biblioteca ”con la Biblioteca para producir un trabajo que contenga partes de la Biblioteca, y
distribuir ese trabajo bajo los términos de su elección, siempre que los términos permitan la modificación
cación del trabajo para uso propio del cliente e ingeniería inversa para depurar tales
modificaciones.
Debe dar un aviso destacado con cada copia del trabajo de que la Biblioteca se utiliza en él.
y que la Biblioteca y su uso están cubiertos por esta Licencia. Debe proporcionar una copia de
esta licencia. Si el trabajo durante la ejecución muestra avisos de derechos de autor, debe incluir el
aviso de derechos de autor para la Biblioteca entre ellos, así como una referencia que dirige al usuario a la
copia de esta licencia. Además, debe hacer una de estas cosas:
a) Acompañar el trabajo con el código fuente completo legible por máquina correspondiente para
la Biblioteca, incluidos los cambios que se utilizaron en el trabajo (que deben distribuirse
en las Secciones 1 y 2 anteriores); y, si el trabajo es un ejecutable vinculado con la Biblioteca,
con el "trabajo completo legible por máquina que utiliza la biblioteca", como código objeto y / o
código fuente, de modo que el usuario pueda modificar la biblioteca y luego volver a vincular para producir una modificación
ejecutable que contiene la biblioteca modificada. (Se entiende que el usuario que cambia
el contenido de los archivos de definiciones en la biblioteca no necesariamente podrá volver a compilar el
aplicación para utilizar las definiciones modificadas.)
b) Utilice un mecanismo de biblioteca compartida adecuado para vincularse con la biblioteca. Un mecanismo adecuado
anismo es uno que (1) utiliza en tiempo de ejecución una copia de la biblioteca ya presente en el usuario
sistema informático, en lugar de copiar las funciones de la biblioteca en el ejecutable, y (2)
funcionar correctamente con una versión modificada de la biblioteca, si el usuario instala una, siempre que
la versión modificada es compatible con la interfaz con la versión con la que se realizó el trabajo.
c) Acompañar el trabajo con una oferta escrita, válida por al menos tres años, para dar la misma

Página 404
404 APÉNDICE D. PLUGIN

utilizar los materiales especificados en la Subsección 6a, arriba, por un cargo no mayor que el costo de
realizar esta distribución.
d) Si la distribución de la obra se realiza ofreciendo acceso a copia desde un lugar designado,
ofrecer acceso equivalente para copiar los materiales especificados anteriormente desde el mismo lugar.
e) Verifique que el usuario ya haya recibido una copia de estos materiales o que ya haya
envió a este usuario una copia.
Para un ejecutable, la forma requerida del "trabajo que usa la biblioteca" debe incluir cualquier
datos y programas de utilidad necesarios para reproducir el ejecutable a partir de él. Sin embargo, como
excepción especial, los materiales que se distribuirán no necesitan incluir nada que normalmente sea
distribuido (ya sea en formato fuente o binario) con los componentes principales (compilador, kernel,
y así sucesivamente) del sistema operativo en el que se ejecuta el ejecutable, a menos que ese componente
sí mismo acompaña al ejecutable.
Puede suceder que este requisito contradiga las restricciones de licencia de otros propietarios
bibliotecas que normalmente no acompañan al sistema operativo. Tal contradicción significa
no puede usarlos a ambos y la biblioteca juntos en un ejecutable que distribuya.
7. Puede colocar las instalaciones de la biblioteca que son un trabajo basado en la Biblioteca una al lado de la otra en un
biblioteca individual junto con otras instalaciones de biblioteca no cubiertas por esta licencia, y distribuir
tal biblioteca combinada, siempre que la distribución separada de la obra basada en la

https://translate.googleusercontent.com/translate_f 359/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
La biblioteca y de las otras instalaciones de la biblioteca está permitida, y siempre que lo haga
estas dos cosas:
a) Acompañar la biblioteca combinada con una copia del mismo trabajo basado en la Biblioteca,
sin combinar con otras instalaciones de la biblioteca. Esto debe distribuirse bajo los términos de
las secciones anteriores.
b) Dar aviso prominente con la biblioteca combinada del hecho de que parte de ella es una obra
basado en la biblioteca, y explicando dónde encontrar la forma no combinada de acompañamiento
el mismo trabajo.
8. No puede copiar, modificar, sublicenciar, vincular o distribuir la Biblioteca, excepto cuando
proporcionado expresamente bajo esta Licencia. Cualquier intento de copiar, modificar, sublicenciar,
vincular o distribuir la Biblioteca es nulo y automáticamente terminará sus derechos
bajo esta Licencia. Sin embargo, las partes que hayan recibido copias o derechos de usted bajo
esta Licencia no tendrá sus licencias rescindidas mientras dichas partes permanezcan en su totalidad
cumplimiento.
9. No es necesario que acepte esta Licencia, ya que no la ha firmado. Sin embargo, nada
else le otorga permiso para modificar o distribuir la Biblioteca o sus trabajos derivados. Estas
Las acciones están prohibidas por ley si no acepta esta Licencia. Por tanto, modificando o
distribuir la Biblioteca (o cualquier trabajo basado en la Biblioteca), usted indica su aceptación de
esta Licencia para hacerlo, y todos sus términos y condiciones para copiar, distribuir o modificar
la Biblioteca u obras basadas en ella.
10. Cada vez que redistribuye la Biblioteca (o cualquier trabajo basado en la Biblioteca), el destinatario
recibe automáticamente una licencia del licenciante original para copiar, distribuir, vincular o
modificar la Biblioteca sujeto a estos términos y condiciones. No puedes imponer más
restricciones al ejercicio por parte de los destinatarios de los derechos aquí otorgados. Tu no eres responsable
para exigir el cumplimiento por parte de terceros de esta Licencia.
11. Si, como consecuencia de una sentencia judicial o alegación de infracción de patente o por
cualquier otro motivo (no limitado a cuestiones de patentes), se le imponen condiciones (ya sea por
orden judicial, acuerdo o de otro tipo) que contradigan las condiciones de esta Licencia, no
no lo exime de las condiciones de esta Licencia. Si no puede distribuir para satisfacer

Página 405
D.3. CÓDIGO DE ACOPLAMIENTO CON FREEFEM ++ 405

simultáneamente sus obligaciones bajo esta Licencia y cualquier otra obligación pertinente, luego
como consecuencia, no puede distribuir la Biblioteca en absoluto. Por ejemplo, si una licencia de patente
no permitiría la redistribución libre de regalías de la biblioteca por parte de todos aquellos que reciban copias
directa o indirectamente a través de usted, entonces la única forma en que podría satisfacer tanto a este como a este
La licencia consistiría en abstenerse por completo de distribuir la Biblioteca.
Si alguna parte de esta sección se considera inválida o inaplicable bajo cualquier circunstancia particular
postura, se pretende que se aplique el saldo de la sección, y se pretende que la sección en su conjunto
para aplicar en otras circunstancias.
No es el propósito de esta sección inducirlo a infringir ninguna patente u otra propiedad
reclamos de derechos o para impugnar la validez de dichos reclamos; esta sección tiene el único propósito de
proteger la integridad del sistema de distribución de software libre implementado por
prácticas de licencias públicas. Muchas personas han hecho contribuciones generosas a la amplia gama
de software distribuido a través de ese sistema en función de la aplicación coherente de ese
sistema; Depende del autor / donante decidir si está dispuesto a distribuir software.
a través de cualquier otro sistema y un licenciatario no puede imponer esa elección.
Esta sección está destinada a dejar completamente en claro lo que se cree que es una consecuencia de
el resto de esta Licencia.
12. Si la distribución y / o uso de la Biblioteca está restringido en ciertos países por
patentes o por interfaces con derechos de autor, el titular original de los derechos de autor que coloca la Biblioteca
bajo esta Licencia puede agregar una limitación de distribución geográfica explícita excluyendo aquellos
países, de modo que la distribución esté permitida solo en o entre países no excluidos. En
En tal caso, esta Licencia incorpora la limitación como si estuviera escrita en el cuerpo de esta Licencia.
13. La Free Software Foundation puede publicar versiones revisadas y / o nuevas del Lesser
Licencia Pública General de vez en cuando. Estas nuevas versiones serán similares en espíritu a las
versión actual, pero pueden diferir en detalles para abordar nuevos problemas o inquietudes.

https://translate.googleusercontent.com/translate_f 360/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
A cada versión se le asigna un número de versión distintivo. Si la biblioteca especifica una versión
número de esta Licencia que se aplica a ella y "cualquier versión posterior", tiene la opción de
siguiendo los términos y condiciones de esa versión o de cualquier versión posterior publicada por
la Free Software Foundation. Si la biblioteca no especifica un número de versión de licencia,
puede elegir cualquier versión publicada por la Free Software Foundation.
14. Si desea incorporar partes de la biblioteca en otros programas gratuitos cuya distribución
las condiciones son incompatibles con estas, escribir al autor para pedir permiso. Para
software que está protegido por derechos de autor de la Free Software Foundation, escriba al software libre
Fundación; a veces hacemos excepciones para esto. Nuestra decisión estará guiada por los dos
objetivos de preservar el estado libre de todos los derivados de nuestro software libre y de promover la
compartir y reutilizar software en general.
SIN GARANTÍA
15. DEBIDO A QUE LA BIBLIOTECA TIENE UNA LICENCIA GRATUITA, NO HAY
GARANTÍA PARA LA BIBLIOTECA, EN LA MEDIDA PERMITIDA POR LA APLICACIÓN
LEY BLE. EXCEPTO CUANDO SE INDIQUE LO CONTRARIO POR ESCRITO EL DERECHO DE AUTOR
LOS TITULARES Y / U OTRAS PARTES PROPORCIONAN LA BIBLIOTECA "TAL CUAL" SIN
GARANTÍA DE CUALQUIER TIPO, YA SEA EXPRESA O IMPLÍCITA, INCLUYENDO, PERO
SIN LIMITARSE A, LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD Y AJUSTE
NESS PARA UN PROPÓSITO PARTICULAR. TODO EL RIESGO EN CUANTO A LA CALIDAD
Y EL RENDIMIENTO DE LA BIBLIOTECA ESTÁ CON USTED. DEBE LA BIBLIOTECA
RESULTAR DEFECTUOSO, USTED ASUME EL COSTE DE TODOS LOS SERVICIOS NECESARIOS,
REPARACIÓN O CORRECCIÓN.

Página 406
406 APÉNDICE D. PLUGIN

16. EN NINGÚN CASO A MENOS QUE LO REQUIERA LA LEY APLICABLE O ACORDADO


POR ESCRITO, CUALQUIER TITULAR DE LOS DERECHOS DE AUTOR O CUALQUIER OTRA PARTE QUE
PUEDE MODIFICAR Y / O REDISTRIBUIR LA BIBLIOTECA COMO SE PERMITE ARRIBA,
SERÁ RESPONSABLE ANTE USTED POR DAÑOS, INCLUYENDO CUALQUIER
DAÑOS CIDENTALES O CONSECUENTES QUE SURJAN DEL USO O IN-
HABILIDAD PARA USAR LA BIBLIOTECA (INCLUYENDO, PERO NO LIMITADO A LA PÉRDIDA DE
DATOS O DATOS REPRESENTADOS INEXACTITOS O PÉRDIDAS SOSTENIDAS POR
USTED O TERCEROS O UNA FALLA DE LA BIBLIOTECA PARA OPERAR CON
CUALQUIER OTRO SOFTWARE), INCLUSO SI DICHO TITULAR U OTRA PARTE HA SIDO
INFORMADO DE LA POSIBILIDAD DE TALES DAÑOS.
FIN DE TÉRMINOS Y CONDICIONES

https://translate.googleusercontent.com/translate_f 361/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 407

Apéndice E

Palabras clave

Palabras clave principales tiempo

Segunda categoría de palabras clave


adaptmesh
Cmatrix
int1d
R3
int2d
bool
en
frontera
cuadrado
rotura
buildmesh Tercera categoría de palabras clave
captura
cin
dx
complejo
dy
Seguir
convecto
cout
saltar
elemento significar
demás
final
fespace Cuarta categoría de palabras clave
por
func
Si Espere
ifstream PD
incluir solucionador
En t CG
asistencia LU
carga UMFPACK
macro factorizar
matriz en eso
malla endl
movemesh
ofstream
Otras palabras reservadas
gráfico

https://translate.googleusercontent.com/translate_f 362/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
problema
verdadero x, y, z, pi, i,
regreso pecado, cos, bronceado, atan, asin, acos,
savemesh cotan, sinh, cosh, tanh, cotanh,
resolver exp, log, log10, sqrt
cuerda abs, max, min,
intentar
lanzar
vértice
varf

407

Página 408
408 APÉNDICE E. PALABRAS CLAVE

https://translate.googleusercontent.com/translate_f 363/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 409

Bibliografía

[1] Guía del usuario de RB Lehoucq, DC Sorensen y C. Yang ARPACK: solución


de problemas de valores propios a gran escala con los métodos Arnoldi reiniciados implícitamente SIAM,
ISBN 0-89871-407-9 // http://www.caam.rice.edu/software/ARPACK/

[2] I. Babbuška, Límites de error para el método de elementos finitos, Numérico. Matemáticas. 16, 322-333.

[3] Y. Achdou y O. Pironneau, Métodos computacionales para la fijación de precios de opciones. SIAM
monografía (2005).

[4] Satish Balay, Shrirang Abhyankar, Mark F. Adams, Jed Brown, Peter Brune, Kris
Buschelman, Victor Eijkhout, William D. Gropp, Dinesh Kaushik, Matthew G. Knepley,
Lois Curfman McInnes, Karl Rupp, Barry F. Smith y Hong Zhang. PETSc Web
página. http://www.mcs.anl.gov/petsc, 2014.

[5] Satish Balay, William D. Gropp, Lois Curfman McInnes y Barry F. Smith. Eficiente
gestión del paralelismo en bibliotecas de software numéricas orientadas a objetos. En E. Arge,
AM Bruaset y HP Langtangen, editores de Modern Software Tools en Scientific
Computación, páginas 163–202. Birkhäuser Press, 1997.

[6] Pierre Jolivet y Frédéric Nataf. Hpddm: marco unificado de alto rendimiento para Do-
principales métodos de descomposición, biblioteca MPI-C ++. https://github.com/hpddm/hpddm.

[7] Dolean, Jolivet y Nataf. Introducción a la descomposición de dominios


posición Métodos: algoritmos, teoría y implementación paralela,
2015 https://hal.archives-ouvertes.fr/cel-01100932,
Nota a aparecer en la colección de SIAM,

[8] D. Bernardi, F.Hecht, K. Ohtsuka, O. Pironneau, documentación freefem +,


en la web en ftp://www.freefem.org/freefemplus.

[9] D. Bernardi, F.Hecht, O. Pironneau, C. Prud'homme, documentación freefem,


en la web en http://www.freefem.fr/freefem

[10] TA Davis: Algoritmo 8xx: UMFPACK V4.1, un multifrontal de patrón asimétrico


método TOMS, 2003 (enviado para publicación ) http://www.cise.ufl.edu/
investigación / escasa / umfpack

[11] PL George, triangulación automática, Wiley 1996.

[12] F. Hecht, Outils et algorítmes pour la méthode des éléments finis, HdR, Université
Pierre et Marie Curie, Francia, 1992

409

https://translate.googleusercontent.com/translate_f 364/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 410
410 BIBLIOGRAFÍA

[13] F. Hecht, El software de adaptación de mallas: bamg. Informe INRIA 1998.

[14] A. Perronnet et. Alabama. Módulo de bibliotecaf, INRIA , http: //www.inria-rocq/


módulof

[15] M. Bernadou, JM Boisserie y K. Hassan Sur l'implı¿½mentation des


ı¿½lı¿½ments finis de HsieH-Clough-Tocher complet et rı¿½duit, RR 4 INRIA, (1980)
¡Inria- 00076557¿

[16] A. Ern y J.-L. Guermond, métodos de Galerkin discontinuos para el síndrome de Friedrichs
sistemas métricos y PDE de segundo orden, SIAM J. Numer. Anal., (2005). Ver también:
Teoría y práctica de los elementos finitos, vol. 159 de Ciencias Matemáticas Aplicadas,
Springer-Verlag, Nueva York, NY, 2004.

[17] F. Hecht. Herramientas C ++ para construir nuestro lenguaje a nivel de usuario. Vol 36, Nı¿½, 2002 págs.
809-836, Modél. matemáticas y Anal Numér.

[18] JL Lions, O. Pironneau: Algoritmos paralelos para problemas de valores de contorno, nota
CRAS. Diciembre de 1998. También: Superposiciones para dominios compuestos (por aparecer)

[19] B. Lucquin, O. Pironneau: Introducción a la informática científica Wiley 1998.

[20] I. Danaila, F. Hecht y O. Pironneau. Simulación numérique en C ++. Dunod,


París, 2003.

[21] J. Necas, L. Hlavácek, Teoría matemática de cuerpos elásticos y elastoplásticos:


Una introducción, Elsevier, 1981.

[22] K. Ohtsuka, O. Pironneau y F. Hecht: análisis teórico y numérico


de la tasa de liberación de energía en fractura 2D, INFORMACIÓN 3 (2000), 303–315.

[23] F. Preparata, M. Shamos Computational Geometry Springer series in Computer


ciencias, 1984.

[24] R. Rannacher: Sobre el método de proyección de Chorin para los incompresibles Navier-Stokes
ecuaciones, en "Ecuaciones de Navier-Stokes: teoría y métodos numéricos" (R. Raut-
mann, et al., eds.), Proc. Oberwolfach Conf., 19-23 de agosto de 1991, Springer, 1992

[25] JE Roberts y Thomas J.-M: Métodos mixtos e híbridos, Manual de Nu-


Análisis merical, Vol.II, Holanda Septentrional, 1993

[26] JL Steger: El método Chimera de simulación de flujo, Taller sobre CFD aplicado,
Instituto Espacial de la Universidad de Tennessee, agosto de 1991.

[27] M. Tabata: Soluciones numéricas de ecuaciones diferenciales parciales II (en japonés),


Matemáticas aplicadas de Iwanami, 1994

[28] F. Thomasset: Implementación de métodos de elementos finitos de las ecuaciones de Navier-Stokes,


Springer-Verlag, 1981

[29] N. Wirth: Algoritmos + Estructuras de datos = Programas, Prentice Hall, 1976

Página 411
BIBLIOGRAFÍA 411

[30] Bison La documentación del compilador-compilador GNU (en la web).

https://translate.googleusercontent.com/translate_f 365/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
[31] B. Stroustrup, The C ++, lenguaje de programación, tercera edición, Addison-Wesley
1997.

[32] L. Deng, Wences Gouveia, COOOL: un paquete de herramientas para la optimización de la escritura
código y resolución de problemas de optimización , http://coool.mines.edu

[33] B. Riviere, M. Wheeler, V. Girault, Estimaciones de error a priori para elementos finitos
métodos basados en espacios de aproximación discontinuos para problemas elípticos. SIAM J.
Numer. Anal. 39 (2001), núm. 3, 902–931 (electrónico).

[34] R. Glowinski y O. Pironneau, Métodos numéricos para el problema de Stokes, capítulo


ter 13 de Métodos de energía en el análisis de elementos finitos, R. Glowinski, EY Rodin, OC
Zienkiewicz eds., J. Wiley & Sons, Chichester, Reino Unido, 1979, págs. 243-264.

[35] R. Glowinski, Métodos numéricos para problemas variacionales no lineales, Springer-


Verlag, Nueva York, NY, 1984.

[36] R. Glowinski, Métodos de elementos finitos para flujo viscoso incompresible. En la mano
libro de análisis numérico, vol. IX, PG Ciarlet y JL Lions, eds., Holanda Septentrional,
Amsterdam, 2003, págs. 3-1176.

[37] C. Horgan, G. Saccomandi, Modelos constitutivos para compresibles no lineales


Materiales elásticos con extensibilidad de cadena limitante, Journal of Elasticity, Volumen 77,
Número 2, noviembre de 2004, págs. 123-138 (16).

[38] Kazufumi Ito y Karl Kunisch, Métodos de newton semi liso para variaciones
desigualdades del primer tipo, M2AN, vol 37, N ◦ , 2003, pp 41-62.

[39] RW Ogden, Deformaciones elásticas no lineales, Dover, 1984.

[40] PA Raviart, JM Thomas, Introducción `a l'analyse numérique des équations aux


dérivées partielles, Masson, 1983.

[41] Hang Si, TetGen Users 'Guide: Un generador de malla tetraédrica de calidad y tres
Triangulador dimensional de Delaunay // http://tetgen.berlios.de

[42] JR Shewchuk, Generación de mallas tetraédricas por el procedimiento de refinamiento de Delaunay


del Decimocuarto Simposio Anual sobre Geometría Computacional (Minneapolis, Min-
nesota), págs. 86–95, 1998.

[43] MA Taylor, BA Wingate, LP Bos, Varias fórmulas de cuadratura nuevas para


Integración polinomial en el triángulo, Número de informe: SAND2005-0034J , http: // xyz.
lanl.gov/format/math.NA/0501496

[44] P. Willmott, S. Howison, J. Dewynne: Una introducción del estudiante a las matemáticas
finanzas, Cambridge University Press (1995).

[45] P. Frey, Un procedimiento de remallado de superficie isotrópico adaptativo totalmente automático. INRIA
RT – 0252, 2001.

Página 412
412 BIBLIOGRAFÍA

[46] Astrid Sabine Sinwel, Una nueva familia de elementos finitos mixtos para Elas-
ticidad http://www.numa.uni-linz.ac.at/Teaching/PhD/Finished/
sinwel-diss.pdf, Tesis , 2009, Universidad Johannes Kepler, Austria

[47] Steven G. Johnson, El paquete de optimización no lineal NLopt, http: //


ab-initio.mit.edu/nlopt

[48] N. Hansen, The CMA Evolution Strategy , http://www.lri.fr/˜hansen/


cmaesintro.html

https://translate.googleusercontent.com/translate_f 366/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
[49] A. W¨ı¿½chter y LT Biegler, Sobre la implementación de un interior dual primario
Algoritmo de búsqueda de línea de filtro de puntos para programación no lineal a gran escala, matemática
Programación ical 106 (1), págs. 25-57, 2006

[50] A. Forsgren, PE Gill y MH Wright, Interior Methods for Nonlinear


Optimización, Revisión SIAM, Vol. 44, No 4. págs. 525-597, 2002

[51] M. Oxborrow, simulación de elementos finitos 2-D rastreable de los modos de galería susurrante
de resonadores electromagnéticos axisimétricos, IEEE T. Microw. Teoría 55, 1209-1218
(2007).

[52] IS Grudinin y N. Yu, modelado de elementos finitos de resistencias de microdiscos ópticos acoplados.
onadores para detección de desplazamiento, J. Opt. Soc. Soy. B 29, 3010-3014 (2012).

Página 413

Índice

<<, 100 periódico =, 128


matriz, 96 powerin =, 127
>>, 100 ratio =, 126
. *, 94 cambio de escala =, 127
. *, 196 splitin2 =, 127
./, 94 splitpbedge =, 127
=, 184 thetamax =, 127
?:, 77 uniforme, 128
[], 28, 181, 288
https://translate.googleusercontent.com/translate_f 367/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
, 73 verbosidad =, 127
adj, 116
', 94 AffineCG, 211
3d AffineGMRES, 211
haz-3d.edp, 255 alfanumérico, 73
periódica, 244 añadir, 100
área, 76
dependiente del tiempo, 39
coordenada de área, 192
precisión, 31 argumento, 78
acos, 80 ARGV, 103
acosh, 80 -D, 103
adaptación, 124, 143, 164 matriz, 74 , 85, 97, 194
Adaptmesh, 53 , 65, 124, 126 .imax, 88
abserror =, 127 .imin, 88
anisomax =, 249 .l1, 88
corte =, 127 .l2, 88
err =, 126 .linfty, 88
errg =, 126 .max, 88
hmax =, 126 .min, 88
hmin =, 126 .sum, 88
preguntar =, 127 ::, 86
IsMetric =, 127 ?:, 86
iso =, 126 = + - * /. * ./ + = - = / = * =
keepbackvertices =, 127 . * = ./=, 87
maxsubdiv =, 127 matriz, 97
métrica =, 128 columna, 91
nbjacoby =, 126 punto, 95
nbsmooth =, 126 producto escalar, 88
nbvx =, 126 Función FE, 97
nomeshgeneration =, 128 fespace, 175
omega =, 126 matriz completa, 97

413

Página 414
414 ÍNDICE

Soy, 86 , 87 borde fijo, 111


línea, 91 Fixedborder =, 111
cartografía, 89 límite fijo = 1, 244
matriz, 97 nbvx =, 111
máx., 86
malla, 307 captura, 106
min, 86, 98 Cauchy, 69
cuantil, 89 techo, 81
re, 86 , 87 CG, 186
renumerar, 90 cambio, 135
cambiar el tamaño, 86 Características-Galerkin, 45
ordenar, 86 checkmovemesh, 121
suma, 86 chi, 119
varf, 197 Cholesky, 186, 213
asin, 80 cin, 76 , 100
asinh, 80 reloj, 23
afirmar (), 76 CMAES, 214
atan, 80 initialStdDev =, 215
atan2, 80 semilla =, 214
atanh, 80 columna, 91
atof, 80 , 83 condición de compatibilidad, 185
atoi, 80 , 83, 100 compilador, 73
axisimétrico, 39 Complejo, 74

https://translate.googleusercontent.com/translate_f 368/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
complejo, 62, 78, 94
método de Euler hacia atrás, 266 Geometría compleja, 42
coordenadas baricéntricas, 25 concatenación, 126
BDM1, 173 cono, 147
BDM1 Ortho, 174 conj, 78
ser, 116 conectividad, 201
whoinElement, 117 continuar, 98
bessel, 82 convecto, 46 , 276
BFGS, 214 copysign, 79 , 83
BiLaplacien, 172 cos, 80
binario, 100 cosh, 80
bitsign, 79 , 80, 83 cout, 76 , 100
matriz de bloques, 92 Crout, 186
bool, 74 cubo, 136, 138, 147
frontera, 110 , 112 banderas =, 137
múltiples, 113 etiqueta =, 137
condición de contorno, 196 región =, 137
BoundaryEdge, 75 Curva, 166
cuadro delimitador, 118
descanso, 98 fórmula de Moivre, 78
emisión, 307 predeterminado, 101
burbuja, 179 resolver defaults, 384
capa de construcción, 148 predeterminado a GMRES, 385
buildmesh, 34 defaulttoSuperLU, 384

Página 415
ÍNDICE 415

grado de libertad, 25 exp, 80


DFFT, 374 optimización de expresión, 198
diag, 95 , 282 función externa de C ++, 49
matriz diagonal, 95
diffnp, 80 , 83 factorizar =, 213
diffpos, 80 , 83 falso, 74 , 76
dimKrylov =, 248 fdim, 81
Dirichlet, 31 , 37, 69, 185 Función FE
funciones discontinuas, 294 [], 181
Galerkin discontinuo, 45 complejo, 62, 84, 94
vector de desplazamiento, 253 n, 181
dist, 80 , 83 valor, 181
dividir Espacio FE, 174, 175
término a término, 94 Función FE, 84, 174, 175
descomposición de dominio, 285, 286 FEQF, 174
punto, 95 FEQF1, 174
producto escalar, 94, 95, 98 FEQF13d, 174
volquete, 76 FEQF2, 174
FEQF23d, 174
Edge03d, 173 FEQF5, 174
Edge13d, 173 FEQF53d, 174
Edge23d, 173 FEQF7, 174
edgeOrientation, 75 FEQF9, 174
Valor propio, 263 FEspace
ivalue =, 262 (int, int), 201
maxit =, 262 ndof, 201
modo =, 262 nt, 201
ncv =, 262 fespace, 169
nev =, 262 BDM1, 25 , 173
rawvector =, 262 BDM1 Ortho, 25 , 174

https://translate.googleusercontent.com/translate_f 369/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
sigma =, 262 Edge03d, 26, 173
sym =, 262 Edge13d, 26, 173
tol =, 262 Edge23d, 26, 173
valor =, 262 FEQF, 174
vector =, 262 FEQF1, 174
que =, 262 FEQF13d, 174
problemas de valores propios, 38 FEQF2, 174
Elemento, 116 FEQF23d, 174
elementos, 25, 26 FEQF5, 174
malla vacía, 120 FEQF53d, 174
ENDIFMACRO, 105 FEQF7, 174
endl, 100 FEQF9, 174
erf, 82 HCT, 25 , 172
erfc, 82 Morley, 25 años
excepción, 106 P0, 25 , 170
ejecutivo, 76 , 208, 209 P03d, 26
salida, 307 P0Borde, 171

Página 416
416 ÍNDICE

P1, 25 , 170 Métodos de volumen finito, 48


P13d, 26, 170 fijo, 101
P1b, 25, 170 flabel
P1b3d, 26, 170 cambio, 135
P1bl, 170 piso, 81
P1bl3d, 170 fluido, 275
P1dc, 25, 170 al ras, 101
P1Borde, 171 fmáx, 81
P1nc, 25, 173 fmin, 81
P2, 25 , 170 fmod, 81
P23d, 26 para, 98
P2b, 25 Fourier, 40 años
P2BR, 25 , 172, 379 fregion
P2dc, 25, 171 cambio, 135
P2Borde, 171 func, 75
P2h, 25 función
P2 Morley, 171 mesas, 119
P2pnc, 173 funciones, 80
P3, 25 , 171
P3dc, 25, 171 gamma, 82
P3Borde, 171 entrada de geometría, 36
P4, 25 , 171 getline, 80
P4dc, 25, 171 global
P4Edge, 171 área, 76
periódico =, 186, 242 BoundaryEdge, 75
RT0, 25, 172 cin, 76
RT03d, 26 edgeOrientation, 75
RT0Ortho, 25, 173 final, 76
RT1, 25, 173 falso, 76
RT1 Ortho, 25, 173 h Triángulo, 76
RT2, 173 Borde interno, 76
RT2Ortho, 173 etiqueta, 75
ff-mpirun, 16 lenEdge, 75
ffmedit, 208 N, 75
ffNLOpt, 231 notaregion, 75
FFT, 374 nTonEgde, 76
expediente nuEdge, 76

https://translate.googleusercontent.com/translate_f 370/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
am, 347, 348 nuTriangle, 76
Soy fmt, 115, 347, 348 pi, 76
amdba, 347, 348 región, 75
bamg, 115, 345 searchMethod, 183
base de datos, 345 cierto, 76
pies cuadrados, 349 volumen, 76
malla, 115 x, 75
msh, 348 años, 75
nopo, 115 z, 75
espacio de elementos finitos, 169 GMRES, 186

Página 417
ÍNDICE 417

gnuplot, 208 invdiffpos, 80 , 83


bueno, 101 Irecv, 307
paquetes de gráficos, 31 Isend, 307
gslinterpakima, 387 isInf, 79 , 83
gslinterpakimaperiodic, 387 isNaN, 80, 83
gslinterpcspline, 388 isolina, 165
gslinterpcsplineperiodic, 387 isotrópico, 253
gslinterpillarlinear, 387
j0, 82
gslinterppolynomial, 387
j1, 82
gslinterpsteffen, 387
jn, 82
gslspline, 387
saltar, 249
d, 387
dd, 387 l1, 87
eval, 387 l2, 87
etiqueta, 75 , 109, 110, 113
función sombrero, 25
cambio, 135
HCT, 172
etiqueta en los límites, 37
Helmholtz, 62 años
etiqueta =, 128
hmáx, 359
lagrangiano, 122
hmin, 359
Operador de Laplace, 31
h Triángulo, 76 , 249
lenEdge, 75, 249
línea de nivel, 47
IFMACRO, 105
nivel, 187
ifstream, 100
lgamma, 82
binario, 100
línea, 91
problemas planteados, 38
LinearCG, 211
Soy, 86, 87, 93
eps =, 211
imag, 78
nbiter =, 211
incluir, 20 , 103
precon =, 211
includepath, 20
veps =, 211
init, 48
LinealGMRES, 211
init =, 187
eps =, 211
condición inicial, 69
nbiter =, 211
adentro =, 199
precon =, 211
int, 74
veps =, 211
int1d, 187
linfty, 87
int2d, 187
carga, 20
int3d, 186 , 187
camino de carga, 20
instalaciones, 187 , 249
registro, 80
Borde interno, 76
log10, 80
interpolar, 198 círculo
adentro =, 199
implicito, 99
op =, 199
pelusa, 81
t =, 199 redondo, 81

https://translate.googleusercontent.com/translate_f 371/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
interpolación, 184 LU, 186
invdiff, 80
invdiffnp, 80 , 83 m, 383

Página 418
418 ÍNDICE

macro, 47, 103, 299 whoinElement, 117


parámetro, 104 haz, 130
cita, 314 Curva de Bézier, 131
citando, 103 , 105 bordermeasure, 116
con parámetro, 50 límite, 117
sin parámetro, 47 cuadro delimitador, 118
agrupamiento de masa, 49 Cardioide, 131
matriz, 28, 75, 213 Huevo de Cassini, 131
matriz, 91 cambio, 135
bloque, 92 chi, 119
complejo, 94 conectividad, 116
constante, 92 Elemento, 117
diag, 95 , 282 hmáx, 359
factorizar =, 260 hmin, 359
yo, 93 medida, 116, 359
interpolar, 198 NACA0012, 130
re, 93 nbe, 117 , 359
real a complejo, 93 nt, 359
renumerar, 91, 93 nv, 359
cambiar tamaño, 93 , 95 regular, 123
conjunto, 92 Sección del motor, 132
matriz de rigidez, 28 Cara sonriente, 133
varf, 92 , 196 Medida de frontera, 359
eps =, 196 Canal en forma de U, 132
precon =, 197 uniforme, 128
solucionador =, 196 Corte en forma de V, 133
solucionador = factorizar, 196 adaptación de malla, 52
tgv =, 197 malla3, 140
tolpivot =, 197 ser, 359
MatUpWind0, 49 bordermeasure, 136
máx., 80, 83, 86 hmáx, 359
máximo, 77 hmin, 359
media, 14 medida, 136, 359
medit, 208 , 209 nt, 359
meditff =, 155 nv, 359
orden =, 155 Medida de frontera, 359
guardar =, 155 min, 80, 83, 86, 98
membrana, 31 mínimo, 77
malla, 75 mixto, 40
(), 116 mixto Dirichlet Neumann, 31
+, 136 módulo, 78
[], 116 Morley, 171
Flexión de 3 puntos, 134 movemesh, 121, 141
adaptación, 53, 65, 124 movemesh23, 140
adj, 117 orientación =, 140
adyacente, 117 ptmerge =, 140
ser, 117 transfo =, 140

https://translate.googleusercontent.com/translate_f 372/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh

Página 419
ÍNDICE 419

mpiAllgather, 307 veps =, 211


mpiAllReduce, 307 nodos, 25
mpiAlltoall, 307 Dirichlet no homogéneo, 31
mpiAnySource, 305 no lineal, 42
mpiBAND, 305 problema no lineal, 39
mpiBarrier, 306 norma, 374
mpiBXOR, 305 normal, 47, 190
mpiComm, 305 noshowbase, 101
mpiCommWorld, 305 noshowpos, 101
mpiGather, 307 notaregion, 75
mpiGroup, 305 nt, 201 , 359
mpiLAND, 305 nTonEdge, 47, 76
mpiLOR, 305 nuEdge, 76
mpiLXOR, 305 número de grados de libertad, 201
mpiMAX, 305 número de elemento, 201
mpiMIN, 305 nuTriangle, 76
mpiPROD, 305 nv, 359
mpiRank, 306
mpirank, 305 de corriente, 100
mpiReduce, 307 añadir, 100
mpiReduceScatter, 307 binario, 100
mpiRequest, 305 al ras, 101
mpiScatter, 307 bueno, 101
mpiSize, 306 seekg, 101
mpisize, 305 teelp, 101
mpiSUM, 305 en, 190
mpiUndefined, 305 intersección, 278
mpiWait, 306 escalar, 190
mpiWtick, 306 optimizar =, 198
mpiWtime, 306 producto exterior, 91, 94
sistema multifísico, 42
múltiples mallas, 42 P, 75
P0, 170
N, 75 , 190 P0Borde, 171
n, 181 , 383 P1, 170
NaN, 80, 83 P1b, 170
Navier-Stokes, 276 , 278 P1bl, 170
nbcoef, 383 P1dc, 170
nbe, 116 P1Borde, 171
ndof, 201 P1nc, 173
ndofK, 201 P2, 170
Neumann, 69 , 190 P2BR, 172
Newton, 214, 260 P2dc, 171
Algoritmo de Newton, 56 P2Borde, 171
NLCG, 213 P2 Morley, 171
eps =, 211 P2pnc, 173
nbiter =, 211 P3, 171

Página 420
420 ÍNDICE

https://translate.googleusercontent.com/translate_f 373/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
P3dc, 171 tgv =, 187
P4, 171 tolpivot =, 187
P4dc, 171 tolpivotsym =, 187, 197
P4Edge, 171 procesador, 306 , 307
P5Borde, 171 bloque de procesador, 306
parabólico, 39 producto
periódico, 169 , 186, 242 Punto hermitiano, 94
3d, 244 punto, 94 , 95
pi, 76 exterior, 94
parcela, 203 término a término, 94
relación de aspecto =, 204 proyección, 80 , 83
bb =, 204
borde, 112 qfnbpE =, 197, 250
límite =, 205 qft =, 191
bw =, 204 qfV =, 193
cmm =, 204 cuadratura: qf5pT, 192
coef =, 204 cuadratura: qfV5, 193
corte, 206 cuadratura: predeterminado, 193
dim =, 205 cuadratura: qf1pE, 191
gris =, 204 cuadratura: qf1pElump, 191
hsv =, 205 cuadratura: qf1pT, 192
malla, 112 cuadratura: qf1pTlump, 192
nbarrow =, 204 cuadratura: qf2pE, 191
nbiso =, 204 cuadratura: qf2pT, 192
ps =, 204 cuadratura: qf2pT4P1, 192
valor =, 204 cuadratura: qf3pE, 191
varrow =, 204 cuadratura: qf4pE, 190
viso =, 47 , 204 cuadratura: qf5pE, 190
enchufar cuadratura: qf5pT, 192
ff-mmap-semaphore, 395 cuadratura: qf7pT, 192
ffrandom, 82 , 394 cuadratura: qf9pT, 192
gls, 82 , 83 cuadratura: qfe =, 192, 193
gsl, 82 , 83, 387 cuadratura: qforder =, 192, 193
punto cuadratura: qft =, 192 , 193
región, 116 cuadratura: qfV, 193
triange, 116 cuadratura: qfV1, 193
polar, 78 cuadratura: qfV1lump, 193
pow, 80 cuadratura: qfV2, 193
ppm2rnm, 167 cuadratura: qfV5, 193
precisión, 101 cuantil, 90
precon =, 187, 197
problema, 48, 75, 184 radiación, 42
eps =, 187 rand, 82
init =, 187 randinit, 82
precon =, 187 randint31, 82
solucionador =, 187 randint32, 82
estrategia =, 187 , 197 aleatorio, 82

Página 421
ÍNDICE 421

randow, 82 resolver, 75 , 184


randreal1, 82 eps =, 187
randreal2, 82 init =, 187
randreal3, 82 sistema lineal, 94
randreal53, 82 precon =, 187
re, 86 , 87, 93 solucionador =, 187
leer archivos, 115 estrategia =, 187 , 197

https://translate.googleusercontent.com/translate_f 374/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
readmesh, 114, 137 tgv =, 28 , 187
readmesh3, 244 tolpivot =, 187
real, 74 , 78 tolpivotsym =, 187, 197
rectángulo, 109 solucionador =, 213
región, 75 , 116, 293 CG, 126, 186
cambio, 135 Cholesky, 186
indicador de región, 42 Crout, 186
renumerar, 90 GMRES, 186
cambiar tamaño, 86 , 95 LU, 186
Matrices reutilizables, 277 sparsesolver, 186
rint, 81 UMFPACK, 186
Robin, 40, 185, 190 ordenar, 86 , 176
redondo, 81 sparsesolver, 186
RT0, 172 dividir =, 128
RT0Ortho, 173 malla dividida, 129
RT1, 173 cuadrado, 109 , 249
RT1Ortho, 173 banderas =, 110
RT2, 173 etiqueta =, 110
RT2Ortho, 173 región =, 110
aleatorio, 82
savemesh, 114, 137 srandomdev, 82
saveol Stokes, 275
orden =, 154 Stokes, 272
Schwarz, 307 prueba de parada, 187
científico, 101 absoluto, 280
searchMethod, 183 tensor de deformación, 253
seg: Parcela, 203 estrategia =, 187
Secv, 307 líneas de corriente, 276
seekg, 101 tensor de tensión, 253
Enviar, 307 cuerda, 74
conjunto, 48 concatenación, 80
matriz, 92 encontrar, 80
setw, 100 , 101 Encadenamiento, 105
showbase, 101 subdominios, 292
showpos, 101 suma, 86
shurr, 285 , 286 swp, 79, 83
signo, 79 , 83
pecado, 80 bronceado, 80
singularidad, 125 tanh, 81
sinh, 80 Taylor-Hood, 277

Página 422
422 ÍNDICE

teelp, 101 freeboundary.edp, 296


tetg, 139 movemesh.edp, 122
facetcl =, 139 NSUzawaCahouetChabart.edp, 278
lista de hoyos =, 139 period.edp, 242
nboffacetcl =, 139 periodic4.edp, 242
nbofholes =, 139 periodic4bis.edp, 244
nbofregiones =, 139 readmesh.edp, 115
lista de regiones =, 139 Schwarz-gc.edp, 287
interruptor =, 139 Schwarz-sin-solapamiento.edp, 286
casco convexo tetg, 142 Schwarz-solapamiento.edp, 284
tetgreconstruction, 140 StokesUzawa.edp, 277
tetgtransfo, 142 tutotial
facetcl =, 142 VI.edp, 282
nboffacetcl =, 142 tipo de elemento finito, 170

https://translate.googleusercontent.com/translate_f 375/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
ptmerge =, 142 UMFPACK, 186
refface =, 142
lista de regiones =, 142 ceñida, 45
interruptor =, 142 varf, 28 , 75, 187, 194
tgamma, 82 matriz, 196
tgv = matriz, 196
<0, 190 optimizar =, 198
tolpivot =, 187 variable, 73
tolpivotsym =, 187 formulación variacional, 32
transponer, 94, 95, 98, 364 veps =, 213
triángulo verbosidad, 17 , 20
[], 116 versión, 76
área, 116 vértice
etiqueta, 116 etiqueta, 116
región, 116 x, 116
triangular, 119 año, 116
archivos de triangulación, así como de lectura y escritura, viso, 47
36 volumen, 76
cierto, 74 , 76
trunc, 128 forma débil, 32
etiqueta =, 128 mientras, 98
dividir =, 128 whoinElement, 116
intentar, 106 escribir archivos, 115
tutorial
LaplaceRT.edp, 248 x, 75
adapt.edp, 125 años, 75
adaptindicatorP2.edp, 248
a0, 82
AdaptResidualErrorIndicator.edp, 250
y1, 82
aTutorial.edp, 236 yn, 82
beam.edp, 254
BlackSchol.edp, 272 z, 75
convect.edp, 270
fluidStruct.edp, 289

Página 424
423

Descripción del libro

Fruto de un largo proceso de maduración freefem, en su último avatar, FreeFem ++, es un alto
entorno de desarrollo integrado de nivel (IDE) para ecuaciones diferenciales parciales
(PDE). Es la herramienta ideal para enseñar el método de los elementos finitos pero también es perfecta
para que la investigación pruebe rápidamente nuevas ideas o aplicaciones multifísicas y complejas.

FreeFem ++ tiene un generador de malla automático avanzado, capaz de posteri-


adaptación de la malla ori; tiene un solucionador elíptico de propósito general interconectado con
algoritmos como el método multi-frontal UMFPACK. Hiperbólico y parabólico
Los problemas se resuelven mediante algoritmos iterativos prescritos por el usuario con el alto
nivel de lenguaje de FreeFem ++. Tiene varios elementos finitos triangulares, que incluyen
elementos discontinuos. Finalmente, todo está ahí en FreeFem ++ para preparar la
informes de calidad de búsqueda: visualización a color en línea con zoom y otras funciones y
impresiones de posdata.

Este libro es ideal para estudiantes de Máster, para investigadores de cualquier nivel y para
ingenieros también en matemáticas financieras.

reseñas editoriales

”. . . Imposible dejar el libro, suspenso hasta la última página. . . "


A. Tanh, Crónica de Siam.
”. . . El capítulo sobre fems discontinuas es muy divertido. . . . "

https://translate.googleusercontent.com/translate_f 376/377
12/4/2021 F. Hecht, O. Piro A. Le Hyaric, K. Oh
B. Galerkine, .

https://translate.googleusercontent.com/translate_f 377/377

También podría gustarte