class_docstr: Subclass of RectPartitioner2D, which uses 0MQ via pyzmq for communication
  The first two arguments must be `comm`, an EngineCommunicator object,
  and `addrs`, a dict of connection information for other EngineCommunicator
  objects.
docstr: update the inner boundary, sending first, then receiving
docstr_tok: ["update","the","inner","boundary",",","sending","first",",","then","receiving"]
code: def update_internal_boundary_send_recv(self, solution_array):
      """update the inner boundary, sending first, then receiving"""
      nsd_ = self.nsd
      dtype = solution_array.dtype
      if (
          nsd_
          != len(self.in_lower_buffers) | nsd_
          != len(self.out_lower_buffers)
      ):
          print(
              "Buffers for communicating with lower neighbors not ready"
          )
          return
      if (
          nsd_
          != len(self.in_upper_buffers) | nsd_
          != len(self.out_upper_buffers)
      ):
          print(
              "Buffers for communicating with upper neighbors not ready"
          )
          return
  
      loc_nx = self.subd_hi_ix[0] - self.subd_lo_ix[0]
      loc_ny = self.subd_hi_ix[1] - self.subd_lo_ix[1]
  
      lower_x_neigh = self.lower_neighbors[0]
      upper_x_neigh = self.upper_neighbors[0]
      lower_y_neigh = self.lower_neighbors[1]
      upper_y_neigh = self.upper_neighbors[1]
      trackers = []
      flags = dict(copy=False, track=False)
  
      # send in all directions first
      if lower_x_neigh > -1:
          if self.slice_copy:
              self.out_lower_buffers[0] = ascontiguousarray(
                  solution_array[1, :]
              )
          else:
              for i in range(0, loc_ny + 1):
                  self.out_lower_buffers[0][i] = solution_array[1, i]
          t = self.comm.west.send(self.out_lower_buffers[0], **flags)
          trackers.append(t)
  
      if lower_y_neigh > -1:
          if self.slice_copy:
              self.out_lower_buffers[1] = ascontiguousarray(
                  solution_array[:, 1]
              )
          else:
              for i in range(0, loc_nx + 1):
                  self.out_lower_buffers[1][i] = solution_array[i, 1]
          t = self.comm.south.send(self.out_lower_buffers[1], **flags)
          trackers.append(t)
  
      if upper_x_neigh > -1:
          if self.slice_copy:
              self.out_upper_buffers[0] = ascontiguousarray(
                  solution_array[loc_nx - 1, :]
              )
          else:
              for i in range(0, loc_ny + 1):
                  self.out_upper_buffers[0][i] = solution_array[
                      loc_nx - 1, i
                  ]
          t = self.comm.east.send(self.out_upper_buffers[0], **flags)
          trackers.append(t)
  
      if upper_y_neigh > -1:
          if self.slice_copy:
              self.out_upper_buffers[1] = ascontiguousarray(
                  solution_array[:, loc_ny - 1]
              )
          else:
              for i in range(0, loc_nx + 1):
                  self.out_upper_buffers[1][i] = solution_array[
                      i, loc_ny - 1
                  ]
          t = self.comm.north.send(self.out_upper_buffers[1], **flags)
          trackers.append(t)
  
      # now start receiving
      if upper_x_neigh > -1:
          msg = self.comm.east.recv(copy=False)
          self.in_upper_buffers[0] = frombuffer(msg, dtype=dtype)
          if self.slice_copy:
              solution_array[loc_nx, :] = self.in_upper_buffers[0]
          else:
              for i in range(0, loc_ny + 1):
                  solution_array[loc_nx, i] = self.in_upper_buffers[0][
                      i
                  ]
  
      if lower_x_neigh > -1:
          msg = self.comm.west.recv(copy=False)
          self.in_lower_buffers[0] = frombuffer(msg, dtype=dtype)
          if self.slice_copy:
              solution_array[0, :] = self.in_lower_buffers[0]
          else:
              for i in range(0, loc_ny + 1):
                  solution_array[0, i] = self.in_lower_buffers[0][i]
  
      if upper_y_neigh > -1:
          msg = self.comm.north.recv(copy=False)
          self.in_upper_buffers[1] = frombuffer(msg, dtype=dtype)
          if self.slice_copy:
              solution_array[:, loc_ny] = self.in_upper_buffers[1]
          else:
              for i in range(0, loc_nx + 1):
                  solution_array[i, loc_ny] = self.in_upper_buffers[1][
                      i
                  ]
  
      if lower_y_neigh > -1:
          msg = self.comm.south.recv(copy=False)
          self.in_lower_buffers[1] = frombuffer(msg, dtype=dtype)
          if self.slice_copy:
              solution_array[:, 0] = self.in_lower_buffers[1]
          else:
              for i in range(0, loc_nx + 1):
                  solution_array[i, 0] = self.in_lower_buffers[1][i]
  
      # wait for sends to complete:
      if flags["track"]:
          for t in trackers:
              t.wait()
  
imports: from numpy import ascontiguousarray, frombuffer, zeros
label_desc: Use image node_id 4 for calling the ZMQRectPartitioner2D obj's underlying member method code with example usage: obj.update_internal_boundary_send_recv(solution_array) without return types