diff --git a/mbtrack2/tracking/beam_ion_effects.py b/mbtrack2/tracking/beam_ion_effects.py
index a041fee621da8f0249c792213eb0bf5e28ea3901..717b55fefa29fa83120199404be083bca89a9195 100644
--- a/mbtrack2/tracking/beam_ion_effects.py
+++ b/mbtrack2/tracking/beam_ion_effects.py
@@ -56,16 +56,16 @@ class IonMonitor(Monitor, metaclass=ABCMeta):
     def __init__(self, save_every, buffer_size, total_size, file_name=None):
         group_name = "IonData_" + str(next(self._n_monitors))
         dict_buffer = {
-            "mean": (6, buffer_size),
-            "std": (6, buffer_size),
+            "mean": (4, buffer_size),
+            "std": (4, buffer_size),
             "charge": (buffer_size, ),
-            "charge_per_mp": (buffer_size, ),
+            "mp_number": (buffer_size, ),
         }
         dict_file = {
-            "mean": (6, total_size),
-            "std": (6, total_size),
+            "mean": (4, total_size),
+            "std": (4, total_size),
             "charge": (total_size, ),
-            "charge_per_mp": (buffer_size, ),
+            "mp_number": (buffer_size, ),
         }
         self.monitor_init(group_name, save_every, buffer_size, total_size,
                           dict_buffer, dict_file, file_name)
@@ -242,6 +242,7 @@ class IonParticles(Bunch):
             "yp": np.zeros((mp_number, ), dtype=np.float64),
             "tau": np.zeros((mp_number, ), dtype=np.float64),
             "delta": np.zeros((mp_number, ), dtype=np.float64),
+            "charge": np.zeros((mp_number, ), dtype=np.float64),
         }
         self.charge_per_mp = 0
 
@@ -253,8 +254,61 @@ class IonParticles(Bunch):
     @mp_number.setter
     def mp_number(self, value):
         self._mp_number = int(value)
+        
+    @property
+    def charge(self):
+        """Bunch charge in [C]"""
+        return self["charge"].sum()
+    
+    def _mean_weighted(self, coord):
+        """
+        Return the mean position of alive particles for each coordinates.
+        """
+        if self.charge == 0:
+            return np.zeros_like(coord, dtype=float)
+        else:
+            mean = [[np.average(self[name], weights=self["charge"])] for name in coord]
+            return np.squeeze(np.array(mean))
 
-    def generate_as_a_distribution(self, electron_bunch):
+    def _mean_std_weighted(self, coord):
+        """
+        Return the standard deviation of the position of alive
+        particles for each coordinates.
+        """
+        if self.charge == 0:
+            return np.zeros_like(coord, dtype=float), np.zeros_like(coord, dtype=float)
+        else:
+            mean = [[np.average(self[name], weights=self["charge"])] for name in coord]
+            var = []
+            for i, name in enumerate(coord):
+                var.append(np.average((self[name]-mean[i])**2, weights=self["charge"]))
+            var = np.array(var)
+            return np.squeeze(np.array(mean)), np.squeeze(np.sqrt(var))
+    
+    @property
+    def mean(self):
+        coord = ["x","xp","y","yp"]
+        return self._mean_weighted(coord)
+    
+    @property
+    def mean_weighted(self):
+        coord = ["x","y"]
+        mean = self._mean_weighted(coord)
+        return mean[0], mean[1]
+    
+    @property
+    def std(self):
+        coord = ["x","xp","y","yp"]
+        _, std = self._mean_std_weighted(coord)
+        return std
+    
+    @property
+    def mean_std_weighted(self):
+        coord = ["x","y"]
+        mean, std = self._mean_std_weighted(coord)
+        return mean[0], mean[1], std[0], std[1]
+
+    def generate_as_a_distribution(self, electron_bunch, charge):
         """
         Generates the particle positions based on a normal distribution, taking distribution parameters from an electron bunch.
 
@@ -289,8 +343,9 @@ class IonParticles(Bunch):
             high=self.ion_element_length / c,
             size=self.mp_number,
         )
+        self["charge"] = np.ones((self.mp_number, )) * charge / self.mp_number
 
-    def generate_from_random_samples(self, electron_bunch):
+    def generate_from_random_samples(self, electron_bunch, charge):
         """
         Generates the particle positions and times based on random samples from electron positions in the bunch.
 
@@ -316,6 +371,7 @@ class IonParticles(Bunch):
             high=self.ion_element_length / c,
             size=self.mp_number,
         )
+        self["charge"] = np.ones((self.mp_number, )) * charge / self.mp_number
 
     def __add__(self, new_particles):
         self.mp_number += new_particles.mp_number
@@ -514,7 +570,7 @@ class BeamIonElement(Element):
 
     def _get_efields(self, first_beam, second_beam, field_model):
         """
-        Calculates the electromagnetic field of the first beam acting on the second beam for a given field model.
+        Calculates the electromagnetic field of the second beam acting on the first beam for a given field model.
     
         Parameters
         ----------
@@ -536,14 +592,17 @@ class BeamIonElement(Element):
             raise ValueError(
                 f"The implementation for required beam-ion interaction model {field_model} is not implemented"
             )
-        sb_mx, sb_stdx = (
-            second_beam["x"].mean(),
-            second_beam["x"].std(),
-        )
-        sb_my, sb_stdy = (
-            second_beam["y"].mean(),
-            second_beam["y"].std(),
-        )
+        if isinstance(second_beam, IonParticles):
+            sb_mx, sb_my, sb_stdx, sb_stdy = second_beam.mean_std_weighted
+        else:
+            sb_mx, sb_stdx = (
+                second_beam["x"].mean(),
+                second_beam["x"].std(),
+            )
+            sb_my, sb_stdy = (
+                second_beam["y"].mean(),
+                second_beam["y"].std(),
+            )
         if field_model == "weak":
             en_x, en_y = get_displaced_efield(
                 _efieldn_mit,
@@ -556,10 +615,13 @@ class BeamIonElement(Element):
             )
 
         elif field_model == "strong":
-            fb_mx, fb_my = (
-                first_beam["x"].mean(),
-                first_beam["y"].mean(),
-            )
+            if isinstance(first_beam, IonParticles):
+                fb_mx, fb_my = first_beam.mean_weighted
+            else:
+                fb_mx, fb_my = (
+                    first_beam["x"].mean(),
+                    first_beam["y"].mean(),
+                )
             en_x, en_y = get_displaced_efield(_efieldn_mit, fb_mx, fb_my,
                                               sb_stdx, sb_stdy, sb_mx, sb_my)
 
@@ -647,18 +709,19 @@ class BeamIonElement(Element):
             ion_element_length=self.ion_element_length,
             ring=self.ring,
         )
+        new_ion_charge = (electron_bunch.charge *
+                          self.ionization_cross_section *
+                          self.residual_gas_density *
+                          self.ion_element_length)
         if self.generate_method == 'distribution':
             new_ion_particles.generate_as_a_distribution(
-                electron_bunch=electron_bunch)
+                electron_bunch=electron_bunch,
+                charge=new_ion_charge)
         elif self.generate_method == 'samples':
             new_ion_particles.generate_from_random_samples(
-                electron_bunch=electron_bunch)
+                electron_bunch=electron_bunch,
+                charge=new_ion_charge)
         self.ion_beam += new_ion_particles
-        self.ion_beam.charge_per_mp = (electron_bunch.charge *
-                                       self.ionization_cross_section *
-                                       self.residual_gas_density *
-                                       self.ion_element_length /
-                                       self.n_ion_macroparticles_per_bunch)
 
     @parallel
     def track(self, electron_bunch):
diff --git a/tests/unit/tracking/test_beam_ion_effects.py b/tests/unit/tracking/test_beam_ion_effects.py
index 368d063b0ac15aeb93aba8a52e24ed574f59a5fa..8a556efe27e65fa8c77396aa39a139cfe4235122 100644
--- a/tests/unit/tracking/test_beam_ion_effects.py
+++ b/tests/unit/tracking/test_beam_ion_effects.py
@@ -25,8 +25,10 @@ class TestIonParticles:
 
     # Generate particle distribution using electron bunch parameters via generate_as_a_distribution()
     def test_generate_as_distribution(self, generate_ion_particles, large_bunch):
-        ions = generate_ion_particles(mp_number=1e5)
-        ions.generate_as_a_distribution(large_bunch)
+        mp_number = 1e5
+        charge = 1e-9
+        ions = generate_ion_particles(mp_number)
+        ions.generate_as_a_distribution(large_bunch, charge)
     
         assert np.isclose(ions["x"].mean(), large_bunch["x"].mean(), rtol=0.1, atol=1e-5)
         assert np.isclose(ions["x"].std(), large_bunch["x"].std(), rtol=0.1, atol=1e-5)
@@ -37,11 +39,15 @@ class TestIonParticles:
         assert np.all(ions["delta"] == 0)
         assert np.all(ions["tau"] >= -ions.ion_element_length)
         assert np.all(ions["tau"] <= ions.ion_element_length)
+        assert np.isclose(ions.charge, charge)
+        assert np.isclose(ions["charge"].mean(), charge/mp_number, rtol=0.01, atol=1e-9)
 
     # Generate random particle samples from electron bunch via generate_from_random_samples()
     def test_generate_from_random_samples(self, generate_ion_particles, large_bunch):
-        ions = generate_ion_particles(mp_number=1e5)
-        ions.generate_from_random_samples(large_bunch)
+        mp_number = 1e5
+        charge = 1e-9
+        ions = generate_ion_particles(mp_number)
+        ions.generate_from_random_samples(large_bunch, charge)
     
         assert np.all(np.isin(ions["x"], large_bunch["x"]))
         assert np.all(np.isin(ions["y"], large_bunch["y"]))
@@ -50,7 +56,9 @@ class TestIonParticles:
         assert np.all(ions["delta"] == 0)
         assert np.all(ions["tau"] >= -ions.ion_element_length)
         assert np.all(ions["tau"] <= ions.ion_element_length)
-
+        assert np.isclose(ions.charge, charge)
+        assert np.isclose(ions["charge"].mean(), charge/mp_number, rtol=0.01, atol=1e-9)
+        
     # Add two IonParticles instances together and verify combined particle arrays
     def test_add_ion_particles(self, generate_ion_particles):
         ions1 = generate_ion_particles(mp_number=100)
@@ -58,14 +66,14 @@ class TestIonParticles:
     
         combined = ions1 + ions2
         assert combined.mp_number == 150
-        assert all(combined[coord].shape == (150,) for coord in ["x","xp","y","yp","tau","delta"])
+        assert all(combined[coord].shape == (150,) for coord in ["x","xp","y","yp","tau","delta","charge"])
         assert np.all(combined.alive == True)
 
     # Initialize with alive=False and verify all particles marked as dead
     def test_init_dead_particles(self, generate_ion_particles):
         ions = generate_ion_particles(alive=False)
         assert np.all(ions.alive == False)
-        assert all(ions[coord].shape == (1,) for coord in ["x","xp","y","yp","tau","delta"])
+        assert all(ions[coord].shape == (1,) for coord in ["x","xp","y","yp","tau","delta","charge"])
 
     # Generate distributions with electron bunch containing no particles
     def test_generate_from_empty_bunch(self, generate_ion_particles, small_bunch):
@@ -73,9 +81,9 @@ class TestIonParticles:
         ions = generate_ion_particles()
     
         with pytest.raises(ValueError):
-            ions.generate_as_a_distribution(small_bunch)
+            ions.generate_as_a_distribution(small_bunch, 1e-9)
         with pytest.raises(ValueError):
-            ions.generate_from_random_samples(small_bunch)
+            ions.generate_from_random_samples(small_bunch, 1e-9)
             
 @pytest.fixture
 def generate_ion_monitor(tmp_path):
@@ -118,8 +126,8 @@ class TestIonMonitor:
     def test_data_structures_initialization(self, generate_ion_monitor):
         monitor = generate_ion_monitor()
     
-        assert monitor.mean.shape == (6, 10)
-        assert monitor.std.shape == (6, 10)
+        assert monitor.mean.shape == (4, 10)
+        assert monitor.std.shape == (4, 10)
         assert monitor.charge.shape == (10,)
         assert monitor.time.shape == (10,)
         assert monitor.time.dtype == int