示例#1
0
class LinceseSolver(CeseSolver):
    """
    Basic linear CESE solver.

    @ivar cfldt: the time_increment for CFL calculation at boundcond.
    @itype cfldt: float
    @ivar cflmax: the maximum CFL number.
    @itype cflmax: float
    """
    from solvcon.dependency import getcdll
    __clib_lincese = {
        2: getcdll('lincese2d', raise_on_fail=False),
        3: getcdll('lincese3d', raise_on_fail=False),
    }
    del getcdll

    @property
    def _clib_lincese(self):
        return self.__clib_lincese[self.ndim]

    @property
    def _jacofunc_(self):
        return self._clib_lincese.calc_jaco

    def __init__(self, *args, **kw):
        self.cfldt = kw.pop('cfldt', None)
        self.cflmax = 0.0
        super(LinceseSolver, self).__init__(*args, **kw)

    def make_grpda(self):
        raise NotImplementedError

    def provide(self):
        from ctypes import byref, c_int
        # fill group data array.
        self.make_grpda()
        # pre-calculate CFL.
        self._set_time(self.time, self.cfldt)
        self._clib_lincese.calc_cfl(byref(self.exd), c_int(0),
                                    c_int(self.ncell))
        self.cflmax = self.cfl.max()
        # super method.
        super(LinceseSolver, self).provide()

    def calccfl(self, worker=None):
        self.marchret.setdefault('cfl', [0.0, 0.0, 0, 0])
        self.marchret['cfl'][0] = self.cflmax
        self.marchret['cfl'][1] = self.cflmax
        self.marchret['cfl'][2] = 0
        self.marchret['cfl'][3] = 0
        return self.marchret
示例#2
0
class EulerBC(CeseBC):
    """
    Basic BC class for the Euler equations.
    """
    from solvcon.dependency import getcdll
    __clib_eulerb = {
        2: getcdll('eulerb2d', raise_on_fail=False),
        3: getcdll('eulerb3d', raise_on_fail=False),
    }
    del getcdll

    @property
    def _clib_eulerb(self):
        return self.__clib_eulerb[self.svr.ndim]
示例#3
0
class ElaslinBC(CeseBC):
    """
    Basic BC class for elastic problems.
    """
    from solvcon.dependency import getcdll
    __clib_elaslinb = {
        2: getcdll('elaslinb2d', raise_on_fail=False),
        3: getcdll('elaslinb3d', raise_on_fail=False),
    }
    del getcdll

    @property
    def _clib_elaslinb(self):
        return self.__clib_elaslinb[self.svr.ndim]
示例#4
0
class NSBulkSolver(CuseSolver):
    """
    Navier-Stokes solver based on the Bulk modulus.
    """
    def __init__(self, blk, *args, **kw):
        kw['nsca'] = 12
        super(NSBulkSolver, self).__init__(blk, *args, **kw)

    from solvcon.dependency import getcdll
    __clib_nsbulk_c = {
        2: getcdll('nsbulk2d'),
        3: getcdll('nsbulk3d'),
    }
    __clib_nsbulk_cu = {
        2: getcdll('nsbulk2d_cu', raise_on_fail=False),
        3: getcdll('nsbulk3d_cu', raise_on_fail=False),
    }
    del getcdll

    @property
    def _clib_nsbulk_c(self):
        return self.__clib_nsbulk_c[self.ndim]

    @property
    def _clib_nsbulk_cu(self):
        return self.__clib_nsbulk_cu[self.ndim]

    @property
    def _clib_mcu(self):
        return self.__clib_nsbulk_cu[self.ndim]

    _gdlen_ = 0

    @property
    def _jacofunc_(self):
        return self._clib_nsbulk_c.calc_jaco

    @property
    def _viscfunc_(self):
        return self._clib_nsbulk_c.calc_viscous

    def calccfl(self, worker=None):
        from ctypes import byref
        if self.scu:
            self._clib_nsbulk_cu.calc_cfl(self.ncuth, byref(self.cumgr.exd),
                                          self.cumgr.gexd.gptr)
        else:
            self._clib_nsbulk_c.calc_cfl(byref(self.exd))
示例#5
0
class LincuseSolver(CuseSolver):
    """
    Basic linear CESE solver.

    @ivar cfldt: the time_increment for CFL calculation at boundcond.
    @itype cfldt: float
    @ivar cflmax: the maximum CFL number.
    @itype cflmax: float
    """
    from solvcon.dependency import getcdll
    __clib_lincuse_c = {
        2: getcdll('lincuse2d_c', raise_on_fail=False),
        3: getcdll('lincuse3d_c', raise_on_fail=False),
    }
    __clib_lincuse_cu = {
        2: getcdll('lincuse2d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
        3: getcdll('lincuse3d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
    }
    del getcdll
    @property
    def _clib_lincuse_c(self):
        return self.__clib_lincuse_c[self.ndim]
    @property
    def _clib_lincuse_cu(self):
        return self.__clib_lincuse_cu[self.ndim]
    @property
    def _jacofunc_(self):
        return self._clib_lincuse_c.calc_jaco
    def __init__(self, *args, **kw):
        self.cfldt = kw.pop('cfldt', None)
        self.cflmax = 0.0
        super(LincuseSolver, self).__init__(*args, **kw)
    def make_grpda(self):
        raise NotImplementedError
    def provide(self):
        from ctypes import byref, c_int
        # fill group data array.
        self.make_grpda()
        # pre-calculate CFL.
        self._set_time(self.time, self.cfldt)
        self._clib_lincuse_c.calc_cfl(
            byref(self.exd), c_int(0), c_int(self.ncell))
        self.ocfl[:] = self.cfl[:]
        # super method.
        super(LincuseSolver, self).provide()
    def calccfl(self, worker=None):
        pass
示例#6
0
class GasdynSolver(CuseSolver):
    """
    Gas dynamics solver of the Euler equations.
    """
    def __init__(self, blk, *args, **kw):
        kw['nsca'] = 1
        super(GasdynSolver, self).__init__(blk, *args, **kw)

    from solvcon.dependency import getcdll
    __clib_gasdyn_c = {
        2: getcdll('gasdyn2d_c', raise_on_fail=False),
        3: getcdll('gasdyn3d_c', raise_on_fail=False),
    }
    __clib_gasdyn_cu = {
        2: getcdll('gasdyn2d_cu', raise_on_fail=False),
        3: getcdll('gasdyn3d_cu', raise_on_fail=False),
    }
    del getcdll

    @property
    def _clib_gasdyn_c(self):
        return self.__clib_gasdyn_c[self.ndim]

    @property
    def _clib_gasdyn_cu(self):
        return self.__clib_gasdyn_cu[self.ndim]

    @property
    def _clib_mcu(self):
        return self.__clib_gasdyn_cu[self.ndim]

    _gdlen_ = 0

    @property
    def _jacofunc_(self):
        return self._clib_gasdyn_c.calc_jaco

    def calccfl(self, worker=None):
        from ctypes import byref
        if self.scu:
            self._clib_gasdyn_cu.calc_cfl(self.ncuth, byref(self.cumgr.exd),
                                          self.cumgr.gexd.gptr)
        else:
            self._clib_gasdyn_c.calc_cfl(byref(self.exd))
示例#7
0
class NSBulkBC(CuseBC):
    """
    Basic BC class for NS.
    """
    from solvcon.dependency import getcdll
    __clib_nsbulkb_c = {
        2: getcdll('nsbulkb2d'),
        3: getcdll('nsbulkb3d'),
    }
    __clib_nsbulkb_cu = {
        2: getcdll('nsbulkb2d_cu', raise_on_fail=False),
        3: getcdll('nsbulkb3d_cu', raise_on_fail=False),
    }
    del getcdll
    @property
    def _clib_nsbulkb_c(self):
        return self.__clib_nsbulkb_c[self.svr.ndim]
    @property
    def _clib_nsbulkb_cu(self):
        return self.__clib_nsbulkb_cu[self.svr.ndim]
示例#8
0
class EulerSolver(CeseSolver):
    """
    Inviscid aerodynamic solver for the Euler equations.
    """
    def __init__(self, blk, *args, **kw):
        self.cflname = kw.pop('cflname', 'adj')
        kw['nsca'] = 1
        super(EulerSolver, self).__init__(blk, *args, **kw)
        self.cflc = self.cfl.copy()  # FIXME: obselete?

    from solvcon.dependency import getcdll
    __clib_euler = {
        2: getcdll('euler2d', raise_on_fail=False),
        3: getcdll('euler3d', raise_on_fail=False),
    }
    del getcdll

    @property
    def _clib_euler(self):
        return self.__clib_euler[self.ndim]

    _gdlen_ = 0

    @property
    def _jacofunc_(self):
        return self._clib_euler.calc_jaco

    def calccfl(self, worker=None):
        func = getattr(self._clib_euler, 'calc_cfl_' + self.cflname)
        self._tcall(func, 0, self.ncell)
        mincfl = self.ocfl.min()
        maxcfl = self.ocfl.max()
        nadj = (self.cfl == 1).sum()
        self.marchret.setdefault('cfl', [0.0, 0.0, 0, 0])
        self.marchret['cfl'][0] = mincfl
        self.marchret['cfl'][1] = maxcfl
        self.marchret['cfl'][2] = nadj
        self.marchret['cfl'][3] += nadj
        return self.marchret
示例#9
0
class GasdynBC(CuseBC):
    """
    Basic BC class for gas dynamics.
    """
    from solvcon.dependency import getcdll
    __clib_gasdynb_c = {
        2: getcdll('gasdynb2d_c', raise_on_fail=False),
        3: getcdll('gasdynb3d_c', raise_on_fail=False),
    }
    __clib_gasdynb_cu = {
        2: getcdll('gasdynb2d_cu', raise_on_fail=False),
        3: getcdll('gasdynb3d_cu', raise_on_fail=False),
    }
    del getcdll

    @property
    def _clib_gasdynb_c(self):
        return self.__clib_gasdynb_c[self.svr.ndim]

    @property
    def _clib_gasdynb_cu(self):
        return self.__clib_gasdynb_cu[self.svr.ndim]
示例#10
0
class VslinBC(CuseBC):
    """
    Basic BC class for elastic problems.
    """
    from solvcon.dependency import getcdll
    __clib_vslinb_c = {
        2: getcdll('vslinb2d_c', raise_on_fail=False),
        3: getcdll('vslinb3d_c', raise_on_fail=False),
    }
    __clib_vslinb_cu = {
        2: getcdll('vslinb2d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
        3: getcdll('vslinb3d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
    }
    del getcdll

    @property
    def _clib_vslinb_c(self):
        return self.__clib_vslinb_c[self.svr.ndim]

    @property
    def _clib_vslinb_cu(self):
        return self.__clib_vslinb_cu[self.svr.ndim]
示例#11
0
class CeseBC(BC):
    """
    Base class for all BC types for CESE method, except periodic BC.

    @cvar _ghostgeom_: selector for the ghost geometry caculator.
    @ctype _ghostgeom_: str
    """
    from solvcon.dependency import getcdll
    __clib_ceseb = {
        2: getcdll('ceseb2d', raise_on_fail=False),
        3: getcdll('ceseb3d', raise_on_fail=False),
    }
    del getcdll
    @property
    def _clib_ceseb(self):
        return self.__clib_ceseb[self.svr.ndim]

    _ghostgeom_ = None
    def init(self, **kw):
        from ctypes import byref, c_int
        super(CeseBC, self).init(**kw)
        getattr(self._clib_ceseb, 'ghostgeom_'+self._ghostgeom_)(
            byref(self.svr.exd),
            c_int(self.facn.shape[0]),
            self.facn.ctypes._as_parameter_,
        )
    def soln(self):
        """
        Update ghost cells after marchsol.
        """
        pass
    def dsoln(self):
        """
        Update ghost cells after marchdsol.
        """
        pass
示例#12
0
class CeseSolver(BlockSolver):
    """
    The base solver class for multi-dimensional CESE code.

    @cvar _gdlen_: length per group data.  Must be overridden.
    @ctype _gdlen_: int
    @cvar _jacofunc_: ctypes function to Jacobian calculator.  Must be
        overridden.
    @ctype _jacofunc_: ctypes.FuncPtr

    @ivar debug: flag for debugging.
    @itype debug: bool

    @ivar diffname: name of gradient calculation function; tau is default,
        omega is selectable.
    @itype diffname: str
    @ivar tauname: name of tau function; default linear.
    @itype tauname: str
    @ivar omeganame: name of omega function; default scale.
    @itype omeganame: str
    @ivar alpha: parameter to the weighting function.
    @itype alpha: int
    @ivar taylor: factor for Taylor's expansion; 0 off, 1 on.
    @itype taylor: float
    @ivar cnbfac: factor to use BCE centroid, othersize midpoint; 0 off, 1 on.
    @itype cnbfac: float
    @ivar sftfac: factor to shift gradient shape; 0 off, 1 on.
    @itype sftfac: float
    @ivar taumin: the lower bound of tau.
    @itype taumin: float
    @ivar taumax: the upper bound of tau.
    @itype taumax: float
    @ivar tauscale: scaling of tau.
    @itype tauscale: float
    @ivar omegamin: the lower bound of omega.
    @itype omegamin: float
    @ivar omegascale: scaling of omega.
    @itype omegascale: float

    @ivar grpda: group data.
    @ivar cecnd: solution points for CCEs and BCEs.
    @ivar cevol: CCE and BCE volumes.
    @ivar solt: temporal diffrentiation of solution.
    @ivar sol: current solution.
    @ivar soln: next solution.
    @ivar dsol: current gradient of solution.
    @ivar dsoln: next gradient of solution.
    @ivar cfl: CFL number.
    @ivar ocfl: original CFL number.
    @ivar amsca: Parameter scalar array.
    @ivar amvec: Parameter vector array.
    """

    _exedatatype_ = CeseSolverExedata
    _interface_init_ = ['cecnd', 'cevol']
    _solution_array_ = ['sol', 'soln', 'dsol', 'dsoln']

    _gdlen_ = None
    _jacofunc_ = None

    def __init__(self, blk, *args, **kw):
        from numpy import empty
        self.debug = kw.pop('debug', False)
        nsca = kw.pop('nsca', 0)
        nvec = kw.pop('nvec', 0)
        diffname = kw.pop('diffname', None)
        self.diffname = diffname if diffname != None else 'tau'
        tauname = kw.pop('tauname', None)
        self.tauname = tauname if tauname != None else 'linear'
        omeganame = kw.pop('omeganame', None)
        self.omeganame = omeganame if omeganame != None else 'scale'
        self.alpha = int(kw.pop('alpha', 0))
        self.taylor = float(kw.pop('taylor', 1.0))
        self.cnbfac = float(kw.pop('cnbfac', 1.0))
        self.sftfac = float(kw.pop('sftfac', 1.0))
        self.taumin = float(kw.pop('taumin', 0.0))
        self.taumax = float(kw.pop('taumax', 1.0))
        self.tauscale = float(kw.pop('tauscale', 0.0))
        self.omegamin = float(kw.pop('omegamin', 1.1))
        self.omegascale = float(kw.pop('omegascale', 0.0))
        self.mqmin = float(kw.pop('mqmin', 1.0))
        self.mqscale = float(kw.pop('mqscale', 0.0))
        super(CeseSolver, self).__init__(blk, *args, **kw)
        fpdtype = self.fpdtype
        ndim = self.ndim
        ncell = self.ncell
        ngstcell = self.ngstcell
        neq = self.neq
        ngroup = self.ngroup
        # meta array.
        self.grpda = empty((ngroup, self._gdlen_), dtype=fpdtype)
        # dual mesh.
        self.cecnd = empty((ngstcell+ncell, self.CLMFC+1, ndim), dtype=fpdtype)
        self.cevol = empty((ngstcell+ncell, self.CLMFC+1), dtype=fpdtype)
        # mesh quality.
        self.mqlty = empty(ngstcell+ncell, dtype=fpdtype)
        # solutions.
        self.solt = empty((ngstcell+ncell, neq), dtype=fpdtype)
        self.sol = empty((ngstcell+ncell, neq), dtype=fpdtype)
        self.soln = empty((ngstcell+ncell, neq), dtype=fpdtype)
        self.dsol = empty((ngstcell+ncell, neq, ndim), dtype=fpdtype)
        self.dsoln = empty((ngstcell+ncell, neq, ndim), dtype=fpdtype)
        self.cfl = empty(ncell, dtype=fpdtype)
        self.ocfl = empty(ncell, dtype=fpdtype)
        self.amsca = empty((ngstcell+ncell, nsca), dtype=fpdtype)
        self.amvec = empty((ngstcell+ncell, nvec, ndim), dtype=fpdtype)

    @property
    def gdlen(self):
        """
        Length per group data.
        """
        return self._gdlen_
    @property
    def nsca(self):
        return self.amsca.shape[1]
    @property
    def nvec(self):
        return self.amvec.shape[1]

    def locate_point(self, *args):
        from ctypes import byref, c_int, c_void_p
        from numpy import array
        crd = array(args, dtype=self.fpdtype)
        picl = c_int(0)
        pifl = c_int(0)
        pjcl = c_int(0)
        pjfl = c_int(0)
        self._clib_cese.locate_point(
            byref(self.exd),
            crd.ctypes._as_parameter_,
            byref(picl),
            byref(pifl),
            byref(pjcl),
            byref(pjfl),
        )
        return picl.value, pifl.value, pjcl.value, pjfl.value

    def init(self, **kw):
        self._tcall(self._clib_cese.calc_ce, 0, self.ncell)
        super(CeseSolver, self).init(**kw)

    def boundcond(self):
        super(CeseSolver, self).boundcond()
        self.call_non_interface_bc('soln')
        self.call_non_interface_bc('dsoln')

    ##################################################
    # library.
    ##################################################
    from ctypes import c_int
    from solvcon.dependency import getcdll
    __clib_cese = {
        2: getcdll('cese2d', raise_on_fail=False),
        3: getcdll('cese3d', raise_on_fail=False),
    }
    del getcdll, c_int
    @property
    def _clib_cese(self):
        return self.__clib_cese[self.ndim]

    ##################################################
    # marching algorithm.
    ##################################################
    MMNAMES = list()
    MMNAMES.append('update')
    def update(self, worker=None):
        from ctypes import c_void_p
        if self.debug: self.mesg('update')
        # exchange solution and gradient.
        self.sol, self.soln = self.soln, self.sol
        self.dsol, self.dsoln = self.dsoln, self.dsol
        # reset pointers in execution data.
        ngstcell = self.ngstcell
        self.exd.sol = self.sol[ngstcell:].ctypes._as_parameter_
        self.exd.soln = self.soln[ngstcell:].ctypes._as_parameter_
        self.exd.dsol = self.dsol[ngstcell:].ctypes._as_parameter_
        self.exd.dsoln = self.dsoln[ngstcell:].ctypes._as_parameter_
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('ibcam')
    def ibcam(self, worker=None):
        if self.debug: self.mesg('ibcam')
        if worker:
            if self.nsca: self.exchangeibc('amsca', worker=worker)
            if self.nvec: self.exchangeibc('amvec', worker=worker)
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('calcsolt')
    def calcsolt(self, worker=None):
        if self.debug: self.mesg('calcsolt')
        self._tcall(self._clib_cese.calc_solt, -self.ngstcell, self.ncell,
            tickerkey='calcsolt')
        if self.debug: self.mesg(' done.\n')
    MMNAMES.append('calcsoln')
    def calcsoln(self, worker=None):
        if self.debug: self.mesg('calcsoln')
        func = self._clib_cese.calc_soln
        self._tcall(func, 0, self.ncell, tickerkey='calcsoln')
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('ibcsoln')
    def ibcsoln(self, worker=None):
        if self.debug: self.mesg('ibcsoln')
        if worker: self.exchangeibc('soln', worker=worker)
        if self.debug: self.mesg(' done.\n')
    MMNAMES.append('bcsoln')
    def bcsoln(self, worker=None):
        if self.debug: self.mesg('bcsoln')
        self.call_non_interface_bc('soln')
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('calccfl')
    def calccfl(self, worker=None):
        """
        @return: mincfl, maxcfl, number of tuned CFL, accumulated number of
            tuned CFL.
        @rtype: tuple
        """
        raise NotImplementedError

    MMNAMES.append('calcdsoln')
    def calcdsoln(self, worker=None):
        if self.debug: self.mesg('calcdsoln')
        func = getattr(self._clib_cese, 'calc_dsoln_'+self.diffname)
        self._tcall(func, 0, self.ncell, tickerkey='calcdsoln')
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('ibcdsoln')
    def ibcdsoln(self, worker=None):
        if self.debug: self.mesg('ibcdsoln')
        if worker: self.exchangeibc('dsoln', worker=worker)
        if self.debug: self.mesg(' done.\n')
    MMNAMES.append('bcdsoln')
    def bcdsoln(self, worker=None):
        if self.debug: self.mesg('bcdsoln')
        self.call_non_interface_bc('dsoln')
        if self.debug: self.mesg(' done.\n')
示例#13
0
class VslinSolver(LincuseSolver):
    """
    Basic elastic solver.

    @ivar mtrldict: map from names to material objects.
    @itype mtrldict: dict
    @ivar mtrllist: list of all material objects.
    @itype mtrllist: list
    """
    from solvcon.dependency import getcdll
    __clib_vslin_c = {
        2: getcdll('vslin2d_c', raise_on_fail=False),
        3: getcdll('vslin3d_c', raise_on_fail=False),
    }
    __clib_vslin_cu = {
        2: getcdll('vslin2d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
        3: getcdll('vslin3d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
    }
    del getcdll

    @property
    def _clib_vslin_c(self):
        return self.__clib_vslin_c[self.ndim]

    @property
    def _clib_vslin_cu(self):
        return self.__clib_vslin_cu[self.ndim]

    @property
    def _gdlen_(self):
        return 9 * 9 * self.ndim

    def __init__(self, *args, **kw):
        super(VslinSolver, self).__init__(*args, **kw)
        self.mtrldict = kw.pop('mtrldict', {})
        self.mtrllist = None

    def make_grpda(self):
        self.mtrllist = self._build_mtrllist(self.grpnames, self.mtrldict)
        for igrp in range(len(self.grpnames)):
            mtrl = self.mtrllist[igrp]
            jaco = self.grpda[igrp].reshape(self.neq, self.neq, self.ndim)
            mjacos = mtrl.get_jacos()
            for idm in range(self.ndim):
                jaco[:, :, idm] = mjacos[idm, :, :]

    @staticmethod
    def _build_mtrllist(grpnames, mtrldict):
        """
        Build the material list out of the mapping dict.

        @type grpnames: list
        @param mtrldict: the map from names to material objects.
        @type mtrldict: dict
        @return: the list of material object.
        @rtype: Material
        """
        mtrllist = list()
        default_mtuple = mtrldict.get(None, None)
        for grpname in grpnames:
            try:
                mtrl = mtrldict.get(grpname, default_mtuple)
            except KeyError as e:
                args = e.args[:]
                args.append('no material named %s in mtrldict' % grpname)
                e.args = args
                raise
            mtrllist.append(mtrl)
        return mtrllist
示例#14
0
class CuseBC(BC):
    """
    Basic BC class for the cuse series solvers.  This class support glue BCs.

    @cvar _ghostgeom_: indicate which ghost geometry processor to use.
    @ctype _ghostgeom_: str
    """

    _ghostgeom_ = None

    ###########################################################################
    # library.
    ###########################################################################
    from solvcon.dependency import getcdll
    __clib_cuseb_c = {
        2: getcdll('cuseb2d_c', raise_on_fail=False),
        3: getcdll('cuseb3d_c', raise_on_fail=False),
    }
    __clib_cuseb_cu = {
        2: getcdll('cuseb2d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
        3: getcdll('cuseb3d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
    }
    del getcdll

    @property
    def _clib_cuseb_c(self):
        return self.__clib_cuseb_c[self.svr.ndim]

    @property
    def _clib_cuseb_cu(self):
        return self.__clib_cuseb_cu[self.svr.ndim]

    def bind(self):
        super(CuseBC, self).bind()
        if self.svr.scu:
            for key in (
                    'facn',
                    'value',
            ):
                nbytes = getattr(self, key).nbytes
                setattr(self, 'cu' + key, self.svr.scu.alloc(nbytes))

    def unbind(self):
        if self.svr.scu:
            for key in (
                    'facn',
                    'value',
            ):
                gptr = getattr(self, 'cu' + key, None)
                if gptr is not None:
                    self.svr.scu.free(getattr(self, 'cu' + key))

    def init(self, **kw):
        from ctypes import byref, c_int
        super(CuseBC, self).init(**kw)
        # process ghost geometry.
        getattr(self._clib_cuseb_c, 'ghostgeom_' + self._ghostgeom_)(
            byref(self.svr.exd), c_int(self.facn.shape[0]),
            self.facn.ctypes._as_parameter_)
        # initialize GPU data.
        if self.svr.scu:
            for key in (
                    'facn',
                    'value',
            ):
                self.svr.scu.memcpy(getattr(self, 'cu' + key),
                                    getattr(self, key))

    def soln(self):
        """
        Update ghost cells after self.svr.calcsoln.
        """
        pass

    def dsoln(self):
        """
        Update ghost cells after self.svr.calcdsoln.
        """
        pass
示例#15
0
class CuseSolver(BlockSolver):
    """
    The base solver class for second-order, multi-dimensional CESE code with
    CUDA enabled.

    @cvar _gdlen_: length per group data.  Must be overridden.
    @ctype _gdlen_: int
    @cvar _jacofunc_: ctypes function to Jacobian calculator.  Must be
        overridden.
    @ctype _jacofunc_: ctypes.FuncPtr
    @cvar _clib_mcu: ctypes library for physical model on GPU.
    @ctype _clib_mcu: ctypes.CDLL

    @ivar debug: flag for debugging.
    @itype debug: bool

    @ivar scu: CUDA wrapper.
    @itype scu: solvcon.scuda.Scuda
    @ivar ncuth: number of thread per block for CUDA.
    @itype ncuth: int

    @ivar alpha: parameter to the weighting function.
    @itype alpha: int
    @ivar sigma0: constant parameter for W-3 scheme; should be of order of 1.
        Default is 3.0.
    @itype sigma0: float
    @ivar taylor: factor for Taylor's expansion; 0 off, 1 on.
    @itype taylor: float
    @ivar cnbfac: factor to use BCE centroid, othersize midpoint; 0 off, 1 on.
    @itype cnbfac: float
    @ivar sftfac: factor to shift gradient shape; 0 off, 1 on.
    @itype sftfac: float
    @ivar taumin: the lower bound of tau.
    @itype taumin: float
    @ivar tauscale: scaling of tau.
    @itype tauscale: float

    @ivar grpda: group data.
    @ivar cecnd: solution points for CCEs and BCEs.
    @ivar cevol: CCE and BCE volumes.
    @ivar sfmrc: sub-face geometry.  It is a 5-dimensional array, and the shape
        is (ncell, CLMFC, FCMND, 2, NDIM).  sfmrc[...,0,:] are centers,
        while sfmrc[...,1,:] are normal vectors.
    @ivar amsca: Parameter scalar array.
    @ivar amvec: Parameter vector array.
    @ivar solt: temporal diffrentiation of solution.
    @ivar sol: current solution.
    @ivar soln: next solution.
    @ivar dsol: current gradient of solution.
    @ivar dsoln: next gradient of solution.
    @ivar cfl: CFL number.
    @ivar ocfl: original CFL number.
    """

    _exedatatype_ = CuseSolverExedata
    _interface_init_ = ['cecnd', 'cevol']
    _solution_array_ = ['sol', 'soln', 'dsol', 'dsoln']

    _gdlen_ = None
    _jacofunc_ = None
    _clib_mcu = None

    def __init__(self, blk, *args, **kw):
        from numpy import empty
        self.debug = kw.pop('debug', False)
        # shape parameters.
        nsca = kw.pop('nsca', 0)
        nvec = kw.pop('nvec', 0)
        # CUDA parameters.
        self.ncuth = kw.pop('ncuth', 0)
        self.scu = None
        # scheme parameters.
        self.alpha = int(kw.pop('alpha', 0))
        self.sigma0 = int(kw.pop('sigma0', 3.0))
        self.taylor = float(kw.pop('taylor', 1.0))  # dirty hack.
        self.cnbfac = float(kw.pop('cnbfac', 1.0))  # dirty hack.
        self.sftfac = float(kw.pop('sftfac', 1.0))  # dirty hack.
        self.taumin = float(kw.pop('taumin', 0.0))
        self.tauscale = float(kw.pop('tauscale', 1.0))
        # super call.
        kw.setdefault('enable_tpool', False)
        super(CuseSolver, self).__init__(blk, *args, **kw)
        fpdtype = self.fpdtype
        ndim = self.ndim
        ncell = self.ncell
        ngstcell = self.ngstcell
        neq = self.neq
        ngroup = self.ngroup
        # CUDA manager.
        self.cumgr = None
        self.cuarr_map = dict()
        for key in ('ndcrd', ):
            self.cuarr_map[key] = self.ngstnode
        for key in ('fcnds', 'fccls', 'fccnd', 'fcnml', 'fcara'):
            self.cuarr_map[key] = self.ngstface
        for key in ('clfcs', 'clcnd', 'cltpn'):
            self.cuarr_map[key] = self.ngstcell
        # meta array.
        self.grpda = empty((ngroup, self._gdlen_), dtype=fpdtype)
        self.cuarr_map['grpda'] = 0
        # dual mesh.
        self.cecnd = empty((ngstcell + ncell, self.CLMFC + 1, ndim),
                           dtype=fpdtype)
        self.cevol = empty((ngstcell + ncell, self.CLMFC + 1), dtype=fpdtype)
        self.cuarr_map['cecnd'] = self.cuarr_map['cevol'] = self.ngstcell
        self.sfmrc = empty((ncell, self.CLMFC, self.FCMND, 2, ndim),
                           dtype=fpdtype)
        self.cuarr_map['sfmrc'] = 0
        # solutions.
        self.amsca = empty((ngstcell + ncell, nsca), dtype=fpdtype)
        self.amvec = empty((ngstcell + ncell, nvec, ndim), dtype=fpdtype)
        self.solt = empty((ngstcell + ncell, neq), dtype=fpdtype)
        self.sol = empty((ngstcell + ncell, neq), dtype=fpdtype)
        self.soln = empty((ngstcell + ncell, neq), dtype=fpdtype)
        self.dsol = empty((ngstcell + ncell, neq, ndim), dtype=fpdtype)
        self.dsoln = empty((ngstcell + ncell, neq, ndim), dtype=fpdtype)
        self.stm = empty((ngstcell + ncell, neq), dtype=fpdtype)
        self.cfl = empty(ngstcell + ncell, dtype=fpdtype)
        self.ocfl = empty(ngstcell + ncell, dtype=fpdtype)
        for key in ('amsca', 'amvec', 'solt', 'sol', 'soln', 'dsol', 'dsoln',
                    'stm', 'cfl', 'ocfl'):
            self.cuarr_map[key] = self.ngstcell

    @property
    def gdlen(self):
        """
        Length per group data.
        """
        return self._gdlen_

    @property
    def nsca(self):
        return self.amsca.shape[1]

    @property
    def nvec(self):
        return self.amvec.shape[1]

    def bind(self):
        from solvcon.conf import env
        self.scu = env.scu if self.ncuth else None
        if self.scu:
            self.cumgr = CudaDataManager(svr=self)
        super(CuseSolver, self).bind()

    def unbind(self):
        if self.scu and self.cumgr is not None:
            self.cumgr.free_all()
            self.cumgr = None
        super(CuseSolver, self).unbind()

    def init(self, **kw):
        from ctypes import byref
        self._clib_cuse_c.prepare_ce(byref(self.exd))
        super(CuseSolver, self).init(**kw)
        self._clib_cuse_c.prepare_sf(byref(self.exd))
        if self.scu: self.cumgr.arr_to_gpu()
        self.mesg('cuda is %s\n' % ('on' if self.scu else 'off'))

    def boundcond(self):
        if self.scu:
            self.cumgr.update_exd()
            self.cumgr.arr_to_gpu('sol', 'soln', 'dsol', 'dsoln')
            if self.nsca: self.cumgr.arr_to_gpu('amsca')
            if self.nvec: self.cumgr.arr_to_gpu('amvec')
        super(CuseSolver, self).boundcond()
        self.call_non_interface_bc('soln')
        if self.scu:
            self.cumgr.arr_from_gpu('sol', 'soln')
        self.call_non_interface_bc('dsoln')
        if self.scu:
            self.cumgr.arr_from_gpu('dsol', 'dsoln')

    ###########################################################################
    # parallelization.
    ###########################################################################
    def pushibc(self, arrname, bc, recvn, worker=None):
        """
        Push data toward selected interface which connect to blocks with larger
        serial number than myself.  If CUDA is present, data are first uploaded
        to and then downloaded from GPU.

        @param arrname: name of the array in the object to exchange.
        @type arrname: str
        @param bc: the interface BC to push.
        @type bc: solvcon.boundcond.interface
        @param recvn: serial number of the peer to exchange data with.
        @type recvn: int
        @keyword worker: the wrapping worker object for parallel processing.
        @type worker: solvcon.rpc.Worker
        """
        from numpy import empty
        conn = worker.pconns[bc.rblkn]
        ngstcell = self.ngstcell
        arr = getattr(self, arrname)
        shape = list(arr.shape)
        shape[0] = bc.rclp.shape[0]
        # for CUDA up/download.
        if self.scu:
            stride = arr.itemsize
            for size in arr.shape[1:]:
                stride *= size
        # ask the receiver for data.
        rarr = empty(shape, dtype=arr.dtype)
        conn.recvarr(rarr)  # comm.
        # set array and upload to GPU.
        slct = bc.rclp[:, 0] + ngstcell
        if self.scu:
            gslct = self.scu.alloc(slct.nbytes)
            self.scu.memcpy(gslct, slct)
            gbrr = self.scu.alloc(rarr.nbytes)
            self.scu.memcpy(gbrr, rarr)
            garr = self.cumgr[arrname]
            self._clib_cuse_cu.slct_io(self.ncuth, 0, len(slct), stride,
                                       gslct.gptr, garr.gptr, gbrr.gptr)
        else:
            arr[slct] = rarr[:]
        # download from GPU and get array.
        slct = bc.rclp[:, 2] + ngstcell
        if self.scu:
            self.scu.memcpy(gslct, slct)
            self._clib_cuse_cu.slct_io(self.ncuth, 1, len(slct), stride,
                                       gslct.gptr, garr.gptr, gbrr.gptr)
            self.scu.memcpy(rarr, gbrr)
            self.scu.free(gbrr)
            self.scu.free(gslct)
        else:
            rarr[:] = arr[slct]
        # provide the receiver with data.
        conn.sendarr(rarr)  # comm.

    def pullibc(self, arrname, bc, sendn, worker=None):
        """
        Pull data from the interface determined by the serial of peer.  If CUDA
        is present, data are first downloaded from GPU and then uploaded to
        GPU.

        @param arrname: name of the array in the object to exchange.
        @type arrname: str
        @param bc: the interface BC to pull.
        @type bc: solvcon.boundcond.interface
        @param sendn: serial number of the peer to exchange data with.
        @type sendn: int
        @keyword worker: the wrapping worker object for parallel processing.
        @type worker: solvcon.rpc.Worker
        """
        from numpy import empty
        conn = worker.pconns[bc.rblkn]
        ngstcell = self.ngstcell
        arr = getattr(self, arrname)
        shape = list(arr.shape)
        shape[0] = bc.rclp.shape[0]
        # for CUDA up/download.
        if self.scu:
            stride = arr.itemsize
            for size in arr.shape[1:]:
                stride *= size
        # download from GPU and get array.
        slct = bc.rclp[:, 2] + ngstcell
        rarr = empty(shape, dtype=arr.dtype)
        if self.scu:
            gslct = self.scu.alloc(slct.nbytes)
            self.scu.memcpy(gslct, slct)
            gbrr = self.scu.alloc(rarr.nbytes)
            garr = self.cumgr[arrname]
            self._clib_cuse_cu.slct_io(self.ncuth, 1, len(slct), stride,
                                       gslct.gptr, garr.gptr, gbrr.gptr)
            self.scu.memcpy(rarr, gbrr)
        else:
            rarr[:] = arr[slct]
        # provide sender the data.
        conn.sendarr(rarr)  # comm.
        # ask data from sender.
        conn.recvarr(rarr)  # comm.
        # set array and upload to GPU.
        slct = bc.rclp[:, 0] + ngstcell
        if self.scu:
            self.scu.memcpy(gslct, slct)
            self.scu.memcpy(gbrr, rarr)
            self._clib_cuse_cu.slct_io(self.ncuth, 0, len(slct), stride,
                                       gslct.gptr, garr.gptr, gbrr.gptr)
            self.scu.free(gbrr)
            self.scu.free(gslct)
        else:
            arr[slct] = rarr[:]

    ###########################################################################
    # utility.
    ###########################################################################
    def locate_point(self, *args):
        """
        Locate the cell index where the input coordinate is.
        """
        from ctypes import byref, c_int
        from numpy import array
        crd = array(args, dtype='float64')
        picl = c_int(0)
        pifl = c_int(0)
        pjcl = c_int(0)
        pjfl = c_int(0)
        self._clib_cuse_c.locate_point(byref(self.exd),
                                       crd.ctypes._as_parameter_, byref(picl),
                                       byref(pifl), byref(pjcl), byref(pjfl))
        return picl.value, pifl.value, pjcl.value, pjfl.value

    ###########################################################################
    # library.
    ###########################################################################
    from solvcon.dependency import getcdll
    __clib_cuse_c = {
        2: getcdll('cuse2d_c', raise_on_fail=False),
        3: getcdll('cuse3d_c', raise_on_fail=False),
    }
    __clib_cuse_cu = {
        2: getcdll('cuse2d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
        3: getcdll('cuse3d_cu', raise_on_fail=CUDA_RAISE_ON_FAIL),
    }
    del getcdll

    @property
    def _clib_cuse_c(self):
        return self.__clib_cuse_c[self.ndim]

    @property
    def _clib_cuse_cu(self):
        return self.__clib_cuse_cu[self.ndim]

    ###########################################################################
    # marching algorithm.
    ###########################################################################
    MMNAMES = list()

    MMNAMES.append('update')

    def update(self, worker=None):
        if self.debug: self.mesg('update')
        # exchange solution and gradient.
        self.sol, self.soln = self.soln, self.sol
        self.dsol, self.dsoln = self.dsoln, self.dsol
        # exchange pointers in execution data.
        exd = self.exd
        exd.sol, exd.soln = exd.soln, exd.sol
        exd.dsol, exd.dsoln = exd.dsoln, exd.dsol
        # exchange items in GPU execution data.
        if self.scu:
            cumgr = self.cumgr
            cumgr.sol, cumgr.soln = cumgr.soln, cumgr.sol
            cumgr.dsol, cumgr.dsoln = cumgr.dsoln, cumgr.dsol
            cumgr.update_exd()
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('ibcam')

    def ibcam(self, worker=None):
        if self.debug: self.mesg('ibcam')
        if worker:
            if self.nsca: self.exchangeibc('amsca', worker=worker)
            if self.nvec: self.exchangeibc('amvec', worker=worker)
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('calcsolt')

    def calcsolt(self, worker=None):
        from ctypes import byref
        if self.debug: self.mesg('calcsolt')
        if self.scu:
            self._clib_mcu.calc_solt(self.ncuth, byref(self.cumgr.exd),
                                     self.cumgr.gexd.gptr)
        else:
            self._clib_cuse_c.calc_solt(byref(self.exd), -self.ngstcell,
                                        self.ncell)
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('calcsoln')

    def calcsoln(self, worker=None):
        from ctypes import byref
        if self.debug: self.mesg('calcsoln')
        if self.scu:
            self._clib_mcu.calc_soln(self.ncuth, byref(self.cumgr.exd),
                                     self.cumgr.gexd.gptr)
        else:
            self._clib_cuse_c.calc_soln(byref(self.exd))
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('ibcsoln')

    def ibcsoln(self, worker=None):
        if self.debug: self.mesg('ibcsoln')
        if worker: self.exchangeibc('soln', worker=worker)
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('bcsoln')

    def bcsoln(self, worker=None):
        if self.debug: self.mesg('bcsoln')
        self.call_non_interface_bc('soln')
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('calccfl')

    def calccfl(self, worker=None):
        raise NotImplementedError

    MMNAMES.append('calcdsoln')

    def calcdsoln(self, worker=None):
        from ctypes import byref
        if self.debug: self.mesg('calcdsoln')
        if self.scu:
            self._clib_mcu.calc_dsoln_w3(self.ncuth, byref(self.cumgr.exd),
                                         self.cumgr.gexd.gptr)
        else:
            self._clib_cuse_c.calc_dsoln_w3(byref(self.exd))
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('ibcdsoln')

    def ibcdsoln(self, worker=None):
        if self.debug: self.mesg('ibcdsoln')
        if worker: self.exchangeibc('dsoln', worker=worker)
        if self.debug: self.mesg(' done.\n')

    MMNAMES.append('bcdsoln')

    def bcdsoln(self, worker=None):
        if self.debug: self.mesg('bcdsoln')
        self.call_non_interface_bc('dsoln')
        if self.debug: self.mesg(' done.\n')