@@ -298,62 +298,59 @@ def u_exact(self, t=0, noise_level=1e-3, seed=99):
298298 else :
299299 return me
300300
301- def get_fig (self ): # pragma: no cover
301+ def compute_Nusselt_numbers (self , u ):
302302 """
303- Get a figure suitable to plot the solution of this problem
303+ Compute the various versions of the Nusselt number. This reflects the type of heat transport.
304+ If the Nusselt number is equal to one, it indicates heat transport due to conduction. If it is larger,
305+ advection is present.
306+ Computing the Nusselt number at various places can be used to check the code.
304307
305- Returns
306- -------
307- self.fig : matplotlib.pyplot.figure.Figure
308- """
309- import matplotlib .pyplot as plt
310- from mpl_toolkits .axes_grid1 import make_axes_locatable
311-
312- plt .rcParams ['figure.constrained_layout.use' ] = True
313- self .fig , axs = plt .subplots (2 , 1 , sharex = True , sharey = True , figsize = ((10 , 5 )))
314- self .cax = []
315- divider = make_axes_locatable (axs [0 ])
316- self .cax += [divider .append_axes ('right' , size = '3%' , pad = 0.03 )]
317- divider2 = make_axes_locatable (axs [1 ])
318- self .cax += [divider2 .append_axes ('right' , size = '3%' , pad = 0.03 )]
319- return self .fig
320-
321- def plot (self , u , t = None , fig = None , quantity = 'T' ): # pragma: no cover
322- r"""
323- Plot the solution.
324-
325- Parameters
326- ----------
327- u : dtype_u
328- Solution to be plotted
329- t : float
330- Time to display at the top of the figure
331- fig : matplotlib.pyplot.figure.Figure
332- Figure with the same structure as a figure generated by `self.get_fig`. If none is supplied, a new figure will be generated.
333- quantity : (str)
334- quantity you want to plot
335-
336- Returns
337- -------
338- None
339- """
340- fig = self .get_fig () if fig is None else fig
341- axs = fig .axes
308+ Args:
309+ u: The solution you want to compute the Nusselt numbers of
342310
343- imV = axs [1 ].pcolormesh (self .X , self .Z , self .compute_vorticity (u ).real )
311+ Returns:
312+ dict: Nusselt number averaged over the entire volume and horizontally averaged at the top and bottom.
313+ """
314+ iw , iT = self .index (['w' , 'T' ])
315+ zAxis = self .spectral .axes [- 1 ]
344316
345317 if self .spectral_space :
346- u = self .itransform (u )
318+ u_hat = u .copy ()
319+ else :
320+ u_hat = self .transform (u )
347321
348- imT = axs [ 0 ]. pcolormesh (self .X , self . Z , u [ self . index ( quantity )]. real )
322+ DzT_hat = (self .Dz @ u_hat [ iT ]. flatten ()). reshape ( u_hat [ iT ]. shape )
349323
350- for i , label in zip ([0 , 1 ], [rf'${ quantity } $' , 'vorticity' ]):
351- axs [i ].set_aspect (1 )
352- axs [i ].set_title (label )
324+ # compute wT with dealiasing
325+ padding = (self .dealiasing ,) * self .ndim
326+ u_pad = self .itransform (u_hat , padding = padding ).real
327+ _me = self .xp .zeros_like (u_pad )
328+ _me [0 ] = u_pad [iw ] * u_pad [iT ]
329+ wT_hat = self .transform (_me , padding = padding )[0 ]
353330
354- if t is not None :
355- fig .suptitle (f't = { t :.2f} ' )
356- axs [1 ].set_xlabel (r'$x$' )
357- axs [1 ].set_ylabel (r'$z$' )
358- fig .colorbar (imT , self .cax [0 ])
359- fig .colorbar (imV , self .cax [1 ])
331+ nusselt_hat = wT_hat - DzT_hat
332+
333+ if not hasattr (self , '_zInt' ):
334+ self ._zInt = zAxis .get_integration_matrix ()
335+
336+ # get coefficients for evaluation on the boundary
337+ top = zAxis .get_BC (kind = 'Dirichlet' , x = 1 )
338+ bot = zAxis .get_BC (kind = 'Dirichlet' , x = - 1 )
339+
340+ integral_V = 0
341+ if self .comm .rank == 0 :
342+
343+ integral_z = (self ._zInt @ nusselt_hat [0 , 0 ]).real
344+ integral_z [0 ] = zAxis .get_integration_constant (integral_z , axis = - 1 )
345+ integral_V = ((top - bot ) * integral_z ).sum () * self .axes [0 ].L * self .axes [1 ].L / self .nx / self .ny
346+
347+ Nusselt_V = self .comm .bcast (integral_V / self .spectral .V , root = 0 )
348+
349+ Nusselt_t = self .comm .bcast (self .xp .sum (nusselt_hat .real [0 , 0 , :] * top , axis = - 1 ) / self .nx / self .ny , root = 0 )
350+ Nusselt_b = self .comm .bcast (self .xp .sum (nusselt_hat .real [0 , 0 ] * bot / self .nx / self .ny , axis = - 1 ), root = 0 )
351+
352+ return {
353+ 'V' : Nusselt_V ,
354+ 't' : Nusselt_t ,
355+ 'b' : Nusselt_b ,
356+ }
0 commit comments