Skip to content
scalability.py 4.97 KiB
Newer Older
import pyopencl as cl
from sympy.core.cache import clear_cache
import numpy as np
from meshmode.discretization import Discretization
from pytential import bind, sym, norm
from sumpy.kernel import LaplaceKernel
from pytential.qbx import QBXLayerPotentialSource
from pytential.qbx.distributed import DistributedQBXLayerPotentialSource
from mpi4py import MPI
import logging
import os
import warnings
Hao Gao's avatar
Hao Gao committed
import functools

# Configure logging
logging.basicConfig(level=os.environ.get("LOGLEVEL", "WARNING"))
logging.getLogger("pytential.qbx.distributed").setLevel(logging.INFO)

warnings.filterwarnings("ignore", category=UserWarning)

# Disable sympy cache
clear_cache()

# Setup PyOpenCL
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)


class GreenExpr(object):
    zero_op_name = "green"

    def get_zero_op(self, kernel, **knl_kwargs):

        u_sym = sym.var("u")
        dn_u_sym = sym.var("dn_u")

        return (
            sym.S(kernel, dn_u_sym, qbx_forced_limit=-1, **knl_kwargs)
            - sym.D(kernel, u_sym, qbx_forced_limit="avg", **knl_kwargs)
            - 0.5*u_sym)

    order_drop = 0

def get_sphere_mesh(refinement_increment, target_order):
    from meshmode.mesh.generation import generate_icosphere
    mesh = generate_icosphere(1, target_order)
    from meshmode.mesh.refinement import Refiner

    refiner = Refiner(mesh)
    for i in range(refinement_increment):
        flags = np.ones(mesh.nelements, dtype=bool)
        refiner.refine(flags)
        mesh = refiner.get_current_mesh()

    return mesh

# Parameters
k = 0
qbx_order = 3
fmm_order = 10
_expansion_stick_out_factor = 0.5

expr = GreenExpr()

def generate_expr(refinement_increment, target_order, lp_source_contructor):
    mesh = get_sphere_mesh(refinement_increment, target_order)
    d = mesh.ambient_dim
    
    lap_k_sym = LaplaceKernel(d)
    k_sym = lap_k_sym
    knl_kwargs = {}

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
        InterpolatoryQuadratureSimplexGroupFactory
    
    pre_density_discr = Discretization(
        ctx, mesh,
        InterpolatoryQuadratureSimplexGroupFactory(target_order))

    refiner_extra_kwargs = {}

    qbx, _ = lp_source_contructor(
        pre_density_discr, 4 * target_order,
        qbx_order,
        fmm_order=fmm_order,
        _expansions_in_tree_have_extent=True,
        _expansion_stick_out_factor=_expansion_stick_out_factor
    ).with_refinement(**refiner_extra_kwargs)

    density_discr = qbx.density_discr

    # {{{ compute values of a solution to the PDE

    nodes_host = density_discr.nodes().get(queue)
    normal = bind(density_discr, sym.normal(d))(queue).as_vector(np.object)
    normal_host = [normal[j].get() for j in range(d)]

    center = np.array([3, 1, 2])[:d]
    diff = nodes_host - center[:, np.newaxis]
    dist_squared = np.sum(diff ** 2, axis=0)
    dist = np.sqrt(dist_squared)
    if d == 2:
        u = np.log(dist)
        grad_u = diff / dist_squared
    elif d == 3:
        u = 1 / dist
        grad_u = -diff / dist ** 3
    else:
        assert False

    dn_u = 0
    for i in range(d):
        dn_u = dn_u + normal_host[i] * grad_u[i]

    # }}}

    u_dev = cl.array.to_device(queue, u)
    dn_u_dev = cl.array.to_device(queue, dn_u)
    grad_u_dev = cl.array.to_device(queue, grad_u)

    bound_op = bind(qbx, expr.get_zero_op(k_sym, **knl_kwargs))

    return bound_op, {'u': u_dev, 'dn_u': dn_u_dev, 'grad_u': grad_u_dev, 'k': k}

def train():
    from pytential.qbx.perf_model import QBXPerformanceModel
    model = QBXPerformanceModel(ctx, True)

    model.loadjson('model.json')

    training_cases = [
        (0, 6),
        (0, 6),
        (0, 8),
        (1, 8),
        (1, 10),
        (1, 10)
    ]

Hao Gao's avatar
Hao Gao committed
    lp_source_contructor = functools.partial(QBXLayerPotentialSource, fmm_backend='fmmlib')

    for refinement_increment, target_order in training_cases:
Hao Gao's avatar
Hao Gao committed
        expr, context = generate_expr(refinement_increment, target_order, lp_source_contructor)
        model.time_qbx_performance(queue, expr, context)

    model.savejson('model.json')

def eval():
    # MPI information
    comm = MPI.COMM_WORLD
    current_rank = comm.Get_rank()

    if current_rank == 0:
        lp_source_contructor = functools.partial(DistributedQBXLayerPotentialSource, comm)

        bound_op, context = generate_expr(3, 10, lp_source_contructor)
        bound_op.eval(queue, context=context)
    else:
        lp_source = DistributedQBXLayerPotentialSource(comm, None, None)
        distribute_geo_data = lp_source.distibuted_geo_data(None, queue, None)

        from pytential.qbx.distributed import drive_dfmm
        weights = None
        drive_dfmm(queue, weights, distribute_geo_data, comm=comm)


if __name__ == '__main__':
    import sys
    if len(sys.argv) != 2:
        raise RuntimeError("Please specify train or eval")

    if sys.argv[1] == 'train':
        train()
    elif sys.argv[1] == 'eval':
        eval()
    else:
        raise RuntimeError("Unrecognized command line argument. Please specify train or eval.")