@@ -270,8 +270,149 @@ def f_solve(self, b, alpha, u0):
270270 return sol
271271
272272#
273- # A diagonally implicit Runge-Kutta method of order 2, 3 or 4
273+ # Split-Explicit method
274274#
275+
276+ class SplitExplicit :
277+
278+ def __init__ (self , problem , method , pparams ):
279+
280+ assert isinstance (problem , boussinesq_2d_imex ), "problem is wrong type of object"
281+ self .Ndof = np .shape (problem .M )[0 ]
282+ self .method = method
283+ self .logger = logging ()
284+ self .problem = problem
285+ self .pparams = pparams
286+ self .NdofTher = 2 * problem .N [0 ]* problem .N [1 ]
287+ self .NdofMom = 2 * problem .N [0 ]* problem .N [1 ]
288+
289+ print "dx " ,problem .h [0 ]
290+ print "dz " ,problem .h [1 ]
291+
292+ assert self .method in ["MIS4_4" ,"RK3" ], 'Method must be MIS4_4'
293+
294+ if (self .method == 'RK3' ):
295+ self .nstages = 3
296+ self .aRunge = np .zeros ((4 ,4 ))
297+ self .aRunge [0 ,0 ]= 1. / 3.
298+ self .aRunge [1 ,1 ]= 1. / 2.
299+ self .aRunge [2 ,2 ]= 1.
300+ self .dRunge = np .zeros ((4 ,4 ))
301+ self .gRunge = np .zeros ((4 ,4 ))
302+ if (self .method == 'MIS4_4' ):
303+ self .nstages = 4
304+ self .aRunge = np .zeros ((4 ,4 ))
305+ self .aRunge [0 ,0 ]= 0.38758444641450318
306+ self .aRunge [1 ,0 ]= - 2.5318448354142823e-002
307+ self .aRunge [1 ,1 ]= 0.38668943087310403
308+ self .aRunge [2 ,0 ]= 0.20899983523553325
309+ self .aRunge [2 ,1 ]= - 0.45856648476371231
310+ self .aRunge [2 ,2 ]= 0.43423187573425748
311+ self .aRunge [3 ,0 ]= - 0.10048822195663100
312+ self .aRunge [3 ,1 ]= - 0.46186171956333327
313+ self .aRunge [3 ,2 ]= 0.83045062122462809
314+ self .aRunge [3 ,3 ]= 0.27014914900250392
315+ self .dRunge = np .zeros ((4 ,4 ))
316+ self .dRunge [1 ,1 ]= 0.52349249922385610
317+ self .dRunge [2 ,1 ]= 1.1683374366893629
318+ self .dRunge [2 ,2 ]= - 0.75762080241712637
319+ self .dRunge [3 ,1 ]= - 3.6477233846797109e-002
320+ self .dRunge [3 ,2 ]= 0.56936148730740477
321+ self .dRunge [3 ,3 ]= 0.47746263002599681
322+ self .gRunge = np .zeros ((4 ,4 ))
323+ self .gRunge [1 ,1 ]= 0.13145089796226542
324+ self .gRunge [2 ,1 ]= - 0.36855857648747881
325+ self .gRunge [2 ,2 ]= 0.33159232636600550
326+ self .gRunge [3 ,1 ]= - 6.5767130537473045E-002
327+ self .gRunge [3 ,2 ]= 4.0591093109036858E-002
328+ self .gRunge [3 ,3 ]= 6.4902111640806712E-002
329+ self .dtRunge = np .zeros (self .nstages );
330+ for i in range (0 ,self .nstages ):
331+ self .dtRunge [i ]= 0
332+ temp = 1.
333+ for j in range (0 ,i + 1 ):
334+ self .dtRunge [i ]= self .dtRunge [i ]+ self .aRunge [i ,j ]
335+ temp = temp - self .dRunge [i ,j ]
336+ self .dRunge [i ,0 ]= temp
337+ for j in range (0 ,i + 1 ):
338+ self .aRunge [i ,j ]= self .aRunge [i ,j ]/ self .dtRunge [i ]
339+ self .gRunge [i ,j ]= self .gRunge [i ,j ]/ self .dtRunge [i ]
340+
341+ self .U = np .zeros ((self .Ndof ,self .nstages + 1 ))
342+ self .F = np .zeros ((self .Ndof ,self .nstages ))
343+ self .FSlow = np .zeros ((self .Ndof ))
344+ self .nsMin = 8
345+ self .logger .nsmall = 0
346+
347+ def NumSmallTimeSteps (self , dx , dz , dt ):
348+
349+ cs = self .pparams ['c_s' ]
350+ ns = dt / (.9 / np .sqrt (1 / (dx * dx )+ 1 / (dz * dz )) / cs )
351+ ns = max (np .int (np .ceil (ns )),self .nsMin )
352+ # print " dx " , dx
353+ # print " dz " , dz
354+ # print " cs " , cs
355+ # print 1/np.sqrt(1/(dx*dx)+1/(dz*dz))/cs
356+ # print " dt ",dt," ns ",ns
357+
358+ return ns
359+
360+
361+ def timestep (self , u0 , dt ):
362+
363+ self .U [:,0 ] = u0
364+
365+ self .ns = self .NumSmallTimeSteps (self .problem .h [0 ], self .problem .h [1 ], dt )
366+
367+ for i in range (0 ,self .nstages ):
368+ self .F [:,i ] = self .f_slow (self .U [:,i ])
369+ self .FSlow [:] = 0.
370+ for j in range (0 ,i + 1 ):
371+ self .FSlow += (self .aRunge [i ,j ]* self .F [:,j ] + self .gRunge [i ,j ]/ dt * (self .U [:,j ] - u0 ))
372+ self .U [:,i + 1 ] = 0
373+ for j in range (0 ,i + 1 ):
374+ self .U [:,i + 1 ] += self .dRunge [i ,j ]* self .U [:,j ]
375+ nsLoc = np .int (np .ceil (self .ns * self .dtRunge [i ]))
376+ self .logger .nsmall += nsLoc
377+ dtLoc = dt * self .dtRunge [i ]
378+ dTau = dtLoc / nsLoc
379+ self .U [:,i + 1 ] = self .VerletLin (self .U [:,i + 1 ], self .FSlow , nsLoc , dTau )
380+ u0 = self .U [:,self .nstages ]
381+ return u0
382+
383+
384+ def VerletLin (self , u0 , FSlow , ns , dTau ):
385+ for i in range (0 ,ns ):
386+ u0 [0 :self .NdofMom ] += dTau * (self .f_fastMom (u0 ) + FSlow [0 :self .NdofMom ])
387+ u0 [self .NdofMom :self .Ndof ] += dTau * (self .f_fastTher (u0 ) + FSlow [self .NdofMom :self .Ndof ])
388+
389+ return u0
390+
391+ def RK3Lin (self , u0 , FSlow , ns , dTau ):
392+
393+ u = u0
394+ for i in range (0 ,ns ):
395+ u = u0 + dTau / 3. * (self .f_fast (u ) + FSlow )
396+ u = u0 + dTau / 2. * (self .f_fast (u ) + FSlow )
397+ u = u0 + dTau * (self .f_fast (u ) + FSlow )
398+ u0 = u
399+
400+ return u0
401+
402+ def f_slow (self , u ):
403+ return self .problem .D_upwind .dot (u )
404+
405+ def f_fast (self , u ):
406+ return self .problem .M .dot (u )
407+
408+ def f_fastMom (self , u ):
409+ return self .problem .M [0 :self .NdofMom ,self .NdofMom :self .Ndof ]\
410+ .dot (u [self .NdofMom :self .Ndof ])
411+
412+ def f_fastTher (self , u ):
413+ return self .problem .M [self .NdofMom :self .Ndof ,0 :self .NdofMom ]\
414+ .dot (u [0 :self .NdofMom ])
415+
275416class dirk :
276417
277418 def __init__ (self , problem , order ):
@@ -283,7 +424,7 @@ def __init__(self, problem, order):
283424 self .problem = problem
284425
285426 assert self .order in [2 ,22 ,3 ,4 ], 'Order must be 2,22,3,4'
286-
427+
287428 if (self .order == 2 ):
288429 self .nstages = 1
289430 self .A = np .zeros ((1 ,1 ))
0 commit comments