@@ -530,3 +530,110 @@ def dfun(self, state_variables, coupling, local_coupling=0.0,
530
530
531
531
# all this pi makeh me have great hungary, can has sum NaN?
532
532
return self .derivative
533
+
534
+
535
+ class supHopf (ModelNumbaDfun ):
536
+ r"""
537
+ The supHopf model describes the normal form of a supercritical Hopf bifurcation in Cartesian coordinates.
538
+ This normal form has a supercritical bifurcation at a=0 with a the bifurcation parameter in
539
+ the model. So for a < 0, the local dynamics has a stable fixed point, and for a > 0, the local dynamics enters
540
+ in a stable limit cycle.
541
+
542
+ See:
543
+
544
+ .. [Deco_2017a] Deco, G., Kringelbach, M.L., Jirsa, V.K., Ritter, P.
545
+ *The dynamics of resting fluctuations in the brain: metastability and its dynamical
546
+ cortical core* Sci Reports, 2017, 7: 3095.
547
+
548
+ The equations of the supHopf population model read:
549
+
550
+ .. math::
551
+ \dot{x}_{i} &= (a_{i} - x_{i}^{2} - y_{i}^{2})x_{i} - omega{i}y_{i} \\
552
+ \dot{y}_{i} &= (a_{i} - x_{i}^{2} - y_{i}^{2})y_{i} + omega{i}x_{i}
553
+
554
+ """
555
+
556
+ _ui_name = "supHopf"
557
+ ui_configurable_parameters = ['a' , 'omega' ]
558
+
559
+ #supHopf's parameters.
560
+ a = arrays .FloatArray (
561
+ label = r":math:`a`" ,
562
+ default = numpy .array ([- 0.5 ]),
563
+ range = basic .Range (lo = - 10.0 , hi = 10.0 , step = 0.01 ),
564
+ doc = """Local bifurcation parameter.""" ,
565
+ order = 1 )
566
+
567
+ omega = arrays .FloatArray (
568
+ label = r":math:`\omega`" ,
569
+ default = numpy .array ([1. ]),
570
+ range = basic .Range (lo = 0.05 , hi = 630.0 , step = 0.01 ),
571
+ doc = """Angular frequency.""" ,
572
+ order = 2 )
573
+
574
+ # Initialization.
575
+ state_variable_range = basic .Dict (
576
+ label = "State Variable ranges [lo, hi]" ,
577
+ default = {"x" : numpy .array ([- 5.0 , 5.0 ]),
578
+ "y" : numpy .array ([- 5.0 , 5.0 ])},
579
+ doc = """The values for each state-variable should be set to encompass
580
+ the expected dynamic range of that state-variable for the current
581
+ parameters, it is used as a mechanism for bounding random initial
582
+ conditions when the simulation isn't started from an explicit
583
+ history, it is also provides the default range of phase-plane plots.""" ,
584
+ order = 3 )
585
+
586
+ variables_of_interest = basic .Enumerate (
587
+ label = "Variables watched by Monitors" ,
588
+ options = ["x" , "y" ],
589
+ default = ["x" ],
590
+ select_multiple = True ,
591
+ doc = "Quantities of supHopf available to monitor." ,
592
+ order = 4 )
593
+
594
+ state_variables = ["x" , "y" ]
595
+
596
+ _nvar = 2 # number of state-variables
597
+ cvar = numpy .array ([0 , 1 ], dtype = numpy .int32 ) # coupling variables
598
+
599
+ def _numpy_dfun (self , state_variables , coupling , local_coupling = 0.0 ,
600
+ array = numpy .array , where = numpy .where , concat = numpy .concatenate ):
601
+ r"""
602
+ Computes the derivatives of the state-variables of supHopf
603
+ with respect to time.
604
+ """
605
+
606
+ y = state_variables
607
+ ydot = numpy .empty_like (state_variables )
608
+
609
+ # long-range coupling
610
+ c_0 = coupling [0 ]
611
+ c_1 = coupling [1 ]
612
+
613
+ # short-range (local) coupling
614
+ lc_0 = local_coupling * y [0 ]
615
+
616
+ #supHopf's equations in Cartesian coordinates:
617
+ ydot [0 ] = (self .a - y [0 ]** 2 - y [1 ]** 2 ) * y [0 ] - self .omega * y [1 ] + c_0
618
+ ydot [1 ] = (self .a - y [0 ]** 2 - y [1 ]** 2 ) * y [1 ] + self .omega * y [0 ] + c_1
619
+
620
+ return ydot
621
+
622
+ def dfun (self , x , c , local_coupling = 0.0 ):
623
+ x_ = x .reshape (x .shape [:- 1 ]).T
624
+ c_ = c .reshape (c .shape [:- 1 ]).T
625
+ lc_0 = local_coupling * x [0 , :, 0 ]
626
+ deriv = _numba_dfun (x_ , c_ , self .a , self .omega , lc_0 )
627
+ return deriv .T [..., numpy .newaxis ]
628
+
629
+ @guvectorize ([(float64 [:],) * 6 ], '(n),(m)' + ',()' * 3 + '->(n)' , nopython = True )
630
+ def _numba_dfun (y , c , a , omega , lc_0 , ydot ):
631
+ "Gufunc for supHopf model equations."
632
+
633
+ #long-range coupling
634
+ c_0 = c [0 ]
635
+ c_1 = c [1 ]
636
+
637
+ #supHopf equations
638
+ ydot [0 ] = (a [0 ] - y [0 ]** 2 - y [1 ]** 2 ) * y [0 ] - omega [0 ] * y [1 ] + c_0
639
+ ydot [1 ] = (a [0 ] - y [0 ]** 2 - y [1 ]** 2 ) * y [1 ] + omega [0 ] * y [0 ] + c_1
0 commit comments