docs: def simulate(self, timepoints):
          """
          Simulate initialised solver for the specified timepoints
  
          :param timepoints: timepoints that will be returned from simulation
          :return: a list of trajectories for each of the equations in the problem.
          """
          solver = self._solver
          last_timepoint = timepoints[-1]
          try:
              simulated_timepoints, simulated_values = solver.simulate(last_timepoint, ncp_list=timepoints)
  
          except (Exception, self._solver_exception_class) as e:
              # The exceptions thrown by solvers are usually hiding the real cause, try to see if it is
              # our right_hand_side_as_function that is broken first
              try:
                  self._problem.right_hand_side_as_function(self._initial_conditions, self._parameters)
              except:
                  # If it is broken, throw that exception instead
                  raise
              else:
                  # If it is not, handle the original exception
                  self._handle_solver_exception(e)
  
          trajectories =  self._results_to_trajectories(simulated_timepoints, simulated_values)
  
          return trajectories