diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py
index 889145c6865ea1bb0e9de59c5acdec8381302178..4d84ae5ff6e66f98e64b2237fd87872cf86ed803 100644
--- a/binarycpython/utils/grid.py
+++ b/binarycpython/utils/grid.py
@@ -111,7 +111,10 @@ class Population:
     def set_bse_option(self, key, arg):
         """
         Setter for the BSE options.
+
+        # TODO: Put a check here that compares it to the defaults and says something
         """
+
         self.bse_options[key] = arg
 
     def set(self, **kwargs):
@@ -126,19 +129,26 @@ class Population:
         in the self.grid_options
 
         If neither of above is met; the key and the value get stored in a custom_options dict.
-
-        TODO: catch those parameter names that contain an %d
         """
 
+        # Select the params that end with %d
+        special_params = [el for el in list(self.defaults.keys()) if el.endswith('%d')]
+
+        # Go over all the input
         for key in kwargs:
             # Filter out keys for the bse_options
             if key in self.defaults.keys():
-                verbose_print("adding: {}={} to BSE_options".format(key, kwargs[key]), self.grid_options["verbose"], 1)
+                verbose_print("adding: {}={} to BSE_options".format(key, kwargs[key]), self.grid_options["verbosity"], 1)
+                self.bse_options[key] = kwargs[key]
+
+            # Extra check to check if the key fits one of parameter names that end with %d
+            elif any([True if (key.startswith(param[:-2]) and len(param[:-2]) < len(key)) else False for param in special_params]):
+                verbose_print("adding: {}={} to BSE_options by catching the %d".format(key, kwargs[key]), self.grid_options["verbosity"], 1)
                 self.bse_options[key] = kwargs[key]
 
             # Filter out keys for the grid_options
             elif key in self.grid_options.keys():
-                verbose_print("adding: {}={} to grid_options".format(key, kwargs[key]), self.grid_options["verbose"], 1)
+                verbose_print("adding: {}={} to grid_options".format(key, kwargs[key]), self.grid_options["verbosity"], 1)
                 self.grid_options[key] = kwargs[key]
 
             # The of the keys go into a custom_options dict
@@ -168,7 +178,7 @@ class Population:
         # How its set up now is that as input you need to give --cmdline "metallicity=0.002"
         # Its checked if this exists and handled accordingly.
         if args.cmdline:
-            verbose_print("Found cmdline args. Parsing them now", self.grid_options["verbose"], 1)
+            verbose_print("Found cmdline args. Parsing them now", self.grid_options["verbosity"], 1)
 
             # Grab the input and split them up, while accepting only non-empty entries
             cmdline_args = args.cmdline
@@ -285,7 +295,7 @@ class Population:
 
         # Load it into the grid_options
         self.grid_options["grid_variables"][grid_variable["name"]] = grid_variable
-        verbose_print("Added grid variable: {}".format(json.dumps(grid_variable, indent=4)), self.grid_options["verbose"], 1)
+        verbose_print("Added grid variable: {}".format(json.dumps(grid_variable, indent=4)), self.grid_options["verbosity"], 1)
 
     ###################################################
     # Return functions
@@ -378,6 +388,8 @@ class Population:
         TODO: Fix to write things to the directory. which options do which etc
 
         TODO: theres flawed logic here. rewrite this part pls
+
+        TODO: consider actually just removing the whole 'output to file' part and let the user do this. 
         """
 
         all_info = self.return_all_info(
@@ -390,19 +402,6 @@ class Population:
         # Copy dict
         all_info_cleaned = copy.deepcopy(all_info)
 
-        # # Clean the all_info_dict: (i.e. transform the function objects to strings)
-        # if all_info_cleaned.get("population_settings", None):
-        #     if all_info_cleaned["population_settings"]["grid_options"][
-        #             "parse_function"
-        #     ]:
-        #         all_info_cleaned["population_settings"]["grid_options"][
-        #             "parse_function"
-        #         ] = str(
-        #             all_info_cleaned["population_settings"]["grid_options"][
-        #                 "parse_function"
-        #             ]
-        #         )
-
         if use_datadir:
             if not self.custom_options.get("base_filename", None):
                 base_name = "simulation_{}".format(
@@ -420,7 +419,7 @@ class Population:
                 self.custom_options["data_dir"], settings_name
             )
 
-            verbose_print("Writing settings to {}".format(settings_fullname), self.grid_options["verbose"], 1)
+            verbose_print("Writing settings to {}".format(settings_fullname), self.grid_options["verbosity"], 1)
             # if not outfile.endswith('json'):
             with open(settings_fullname, "w") as file:
                 file.write(
@@ -428,10 +427,10 @@ class Population:
                 )
 
         else:
-            verbose_print("Writing settings to {}".format(outfile), self.grid_options["verbose"], 1)
+            verbose_print("Writing settings to {}".format(outfile), self.grid_options["verbosity"], 1)
             # if not outfile.endswith('json'):
             with open(outfile, "w") as file:
-                file.write(json.dumps(all_info_cleaned, indent=4))
+                file.write(json.dumps(all_info_cleaned, indent=4, default=binaryc_json_serializer))
 
     def set_custom_logging(self):
         """
@@ -440,12 +439,12 @@ class Population:
         """
 
         # C_logging_code gets priority of C_autogen_code
-        verbose_print("Creating and loading custom logging functionality", self.grid_options["verbose"], 1)
+        verbose_print("Creating and loading custom logging functionality", self.grid_options["verbosity"], 1)
         if self.grid_options["C_logging_code"]:
             # Generate entire shared lib code around logging lines
             custom_logging_code = binary_c_log_code(
                 self.grid_options["C_logging_code"],
-                verbose=self.grid_options["verbose"],
+                verbose=self.grid_options["verbosity"],
             )
 
             # Load memory adress
@@ -453,19 +452,19 @@ class Population:
                 self.grid_options["custom_logging_func_memaddr"],
                 self.grid_options["custom_logging_shared_library_file"],
             ) = create_and_load_logging_function(
-                custom_logging_code, verbose=self.grid_options["verbose"]
+                custom_logging_code, verbose=self.grid_options["verbosity"]
             )
 
         elif self.grid_options["C_auto_logging"]:
             # Generate real logging code
             logging_line = autogen_C_logging_code(
                 self.grid_options["C_auto_logging"],
-                verbose=self.grid_options["verbose"],
+                verbose=self.grid_options["verbosity"],
             )
 
             # Generate entire shared lib code around logging lines
             custom_logging_code = binary_c_log_code(
-                logging_line, verbose=self.grid_options["verbose"]
+                logging_line, verbose=self.grid_options["verbosity"]
             )
 
             # Load memory adress
@@ -473,7 +472,7 @@ class Population:
                 self.grid_options["custom_logging_func_memaddr"],
                 self.grid_options["custom_logging_shared_library_file"],
             ) = create_and_load_logging_function(
-                custom_logging_code, verbose=self.grid_options["verbose"]
+                custom_logging_code, verbose=self.grid_options["verbosity"]
             )
 
     ###################################################
@@ -484,8 +483,6 @@ class Population:
         """
         Function that loads a set amount (amt_cores) of persistent data memory adresses to
         pass to binary_c.
-
-        TODO: fix the function
         """
 
         for thread_nr in self.grid_options["amt_cores"]:
@@ -493,7 +490,7 @@ class Population:
             self.persistent_data_memory_dict[thread_nr] = persistent_data_memaddr
         verbose_print("Created the following dict with persistent memaddresses: {}".format(self.persistent_data_memory_dict), self.grid_options["verbosity"], 1)
 
-    def free_persistent_data_memory_and_combine_results(self):
+    def free_persistent_data_memory_and_combine_results_and_output(self):
         """
         Function that loads a set amount of persisten data memory adresses to
         pass to binary_c.
@@ -520,7 +517,9 @@ class Population:
         full_output_filename = os.path.join(self.custom_options["data_dir"], self.custom_options["ensemble_output_name"])
         verbose_print("Writing ensemble output to {}".format(full_output_filename), self.grid_options["verbosity"], 1)
 
-
+        # Output to dir:
+        with open(full_output_filename, 'w') as output_file:
+            output_file.write(json.dumps(combined_ensemble_json, indent=4))
 
     ###################################################
     # Evolution functions
@@ -528,7 +527,11 @@ class Population:
 
     def setup(self):
         """
-        Function to set up the necessary stuff for the population evolution:
+        Function to set up the necessary stuff for the population evolution.
+
+        The idea is to do all the stuff that is necessary for a population to run.
+        Since we have different methods of running a population, this setup function
+        will do different things depending on different settings
 
         # TODO: Make other kinds of populations possible. i.e, read out type of grid,
             and set up accordingly
@@ -548,6 +551,17 @@ class Population:
         ### Load store
         self.grid_options["store_memaddr"] = binary_c_python_api.return_store("")
 
+        ### ensemble:
+        ## Load persistent_data_memaddr if necessary:
+        if self.bse_options["ensemble"] == 1:
+            self.load_persistent_data_memory_dict()
+
+        ## check the settings:
+        if self.bse_options["ensemble"] == 1:
+            if not self.bse_options["ensemble_defer"] == 1:
+                verbose_print("Error, if you want to run an ensemble in a population, the output needs to be deferred", self.grid_options["verbosity"], 0)
+                raise ValueError
+
         #######################
         # Dry run and getting starcount
         self.grid_options["probtot"] = 0
@@ -557,10 +571,13 @@ class Population:
             print("Error: you havent defined any grid variables! Aborting")
             raise ValueError
 
+        # Set up the grid code with a dry run option to see total probability
         self.generate_grid_code(dry_run=True)
 
+        # Load the grid code
         self.load_grid_function()
 
+        # Do a dry run
         self.dry_run()
 
         print(
@@ -597,14 +614,22 @@ class Population:
         - unload dry grid function/module
         """
 
+        # Output the ensemble if necessary:
+        if self.bse_options["ensemble"] == 1:
+            self.free_persistent_data_memory_and_combine_results_and_output()
+
         # Reset values
         self.grid_options["count"] = 0
         self.grid_options["probtot"] = 0
         self.grid_options["system_generator"] = None
 
         # Remove files
+
         # Unload functions
 
+        # Unload store
+        binary_c_python_api.binary_c_free_store_memaddr(self.grid_options["store_memaddr"])
+
     def evolve_system_mp(self, binary_cmdline_string):
         """
         Function that the multiprocessing evolution method calls to evolve a system
@@ -652,7 +677,8 @@ class Population:
 
         # Get argument line
         argline = self.return_argline(self.bse_options)
-        print("Running {}".format(argline))
+        verbose_print("Running {}".format(argline), self.grid_options['verbosity'], 1)
+
         # Run system
         out = binary_c_python_api.run_system(
             argstring=argline,
@@ -768,40 +794,6 @@ class Population:
         # Clean up code: remove files, unset values.
         self.cleanup()
 
-    ###################################################
-    # Function to test evolution algorithms
-    ###################################################
-
-    def test_evolve_single(self):
-        """
-        Function to test the evolution of a system. Calls the api binding directly.
-        """
-
-        verbose_print("running a single system as a test", self.grid_options["verbose"], 1)
-
-        m_1 = 15.0  # Msun
-        m_2 = 14.0  # Msun
-        separation = 0  # 0 = ignored, use period
-        orbital_period = 4530.0  # days
-        eccentricity = 0.0
-        metallicity = 0.02
-        max_evolution_time = 15000
-        argstring = "binary_c M_1 {0:g} M_2 {1:g} separation {2:g} orbital_period {3:g}\
-        eccentricity {4:g} metallicity {5:g} max_evolution_time {6:g}".format(
-            m_1,
-            m_2,
-            separation,
-            orbital_period,
-            eccentricity,
-            metallicity,
-            max_evolution_time,
-        )
-
-        output = binary_c_python_api.run_system(argstring)
-
-        print("\n\nBinary_c output:")
-        print(output)
-
     ###################################################
     # Gridcode functions
     #
@@ -830,7 +822,7 @@ class Population:
         Results in a generated file that contains a system_generator function.
         """
 
-        verbose_print("Generating grid code", self.grid_options["verbose"], 1)
+        verbose_print("Generating grid code", self.grid_options["verbosity"], 1)
 
         # Some local values
         code_string = ""
@@ -1193,7 +1185,7 @@ class Population:
         # Stop of code generation. Here the code is saved and written
 
         # Save the gridcode to the grid_options
-        verbose_print("Saving grid code to grid_options", self.grid_options["verbose"], 1)
+        verbose_print("Saving grid code to grid_options", self.grid_options["verbosity"], 1)
 
         self.grid_options["code_string"] = code_string
 
@@ -1203,7 +1195,7 @@ class Population:
         )
         self.grid_options["gridcode_filename"] = gridcode_filename
 
-        verbose_print("Writing grid code to {}".format(gridcode_filename), self.grid_options["verbose"], 1)
+        verbose_print("Writing grid code to {}".format(gridcode_filename), self.grid_options["verbosity"], 1)
 
         with open(gridcode_filename, "w") as file:
             file.write(code_string)
@@ -1219,7 +1211,7 @@ class Population:
             message="Loading grid code function from {}".format(
                 self.grid_options["gridcode_filename"]
             ),
-            verbosity=self.grid_options["verbose"], minimal_verbosity=1)
+            verbosity=self.grid_options["verbosity"], minimal_verbosity=1)
 
         spec = importlib.util.spec_from_file_location(
             "binary_c_python_grid",
@@ -1231,7 +1223,7 @@ class Population:
 
         self.grid_options["system_generator"] = generator
 
-        verbose_print("Grid code loaded", self.grid_options["verbose"], 1)
+        verbose_print("Grid code loaded", self.grid_options["verbosity"], 1)
 
     def dry_run(self):
         """
@@ -1253,7 +1245,7 @@ class Population:
         """
 
         # Define frequency
-        if self.grid_options["verbose"] == 1:
+        if self.grid_options["verbosity"] == 1:
             print_freq = 1
         else:
             print_freq = 10
@@ -1394,7 +1386,7 @@ class Population:
         """
 
         if evol_type == "single":
-            verbose_print("Cleaning up the custom logging stuff. type: single", self.grid_options["verbose"], 1)
+            verbose_print("Cleaning up the custom logging stuff. type: single", self.grid_options["verbosity"], 1)
 
             # TODO: Unset custom logging code
 
@@ -1405,11 +1397,11 @@ class Population:
             if self.grid_options["custom_logging_shared_library_file"]:
                 remove_file(
                     self.grid_options["custom_logging_shared_library_file"],
-                    self.grid_options["verbose"],
+                    self.grid_options["verbosity"],
                 )
 
         if evol_type == "population":
-            verbose_print("Cleaning up the custom logging stuffs. type: population", self.grid_options["verbose"], 1)
+            verbose_print("Cleaning up the custom logging stuffs. type: population", self.grid_options["verbosity"], 1)
 
             # TODO: make sure that these also work. not fully sure if necessary tho.
             #   whether its a single file, or a dict of files/memaddresses
@@ -1444,7 +1436,7 @@ class Population:
 
         # Set up logger
         self.logger = logging.getLogger('binary_c_python_logger')
-        self.logger.setLevel(self.grid_options["verbose"])
+        self.logger.setLevel(self.grid_options["verbosity"])
 
         # Reset handlers
         self.logger.handlers = []
diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py
index 68eeef0f9c366141454efe8316ad4615fef4bc6b..bed3b9fabf5ef1a4e80d0a632bd2be389424bd63 100644
--- a/binarycpython/utils/grid_options_defaults.py
+++ b/binarycpython/utils/grid_options_defaults.py
@@ -19,7 +19,7 @@ grid_options_defaults_dict = {
     ##########################
     # Execution log:
     ##########################
-    "verbose": 0,  # Level of verbosity of the simulation. 0=INFO, 
+    "verbosity": 0,  # Level of verbosity of the simulation. 0=INFO, 
     "log_file": os.path.join(temp_dir(), 'binary_c_python.log'), # Set to None to not log to file. The directory will be created
     ##########################
     # binary_c files