@@ -2,6 +2,9 @@ export add_Hopf!
22export Hopf_variables
33export replace_Hopf_variable!
44
5+ using HarmonicBalance: is_rearranged, rearrange_standard
6+ using HarmonicBalance: LinearResponse. get_implicit_Jacobian
7+
58
69" Add a Hopf bifurcation to the system."
710function add_Hopf! (eom:: DifferentialEquation , Δω:: Num )
1619add_Hopf! (eom:: DifferentialEquation ; frequency:: Num , multiplicity:: Int ) = [add_Hopf! (eom, frequency) for k in 1 : multiplicity]
1720
1821
19-
2022"""
2123 Hopf_variables(eom, freq)
2224"""
2325Hopf_variables (eom:: HarmonicEquation , freq:: Num ) = filter (x -> any (isequal .(freq, get_all_terms (x. ω))), eom. variables)
2426
2527
26- function replace_Hopf_variable! (eom :: HarmonicEquation , freq :: Num )
27- pair_to_change = Hopf_variables (eom, freq)[ 1 ] # eliminate of the Cartesian variables, it does not matter from which VDP pair
28- to_eliminate = pair_to_change . symbols[ 2 ]
29- rules = Dict (freq => HarmonicBalance . declare_variable ( string (freq), first ( get_independent_variables (eom))), to_eliminate => Num ( 0 ) )
30- eom . equations = expand_derivatives .( substitute_all (eom . equations, rules))
31- eom . parameters = setdiff (eom. parameters, [freq]) # freq is now NOT a parameter
32- eom . variables = setdiff (eom. variables, [pair_to_change] )
33- new_variable = HarmonicBalance . declare_variable ( string (freq))
34- eom . variables = cat (eom . variables, _VDP_Hopf (pair_to_change, to_eliminate, new_variable), dims = 1 )
35- end
28+ """
29+ Obtain the Jacobian of `eom` with a free (Hopf) variable `free_var`.
30+ `free_var` marks the variable which is free due to U(1) symmetry. Its entry in the Jacobian matrix must be discarded
31+ (the discarded eigenvalue is 0, corresponding to a free phase. )
32+ """
33+ function _Hopf_Jacobian (eom:: HarmonicEquation , free_var :: HarmonicVariable )
34+ eom_Jac = rearrange_standard (eom)
35+ free_idx = findall (x -> isequal (x, free_var), eom_Jac . variables)
36+ deleteat! (eom_Jac . equations, free_idx )
37+ deleteat! (eom_Jac . variables, free_idx)
3638
37- function replace_Hopf_variable (eom:: HarmonicEquation , freq:: Num )
38- new_eom = deepcopy (eom)
39- replace_Hopf_variable! (new_eom, freq)
40- new_eom
39+ # the free variable can be fixed to zero, this is also done in the corresponding HarmonicEquation later
40+ eom_Jac = substitute_all (eom_Jac, free_var => 0 )
41+ J = get_implicit_Jacobian (eom_Jac)
4142end
4243
4344
44- function _VDP_Hopf (old:: HarmonicVariable , eliminated:: Num , new_sym:: Num )
45- new_VDP = deepcopy (old)
46- idx = findall (x-> isequal (x, eliminated), old. symbols)[1 ]
47- indep = Num (first (arguments (eliminated. val)))
48- new_VDP. symbols[idx] = HarmonicBalance. declare_variable (string (new_sym), indep)
49- new_VDP. types[idx] = " Hopf"
50- new_VDP. names[new_sym] = string (new_sym)
51- delete! (new_VDP. names, Num (var_name (eliminated)))
52- return new_VDP
45+ """
46+ Construct a `Problem` in the case where U(1) symmetry is present
47+ due to having added a Hopf variable with frequency `Hopf_ω`.
48+ """
49+ function _Hopf_Problem (eom:: HarmonicEquation , Hopf_ω:: Num )
50+
51+ isempty (Hopf_variables (eom, Hopf_ω)) ? error (" No Hopf variables found!" ) : nothing
52+ ! any (isequal .(eom. parameters, Hopf_ω)) ? error (Hopf_ω, " is not a parameter of the harmonic equation!" ) : nothing
53+
54+ free_var = Hopf_variables (eom, Hopf_ω)[end ] # eliminate one of the Cartesian variables, it does not matter which
55+
56+ # get the Hopf Jacobian before altering anything - this is the usual Jacobian but the entries corresponding
57+ # to the free variable are removed
58+ J = _Hopf_Jacobian (eom, free_var)
59+
60+ new_symbol = HarmonicBalance. declare_variable (string (Hopf_ω), first (get_independent_variables (eom)))
61+ rules = Dict (Hopf_ω => new_symbol, free_var. symbol => Num (0 ))
62+ eom. equations = expand_derivatives .(substitute_all (eom. equations, rules))
63+ eom. parameters = setdiff (eom. parameters, [Hopf_ω]) # Hopf_ω is now NOT a parameter anymore
64+
65+ free_var. type = " Hopf"
66+ free_var. ω = Num (0 )
67+ free_var. symbol = new_symbol
68+ free_var. name = var_name (new_symbol)
69+
70+ # define Problem as usual but with the Hopf Jacobian (always computed implicitly)
71+ p = Problem (eom; Jacobian= J)
72+ return p
5373end
5474
0 commit comments