@@ -889,28 +889,101 @@ def toVTR(self, idxFormat="{:06d}"):
889889 u = self .readFieldAt (i )
890890 writeToVTR (template .format (i ), u , coords , varNames )
891891
892+ def checkDNS (spectrum :np .ndarray , kappa :np .ndarray , sRatio :int = 4 , nThrow :int = 0 ):
893+ r"""
894+ Check for a well-resolved DNS, by looking at an energy spectrum
895+ :math:`s(\kappa)` and doing a quadratic regression in log space
896+ on its tail :
897+
898+ .. math::
899+ \log(s_{tail}) \simeq
900+ a\log(\kappa_{tail})^2 + b\log(\kappa_{tail}) + c
901+
902+ where :math:`(\kappa_{tail},s_{tail})` is continuous subset of the
903+ mapping :math:`(\kappa,s)` for large values of :math:`\kappa`
904+ (i.e spectrum tail).
905+ If the quadratic regression produces a convex polynomial
906+ (i.e :math:`a > 0`) then the simulation is considered as under-resolved
907+ (no DNS).
908+ Per default, the tail is built considering the
909+ **last quarter of the spectrum**.
910+
911+ Parameters
912+ ----------
913+ spectrum : np.ndarray
914+ Vector of the spectrum values :math:`s(\kappa)`.
915+ kappa : np.ndarray
916+ Vector of the wavenumber values :math:`\kappa`.
917+ sRatio : int, optional
918+ Spectrum ratio used to define the tail: if the spectrum has
919+ N values, then the tail is defined with the last N/sRatio values.
920+ The default is 4.
921+ nThrow : int, optional
922+ Number of higher kappa extremity spectrum values to not consider
923+ when defining the tail. The default is 1.
924+
925+ Returns
926+ -------
927+ results : dict
928+ Dictionnary containing the results, with keys :
929+
930+ - `DNS` : boolean indicating if the simulation is well resolved
931+ - `coeffs` : the :math:`a,b,c` regression coefficients, stored in a tuple
932+ - `kTail` : the :math:`\kappa_{tail}` values used for the regression
933+ - `sTail` : the :math:`s_{tail}` values used for the regression
934+
935+ """
936+ spectrum = np .asarray (spectrum )
937+ kappa = np .asarray (kappa )
938+ assert spectrum .ndim == 1 , "spectrum must be a 1D vector"
939+ assert kappa .shape == spectrum .shape , "kappa and spectrum must have the same shape"
940+
941+ nValues = kappa .size // sRatio
942+ sl = slice (- nValues - nThrow , - nThrow if nThrow else None )
943+
944+ kTail = kappa [sl ]
945+ sTail = spectrum [sl ]
946+
947+ y = np .log (sTail )
948+ x = np .log (kTail )
949+
950+ def fun (coeffs ):
951+ a , b , c = coeffs
952+ return np .linalg .norm (y - a * x ** 2 - b * x - c )
953+
954+ res = sco .minimize (fun , [0 , 0 , 0 ])
955+ a , b , c = res .x
956+
957+ results = {
958+ "DNS" : not a > 0 ,
959+ "coeffs" : (a , b , c ),
960+ "kTail" : kTail ,
961+ "sTail" : sTail ,
962+ }
963+
964+ return results
892965
893966if __name__ == "__main__" :
894967 import matplotlib .pyplot as plt
895968
896969 # dirName = "run_3D_A4_M0.5_R1_Ra1e6"
897- dirName = "run_3D_A4_M0.5_R1_Ra1e6 "
898- # dirName = "run_M4_R1 "
970+ dirName = "run_3D_A4_M1_R1_Ra1e6 "
971+ # dirName = "run_M4_R2 "
899972 # dirName = "test_M4_R2"
900973 OutputFiles .VERBOSE = True
901974 output = OutputFiles (dirName )
902975
903- if True :
976+ if False :
904977 series = output .getTimeSeries (which = ["NuV" , "NuT" , "NuB" ])
905978
906979 plt .figure ("series" )
907980 for name , values in series .items ():
908981 plt .plot (output .times , values , label = name )
909982 plt .legend ()
910983
911- start = 40
984+ start = 60
912985
913- if True :
986+ if False :
914987 which = ["bRMS" ]
915988
916989
@@ -957,11 +1030,20 @@ def toVTR(self, idxFormat="{:06d}"):
9571030
9581031 if True :
9591032 spectrum = output .getSpectrum (
960- which = ["b " ], zVal = "all" , start = start , batchSize = None )
1033+ which = ["uh " ], zVal = "all" , start = start , batchSize = None )
9611034 kappa = output .kappa
9621035
1036+ check = checkDNS (spectrum ["uh" ], kappa )
1037+ print (f"DNS : { check ['DNS' ]} " )
1038+ a , b , c = check ["coeffs" ]
1039+ kTail = check ["kTail" ]
1040+ sTail = check ["sTail" ]
1041+
9631042 plt .figure ("spectrum" )
9641043 for name , vals in spectrum .items ():
9651044 plt .loglog (kappa [1 :], vals [1 :], label = name )
1045+ plt .loglog (kTail , sTail , '.' , c = "black" )
1046+ kTL = np .log (kTail )
1047+ plt .loglog (kTail , np .exp (a * kTL ** 2 + b * kTL + c ), c = "gray" )
9661048 plt .loglog (kappa [1 :], kappa [1 :]** (- 5 / 3 ), '--k' )
9671049 plt .legend ()
0 commit comments