docs: def start(self, model, progress_hook=None):
          """
          Start the simulation from time zero.
  
          :param model: Model with layers and registries containing parameters
          :type: :class:`~simkit.core.models.Model`
          :param progress_hook: A function that receives either a string or a
              list containing the index followed by tuples of the data or outputs
              names and values specified by ``write_fields`` in the simfile.
          :type progress_hook: function
  
  
          The model registries should contain the following layer registries:
          * :class:`~simkit.core.data_sources.DataRegistry`,
          * :class:`~simkit.core.formulas.FormulaRegistry`,
          * :class:`~simkit.core.outputs.OutputRegistry`,
          * :class:`~simkit.core.calculation.CalcRegistry`
          """
          # check if data loaded
          data_objs = self.check_data(model.data)
          if not self.is_data_loaded:
              raise MissingDataError([ds for ds in data_objs if ds is None])
          # get layer registries
          data_reg = model.registries['data']
          formula_reg = model.registries['formulas']
          out_reg = model.registries['outputs']
          calc_reg = model.registries['calculations']
          # initialize
          if not self.isinitialized:
              self.initialize(calc_reg)
          # default progress hook
          if not progress_hook:
              progress_hook = functools.partial(
                  sim_progress_hook, display_header=True
              )
          # start, resume or restart
          if self.ispaused:
              # if paused, then resume, do not resize outputs again.
              self._ispaused = False  # change pause state
              progress_hook('resume simulation')
          elif self.iscomplete:
              # if complete, then restart, do not resize outputs again.
              self._iscomplete = False  # change pause state
              progress_hook('restart simulation')
              self.idx_iter = self.index_iterator()
          else:
              # resize outputs
              # assumes that self.write_frequency is immutable
              # TODO: allow self.write_frequency to be changed
              # only resize outputs first time simulation is started
              # repeat output rows to self.write_frequency
              # put initial conditions of outputs last so it's copied when
              # idx == 0
              progress_hook('resize outputs')  # display progress
              for k in out_reg:
                  if out_reg.isconstant[k]:
                      continue
                  # repeat rows (axis=0)
                  out_reg[k] = out_reg[k].repeat(self.write_frequency, 0)
                  _initial_value = out_reg.initial_value[k]
                  if not _initial_value:
                      continue
                  if isinstance(_initial_value, basestring):
                      # initial value is from data registry
                      # assign in a scalar to a vector fills in the vector, yes!
                      out_reg[k][-1] = data_reg[_initial_value]
                  else:
                      out_reg[k][-1] = _initial_value * out_reg[k].units
              progress_hook('start simulation')
          # check and/or make SimKit_Simulations and simulation ID folders
          mkdir_p(self.path)
          sim_id_path = os.path.join(self.path, self.ID)
          mkdir_p(sim_id_path)
          # header & units for save files
          data_fields = self.write_fields.get('data', [])  # any data fields
          out_fields = self.write_fields.get('outputs', [])  # any outputs fields
          save_header = tuple(data_fields + out_fields)  # concatenate fields
          # get units as strings from data & outputs
          data_units = [str(data_reg[f].dimensionality) for f in data_fields]
          out_units = [str(out_reg[f].dimensionality) for f in out_fields]
          save_units = tuple(data_units + out_units)  # concatenate units
          # string format for header & units
          save_str = ('%s' + ',%s' * (len(save_header) - 1)) + '\n'  # format
          save_header = (save_str * 2) % (save_header + save_units)  # header
          save_header = save_header[:-1]  # remove trailing new line
          # ===================
          # Static calculations
          # ===================
          progress_hook('static calcs')
          for calc in self.calc_order:
              if not calc_reg.is_dynamic[calc]:
                  calc_reg.calculator[calc].calculate(
                      calc_reg[calc], formula_reg, data_reg, out_reg
                  )
          # ====================
          # Dynamic calculations
          # ====================
          progress_hook('dynamic calcs')
          # TODO: assumes that interval size and indices are same, but should
          # interpolate for any size interval or indices
          for idx_tot in self.idx_iter:
              self.interval_idx = idx_tot  # update simulation interval counter
              idx = idx_tot % self.write_frequency
              # update properties
              for k, v in out_reg.isproperty.iteritems():
                  # set properties from previous interval at night
                  if v:
                      out_reg[k][idx] = out_reg[k][idx - 1]
              # night if any threshold exceeded
              if self.thresholds:
                  night = not all(limits[0] < data_reg[data][idx] < limits[1] for
                                  data, limits in self.thresholds.iteritems())
              else:
                  night = None
              # daytime or always calculated outputs
              for calc in self.calc_order:
                  # Determine if calculation is scheduled for this timestep
                  # TODO: add ``start_at`` parameter combined with ``frequency``
                  freq = calc_reg.frequency[calc]
                  if not freq.dimensionality:
                      is_scheduled = (idx_tot % freq) == 0
                  else:
                      # Frequency with units of time
                      is_scheduled = ((idx_tot * self.interval) % freq) == 0
                  is_scheduled = (
                      is_scheduled and (not night or calc_reg.always_calc[calc])
                  )
                  if calc_reg.is_dynamic[calc] and is_scheduled:
                      calc_reg.calculator[calc].calculate(
                          calc_reg[calc], formula_reg, data_reg, out_reg,
                          timestep=self.interval, idx=idx
                      )
              # display progress
              if not (idx % self.display_frequency):
                  progress_hook(self.format_progress(idx, data_reg, out_reg))
                  # disp_head = False
              # create an index for the save file, 0 if not saving
              if not ((idx_tot + 1) % self.write_frequency):
                  savenum = (idx_tot + 1) / self.write_frequency
              elif idx_tot == self.number_intervals - 1:
                  # save file index should be integer!
                  savenum = int(np.ceil((idx_tot + 1) /
                                        float(self.write_frequency)))
              else:
                  savenum = 0  # not saving this iteration
              # save file to disk
              if savenum:
                  savename = self.ID + '_' + str(savenum) + '.csv'  # filename
                  savepath = os.path.join(sim_id_path, savename)  # path
                  # create array of all data & outputs to save
                  save_array = self.format_write(data_reg, out_reg, idx + 1)
                  # save as csv using default format & turn comments off
                  np.savetxt(savepath, save_array, delimiter=',',
                             header=save_header, comments='')
              try:
                  cmd = self.cmd_queue.get_nowait()
              except Queue.Empty:
                  continue
              if cmd == 'pause':
                  self._ispaused = True
                  return
          self._iscomplete = True