def METHOD_NAME(self,
                       pos,
                       vel,
                       other_feats,
                       box,
                       box_feats,
                       fixed_radius_search_hash_table=None):
    """Expects that the pos and vel has already been updated with gravity and velocity"""
    # compute the extent of the filters (the diameter)
    filter_extent = tf.constant(self.filter_extent)
    fluid_feats = [tf.ones_like(pos[:, 0:1]), vel]
    if not other_feats is None:
        fluid_feats.append(other_feats)
    fluid_feats = tf.concat(fluid_feats, axis=-1)
    self.ans_conv0_fluid = self.conv0_fluid(fluid_feats, pos, pos,
                                            filter_extent)
    self.ans_dense0_fluid = self.dense0_fluid(fluid_feats)
    self.ans_conv0_obstacle = self.conv0_obstacle(box_feats, box, pos,
                                                  filter_extent)
    feats = tf.concat([
        self.ans_conv0_obstacle, self.ans_conv0_fluid, self.ans_dense0_fluid
    ],
                      axis=-1)
    self.ans_convs = [feats]
    for conv, dense in zip(self.convs, self.denses):
        inp_feats = tf.keras.activations.relu(self.ans_convs[-1])
        ans_conv = conv(inp_feats, pos, pos, filter_extent)
        ans_dense = dense(inp_feats)
        if ans_dense.shape[-1] == self.ans_convs[-1].shape[-1]:
            ans = ans_conv + ans_dense + self.ans_convs[-1]
        else:
            ans = ans_conv + ans_dense
        self.ans_convs.append(ans)
    # compute the number of fluid neighbors.
    # this info is used in the loss function during training.
    self.num_fluid_neighbors = ml3d.ops.reduce_subarrays_sum(
        tf.ones_like(self.conv0_fluid.nns.neighbors_index,
                     dtype=tf.float32),
        self.conv0_fluid.nns.neighbors_row_splits)
    self.last_features = self.ans_convs[-2]
    # scale to better match the scale of the output distribution
    self.pos_correction = (1.0 / 128) * self.ans_convs[-1]
    return self.pos_correction