def _load_eles(self, rallocs, mesh, initsoln): basismap = {b.name: b for b in subclasses(BaseBasis, just_leaf=True)} # Look for and load each element type from the mesh elemap = OrderedDict() for f in mesh: m = re.match('spt_(.+?)_p%d$' % rallocs.prank, f) if m: # Element type t = m.group(1) elemap[t] = self.elementscls(basismap[t], mesh[f], self._cfg) # Construct a proxylist to simplify collective operations eles = proxylist(elemap.values()) # Set the initial conditions either from a pyfrs file or from # explicit expressions in the config file if initsoln: # Load the config used to produce the solution solncfg = Inifile(initsoln['config'].item()) # Process the solution for k, ele in elemap.iteritems(): soln = initsoln['soln_%s_p%d' % (k, rallocs.prank)] ele.set_ics_from_soln(soln, solncfg) else: eles.set_ics_from_cfg() # Allocate these elements on the backend eles.set_backend(self._backend, self._nreg) return eles, elemap
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Compute the error coeffs self.e = [b - bh for b, bh in zip(self.b, self.bhat)] self._nstages = len(self.b) # Register a kernel to multiply rhs with local pseudo time-step self.backend.pointwise.register( 'pyfr.integrators.dual.pseudo.kernels.localdtau') tplargs = dict(ndims=self.system.ndims, nvars=self.system.nvars) self.dtau_upts = proxylist([]) for ele, shape in zip(self.system.ele_map.values(), self.system.ele_shapes): # Allocate storage for the local pseudo time-step dtaumat = self.backend.matrix(shape, np.ones(shape) * self._dtau, tags={'align'}) self.dtau_upts.append(dtaumat) # Append the local dtau kernels to the proxylist self.pintgkernels['localdtau'].append( self.backend.kernel('localdtau', tplargs=tplargs, dims=[ele.nupts, ele.neles], negdivconf=ele.scal_upts_inb, dtau_upts=dtaumat))
def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg): super().__init__(backend, rallocs, mesh, initsoln, cfg) # Sanity checks if self._controller_needs_errest and not self._stepper_has_errest: raise TypeError('Incompatible stepper/controller combination') # Ensure the system is compatible with our formulation if 'std' not in systemcls.elementscls.formulations: raise RuntimeError(f'System {systemcls.name} does not support ' f'time stepping formulation std') # Determine the amount of temp storage required by this method self.nregs = self._stepper_nregs # Construct the relevant system self.system = systemcls(backend, rallocs, mesh, initsoln, nregs=self.nregs, cfg=cfg) # Storage for register banks and current index self._init_reg_banks() # Global degree of freedom count self._gndofs = self._get_gndofs() # Event handlers for advance_to self.completed_step_handlers = proxylist(self._get_plugins()) # Delete the memory-intensive elements map from the system del self.system.ele_map
def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg): super().__init__(backend, rallocs, mesh, initsoln, cfg) # Determine the amount of temp storage required by this method self.nregs = self._stepper_nregs # Construct the relevant mesh partition self.system = systemcls(backend, rallocs, mesh, initsoln, nregs=self.nregs, cfg=cfg) # Storage for register banks and current index self._init_reg_banks() # Global degree of freedom count self._gndofs = self._get_gndofs() # Add kernel cache self._axnpby_kerns = {} # Event handlers for advance_to self.completed_step_handlers = proxylist(self._get_plugins()) # Sanity checks if self._controller_needs_errest and not self._stepper_has_errest: raise TypeError('Incompatible stepper/controller combination') # Ensure the system is compatible with our formulation if 'std' not in systemcls.elementscls.formulations: raise RuntimeError( 'System {0} does not support time stepping formulation std' .format(systemcls.name) )
def _load_eles(self, rallocs, mesh, initsoln): basismap = subclass_map(BaseBasis, 'name') # Look for and load each element type from the mesh self._elemaps = elemaps = OrderedDict() for bname, bcls in basismap.iteritems(): mk = 'spt_%s_p%d' % (bname, rallocs.prank) if mk in mesh: elemaps[bname] = self.elementscls(bcls, mesh[mk], self._cfg) # Construct a proxylist to simplify collective operations self._eles = eles = proxylist(elemaps.values()) # Set the initial conditions either from a pyfrs file or from # explicit expressions in the config file if initsoln: # Load the config used to produce the solution solncfg = Inifile(initsoln['config'].item()) # Process the solution for k, ele in elemaps.iteritems(): soln = initsoln['soln_%s_p%d' % (k, rallocs.prank)] ele.set_ics_from_soln(soln, solncfg) else: eles.set_ics_from_cfg() # Allocate these elements on the backend eles.set_backend(self._backend, self._nreg)
def mgproject(self, l1, l2): inbanks = self._mgsystems[l1].eles_scal_upts_inb outbanks = self._mgsystems[l2].eles_scal_upts_inb return proxylist( self.backend.kernel('mul', pm, inb, out=outb) for pm, inb, outb in zip(self.projmats[l1, l2], inbanks, outbanks))
def dtauproject(self, l1, l2): inbanks = self.pintgs[l1].dtau_upts outbanks = self.pintgs[l2].dtau_upts return proxylist( self.backend.kernel('mul', pm, inb, out=outb, alpha=self.dtauf) for pm, inb, outb in zip(self.projmats[l1, l2], inbanks, outbanks))
def _load_eles(self, rallocs, mesh, initsoln): basismap = {b.name: b for b in subclasses(BaseShape, just_leaf=True)} # Look for and load each element type from the mesh elemap = OrderedDict() for f in mesh: m = re.match('spt_(.+?)_p%d$' % rallocs.prank, f) if m: # Element type t = m.group(1) elemap[t] = self.elementscls(basismap[t], mesh[f], self._cfg) # Construct a proxylist to simplify collective operations eles = proxylist(elemap.values()) # Set the initial conditions either from a pyfrs file or from # explicit expressions in the config file if initsoln: # Load the config used to produce the solution solncfg = Inifile(initsoln['config']) # Process the solution for k, ele in elemap.iteritems(): soln = initsoln['soln_%s_p%d' % (k, rallocs.prank)] ele.set_ics_from_soln(soln, solncfg) else: eles.set_ics_from_cfg() # Allocate these elements on the backend eles.set_backend(self._backend, self._nreg) return eles, elemap
def _load_int_inters(self, rallocs, mesh): lhs, rhs = mesh['con_p%d' % rallocs.prank] int_inters = self.intinterscls(self._backend, lhs, rhs, self._elemaps, self._cfg) # Although we only have a single internal interfaces instance # we wrap it in a proxylist for consistency self._int_inters = proxylist([int_inters])
def mgproject(self, l1, l2): inbanks = self._mgsystems[l1].eles_scal_upts_inb outbanks = self._mgsystems[l2].eles_scal_upts_inb return proxylist( self.backend.kernel('mul', pm, inb, out=outb) for pm, inb, outb in zip(self.projmats[l1, l2], inbanks, outbanks) )
def _load_int_inters(self, rallocs, mesh, elemap): lhs, rhs = mesh['con_p%d' % rallocs.prank].tolist() int_inters = self.intinterscls(self._backend, lhs, rhs, elemap, self._cfg) # Although we only have a single internal interfaces instance # we wrap it in a proxylist for consistency return proxylist([int_inters])
def _kernel(self, name, nargs): # Transpose from [nregs][neletypes] to [neletypes][nregs] transregs = zip(*self._regs) # Generate an kernel for each element type kerns = proxylist([]) for tr in transregs: kerns.append(self.backend.kernel(name, *tr[:nargs])) return kerns
def _kernel(self, name, nargs): # Transpose from [nregs][neletypes] to [neletypes][nregs] transregs = zip(*self._regs) # Generate an kernel for each element type kerns = proxylist([]) for tr in transregs: kerns.append(self._backend.kernel(name, *tr[:nargs])) return kerns
def _init_reg_banks(self): self._regs, self._regidx = [], list(range(self.nreg)) self._idxcurr = 0 # Create a proxylist of matrix-banks for each storage register for i in self._regidx: self._regs.append( proxylist([self.backend.matrix_bank(em, i) for em in self.system.ele_banks]) )
def _load_int_inters(self, rallocs, mesh, elemap): key = 'con_p{0}'.format(rallocs.prank) lhs, rhs = mesh[key].astype('U4,i4,i1,i1').tolist() int_inters = self.intinterscls(self.backend, lhs, rhs, elemap, self.cfg) # Although we only have a single internal interfaces instance # we wrap it in a proxylist for consistency return proxylist([int_inters])
def _load_int_inters(self, rallocs, mesh, elemap): key = 'con_p{0}'.format(rallocs.prank) lhs, rhs = mesh[key].astype('U4,i4,i1,i1').tolist() int_inters = self.intinterscls(self.backend, lhs, rhs, elemap, self.cfg) # Although we only have a single internal interfaces instance # we wrap it in a proxylist for consistency return proxylist([int_inters])
def _init_reg_banks(self): self._regs, self._regidx = [], list(range(self.nreg)) self._idxcurr = 0 # Create a proxylist of matrix-banks for each storage register for i in self._regidx: self._regs.append( proxylist([self.backend.matrix_bank(em, i) for em in self.system.ele_banks]) )
def _get_reg_banks(self, nreg): regs, regidx = [], list(range(nreg)) # Create a proxylist of matrix-banks for each storage register for i in regidx: regs.append( proxylist([self.backend.matrix_bank(em, i) for em in self.system.ele_banks]) ) return regs, regidx
def _init_reg_banks(self): # Multi-p requires two additional storage registers at lower levels self._mgregs, self._regidx = {}, list(range(self.nreg + 2)) self._mgidxcurr = dict.fromkeys(self.levels, 0) # Create a proxylist of matrix-banks for each storage register for l, sys in self._mgsystems.items(): regs = self._mgregs[l] = [] for i in range(self.nreg + (2 if l != self._order else 0)): regs.append(proxylist(self.backend.matrix_bank(em, i) for em in sys.ele_banks))
def _load_mpi_inters(self, rallocs, mesh): lhsprank = rallocs.prank self._mpi_inters = proxylist([]) for rhsprank in rallocs.prankconn[lhsprank]: rhsmrank = rallocs.pmrankmap[rhsprank] interarr = mesh['con_p%dp%d' % (lhsprank, rhsprank)] mpiiface = self.mpiinterscls(self._backend, interarr, rhsmrank, rallocs, self._elemaps, self._cfg) self._mpi_inters.append(mpiiface)
def _init_reg_banks(self): # Multi-p requires two additional storage registers at lower levels self._mgregs, self._regidx = {}, list(range(self.nreg + 2)) self._mgidxcurr = dict.fromkeys(self.levels, 0) # Create a proxylist of matrix-banks for each storage register for l, sys in self._mgsystems.items(): regs = self._mgregs[l] = [] for i in range(self.nreg + (2 if l != self._order else 0)): regs.append( proxylist( self.backend.matrix_bank(em, i) for em in sys.ele_banks))
def _load_mpi_inters(self, rallocs, mesh, elemap): lhsprank = rallocs.prank mpi_inters = proxylist([]) for rhsprank in rallocs.prankconn[lhsprank]: rhsmrank = rallocs.pmrankmap[rhsprank] interarr = mesh['con_p%dp%d' % (lhsprank, rhsprank)].tolist() mpiiface = self.mpiinterscls(self._backend, interarr, rhsmrank, rallocs, elemap, self._cfg) mpi_inters.append(mpiiface) return mpi_inters
def _load_mpi_inters(self, rallocs, mesh, elemap): lhsprank = rallocs.prank mpi_inters = proxylist([]) for rhsprank in rallocs.prankconn[lhsprank]: rhsmrank = rallocs.pmrankmap[rhsprank] interarr = mesh['con_p{0}p{1}'.format(lhsprank, rhsprank)] interarr = interarr.astype('U4,i4,i1,i1').tolist() mpiiface = self.mpiinterscls(self.backend, interarr, rhsmrank, rallocs, elemap, self.cfg) mpi_inters.append(mpiiface) return mpi_inters
def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg): super().__init__(backend, rallocs, mesh, initsoln, cfg) # Get the pseudo-integrator self.pseudointegrator = get_pseudo_integrator( backend, systemcls, rallocs, mesh, initsoln, cfg, self._stepper_coeffs, self._dt ) # Event handlers for advance_to self.completed_step_handlers = proxylist(self._get_plugins()) # Delete the memory-intensive elements map from the system del self.system.ele_map
def _load_mpi_inters(self, rallocs, mesh, elemap): lhsprank = rallocs.prank mpi_inters = proxylist([]) for rhsprank in rallocs.prankconn[lhsprank]: rhsmrank = rallocs.pmrankmap[rhsprank] interarr = mesh['con_p%dp%d' % (lhsprank, rhsprank)] interarr = interarr.astype('U4,i4,i1,i1').tolist() mpiiface = self.mpiinterscls(self.backend, interarr, rhsmrank, rallocs, elemap, self.cfg) mpi_inters.append(mpiiface) return mpi_inters
def _init_reg_banks(self): # Multi-p requires three additional storage registers self._mgregs, self._regidx = {}, list(range(self.nreg + 3)) self._mgidxcurr = dict.fromkeys(self.levels, 0) # Create a proxylist of matrix-banks for each storage register self._mgregs = { l: [ proxylist( self.backend.matrix_bank(em, i) for em in sys.ele_banks) for i in self._regidx ] for l, sys in self._mgsystems.items() }
def _load_eles(self, rallocs, mesh, initsoln, nregs, nonce): basismap = {b.name: b for b in subclasses(BaseShape, just_leaf=True)} # Look for and load each element type from the mesh elemap = {} for f in mesh: m = re.match(f'spt_(.+?)_p{rallocs.prank}$', f) if m: # Element type t = m.group(1) elemap[t] = self.elementscls(basismap[t], mesh[f], self.cfg) # Construct a proxylist to simplify collective operations eles = proxylist(elemap.values()) # Set the initial conditions if initsoln: # Load the config and stats files from the solution solncfg = Inifile(initsoln['config']) solnsts = Inifile(initsoln['stats']) # Get the names of the conserved variables (fields) solnfields = solnsts.get('data', 'fields', '') currfields = ','.join(eles[0].convarmap[eles[0].ndims]) # Ensure they match up if solnfields and solnfields != currfields: raise RuntimeError('Invalid solution for system') # Process the solution for etype, ele in elemap.items(): soln = initsoln[f'soln_{etype}_p{rallocs.prank}'] ele.set_ics_from_soln(soln, solncfg) else: eles.set_ics_from_cfg() # Allocate these elements on the backend for etype, ele in elemap.items(): k = f'spt_{etype}_p{rallocs.prank}' try: curved = ~mesh[k, 'linear'] linoff = np.max(*np.nonzero(curved), initial=-1) + 1 except KeyError: linoff = ele.neles ele.set_backend(self.backend, nregs, nonce, linoff) return eles, elemap
def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg): super().__init__(backend, rallocs, mesh, initsoln, cfg) # Get the pseudo-integrator self.pseudointegrator = get_pseudo_integrator(backend, systemcls, rallocs, mesh, initsoln, cfg, self.stepper_coeffs, self._dt) # Event handlers for advance_to self.completed_step_handlers = proxylist(self._get_plugins()) # Delete the memory-intensive elements map from the system del self.system.ele_map
def __init__(self, *args, **kwargs): super(BaseStepper, self).__init__(*args, **kwargs) backend = self.backend elemats = self._system.ele_banks # Create a proxylist of matrix-banks for each storage register self._regs = regs = [] self._regidx = regidx = [] for i in xrange(self._stepper_nregs): b = proxylist([backend.matrix_bank(em, i) for em in elemats]) regs.append(b) regidx.append(i) # Add kernel cache self._axnpby_kerns = {}
def __init__(self, *args, **kwargs): super(BaseStepper, self).__init__(*args, **kwargs) backend = self._backend elemats = self._system.ele_banks # Create a proxylist of matrix-banks for each storage register self._regs = regs = [] self._regidx = regidx = [] for i in xrange(self._stepper_nregs): b = proxylist([backend.matrix_bank(em, i) for em in elemats]) regs.append(b) regidx.append(i) # Add kernel cache self._axnpby_kerns = {}
def __init__(self, *args, **kwargs): super(BaseController, self).__init__(*args, **kwargs) # Current and minimum time steps self._dt = self._cfg.getfloat('solver-time-integrator', 'dt') self._dtmin = 1.0e-14 # Bank index of solution self._idxcurr = 0 # Accepted and rejected step counters self.nacptsteps = 0 self.nrjctsteps = 0 self.nacptchain = 0 # Event handlers for advance_to self.completed_step_handlers = proxylist([])
def _load_eles(self, rallocs, mesh, initsoln, nregs, nonce): basismap = {b.name: b for b in subclasses(BaseShape, just_leaf=True)} # Look for and load each element type from the mesh elemap = OrderedDict() for f in mesh: m = re.match('spt_(.+?)_p{0}$'.format(rallocs.prank), f) if m: # Element type t = m.group(1) elemap[t] = self.elementscls(basismap[t], mesh[f], self.cfg) # Construct a proxylist to simplify collective operations eles = proxylist(elemap.values()) # Set the initial conditions if initsoln: # Load the config and stats files from the solution solncfg = Inifile(initsoln['config']) solnsts = Inifile(initsoln['stats']) # Get the names of the conserved variables (fields) solnfields = solnsts.get('data', 'fields', '') currfields = ','.join(eles[0].convarmap[eles[0].ndims]) # Ensure they match up if solnfields and solnfields != currfields: raise RuntimeError('Invalid solution for system') # Process the solution for etype, ele in elemap.items(): soln = initsoln['soln_{0}_p{1}'.format(etype, rallocs.prank)] ele.set_ics_from_soln(soln, solncfg) else: eles.set_ics_from_cfg() # Compute the index of first strictly interior element intoffs = self._compute_int_offsets(rallocs, mesh) # Allocate these elements on the backend for etype, ele in elemap.items(): ele.set_backend(self.backend, nregs, nonce, intoffs[etype]) return eles, elemap
def _load_bc_inters(self, rallocs, mesh): bcmap = subclass_map(self.bbcinterscls, 'type') self._bc_inters = proxylist([]) for f in mesh: m = re.match('bcon_(.+?)_p%d' % rallocs.prank, f) if m: # Get the region name rgn = m.group(1) # Determine the config file section cfgsect = 'soln-bcs-%s' % rgn # Instantiate bcclass = bcmap[self._cfg.get(cfgsect, 'type')] bciface = bcclass(self._backend, mesh[f], self._elemaps, cfgsect, self._cfg) self._bc_inters.append(bciface)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Current and minimum time steps self._dt = self.cfg.getfloat('solver-time-integrator', 'dt') self.dtmin = 1.0e-12 # Solution filtering frequency self._fnsteps = self.cfg.getint('soln-filter', 'nsteps', '0') # Bank index of solution self._idxcurr = 0 # Solution cache self._curr_soln = None # Accepted and rejected step counters self.nacptsteps = 0 self.nrjctsteps = 0 self.nacptchain = 0 # Stats on the most recent step self.stepinfo = [] # Event handlers for advance_to self.completed_step_handlers = proxylist([]) # Record the starting wall clock time self._wstart = time.time() # Load any plugins specified in the config file for s in self.cfg.sections(): m = re.match('soln-plugin-(.+?)(?:-(.+))?$', s) if m: cfgsect, name, suffix = m.group(0), m.group(1), m.group(2) # Instantiate plugin = get_plugin(name, self, cfgsect, suffix) # Register as an event handler self.completed_step_handlers.append(plugin) # Delete the memory-intensive elements map from the system del self.system.ele_map
def _load_eles(self, rallocs, mesh, initsoln, nreg): basismap = {b.name: b for b in subclasses(BaseShape, just_leaf=True)} # Look for and load each element type from the mesh elemap = OrderedDict() for f in mesh: m = re.match('spt_(.+?)_p%d$' % rallocs.prank, f) if m: # Element type t = m.group(1) elemap[t] = self.elementscls(basismap[t], mesh[f], self.cfg) # Construct a proxylist to simplify collective operations eles = proxylist(elemap.values()) # Set the initial conditions either from a pyfrs file or from # explicit expressions in the config file if initsoln: # Load the config and stats files from the solution solncfg = Inifile(initsoln['config']) solnsts = Inifile(initsoln['stats']) # Get the names of the conserved variables (fields) solnfields = solnsts.get('data', 'fields', '') currfields = ','.join(eles[0].convarmap[eles[0].ndims]) # Ensure they match up if solnfields and solnfields != currfields: raise RuntimeError('Invalid solution for system') # Process the solution for k, ele in elemap.items(): soln = initsoln['soln_%s_p%d' % (k, rallocs.prank)] ele.set_ics_from_soln(soln, solncfg) else: eles.set_ics_from_cfg() # Allocate these elements on the backend eles.set_backend(self.backend, nreg) return eles, elemap
def _load_bc_inters(self, rallocs, mesh, elemap): bccls = self.bbcinterscls bcmap = {b.type: b for b in subclasses(bccls, just_leaf=True)} bc_inters = proxylist([]) for f in mesh: if (m := re.match(f'bcon_(.+?)_p{rallocs.prank}$', f)): # Get the region name rgn = m.group(1) # Determine the config file section cfgsect = f'soln-bcs-{rgn}' # Get the interface interarr = mesh[f].astype('U4,i4,i1,i2').tolist() # Instantiate bcclass = bcmap[self.cfg.get(cfgsect, 'type')] bciface = bcclass(self.backend, interarr, elemap, cfgsect, self.cfg) bc_inters.append(bciface)
def _load_bc_inters(self, rallocs, mesh, elemap): bccls = self.bbcinterscls bcmap = {b.type: b for b in subclasses(bccls, just_leaf=True)} bc_inters = proxylist([]) for f in mesh: m = re.match('bcon_(.+?)_p%d$' % rallocs.prank, f) if m: # Get the region name rgn = m.group(1) # Determine the config file section cfgsect = 'soln-bcs-%s' % rgn # Instantiate bcclass = bcmap[self._cfg.get(cfgsect, 'type')] bciface = bcclass(self._backend, mesh[f], elemap, cfgsect, self._cfg) bc_inters.append(bciface) return bc_inters
def _load_bc_inters(self, rallocs, mesh, elemap): bccls = self.bbcinterscls bcmap = {b.type: b for b in subclasses(bccls, just_leaf=True)} bc_inters = proxylist([]) for f in mesh: m = re.match('bcon_(.+?)_p%d$' % rallocs.prank, f) if m: # Get the region name rgn = m.group(1) # Determine the config file section cfgsect = 'soln-bcs-%s' % rgn # Instantiate bcclass = bcmap[self._cfg.get(cfgsect, 'type')] bciface = bcclass(self._backend, mesh[f].tolist(), elemap, cfgsect, self._cfg) bc_inters.append(bciface) return bc_inters
def __init__(self, kernels): self._kernels = proxylist(kernels)
def __init__(self, kernels): self._kernels = proxylist(kernels)
def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg): self.backend = backend self.rallocs = rallocs self.isrestart = initsoln is not None self.cfg = cfg self.prevcfgs = {f: initsoln[f] for f in initsoln or [] if f.startswith('config-')} # Ensure the system is compatible with our formulation if self.formulation not in systemcls.elementscls.formulations: raise RuntimeError( 'System {0} does not support time stepping formulation {1}' .format(systemcls.name, self.formulation) ) # Start time self.tstart = cfg.getfloat('solver-time-integrator', 'tstart', 0.0) self.tend = cfg.getfloat('solver-time-integrator', 'tend') # Current time; defaults to tstart unless restarting if self.isrestart: stats = Inifile(initsoln['stats']) self.tcurr = stats.getfloat('solver-time-integrator', 'tcurr') else: self.tcurr = self.tstart # List of target times to advance to self.tlist = deque([self.tend]) # Accepted and rejected step counters self.nacptsteps = 0 self.nrjctsteps = 0 self.nacptchain = 0 # Current and minimum time steps self._dt = self.cfg.getfloat('solver-time-integrator', 'dt') self.dtmin = 1.0e-12 # Determine the amount of temp storage required by this method nreg = self._stepper_nregs # Construct the relevant mesh partition self.system = systemcls(backend, rallocs, mesh, initsoln, nreg, cfg) # Storage register banks self._regs, self._regidx = self._get_reg_banks(nreg) # Extract the UUID of the mesh (to be saved with solutions) self.mesh_uuid = mesh['mesh_uuid'] # Get a queue for subclasses to use self._queue = backend.queue() # Global degree of freedom count self._gndofs = self._get_gndofs() # Bank index of solution self._idxcurr = 0 # Solution cache self._curr_soln = None # Add kernel cache self._axnpby_kerns = {} # Record the starting wall clock time self._wstart = time.time() # Event handlers for advance_to self.completed_step_handlers = proxylist(self._get_plugins()) # Delete the memory-intensive elements map from the system del self.system.ele_map
class BaseSystem(object): elementscls = None intinterscls = None mpiinterscls = None bbcinterscls = None # Number of queues to allocate _nqueues = None # Nonce sequence _nonce_seq = it.count() def __init__(self, backend, rallocs, mesh, initsoln, nregs, cfg): self.backend = backend self.mesh = mesh self.cfg = cfg # Obtain a nonce to uniquely identify this system nonce = str(next(self._nonce_seq)) # Load the elements eles, elemap = self._load_eles(rallocs, mesh, initsoln, nregs, nonce) backend.commit() # Retain the element map; this may be deleted by clients self.ele_map = elemap # Get the banks, types, num DOFs and shapes of the elements self.ele_banks = list(eles.scal_upts_inb) self.ele_types = list(elemap) self.ele_ndofs = [e.neles * e.nupts * e.nvars for e in eles] self.ele_shapes = [(e.nupts, e.nvars, e.neles) for e in eles] # Get all the solution point locations for the elements self.ele_ploc_upts = [e.ploc_at_np('upts') for e in eles] # I/O banks for the elements self.eles_scal_upts_inb = eles.scal_upts_inb self.eles_scal_upts_outb = eles.scal_upts_outb if hasattr(eles, '_vect_upts'): self.eles_vect_upts = eles._vect_upts # Save the number of dimensions and field variables self.ndims = eles[0].ndims self.nvars = eles[0].nvars # Load the interfaces int_inters = self._load_int_inters(rallocs, mesh, elemap) mpi_inters = self._load_mpi_inters(rallocs, mesh, elemap) bc_inters = self._load_bc_inters(rallocs, mesh, elemap) backend.commit() # Prepare the queues and kernels self._gen_queues() self._gen_kernels(eles, int_inters, mpi_inters, bc_inters) backend.commit() # Save the BC interfaces, but delete the memory-intensive elemap self._bc_inters = bc_inters del bc_inters.elemap def _load_eles(self, rallocs, mesh, initsoln, nregs, nonce): basismap = {b.name: b for b in subclasses(BaseShape, just_leaf=True)} # Look for and load each element type from the mesh elemap = {} for f in mesh: if (m := re.match(f'spt_(.+?)_p{rallocs.prank}$', f)): # Element type t = m.group(1) elemap[t] = self.elementscls(basismap[t], mesh[f], self.cfg) # Construct a proxylist to simplify collective operations eles = proxylist(elemap.values()) # Set the initial conditions if initsoln: # Load the config and stats files from the solution solncfg = Inifile(initsoln['config']) solnsts = Inifile(initsoln['stats']) # Get the names of the conserved variables (fields) solnfields = solnsts.get('data', 'fields', '') currfields = ','.join(eles[0].convarmap[eles[0].ndims]) # Ensure they match up if solnfields and solnfields != currfields: raise RuntimeError('Invalid solution for system') # Process the solution for etype, ele in elemap.items(): soln = initsoln[f'soln_{etype}_p{rallocs.prank}'] ele.set_ics_from_soln(soln, solncfg) else: eles.set_ics_from_cfg() # Allocate these elements on the backend for etype, ele in elemap.items(): k = f'spt_{etype}_p{rallocs.prank}' try: curved = ~mesh[k, 'linear'] linoff = np.max(*np.nonzero(curved), initial=-1) + 1 except KeyError: linoff = ele.neles ele.set_backend(self.backend, nregs, nonce, linoff) return eles, elemap
def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg): self.backend = backend self.rallocs = rallocs self.isrestart = initsoln is not None self.cfg = cfg self.prevcfgs = {f: initsoln[f] for f in initsoln or [] if f.startswith('config-')} # Ensure the system is compatible with our formulation if self.formulation not in systemcls.elementscls.formulations: raise RuntimeError( 'System {0} does not support time stepping formulation {1}' .format(systemcls.name, self.formulation) ) # Start time self.tstart = cfg.getfloat('solver-time-integrator', 'tstart', 0.0) self.tend = cfg.getfloat('solver-time-integrator', 'tend') # Current time; defaults to tstart unless restarting if self.isrestart: stats = Inifile(initsoln['stats']) self.tcurr = stats.getfloat('solver-time-integrator', 'tcurr') else: self.tcurr = self.tstart # List of target times to advance to self.tlist = deque([self.tend]) # Accepted and rejected step counters self.nacptsteps = 0 self.nrjctsteps = 0 self.nacptchain = 0 # Current and minimum time steps self._dt = cfg.getfloat('solver-time-integrator', 'dt') self.dtmin = cfg.getfloat('solver-time-integrator', 'dt-min', 1e-12) # Determine the amount of temp storage required by this method self.nreg = self._stepper_nregs # Construct the relevant mesh partition self._init_system(systemcls, backend, rallocs, mesh, initsoln) # Storage for register banks and current index self._init_reg_banks() # Extract the UUID of the mesh (to be saved with solutions) self.mesh_uuid = mesh['mesh_uuid'] # Get a queue for subclasses to use self._queue = backend.queue() # Global degree of freedom count self._gndofs = self._get_gndofs() # Solution cache self._curr_soln = None # Add kernel cache self._axnpby_kerns = {} # Record the starting wall clock time self._wstart = time.time() # Event handlers for advance_to self.completed_step_handlers = proxylist(self._get_plugins()) # Delete the memory-intensive elements map from the system del self.system.ele_map