def run(params):
    controller.clear()

    topo = params['topology']
    geo = params['geometry']
    phs = params['phase']
    phys = params['physics']

    network = Cubic(shape=list(topo.dimensions.data.values()),
                    connectivity=topo.connectivity.data)

    geometry = GenericGeometry(network=network,
                               pores=network.pores(),
                               throats=network.throats())
    geometry.add_model(geometry=geometry, **_pore_seed_model(geo))
    geometry.add_model(geometry=geometry, **_pore_diameter_model())
    geometry.add_model(geometry=geometry, **_pore_volume_model())
    geometry.add_model(geometry=geometry, **_throat_seed_model(geo))
    geometry.add_model(geometry=geometry, **_throat_diameter_model())
    geometry.add_model(geometry=geometry, **_throat_length_model())
    geometry.add_model(geometry=geometry, **_throat_volume_model())

    invading_phase = GenericPhase(network=network, name='invading')
    invading_phase['pore.contact_angle'] = phs.contact_angle.data
    invading_phase['pore.surface_tension'] = phs.surface_tension.data

    invading_physics = GenericPhysics(network=network,
                                      phase=invading_phase,
                                      geometry=geometry)

    invading_physics.add_model(**_capillary_pressure_model(phys))

    algorithm = OrdinaryPercolation(network=network, invading_phase=invading_phase)
    algorithm.run(inlets=network.pores('top'))

    return {
        'invasionPressure': _transform_data(algorithm).tolist(),
        'poreDiameter': geometry['pore.diameter'].tolist(),
        'throatDiameter': geometry['throat.diameter'].tolist(),
        'throatLength': geometry['throat.length'].tolist()
    }
  def run(self):
    super().run()
    network = Cubic(shape=[self.topo.height,
                           self.topo.width,
                           self.topo.depth],
                    connectivity=self.topo.connectivity)

    geometry = GenericGeometry(network=network,
                               pores=network.pores(),
                               throats=network.throats())
    geometry.add_model(geometry=geometry, **self._pore_seed_model())
    geometry.add_model(geometry=geometry, **self._pore_diameter_model())
    geometry.add_model(geometry=geometry, **self._pore_volume_model())
    geometry.add_model(geometry=geometry, **self._throat_seed_model())
    geometry.add_model(geometry=geometry, **self._throat_diameter_model())
    geometry.add_model(geometry=geometry, **self._throat_length_model())
    geometry.add_model(geometry=geometry, **self._throat_volume_model())

    invading_phase = GenericPhase(network=network, name='invading')
    defending_phase = GenericPhase(network=network, name='defending')

    if self.phs.type == 'custom':
      invading_phase['pore.contact_angle'] = self.phs.contactAngle
      invading_phase['pore.surface_tension'] = self.phs.surfaceTension
      defending_phase['pore.contact_angle'] = self.phs.contactAngle
      defending_phase['pore.surface_tension'] = self.phs.surfaceTension

    invading_physics = GenericPhysics(network=network,
                                      phase=invading_phase,
                                      geometry=geometry)
    defending_physics = GenericPhysics(network=network,
                                       phase=defending_phase,
                                       geometry=geometry)

    invading_physics.add_model(**self._capillary_pressure_model())
    defending_physics.add_model(**self._capillary_pressure_model())

    algorithm = OP(network=network,
                   invading_phase=invading_phase,
                   defending_phase=defending_phase)

    algorithm.run(inlets=network.pores('top'))

    return {
      'invasion_pressures': self._transform_data(algorithm).tolist(),
      'pore_volumes': geometry['pore.volume'].tolist()
    }