def residuals(self, part, facefluxes, celltransient=0., cellsource=0.): """ Calculate FVM residuals Parameters: ----------- facefluxes: vector or None fluxes per unit of surface or None celltransient: float or vector transient term per unit of volume cellsource: float or vector source term per unit of volume Returns: tuple (residuals,FdS) -------- residuals: residuals for each cell, per unit of volume FdS: integral FdS per cell """ assert part is self.mesh.internal or part is self.mesh.boundary idx = part.idx if facefluxes is None: FdS = 0. else: FdS = ad.dot(part.fluxsum, facefluxes) if not ad.isscalar(celltransient): celltransient = celltransient[idx] if not ad.isscalar(cellsource): cellsource = cellsource[idx] return self.idx[idx], -FdS / \ part.cells['volume'] + celltransient - cellsource
def solve_general(self, ctx, eq, fixed): def conc(Ef, numeric_parameters): for s in eq.with_dos: yield s, s.dos.concentrationv(ctx, s, None, Ef, numeric_parameters=numeric_parameters) nfixed = nvalue(fixed) def f(Ef, numeric_parameters=True): if numeric_parameters: charge = nfixed else: charge = fixed for eq, c in conc(Ef, numeric_parameters): charge = charge + c*eq.z return charge bandv = np.asarray([nvalue(ctx.varsOf(s)['Ebandv']) for s in eq.with_dos]) a = np.amax(bandv) b = np.amin(bandv) Ef_value = brent(f, a, b, xtol=self.etol, maxiter=50) g = f(Ef_value, False) if isinstance(g, forward.value): raise NotImplementedError('not tested') dg = f(forward.seed(Ef_value), True).deriv if not isscalar(dg): dg = dg.tocsr().diagonal() # must create value : (Ef_value, 1/dg*g') Ef = custom_function(lambda *args: Ef_value, lambda *args: dg)(g) else: Ef = Ef_value info = dict((id(eq), c) for eq, c in conc(Ef, False)) return Ef, info
def faceaverage(self, x): if isscalar(x): return x else: return (x[self.faces['-']] + x[self.faces['+']]) * 0.5
def cellaveragev(self, x): if isscalar(x): return x return dot(self.cellavg, x)