def __init__(self, intg, cfgsect, suffix=None): super().__init__(intg, cfgsect, suffix) comm, rank, root = get_comm_rank_root() # Underlying system system = intg.system # Underlying system elements class self.elementscls = system.elementscls # Expressions to integrate c = self.cfg.items_as('constants', float) self.exprs = [ self.cfg.getexpr(cfgsect, k, subs=c) for k in self.cfg.items(cfgsect) if k.startswith('int-') ] # Integration region pre-processing rinfo = self._prepare_region_info(intg) # Gradient pre-processing self._init_gradients(intg, rinfo) # Save a reference to the physical solution point locations self.plocs = system.ele_ploc_upts # Integration parameters self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # The root rank needs to open the output file if rank == root: header = ['t'] + [ k for k in self.cfg.items(cfgsect) if k.startswith('int-') ] # Open self.outf = init_csv(self.cfg, cfgsect, ','.join(header)) # Prepare the per element-type info list self.eleinfo = [] for (ename, eles), (eset, emask) in zip(system.ele_map.items(), rinfo): # Locations of each solution point ploc = eles.ploc_at_np('upts')[..., eset] ploc = ploc.swapaxes(0, 1) # Jacobian determinants rcpdjacs = eles.rcpdjac_at_np('upts')[:, eset] # Quadature weights rname = self.cfg.get(f'solver-elements-{ename}', 'soln-pts') wts = get_quadrule(ename, rname, eles.nupts).wts # Save self.eleinfo.append((ploc, wts[:, None] / rcpdjacs, eset, emask))
def __init__(self, intg, cfgsect, suffix): super().__init__(intg, cfgsect, suffix) comm, rank, root = get_comm_rank_root() # Output frequency self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # The root rank needs to open the output file if rank == root: header = ['t'] + intg.system.elementscls.convarmap[self.ndims] # Open self.outf = init_csv(self.cfg, cfgsect, ','.join(header))
def __init__(self, intg, cfgsect, prefix): super().__init__(intg, cfgsect, prefix) self.flushsteps = self.cfg.getint(self.cfgsect, 'flushsteps', 500) self.count = 0 self.stats = [] self.tprev = intg.tcurr # MPI info comm, rank, root = get_comm_rank_root() # The root rank needs to open the output file if rank == root: self.outf = init_csv(self.cfg, cfgsect, 'n,t,dt,action,error')
def __init__(self, intg, cfgsect, prefix): super().__init__(intg, cfgsect, prefix) self.flushsteps = self.cfg.getint(self.cfgsect, 'flushsteps', 500) self.count = 0 self.stats = [] self.tprev = intg.tcurr # MPI info comm, rank, root = get_comm_rank_root() # The root rank needs to open the output file if rank == root: self.outf = init_csv(self.cfg, cfgsect, 'n,t,dt,action,error') else: self.outf = None
def __init__(self, intg, cfgsect, prefix): super().__init__(intg, cfgsect, prefix) self.flushsteps = self.cfg.getint(self.cfgsect, 'flushsteps', 500) self.count = 0 self.stats = [] self.tprev = intg.tcurr fvars = ','.join(intg.system.elementscls.convarmap[self.ndims]) # MPI info comm, rank, root = get_comm_rank_root() # The root rank needs to open the output file if rank == root: self.outf = init_csv(self.cfg, cfgsect, 'n,t,i,' + fvars) else: self.outf = None
def __init__(self, intg, cfgsect, suffix): super().__init__(intg, cfgsect, suffix) # Underlying elements class self.elementscls = intg.system.elementscls # Output frequency self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # List of points to be sampled and format self.pts = self.cfg.getliteral(cfgsect, 'samp-pts') self.fmt = self.cfg.get(cfgsect, 'format', 'primitive') # MPI info comm, rank, root = get_comm_rank_root() # MPI rank responsible for each point and rank-indexed info self._ptsrank = ptsrank = [] self._ptsinfo = ptsinfo = [[] for i in range(comm.size)] # Physical location of the solution points plocs = [p.swapaxes(1, 2) for p in intg.system.ele_ploc_upts] # Locate the closest solution points in our partition closest = _closest_upts(intg.system.ele_types, plocs, self.pts) # Process these points for cp in closest: # Reduce over the distance _, mrank = comm.allreduce((cp[0], rank), op=get_mpi('minloc')) # Store the rank responsible along with its info ptsrank.append(mrank) ptsinfo[mrank].append( comm.bcast(cp[1:] if rank == mrank else None, root=mrank) ) # If we're the root rank then open the output file if rank == root: self.outf = init_csv(self.cfg, cfgsect, self._header)
def __init__(self, intg, cfgsect, suffix): super().__init__(intg, cfgsect, suffix) # Underlying elements class self.elementscls = intg.system.elementscls # Output frequency self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # List of points to be sampled and format self.pts = self.cfg.getliteral(cfgsect, 'samp-pts') self.fmt = self.cfg.get(cfgsect, 'format', 'primitive') # MPI info comm, rank, root = get_comm_rank_root() # MPI rank responsible for each point and rank-indexed info self._ptsrank = ptsrank = [] self._ptsinfo = ptsinfo = [[] for i in range(comm.size)] # Physical location of the solution points plocs = [p.swapaxes(1, 2) for p in intg.system.ele_ploc_upts] # Locate the closest solution points in our partition closest = _closest_upts(intg.system.ele_types, plocs, self.pts) # Process these points for cp in closest: # Reduce over the distance _, mrank = comm.allreduce((cp[0], rank), op=get_mpi('minloc')) # Store the rank responsible along with its info ptsrank.append(mrank) ptsinfo[mrank].append( comm.bcast(cp[1:] if rank == mrank else None, root=mrank)) # If we're the root rank then open the output file if rank == root: self.outf = init_csv(self.cfg, cfgsect, self._header)
def __init__(self, intg, cfgsect, suffix): super().__init__(intg, cfgsect, suffix) # Underlying elements class self.elementscls = intg.system.elementscls # Output frequency self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # List of points to be sampled and format self.pts = ast.literal_eval(self.cfg.get(cfgsect, 'samp-pts')) self.fmt = self.cfg.get(cfgsect, 'format', 'primitive') # MPI info comm, rank, root = get_comm_rank_root() # MPI rank responsible for each point and rank-indexed info self._ptsrank = ptsrank = [] self._ptsinfo = ptsinfo = [[] for i in range(comm.size)] # Physical location of the solution points plocs = [p.swapaxes(1, 2) for p in intg.system.ele_ploc_upts] for p in self.pts: # Find the nearest point in our partition cp = _closest_upt(intg.system.ele_types, plocs, p) # Reduce over all partitions mcp, mrank = comm.allreduce(cp, op=get_mpi('minloc')) # Store the rank responsible along with the info ptsrank.append(mrank) ptsinfo[mrank].append(mcp[1:]) # If we're the root rank then open the output file if rank == root: self.outf = init_csv(self.cfg, cfgsect, self._header)
def __init__(self, intg, cfgsect, suffix=None): super().__init__(intg, cfgsect, suffix) comm, rank, root = get_comm_rank_root() # Underlying system system = intg.system # Underlying system elements class self.elementscls = system.elementscls # Expressions to integrate c = self.cfg.items_as('constants', float) self.exprs = [ self.cfg.getexpr(cfgsect, k, subs=c) for k in self.cfg.items(cfgsect) if k.startswith('int-') ] # Integration region pre-processing rinfo = self._prepare_region_info(intg) # Gradient pre-processing self._init_gradients(intg, rinfo) # Save a reference to the physical solution point locations self.plocs = system.ele_ploc_upts # Integration parameters self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # The root rank needs to open the output file if rank == root: header = ['t'] + [ k for k in self.cfg.items(cfgsect) if k.startswith('int-') ] # Open self.outf = init_csv(self.cfg, cfgsect, ','.join(header)) # Prepare the per element-type info list self.eleinfo = eleinfo = [] for (ename, eles), (eset, emask) in zip(system.ele_map.items(), rinfo): # Obtain quadrature info rname = self.cfg.get(f'solver-elements-{ename}', 'soln-pts') try: # Quadrature rule (default to that of the solution points) qrule = self.cfg.get(cfgsect, f'quad-pts-{ename}', rname) # Quadrature rule degree try: qdeg = self.cfg.getint(cfgsect, f'quad-deg-{ename}') except NoOptionError: qdeg = self.cfg.getint(cfgsect, 'quad-deg') r = get_quadrule(ename, qrule, qdeg=qdeg) # Interpolation to quadrature points matrix m0 = eles.basis.ubasis.nodal_basis_at(r.pts) except NoOptionError: # Default to the quadrature rule of the solution points r = get_quadrule(ename, rname, eles.nupts) m0 = None # Locations of each quadrature point ploc = eles.ploc_at_np(r.pts).swapaxes(0, 1)[..., eset] # Jacobian determinants at each quadrature point rcpdjacs = eles.rcpdjac_at_np(r.pts)[:, eset] # Save eleinfo.append((ploc, r.wts[:, None] / rcpdjacs, m0, eset, emask))
def __init__(self, intg, cfgsect, suffix): super().__init__(intg, cfgsect, suffix) # Underlying elements class self.elementscls = intg.system.elementscls # Output frequency self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # List of points to be sampled and format self.pts = self.cfg.getliteral(cfgsect, 'samp-pts') self.fmt = self.cfg.get(cfgsect, 'format', 'primitive') # MPI info comm, rank, root = get_comm_rank_root() # MPI rank responsible for each sample point if rank == root: ptsrank = [] # Sample points we're responsible for, grouped by element type elepts = [[] for i in range(len(intg.system.ele_map))] # Search locations in transformed and physical space tlocs, plocs = self._search_pts(intg) # For each sample point find our nearest search location closest = _closest_pts(plocs, self.pts) # Process these points for i, (dist, etype, (uidx, eidx)) in enumerate(closest): # Reduce over the distance _, mrank = comm.allreduce((dist, rank), op=get_mpi('minloc')) # If we have the closest point then save the relevant info if rank == mrank: elepts[etype].append((i, eidx, tlocs[etype][uidx])) # Note what rank is responsible for the point if rank == root: ptsrank.append(mrank) # Refine self._ourpts = ourpts = self._refine_pts(intg, elepts) # Send the refined sample locations to the root rank ptsplocs = comm.gather([pl for et, ei, pl, op in ourpts], root=root) if rank == root: nvars = self.nvars # Allocate a buffer to store the sampled points self._ptsbuf = ptsbuf = np.empty((len(self.pts), self.nvars)) # Tally up how many points each rank is responsible for nptsrank = [len(ploc) for ploc in ptsplocs] # Compute the counts and displacements, sans nvars ptscounts = np.array(nptsrank, dtype=np.int32) ptsdisps = np.cumsum([0] + nptsrank[:-1], dtype=np.int32) # Apply the displacements to each ranks points miters = [ enumerate(ploc, start=pdisp) for ploc, pdisp in zip(ptsplocs, ptsdisps) ] # With this form the final point (offset, location) list self._ptsinfo = [next(miters[pr]) for pr in ptsrank] # Form the MPI Gatherv receive buffer tuple self._ptsrecv = (ptsbuf, (nvars * ptscounts, nvars * ptsdisps)) # Open the output file self.outf = init_csv(self.cfg, cfgsect, self._header) else: self._ptsrecv = None
def __init__(self, intg, cfgsect, suffix): super().__init__(intg, cfgsect, suffix) comm, rank, root = get_comm_rank_root() # Output frequency self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # Check if we need to compute viscous force self._viscous = intg.system.name == 'navier-stokes' # Viscous correction self._viscorr = self.cfg.get('solver', 'viscosity-correction', 'none') # Constant variables self._constants = self.cfg.items_as('constants', float) # Underlying elements class self.elementscls = intg.system.elementscls # Boundary to integrate over bc = 'bcon_{0}_p{1}'.format(suffix, intg.rallocs.prank) # Get the mesh and elements mesh, elemap = intg.system.mesh, intg.system.ele_map # See which ranks have the boundary bcranks = comm.gather(bc in mesh, root=root) # The root rank needs to open the output file if rank == root: if not any(bcranks): raise RuntimeError('Boundary {0} does not exist' .format(suffix)) # CSV header header = ['t', 'px', 'py', 'pz'][:self.ndims + 1] if self._viscous: header += ['vx', 'vy', 'vz'][:self.ndims] # Open self.outf = init_csv(self.cfg, cfgsect, header) # Interpolation matrices and quadrature weights self._m0 = m0 = {} self._qwts = qwts = defaultdict(list) if self._viscous: self._m4 = m4 = {} rcpjact = {} # If we have the boundary then process the interface if bc in mesh: # Element indices and associated face normals eidxs = defaultdict(list) norms = defaultdict(list) for etype, eidx, fidx, flags in mesh[bc].astype('U4,i4,i1,i1'): eles = elemap[etype] if (etype, fidx) not in m0: facefpts = eles.basis.facefpts[fidx] m0[etype, fidx] = eles.basis.m0[facefpts] qwts[etype, fidx] = eles.basis.fpts_wts[facefpts] if self._viscous and etype not in m4: m4[etype] = eles.basis.m4 # Get the smats at the solution points smat = eles.smat_at_np('upts').transpose(2, 0, 1, 3) # Get |J|^-1 at the solution points rcpdjac = eles.rcpdjac_at_np('upts') # Product to give J^-T at the solution points rcpjact[etype] = smat*rcpdjac # Unit physical normals and their magnitudes (including |J|) npn = eles.get_norm_pnorms(eidx, fidx) mpn = eles.get_mag_pnorms(eidx, fidx) eidxs[etype, fidx].append(eidx) norms[etype, fidx].append(mpn[:, None]*npn) self._eidxs = {k: np.array(v) for k, v in eidxs.items()} self._norms = {k: np.array(v) for k, v in norms.items()} if self._viscous: self._rcpjact = {k: rcpjact[k[0]][..., v] for k, v in self._eidxs.items()}
def __init__(self, intg, cfgsect, suffix): super().__init__(intg, cfgsect, suffix) comm, rank, root = get_comm_rank_root() # Output frequency self.nsteps = self.cfg.getint(cfgsect, 'nsteps') # Check if we need to compute viscous force self._viscous = 'navier-stokes' in intg.system.name # Check if the system is incompressible self._ac = intg.system.name.startswith('ac') # Viscous correction self._viscorr = self.cfg.get('solver', 'viscosity-correction', 'none') # Constant variables self._constants = self.cfg.items_as('constants', float) # Underlying elements class self.elementscls = intg.system.elementscls # Boundary to integrate over bc = f'bcon_{suffix}_p{intg.rallocs.prank}' # Moments mcomp = 3 if self.ndims == 3 else 1 self._mcomp = mcomp if self.cfg.hasopt(cfgsect, 'morigin') else 0 if self._mcomp: morigin = np.array(self.cfg.getliteral(cfgsect, 'morigin')) if len(morigin) != self.ndims: raise ValueError(f'morigin must have {self.ndims} components') # Get the mesh and elements mesh, elemap = intg.system.mesh, intg.system.ele_map # See which ranks have the boundary bcranks = comm.gather(bc in mesh, root=root) # The root rank needs to open the output file if rank == root: if not any(bcranks): raise RuntimeError(f'Boundary {suffix} does not exist') # CSV header header = ['t', 'px', 'py', 'pz'][:self.ndims + 1] if self._mcomp: header += ['mpx', 'mpy', 'mpz'][3 - mcomp:] if self._viscous: header += ['vx', 'vy', 'vz'][:self.ndims] if self._mcomp: header += ['mvx', 'mvy', 'mvz'][3 - mcomp:] # Open self.outf = init_csv(self.cfg, cfgsect, ','.join(header)) # Interpolation matrices and quadrature weights self._m0 = m0 = {} self._qwts = qwts = defaultdict(list) if self._viscous: self._m4 = m4 = {} rcpjact = {} # If we have the boundary then process the interface if bc in mesh: # Element indices, associated face normals and relative flux # points position with respect to the moments origin eidxs = defaultdict(list) norms = defaultdict(list) rfpts = defaultdict(list) for etype, eidx, fidx, flags in mesh[bc].astype('U4,i4,i1,i2'): eles = elemap[etype] if (etype, fidx) not in m0: facefpts = eles.basis.facefpts[fidx] m0[etype, fidx] = eles.basis.m0[facefpts] qwts[etype, fidx] = eles.basis.fpts_wts[facefpts] if self._viscous and etype not in m4: m4[etype] = eles.basis.m4 # Get the smats at the solution points smat = eles.smat_at_np('upts').transpose(2, 0, 1, 3) # Get |J|^-1 at the solution points rcpdjac = eles.rcpdjac_at_np('upts') # Product to give J^-T at the solution points rcpjact[etype] = smat * rcpdjac # Unit physical normals and their magnitudes (including |J|) npn = eles.get_norm_pnorms(eidx, fidx) mpn = eles.get_mag_pnorms(eidx, fidx) eidxs[etype, fidx].append(eidx) norms[etype, fidx].append(mpn[:, None] * npn) # Get the flux points position of the given face and element # indices relative to the moment origin if self._mcomp: fpts_idx = eles.basis.facefpts[fidx] rfpt = eles.plocfpts[fpts_idx, eidx] - morigin rfpts[etype, fidx].append(rfpt) self._eidxs = {k: np.array(v) for k, v in eidxs.items()} self._norms = {k: np.array(v) for k, v in norms.items()} self._rfpts = {k: np.array(v) for k, v in rfpts.items()} if self._viscous: self._rcpjact = { k: rcpjact[k[0]][..., v] for k, v in self._eidxs.items() }