diff --git a/tracking/monitors/monitors.py b/tracking/monitors/monitors.py
index 1533e1501745a371ebfdbd3a46df4ebe939e4c64..348371aafad9bcc97de7ba8508b5029429ce8d96 100644
--- a/tracking/monitors/monitors.py
+++ b/tracking/monitors/monitors.py
@@ -1370,13 +1370,34 @@ class CavityMonitor(Monitor):
         group_name = cavity_name
         dict_buffer = {"cavity_phasor_record":(ring.h, buffer_size,),
                        "beam_phasor_record":(ring.h, buffer_size,),
-                       "detune":(buffer_size,)}
+                       "detune":(buffer_size,),
+                       "psi":(buffer_size,),
+                       "Vg":(buffer_size,),
+                       "theta_g":(buffer_size,),
+                       "Pg":(buffer_size,),
+                       "Rs":(buffer_size,),
+                       "Q":(buffer_size,),
+                       "QL":(buffer_size,)}
         dict_file = {"cavity_phasor_record":(ring.h, total_size,),
                      "beam_phasor_record":(ring.h, total_size,),
-                      "detune":(total_size,)}
+                     "detune":(total_size,),
+                     "psi":(total_size,),
+                     "Vg":(total_size,),
+                     "theta_g":(total_size,),
+                     "Pg":(total_size,),
+                     "Rs":(total_size,),
+                     "Q":(total_size,),
+                     "QL":(total_size,)}
         dict_dtype = {"cavity_phasor_record":complex,
                       "beam_phasor_record":complex,
-                      "detune":float}
+                      "detune":float,
+                      "psi":float,
+                      "Vg":float,
+                      "theta_g":float,
+                      "Pg":float,
+                      "Rs":float,
+                      "Q":float,
+                      "QL":float}
         
         self.monitor_init(group_name, save_every, buffer_size, total_size,
                           dict_buffer, dict_file, file_name, mpi_mode, 
diff --git a/tracking/monitors/plotting.py b/tracking/monitors/plotting.py
index dfbe1bb38d658e62f97ac4c892af5ff08048a1fe..8096647a0ee7f0670a055fdc03b50b4dde369200 100644
--- a/tracking/monitors/plotting.py
+++ b/tracking/monitors/plotting.py
@@ -1072,9 +1072,12 @@ def plot_cavitydata(filename, cavity_name, phasor="cavity",
             - "turn" plots the phasor voltage and ange versus bunch index for
             a given turn.
             - "streak_volt" plots the phasor voltage versus bunch index and 
-            time
+            time.
             - "streak_angle" plots the phasor angle versus bunch index and 
-            time
+            time.
+            - "detune" or "psi" plots the detuning or tuning angle versus time.
+            - "power" plots the generator, cavity, beam and reflected power
+            versus time.
     bunch_number : int, optional
         Bunch number to select. The default is 0.
     turn : int, optional
@@ -1166,7 +1169,45 @@ def plot_cavitydata(filename, cavity_name, phasor="cavity",
         ax.set_xlabel("Bunch index")
         ax.set_ylabel("Number of turns")
         cbar = fig.colorbar(c, ax=ax)
-        cbar.set_label(ylabel) 
-    
+        cbar.set_label(ylabel)
+        
+    if plot_type == "detune" or plot_type == "psi":
+        
+        fig, ax = plt.subplots()
+        if plot_type == "detune":
+            data = np.array(cavity_data["detune"])*1e-3
+            ylabel = r"Detuning $\Delta f$ [kHz]"
+        elif plot_type == "psi":
+            data = np.array(cavity_data["psi"])
+            ylabel = r"Tuning angle $\psi$"
+            
+        ax.plot(time, data)
+        ax.set_xlabel("Number of turns")
+        ax.set_ylabel(ylabel)
+        
+    if plot_type == "power":
+        Vc = np.mean(np.abs(cavity_data["cavity_phasor_record"]),0)
+        theta = np.mean(np.angle(cavity_data["cavity_phasor_record"]),0)
+        try:
+            bunch_index = (file["Beam"]["current"][:,0] != 0).nonzero()[0]
+            I0 = np.nansum(file["Beam"]["current"][bunch_index,:],0)
+        except:
+            print("Beam monitor is needed to compute power.")
+            
+        Rs = np.array(cavity_data["Rs"])
+        Pc = Vc**2 / (2 * Rs)
+        Pb = I0 * Vc * np.cos(theta)
+        Pg = np.array(cavity_data["Pg"])
+        Pr = Pg - Pb - Pc
+        
+        fig, ax = plt.subplots()
+        ax.plot(time, Pg*1e-3, label="Generator power $P_g$ [kW]")
+        ax.plot(time, Pb*1e-3, label="Beam power $P_b$ [kW]")
+        ax.plot(time, Pc*1e-3, label="Dissipated cavity power $P_c$ [kW]")
+        ax.plot(time, Pr*1e-3, label="Reflected power $P_r$ [kW]")
+        ax.set_xlabel("Number of turns")
+        ax.set_ylabel("Power [kW]")
+        plt.legend()
+        
     file.close()
     return fig
diff --git a/tracking/rf.py b/tracking/rf.py
index f5fc31472ccdbdddb44b60b486ed4e24aa93c219..de05d591b9e3e6d57a4752619b3882c204ea354e 100644
--- a/tracking/rf.py
+++ b/tracking/rf.py
@@ -55,6 +55,7 @@ class RFCavity(Element):
 class CavityResonator():
     """Cavity resonator class for active or passive RF cavity with beam
     loading or HOM, based on [1].
+    Use cosine definition.
     
     Parameters
     ----------
@@ -62,13 +63,17 @@ class CavityResonator():
     m : int or float
         Harmonic number of the cavity.
     Rs : float
-        Shunt impedance of the cavity in [Ohm], defined as 0.5*Vc*Vc/Pc.
+        Shunt impedance of the cavities in [Ohm], defined as 0.5*Vc*Vc/Pc.
+        If Ncav = 1, used for the total shunt impedance.
+        If Ncav > 1, used for the shunt impedance per cavity.
     Q : float
         Quality factor of the cavity.
     QL : float
         Loaded quality factor of the cavity.
     detune : float
         Detuing of the cavity in [Hz], defined as (fr - m*ring.f1).
+    Ncav : int, optional
+        Number of cavities.
     Vc : float, optinal
         Total cavity voltage in [V].
     theta : float, optional
@@ -92,6 +97,8 @@ class CavityResonator():
         Cavity total phase in [rad].
     loss_factor : float
         Cavity loss factor in [V/C].
+    Rs_per_cavity : float
+        Shunt impedance of a single cavity in [Ohm], defined as 0.5*Vc*Vc/Pc.
     beta : float
         Coupling coefficient of the cavity.
     fr : float
@@ -102,6 +109,8 @@ class CavityResonator():
         Tuning angle in [rad].
     filling_time : float
         Cavity filling time in [s].
+    Pc : float
+        Power dissipated in the cavity walls in [W].
     Pg : float
         Generator power in [W].
     Vgr : float
@@ -126,8 +135,14 @@ class CavityResonator():
         Return beam voltage at resonance in [V].
     Vb(I0)
         Return beam voltage in [V].
+    Pb(I0)
+        Return power transmitted to the beam in [W].
+    Pr(I0)
+        Return power reflected back to the generator in [W].
     Z(f)
         Cavity impedance in [Ohm] for a given frequency f in [Hz].
+    set_optimal_coupling(I0)
+        Set coupling to optimal value.
     set_optimal_detune(I0)
         Set detuning to optimal conditions.
     set_generator(I0)
@@ -161,10 +176,14 @@ class CavityResonator():
     factories. In Frontiers of Particle Beams: Factories with e+ e-Rings 
     (pp. 293-311). Springer, Berlin, Heidelberg.
     """
-    def __init__(self, ring, m, Rs, Q, QL, detune, Vc=0, theta=0):
+    def __init__(self, ring, m, Rs, Q, QL, detune, Ncav=1, Vc=0, theta=0):
         self.ring = ring
         self.m = m
-        self.Rs = Rs
+        self.Ncav = Ncav
+        if Ncav != 1:
+            self.Rs_per_cavity = Rs
+        else:
+            self.Rs = Rs
         self.Q = Q
         self.QL = QL
         self.detune = detune
@@ -173,6 +192,11 @@ class CavityResonator():
         self.beam_phasor = np.zeros(1, dtype=np.complex)
         self.beam_phasor_record = np.zeros((self.ring.h), dtype=np.complex)
         self.tracking = False
+        self.Vg = 0
+        self.theta_g = 0
+        self.Vgr = 0
+        self.theta_gr = 0
+        self.Pg = 0
         
     def init_tracking(self, beam):
         """
@@ -516,15 +540,34 @@ class CavityResonator():
     @m.setter
     def m(self, value):
         self._m = value
+        
+    @property
+    def Ncav(self):
+        """Number of cavities"""
+        return self._Ncav
+
+    @Ncav.setter
+    def Ncav(self, value):
+        self._Ncav = value
+        
+    @property
+    def Rs_per_cavity(self):
+        """Shunt impedance of a single cavity in [Ohm], defined as 
+        0.5*Vc*Vc/Pc."""
+        return self._Rs_per_cavity
+
+    @Rs_per_cavity.setter
+    def Rs_per_cavity(self, value):
+        self._Rs_per_cavity = value
 
     @property
     def Rs(self):
         """Shunt impedance [ohm]"""
-        return self._Rs
+        return self.Rs_per_cavity * self.Ncav
 
     @Rs.setter
     def Rs(self, value):
-        self._Rs = value
+        self.Rs_per_cavity = value / self.Ncav
 
     @property
     def Q(self):
@@ -600,7 +643,46 @@ class CavityResonator():
     def filling_time(self):
         """Cavity filling time in [s]"""
         return 2*self.QL/self.wr
-        
+    
+    @property
+    def Pc(self):
+        """Power dissipated in the cavity walls in [W]"""
+        return self.Vc**2 / (2 * self.Rs)
+    
+    def Pb(self, I0):
+        """
+        Return power transmitted to the beam in [W] - near Eq. (4.2.3) in [1].
+
+        Parameters
+        ----------
+        I0 : float
+            Beam current in [A].
+
+        Returns
+        -------
+        float
+            Power transmitted to the beam in [W].
+
+        """
+        return I0 * self.Vc * np.cos(self.theta)
+    
+    def Pr(self, I0):
+        """
+        Power reflected back to the generator in [W].
+
+        Parameters
+        ----------
+        I0 : float
+            Beam current in [A].
+
+        Returns
+        -------
+        float
+            Power reflected back to the generator in [W].
+
+        """
+        return self.Pg - self.Pb(I0) - self.Pc
+
     def Vbr(self, I0):
         """
         Return beam voltage at resonance in [V].
@@ -650,6 +732,19 @@ class CavityResonator():
 
         """
         self.psi = np.arctan(-self.Vbr(I0)/self.Vc*np.sin(self.theta))
+        
+    def set_optimal_coupling(self, I0):
+        """
+        Set coupling to optimal value - Eq. (4.2.3) in [1].
+
+        Parameters
+        ----------
+        I0 : float
+            Beam current in [A].
+
+        """
+        self.beta = 1 + (2 * I0 * self.Rs * np.cos(self.theta) / 
+                         self.Vc)
                 
     def set_generator(self, I0):
         """
diff --git a/vlasov/beamloading.py b/vlasov/beamloading.py
index 87aea1ab1d02956b2e315fa3d7b4c48da100ed1f..ae2eed4c549ad692565eed0b38005d46c1564424 100644
--- a/vlasov/beamloading.py
+++ b/vlasov/beamloading.py
@@ -26,8 +26,8 @@ class BeamLoadingEquilibrium():
     ring : Synchrotron object
     cavity_list : list of CavityResonator objects
     I0 : beam current in [A].
-    auto_set_MC_theta : if True, allow class to change generator phase for
-        CavityResonator objetcs with m = 1
+    auto_set_MC_theta : if True, allow class to change cavity phase for
+        CavityResonator objetcs with m = 1 (i.e. main cavities)
     F : list of form factor amplitude
     PHI : list of form factor phase
     B1 : lower intergration boundary
@@ -61,6 +61,10 @@ class BeamLoadingEquilibrium():
             * self.ring.E0 * self.ring.L)
         self.ug = np.zeros((self.n_cavity,))
         self.ub = np.zeros((self.n_cavity,))
+        self.update_potentials()
+            
+    def update_potentials(self):
+        """Update potentials with cavity and ring data."""
         for i in range(self.n_cavity):
             cavity = self.cavity_list[i]
             self.ug[i] = cavity.Vg / (
@@ -121,20 +125,24 @@ class BeamLoadingEquilibrium():
         B = quad(f, self.B1, self.B2)
         return A[0] / B[0]
 
-    def to_solve(self, x):
+    def to_solve(self, x, CM=True):
         """System of non-linear equation to solve to find the form factors F
         and PHI at equilibrum.
         The system is composed of Eq. (B6) and (B7) of [1] for each cavity.
-        If auto_set_MC_theta == True, the system also find the generator phase
-        to impose energy balance.
+        If auto_set_MC_theta == True, the system also find the main cavity 
+        phase to impose energy balance or cancel center of mass offset.
+        If CM is True, the system imposes zero center of mass offset,
+        if False, the system imposes energy balance.
         """
-        # Update values of F, PHI and theta_g
+        # Update values of F, PHI and theta
         if self.auto_set_MC_theta:
             self.F = x[:-1:2]
             for i in range(self.n_cavity):
                 cavity = self.cavity_list[i]
                 if cavity.m == 1:
-                    cavity.theta_g = x[-1]
+                    cavity.theta = x[-1]
+                    cavity.set_generator(0.5)
+                    self.update_potentials()
         else:
             self.F = x[::2]
         self.PHI = x[1::2]
@@ -148,8 +156,11 @@ class BeamLoadingEquilibrium():
                     lambda y: self.uexp(y), lambda y: np.cos(self.ring.k1 * cavity.m * y))
                 res[2 * i + 1] = self.F[i] * np.sin(self.PHI[i]) - self.integrate_func(
                     lambda y: self.uexp(y), lambda y: np.sin(self.ring.k1 * cavity.m * y))
-            # Factor 1e-8 for better convergence
-            res[self.n_cavity * 2] = self.energy_balance() * 1e-8
+            # Factor 1e-8 or 1e12 for better convergence
+            if CM is True:
+                res[self.n_cavity * 2] = self.center_of_mass() * 1e12
+            else:
+                res[self.n_cavity * 2] = self.energy_balance() * 1e-8
         else:
             res = np.zeros((self.n_cavity * 2,))
             for i in range(self.n_cavity):
@@ -242,7 +253,8 @@ class BeamLoadingEquilibrium():
         variance = np.average((z0 - average)**2, weights=values)
         return np.sqrt(variance)
 
-    def beam_equilibrium(self, x0=None, tol=1e-4, method='hybr', options=None, plot = False):
+    def beam_equilibrium(self, x0=None, tol=1e-4, method='hybr', options=None, 
+                         plot = False, CM=True):
         """Solve system of non-linear equation to find the form factors F
         and PHI at equilibrum. Can be used to compute the equilibrium bunch
         profile.
@@ -254,6 +266,8 @@ class BeamLoadingEquilibrium():
         method : method used by scipy.optimize.root to solve the system
         options : options given to scipy.optimize.root
         plot : if True, plot the equilibrium bunch profile
+        CM : if True, the system imposes zero center of mass offset,
+        if False, the system imposes energy balance.
         
         Returns
         -------
@@ -262,12 +276,17 @@ class BeamLoadingEquilibrium():
         if x0 is None:
             x0 = [1, 0] * self.n_cavity
             if self.auto_set_MC_theta:
-                x0 = x0 + [self.cavity_list[0].theta_g]
+                x0 = x0 + [self.cavity_list[0].theta]
 
-        print("The initial energy balance is " +
-              str(self.energy_balance()) + " eV")
+        if CM:
+            print("The initial center of mass offset is " +
+                  str(self.center_of_mass()*1e12) + " ps")
+        else:
+            print("The initial energy balance is " +
+                  str(self.energy_balance()) + " eV")
 
-        sol = root(self.to_solve, x0, tol=tol, method=method, options=options)
+        sol = root(lambda x : self.to_solve(x, CM), x0, tol=tol, method=method, 
+                   options=options)
 
         # Update values of F, PHI and theta_g
         if self.auto_set_MC_theta:
@@ -275,13 +294,17 @@ class BeamLoadingEquilibrium():
             for i in range(self.n_cavity):
                 cavity = self.cavity_list[i]
                 if cavity.m == 1:
-                    cavity.theta_g = sol.x[-1]
+                    cavity.theta = sol.x[-1]
         else:
             self.F = sol.x[::2]
         self.PHI = sol.x[1::2]
 
-        print("The final energy balance is " +
-              str(self.energy_balance()) + " eV")
+        if CM:
+            print("The final center of mass offset is " +
+                  str(self.center_of_mass()*1e12) + " ps")
+        else:
+            print("The final energy balance is " +
+                  str(self.energy_balance()) + " eV")
         print("The algorithm has converged: " + str(sol.success))
         
         if plot: