def calculate_3D_sensor_potential(pitch_x, pitch_y, n_pixel_x, n_pixel_y, radius, resolution, V_readout, V_bias, nD=2): points, cells = pg.generate_mesh(mesh_3D_sensor(x=pitch_x, y=pitch_y, n_pixel_x=n_pixel_x, n_pixel_y=n_pixel_y, radius=radius, nD=nD, resolution=resolution)) mio.write('sensor.msh', points, cells) mesh = fipy.GmshImporter2D('sensor.msh') plot.plot_mesh(mesh) potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.) permittivity = 1. potential.equation = (fipy.DiffusionTerm(coeff=permittivity) == 0.) bcs = [] allfaces = mesh.getExteriorFaces() X,Y = mesh.getFaceCenters() # Readout pillars for pillar in range(nD): position = pitch_x / nD * (pillar + 1. / 2.) - pitch_x / 2. ring = allfaces & ( (X-position)**2+(Y)**2 < (radius)**2) bcs.append(fipy.FixedValue(value=V_readout,faces=ring)) # Bias pillars # Edges positions = [(- pitch_x / 2., - pitch_y / 2.), (+ pitch_x / 2., - pitch_y / 2.), (+ pitch_x / 2., + pitch_y / 2.), (- pitch_x / 2., + pitch_y / 2.)] # Sides positions += [(0, - pitch_y / 2.), (0, + pitch_y / 2.)] for pos_x, pos_y in positions: ring = allfaces & ( (X-pos_x)**2+(Y-pos_y)**2 < (radius)**2) bcs.append(fipy.FixedValue(value=V_bias, faces=ring)) # # Calculate boundaries # p_pillars = mesh.getFaces() # n_pillars = mesh.getFacesTop() # # electrodes = readout_plane # bcs = [fipy.FixedValue(value=V_backplane, faces=backplane)] # # for pixel in range(n_pixel): # pixel_position = width * (pixel + 1. / 2.) - width * n_pixel / 2. # bcs.append(fipy.FixedValue(value=V_readout, # faces=electrodes & # (X > pixel_position - pitch / 2.) & # (X < pixel_position + pitch / 2.))) potential.equation.solve(var=potential, boundaryConditions=bcs) return potential
def solve(self): sideFaceFactor = fp.CellVariable( name="sideFaceFactor", mesh=self.mesh, value=self.areaExtFaces / (self.AcsMult * self.mesh.cellVolumes)) # Create variables self.TCore = fp.CellVariable(name="coreTemperature", mesh=self.mesh, value=self.TAmb) self.TSurface = fp.CellVariable(name="surfaceTemperature", mesh=self.mesh, value=self.TAmb) # Apply boundary conditions: self.applyBC(self.mesh.facesLeft(), self.BC[0], self.mesh.scaledFaceAreas[0] * self.AcsMult) self.applyBC(self.mesh.facesRight(), self.BC[1], self.mesh.scaledFaceAreas[-1] * self.AcsMult) # Create linear solver linSolver = LinearLUSolver(tolerance=1e-10) # Create base equation (thermal conduction): eq = fp.DiffusionTerm(coeff=self.thermalConductivity, var=self.TCore) if (self.jouleHeating['active']): eq += self.jouleHeating['j']**2 * self.jouleHeating['eResistivity'] if (self.radiation['active']): raise NotImplementedError('Radiation not implemented yet!') else: if (self.convection['active']): RAmb = 1. / self.convection['coefficient'] if (self.insulation['active']): RAmb += self.insulation['thickness'] / self.insulation[ 'thermConductivity'] eq += 1. / RAmb * (sideFaceFactor * self.TAmb - fp.ImplicitSourceTerm(coeff=sideFaceFactor, var=self.TCore)) eq.solve(var=self.TCore, solver=linSolver) if (self.convection['active'] and self.insulation['active']): # 0 - limited by conduction, 1 - limited by convection a1 = 1. / (RAmb * self.convection['coefficient']) self.TSurface.setValue(a1 * self.TCore() + (1 - a1) * self.TAmb) else: self.TSurface.setValue(self.TCore())
def distributionInitial(): phi = fipy.CellVariable(mesh=Mesh, name=r"$\rho(x,p)$") X, P = Mesh.cellCenters() temp = numpy.exp(-(1. / 2) * (X)**2 - (1. / 2) * (P)**2) phi.setValue(temp) norm = fipy.numerix.sum(phi.value, axis=0) * Dx * Dp phi.setValue(phi.value / norm) del temp, norm, X, P return phi
def to_face_value(mesh, value): """Convert an array over cells to an array over faces """ return pipe( value, lambda x: fp.CellVariable(mesh=mesh, value=value), lambda x: x.faceValue, np.array, )
def forwardEvo(phi, tStart, tEnd, path, saveResults): # Initialize step counter and evolution time step = 0 tEvo = tStart # Extract cell centers and faces from mesh X, P = Mesh.cellCenters() xFace, pFace = Mesh.faceCenters() # Create plot for starting distribution target = 'forwardEvo-Step-' + '%05d' % step + '.png' genPlots(phi, tEvo, saveResults, target, path) # Continue to evolve distribution until specified end time while (tEvo < tEnd): # Find current spring constant and location of minimum kT = springConstant(tEvo) zT = potentialMinimum(tEvo) # Calculate time step size timeStepDuration = (1. / (SubDiv * Nx)) * (1. / numpy.sqrt(1. / Tau**2 + kT)) if (tEvo + timeStepDuration > tEnd): timeStepDuration = tEnd - tEvo # Create Diffusion Term gxx = numpy.zeros(X.shape) gxp = numpy.zeros(X.shape) gpx = numpy.zeros(X.shape) gpp = numpy.ones(X.shape) * (2. / Tau) dTerm = fipy.DiffusionTerm( fipy.CellVariable(mesh=Mesh, value=[[gxx, gxp], [gpx, gpp]])) del gxx, gxp, gpx, gpp # Create convection term uX = pFace uP = -kT * (xFace - zT) - (2. / Tau) * pFace cCoeff = fipy.FaceVariable(mesh=Mesh, value=[uX, uP]) cTerm = fipy.ExponentialConvectionTerm(cCoeff) del uX, uP, cCoeff # Create evolution equation eq = fipy.TransientTerm() + cTerm == dTerm # Specify solver solver = fipy.solvers.pysparse.LinearLUSolver(tolerance=10**-15, \ iterations=1000, precon=None) # Evolve system eq.solve(var=phi, dt=timeStepDuration, solver=solver) tEvo = tEvo + timeStepDuration step = step + 1 # Check normalization for possible errors norm = fipy.numerix.sum(phi.value, axis=0) * Dx * Dp if (abs(norm - 1) > 10**(-13)): s1 = 'Distribution is no longer normalized.\n' s2 = 'Abs(1-Norm) = ' s3 = repr(norm - 1.) raise RuntimeError(s1 + s2 + s3) del kT, zT, timeStepDuration, cTerm, eq, norm # Create plot of current distribution target = 'forwardEvo-Step-' + '%05d' % step + '.png' genPlots(phi, tEvo, saveResults, target, path) del tEvo, X, P, xFace, pFace return phi
def excess_heating(self, val): """ Similar to radiogenic heat production, but not based on the material properties of the forearc. """ if val == 0: v = None else: v = F.CellVariable(mesh=self.mesh, value=val.into('K/s')) self._excess = v
def solve_fipy_with_given_N(N, params): s1 = params[0] s2 = params[1] t1 = params[2] t2 = params[3] dx = 100.0 / N dt = 1.0 NDAYS = 10 f_start_time = time.time() mesh = fp.Grid1D(nx=N, dx=dx) v_fp = fp.CellVariable(name="v_fp", mesh=mesh, value=INI_VALUE, hasOld=True) # BC v_fp.constrain(0, where=mesh.facesLeft) # left BC is always Dirichlet # v_fp.faceGrad.constrain(0. * mesh.faceNormals, where=mesh.facesRight) # right: flux=0 def dif_fp(u): b = -4. D = (numerix.exp(t1) / t2 * (numerix.power(s2 * numerix.exp(-s1) * u + numerix.exp(s2 * b), t2 / s2) - numerix.exp(t2 * b))) / ( s2 * u + numerix.exp(s1 + s2 * b)) return D # Boussinesq eq. for theta eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=dif_fp(v_fp)) + SOURCE MAX_SWEEPS = 10000 for t in range(NDAYS): v_fp.updateOld() res = 0.0 for r in range(MAX_SWEEPS): # print(i, res) resOld = res # res = eq.sweep(var=v_fp, dt=dt, underRelaxation=0.1) res = eq.sweep(var=v_fp, dt=dt) if abs(res - resOld) < abs_tolerance: break # it has reached to the solution of the linear system time_spent = time.time() - f_start_time return v_fp.value, time_spent
def S_value(phi, ele, cmask, peat_bottom_arr): # Some inputs are in fipy CellVariable type gwt = (phi.value * cmask.value - ele).reshape(ny, nx) S = storage(gwt, s0, s1, s2, s_sapric_coef) - storage( peat_bottom_arr, s0, s1, s2, s_sapric_coef) S[S < 0] = 1e-3 # Same reasons as for D Scell = fp.CellVariable(mesh=mesh, value=S.flatten( )) # diffusion coefficient, transmissivity. As a cell variable. return Scell.value
def distributionInitial(): phi = fipy.CellVariable(mesh=Mesh, name=r"$\rho(x,p)$") X, P = Mesh.cellCenters() temp = numpy.exp(-(1./2)*(X/.2)**2-(1./2)*((P-4)/.2)**2) \ + numpy.exp(-(1./2)*(X/.2)**2-(1./2)*((P+4)/.2)**2) #mask = (P<-4)|(P>4) #temp = temp*mask phi.setValue(temp) norm = fipy.numerix.sum(phi.value, axis=0) * Dx * Dp phi.setValue(phi.value / norm) del temp, norm, X, P return phi
def radiogenic_heating(self): """Radiogenic heat production varying in space.""" a, Cp, rho = (self.section.material_property(i) for i in ("heat_generation", "specific_heat", "density")) if a.sum().magnitude == 0: return None arr = (a / Cp / rho).into("K/s") assert len(arr) == len(self.mesh.cellCenters[0]) return F.CellVariable(mesh=self.mesh, value=arr)
def calculate_potential(mesh, rho, epsilon, V_read, V_bias, x_dep): r''' Calculate the potential with a given space charge distribution. If the depletion width is too large the resulting potential will have a minimum < bias voltage. This is unphysical. ''' # The field scales with rho / epsilon, thus scale to proper value to # counteract numerical instabilities epsilon_scaled = 1. rho_scale = rho / epsilon potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.) electrons = fipy.CellVariable(mesh=mesh, name='e-') electrons.valence = -1 electrons.setValue(rho_scale) charge = electrons * electrons.valence charge.name = "charge" # A depletion zone within the bulk requires an internal boundary condition # Internal boundary conditions seem to challenge fipy, see: # http://www.ctcms.nist.gov/fipy/documentation/USAGE.html#applying-internal-boundary-conditions large_value = 1e+15 # Hack for optimizer mask = mesh.x > x_dep potential.equation = (fipy.DiffusionTerm(coeff=epsilon_scaled) - fipy.ImplicitSourceTerm(mask * large_value) + mask * large_value * V_bias + charge == 0) potential.constrain(V_read, mesh.facesLeft) potential.constrain(V_bias, mesh.facesRight) solver.solve(potential, equation=potential.equation) return potential
def C_value(phi, ele, sto_to_cut, cmask, drmask_not): # Some inputs are in fipy CellVariable type gwt = phi.value * cmask.value - ele c = hydro_utils.peat_map_h_to_sto( soil_type_mask=peat_type_mask, gwt=gwt, h_to_tra_and_C_dict=httd) - sto_to_cut c[c < 0] = 1e-3 # Same reasons as for D ccell = fp.CellVariable( mesh=mesh, value=c ) # diffusion coefficient, transmissivity. As a cell variable. return ccell.value
def make_source(xs, mesh, time): """ Makes the source term of the diffusion equation """ #assert xs.shape[0] == 2 sourceTerm = fp.CellVariable(name = "Source term", mesh=mesh, value = 0.) rho = 0.05 q0 = 1 / (np.pi * rho ** 2) T = 0.3 for i in range(sourceTerm().shape[0]): sourceTerm()[i] = q0 * np.exp( - ((mesh.cellCenters[0]()[i] - xs[0]) ** 2 + (mesh.cellCenters[1]()[i] - xs[1]) ** 2 ) / (2 * rho **2)) * (time() < T) return sourceTerm
def get_eqn(mesh, diff): """Generate a generic 1D diffusion equation with flux from the left Args: mesh: the mesh diff: the diffusion coefficient Returns: a tuple of the flux and the equation """ flux = fipy.CellVariable(mesh, value=0.) eqn = fipy.TransientTerm() == fipy.DiffusionTerm( diff) + fipy.ImplicitSourceTerm(flux * GET_MASK(mesh) / mesh.dx) return (flux, eqn)
def impulseResponse(argArray): # Extract arguments tStart = argArray[0] tFinal = argArray[1] k = argArray[2] # Initialize the impulse distribution phi = fipy.CellVariable(mesh=Mesh, name=r"$\rho(x,p)$") temp = numpy.zeros(((2 * Nx)**2, )) temp[k] = 1. norm = Dx * Dp phi.setValue(temp / norm) # Evolve the distribution response = evolution(phi, tStart, tFinal, '', False) return response
def df2(xs, mesh, i, j): """ Evaluate the model for the 2nd derivatives at the four corners of the domain at times ``t``. It returns a flatten version of the system, i.e.: y_1(t_1) ... y_4(t_1) ... y_1(t_4) ... y_4(t_4) """ assert i == 1 or i == 2 assert j == 1 or j == 2 nx = 25 ny = nx dx = 0.04 dy = dx mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny) time = fp.Variable() q0 = make_source_der_2(xs, mesh, time, i, j) D = 1. # Define the equation eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=D) + q0 # Boundary conditions # The solution variable phi = fp.CellVariable(name="Concentraion", mesh=mesh, value=0.) # Solve dt = 0.005 steps = 60 d2U = [] for step in range(steps): eq.solve(var=phi, dt=dt) if step == 14 or step == 29 or step == 44 or step == 59: dl = phi()[0] #dr = phi()[24] ul = phi()[600] #ur = phi()[624] #d2U = np.hstack([d2U, np.array([dl, dr, ul, ur])]) d2U = np.hstack([d2U, np.array([dl, ul])]) return d2U
def get_var(params, ini, inf): """Make a variable with constraint Args: params: the parameter dictionary ini: initial value inf: far field value Returns: the variable """ return pipe( params, lambda x: get_mesh(x["nx"], x["delta"]), lambda x: fipy.CellVariable(x, value=ini, hasOld=True), do(lambda x: x.constrain(inf, where=x.mesh.facesRight)), )
def solve(self): sideFaceFactor = fp.CellVariable(name = "sideFaceFactor", mesh = self.mesh, value = self.sideFaceAreas / (self.areaMult * self.mesh.cellVolumes)) # Initial conditions self.T.setValue(self.TAmb) # Run solverSettings solver = LinearLUSolver(tolerance=1e-10) if (self.solverSettings['nonlinear']): res = 1 sweep = 0 self.resVector = [] TFaces = self.T.arithmeticFaceValue() self.TLeft = [] self.TRight = [] self.QLeft = [] self.QRight = [] while (res > self.solverSettings['tolerance'] and sweep < self.solverSettings['maxIterations']): # Compute temperature dependent thermal conductivity self.thermCond.setValue(self.conduction['model'](TFaces)) # Add the conductivity term to the equation eqX = fp.DiffusionTerm(coeff = self.thermCond) if (self.radiation['active']): # Compute temperature dependent emissivity self.emissivity.setValue(self.emissivityCalculator(self.T())) # Add radiation term to the equation radMultiplier = sigmaSB * self.emissivity * sideFaceFactor eqX = eqX + radMultiplier * (self.TAmb**4 - self.T**4) # Perform iteration res = eqX.sweep(var = self.T, solver = solver, underRelaxation = self.solverSettings['relaxationFactor']) # Save residual self.resVector.append(res) # Save temperature and fluxes at the ends TFaces = self.T.arithmeticFaceValue() self.TLeft.append(TFaces[0]) self.TRight.append(TFaces[-1]) self.QLeft.append(self.QAx[0]) self.QRight.append(self.QAx[-1]) sweep += 1 else: eqX.solve(var = self.T)
def calculate_planar_sensor_w_potential(mesh, width, pitch, n_pixel, thickness): ''' Calculates the weighting field of a planar sensor. ''' _LOGGER.info('Calculating weighting potential') # Mesh validity check mesh_width = mesh.getFaceCenters()[0, :].max() - mesh.getFaceCenters()[ 0, :].min() if mesh_width != width * n_pixel: raise ValueError( 'The provided mesh width does not correspond to the sensor width') if mesh.getFaceCenters()[1, :].min() != 0: raise ValueError('The provided mesh does not start at 0.') if mesh.getFaceCenters()[1, :].max() != thickness: raise ValueError('The provided mesh does not end at sensor thickness.') potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.) permittivity = 1. potential.equation = (fipy.DiffusionTerm(coeff=permittivity) == 0.) # Calculate boundaries backplane = mesh.getFacesTop() readout_plane = mesh.getFacesBottom() electrodes = readout_plane bcs = [fipy.FixedValue(value=0., faces=backplane)] X, _ = mesh.getFaceCenters() for pixel in range(n_pixel): pixel_position = width * (pixel + 1. / 2.) - width * n_pixel / 2. bcs.append( fipy.FixedValue(value=1.0 if pixel_position == 0. else 0., faces=electrodes & (X > pixel_position - pitch / 2.) & (X < pixel_position + pitch / 2.))) solver.solve(potential, equation=potential.equation, boundaryConditions=bcs) return potential
def T_value(phi, ele, cmask, peat_bottom_arr): # Some inputs are in fipy CellVariable type gwt = (phi.value * cmask.value - ele).reshape(ny, nx) # T(h) - T(bottom) T = transmissivity(gwt, t0, t1, t2, t_sapric_coef) - transmissivity( peat_bottom_arr, t0, t1, t2, t_sapric_coef) # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that # phi is below the impermeable bottom. We allow phi to have those values, but # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom). T[T < 0] = 1e-3 # Small non-zero value not to wreck the computation Tcell = fp.CellVariable(mesh=mesh, value=T.flatten( )) # diffusion coefficient, transmissivity. As a cell variable. Tface = fp.FaceVariable(mesh=mesh, value=Tcell.arithmeticFaceValue.value ) # THe correct Face variable. return Tface.value
def D_value(phi, ele, tra_to_cut, cmask, drmask_not): # Some inputs are in fipy CellVariable type gwt = phi.value * cmask.value - ele d = hydro_utils.peat_map_h_to_tra( soil_type_mask=peat_type_mask, gwt=gwt, h_to_tra_and_C_dict=httd) - tra_to_cut # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that # phi is below the impermeable bottom. We allow phi to have those values, but # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom). d[d < 0] = 1e-3 # Small non-zero value not to wreck the computation dcell = fp.CellVariable( mesh=mesh, value=d ) # diffusion coefficient, transmissivity. As a cell variable. dface = fp.FaceVariable(mesh=mesh, value=dcell.arithmeticFaceValue.value ) # THe correct Face variable. return dface.value
def get_vars(params, set_eta, mesh): """Get the variables Args: params: the parameter dict set_eta: function to set the initial value of the phase field mesh: the FiPy mesh Returns: a dictionary of the variables (eta, d2f) """ return pipe( dict( eta=fp.CellVariable(mesh=mesh, hasOld=True, value=params["eta0"], name="eta"), d2f=fp.FaceVariable(mesh=mesh, name="d2f"), ), do(set_eta(params, mesh)), )
def df(xs, mesh, i): """ Evaluate the model for the derivatives at the four corners of the domain at times ``t``. It returns a flatten version of the system, i.e.: y_1(t_1) ... y_4(t_1) ... y_1(t_4) ... y_4(t_4) """ assert i == 1 or i == 2 time = fp.Variable() q0 = make_source_der(xs, mesh, time, i) D = 1. # Define the equation eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=D) + q0 # Boundary conditions # The solution variable phi = fp.CellVariable(name = "Concentraion", mesh=mesh, value=0.) # Solve dt = 0.005 steps = 60 dU = [] for step in range(steps): eq.solve(var=phi, dt=dt) if step == 14 or step == 29 or step == 44 or step == 59: dc = phi()[12] #dr = phi()[24] uc = phi()[612] #ur = phi()[624] #dU = np.hstack([dU, np.array([dl, dr, ul, ur])]) dU = np.hstack([dU, np.array([dc, uc])]) return dU
def f(xs, mesh): """ Evaluate the model for the concentration at the four corners of the domain at times ``t``. It returns a flatten version of the system, i.e.: y_1(t_1) ... y_4(t_1) ... y_1(t_4) ... y_4(t_4) """ time = fp.Variable() q = make_source(xs, mesh, time) D = 1. # Define the equation eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=D) + q # Boundary conditions # The solution variable phi = fp.CellVariable(name="Concentraion", mesh=mesh, value=0.) # Solve dt = 0.005 steps = 60 U_sol = [] for step in range(steps): eq.solve(var=phi, dt=dt) if step == 14 or step == 29 or step == 44 or step == 59: dl = phi()[0] #dr = phi()[24] ul = phi()[600] #ur = phi()[624] #U_sol = np.hstack([U_sol, np.array([dl, dr, ul, ur])]) U_sol = np.hstack([U_sol, np.array([dl, ul])]) return U_sol
def get_eq(params, eta, d2f): """Get the equation Args: params: the parameter dictionary eta: the phase field variable d2f: the free energy double derivative variable Returns: a dictionary of the equation and variables """ return pipe( fp.CellVariable(mesh=eta.mesh, name="psi"), lambda x: ( fp.TransientTerm(var=eta) == -fp.DiffusionTerm( coeff=params["mobility"], var=x) + fp.DiffusionTerm( coeff=params["mobility"] * d2f, var=eta), fp.ImplicitSourceTerm(coeff=1.0, var=x) == fp.DiffusionTerm( coeff=params["kappa"], var=eta), ), lambda x: x[0] & x[1], )
def _Execute(self): input = self.GetPolyDataInput() self.mesh = FiPyTriangleMesher(input).GetMesh() self.speed = fipy.CellVariable(name="speed", mesh=self.mesh, value=0.) self.BCs = (fipy.FixedValue(faces=self.mesh.getExteriorFaces(), value=0), ) self.equation = fipy.DiffusionTerm() + 1. == 0. self.equation.solve(var=self.speed, boundaryConditions=self.BCs) # FiPy API doesn't seem to have an integrate method volumeFlux = self.speed.getCellVolumeAverage() * \ self.speed.mesh.getCellVolumes().sum() # Scale such that the flux will be unity self.speed /= volumeFlux output = self.GetPolyDataOutput() output.ShallowCopy(input) speed = convert.numpy_to_vtk(self.speed.getValue()) output.GetCellData().SetScalars(speed) return
def __init__(self, section, **kwargs): BaseFiniteSolver.__init__(self, section, **kwargs) self._excess = None if not hasattr(section, "layers"): # We need to convert a layer to section section = Section(section) self.section = section self.mesh = self.create_mesh() self.initial_values = self.section.profile.into("kelvin") self.var = F.CellVariable(name="Temperature", mesh=self.mesh, value=self.initial_values, hasOld=(self.type == 'crank-nicholson')) self._exterior_flux = 0 self.create_coefficient() if self.constraints is not None: self.set_constraints(*self.constraints) if self.type == "explicit": # Use stable timesteps if we're running explicit finite differences if self.time_step is not None: warn("For explicit finite differences, the " "timestep is not user-adjustable") self.time_step = self.stable_timestep(0.05) if self.type == "crank-nicholson": eqns = [self.create_equation(i) for i in ("implicit", "explicit")] self.__implicit_equation = eqns[0] self.equation = sum(eqns) else: self.equation = self.create_equation(self.type)
# scanf("%g") simulator # https://docs.python.org/3/library/re.html#simulating-scanf scanf_g = "[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?" pattern = ".*t=({g})\.tar\.gz".format(g=scanf_g) elapsed = re.match(pattern, params['restart']).group(1) elapsed = fp.Variable(name="$t$", value=float(elapsed)) else: Lx = params['Lx'] Ly = params['Ly'] dx, nx = _dnl(dx=params['dx'], nx=None, Lx=Lx) dy, ny = _dnl(dx=params['dx'], nx=None, Lx=Ly) mesh = fp.PeriodicGrid2D(dx=dx, nx=nx, dy=dy, ny=ny) phi = fp.CellVariable(mesh=mesh, name="$\phi$", value=0., hasOld=True) elapsed = fp.Variable(name="$t$", value=0.) x, y = mesh.cellCenters[0], mesh.cellCenters[1] X, Y = mesh.faceCenters[0], mesh.faceCenters[1] # In[6]: if isnotebook: viewer = fp.Viewer(vars=phi, datamin=0., datamax=1.) viewer.plot()
def test_steady_state(): """ Test that we can create a steady-state model using FiPy that is similar to that given by our 'naive' solver """ continental_crust.heat_generation = u(1, 'mW/m^3') _ = continental_crust.to_layer(u(3000, 'm')) section = Section([_]) heatflow = u(15, 'mW/m^2') surface_temperature = u(0, 'degC') m = continental_crust q = heatflow k = m.conductivity a = m.heat_generation Cp = m.specific_heat rho = m.density def simple_heat_flow(x): # Density and heat capacity matter don't matter in steady-state T0 = surface_temperature return T0.to('K') + q * x / k + a / (2 * k) * x**2 p = simple_heat_flow(section.cell_centers) dx = section.cell_sizes[0] test_profile = p.into('degC') grad = (-q / k).into('K/m') # Divergence div = (-a / k).into('K/m^2') a_ = -N.gradient(N.gradient(test_profile, dx), dx) assert all(a_ < 0) assert N.allclose(a_.min(), div) res = steady_state(section, heatflow, surface_temperature) profile = res.profile.into('degC') assert N.allclose(test_profile, profile) solver = FiniteSolver(_) solver.constrain(surface_temperature, None) solver.constrain(heatflow, None) res2 = solver.steady_state() # Make sure it's nonlinear and has constant 2nd derivative arr = solver.var.faceGrad.divergence.value assert N.allclose(sum(arr - arr[0]), 0) assert N.allclose(arr.mean(), div) # Test simple finite element model mesh = F.Grid1D(nx=section.n_cells, dx=section.cell_sizes[0].into('m')) T = F.CellVariable(name="Temperature", mesh=mesh) T.constrain(surface_temperature.into("K"), mesh.facesLeft) A = F.FaceVariable(mesh=mesh, value=m.diffusivity.into("m**2/s")) rad_heat = F.CellVariable(mesh=mesh, value=(a / Cp / rho).into("K/s")) D = F.DiffusionTerm(coeff=A) + F.ImplicitSourceTerm(coeff=rad_heat) sol = D.solve(var=T) val = T.faceGrad.divergence.value arr = T.value - 273.15 #assert N.allclose(val.mean(), div) assert N.allclose(test_profile, arr) P = res2.profile.into('degC') assert N.allclose(test_profile, P)
categories = dict() data = dummyTreant() viscosity = 1 density = 100. gravity = [params["gx"], params["gy"]] pressureRelaxation = 0.8 velocityRelaxation = 0.5 meshmodule = import_module("mesh{}".format(params["problem"])) (mesh, inlet, outlet, walls, top_right) = meshmodule.mesh_and_boundaries(params) volumes = fp.CellVariable(mesh=mesh, value=mesh.cellVolumes) pressure = fp.CellVariable(mesh=mesh, name="$p$") pressureCorrection = fp.CellVariable(mesh=mesh, name="$p'$") xVelocity = fp.CellVariable(mesh=mesh, name="$u_x$") yVelocity = fp.CellVariable(mesh=mesh, name="$u_y$") velocity = fp.FaceVariable(mesh=mesh, name=r"$\vec{u}$", rank=1) xVelocityEq = fp.DiffusionTerm(coeff=viscosity) - pressure.grad.dot( [[1.], [0.]]) + density * gravity[0] yVelocityEq = fp.DiffusionTerm(coeff=viscosity) - pressure.grad.dot( [[0.], [1.]]) + density * gravity[1] ap = fp.CellVariable(mesh=mesh, value=1.) coeff = 1. / ap.arithmeticFaceValue * mesh._faceAreas * mesh._cellDistances