def _setup_equation(self, biomass_height): height = biomass_height + self._layer_height size = height * self._layer mesh = self.space.construct_mesh(height) variables, terms = [], [] phi = CellVariable(name=self.solute.name, mesh=mesh, hasOld=True) for r in self.reactions: variables.append( CellVariable(name=f"{r.bacteria.name}_rate", mesh=mesh, value=0.0)) terms.append( ImplicitSourceTerm(coeff=(variables[-1] / (phi + self._sr)))) equation = DiffusionTerm(coeff=self.diffusivity) - sum(terms) phi.constrain(1, where=mesh.facesTop) for var, coef in zip( variables, [r.rate_coefficient()[:size] for r in self.reactions]): try: var.setValue(coef / self.space.dV) except ValueError as err: print("Boundary layer height greater than system size") raise err phi.setValue(self.solute.value.reshape(-1)[:size]) return equation, phi, size
def setup(self, ncell): m = Grid1D(nx=ncell, Lx=1.) v = CellVariable(mesh=m, hasOld=True, value=[[0.5], [0.5]], elementshape=(2,)) v.constrain([[0], [1]], m.facesLeft) v.constrain([[1], [0]], m.facesRight) eqn = TransientTerm([[1,0], [0,1]]) == DiffusionTerm([[[0.01, -1], [1, 0.01]]]) self.v = v self.eqn = eqn for step in range(2): self.time_step()
def solve_pde( xmin, # domain min xmax, # domain max Tmax, # time max theta=1, # dynamics drift mu=0, # dynamics stable level sigma=1, # dynamics noise dx=0.01, # space discretization dt=0.01, # time discretization gbm=False): # state-dependent drift mesh = Grid1D(dx=dx, nx=(xmax - xmin) / dx) + xmin Tsteps = int(Tmax / dt) + 1 x_face = mesh.faceCenters x_cell = mesh.cellCenters[0] V = CellVariable(name="V", mesh=mesh, value=0.) # PDE if gbm: eq = TransientTerm( var=V) == (DiffusionTerm(coeff=float(sigma) * sigma / 2, var=V) - UpwindConvectionTerm( coeff=float(theta) * (x_face - float(mu)), var=V) + V * (float(theta) - x_cell)) else: eq = TransientTerm( var=V) == (DiffusionTerm(coeff=float(sigma) * sigma / 2, var=V) - UpwindConvectionTerm(coeff=float(theta) * (x_face - float(mu)), var=V) + V * float(theta)) # Boundary conditions V.constrain(1., mesh.facesRight) V.faceGrad.constrain([0.], mesh.facesLeft) # Solve by stepping in time sol = np.zeros((Tsteps, mesh.nx)) for step in range(Tsteps): eq.solve(var=V, dt=dt) sol[step] = V.value X = mesh.cellCenters.value[0] T = dt * np.arange(Tsteps) return T, X, sol
potential = CellVariable(mesh=mesh, name='Potential', value=y03(mesh.x)) Jp = CellVariable(mesh=mesh, name='Positive ion Current Density', value=0.) Jn = CellVariable(mesh=mesh, name='Negative ion Current Density', value=0.) Jp.value = -mu_p * Pion * potential.arithmeticFaceValue.divergence + Dn * Pion.arithmeticFaceValue.divergence Jn.value = -mu_n * Nion * potential.arithmeticFaceValue.divergence + Dn * Pion.arithmeticFaceValue.divergence Pion.equation = TransientTerm( coeff=1, var=Pion) == -k_rec * Pion * Nion + (Jp.arithmeticFaceValue).divergence Nion.equation = TransientTerm( coeff=1, var=Nion) == -k_rec * Pion * Nion - (Jn.arithmeticFaceValue).divergence potential.equation = DiffusionTerm(coeff=epsilon, var=potential) == Pion - Nion Pion.constrain(0., where=mesh.facesLeft) Pion.constrain(0., where=mesh.facesRight) Nion.constrain(0., where=mesh.facesLeft) Nion.constrain(0., where=mesh.facesRight) potential.constrain(0., where=mesh.facesLeft) potential.constrain(0., where=mesh.facesRight) eq = Pion.equation & Nion.equation & potential.equation steps = 253 dt = 6 if __name__ == "__main__": viewer = Viewer(vars=(Nion, ), datamin=-1e15, datamax=1e15) for steps in range(steps):
Plane Surface(3) = {3}; Physical Line("Ground") = {4, 5, 6}; Physical Surface("Field") = {1}; Physical Surface("Anode") = {2}; Physical Surface("Cathode") = {3}; """ for refinement in range(10): mesh = Gmsh2D(geo, background=monitor) charge = CellVariable(mesh=mesh, name=r"$\rho$", value=0.) charge.setValue(+1, where=mesh.physicalCells["Anode"]) charge.setValue(-1, where=mesh.physicalCells["Cathode"]) potential = CellVariable(mesh=mesh, name=r"$\psi$") potential.constrain(0., where=mesh.physicalFaces["Ground"]) eq = DiffusionTerm(coeff=1.) == -charge res0 = eq.sweep(var=potential) res = eq.justResidualVector(var=potential) res1 = numerix.L2norm(res) res1a = CellVariable(mesh=mesh, value=abs(res)) res = CellVariable(mesh=mesh, name="residual", value=abs(res) / mesh.cellVolumes**(1./mesh.dim) / 1e-3) # want cells no bigger than 1 and no smaller than 0.001 maxSize = 1. minSize = 0.001
potential.equation = DiffusionTerm( coeff=1, var=potential) == (-q / epsilon) * (Pion + Nion) ################################################################ ##################''' BOUNDARY CONDITIONS '''################### ################################################################ Pion.faceGrad.constrain( 0., where=mesh.exteriorFaces) #dPion/dx = 0 at the exterior faces of the mesh Nion.faceGrad.constrain( 0., where=mesh.exteriorFaces) #dNion/dx = 0 at the exterior faces of the mesh potential.constrain( 0., where=mesh.exteriorFaces) #potential = 0 at the exterior faces of the mesh ################################################################ #################''' SOLVE EQUATIONS '''######################## ################################################################ eq = Pion.equation & Nion.equation & potential.equation #Couple all of the equations together steps = 100 #How many time steps to take dt = 1 #How long each time step is in seconds if __name__ == "__main__": #viewer = Viewer(vars=(potential,),datamin=-1.1,datamax=1.1) #Sets up viewer for the potential with y-axis limits viewer = Viewer( vars=(Pion, ), datamin=0, datamax=1e21
mesh = Grid3D(dx=dx, dy=dy, dz=dz, nx=nx, ny=ny, nz=nz) var = CellVariable(name="variable", mesh=mesh, value=valueSides) ##viewer1 = Grid3DPyxViewer(var, zvalue = 1.0) ##viewer3 = Grid3DPyxViewer(var, zvalue = 3.0) ##viewer5 = Grid3DPyxViewer(var, zvalue = 5.0) ##viewer7 = Grid3DPyxViewer(var, zvalue = 7.0) ##viewer9 = Grid3DPyxViewer(var, zvalue = 9.0) ## viewer = Viewer(vars = var) ## viewer.plot() var.constrain(valueSides, mesh.facesLeft) var.constrain(valueSides, mesh.facesRight) var.constrain(valueSides, mesh.facesTop) var.constrain(valueSides, mesh.facesBottom) var.constrain(valueFront, mesh.facesFront) var.constrain(valueBack, mesh.facesBack) ## viewer.plot() if __name__ == '__main__': ##viewer1.plot(resolution = 0.2, xlabel = "X values (Z value = 1)", minval = valueFront, maxval = valueBack) ##raw_input("press enter to continue") ##viewer3.plot(resolution = 0.2, xlabel = "X values (Z value = 3)", minval = valueFront, maxval = valueBack) ##raw_input("press enter to continue") ##viewer5.plot(resolution = 0.2, xlabel = "X values (Z value = 5)", minval = valueFront, maxval = valueBack) ##raw_input("press enter to continue")
distanceVar = DistanceVariable(mesh = mesh, value = value, hasOld = 1) ## Build the bulk diffusion equation bulkVar = CellVariable(mesh = mesh, value = cinf) surfactantVar = SurfactantVariable(distanceVar = distanceVar) from .surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation bulkEqn = buildSurfactantBulkDiffusionEquation(bulkVar, distanceVar = distanceVar, surfactantVar = surfactantVar, diffusionCoeff = diffusion, rateConstant = rateConstant * siteDensity) bulkVar.constrain(cinf, mesh.facesRight) ## Build the surfactant equation surfEqn = AdsorbingSurfactantEquation(surfactantVar = surfactantVar, distanceVar = distanceVar, bulkVar = bulkVar, rateConstant = rateConstant) ## Build the analytical solutions, x = mesh.cellCenters[0, 1:] - dx def concentrationFunc(theta): tmp = (1 + rateConstant * siteDensity * (1 - theta) * L / diffusion) return cinf * (1 + rateConstant * siteDensity * (1 - theta) * x / diffusion) / tmp
def runSimpleTrenchSystem(faradaysConstant=9.6e4, gasConstant=8.314, transferCoefficient=0.5, rateConstant0=1.76, rateConstant3=-245e-6, catalystDiffusion=1e-9, siteDensity=9.8e-6, molarVolume=7.1e-6, charge=2, metalDiffusion=5.6e-10, temperature=298., overpotential=-0.3, metalConcentration=250., catalystConcentration=5e-3, catalystCoverage=0., currentDensity0=0.26, currentDensity1=45., cellSize=0.1e-7, trenchDepth=0.5e-6, aspectRatio=2., trenchSpacing=0.6e-6, boundaryLayerDepth=0.3e-6, numberOfSteps=5, displayViewers=True): cflNumber = 0.2 numberOfCellsInNarrowBand = 10 cellsBelowTrench = 10 yCells = cellsBelowTrench \ + int((trenchDepth + boundaryLayerDepth) / cellSize) xCells = int(trenchSpacing / 2 / cellSize) from fipy.tools import serialComm mesh = Grid2D(dx = cellSize, dy = cellSize, nx = xCells, ny = yCells, communicator=serialComm) narrowBandWidth = numberOfCellsInNarrowBand * cellSize distanceVar = DistanceVariable( name = 'distance variable', mesh = mesh, value = -1., hasOld = 1) bottomHeight = cellsBelowTrench * cellSize trenchHeight = bottomHeight + trenchDepth trenchWidth = trenchDepth / aspectRatio sideWidth = (trenchSpacing - trenchWidth) / 2 x, y = mesh.cellCenters distanceVar.setValue(1., where=(y > trenchHeight) | ((y > bottomHeight) & (x < xCells * cellSize - sideWidth))) distanceVar.calcDistanceFunction(order=2) catalystVar = SurfactantVariable( name = "catalyst variable", value = catalystCoverage, distanceVar = distanceVar) bulkCatalystVar = CellVariable( name = 'bulk catalyst variable', mesh = mesh, value = catalystConcentration) metalVar = CellVariable( name = 'metal variable', mesh = mesh, value = metalConcentration) expoConstant = -transferCoefficient * faradaysConstant / (gasConstant * temperature) tmp = currentDensity1 * catalystVar.interfaceVar exchangeCurrentDensity = currentDensity0 + tmp expo = numerix.exp(expoConstant * overpotential) currentDensity = expo * exchangeCurrentDensity * metalVar / metalConcentration depositionRateVariable = currentDensity * molarVolume / (charge * faradaysConstant) extensionVelocityVariable = CellVariable( name = 'extension velocity', mesh = mesh, value = depositionRateVariable) surfactantEquation = AdsorbingSurfactantEquation( surfactantVar = catalystVar, distanceVar = distanceVar, bulkVar = bulkCatalystVar, rateConstant = rateConstant0 + rateConstant3 * overpotential**3) advectionEquation = TransientTerm() + AdvectionTerm(extensionVelocityVariable) metalEquation = buildMetalIonDiffusionEquation( ionVar = metalVar, distanceVar = distanceVar, depositionRate = depositionRateVariable, diffusionCoeff = metalDiffusion, metalIonMolarVolume = molarVolume, ) metalVar.constrain(metalConcentration, mesh.facesTop) from .surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation bulkCatalystEquation = buildSurfactantBulkDiffusionEquation( bulkVar = bulkCatalystVar, distanceVar = distanceVar, surfactantVar = catalystVar, diffusionCoeff = catalystDiffusion, rateConstant = rateConstant0 * siteDensity ) bulkCatalystVar.constrain(catalystConcentration, mesh.facesTop) if displayViewers: try: from .mayaviSurfactantViewer import MayaviSurfactantViewer viewer = MayaviSurfactantViewer(distanceVar, catalystVar.interfaceVar, zoomFactor = 1e6, datamax=0.5, datamin=0.0, smooth = 1, title = 'catalyst coverage') except: viewer = MultiViewer(viewers=( Viewer(distanceVar, datamin=-1e-9, datamax=1e-9), Viewer(catalystVar.interfaceVar))) else: viewer = None levelSetUpdateFrequency = int(0.8 * narrowBandWidth \ / (cellSize * cflNumber * 2)) for step in range(numberOfSteps): if step>5 and step % 5 == 0 and viewer is not None: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction(order=2) extensionVelocityVariable.setValue(depositionRateVariable()) distanceVar.updateOld() distanceVar.extendVariable(extensionVelocityVariable, order=2) dt = cflNumber * cellSize / extensionVelocityVariable.max() advectionEquation.solve(distanceVar, dt = dt) surfactantEquation.solve(catalystVar, dt = dt) metalEquation.solve(metalVar, dt = dt) bulkCatalystEquation.solve(bulkCatalystVar, dt = dt, solver=GeneralSolver(tolerance=1e-15, iterations=2000)) try: import os filepath = os.path.splitext(__file__)[0] + '.gz' print(catalystVar.allclose(numerix.loadtxt(filepath), rtol = 1e-4)) except: return 0
def solve_Te(Qe_tot=2e6, H0=0, Hw=0.1, Te_bc=100, chi=1, a0=1, R0=3, E0=1.5, b_pos=0.98, b_height=6e19, b_sol=2e19, b_width=0.01, b_slope=0.01, nr=100, dt=100, plots=True): """ :param Qe_tot: heating power [W] :type Qe_tot: numpy float :param H0: position of Gaussian [-] :type H0: numpy float :param Hw: width of Gaussian [-] :type Hw: numpy float :param Te_bc: outer edge Te boundary condition [eV] :type Te_bc: numpy float :param chi: thermal diffusivity [?] :type chi: numpy float :param a0: minor radius [m] :type a0: numpy float :param R0: major radius [m] :type R0: numpy float :param E0: ellipticity :type E0: numpy float :param b_pos: position of density pedestal [-] :type b_pos: numpy float :param b_height: height of density pedestal [m^-3] :type b_height: numpy float :param b_sol: sol value for density pedestal [m^-3] :type b_sol: numpy float :param b_width: width of density pedestal [-] :type b_width: numpy float :param b_slope: slope of density pedestal [?] :type b_slope: numpy float :param nr: number of radial grid points :type nr: inteher :param dt: time-step [s] :type dt: numpy float :param plots: enable plots :type plots: boolean :return: array of Te values [eV] :type: numpy float array :return: array of ne values [m^-3] :type: numpy float array :return: rho values corresponding to the Te and ne values [m] :type: numpy float array :return: rho_norm values corresponding to the Te and ne values [-] :type: numpy float array [email protected] """ if plots: import os import matplotlib if not os.getenv("DISPLAY"): matplotlib.use('Agg') import matplotlib.pylab as plt import scipy.constants from fipy import Variable, FaceVariable, CellVariable, TransientTerm, DiffusionTerm, Viewer, meshes a = a0 * np.sqrt(E0) V = 2 * np.pi * 2 * np.pi * R0 mesh = meshes.CylindricalGrid1D(nr=nr, Lr=a) Te = CellVariable(name="Te", mesh=mesh, value=1e3) ne = CellVariable(name="ne", mesh=mesh, value=F_ped(mesh.cellCenters.value[0] / a, b_pos, b_height, b_sol, b_width, b_slope)) Qe = CellVariable(name="Qe", mesh=mesh, value=np.exp(-((mesh.cellCenters.value / a - H0) / (Hw))**2)[0]) Qe = Qe * Qe_tot / ((mesh.cellVolumes * Qe.value).sum() * V) print('Volume = %s m^3' % (mesh.cellVolumes.sum() * V)) print('Heating power = %0.3e W' % ((mesh.cellVolumes * Qe).sum() * V)) Te.constrain(Te_bc, mesh.facesRight) eqI = TransientTerm( coeff=scipy.constants.e * ne * 1.5) == DiffusionTerm(coeff=scipy.constants.e * ne * chi) + Qe if plots: viewer = Viewer(vars=(Te), title='Heating power = %0.3e W\nchi = %s' % (Qe.cellVolumeAverage.value * V, chi), datamin=0, datamax=5000) eqI.solve(var=Te, dt=dt) if plots: viewer.plot() return Te.value, ne.value, mesh.cellCenters.value[ 0], mesh.cellCenters.value[0] / a
from fipy import Grid1D, CellVariable, TransientTerm, DiffusionTerm, Viewer m = Grid1D(nx=100, Lx=1.) v0 = CellVariable(mesh=m, hasOld=True, value=0.5) v1 = CellVariable(mesh=m, hasOld=True, value=0.5) v0.constrain(0, m.facesLeft) v0.constrain(1, m.facesRight) v1.constrain(1, m.facesLeft) v1.constrain(0, m.facesRight) eq0 = TransientTerm() == DiffusionTerm(coeff=0.01) - v1.faceGrad.divergence eq1 = TransientTerm() == v0.faceGrad.divergence + DiffusionTerm(coeff=0.01) vi = Viewer((v0, v1)) for t in range(100): v0.updateOld() v1.updateOld() res0 = res1 = 1e100 while max(res0, res1) > 0.1: res0 = eq0.sweep(var=v0, dt=1e-5) res1 = eq1.sweep(var=v1, dt=1e-5) if t % 10 == 0: vi.plot() # eqn0 = TransientTerm(var=v0) == DiffusionTerm(0.01, var=v0) - DiffusionTerm(1, var=v1) # eqn1 = TransientTerm(var=v1) == DiffusionTerm(1, var=v0) + DiffusionTerm(0.01, var=v1)
def icivir_cuboid_solve(self): # step 2: Equation phi = CellVariable(mesh=self.mesh, name='potential phi', value=0.) eqn = (DiffusionTerm(coeff=1.) == 0.) # step 3: Boundary conditions # compute flow of 8 vertexes # one vertex has 3 components of wind vector, (x, y, z) vertexWindVec = np.array([[0.0 for i in range(3)] for i in range(8)]) for i in range(8): # 8 vertexes for j in range(3): # 3 components vertexWindVec[i, j] = self.mean_flow[j] \ + self.colored_noise(self.vertexWindVecRanInc[i][j]) # save these 8 vector for interp wind of edge area for plume sim self.wind_at_vertex = vertexWindVec #print 'vertexWindVec = ' + str(vertexWindVec) # interpolate flow vector on sim area faces, and set neumann boundary # conditions, because /grad /phi = V(x,y,z) # /grad /phi array, of points of mesh face centers # grad_phi_bc[0, :] /grad/phi_x # grad_phi_bc[1, :] /grad/phi_y # grad_phi_bc[2, :] /grad/phi_z grad_phi_bc = np.zeros_like(self.mesh.faceCenters()) # p: points on one face to interpolate, 2 dimension # vx, vy: x&y components of interpolated wind vectors of points list p # vertex index, for interpolate bc on 6 faces # vertexIndex[0] = [0,1,4,5], down face, 0<x<nx*dx, y=0, 0<z<nz*dz # vertexIndex[1] = [0,2,4,6], left face, x=0, 0<y<ny*dy, 0<z<nz*dz # vertexIndex[2] = [2,3,6,7], up face, 0<x<nx*dx, y=ny*dy, 0<z<nz*dz # vertexIndex[3] = [1,3,5,7], right face, x=nx*dx, 0<y<ny*dy, 0<z<nz*dz # vertexIndex[4] = [0,1,2,3], front face, 0<x<nx*dx, 0<y<ny*dy, z=0 # vertexIndex[5] = [4,5,6,7], back face, 0<x<nx*dx, 0<y<ny*dy, z=nz*dz # write vertexIndex as mask type vertexMask = np.array([ \ [True, True, False, False, True, True, False, False], [True, False, True, False, True, False, True, False], [False, False, True, True, False, False, True, True], [False, True, False, True, False, True, False, True], [True, True, True, True, False, False, False, False], [False, False, False, False, True, True, True, True] ]) xyz_index = np.array([[0, 2], [1, 2], [0, 2], [1, 2], [0, 1], [0, 1]]) for i in range(6): # 6 faces for 3D cuboid area p1, p2 = np.mgrid[self.gsize/2:self.gsize*self.xyz_n[xyz_index[i,0]]:self.gsize, \ self.gsize/2:self.gsize*self.xyz_n[xyz_index[i,1]]:self.gsize] vx = griddata(zip(\ [0, self.gsize*self.xyz_n[xyz_index[i,0]], 0, self.gsize*self.xyz_n[xyz_index[i,0]]],\ [0, 0, self.gsize*self.xyz_n[xyz_index[i,1]], self.gsize*self.xyz_n[xyz_index[i,1]]]),\ vertexWindVec[vertexMask[i],0], (p1, p2), method='linear').T.reshape(1,-1)[0] vy = griddata(zip(\ [0, self.gsize*self.xyz_n[xyz_index[i,0]], 0, self.gsize*self.xyz_n[xyz_index[i,0]]],\ [0, 0, self.gsize*self.xyz_n[xyz_index[i,1]], self.gsize*self.xyz_n[xyz_index[i,1]]]),\ vertexWindVec[vertexMask[i],1], (p1, p2), method='linear').T.reshape(1,-1)[0] vz = griddata(zip(\ [0, self.gsize*self.xyz_n[xyz_index[i,0]], 0, self.gsize*self.xyz_n[xyz_index[i,0]]],\ [0, 0, self.gsize*self.xyz_n[xyz_index[i,1]], self.gsize*self.xyz_n[xyz_index[i,1]]]),\ vertexWindVec[vertexMask[i],2], (p1, p2), method='linear').T.reshape(1,-1)[0] if i == 0: # down boundary grad_phi_bc[:, self.mesh.facesDown()] = np.array([vx, vy, vz]) elif i == 1: # left boundary grad_phi_bc[:, self.mesh.facesLeft()] = np.array([vx, vy, vz]) elif i == 2: # up boundary grad_phi_bc[:, self.mesh.facesUp()] = np.array([vx, vy, vz]) elif i == 3: # right boundary grad_phi_bc[:, self.mesh.facesRight()] = np.array([vx, vy, vz]) elif i == 4: # front grad_phi_bc[:, self.mesh.facesFront()] = np.array([vx, vy, vz]) elif i == 5: # back grad_phi_bc[:, self.mesh.facesBack()] = np.array([vx, vy, vz]) #print 'grad_phi_bc[ext] = ' + str(grad_phi_bc[:, self.mesh.exteriorFaces()]) # set neumann boundary condition phi.faceGrad.constrain( ((grad_phi_bc[0]), (grad_phi_bc[1]), (grad_phi_bc[2])), where=self.mesh.exteriorFaces) # set dirichlet boundary condition # set /phi value on one point of a cell, to provide a init value for equaition solver # get all points which lie on the center of faces of cells X, Y, Z = self.mesh.faceCenters mask = ((X == self.gsize / 2) & (Y == self.gsize / 2) & (Z == 0) ) # front face of cell 0 phi.constrain(0, where=self.mesh.exteriorFaces & mask) # step 4: Solve eqn.solve(var=phi) # Post processing # get /phi array self.wind_phi_field = np.array(phi).reshape(self.xyz_n[2], \ self.xyz_n[1], self.xyz_n[0]).T # convert /phi to wind vector self.wind_vector_field = np.array( np.gradient(self.wind_phi_field, self.gsize)) #print 'wind_vector_field = ' + str(self.wind_vector_field) # get cell centers self.wind_mesh_centers = self.mesh.cellCenters()
from fipy import Variable, FaceVariable, CellVariable, Grid1D, ExplicitDiffusionTerm, TransientTerm, DiffusionTerm, Viewer from fipy.tools import numerix nx = 50 dx = 1. mesh = Grid1D(nx=nx, dx=dx) phi = CellVariable(name='sol var', mesh=mesh, value=0., hasOld=False) D = 1. valueleft = 1 valueright = 0 phi.constrain(valueleft, mesh.facesLeft) phi.constrain(valueright, mesh.facesRight) eq = TransientTerm() == DiffusionTerm(coeff=D) timeStepDuration = 1. steps = 10 MAX_SWEEPS = 100 for step in range(steps): res = 0.0 # phi.updateOld() for r in range(MAX_SWEEPS): resOld = res res = eq.sweep(var=phi, dt=timeStepDuration)
Rim = 1.0 # immobile domain retardation coefficient betaT = phiim*Rim/(phim*Rm) DR = D/Rm m = Grid1D(dx=dx, nx=nx) c0 = np.zeros(nx, 'd') c0[20:50] = 1.0 # mobile domain concentration cm = CellVariable(name="$c_m$", mesh=m, value=c0) # immobile domain concentration cim = CellVariable(name="$c_{im}$", mesh=m, value=0.0) cm.constrain(0, m.facesLeft) cm.constrain(0, m.facesRight) cim.constrain(0, m.facesLeft) cim.constrain(0, m.facesRight) # advective flow velocity u = FaceVariable(mesh=m, value=(0.0,), rank=1) # 1D convection diffusion equation (mobile domain) # version with \frac{\partial c_{im}}{\partial t} eqM = (TransientTerm(1.0,var=cm) + TransientTerm(betaT,var=cim) == DiffusionTerm(DR,var=cm) - ExponentialConvectionTerm(u/(Rm*phim),var=cm)) # immobile domain (lumped approach) eqIM = TransientTerm(Rim*phiim,var=cim) == beta/Rim*(cm - ImplicitSourceTerm(1.0,var=cim))
# Physical parameters mm = 4. # anisotropic symmetry epsilon_m = 0.025 # degree of anisotropy theta_0 = 0.0 # tilt w.r.t. x-axis tau_0 = 1. # numerical mobility DD = 10. # thermal diffusivity W_0 = 1. # isotropic well height lamda = DD * tau_0 / 0.6267 / W_0**2 delta = 0.05 # undercooling # Mesh and field variables mesh = Grid2D(nx=nx, ny=ny, dx=dx, dy=dy) phase = CellVariable(mesh=mesh, hasOld=True) uu = CellVariable(mesh=mesh, hasOld=True) uu.constrain(-delta, mesh.exteriorFaces) def initialize(): phase[:] = -1.0 x, y = mesh.cellCenters radius = 2.0 # Initial r=1 collapses due to Gibbs-Thomson, r=2 slumps to phi=0.6, r=4 seems OK. center = (nx * dx / 2., ny * dy / 2.) mask = (x - center[0])**2 + (y - center[1])**2 < radius**2 phase.setValue(1., where=mask) uu[:] = -delta initialize() def make_tau(phase_):
nz = 3 dx = 1. dy = 1. dz = 1. valueBottomTop = 0. valueLeftRight = 1. mesh = Grid3D(dx = dx, dy = dy, dz = dz, nx = nx, ny = ny, nz = nz) var = CellVariable(name = "solution variable", mesh = mesh, value = valueBottomTop) var.constrain(valueLeftRight, mesh.facesLeft) var.constrain(valueLeftRight, mesh.facesRight) var.constrain(valueBottomTop, mesh.facesTop) var.constrain(valueBottomTop, mesh.facesBottom) #do the 2D problem for comparison nx = 8 # FIXME: downsized temporarily from 10 due to https://github.com/usnistgov/fipy/issues/622 ny = 5 dx = 1. dy = 1. mesh2 = Grid2D(dx = dx, dy = dy, nx = nx, ny = ny) var2 = CellVariable(name = "solution variable 2D",
def runGold(faradaysConstant=9.6e4, consumptionRateConstant=2.6e+6, molarVolume=10.21e-6, charge=1.0, metalDiffusion=1.7e-9, metalConcentration=20.0, catalystCoverage=0.15, currentDensity0=3e-2 * 16, currentDensity1=6.5e-1 * 16, cellSize=0.1e-7, trenchDepth=0.2e-6, aspectRatio=1.47, trenchSpacing=0.5e-6, boundaryLayerDepth=90.0e-6, numberOfSteps=10, taperAngle=6.0, displayViewers=True): cflNumber = 0.2 numberOfCellsInNarrowBand = 20 mesh = TrenchMesh(cellSize=cellSize, trenchSpacing=trenchSpacing, trenchDepth=trenchDepth, boundaryLayerDepth=boundaryLayerDepth, aspectRatio=aspectRatio, angle=numerix.pi * taperAngle / 180.) narrowBandWidth = numberOfCellsInNarrowBand * cellSize distanceVar = GapFillDistanceVariable(name='distance variable', mesh=mesh, value=-1.) distanceVar.setValue(1., where=mesh.electrolyteMask) distanceVar.calcDistanceFunction() catalystVar = SurfactantVariable(name="catalyst variable", value=catalystCoverage, distanceVar=distanceVar) metalVar = CellVariable(name='metal variable', mesh=mesh, value=metalConcentration) exchangeCurrentDensity = currentDensity0 + currentDensity1 * catalystVar.interfaceVar currentDensity = metalVar / metalConcentration * exchangeCurrentDensity depositionRateVariable = currentDensity * molarVolume / charge / faradaysConstant extensionVelocityVariable = CellVariable(name='extension velocity', mesh=mesh, value=depositionRateVariable) catalystSurfactantEquation = AdsorbingSurfactantEquation( catalystVar, distanceVar=distanceVar, bulkVar=0, rateConstant=0, consumptionCoeff=consumptionRateConstant * extensionVelocityVariable) advectionEquation = TransientTerm() + FirstOrderAdvectionTerm( extensionVelocityVariable) metalEquation = buildMetalIonDiffusionEquation( ionVar=metalVar, distanceVar=distanceVar, depositionRate=depositionRateVariable, diffusionCoeff=metalDiffusion, metalIonMolarVolume=molarVolume) metalVar.constrain(metalConcentration, mesh.facesTop) if displayViewers: try: from .mayaviSurfactantViewer import MayaviSurfactantViewer viewer = MayaviSurfactantViewer(distanceVar, catalystVar.interfaceVar, zoomFactor=1e6, datamax=1.0, datamin=0.0, smooth=1, title='catalyst coverage', animate=True) except: class PlotVariable(CellVariable): def __init__(self, var=None, name=''): CellVariable.__init__(self, mesh=mesh.fineMesh, name=name) self.var = self._requires(var) def _calcValue(self): return numerix.array(self.var(self.mesh.cellCenters)) viewer = MultiViewer( viewers=(Viewer( PlotVariable( var=distanceVar), datamax=1e-9, datamin=-1e-9), Viewer(PlotVariable(var=catalystVar.interfaceVar)))) else: viewer = None levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2) step = 0 while step < numberOfSteps: if step % 10 == 0 and viewer is not None: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction() extensionVelocityVariable.setValue( numerix.array(depositionRateVariable)) dt = cflNumber * cellSize / max(extensionVelocityVariable.globalValue) distanceVar.extendVariable(extensionVelocityVariable) advectionEquation.solve(distanceVar, dt=dt) catalystSurfactantEquation.solve(catalystVar, dt=dt) metalEquation.solve(metalVar, dt=dt) step += 1 point = ((5e-09, ), (1.15e-07, )) value = 1.45346701e-09 return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0
D_Zohm.setValue((D_max + D_min) / 2.0 + ((D_max - D_min)*numerix.tanh(Z)) / 2.0) # Stap's Model alpha_sup = 0.5 D_Staps.setValue(D_min + (D_max - D_min) / (1.0 + alpha_sup*(Z.grad.mag)**2)) # Flow-Shear Model a1, a2, a3 = 0.7, 1.25, 0.5 D_Shear.setValue(D_min + (D_max - D_min) / (1.0 + a1*Z**2 + a2*Z*(Z.grad) + a3*(Z.grad)**2)) # ----------------- Boundary Conditions ------------------- # Z Boundary Conditions: # d/dx(Z(0,t)) == Z / lambda_Z # mu*D/epsilon * d/dx(Z(L,t)) == 0 # d^2/dx^2(Z(0,t)) == 0 Z.faceGrad.constrain(Z.faceValue / lambda_Z, mesh.facesLeft) Z.constrain(0.0, mesh.facesRight) Z.grad.faceGrad.constrain(0.0, mesh.facesLeft) # ----------------- PDE Declarations ---------------------- #initial_viewer = MatplotlibViewer((D_Zohm, D_Staps, D_Shear), title=r"Diffusivity Models: FiPy", xmin=0.0, xmax=3.0) #pyplot.grid(True) #pyplot.axes().set_aspect('equal') viewer = None if __name__ == '__main__': try: viewer = Viewer(vars=D_Zohm, datamin=0.0, datamax=3.0) viewer.plotMesh()
dx = 1 dy = dx L = dx * nx mesh = Grid2D(dx=dx, dy=dy, nx=nx, ny=ny) phi = CellVariable(name="solution variable", mesh=mesh, value=0.) D = 1 eq = TransientTerm() == DiffusionTerm(coeff=D) valueTopLeft = 0 valueBottomRight = 1 X, Y = mesh.faceCenters facesTopLeft = ((mesh.facesLeft & (Y > L / 2)) | (mesh.facesTop & (X < L / 2))) facesBottomRight = ((mesh.facesRight & (Y < L / 2)) | (mesh.facesBottom & (X > L / 2))) phi.constrain(valueTopLeft, facesTopLeft) phi.constrain(valueBottomRight, facesBottomRight) if __name__ == '__main__': viewer = Viewer(vars=phi, datamin=0., datamax=1.) viewer.plot() timeStepDuration = 10 * 0.9 * dx**2 / (2 * D) steps = 10 for step in range(steps): eq.solve(var=phi, dt=timeStepDuration) if __name__ == '__main__': viewer.plot()
from fipy import SkewedGrid2D, CellVariable, Viewer, DiffusionTerm from fipy.tools import numerix valueLeft = 0. valueRight = 1. mesh = SkewedGrid2D(dx = 1.0, dy = 1.0, nx = 20, ny = 20, rand = 0.1) var = CellVariable(name = "solution variable", mesh = mesh, value = valueLeft) viewer = Viewer(vars = var) var.constrain(valueLeft, mesh.facesLeft) var.constrain(valueRight, mesh.facesRight) DiffusionTerm().solve(var) varArray = numerix.array(var) x = mesh.cellCenters[0] analyticalArray = valueLeft + (valueRight - valueLeft) * x / 20 errorArray = varArray - analyticalArray errorVar = CellVariable(name = 'absolute error', mesh = mesh, value = abs(errorArray)) errorViewer = Viewer(vars = errorVar) NonOrthoVar = CellVariable(name = "non-orthogonality", mesh = mesh,
TIME_STRIDE = 10 chi_AB = 0.08 N_A = 1000 N_B = 1000 print ("Yay") # # Define mesh mesh = PeriodicGrid2D(nx=10.0, ny=10.0, dx=1.0, dy=1.0) print ("mesh loaded") x_a = CellVariable(name=r"x_a", mesh = mesh, hasOld=1) xi = CellVariable(name=r"xi", mesh = mesh, hasOld=1) x_a.constrain(x_a.faceValue, mesh.facesLeft) x_a.constrain(x_a.faceValue, mesh.facesRight) xi.constrain(xi.faceValue, mesh.facesLeft) xi.constrain(xi.faceValue, mesh.facesRight) # We need to introduce the noise noise = GaussianNoiseVariable(mesh=mesh, mean = A_RAW, variance = NOISE_MAGNITUDE).value x_a[:] = noise dgdx_a = ((1.0/N_A) - (1.0/N_B)) + (1.0/N_A)*numerix.log(x_a) - (1.0/N_B)*numerix.log(1.0 - x_a) + chi_AB*(1.0 - 2*x_a)
## Build the bulk diffusion equation bulkVar = CellVariable(mesh=mesh, value=cinf) surfactantVar = SurfactantVariable(distanceVar=distanceVar) from .surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation bulkEqn = buildSurfactantBulkDiffusionEquation(bulkVar, distanceVar=distanceVar, surfactantVar=surfactantVar, diffusionCoeff=diffusion, rateConstant=rateConstant * siteDensity) bulkVar.constrain(cinf, mesh.facesRight) ## Build the surfactant equation surfEqn = AdsorbingSurfactantEquation(surfactantVar=surfactantVar, distanceVar=distanceVar, bulkVar=bulkVar, rateConstant=rateConstant) ## Build the analytical solutions, x = mesh.cellCenters[0, 1:] - dx def concentrationFunc(theta): tmp = (1 + rateConstant * siteDensity * (1 - theta) * L / diffusion)
def runLeveler(kLeveler=0.018, bulkLevelerConcentration=0.02, cellSize=0.1e-7, rateConstant=0.00026, initialAcceleratorCoverage=0.0, levelerDiffusionCoefficient=5e-10, numberOfSteps=400, displayRate=10, displayViewers=True): kLevelerConsumption = 0.0005 aspectRatio = 1.5 faradaysConstant = 9.6485e4 gasConstant = 8.314 acceleratorDiffusionCoefficient = 4e-10 siteDensity = 6.35e-6 atomicVolume = 7.1e-6 charge = 2 metalDiffusionCoefficient = 4e-10 temperature = 298. overpotential = -0.25 bulkMetalConcentration = 250. bulkAcceleratorConcentration = 50.0e-3 initialLevelerCoverage = 0. cflNumber = 0.2 cellsBelowTrench = 10 trenchDepth = 0.4e-6 trenchSpacing = 0.6e-6 boundaryLayerDepth = 98.7e-6 i0Suppressor = 0.3 i0Accelerator = 22.5 alphaSuppressor = 0.5 alphaAccelerator = 0.4 alphaAdsorption = 0.62 m = 4 b = 2.65 A = 0.3 Ba = -40 Bb = 60 Vd = 0.098 Bd = 0.0008 etaPrime = faradaysConstant * overpotential / gasConstant / temperature mesh = TrenchMesh(cellSize=cellSize, trenchSpacing=trenchSpacing, trenchDepth=trenchDepth, boundaryLayerDepth=boundaryLayerDepth, aspectRatio=aspectRatio, angle=numerix.pi * 4. / 180.) distanceVar = GapFillDistanceVariable(name='distance variable', mesh=mesh, value=-1.) distanceVar.setValue(1., where=mesh.electrolyteMask) distanceVar.calcDistanceFunction() levelerVar = SurfactantVariable(name="leveler variable", value=initialLevelerCoverage, distanceVar=distanceVar) acceleratorVar = SurfactantVariable(name="accelerator variable", value=initialAcceleratorCoverage, distanceVar=distanceVar) bulkAcceleratorVar = CellVariable(name='bulk accelerator variable', mesh=mesh, value=bulkAcceleratorConcentration) bulkLevelerVar = CellVariable(name='bulk leveler variable', mesh=mesh, value=bulkLevelerConcentration) metalVar = CellVariable(name='metal variable', mesh=mesh, value=bulkMetalConcentration) def depositionCoeff(alpha, i0): expo = numerix.exp(-alpha * etaPrime) return 2 * i0 * (expo - expo * numerix.exp(etaPrime)) coeffSuppressor = depositionCoeff(alphaSuppressor, i0Suppressor) coeffAccelerator = depositionCoeff(alphaAccelerator, i0Accelerator) exchangeCurrentDensity = acceleratorVar.interfaceVar * ( coeffAccelerator - coeffSuppressor) + coeffSuppressor currentDensity = metalVar / bulkMetalConcentration * exchangeCurrentDensity depositionRateVariable = currentDensity * atomicVolume / charge / faradaysConstant extensionVelocityVariable = CellVariable(name='extension velocity', mesh=mesh, value=depositionRateVariable) kAccelerator = rateConstant * numerix.exp(-alphaAdsorption * etaPrime) kAcceleratorConsumption = Bd + A / (numerix.exp(Ba * (overpotential + Vd)) + numerix.exp(Bb * (overpotential + Vd))) q = m * overpotential + b levelerSurfactantEquation = AdsorbingSurfactantEquation( levelerVar, distanceVar=distanceVar, bulkVar=bulkLevelerVar, rateConstant=kLeveler, consumptionCoeff=kLevelerConsumption * depositionRateVariable) accVar1 = acceleratorVar.interfaceVar accVar2 = (accVar1 > 0) * accVar1 accConsumptionCoeff = kAcceleratorConsumption * (accVar2**(q - 1)) acceleratorSurfactantEquation = AdsorbingSurfactantEquation( acceleratorVar, distanceVar=distanceVar, bulkVar=bulkAcceleratorVar, rateConstant=kAccelerator, otherVar=levelerVar, otherBulkVar=bulkLevelerVar, otherRateConstant=kLeveler, consumptionCoeff=accConsumptionCoeff) advectionEquation = TransientTerm() + FirstOrderAdvectionTerm( extensionVelocityVariable) metalEquation = buildMetalIonDiffusionEquation( ionVar=metalVar, distanceVar=distanceVar, depositionRate=depositionRateVariable, diffusionCoeff=metalDiffusionCoefficient, metalIonMolarVolume=atomicVolume) metalVar.constrain(bulkMetalConcentration, mesh.facesTop) bulkAcceleratorEquation = buildSurfactantBulkDiffusionEquation( bulkVar=bulkAcceleratorVar, distanceVar=distanceVar, surfactantVar=acceleratorVar, otherSurfactantVar=levelerVar, diffusionCoeff=acceleratorDiffusionCoefficient, rateConstant=kAccelerator * siteDensity) bulkAcceleratorVar.constrain(bulkAcceleratorConcentration, mesh.facesTop) bulkLevelerEquation = buildSurfactantBulkDiffusionEquation( bulkVar=bulkLevelerVar, distanceVar=distanceVar, surfactantVar=levelerVar, diffusionCoeff=levelerDiffusionCoefficient, rateConstant=kLeveler * siteDensity) bulkLevelerVar.constrain(bulkLevelerConcentration, mesh.facesTop) eqnTuple = ((advectionEquation, distanceVar, (), None), (levelerSurfactantEquation, levelerVar, (), None), (acceleratorSurfactantEquation, acceleratorVar, (), None), (metalEquation, metalVar, (), None), (bulkAcceleratorEquation, bulkAcceleratorVar, (), GeneralSolver()), (bulkLevelerEquation, bulkLevelerVar, (), GeneralSolver())) narrowBandWidth = 20 * cellSize levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2) totalTime = 0.0 if displayViewers: try: raise Exception from mayaviSurfactantViewer import MayaviSurfactantViewer viewers = (MayaviSurfactantViewer(distanceVar, acceleratorVar.interfaceVar, zoomFactor=1e6, datamax=0.5, datamin=0.0, smooth=1, title='accelerator coverage'), MayaviSurfactantViewer(distanceVar, levelerVar.interfaceVar, zoomFactor=1e6, datamax=0.5, datamin=0.0, smooth=1, title='leveler coverage')) except: class PlotVariable(CellVariable): def __init__(self, var=None, name=''): CellVariable.__init__(self, mesh=mesh.fineMesh, name=name) self.var = self._requires(var) def _calcValue(self): return numerix.array(self.var(self.mesh.cellCenters)) viewers = (Viewer(PlotVariable(var=acceleratorVar.interfaceVar)), Viewer(PlotVariable(var=levelerVar.interfaceVar))) for step in range(numberOfSteps): if displayViewers: if step % displayRate == 0: for viewer in viewers: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction() extensionVelocityVariable.setValue(depositionRateVariable) extOnInt = numerix.where( distanceVar.globalValue > 0, numerix.where(distanceVar.globalValue < 2 * cellSize, extensionVelocityVariable.globalValue, 0), 0) dt = cflNumber * cellSize / extOnInt.max() distanceVar.extendVariable(extensionVelocityVariable) for eqn, var, BCs, solver in eqnTuple: eqn.solve(var, boundaryConditions=BCs, dt=dt, solver=solver) totalTime += dt point = ((1.25e-08, ), (3.125e-07, )) value = 2.02815779e-08 return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0
def runSimpleTrenchSystem(faradaysConstant=9.6e4, gasConstant=8.314, transferCoefficient=0.5, rateConstant0=1.76, rateConstant3=-245e-6, catalystDiffusion=1e-9, siteDensity=9.8e-6, molarVolume=7.1e-6, charge=2, metalDiffusion=5.6e-10, temperature=298., overpotential=-0.3, metalConcentration=250., catalystConcentration=5e-3, catalystCoverage=0., currentDensity0=0.26, currentDensity1=45., cellSize=0.1e-7, trenchDepth=0.5e-6, aspectRatio=2., trenchSpacing=0.6e-6, boundaryLayerDepth=0.3e-6, numberOfSteps=5, displayViewers=True): cflNumber = 0.2 numberOfCellsInNarrowBand = 10 cellsBelowTrench = 10 yCells = cellsBelowTrench \ + int((trenchDepth + boundaryLayerDepth) / cellSize) xCells = int(trenchSpacing / 2 / cellSize) from fipy.tools import serialComm mesh = Grid2D(dx=cellSize, dy=cellSize, nx=xCells, ny=yCells, communicator=serialComm) narrowBandWidth = numberOfCellsInNarrowBand * cellSize distanceVar = DistanceVariable(name='distance variable', mesh=mesh, value=-1., hasOld=1) bottomHeight = cellsBelowTrench * cellSize trenchHeight = bottomHeight + trenchDepth trenchWidth = trenchDepth / aspectRatio sideWidth = (trenchSpacing - trenchWidth) / 2 x, y = mesh.cellCenters distanceVar.setValue(1., where=(y > trenchHeight) | ((y > bottomHeight) & (x < xCells * cellSize - sideWidth))) distanceVar.calcDistanceFunction(order=2) catalystVar = SurfactantVariable(name="catalyst variable", value=catalystCoverage, distanceVar=distanceVar) bulkCatalystVar = CellVariable(name='bulk catalyst variable', mesh=mesh, value=catalystConcentration) metalVar = CellVariable(name='metal variable', mesh=mesh, value=metalConcentration) expoConstant = -transferCoefficient * faradaysConstant \ / (gasConstant * temperature) tmp = currentDensity1 * catalystVar.interfaceVar exchangeCurrentDensity = currentDensity0 + tmp expo = numerix.exp(expoConstant * overpotential) currentDensity = expo * exchangeCurrentDensity * metalVar \ / metalConcentration depositionRateVariable = currentDensity * molarVolume \ / (charge * faradaysConstant) extensionVelocityVariable = CellVariable(name='extension velocity', mesh=mesh, value=depositionRateVariable) surfactantEquation = AdsorbingSurfactantEquation( surfactantVar=catalystVar, distanceVar=distanceVar, bulkVar=bulkCatalystVar, rateConstant=rateConstant0 + rateConstant3 * overpotential**3) advectionEquation = TransientTerm() + AdvectionTerm( extensionVelocityVariable) metalEquation = buildMetalIonDiffusionEquation( ionVar=metalVar, distanceVar=distanceVar, depositionRate=depositionRateVariable, diffusionCoeff=metalDiffusion, metalIonMolarVolume=molarVolume, ) metalVar.constrain(metalConcentration, mesh.facesTop) from surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation bulkCatalystEquation = buildSurfactantBulkDiffusionEquation( bulkVar=bulkCatalystVar, distanceVar=distanceVar, surfactantVar=catalystVar, diffusionCoeff=catalystDiffusion, rateConstant=rateConstant0 * siteDensity) bulkCatalystVar.constrain(catalystConcentration, mesh.facesTop) if displayViewers: try: from mayaviSurfactantViewer import MayaviSurfactantViewer viewer = MayaviSurfactantViewer(distanceVar, catalystVar.interfaceVar, zoomFactor=1e6, datamax=0.5, datamin=0.0, smooth=1, title='catalyst coverage') except: viewer = MultiViewer( viewers=(Viewer(distanceVar, datamin=-1e-9, datamax=1e-9), Viewer(catalystVar.interfaceVar))) else: viewer = None levelSetUpdateFrequency = int(0.8 * narrowBandWidth \ / (cellSize * cflNumber * 2)) for step in range(numberOfSteps): if step > 5 and step % 5 == 0 and viewer is not None: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction(order=2) extensionVelocityVariable.setValue(depositionRateVariable()) distanceVar.updateOld() distanceVar.extendVariable(extensionVelocityVariable, order=2) dt = cflNumber * cellSize / extensionVelocityVariable.max() advectionEquation.solve(distanceVar, dt=dt) surfactantEquation.solve(catalystVar, dt=dt) metalEquation.solve(metalVar, dt=dt) bulkCatalystEquation.solve(bulkCatalystVar, dt=dt, solver=GeneralSolver(tolerance=1e-15, iterations=2000)) try: import os filepath = os.path.splitext(__file__)[0] + '.gz' print catalystVar.allclose(numerix.loadtxt(filepath), rtol=1e-4) except: return 0
#!/usr/bin/env python from fipy import Grid1D, CellVariable, TransientTerm, DiffusionTerm, Viewer # m = Grid1D(nx=100, Lx=1.) # v0 = CellVariable(mesh=m, hasOld=True, value=0.5) v1 = CellVariable(mesh=m, hasOld=True, value=0.5) # v0.constrain(0, m.facesLeft) v0.constrain(1, m.facesRight) # v1.constrain(1, m.facesLeft) v1.constrain(0, m.facesRight) # eq0 = TransientTerm() == DiffusionTerm(coeff=0.01) - v1.faceGrad.divergence eq1 = TransientTerm() == v0.faceGrad.divergence + DiffusionTerm(coeff=0.01) # vi = Viewer((v0, v1)) # for t in range(100): v0.updateOld() v1.updateOld() res0 = res1 = 1e100 while max(res0, res1) > 0.1: res0 = eq0.sweep(var=v0, dt=1e-5) res1 = eq1.sweep(var=v1, dt=1e-5) if t % 10 == 0: vi.plot()
def runGold(faradaysConstant=9.6e4, consumptionRateConstant=2.6e+6, molarVolume=10.21e-6, charge=1.0, metalDiffusion=1.7e-9, metalConcentration=20.0, catalystCoverage=0.15, currentDensity0=3e-2 * 16, currentDensity1=6.5e-1 * 16, cellSize=0.1e-7, trenchDepth=0.2e-6, aspectRatio=1.47, trenchSpacing=0.5e-6, boundaryLayerDepth=90.0e-6, numberOfSteps=10, taperAngle=6.0, displayViewers=True): cflNumber = 0.2 numberOfCellsInNarrowBand = 20 mesh = TrenchMesh(cellSize = cellSize, trenchSpacing = trenchSpacing, trenchDepth = trenchDepth, boundaryLayerDepth = boundaryLayerDepth, aspectRatio = aspectRatio, angle = numerix.pi * taperAngle / 180.) narrowBandWidth = numberOfCellsInNarrowBand * cellSize distanceVar = GapFillDistanceVariable( name = 'distance variable', mesh = mesh, value = -1.) distanceVar.setValue(1., where=mesh.electrolyteMask) distanceVar.calcDistanceFunction() catalystVar = SurfactantVariable( name = "catalyst variable", value = catalystCoverage, distanceVar = distanceVar) metalVar = CellVariable( name = 'metal variable', mesh = mesh, value = metalConcentration) exchangeCurrentDensity = currentDensity0 + currentDensity1 * catalystVar.interfaceVar currentDensity = metalVar / metalConcentration * exchangeCurrentDensity depositionRateVariable = currentDensity * molarVolume / charge / faradaysConstant extensionVelocityVariable = CellVariable( name = 'extension velocity', mesh = mesh, value = depositionRateVariable) catalystSurfactantEquation = AdsorbingSurfactantEquation( catalystVar, distanceVar = distanceVar, bulkVar = 0, rateConstant = 0, consumptionCoeff = consumptionRateConstant * extensionVelocityVariable) advectionEquation = TransientTerm() + FirstOrderAdvectionTerm(extensionVelocityVariable) metalEquation = buildMetalIonDiffusionEquation( ionVar = metalVar, distanceVar = distanceVar, depositionRate = depositionRateVariable, diffusionCoeff = metalDiffusion, metalIonMolarVolume = molarVolume) metalVar.constrain(metalConcentration, mesh.facesTop) if displayViewers: try: from .mayaviSurfactantViewer import MayaviSurfactantViewer viewer = MayaviSurfactantViewer(distanceVar, catalystVar.interfaceVar, zoomFactor = 1e6, datamax=1.0, datamin=0.0, smooth = 1, title = 'catalyst coverage', animate=True) except: class PlotVariable(CellVariable): def __init__(self, var = None, name = ''): CellVariable.__init__(self, mesh = mesh.fineMesh, name = name) self.var = self._requires(var) def _calcValue(self): return numerix.array(self.var(self.mesh.cellCenters)) viewer = MultiViewer(viewers=( Viewer(PlotVariable(var = distanceVar), datamax=1e-9, datamin=-1e-9), Viewer(PlotVariable(var = catalystVar.interfaceVar)))) else: viewer = None levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2) step = 0 while step < numberOfSteps: if step % 10 == 0 and viewer is not None: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction() extensionVelocityVariable.setValue(numerix.array(depositionRateVariable)) dt = cflNumber * cellSize / max(extensionVelocityVariable.globalValue) distanceVar.extendVariable(extensionVelocityVariable) advectionEquation.solve(distanceVar, dt = dt) catalystSurfactantEquation.solve(catalystVar, dt = dt) metalEquation.solve(metalVar, dt = dt) step += 1 point = ((5e-09,), (1.15e-07,)) value = 1.45346701e-09 return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0
dx = 1. dy = dx L = dx * nx mesh = Grid2D(dx=dx, dy=dy, nx=nx, ny=ny) #We create a :class:`~fipy.variables.cellVariable.CellVariable` and initialize it to zero: phi = CellVariable(name="solution variable", mesh=mesh, value=0.) #and then create a diffusion equation. This is solved by default with an #iterative conjugate gradient solver. D = 1. eq = TransientTerm() == DiffusionTerm(coeff=D) X, Y = mesh.faceCenters if doBlob: phi.constrain([random.random() for x in X], mesh.exteriorFaces) elif doCirc: phi.constrain(X, mesh.exteriorFaces) else: #We apply Dirichlet boundary conditions valueTopLeft = 0 valueBottomRight = 1 #to the top-left and bottom-right corners. Neumann boundary conditions #are automatically applied to the top-right and bottom-left corners. facesTopLeft = ((mesh.facesLeft & (Y > L / 2)) | (mesh.facesTop & (X < L / 2))) facesBottomRight = ((mesh.facesRight & (Y < L / 2)) | (mesh.facesBottom & (X > L / 2)))
Physical Surface("inner") = {{30, 26}}; Physical Surface("outer") = {{37}}; Physical Volume("volume") = {{1}}; '''.format(cellSize, l1, l2, math.tan(beta) * (l2 - l1), l3, math.tan(alpha) * l3) mesh = Gmsh3D(geometryTemplate) # Enthaelt die Temperatur phi = CellVariable(name="Temperature", mesh=mesh, value=T0) # boundry conditions ---------------------------------------------------------- phi.constrain(Ti, where=mesh.physicalFaces["inner"]) phi.constrain(Te, where=mesh.physicalFaces["outer"]) # calculation ----------------------------------------------------------------- viewer = Viewer(vars=phi, datamin=200., datamax=Te * 1.01) print "Calculation started" started = time.clock() # Loest die Stationaere Waermegleichung DiffusionTerm(coeff=D).solve(var=phi) print "Calculation finished, took {} seconds".format(time.clock() - started) viewer.plot()
# Continuity Equation Pion_equation = TransientTerm(coeff=1., var=Pion) == mu_p_1 * ConvectionTerm(coeff=potential.faceGrad, var=Pion) + Dp_1 * DiffusionTerm(coeff=1., var=Pion) - k_rec * Pion * Nion # In English: dNion/dt = 1/q * divergence.Jn(x,t) - k_rec * Nion(x,t) * Pion(x,t) where # Jn = q * mu_n * E(x,t) * Nion(x,t) - q * Dn * grad.Nion(x,t) and E(x,t) = -grad.potential(x,t) # Continuity Equation Nion_equation = TransientTerm(coeff=1., var=Nion) == -mu_n_1 * ConvectionTerm(coeff=potential.faceGrad, var=Nion) + Dn_1 * DiffusionTerm(coeff=1., var=Nion) - k_rec * Pion * Nion # Electron_equation = TransientTerm(coeff=1., var=Electron) == -mu_n_2 * ConvectionTerm(coeff=potential.faceGrad, var=Electron) + Dn_2 * DiffusionTerm(coeff=1., var=Electron) - k_rec * Electron * Hole # Hole_equation = TransientTerm(coeff=1., var=Hole) == mu_p_2 * ConvectionTerm(coeff=potential.faceGrad, var=Hole) + Dp_2 * DiffusionTerm(coeff=1., var=Hole) - k_rec * Electron * Hole # In English: d^2potential/dx^2 = -q/epsilon * Charge_Density and Charge Density= Pion-Nion # Poisson's Equation potential_equation = DiffusionTerm(coeff=1., var=potential) == -(q / epsilon) * (Pion - Nion) # potential_equation = DiffusionTerm(coeff=1., var=potential) == -(q / epsilon) * (Pion - Nion + Hole - Electron) ### Boundary conditions ### # Fipy is defaulted to be no-flux, so we only need to constrain potential potential.constrain(0., where=mesh.exteriorFaces) # potential.constrain(9., where=mesh.facesLeft) # potential.constrain(0., where=mesh.facesRight) # potential.constrain(0., where=mesh.exteriorFaces) ### Solve Equations in a coupled manner ### eq = Pion_equation & Nion_equation & potential_equation steps = 2000 timestep = 0.2 Efield_save = np.empty([nx, steps]) potential_save = np.empty_like(Efield_save) # Pion_save = np.empty_like(Efield_save) # Nion_save = np.empty_like(Efield_save)
cfl = 0.01 velocity = 1. timeStepDuration = cfl * dx / abs(velocity) steps = 1000 mesh = Grid1D(dx = dx, nx = nx) startingArray = numerix.zeros(nx, 'd') startingArray[50:90] = 1. var = CellVariable( name = "advection variable", mesh = mesh, value = startingArray) var.constrain(valueLeft, mesh.facesLeft) var.constrain(valueRight, mesh.facesRight) eq = TransientTerm() - PowerLawConvectionTerm(coeff = (velocity,)) if __name__ == '__main__': viewer = Viewer(vars=(var,)) viewer.plot() raw_input("press key to continue") for step in range(steps): eq.solve(var, dt = timeStepDuration, solver = LinearLUSolver(tolerance = 1.e-15)) viewer.plot() viewer.plot()
def runLeveler(kLeveler=0.018, bulkLevelerConcentration=0.02, cellSize=0.1e-7, rateConstant=0.00026, initialAcceleratorCoverage=0.0, levelerDiffusionCoefficient=5e-10, numberOfSteps=400, displayRate=10, displayViewers=True): kLevelerConsumption = 0.0005 aspectRatio = 1.5 faradaysConstant = 9.6485e4 gasConstant = 8.314 acceleratorDiffusionCoefficient = 4e-10 siteDensity = 6.35e-6 atomicVolume = 7.1e-6 charge = 2 metalDiffusionCoefficient = 4e-10 temperature = 298. overpotential = -0.25 bulkMetalConcentration = 250. bulkAcceleratorConcentration = 50.0e-3 initialLevelerCoverage = 0. cflNumber = 0.2 cellsBelowTrench = 10 trenchDepth = 0.4e-6 trenchSpacing = 0.6e-6 boundaryLayerDepth = 98.7e-6 i0Suppressor = 0.3 i0Accelerator = 22.5 alphaSuppressor = 0.5 alphaAccelerator = 0.4 alphaAdsorption = 0.62 m = 4 b = 2.65 A = 0.3 Ba = -40 Bb = 60 Vd = 0.098 Bd = 0.0008 etaPrime = faradaysConstant * overpotential / gasConstant / temperature mesh = TrenchMesh(cellSize = cellSize, trenchSpacing = trenchSpacing, trenchDepth = trenchDepth, boundaryLayerDepth = boundaryLayerDepth, aspectRatio = aspectRatio, angle = numerix.pi * 4. / 180.) distanceVar = GapFillDistanceVariable( name = 'distance variable', mesh = mesh, value = -1.) distanceVar.setValue(1., where=mesh.electrolyteMask) distanceVar.calcDistanceFunction() levelerVar = SurfactantVariable( name = "leveler variable", value = initialLevelerCoverage, distanceVar = distanceVar) acceleratorVar = SurfactantVariable( name = "accelerator variable", value = initialAcceleratorCoverage, distanceVar = distanceVar) bulkAcceleratorVar = CellVariable(name = 'bulk accelerator variable', mesh = mesh, value = bulkAcceleratorConcentration) bulkLevelerVar = CellVariable( name = 'bulk leveler variable', mesh = mesh, value = bulkLevelerConcentration) metalVar = CellVariable( name = 'metal variable', mesh = mesh, value = bulkMetalConcentration) def depositionCoeff(alpha, i0): expo = numerix.exp(-alpha * etaPrime) return 2 * i0 * (expo - expo * numerix.exp(etaPrime)) coeffSuppressor = depositionCoeff(alphaSuppressor, i0Suppressor) coeffAccelerator = depositionCoeff(alphaAccelerator, i0Accelerator) exchangeCurrentDensity = acceleratorVar.interfaceVar * (coeffAccelerator - coeffSuppressor) + coeffSuppressor currentDensity = metalVar / bulkMetalConcentration * exchangeCurrentDensity depositionRateVariable = currentDensity * atomicVolume / charge / faradaysConstant extensionVelocityVariable = CellVariable( name = 'extension velocity', mesh = mesh, value = depositionRateVariable) kAccelerator = rateConstant * numerix.exp(-alphaAdsorption * etaPrime) kAcceleratorConsumption = Bd + A / (numerix.exp(Ba * (overpotential + Vd)) + numerix.exp(Bb * (overpotential + Vd))) q = m * overpotential + b levelerSurfactantEquation = AdsorbingSurfactantEquation( levelerVar, distanceVar = distanceVar, bulkVar = bulkLevelerVar, rateConstant = kLeveler, consumptionCoeff = kLevelerConsumption * depositionRateVariable) accVar1 = acceleratorVar.interfaceVar accVar2 = (accVar1 > 0) * accVar1 accConsumptionCoeff = kAcceleratorConsumption * (accVar2**(q - 1)) acceleratorSurfactantEquation = AdsorbingSurfactantEquation( acceleratorVar, distanceVar = distanceVar, bulkVar = bulkAcceleratorVar, rateConstant = kAccelerator, otherVar = levelerVar, otherBulkVar = bulkLevelerVar, otherRateConstant = kLeveler, consumptionCoeff = accConsumptionCoeff) advectionEquation = TransientTerm() + FirstOrderAdvectionTerm(extensionVelocityVariable) metalEquation = buildMetalIonDiffusionEquation( ionVar = metalVar, distanceVar = distanceVar, depositionRate = depositionRateVariable, diffusionCoeff = metalDiffusionCoefficient, metalIonMolarVolume = atomicVolume) metalVar.constrain(bulkMetalConcentration, mesh.facesTop) bulkAcceleratorEquation = buildSurfactantBulkDiffusionEquation( bulkVar = bulkAcceleratorVar, distanceVar = distanceVar, surfactantVar = acceleratorVar, otherSurfactantVar = levelerVar, diffusionCoeff = acceleratorDiffusionCoefficient, rateConstant = kAccelerator * siteDensity) bulkAcceleratorVar.constrain(bulkAcceleratorConcentration, mesh.facesTop) bulkLevelerEquation = buildSurfactantBulkDiffusionEquation( bulkVar = bulkLevelerVar, distanceVar = distanceVar, surfactantVar = levelerVar, diffusionCoeff = levelerDiffusionCoefficient, rateConstant = kLeveler * siteDensity) bulkLevelerVar.constrain(bulkLevelerConcentration, mesh.facesTop) eqnTuple = ( (advectionEquation, distanceVar, (), None), (levelerSurfactantEquation, levelerVar, (), None), (acceleratorSurfactantEquation, acceleratorVar, (), None), (metalEquation, metalVar, (), None), (bulkAcceleratorEquation, bulkAcceleratorVar, (), GeneralSolver()), (bulkLevelerEquation, bulkLevelerVar, (), GeneralSolver())) narrowBandWidth = 20 * cellSize levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2) totalTime = 0.0 if displayViewers: try: raise Exception from .mayaviSurfactantViewer import MayaviSurfactantViewer viewers = ( MayaviSurfactantViewer(distanceVar, acceleratorVar.interfaceVar, zoomFactor = 1e6, datamax=0.5, datamin=0.0, smooth = 1, title = 'accelerator coverage'), MayaviSurfactantViewer(distanceVar, levelerVar.interfaceVar, zoomFactor = 1e6, datamax=0.5, datamin=0.0, smooth = 1, title = 'leveler coverage')) except: class PlotVariable(CellVariable): def __init__(self, var = None, name = ''): CellVariable.__init__(self, mesh = mesh.fineMesh, name = name) self.var = self._requires(var) def _calcValue(self): return numerix.array(self.var(self.mesh.cellCenters)) viewers = (Viewer(PlotVariable(var=acceleratorVar.interfaceVar)), Viewer(PlotVariable(var=levelerVar.interfaceVar))) for step in range(numberOfSteps): if displayViewers: if step % displayRate == 0: for viewer in viewers: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction() extensionVelocityVariable.setValue(depositionRateVariable) extOnInt = numerix.where(distanceVar.globalValue > 0, numerix.where(distanceVar.globalValue < 2 * cellSize, extensionVelocityVariable.globalValue, 0), 0) dt = cflNumber * cellSize / extOnInt.max() distanceVar.extendVariable(extensionVelocityVariable) for eqn, var, BCs, solver in eqnTuple: eqn.solve(var, boundaryConditions = BCs, dt = dt, solver=solver) totalTime += dt point = ((1.25e-08,), (3.125e-07,)) value = 2.02815779e-08 return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0