def auto_matrix(self, initval, iopacking='AoS', tags=set()): """Creates either a constant or block diagonal matrix from *initval* """ # HACK: The following code attempts to identify one special- # case of block diagonal matrices; while it is currently # sufficient a more robust methodology is desirable. shape = initval.shape if iopacking == 'AoS' and len(shape) == 4 and shape[1] == shape[3]: for i, j in ndrange(shape[1], shape[1]): if i == j: continue if np.any(initval[:,i,:,j] != 0): break else: # Block spans are trivial brange = [(i*shape[0], (i + 1)*shape[0], i*shape[2], (i + 1)*shape[2]) for i in xrange(shape[1])] return self.block_diag_matrix(initval, brange, iopacking, tags) # Not block-diagonal; return a constant matrix return self.const_matrix(initval, iopacking, tags)
def col_view(mat): vshape = (mat.nrow,) rcmap = np.array(list(ndrange(1, mat.ncol))) matmap = np.array([mat.mid]*mat.ncol) stridemap = np.array([[mat.leaddim]]*mat.ncol) return backend.view(matmap, rcmap, stridemap, vshape)
def _eval_lbasis_at(self, lbasis, pts): m = np.empty((len(pts), len(lbasis)), dtype=np.object) for i, j in ndrange(*m.shape): m[i,j] = lbasis[j](*pts[i]) m[abs(m) < 1e-14] = 0 return m
def _get_jac_smats_2d(self, jac, retdets): a, b, c, d = [jac[...,i,j] for i, j in ndrange(2, 2)] smats = np.empty_like(jac) smats[...,0,0], smats[...,0,1] = d, -b smats[...,1,0], smats[...,1,1] = -c, a if retdets: return smats, a*d - b*c else: return smats
def artf_vis(): # Compute entropy and save to avis_upts ent = backend.kernel('entropy', tplargs=tplargs, dims=[nupts, neles], u=self.scal_upts_inb, s=avis_upts) # Compute modal coefficients of entropy rcpvdm = np.linalg.inv(self.basis.ubasis.vdm.T) rcpvdm = self._be.const_matrix(rcpvdm, tags={'align'}) mul = backend.kernel('mul', rcpvdm, avis_upts, out=avis_upts_temp) # Additional constants for element-wise artificial viscosity tplargs['c'].update( self.cfg.items_as('solver-artificial-viscosity', float)) tplargs.update( dict( nupts=nupts, nfpts=nfpts, order=self.basis.order, ubdegs=self.basis.ubasis.degrees, )) # Column view for avis_upts/fpts matrices col_view = lambda mat: backend.view( matmap=np.array([mat.mid] * mat.ncol), rcmap=np.array(list(ndrange(1, mat.ncol))), stridemap=np.array([[mat.leaddim]] * mat.ncol), vshape=(mat.nrow, )) avis_fpts_cv = col_view(self._avis_fpts) avis_upts_temp_cv = col_view(avis_upts_temp) if 'flux' in self.antialias: ame_e = col_view(avis_qpts) tplargs['nrow_amu'] = self.nqpts else: ame_e = col_view(avis_upts) tplargs['nrow_amu'] = nupts # Element-wise artificial viscosity kernel avis = backend.kernel('avis', tplargs, dims=[neles], s=avis_upts_temp_cv, amu_e=ame_e, amu_f=avis_fpts_cv) return ComputeMetaKernel([ent, mul, avis])
def artf_vis(): # Compute entropy and save to avis_upts ent = backend.kernel( 'entropy', tplargs=tplargs, dims=[nupts, neles], u=self.scal_upts_inb, s=avis_upts ) # Compute modal coefficients of entropy rcpvdm = np.linalg.inv(self.basis.ubasis.vdm.T) rcpvdm = self._be.const_matrix(rcpvdm, tags={'align'}) mul = backend.kernel( 'mul', rcpvdm, avis_upts, out=avis_upts_temp ) # Additional constants for element-wise artificial viscosity tplargs['c'].update( self.cfg.items_as('solver-artificial-viscosity', float) ) tplargs.update(dict( nupts=nupts, nfpts=nfpts, order=self.basis.order, ubdegs=self.basis.ubasis.degrees, )) # Column view for avis_upts/fpts matrices col_view = lambda mat: backend.view( matmap=np.array([mat.mid]*mat.ncol), rcmap=np.array(list(ndrange(1, mat.ncol))), stridemap=np.array([[mat.leaddim]]*mat.ncol), vshape=(mat.nrow,) ) avis_fpts_cv = col_view(self._avis_fpts) avis_upts_temp_cv = col_view(avis_upts_temp) if 'flux' in self.antialias: ame_e = col_view(avis_qpts) tplargs['nrow_amu'] = self.nqpts else: ame_e = col_view(avis_upts) tplargs['nrow_amu'] = nupts # Element-wise artificial viscosity kernel avis = backend.kernel( 'avis', tplargs, dims=[neles], s=avis_upts_temp_cv, amu_e=ame_e, amu_f=avis_fpts_cv ) return ComputeMetaKernel([ent, mul, avis])
def _offset_arg_array_2d(self, arg): stmts = [] # Matrix; name + _y*lsdim + cb if arg.ncdim == 0: stmts.append('{0}_v + _y*lsd{0} + cb'.format(arg.name)) # Stacked matrix; name + (_y*nv + <0>)*lsdim + cb elif arg.ncdim == 1: stmts.extend('{0}_v + (_y*{1} + {2})*lsd{0} + cb'.format( arg.name, arg.cdims[0], i) for i in range(arg.cdims[0])) # Doubly stacked matrix; name + ((<0>*_ny + _y)*nv + <1>)*lsdim + cb else: stmts.extend( '{0}_v + (({1}*_ny + _y)*{2} + {3})*lsd{0} + cb'.format( arg.name, i, arg.cdims[1], j) for i, j in ndrange(*arg.cdims)) return stmts
def _offset_arg_array_2d(self, arg): stmts = [] # Matrix; name + _y*lsdim + cb if arg.ncdim == 0: stmts.append('{0}_v + _y*lsd{0} + cb'.format(arg.name)) # Stacked matrix; name + (_y*nv + <0>)*lsdim + cb elif arg.ncdim == 1: stmts.extend('{0}_v + (_y*{1} + {2})*lsd{0} + cb' .format(arg.name, arg.cdims[0], i) for i in range(arg.cdims[0])) # Doubly stacked matrix; name + ((<0>*_ny + _y)*nv + <1>)*lsdim + cb else: stmts.extend('{0}_v + (({1}*_ny + _y)*{2} + {3})*lsd{0} + cb' .format(arg.name, i, arg.cdims[1], j) for i, j in ndrange(*arg.cdims)) return stmts
def _emit_load_store(self, arg): # Dereference the argument darg = self._deref_arg(arg) if arg.ncdim == 0: return [(arg.name, darg)] else: exprs = [] for ij in ndrange(*arg.cdims): # Local variable; name[<i>] or name[<i>][<j>] lidx = '[{}]'.format(']['.join(str(n) for n in ij)) lvar = arg.name + lidx # Global variable; varies gvar = darg.format(*ij) exprs.append((lvar, gvar)) return exprs
def _emit_inner_spec(self): # Inner dimension ikargs = ['int _nx'] # Add any scalar arguments ikargs.extend('{0.dtype} {0.name}'.format(sa) for sa in self.scalargs) # Vector arguments (always arrays as we're 2D) for va in self.vectargs: const = 'const' if va.intent == 'in' else '' stmt = '{0} {1.dtype} *__restrict__ {1.name}_v'.format(const, va) stmt = stmt.strip() if va.ncdim == 0: ikargs.append(stmt) else: for ij in ndrange(*va.cdims): ikargs.append(stmt + 'v'.join(str(n) for n in ij)) return ('static PYFR_NOINLINE void {0}_inner({1})'.format( self.name, ', '.join(ikargs)))
def _emit_inner_spec(self): # Inner dimension ikargs = ['int _nx'] # Add any scalar arguments ikargs.extend('{0.dtype} {0.name}'.format(sa) for sa in self.scalargs) # Vector arguments (always arrays as we're 2D) for va in self.vectargs: const = 'const' if va.intent == 'in' else '' stmt = '{0} {1.dtype} *__restrict__ {1.name}_v'.format(const, va) stmt = stmt.strip() if va.ncdim == 0: ikargs.append(stmt) else: for ij in ndrange(*va.cdims): ikargs.append(stmt + 'v'.join(str(n) for n in ij)) return ('static PYFR_NOINLINE void {0}_inner({1})' .format(self.name, ', '.join(ikargs)))
def ndrange(context, *args): return util.ndrange(*args)