-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapend2.tex
380 lines (312 loc) · 20.2 KB
/
apend2.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
\chapter{Descripción del código maestro \textbf{Newton}}
\label{C:newton}
%\chapterquote{Negociemos Don Inodoro}{Fernando de la R\'{u}a, 2001}
\textbf{Newton} es un código escrito en \texttt{C++} desarrollado durante la maestría,
publicado en \textbf{Github} \cite{github} bajo Licencia Pública General (GPL por sus siglas en inglés, \textit{Public General License}) del Proyecto GNU colaborativo de software libre.
Fue diseñado como programa \textit{maestro} con un propósito general, de forma que permita resolver cualquier tipo de ecuaciones acopladas,
parcialmente resueltas por códigos \textit{esclavos}.
Algunos ejemplos de los problemas que pueden resolverse con \textbf{Newton} son los siguientes:
\begin{itemize}
\item Cálculos formulados con el Método de Doscomposición Disjunta de Dominios:
acoplamientos fluidodinámicos multiescala, con o sin transferencia de calor, como los presentados en las secciones \ref{3:ff}, \ref{3:mockup} y \ref{3:redes}.
\item Cálculos multifísicos: acoplamiento fluido-estructura, acoplamiento neutrónico-termohidráulico, como los presentados en la sección \ref{3:extension-nucleo}.
También podrían pensarse modelos de núcleo completo (\textit{full core models}), acoplando el comportamiento de los materiales a la dinámica neutrónica-termohidráulica y otros fenómenos de interés.
\end{itemize}
\section{Principales características}
\label{ap2:main-features}
\subsection*{Archivo de configuración}
\label{ap2:parser}
La ejecución de \textbf{Newton} requiere el archivo de configuración \texttt{newton.config} en el que debe detallarse la formulación del problema a resolver,
la forma de comunicación con cada código \textit{esclavo}, los mapeos utilizados, y métodos numéricos y demás parámetros asociados a la resolución del sistema \ref{sistema-simple}.
El formato de entrada fue pensado de forma tal que resulte simple e intuitivo al usuario.
Las funciones implementadas en la clase \texttt{Parser} se encargan de analizar las diferentes palabras claves ingresadas y sus atributos.
Se desarrolló un manual de comandos de entrada \cite{newton-user-manual}.
\subsection*{Mapeos}
\label{ap2:mappers}
En ciertas formulaciones las variables de acoplamiento pueden ser expresadas bajo transformaciones en las diferentes ecuaciones acopladas.
Por ejemplo, en acoplamientos fluidodinámicos es común que en algunos modelos se calculen velocidades medias en interfaces de acople
y que en otros modelos se calculen valores de caudales.
En estos casos es necesario realizar mapeos \textit{velocidad-caudal}.
En otros tipos de problemas también es necesario realizar mapeos.
En acoplamiento neutrónico-termohidráulico, por ejemplo, las variables de cálculo del programa termohidráulico podrían ser densidades y termperaturas,
pero el programa neutrónico utiliza como variables secciones eficaces, que dependen de ellas.
Además, las variables transformadas podrían ser condensadas o multiplicadas.
Aquí podría pensarse un mapeo \textit{termohidráulico-secciones eficaces}.
En general, los mapeos son transformaciones simples de las variables de acoplamiento, y pueden extraerse de la resolución de las ecuaciones parciales,
definiendo ecuaciones extras que pueden ser resueltas por el programa \textit{maestro}.
Debido a esta generalización, es necesario definir cuál va a ser la variable acoplada utilizada para resolver el sistema de residuos \ref{sistema-simple}.
Diferentes mapeos pueden ser utilizados para diferentes códigos \textit{esclavos}, ya sea para adecuar variables \textit{guess} o variables calculadas.
Su implementación requiere una mínima programación en funciones listas para ser utilizadas pertenecientes a la clase \texttt{Mapper}.
Luego deben ser incluidos mediante palabras claves en el archivo de configuración \texttt{newton.config}.
\subsection*{Modelos de comunicación}
\label{ap2:comm}
Con la finalidad de poder establecer conexiones con programas \textit{esclavos} cuyos códigos fuente no están disponibles,
se incorporaron diferentes modos de comunicación, conforme a la estrategia descripta en el \hyperlink{chapter.2}{Capítulo 2}:
\begin{itemize}
\item Comunicación por MPI entre programas ejecutados en simultáneo o entre programas ejecutados de manera independiente, cuando es posible acceder al código fuente.
\item Comunicación por lectura y escritura de archivos con programas sin acceso al código fuente.
\end{itemize}
Todas estas funciones fueron implementadas en la clase \texttt{Communicator}.
\textbf{Newton} puede ser ejecutado en múltiples procesos de modo que la conexión mediante manejo de archivos sea paralelizada.
Las tareas se distribuyen automáticamente de forma eficiente conforme a la cantidad de procesos lanzados por el usuario.
\subsection*{Métodos numéricos}
\label{ap2:num-met}
\textbf{Newton} puede resolver acoplamientos utilizando diferentes métodos numéricos:
\begin{itemize}
\item Métodos explícitos:
\begin{itemize}
\item método \textit{Picard} simple;
\item método \textit{Picard} combinado.
\end{itemize}
\item Métodos implícitos:
\begin{itemize}
\item método de \textit{Newton-Raphson};
\item método de \textit{Shamanskii};
\item método de \textit{Broyden}.
\end{itemize}
\end{itemize}
A futuro sería posible implementar otros métodos en la clase \texttt{Solver}.
Los sistemas algebraicos resultantes en los métodos implícitos son resueltos mediante la biblioteca \textbf{PETSc} \cite{petsc-web-page} altamente eficiente para este tipo de cálculos.
\subsection*{Manejo de errores}
\label{ap2:error}
El manejo eficiente de errores fue pensado como una de las características principales durante el diseño del programa,
debido a la complejidad de conexiones y consecuente diversidad en origen de fallas.
Cualquier error generado comienza la siguiente cascada de eventos:
\begin{enumerate}
\item Devolución de un mensaje correspondiente en la salida estándar.
\item Comunicación del error a todos los procesos de \textbf{Newton}.
\item Envío de órden de aborto a los programas \textit{esclavos} por parte del proceso \textit{raiz}.
\item Finalización de las tareas.
\end{enumerate}
\subsection*{Depuración}
\label{ap2:debug}
Se desarrolló un visualizador genérico en la clase \texttt{Debugger} para realizar seguimiento de la evolución de las variables pertenecientes a las diferentes clases implementadas.
El usuario puede requerir su uso en clases específicas mediante palabras claves ingresadas en el archivo de configuración para la ejecución de \textbf{Newton}.
\texttt{Debugger} va imprimiendo la salida requerida en archivos particulares para cada clase.
\subsection*{Validación}
\label{ap2:bench}
Las funciones implementadas y la metodología de cálculo fueron puestas a prueba exitosamente en la resolución de sistemas de ecuaciones lineales y no lineales acopladas.
Las mismos pueden encontrarse dentro de la carpeta \texttt{examples} en el directorio principal de \textbf{Newton}.
Se verificó el correcto funcionamiento de los diferentes tipos de comunicación, de las intancias de mapeos y de los distintos métodos numéricos implementados para la resolución del sistema de ecuaciones de residuos.
\section{Modelado de problemas acoplados}
\label{ap1:definicion}
\textbf{Newton} resuelve problemas que comprenden algún sistema de ecuaciones acopladas, en el que las ecuaciones son resueltas por separado por diferentes programas.
Conforme a la estrategia de acoplamiento extendida comentada en la sección \ref{3:strategy-extended},
es necesario definir qué variables van a ser datos y qué variables van a ser incógnitas para cada subsistema de análisis.
Como existe la posibilidad de transformaciones previas o posteriores a la resolución del sistema de ecuaciones de residuos característico de cada problema,
es necesario además definir en forma clara cuáles van a ser las variables transformadas y los mapeos.
Para organizar esta formulación en forma clara \texttt{Newton} trabaja con cuatro instancias de variables para cada programa \textit{esclavo}:
las instancias $\alpha$, $\beta$, $\gamma$ y $\delta$.
\subsection*{Alfas, betas, gammas y deltas}
\label{ap1:abgd}
Existen cuatro instancias de variables para cada programa \textit{esclavo}:
\begin{enumerate}
\item Instancia $\alpha$: corresponde al valor crudo de las variables calculadas por el programa.
\item Instancia $\beta$: corresponde al valor transformado de las variables $\alpha$.
En el caso de que no se haya definido una transformación, se utiliza la transformación de identidad por defecto.
Las variables $\beta$ están listas para ser utilizadas en el cálculo de residuos.
\item Instancia $\gamma$: corresponde a los valores \textit{guess} generados por \textbf{Newton} para ese programa.
\item Instancia $\delta$: corresponde a los valores $\gamma$ transformados, utilizando también la transformación de identidad por defecto.
\end{enumerate}
La Figura \ref{fig:abgd} esquematiza lo expresado.
\pgfdeclarelayer{bg} % declare background layer
\pgfsetlayers{bg,main} % set the order of the layers (main is the standard laye
\begin{figure}[h]
\centering{}
\begin{tikzpicture}[
block1/.style={
draw,
fill=white,
rectangle,
minimum width={width("Esclavo 1")+3pt},
minimum height={17pt},
font=\small,
align=center},
arrow1/.style={
-{Latex[length=3mm, width=1mm]}
}
]
% residuos
\node [block1, text width=6em] at (0,6em) (res) {\textbf{Resolución de residuos}};
% programa 1
\node[block1, above of=res, yshift=6em] (e1) {\textbf{Esclavo 1}};
% alpha 1
\node [block1, below left of=e1, yshift=-0.8em, xshift=-9em] (alpha1) {\textbf{variables} $\alpha_1$};
% beta 1
\node [block1, above left of=res, yshift=0.8em, xshift=-9em] (beta1) {\textbf{variables} $\beta_1$};
% gamma 1
\node [block1, above right of=res, yshift=0.8em, xshift=9em] (gamma1) {\textbf{variables} $\gamma_1$};
% delta 1
\node [block1, below right of=e1, yshift=-0.8em, xshift=9em] (delta1) {\textbf{variables} $\delta_1$};
% programa 2
\node [block1, below of=res, yshift=-6em] (e2) {\textbf{Esclavo 2}};
% alpha 2
\node [block1, above left of=e2, yshift=0.8em, xshift=-9em] (alpha2) {\textbf{variables} $\alpha_2$};
% beta 2
\node [block1, below left of=res, yshift=-0.8em, xshift=-9em] (beta2) {\textbf{variables} $\beta_2$};
% gamma 2
\node [block1, below right of=res, yshift=-0.8em, xshift=9em] (gamma2) {\textbf{variables} $\gamma_2$};
% delta 2
\node [block1, above right of=e2, yshift=0.8em, xshift=9em] (delta2) {\textbf{variables} $\delta_2$};
% Conexiones 1
\draw[arrow1] ($(e1.west)$) to[out=180, in=70, distance=2em] (alpha1.north);
\draw[arrow1] ($(alpha1.south)$) to node [midway, anchor=center, left]{\textit{mapeo $\alpha_1-\beta_1$}} (beta1.north);
\draw[arrow1] ($(beta1.south)$) to[out=-70, in=-180, distance=1.7em] ($(res.west)+(0,0.2em)$);
\draw[arrow1] ($(res.east)+(0,0.2em)$) to[out=0, in=-110, distance=1.7em] ($(gamma1.south)$);
\draw[arrow1] ($(gamma1.north)$) to node [midway, anchor=center, right]{\textit{mapeo $\gamma_1-\delta_1$}} (delta1.south);
\draw[arrow1] ($(delta1.north)$) to [out=110, in=0, distance=2em] ($(e1.east)$);
% Conexiones 2
\draw[arrow1] ($(e2.west)$) to[out=180, in=-70, distance=2em] (alpha2.south);
\draw[arrow1] ($(alpha2.north)$) to node [midway, anchor=center, left]{\textit{mapeo $\alpha_2-\beta_2$}} (beta2.south);
\draw[arrow1] ($(beta2.north)$) to[out=70, in=-180, distance=1.7em] ($(res.west)-(0,0.2em)$);
\draw[arrow1] ($(res.east)-(0,0.2em)$) to[out=0, in=110, distance=1.7em] ($(gamma2.north)$);
\draw[arrow1] ($(gamma2.south)$) to node [midway, anchor=center, right]{\textit{mapeo $\gamma_1-\delta_1$}} (delta2.north);
\draw[arrow1] ($(delta2.south)$) to [out=-110, in=0, distance=2em] ($(e2.east)$);
% Fondo
\begin{pgfonlayer}{bg} % select the background layer
% Newton frame
\draw [blue, rounded corners, thick, dashed, opacity=0.5, fill=blue!10]
($(alpha1.west) + (-5em, 1.2em)$)
-- ($(alpha2.west) + (-5em,-1.2em)$)
-- ($(delta2.east) + (5em,-1.2em)$)
-- ($(delta1.east) + (5em,1.2em)$)
-- ($(alpha1.west) + (-5em,1.2em)$);
% newton
\node [draw,blue, rounded corners, thick, dashed, opacity=0.5, fill=blue!10]
at ($(beta1.west) + (-2em, -2.5em)$) (newton) {\textbf{Newton}};
\end{pgfonlayer}
\end{tikzpicture}
\caption[Instancias de cálculo de las variables relacionadas con cada programa \textit{esclavo}]
{Instancias de cálculo $\alpha$, $\beta$, $\gamma$ y $\delta$ de las variables relacionadas con cada programa \textit{esclavo}.
En este ejemplo los programas \textbf{Esclavo 1} y \textbf{Esclavo 2} se comunican con \textbf{Newton}.}
\label{fig:abgd}
\end{figure}
\subsection*{Configuración del problema}
\label{ap1:abgd}
Una vez definidas estas instancias para cada subsistema de análisis, debe completarse el archivo de configuración \texttt{newton.config}.
En el mismo deben definirse \textit{clientes}, que son los diferentes programas \textit{esclavos}.
Para cada \textit{cliente} es necesario ingresar el nombre de las variables de instancia $\beta$ depués de la palabra clave \texttt{CALCS},
y de instancia $\gamma$ después de la palabra clave \texttt{GUESSES}.
En el caso de que no sean requeridos mapeos no debe especificarse nada sobre las instancias $\alpha$ y $\delta$.
Si se requieren transformaciones, éstas deben ser ingresadas en otra instancia del archivo, bajo la palabra clave \texttt{MAPPER}.
Allí se detalla el \textit{cliente}, si corresponde a una transformación $\alpha-\beta$ o a una transformación $\gamma-\delta$, y la cantidad de variables implicadas en la transformación.
Para cada \textit{cliente} también es necesario ingresar el tipo de comunicación con \textbf{Newton}, y otras opciones de conexión en el caso de manejo de archivos.
Finalmente, es necesario definir el método de acoplamiento a utilizar y sus parámetros específicos.
\section{Metodología de resolución}
\label{ap2:resolucion}
El archivo \texttt{src/main.cpp} contiene la estructura principal del programa.
En el mismo se crea un objeto de clase \texttt{Newton} y se ejecutan sus tres funciones principales:
\begin{enumerate}
\item Función de inicio: \texttt{Newton::initialize}.
\item Función de ejecución: \texttt{Newton::run}.
\item Función de finalización: \texttt{Newton::finish}.
\end{enumerate}
A continuación se describen brevemente las tareas desarrolladas en cada función.
\subsection*{Función de inicio}
\label{ap2:newton-init}
La función \texttt{Newton::initialize} ejecuta todas las tareas necesarias para comenzar el cálculo:
\begin{enumerate}
\item Creación de objetos de uso interno.
\item Lectura del archivo de configuración.
\item Creación de comunicadores con procesos \textit{raíces} de programas ejecutados en simultáneo junto con \textbf{Newton}.
\item Publicación de puertos y establecimiento de conexiones con procesos \textit{raíces} de programas que necesitan establecer comunicación por MPI.
\item Envío de datos generales del problema a los programas \textit{esclavos} para chequeo de compatibilidad de datos.
\item Asignación de espacio en memoria a los arreglos de uso interno dependientes del problema.
\end{enumerate}
\subsection*{Función de ejecución}
\label{ap2:newton-run}
La función \texttt{Newton::run} ejecuta todas las tareas necesarias para completar el cálculo:
\begin{enumerate}
\item Ingreso en el bucle de evolución.
\begin{enumerate}
\item Comunicación de valores \textit{guess} para las condiciones de borde de cada subdominio a cada programa \textit{esclavo}:
\begin{enumerate}
\item escritura de los valores en archivos de entrada y ejecución de los programa \textit{esclavos} conectados por manejo de archivos;
\item envío de valores por MPI a aquellos programas conectados por paso de mensajes.
\end{enumerate}
\item Recepción de valores calculados para las incógnitas de cada subdominio de cada programa \textit{esclavo}:
\begin{enumerate}
\item lectura de los valores en archivos de salida de los programa \textit{esclavos} conectados por manejo de archivos;
\item recepción de valores por MPI desde aquellos programas conectados por paso de mensajes.
\end{enumerate}
\item Resolución de las ecuaciones de residuos \ref{ecuaciones-residuos}.
\item Evaluación de la convergencia:
\begin{itemize}
\item si los resultados están convergidos el problema puede continuar con el siguiente paso de evolución;
\item si los resultados no están convergidos, es necesario proponer nuevos valores \textit{guess} y reiniciar el cálculo.
\end{itemize}
\item Envío de orden de avance o de reinicio a cada programa \textit{esclavo} conectado por MPI.
\end{enumerate}
\item Finalización del bucle de evolución.
\end{enumerate}
\subsection*{Función de finalización}
\label{ap2:newton-finish}
La función \texttt{Newton::finish} ejecuta todas las tareas necesarias para terminar el programa de forma segura:
\begin{enumerate}
\item Desconexión de programas comunicados por MPI.
\item Liberación de comunicadores.
\item Finalización de \textbf{PETSc} y de MPI.
\item Cierre de archivos de depuración.
\end{enumerate}
\section{Ejemplo de uso}
\label{ap2:ejemplo}
A continuación se comenta la resolución de uno de los problemas utilizados para la validación de las funciones desarrolladas.
Se quiere resolver el siguiente sistema de ecuaciones:
\begin{equation}
\left\{ \begin{array}{rcl}
1w + 2x + 3y + 4z &=& 17 \\
12w + 13x + 14y + 5z &=& 18 \\
11w + 16x + 15y + 6z &=& 19 \\
10w + 9x + 8y + 7z &=& 20
\end{array}
\right.
\label{eq:linear2}
\end{equation}
Uno de los programas \textit{esclavos} calcula $(w,x,y)$ en función de algún valor $z_{guess}$ poporcionado, y resuelve las primeras tres ecuaciones:
\begin{equation}
\left\{ \begin{array}{rcl}
w &=& (17 - 2x - 3y - 4z_{guess})/ 1 \\
x &=& (18 - 12w - 14y - 5z_{guess})/13 \\
y &=& (19 - 11w - 16x - 6z_{guess})/15
\end{array}
\right.
\label{eq:linear2a}
\end{equation}
El otro programa \textit{esclavo} calcula $z$ como función de los valores $(w_{guess},x_{guess},y_{guess})$ proporcionados, resolviendo la última ecuación de \ref{eq:linear2}:
\begin{equation}
z = (20 - 10w_{guess} - 9x_{guess} - 8y_{guess})/ 7
\label{eq:linear2b}
\end{equation}
La solución analítica para este problema es la siguiente:
\begin{equation}
\left\{ \begin{array}{rcl}
w &=& -0.70909 \\
x &=& -1.89091 \\
y &=& 2.36364 \\
z &=& 3.60000
\end{array}
\right.
\label{eq:linear2-sol}
\end{equation}
Para formular este problema comunicando los programas por MPI,
mediante una ejecución en modo MISD de \textbf{Newton} y los dos programas \textit{esclavos},
el archivo de configuración \texttt{newton.config} se completa como sigue:
\begin{Verbatim}[frame=single,commandchars=\\\{\}]
\textcolor{Gray}{ # Métodos numéricos}
\textcolor{Red}{METHOD} \textcolor{OliveGreen}{secant} \textcolor{Gray}{# Método selecionado}
\textcolor{Red}{ABS_TOL} \textcolor{OliveGreen}{1e-15} \textcolor{Red}{MAX_ITER} \textcolor{OliveGreen}{10} \textcolor{Gray}{# Parámetros de iteración}
\textcolor{Red}{X_INI} \textcolor{OliveGreen}{w 1 x 2 y 3 z 4} \textcolor{Gray}{# Semilla inicial}
\textcolor{Gray}{ # Especificaciones para códigos esclavos}
\textcolor{Red}{CLIENT} \textcolor{OliveGreen}{linear1} \textcolor{Gray}{# Apodo del primer programa esclavo}
\textcolor{Red}{ROOT_GLOBAL_RANK} \textcolor{OliveGreen}{1} \textcolor{Gray}{# Rango global del proceso raíz}
\textcolor{Red}{CALCS} \textcolor{OliveGreen}{w x y} \textcolor{Red}{GUESSES} \textcolor{OliveGreen}{z} \textcolor{Gray}{# Variables de cálculo y variables dato}
\textcolor{Red}{CONNECTION} \textcolor{OliveGreen}{mpi_comm} \textcolor{Gray}{# Tipo de conexión}
\textcolor{Red}{CLIENT} \textcolor{OliveGreen}{linear2} \textcolor{Gray}{# Apodo del primer programa esclavo}
\textcolor{Red}{ROOT_GLOBAL_RANK} \textcolor{OliveGreen}{2} \textcolor{Gray}{# Rango global del proceso raíz}
\textcolor{Red}{CALCS} \textcolor{OliveGreen}{z} \textcolor{Red}{GUESSES} \textcolor{OliveGreen}{w x y} \textcolor{Gray}{# Variables de cálculo y variables dato}
\textcolor{Red}{CONNECTION} \textcolor{OliveGreen}{mpi_comm} \textcolor{Gray}{# Tipo de conexión}
\end{Verbatim}
Notar que en este modo de ejecución \textbf{Newton} debe conocer
cuál es la numeración global de los procesos raíces de los programas \textit{esclavos} para poder establecer los comunicadores con ellos.
Con el método de resolución seleccionado, \textbf{Newton} construye la matriz jacobiana del sistema y luego converge a la solución \ref{eq:linear2-sol} en una sola iteración,
utilizando en total 6 evaluaciones de funciones.