def __solve_diffusion(self, model):
        oxygen_grid = model.environments[self.oxygen_env_name]
        nx = oxygen_grid.xsize
        ny = oxygen_grid.ysize
        nz = oxygen_grid.zsize

        dx = dy = dz = 1.0

        D = self.oxygen_diffusion_coeff

        mesh = Grid3D(dx=dx, dy=dy, nx=nx, ny=ny, dz=dz, nz=nz)

        phi = CellVariable(name="solutionvariable", mesh=mesh)
        phi.setValue(0.)

        start = time.time()
        for _ in range(self.diffusion_solve_iterations):
            source_grid, sink_grid = self.__get_source_sink_grids(phi, model)
            eq = TransientTerm() == DiffusionTerm(
                coeff=D) + source_grid - sink_grid

            eq.solve(var=phi, dt=1)
            eq = TransientTerm() == DiffusionTerm(coeff=D)

            eq.solve(var=phi, dt=self.dt)
        end = time.time()
        print("Solving oxygen diffusion took %s seconds" % str(end - start))

        return phi, nx, ny, nz
 def define_convection_variable(self, current_time):
     x_convection, y_convection = self.get_convection_x_and_y(current_time)
     if self.baseline_convection is None:
         convection_variable = CellVariable(mesh=self.mesh, rank=1) #  Only define the variable from scratch once
     else:
         convection_variable = self.baseline_convection
     convection_variable.setValue((x_convection, y_convection))
     return convection_variable
Exemple #3
0
    def __init__(self,
                 X=None,
                 T=None,
                 time_steps=5,
                 max_time=0.4,
                 num_cells=25,
                 L=1.):
        """Initialize the objet.

        Keyword Arguments:
            X           ---     The sensor locations.
            T           ---     The sensor measurment times.
            time_steps  ---     How many timesteps do you want to measure.
            max_time    ---     The maximum solution time.
            num_cells   ---     The number of cells per dimension.
            L           ---     The size of the computational domain.
        """
        assert isinstance(num_cells, int)
        self._num_cells = num_cells
        assert isinstance(L, float) and L > 0.
        self._dx = L / self.num_cells
        self._mesh = Grid2D(dx=self.dx,
                            dy=self.dx,
                            nx=self.num_cells,
                            ny=self.num_cells)
        self._phi = CellVariable(name='solution variable', mesh=self.mesh)
        self._source = CellVariable(name='source term',
                                    mesh=self.mesh,
                                    hasOld=True)
        self._eqX = TransientTerm() == ExplicitDiffusionTerm(
            coeff=1.) + self.source
        self._eqI = TransientTerm() == DiffusionTerm(coeff=1.) + self.source
        self._eq = self._eqX + self._eqI
        assert isinstance(max_time, float) and max_time > 0.
        self._max_time = max_time
        #self.max_time / time_steps #.
        if X is None:
            idx = range(self.num_cells**2)
        else:
            idx = []
            x1, x2 = self.mesh.cellCenters
            for x in X:
                dist = (x1 - x[0])**2 + (x2 - x[1])**2
                idx.append(np.argmin(dist))
        self._idx = idx
        if T is None:
            T = np.linspace(0, self.max_time, time_steps)[1:]
        self._max_time = T[-1]
        self._T = T
        self._dt = self.T[0] / time_steps
        super(Diffusion, self).__init__(5,
                                        len(self.T) * len(self.idx),
                                        name='Diffusion Solver')
Exemple #4
0
    def __get_source_sink_grids(self, phi, model):
        xsize = model.environments[self.vegf_env_name].xsize
        ysize = model.environments[self.vegf_env_name].ysize
        zsize = model.environments[self.vegf_env_name].zsize

        agent_grid = model.environments["agentEnv"].grid
        phi_tmp = np.reshape(phi._array, (xsize, ysize, zsize))

        source_grid = CellVariable(name="source",
                                   mesh=Grid3D(dx=1,
                                               dy=1,
                                               dz=1,
                                               nx=xsize,
                                               ny=ysize,
                                               nz=zsize))

        for coordinate, agents in agent_grid.items():
            if len(agents) == 0:
                continue

            concentration_at_pos = phi_tmp[coordinate[0]][coordinate[1]][
                coordinate[2]]

            source_rate = sum([
                a.current_vegf_secretion_rate for a in agents
                if (a.__class__.__name__ == "CancerCell"
                    and not (a.quiescent or a.dead))
            ])
            # A pre-estimate of what the concentration at this position will
            # be. This of course neglects diffusion,
            # but can give an estimate of how we should regulate our sources
            # and sinks
            estimated_concentration = concentration_at_pos + source_rate

            # If our estimated concentration is greater than our maximum
            # source rate, this means we really are outputting
            # too much. At most, we want to achieve equilibrium between
            # sources and environment, so we reduce our
            # output rate. Of course, we can't reduce our output rate by
            # more than the output rate itself
            if estimated_concentration >= self.max_vegf:
                source_rate -= min(source_rate,
                                   estimated_concentration - self.max_vegf)

            i = np.ravel_multi_index(
                [coordinate[0], coordinate[1], coordinate[2]],
                (xsize, ysize, zsize))

            source_grid.value[i] = source_rate

        return source_grid
Exemple #5
0
    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()
Exemple #6
0
 def view_sol(self, times, conc):
     """
     Show the solution in conc with times.
     conc[i][:] contains solution at time times[i]
     """
     if self.plotevery:
         self.solution_view = CellVariable(name="Yarn radial concentration",
                     mesh=self.mesh_yarn, value=conc[0][:self.nr_cell])
         if isinstance(conc, np.ndarray):
             maxv = conc.max() * 1.2
             minv = conc.min() * 0.9
         else:
             maxv = np.max(conc) * 1.2
             minv = np.min(conc) * 0.9
         self.viewer =  Matplotlib1DViewer(vars=self.solution_view,
                             datamin=minv, datamax=maxv)
         self.viewerplotcount = 0
         self.viewerwritecount = 0
         for time, con in zip(times, conc):
             self.solution_view.setValue(con[:self.nr_cell])
             if self.viewerplotcount == 0 or (self.writeevery and 
                                         self.viewerwritecount == 0):
                 self.viewer.axes.set_title('time %s' %str(time))
                 if self.writeevery and self.viewerwritecount == 0:
                     #plot and savefig
                     self.viewer.plot(filename=utils.OUTPUTDIR + os.sep \
                                             + 'yarnconc%08.4f.png' % time)
                 else:
                     #only plot
                     self.viewer.plot()
             self.viewerplotcount += 1
             self.viewerplotcount = self.viewerplotcount % self.plotevery
             if self.writeevery:
                 self.viewerwritecount += 1
                 self.viewerwritecount = self.viewerwritecount % self.writeevery
Exemple #7
0
 def initializeTright(self):
     extrapol_dist = (
         self.mesh.mesh.faceCenters[0, self.mesh.mesh.facesRight()][0] -
         self.mesh.cell_mid_points)
     self.dxf = CellVariable(mesh=self.mesh.mesh, value=extrapol_dist)
     self.variables['T_right'] = (self.variables['T'] +
                                  self.variables['T'].grad[0] * self.dxf)
Exemple #8
0
    def icir_rect(self):
        # step 1: Mesh
        mesh = Grid2D(dx=self.gsize, dy=self.gsize, nx=self.xy_n[0], ny=self.xy_n[1])

        # step 2: Equation
        phi = CellVariable(mesh=mesh, name='potential phi', value=0.)
        eqn = (DiffusionTerm(coeff = 1.) == 0.)

        # step 3: Boundary conditions
        # compute flow of 4 vertexes
        # one vertex has 2 components of wind vector, (x, y)
        vertexWindVec = np.array([ [0.0 for i in range(2)] for i in range(4)])
        for i in range(4): # 4 vertexes
            for j in range(2): # 2 components
                vertexWindVec[i, j] = self.mean_flow[j] \
                        + self.colored_noise(self.vertexWindVecRanInc[i][j])
        # interpolate flow vector on sim area edges, and set neumann boundary
        #   conditions, because /grad /phi = V(x,y)
        # get all points which lie on the center of edges of cells
        X, Y = mesh.faceCenters
        # /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 = np.zeros_like(mesh.faceCenters())
        # p: points on one edge to interpolate, 1 dimension
        # vx, vy: x&y components of interpolated wind vectors of points list p
        # vertex index, for interpolate bc on 4 edges
        # vertexIndex[0] = [1,2], down  boundary, 0<x<nx*dx, y=0
        # vertexIndex[1] = [1,0], left  boundary, x=0, 0<y<ny*dy
        # vertexIndex[2] = [0,3], up    boundary, 0<x<nx*dx, y=ny*dy
        # vertexIndex[3] = [2,3], right boundary, x=nx*dx, 0<y<ny*dy
        vertexIndex = np.array([ [1,2], [1,0], [0,3], [2,3] ])
        for i in range(4): # 4 edges for 2D rect area
            p = np.arange(self.gsize/2, self.gsize*self.xy_n[i%2], self.gsize)
            vx = np.interp(p, [0.0, self.gsize*self.xy_n[i%2]], \
                    [vertexWindVec[vertexIndex[0,0], 0], \
                    vertexWindVec[vertexIndex[0,1], 0]]).T.reshape(1,-1)[0]
            vy = np.interp(p, [0.0, self.gsize*self.xy_n[i%2]], \
                    [vertexWindVec[vertexIndex[0,0], 1], \
                    vertexWindVec[vertexIndex[0,1], 1]]).T.reshape(1,-1)[0]
            print 'vx = ' + str(vx)
            if i == 0: # down boundary
                grad_phi_bc[:, mesh.facesDown()] = np.array([vx, vy])
            elif i == 1: # left boundary
                grad_phi_bc[:, mesh.facesLeft()] = np.array([vx, vy])
            elif i == 2: # up boundary
                grad_phi_bc[:, mesh.facesUp()] = np.array([vx, vy])
            elif i == 3: # right boundary
                grad_phi_bc[:, mesh.facesRight()] = np.array([vx, vy])
        # set neumann boundary condition
        phi.faceGrad.constrain(((grad_phi_bc[0]),(grad_phi_bc[1])), where=mesh.exteriorFaces)

        # step 4: Solve
        eqn.solve(var=phi)
        #print str(phi)
        #print str(type(np.array(phi)))
        self.wind_phi_field = np.array(phi)
        self.wind_mesh_centers = mesh.cellCenters()
Exemple #9
0
    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
Exemple #10
0
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
Exemple #11
0
 def define_cellvariables(self, phi_s_initial, cs_surface_initial,
                          phi_e_initial, theta_initial, ce_initial,
                          sim_cell):
     self.phi_s = CellVariable(mesh=self.axial_mesh, value=phi_s_initial)
     # self.deltaPhiS = CellVariable(mesh=self.axial_mesh, value = 0.)                                               # For Newton iteration
     self.phi_e_copy_from_supermesh = CellVariable(mesh=self.axial_mesh,
                                                   value=phi_e_initial)
     self.Cs_surface = CellVariable(mesh=self.axial_mesh,
                                    value=cs_surface_initial)
     self.overpotential = CellVariable(
         mesh=self.axial_mesh,
         value=(phi_s_initial - phi_e_initial -
                self.calc_ocp_interp(theta_initial)))
     self.Cs_p2d = CellVariable(mesh=self.p2d_mesh,
                                value=cs_surface_initial[0],
                                hasOld=True)
     self.j0 = CellVariable(
         mesh=self.axial_mesh,
         value=self.k_norm * numerix.absolute(
             ((self.cs_max - cs_surface_initial) / self.cs_max)
             **(1 - sim_cell.alpha)) * numerix.absolute(
                 (cs_surface_initial / self.cs_max)**sim_cell.alpha) *
         numerix.absolute(
             (ce_initial / ce_initial)**(1.0 - sim_cell.alpha)))
     self.uocp = CellVariable(mesh=self.axial_mesh,
                              value=self.calc_ocp_interp(self.Cs_surface /
                                                         self.cs_max))
Exemple #12
0
 def _genTorque(self):
     """Generate Torque"""
     self.Lambda = FaceVariable(name='Torque at cell faces', mesh=self.mesh, rank=1)
     self.LambdaCell = CellVariable(name='Torque at cell centers', mesh=self.mesh)
     LambdaArr = np.zeros(self.rF.shape)
     LambdaArr[1:] = self.chi*np.power(1.0/(self.rF[1:]*self.gamma-1.0), 4)
     #LambdaArr[self.gap] = 0.0; LambdaArr[self.gap] = LambdaArr.max()
     self.Lambda.setValue(LambdaArr)
     self.LambdaCell.setValue(self.chi*np.power(1.0/(self.r*self.gamma-1.0), 4))
     self.LambdaCell[np.where(self.LambdaCell > LambdaArr.max())] = LambdaArr.max()
Exemple #13
0
    def Battery_cellvariables(self, neg_epsilon_e, sep_epsilon_e,
                              pos_epsilon_e, neg_a_s, pos_a_s, nx_neg, nx_sep,
                              nx_pos, j_battery_value, ce_initial,
                              phi_e_initial, neg_L, sep_L, pos_L, neg_De_eff,
                              sep_De_eff, pos_De_eff):
        self.Ce = CellVariable(mesh=self.axial_mesh,
                               value=ce_initial,
                               hasOld=True)
        self.phi_e = CellVariable(mesh=self.axial_mesh, value=phi_e_initial)

        self.epsilon_e_value = numerix.zeros(nx_neg + nx_sep + nx_pos)
        self.epsilon_e_value[0:nx_neg], self.epsilon_e_value[
            nx_neg:nx_neg + nx_sep] = neg_epsilon_e, sep_epsilon_e
        self.epsilon_e_value[nx_neg + nx_sep:] = pos_epsilon_e
        self.epsilon_e = CellVariable(mesh=self.axial_mesh,
                                      value=self.epsilon_e_value)

        self.epsilon_e_eff_value = numerix.zeros(nx_neg + nx_sep + nx_pos)
        self.epsilon_e_eff_value[0:nx_neg] = neg_epsilon_e**self.brug
        self.epsilon_e_eff_value[nx_neg:nx_neg +
                                 nx_sep] = sep_epsilon_e**self.brug
        self.epsilon_e_eff_value[nx_neg + nx_sep:] = pos_epsilon_e**self.brug
        self.epsilon_e_eff = CellVariable(mesh=self.axial_mesh,
                                          value=self.epsilon_e_eff_value)

        self.a_s_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.a_s_value[0:nx_neg] = neg_a_s
        self.a_s_value[nx_neg:nx_neg + nx_sep] = 0.0
        self.a_s_value[nx_neg + nx_sep:] = pos_a_s
        self.a_s = CellVariable(mesh=self.axial_mesh, value=self.a_s_value)

        self.L_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.L_value[0:nx_neg], self.L_value[nx_neg:nx_neg +
                                             nx_sep] = neg_L, sep_L
        self.L_value[nx_neg + nx_sep:] = pos_L
        self.L = CellVariable(mesh=self.axial_mesh, value=self.L_value)

        self.De_eff_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.De_eff_value[0:nx_neg], self.De_eff_value[
            nx_neg:nx_neg + nx_sep], self.De_eff_value[
                nx_neg + nx_sep:] = neg_De_eff, sep_De_eff, pos_De_eff
        self.De_eff = CellVariable(mesh=self.axial_mesh,
                                   value=self.De_eff_value)

        self.j_battery = CellVariable(mesh=self.axial_mesh,
                                      value=j_battery_value)
Exemple #14
0
    def _genSigma(self, width=0.1):
        """Create dependent variable Sigma"""
        # Gaussian initial condition
        value = self.mDisk*M/np.sqrt(2*np.pi)/(self.gamma*a*width)*\
                np.exp(-0.5*np.square(self.r-1.0)/width**2)/(2*np.pi*self.gamma*self.r*a)
        # Make it dimensionless
        value /= self.mDisk*M/(self.gamma*a)**2
        idxs = np.where(self.r < 0.1)
        value[idxs] = 0.0
        value = tuple(value)

        # Create the dependent variable and set the boundary conditions
        # to zero
        self.Sigma = CellVariable(name='Surface density',
                                 mesh=self.mesh, hasOld=True, value=value)
Exemple #15
0
 def initializeDiagnostic(self,
                          variable,
                          funpointer,
                          default=0.0,
                          face_variable=False,
                          output_variable=True):
     if not face_variable:
         self.variables[variable] = CellVariable(name=variable,
                                                 mesh=self.mesh.mesh,
                                                 value=default)
     else:
         self.variables[variable] = FaceVariable(name=variable,
                                                 mesh=self.mesh.mesh,
                                                 value=default)
     self.diagnostic_modules[variable] = DiagnosticModule(funpointer, self)
     if output_variable:
         self.variables_store.append(variable)
     self.diagnostic_update_order.append(variable)
    def define_solution_variable(self, existing_solution=None, boundary_source = None):
        if existing_solution is None:
            initial_condition_value = self.parameter.IC_value
            ic_region = self.parameter.IC_region
            ic_array = copy.deepcopy(self.mesh.cellCenters[0])

            xmesh = self.mesh.cellCenters[0]
            ymesh = self.mesh.cellCenters[1]

            ic_array[xmesh < ic_region['xmin']] = 0
            ic_array[xmesh >= ic_region['xmin']] = initial_condition_value
            ic_array[xmesh > ic_region['xmax']] = 0
            ic_array[ymesh < ic_region['ymin']] = 0
            ic_array[ymesh > ic_region['ymax']] = 0

            ic_array.mesh = self.mesh

        else:
            ic_array = existing_solution

        # Create solution variable
        phi = CellVariable(name="solution variable",
                           mesh=self.mesh,
                           value=ic_array)

        # Edit to add boundary condition if requried.
        if boundary_source is not 'no flux' or boundary_source is not None:
            x, y = self.mesh.faceCenters

            boundary_source_value = self.parameter.boundary_source_value
            boundary_source_region = self.parameter.boundary_source_region

            boundary_source_mask = (
                (x > boundary_source_region.xmin) &
                (x < boundary_source_region.xmax) &
                (y > boundary_source_region.ymin) &
                (y < boundary_source_region.ymax)
            )

            # phi.faceGrad.constrain(0*self.mesh.faceNormals, self.mesh.exteriorFaces)
            phi.faceGrad.constrain(boundary_source_value*self.mesh.faceNormals,
                                   self.mesh.exteriorFaces & boundary_source_mask)

        return phi
Exemple #17
0
    def __init__(self,
                 tsmesh,
                 time_step_module=None,
                 output_step_module=None,
                 h_initial=0.0,
                 T_initial=None,
                 time_initial=None,
                 proportion_frozen_initial=None,
                 forcing_module=None,
                 thermal_properties=None,
                 bc_inside=None,
                 bc_headwall=None):
        # T_initial only works if thermal_properties are provided
        ThawSlump.__init__(self,
                           tsmesh,
                           time_step_module=time_step_module,
                           output_step_module=output_step_module,
                           time_initial=time_initial,
                           forcing_module=forcing_module,
                           thermal_properties=thermal_properties)
        self._initializeSourcesZero(source_name='S')
        self._initializeSourcesZero(source_name='S_inside')
        self._initializeSourcesZero(source_name='S_headwall')
        # specific volumetric enthalpy
        self.variables['h'] = CellVariable(name='h',
                                           mesh=self.mesh.mesh,
                                           value=h_initial,
                                           hasOld=True)
        self.addStoredVariable('h')
        if T_initial is not None:  # essentially overrides h_initial
            self.initializeEnthalpyTemperature(
                T_initial, proportion_frozen=proportion_frozen_initial)
        if (bc_inside is not None and bc_headwall is not None
                and self.thermal_properties is not None
                and self.forcing_module is not None):
            bcc = BoundaryConditionCollection1D(bc_headwall=bc_headwall,
                                                bc_inside=bc_inside)
            self.specifyBoundaryConditions(bcc)

        self._output_module.storeInitial(self)
Exemple #18
0
    def run(self, initialConditions, step_n):
        pinit = np.zeros(
            self.nx * self.ny *
            self.nz)  #TODO: how to map from the ABM domain to this form
        if initialConditions == None:
            for i in range(self.nx * self.ny * self.nz):
                pinit[i] = float(
                    decimal.Decimal(random.randrange(8, 50)) /
                    1000000)  #ng/mm3
        else:
            pass

        print("Initial values:")
        print(pinit)
        phi = CellVariable(name="Concentration (ng/ml)",
                           mesh=self.mesh,
                           value=pinit)
        t = Variable(0.)
        for step in range(step_n):
            print("Time = {}".format(t.value))
            self.eq.solve(var=phi, dt=self.timeStepDuration)
            t.setValue(t.value + self.timeStepDuration)
        return phi.value
Exemple #19
0
## build the mesh

dx = L / (nx - 1.5)
mesh = Grid1D(nx = nx, dx = dx, communicator=serialComm)

## build the distance variable


value = mesh.cellCenters[0] - 1.499 * dx
##distanceVar = DistanceVariable(mesh = mesh, value = dx * (arange(nx) - 0.999))
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,
Exemple #20
0
#!/usr/bin/env python

from fipy import Grid2D, CellVariable, TransientTerm, DiffusionTerm, FixedValue
import pylab
import sys

nx = 300
dx = 0.05
L = nx * dx
mesh = Grid2D(dx=dx,dy=dx,nx=nx,ny=nx)
x,y = mesh.getCellCenters()
x0,y0 = L/2,L/2
X,Y = mesh.getFaceCenters()

potential = CellVariable(mesh=mesh, name='potential', value=0.)
potential.equation = (DiffusionTerm(coeff = 1.) == 0.)

bcs = (
    FixedValue(value=5,faces=mesh.getFacesLeft() & (Y<y0) ),
    FixedValue(value=0,faces=mesh.getFacesRight() & (Y<y0) ),
    FixedValue(value=2,faces=mesh.getFacesTop() ),
)

potential.equation.solve(var=potential, boundaryConditions=bcs)

# The follow evaluation of the solution is only
# possible with "common" meshes.
result = pylab.array(potential)
result = result.reshape((nx,nx))
xx,yy = pylab.array(x), pylab.array(y)
Exemple #21
0
from builtins import range
from fipy import input
from fipy import CellVariable, Tri2D, TransientTerm, ExplicitDiffusionTerm, DefaultSolver, Viewer
from fipy.tools import numerix

dx = 1.
dy = 1.
nx = 10
ny = 1
valueLeft = 0.
valueRight = 1.
timeStepDuration = 0.02

mesh = Tri2D(dx, dy, nx, ny)

var = CellVariable(name="concentration", mesh=mesh, value=valueLeft)

eq = TransientTerm() == ExplicitDiffusionTerm()

solver = DefaultSolver(tolerance=1e-6, iterations=1000)

var.constrain(valueLeft, mesh.facesLeft)
var.constrain(valueRight, mesh.facesRight)

answer = numerix.array([
    0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
    0.00000000e+00, 0.00000000e+00, 1.58508452e-07, 6.84325019e-04,
    7.05111362e-02, 7.81376523e-01, 0.00000000e+00, 0.00000000e+00,
    0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
    0.00000000e+00, 4.99169535e-05, 1.49682805e-02, 3.82262622e-01,
    0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
Exemple #22
0
Line Loop(1) = {1, 2, 3, 4, 5, 6};
Line Loop(2) = {7, 8, 9, 10};
Line Loop(3) = {11, 12, 13, 14};
Plane Surface(1) = {1, 2, 3};
Plane Surface(2) = {2};
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))
Exemple #23
0
 def __init__(self, var = None, name = ''):
     CellVariable.__init__(self, mesh = mesh.fineMesh, name = name)
     self.var = self._requires(var)
Exemple #24
0
    temp_yR = (2 * temp_i[:-2, 1:-1] - 2 * temp_i[1:-1, 1:-1]) / (dx**2)
    temp_yy = (temp_i[1:-1, 2:] - 2 * temp_i[1:-1, 1:-1] +
               temp_i[:2, 1:-1]) / (dy**2)
    temp_xL = (2 * temp_i[1:-1, 2:] - 2 * temp_i[1:-1, 1:-1]) / (dy**2)
    temp_xR = (2 * temp_i[1:-1, :-2] - 2 * temp_i[1:-1, 1:-1]) / (dy**2)
    temp_f[1:-1, 1:-1] = temp_xx + temp_yy
    temp_f[-1, 1:-1] = temp_xR
    temp_f[0, 1:-1] = temp_xL
    temp_f[1:-1, 0] = temp_yL
    return temp_f


#%% Phase Field Derivative

#%% Phase Field Variable
phase = CellVariable(name=r'$\phi$', mesh=mesh, hasOld=True)
D_temp = CellVariable(name=r'$\Delta T$', mesh=mesh, hasOld=True)
CHANGE_TEMP = 2.25
#%% Heat Equation
heatEQ = (TransientTerm() == DiffusionTerm(CHANGE_TEMP) +
          (phase - phase.old) / D_time)

#%% Parameter Setup
# ALPHA = 0.015 # Alpha CONSTANT
C_ani = 0.02  # Component of (D) the anisotropic diffusion tensor in 2D
N = 6.  # Symmetry
THETA = np.pi / 8  # Orientation

psi = THETA + np.arctan2(phase.faceGrad[1], phase.faceGrad[0])

PHI = np.tan(N * psi / 2)
Exemple #25
0
    valueLeft = 0.
    valueRight = 1.

    meshList = []
    RMSNonOrthoList = []
    RMSErrorList = []

    for i in range(1, 501):
        meshList = meshList + [
            SkewedGrid2D(dx=1.0, dy=1.0, nx=20, ny=20, rand=(0.001 * i))
        ]

    for mesh in meshList:
        var = CellVariable(name="solution variable",
                           mesh=mesh,
                           value=valueLeft)

        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
        nonOrthoArray = mesh._nonOrthogonality
        RMSError = (numerix.add.reduce(errorArray * errorArray) /
                    len(errorArray))**0.5
        RMSNonOrtho = (numerix.add.reduce(nonOrthoArray * nonOrthoArray) /
Exemple #26
0
from examples.chemotaxis.parameters import parameters

from fipy import CellVariable, Grid1D, TransientTerm, DiffusionTerm, ImplicitSourceTerm, Viewer

params = parameters['case 2']

nx = 50
dx = 1.
L = nx * dx

mesh = Grid1D(nx=nx, dx=dx)

shift = 1.

KMVar = CellVariable(mesh=mesh, value=params['KM'] * shift, hasOld=1)
KCVar = CellVariable(mesh=mesh, value=params['KC'] * shift, hasOld=1)
TMVar = CellVariable(mesh=mesh, value=params['TM'] * shift, hasOld=1)
TCVar = CellVariable(mesh=mesh, value=params['TC'] * shift, hasOld=1)
P3Var = CellVariable(mesh=mesh, value=params['P3'] * shift, hasOld=1)
P2Var = CellVariable(mesh=mesh, value=params['P2'] * shift, hasOld=1)
RVar = CellVariable(mesh=mesh, value=params['R'], hasOld=1)

PN = P3Var + P2Var

KMscCoeff = params['chiK'] * (RVar + 1) * (1 - KCVar - KMVar.cellVolumeAverage)
KMspCoeff = params['lambdaK'] / (1 + PN / params['kappaK'])
KMEq = TransientTerm() - KMscCoeff + ImplicitSourceTerm(KMspCoeff)

TMscCoeff = params['chiT'] * (1 - TCVar - TMVar.cellVolumeAverage)
TMspCoeff = params['lambdaT'] * (KMVar + params['zetaT'])
Exemple #27
0
    >>> print var.allclose(analyticalArray)
    1

"""

__docformat__ = 'restructuredtext'

from fipy import Tri2D, CellVariable, DiffusionTerm, Viewer

nx = 50
dx = 1.

mesh = Tri2D(dx = dx, nx = nx)

valueLeft = 0.
valueRight = 1.
var = CellVariable(name = "solution-variable", mesh = mesh, value = valueLeft)

var.constrain(valueLeft, mesh.facesLeft)
var.constrain(valueRight, mesh.facesRight)

if __name__ == '__main__':
    DiffusionTerm().solve(var)
    viewer = Viewer(vars=var)
    viewer.plot()
    x = mesh.cellCenters[0]
    Lx = nx * dx
    analyticalArray = valueLeft + (valueRight - valueLeft) * x / Lx
    print var.allclose(analyticalArray)
    raw_input("finished")
Exemple #28
0
"""
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals
from builtins import input
__docformat__ = 'restructuredtext'

from fipy import CellVariable, Grid1D, LinearLUSolver, NthOrderBoundaryCondition, DiffusionTerm, Viewer

Lx = 1.
nx = 100000
dx = Lx / nx

mesh = Grid1D(dx = dx, nx = nx)

var = CellVariable(mesh = mesh)

eq = DiffusionTerm((1.0, 1.0))

BCs = (NthOrderBoundaryCondition(mesh.facesLeft, 0., 0),
       NthOrderBoundaryCondition(mesh.facesRight, Lx, 0),
       NthOrderBoundaryCondition(mesh.facesLeft, 0., 2),
       NthOrderBoundaryCondition(mesh.facesRight, 0., 2))

solver = LinearLUSolver(iterations=10)

if __name__ == '__main__':
    eq.solve(var,
             boundaryConditions = BCs,
             solver = solver)
Exemple #29
0
class Yarn1DModel(object):
    """
    Yarn1DModel is a special diffusion model for a single yarn which is composed 
    by a certain amount of fibers. A cross-section of a fiber is 
    generated. The domain is a line from the center of the yarn to the surface. 
    On this line there are some fibers distributed as in the module yarn1Dgrid.
    Only diffusion processes in a single fiber and yarn are considered. 
    ODE of scipy solve the diffusion process in the layers of DEET and permithrine
    which are on the fiber
    An overlap region outside of the yarn can be added for multiscale simulations
    Fipy solve the transient diffusion problem in the whole domain
    """
    def __init__(self, config):
        """ 
        a config class must be passed in that contains the required settings
        """
        self.cfg = config
        self.verbose = self.cfg.get('general.verbose')
        self.time_period = self.cfg.get('time.time_period')
        self.delta_t = self.cfg.get('time.dt')
        self.steps = int((self.time_period*(1.+self.delta_t*1e-6)) // self.delta_t)
        #set correct delta_t
        self.delta_t = self.time_period / self.steps
        if self.verbose:
            print "Timestep used in yarn1d model:", self.delta_t
        
        self.diff_coef = self.cfg.get('diffusion.diffusion_coeff')
        self.init_conc_func = eval(self.cfg.get('initial.init_conc1d'))
        
        self.number_fiber = self.cfg.get('fiber.number_fiber')
        self.blend = self.cfg.get('fiber.blend')
        self.blend = [x/100. for x in self.blend]
        self.nr_models = self.cfg.get('fiber.number_type')
        assert self.nr_models == len(self.blend) == len(self.cfg.get('fiber.fiber_config'))

        #Initialize the tortuosity
        self.tortuosity = self.cfg.get('yarn.tortuosity')
        
        #construct the config for the fibers
        self.cfg_fiber = []
        for filename in self.cfg.get('fiber.fiber_config'):
            if not os.path.isabs(filename):
                filename = os.path.normpath(os.path.join(
                            os.path.dirname(self.cfg.filename), filename))
            self.cfg_fiber.append(FiberConfigManager.get_instance(filename))
            #set values from the yarn on this inifile
            self.cfg_fiber[-1].set("time.time_period", self.time_period)
            if self.cfg_fiber[-1].get("time.dt") > self.cfg.get("time.dt"):
                self.cfg_fiber[-1].set("time.dt", self.cfg.get("time.dt"))
            #we need stepwize solution, we select cvode
            self.cfg_fiber[-1].set("general.method", 'FVM')
            self.cfg_fiber[-1].set("general.submethod", 'cvode_step')
            #we check that boundary is transfer or evaporation
            bty = self.cfg_fiber[-1].get("boundary.type_right")
            if bty not in ['evaporation', 'transfer']:
                raise ValueError, 'Boundary type for a fiber should be evaporation or transfer'
            if self.verbose:
                print 'NOTE: Fiber has boundary out of type %s' %  bty
            #set data in case fiber with extension area is used
            self.cfg_fiber[-1].set("fiber.extenddiff", self.diff_coef/self.tortuosity)

        #some memory
        self.step_old_time = None
        self.step_old_sol = None
        
        #use the area function for calculating porosity
        self.prob_area = eval(self.cfg.get('fiber.prob_area'))
        # boundary data
        self.bound_type = conf.BOUND_TYPE[self.cfg.get('boundary.type_right')]
        self.boundary_conc_out = self.cfg.get('boundary.conc_out')
        self.boundary_D_out = self.cfg.get('boundary.D_out')
        self.boundary_dist = self.cfg.get('boundary.dist_conc_out')
        self.boundary_transf_right = self.cfg.get('boundary.transfer_coef')
        self.nr_fibers = self.cfg.get('fiber.number_fiber')
        
        self.plotevery = self.cfg.get("plot.plotevery")
        self.writeevery = self.cfg.get("plot.writeevery")
        
        #allow a multiscale model to work with a source in overlap zone
        self.source_overlap = 0.

        self.initialized = False
    
        self.fiberconc_center = 0
        self.fiberconc_middle = 0
        self.fiberconc_surface = 0
    
    def times(self, timestep, end=None):
        """ Compute the time at one of our steps
        If end is given, all times between step timestep and step end are 
        returned as a list, with end included
        """
        if end is None:
            return timestep * self.delta_t
        else:
            begin = timestep * self.delta_t
            end = end * self.delta_t
            return np.linspace(begin, end, end-begin + 1)

    def create_mesh(self):
        """
        Create a mesh for use in the model.
        We use an equidistant mesh!
        
        grid: the space position of each central point for every cell element (r-coordinate);
        """
        self.end_point = self.cfg.get('domain.yarnradius')
        self.nr_edge = self.cfg.get('domain.n_edge')
        self.nr_cell = self.nr_edge - 1
        self.use_extend = self.cfg.get("domain.useextension")
        self.fiberlayout_method = self.cfg.get('domain.fiberlayout_method')
        self.areaextend = 0.
        if self.use_extend:
            self.end_extend = self.end_point + \
                self.cfg.get('domain.extensionfraction') * self.end_point
            self.nr_edge_extend = max(2, 
                    int(self.nr_edge*self.cfg.get('domain.extensionfraction')))
            self.areaextend = np.pi * (self.end_extend**2 - self.end_point**2)
        else:
            self.end_extend = self.end_point
            self.nr_edge_extend = 1
        #we now construct the full edge grid
        self.nr_edge_tot = self.nr_edge + self.nr_edge_extend - 1
        self.nr_cell_tot = self.nr_edge_tot - 1
        self.grid_edge = np.empty(self.nr_edge_tot, float)
        self.grid_edge[:self.nr_edge] = np.linspace(0., 
                                    self.end_point, self.nr_edge)
        self.grid_edge[self.nr_edge:] = np.linspace(self.end_point,
                                    self.end_extend, self.nr_edge_extend)[1:]
        #construct cell centers from this
        self.grid = (self.grid_edge[:-1] + self.grid_edge[1:])/2.
        #obtain cell sizes
        self.delta_r = self.grid_edge[1:] - self.grid_edge[:-1]
        grid_square = np.power(self.grid_edge, 2)
        self.delta_rsquare = grid_square[1:] - grid_square[:-1]

        #create fiber models as needed: one per fibertype and per cell in the yarn model
        self.fiber_models = [0] * (self.nr_edge - 1)
        self.fiber_mass = np.empty((self.nr_edge - 1, self.nr_models), float)
        self.source_mass = np.empty((self.nr_edge - 1, self.nr_models), float)
        self.source_conc = np.empty((self.nr_edge - 1, self.nr_models), float)
        self.source = np.zeros(self.nr_edge_tot - 1, float)
        for ind in range(self.nr_edge-1):
            self.fiber_models[ind] = []
            for cfg in self.cfg_fiber:
                cfg.set("fiber.extendinit_conc",  self.init_conc_func(self.grid[ind]))
                self.fiber_models[ind].append(FiberModel(cfg))

        #calculate the porosity as n=(pi Ry^2-nr_fibers pi Rf^2) / pi Ry^2
        #porosity in the yarn
        self.porosity = np.ones(self.nr_cell_tot, float)
        self.volfracfib = []  # volume fraction of the fiber types
        if self.fiberlayout_method == 'virtlocoverlap':
            value_from_areafunction = np.zeros(self.nr_cell, float)
            for i_porosity in range(len(self.prob_area)):
                function_area = self.prob_area[i_porosity]
                value_from_areafunction += function_area(self.grid[:])
                #plot the value from the function and the porosity value to check
                #the calculation for porosity
                plt.figure()
                plt.plot(self.grid[:], 1 - value_from_areafunction, '-', color = 'red')
                plt.plot(self.grid[:], 1 - function_area(self.grid[:]), '*')
                plt.xlabel('Yarn domain')
                plt.ylabel('value')
                plt.ylim(0., 1.0)
                plt.show()
            self.porosity[:self.nr_cell] = 1. - value_from_areafunction[:self.nr_cell]
        else:
            for blend, model in zip(self.blend, self.fiber_models[0]):
                print 'fiberradius', model.radius(), 'yarnradius', self.end_point   
                self.volfracfib.append(
                        blend * self.nr_fibers *  np.power(model.radius(), 2)
                                / np.power(self.end_point, 2) )
                if np.sum(self.volfracfib) > 1:
                    raise ValueError, 'porosity  negative, unrealistic number of fibers in yarn cross section, %f fibers per yarn * Rf^2/Ry^2 = %f' % (self.nr_fibers,np.sum(self.volfracfib))
                    raw_input()
            self.porosity[:self.nr_cell] = 1 - np.sum(self.volfracfib)
            #print 'porosity in yarn', self.porosity[:self.nr_cell], 

        #nrf is number of fibers in the shell at that grid position
        # per radial
        if not self.fiberlayout_method == 'virtlocoverlap':
            self.nrf_shell = (self.delta_rsquare[:self.nr_cell]
                                / (self.end_point**2) * self.nr_fibers)
        else:
            raise NotImplementedError, 'nrfibers per shell still to determine'

        #we now have porosity and fiber models, we can calculate area extend available
        for ind in range(self.nr_edge-1):
            for fibmod in self.fiber_models[ind]:
                area_extend = np.pi * self.delta_rsquare[ind] \
                                    * self.porosity[ind] / self.nrf_shell[ind]
                fibmod.set_areaextend(area_extend) # set fiber.extendarea in the fiber model!

        #create cylindrical 1D grid over domain for using fipy to view.
        if self.plotevery:
            self.mesh_yarn = CylindricalGrid1D(dr=tuple(self.delta_r[:self.nr_cell]))
            self.mesh_yarn.periodicBC = False
            self.mesh_yarn = self.mesh_yarn

        #print 'mesh yarn', self.grid_edge, ', delta_r yarn', self.delta_r

    def initial_yarn1d(self):
        """ initial concentration over the domain"""
        self.init_conc = np.empty(self.nr_cell_tot, float)
        #zero to the outside
        for ind, r in enumerate(self.grid[:self.nr_cell]):
            self.init_conc[ind] = self.init_conc_func(r)
        self.init_conc[self.nr_cell:] = self.boundary_conc_out

    def get_data(self, cellnr):
        index = cellnr
        return index

    def out_conc(self, data, t):
        """
        return the concentration of compound in the void zone of cell cellnr at
        time t
        """
        timenowyarn = self.step_old_time
        if t >= timenowyarn:
            #return data
            return self.step_old_sol[data]
        raise ValueError, 'out concentration should only be requested at a later time'

    def solve_fiber_init(self):
        """
        Solve the diffusion process for a repellent on the fiber at radial position r in the yarn.
        &C/&t = 1/r * &(Dr&C/&r) / &r
        The diffusion coefficient is constant. The finite volume method is used to
        discretize the right side of equation. The mesh in this 1-D condition is 
        uniform.
        """
        for ind, models in enumerate(self.fiber_models):
            for type, model in enumerate(models):
                model.run_init()
                model.solve_init()
                #rebind the out_conc method to a call to yarn1d
                if model.use_extend:
                    model.set_outconc(self.out_conc(ind, 0))
                else:
                    model.set_userdata(self.get_data(ind))
                    model.out_conc = lambda t, data: self.out_conc(data, t)
                self.fiber_mass[ind, type] = model.calc_mass(model.initial_c1)
                self.fiberconc_center = model.initial_c1[0]
                n = int((model.tot_edges_no_extend-2)/2)
                self.fiberconc_middle = model.initial_c1[n]
                self.fiberconc_surface = model.initial_c1[model.tot_edges_no_extend-2]

    def do_fiber_step(self, stoptime):
        """
        Solve the diffusion process on the fiber up to stoptime, starting
        from where we where last. 
        The flux is the BC: S*h(C_equi - C_yarn(t))*H(C-C_b,C_equi-C_yarn(t))
        """
        for ind, models in enumerate(self.fiber_models):
            for type, model in enumerate(models):
                if model.use_extend:
                    model.set_outconc(self.out_conc(ind, self.step_old_time))
                time, result = model.do_step(stoptime, needreinit=True)
                self.fiberconc_center = result[0]
                n = int((model.tot_edges_no_extend-2)/2)
                self.fiberconc_middle = result[n]
                self.fiberconc_surface = result[model.tot_edges_no_extend-2]
                #filedata= open(utils.OUTPUTDIR + os.sep + "fiberconc_%05d" %stoptime + ".txt",'w')
                #filedata.write("conc on %.10f is %s" % (stoptime,result))
                #filedata.close()
                tmp = model.calc_mass(result)
                self.source_mass[ind, type] = self.fiber_mass[ind, type] - tmp
                self.fiber_mass[ind, type] = tmp
                                
    def get_fiber_conc(self):
        """
        method for reading fiberconcentrations from roommodel for last computed
        fiber in the yarn
        """
        return self.fiberconc_center, self.fiberconc_middle, self.fiberconc_surface
                
    def _set_bound_flux(self, flux_edge, conc_r):
        """
        Method that takes BC into account to set flux on edge
        flux here is the flux per radial
        Data is written to flux_edge, conc_r contains solution in the cell centers
        """
        flux_edge[0] = 0.
        #avergage porosity on edge:
        if self.use_extend:
            porright = (self.porosity[self.nr_cell-1] + self.porosity[self.nr_cell]) / 2
        else:
            porright = (self.porosity[self.nr_cell-1] + 1.) / 2
        diffright = (self.diff_coef/self.tortuosity + self.boundary_D_out)/ 2
        if self.bound_type == conf.TRANSFER:
            # tranfer flux, in x: flux_x  = tf * C, so radially per radial a flux
            #  flux_radial = 2 Pi * radius * flux_x / 2 * Pi
            flux_edge[self.nr_edge-1] = self.boundary_transf_right * porright \
                    * conc_r[self.nr_cell-1] * self.grid_edge[self.nr_edge-1]
        elif self.bound_type == conf.DIFF_FLUX:
            # diffusive flux with the outside
            # flux radial = - D_out * (conc_out - yarn_edge_conc)/dist_conc_out * radius
            if self.use_extend:
                conright = conc_r[self.nr_cell]
                bcdist = (self.delta_r[self.nr_cell-1] + self.delta_r[self.nr_cell]) / 2.
            else:
                conright = self.boundary_conc_out
                bcdist = self.boundary_dist
            flux_edge[self.nr_edge-1] = -(diffright * porright * 
                    (conright - conc_r[self.nr_cell-1]) 
                    / bcdist 
                    * self.grid_edge[self.nr_edge-1])
        if self.use_extend:
            #zero flux at right boundary
            flux_edge[-1] = 0.

    def calc_mass(self, conc):
        """
        calculate current amount of mass of volatile based on data currently
        stored
        """
        #first we calculate the mass in the void space:
        mass = np.sum(conc[:self.nr_cell] *
                     (np.power(self.grid_edge[1:self.nr_edge], 2) -
                       np.power(self.grid_edge[:self.nr_edge-1], 2)) *
                     self.porosity[:self.nr_cell]
                    ) * np.pi
##        print "mass in void space yarn", mass
        #now we add the mass in the fibers
        for ind, pos in enumerate(self.grid[:self.nr_cell]):
            for type, blend in enumerate(self.blend):
                #nrf_shell is number of fibers of blend in the shell at that grid position
                massfib = (self.fiber_mass[ind, type]
                            * self.nrf_shell[ind] * blend)
                #print 'mass fiber', self.fiber_mass[ind,type], 'nr fibers per shell', self.nrf_shell[ind]
                mass += massfib
        #print 'yarn conc', conc
        #print 'yarn totalmass',  mass, 'microgram'
        return mass

    def calc_mass_overlap(self, conc):
        """
        calculate current amount of mass of volatile in the overlap region
        based on data currently stored. From mol/microm^2 to mol
        """
        #we calculate the mass in the void space:
        mass = np.sum(conc[self.nr_cell:] * 
                      (np.power(self.grid_edge[self.nr_edge:], 2) -
                        np.power(self.grid_edge[self.nr_edge-1:-1], 2)) *
                      self.porosity[self.nr_cell:]
                     ) * np.pi
        #print "porosity",self.porosity
        ##print 'yarn mass overlap', conc[self.nr_cell:], mass
        return mass

    def set_source(self, timestep):
        ## we calculated the source_mass from a fiber, using upscaling via volume averaging technique:
        ## source conc = nrf_shell * conc_r * \int_{r_{i+1}}^r_i rdr / V = nrf_shell * conc_r / (2*\pi)
        ## source mass = source conc * V = nrf_shell * conc_r * (r_{i+1}^2-r_i^2)*pi / 2*pi

        """
        Method to calculate the radial source term
        Per radial we have the global equation 
           \partial_t (n r C) = \partial_r (D/tau) r \partial_r (n C) + r Source
        where Source is mass per time per volume released/absorbed by the fibers
        So Source = nrf_shell * mass_source_fiber / (V \Delta t)
        This equation is integrated over a shell and devided by n (the porosity),
        and we determine 
           n d_t w, with w = rC, where the sourceterm is \int_{r_i}^{r_{i+1}} r Source dr
        and is the term here calculated and stored in self.source
        As we assume Source constant over a shell by averaging out the mass over
        the area of void space of a shell (nV), we have
            Source = nrf_shell * mass_source_fiber/(nV \Delta t) * \Delta r_i^2 / 2
        self.source_mass contains per shell how much mass was released in 
        previous step by one fiber. Suppose this mass is M. 
        We determine how many fibers there are radially, multiply this with M
        and divide by volume V * porosity n \delta t to obtain Source-concentration,
        since concentration is mass/volume time. 
        Afterwards we multiply this Source with \Delta r_i^2 / (2 n \Delta r)
        coming from the integration (int n d_t w gives the term n \Delta r).
        """
        for ind, pos in enumerate(self.grid_edge[:self.nr_cell]):
            self.source[ind] = 0.
            #V is the area of the shell
            V = np.pi*((pos+self.delta_r[ind])**2-pos**2)
            for type, blend in enumerate(self.blend):
                #nrf_shell is number of fibers of blend in the shell at that grid position
                # per radial
                # self.source_mass is the mass coming out of one fiber, we need a concentration
                # so,nrf_shell * self.source_conc = (nrf_shell * self.source_mass) / (porosity*V_shell)
                self.source_conc[ind,type] = (self.source_mass[ind, type] 
                                                / (self.porosity[ind]*V) )
                self.source[ind] += (self.source_conc[ind, type]
                                        * self.nrf_shell[ind] * blend)
            self.source[ind] /= timestep
        ## Note: source must be per second, so divided by the timestep

    def f_conc1_ode(self, t, conc_r, diff_u_t):
        """
        Solving the radial yarn 1D diffusion equation: 
        
         n \partial_t (rC) =  \partial_r (D/tau r n \partial_r C) + Source * r
        
        with Source the conc amount per time unit added at r. 
        Solution is obtained by integration over a cell, so
        
         n \delta r d_t (r C) = flux_right - flux_left + Source (\delta r^2 /2)
        
        so
        
         n d_t C = 1 / (r \delta r) * (flux_right - flux_left + Source (\delta r^2 /2) )
        """
        grid = self.grid
        #Initialize the flux rate on the edges
        flux_edge = self.__tmp_flux_edge
        #set flux on edge 0, self.nr_edge-1 and -1
        self._set_bound_flux(flux_edge, conc_r)

        #calculate flux rate in each edge of the domain
        flux_edge[1:self.nr_edge-1] = -(2 * (self.diff_coef/self.tortuosity) *
            self.grid_edge[1:self.nr_edge-1] *
            (conc_r[1:self.nr_cell]-conc_r[:self.nr_cell-1])
            /(self.delta_r[:self.nr_cell-1]+self.delta_r[1:self.nr_cell])
            * (self.porosity[:self.nr_cell-1] + self.porosity[1:self.nr_cell])/2
            )
        if self.use_extend:
            # diffusion in the outside region
            flux_edge[self.nr_edge:-1] = -(2 * self.boundary_D_out *
              self.grid_edge[self.nr_edge:-1] *
              (conc_r[self.nr_cell+1:]-conc_r[self.nr_cell:-1])
              /(self.delta_r[self.nr_cell:-1]+self.delta_r[self.nr_cell+1:])
              * (self.porosity[self.nr_cell:-1] + self.porosity[self.nr_cell+1:])/2
              )
        diff_u_t[:] = ((flux_edge[:-1]-flux_edge[1:])
                            / self.delta_r[:]/ self.porosity[:]
                    + self.source[:] * self.delta_rsquare / 2
                      / self.delta_r
                      )
        if self.use_extend and self.source_overlap:
            #porosity assumed 1 in extend!
            diff_u_t[self.nr_cell:] += (self.source_overlap
                            * self.delta_rsquare[self.nr_cell:] / 2
                            / self.delta_r[self.nr_cell:])
        diff_u_t[:] = diff_u_t[:] / self.grid[:]  # still division by r to move from w to C

    def solve_ode_init(self):
        """
        Initialize the ode solver
        """
        self.initial_t = 0.
        self.step_old_time = self.initial_t
        n_cells = len(self.init_conc)
        self.ret_y = np.empty(n_cells, float)
        self.__tmp_flux_edge = np.empty(n_cells+1, float)
        self.tstep = 0
        self.step_old_sol = np.empty(n_cells, float)
        self.step_old_sol[:] = self.init_conc[:]
        
        self.solver = sc_ode('cvode', self.f_conc1_ode,
                             min_step_size=1e-9,
                             first_step_size=1e-16,
                             rtol=1e-6, atol=1e-10,
                             max_steps=50000, lband=1, uband=1)
        self.solver.init_step(self.step_old_time, self.init_conc)
        self.initialized = True

    def do_ode_step(self, stoptime):
        """Solve the yarnmodel up to stoptime, continuing from the present
           state, return the time, concentration after step
        """
        #fix where next to stop
        self.solver.set_options(tstop=stoptime)
        if not self.initialized:
            raise Exception, 'Solver ode not initialized'
        #solve the problem
        flag, realtime = self.solver.step(stoptime, self.ret_y)
        if flag < 0:
            raise Exception, 'could not find solution, flag %d' % flag
        assert np.allclose(realtime, stoptime), "%f %f" % (realtime, stoptime)
        return stoptime, self.ret_y

    def do_yarn_init(self):
        """
        generic initialization needed before yarn can be solved
        """
        self.create_mesh()
        self.initial_yarn1d()
        if not self.initialized:
            self.solve_ode_init()
        self.solve_fiber_init()

    def do_yarn_step(self, stoptime):
        """
        Solve yarn up to time t. This does:
           1. solve the fiber up to t
           2. set correct source term for the yarn
           3. solve the yarn up to t
        """
        compute = True
        #even is step is large, we don't compute for a longer time than delta_t
        t = self.step_old_time
        while compute:
            t +=  self.delta_t
            if  t >= stoptime - self.delta_t/100.:
                t = stoptime
                compute = False
            self.do_fiber_step(t)
            self.set_source(t-self.step_old_time)
            #we need to reinit as rhs changed
            if REINIT_ALWAYS:
                self.solver.init_step(self.step_old_time, self.step_old_sol)
            realtime, self.step_old_sol = self.do_ode_step(t)
            self.tstep += 1
            self.step_old_time = t
#        filedata= open(utils.OUTPUTDIR + os.sep + "fiberconccenter" + ".txt",'w')
#        for i in range(0,len(self.fiberconc_center)):
#            filedata.write("%.5f %.5f\n" % (self.fiberconc_center[i,0],self.fiberconc_center[i,1]))
#        filedata.close()
#        filedata= open(utils.OUTPUTDIR + os.sep + "fiberconcmiddle" + ".txt",'w')
#        for i in range(0,len(self.fiberconc_middle)):
#            filedata.write("%.5f %.5f\n" % (self.fiberconc_middle[i,0],self.fiberconc_middle[i,1]))
#        filedata.close()
#        filedata= open(utils.OUTPUTDIR + os.sep + "fiberconcsurface" + ".txt",'w')
#        for i in range(0,len(self.fiberconc_surface)):
#            filedata.write("%.5f %.5f\n" % (self.fiberconc_surface[i,0],self.fiberconc_surface[i,1]))
#        filedata.close()
        
        return realtime, self.step_old_sol

    def view_sol(self, times, conc):
        """
        Show the solution in conc with times.
        conc[i][:] contains solution at time times[i]
        """
        if self.plotevery:
            self.solution_view = CellVariable(name="Yarn radial concentration",
                        mesh=self.mesh_yarn, value=conc[0][:self.nr_cell])
            if isinstance(conc, np.ndarray):
                maxv = conc.max() * 1.2
                minv = conc.min() * 0.9
            else:
                maxv = np.max(conc) * 1.2
                minv = np.min(conc) * 0.9
            self.viewer =  Matplotlib1DViewer(vars=self.solution_view,
                                datamin=minv, datamax=maxv)
            self.viewerplotcount = 0
            self.viewerwritecount = 0
            for time, con in zip(times, conc):
                self.solution_view.setValue(con[:self.nr_cell])
                if self.viewerplotcount == 0 or (self.writeevery and 
                                            self.viewerwritecount == 0):
                    self.viewer.axes.set_title('time %s' %str(time))
                    if self.writeevery and self.viewerwritecount == 0:
                        #plot and savefig
                        self.viewer.plot(filename=utils.OUTPUTDIR + os.sep \
                                                + 'yarnconc%08.4f.png' % time)
                    else:
                        #only plot
                        self.viewer.plot()
                self.viewerplotcount += 1
                self.viewerplotcount = self.viewerplotcount % self.plotevery
                if self.writeevery:
                    self.viewerwritecount += 1
                    self.viewerwritecount = self.viewerwritecount % self.writeevery

    def run(self, wait=False):
        self.do_yarn_init()
        #data storage, will lead to memerror if many times !
        n_cells = len(self.init_conc)
        self.conc1 = np.empty((self.steps+1, n_cells), float)
        self.conc1[0][:] = self.init_conc[:]
        
        print 'Start mass of DEET per grid cell per fiber type'
        for ind, masses in enumerate(self.fiber_mass):
            print 'cell', ind,
            for mass in masses:
                print mass, ' - ',
            print ' '
        mc1 = self.calc_mass(self.step_old_sol)
        mc2 = self.calc_mass_overlap(self.step_old_sol)
        print 'Total mass in yarn', mc1, ', mass in overlap zone:', mc2, \
                'Sum', mc1 + mc2

        tstep = 0
        t = self.times(tstep+1)
        while t <= self.time_period+self.delta_t/10:
            tstep += 1
            #print 'solving t', t
            rt, rety = self.do_yarn_step(t)
            self.conc1[self.tstep][:] = self.ret_y[:]
            t = self.times(tstep+1)
        

        print 'Final mass of DEET per grid cell per fiber type'
        for ind, masses in enumerate(self.fiber_mass):
            print 'cell', ind,
            for mass in masses:
                print mass, ' - ',
            print ' '
        mc1 = self.calc_mass(self.step_old_sol)
        mc2 = self.calc_mass_overlap(self.step_old_sol)
        print 'Total mass in yarn', mc1, ', mass in overlap zone:', mc2, \
                'Sum', mc1 + mc2

        self.view_sol(self.times(0,self.steps), self.conc1)

        if wait:
            raw_input("Finished yarn1d run")
Exemple #30
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
Exemple #31
0
from fipy.solvers import *

from parameters import *

# ----------------- Solver --------------------------------
mySolver = LinearGMRESSolver(iterations=1000, tolerance=1.0e-6)

# ----------------- Mesh Generation -----------------------
nx = 100
L = 5.0
mesh = Grid1D(nx=nx, Lx=L)

x = mesh.cellCenters[0]  # Cell position

# ----------------- Variable Declarations -----------------
density = CellVariable(name=r"$n$", mesh=mesh, hasOld=True)
temperature = CellVariable(name=r"$T$", mesh=mesh, hasOld=True)
Z = CellVariable(name=r"$Z$", mesh=mesh, hasOld=True)

Diffusivity = CellVariable(name=r"$D$", mesh=mesh, hasOld=True)

# ----------- Initial Conditions of Z ---------------------
Z0L = 1.0  # L--mode
Z0H = Z_S * (1.0 - numerix.tanh((L * x - L) / 2.0))  # H--mode
Z.setValue(Z0H)

# ----------------- Diffusivities -------------------------
# Itohs'/Zohm's model
D_Zohm = (D_max + D_min) / 2.0 + ((D_max - D_min) * numerix.tanh(Z)) / 2.0
# Stap's Model
alpha_sup = 0.5
Exemple #32
0
valueRight = 0.
L = 10.
nx = 400
dx = L / nx
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,
del logLevel, logFilename

R_outer = 2e-6  #SETTING  must match what is in .geo file
R_inner = 1e-6  #SETTING  must match what is in .geo file
cellSize = .05 * (R_outer - R_inner)  #SETTING  must match what is in .geo file

#run gmsh gui to produce this mesh (.msh file)
#gmsh infiniteCylinder01.geo
filename = 'infiniteCylinder01.msh'
mesh = Gmsh2D(filename, communicator=serialComm)
del filename

T_initial = 425.08  #deg K
T_infinity = 293.15  #deg K  #SETTING

var = CellVariable(mesh=mesh,
                   value=T_initial - T_infinity)  #let var be T-T_infinity

rho = 6980.  #kg/m^3
cp = 227.  #J/kg/K
k = 59.6  #W/m/K
D_thermal = k / rho / cp

X_faces, Y_faces = mesh.faceCenters

surfaceFaces = (Y_faces > 0) & (
    (X_faces**2 + Y_faces**2)**.5 > R_outer - cellSize / 10.)

#convectionCoeff=200.  #W/m^2/K
Bi_desired = 10.  #SETTING
convectionCoeff = Bi_desired * k / R_inner
logging.info('convection coefficient is %.2E' % convectionCoeff)
Exemple #34
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
    """Initial potential"""
    return a1 * np.sin(b1 * x + c1) + a2 * np.sin(b2 * x + c2)


mesh = Grid1D(dx=dx, nx=nx)  #Establish mesh in how many dimensions necessary

##############################################################################
#################''' SETUP CELLVARIABLES AND EQUATIONS '''####################
##############################################################################

#CellVariable - defines the variables that you want to solve for:
'''Initial value can be established when defining the variable, or later using 'var.value =' 
   Value defaults to zero if not defined'''

Pion = CellVariable(mesh=mesh,
                    name='Positive ion Charge Density',
                    value=y01(x))

Nion = CellVariable(mesh=mesh,
                    name='Negative ion Charge Density',
                    value=y02(x))

potential = CellVariable(mesh=mesh, name='Potential', value=y03(x))

#EQUATION SETUP BASIC DESCRIPTION
'''Equations to solve for each varible must be defined:
  -TransientTerm = dvar/dt
  -ConvectionTerm = dvar/dx
  -DiffusionTerm = d^2var/dx^2
  -Source terms can be described as they would appear mathematically
Notes:  coeff = terms that are multiplied by the Term.. must be rank-1 FaceVariable for ConvectionTerm
Exemple #36
0
from builtins import input
if __name__ == '__main__':
    import sys
    import os

    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,
Exemple #37
0
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 = dy = 1.0        # mesh resolution
dt = Variable(0.1) # initial timestep

# 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()
Extrude {{ {{1, 0, 0}}, {{0, 0, 0}}, Pi/2}} {{
  Surface{{16}}; 
}}

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)
Exemple #40
0
from __future__ import division
from __future__ import unicode_literals

from builtins import input
__docformat__ = 'restructuredtext'

from fipy import Tri2D, CellVariable, DiffusionTerm, Viewer

nx = 50
dx = 1.

mesh = Tri2D(dx = dx, nx = nx)

valueLeft = 0.
valueRight = 1.
var = CellVariable(name = "solution-variable", mesh = mesh, value = valueLeft)

var.constrain(valueLeft, mesh.facesLeft)
var.constrain(valueRight, mesh.facesRight)

if __name__ == '__main__':
    DiffusionTerm().solve(var)
    viewer = Viewer(vars=var)
    viewer.plot()
    x = mesh.cellCenters[0]
    Lx = nx * dx
    analyticalArray = valueLeft + (valueRight - valueLeft) * x / Lx
    print(var.allclose(analyticalArray))
    input("finished")

Exemple #41
0
import time
from fipy import PeriodicGrid2D

from params_fipy import (A_RAW, NOISE_MAGNITUDE, TIME_MAX, DT, N_CELLS,
                         DOMAIN_LENGTH, TIME_STRIDE, chi_AB, N_A, N_B, GIBBS,
                         DESIRED_RESIDUAL)

print("Yay")

# # Define mesh
# mesh = Grid2D(dx=dx, dy=dx, nx=N_CELLS, ny=N_CELLS)
mesh = PeriodicGrid2D(nx=50.0, ny=50.0, dx=0.1, dy=0.1)
print("mesh loaded")

# We need to define the relevant variables:
x_a = CellVariable(name=r"x_a", mesh=mesh, hasOld=1)
mu_AB = CellVariable(name=r"mu_AB", mesh=mesh, hasOld=1)

# We need to introduce the noise
noise = GaussianNoiseVariable(mesh=mesh, mean=A_RAW,
                              variance=NOISE_MAGNITUDE).value

x_a[:] = noise

# x_a.setValue(GaussianNoiseVariable(mesh=mesh,
#                                    mean=A_RAW,
#                                    variance=NOISE_MAGNITUDE)
# )

# def g(x_a):
#     if GIBBS == "FH":
Exemple #42
0
class Circumbinary(object):
    def __init__(self, rmax=1.0e4, ncell=300, dt=1.0e-6, delta=1.0e-100,
                 fudge=1.0e-3, q=1.0, gamma=100, mdisk=0.1, odir='output',
                 bellLin=True, emptydt=0.001, **kargs):
        self.rmax = rmax
        self.ncell = ncell
        self.dt = dt
        self.delta = delta
        self.mDisk = mdisk
        Omega0 = (G*M/(gamma*a)**3)**0.5
        nu0 = alpha*cs**2/Omega0
        self.chi = 2*fudge*q**2*np.sqrt(G*M)/nu0/a*(gamma*a)**1.5
        self.T0 = mu*Omega0/alpha/k*nu0
        self.gamma = gamma
        self.fudge = fudge
        self.q = q
        self.nu0 = nu0
        self.t = 0.0
        self.odir = odir
        self.bellLin = bellLin
        self.emptydt = emptydt
        self._genGrid()
        self.r = self.mesh.cellCenters.value[0]
        self.rF = self.mesh.faceCenters.value[0]
        if self.q > 0.0:
            self.gap = np.where(self.rF < 1.7/gamma)
        else:
            self.gap = np.where(self.rF < 1.0/gamma)
        self._genSigma()
        self._genTorque()
        self._genT(bellLin=self.bellLin, **kargs)
        self._genVr()
        self._buildEq()

    def _genGrid(self, inB=1.0):
        """Generate a logarithmically spaced grid"""
        logFaces = np.linspace(-np.log(self.gamma/inB), np.log(self.rmax), num=self.ncell+1)
        logFacesLeft = logFaces[:-1]
        logFacesRight = logFaces[1:]
        dr = tuple(np.exp(logFacesRight) - np.exp(logFacesLeft))
        self.mesh = CylindricalGrid1D(dr=dr, origin=(inB/self.gamma,))

    def _genSigma(self, width=0.1):
        """Create dependent variable Sigma"""
        # Gaussian initial condition
        value = self.mDisk*M/np.sqrt(2*np.pi)/(self.gamma*a*width)*\
                np.exp(-0.5*np.square(self.r-1.0)/width**2)/(2*np.pi*self.gamma*self.r*a)
        # Make it dimensionless
        value /= self.mDisk*M/(self.gamma*a)**2
        idxs = np.where(self.r < 0.1)
        value[idxs] = 0.0
        value = tuple(value)

        # Create the dependent variable and set the boundary conditions
        # to zero
        self.Sigma = CellVariable(name='Surface density',
                                 mesh=self.mesh, hasOld=True, value=value)
        #self.Sigma.constrain(0, self.mesh.facesLeft)
        #self.Sigma.constrain(0, self.mesh.facesRight)

    def _genTorque(self):
        """Generate Torque"""
        self.Lambda = FaceVariable(name='Torque at cell faces', mesh=self.mesh, rank=1)
        self.LambdaCell = CellVariable(name='Torque at cell centers', mesh=self.mesh)
        LambdaArr = np.zeros(self.rF.shape)
        LambdaArr[1:] = self.chi*np.power(1.0/(self.rF[1:]*self.gamma-1.0), 4)
        #LambdaArr[self.gap] = 0.0; LambdaArr[self.gap] = LambdaArr.max()
        self.Lambda.setValue(LambdaArr)
        self.LambdaCell.setValue(self.chi*np.power(1.0/(self.r*self.gamma-1.0), 4))
        self.LambdaCell[np.where(self.LambdaCell > LambdaArr.max())] = LambdaArr.max()

    def _interpT(self):
        """
        Get an initial guess for T using an interpolation of the solutions for T
        in the various thermodynamic limits.
        """
        Lambda = self.Lambda/self.chi*self.fudge*self.q**2*G*M/a
        LambdaCell = self.LambdaCell/self.chi*self.fudge*self.q**2*G*M/a
        Sigma = self.Sigma*M/(self.gamma*a)**2
        r = self.r*a*self.gamma #In physical units (cgs)
        self.Omega = np.sqrt(G*M/r**3)
        self.TvThin = np.power(9.0/4*alpha*k/sigma/mu/kappa0*self.Omega, 1.0/(3.0+beta))
        self.TtiThin = np.power(1/sigma/kappa0*(OmegaIn-self.Omega)*LambdaCell, 1.0/(4.0+beta))
        self.Ti = np.power(np.square(eta/7*L/4/np.pi/sigma)*k/mu/G/M*r**(-3), 1.0/7)
        self.TvThick = np.power(27.0/64*kappa0*alpha*k/sigma/mu*self.Omega*Sigma**2, 1.0/(3.0-beta))
        self.TtiThick = np.power(3*kappa0/16/sigma*Sigma**2*(OmegaIn-self.Omega)*LambdaCell, 1.0/(4.0-beta))
        #return np.power(self.TvThin**4 + self.TvThick**4 + self.TtiThin**4 + self.TtiThick**4 + self.Ti**4, 1.0/4)/self.T0
        return np.power(self.TvThin**4 + self.TvThick**4 + self.Ti**4, 1.0/4)/self.T0

    def _genT(self, bellLin=True, **kargs):
        """Create a cell variable for temperature"""
        if bellLin:
            @pickle_results(os.path.join(self.odir, "interpolator.pkl"))
            def buildInterpolator(r, gamma, q, fudge, mDisk, **kargs):
                # Keep in mind that buildTemopTable() returns the log10's of the values
                rGrid, SigmaGrid, temp = thermopy.buildTempTable(r*a*gamma, q=q, f=fudge, **kargs)
                # Go back to dimensionless units
                rGrid -= np.log10(a*gamma)
                SigmaGrid -= np.log10(mDisk*M/gamma**2/a**2)
                # Get the range of values for Sigma in the table
                rangeSigma = (np.power(10.0, SigmaGrid.min()), np.power(10.0, SigmaGrid.max()))
                # Interpolate in the log of dimensionless units
                return rangeSigma, RectBivariateSpline(rGrid, SigmaGrid, temp)
            # Pass the radial grid in phsyical units
            # Get back interpolator in logarithmic space
            rangeSigma, log10Interp = buildInterpolator(self.r, self.gamma, self.q, self.fudge, self.mDisk, **kargs)
            rGrid = np.log10(self.r)
            SigmaMin = np.ones(rGrid.shape)*rangeSigma[0]
            SigmaMax = np.ones(rGrid.shape)*rangeSigma[1]
            r = self.r*a*self.gamma #In physical units (cgs)
            self.Omega = np.sqrt(G*M/r**3)
            Ti = np.power(np.square(eta/7*L/4/np.pi/sigma)*k/mu/G/M*r**(-3), 1.0/7)
            T = np.zeros(Ti.shape)
            # Define wrapper function that uses the interpolator and stores the results
            # in an array given as a second argument. It can handle zero or negative
            # Sigma values.
            def func(Sigma):
                good = np.logical_and(Sigma > rangeSigma[0], Sigma < rangeSigma[1])
                badMin = np.logical_and(True, Sigma < rangeSigma[0])
                badMax = np.logical_and(True, Sigma > rangeSigma[1])
                if np.sum(good) > 0:
                    T[good] = np.power(10.0, log10Interp.ev(rGrid[good], np.log10(Sigma[good])))
                if np.sum(badMin) > 0:
                    T[badMin] = np.power(10.0, log10Interp.ev(rGrid[badMin], np.log10(SigmaMin[badMin])))
                if np.sum(badMax) > 0:
                    raise ValueError("Extrapolation to large values of Sigma is not allowed, build a table with a larger Sigmax")
                    T[badMax] = np.power(10.0, log10Interp.ev(rGrid[badMax], np.log10(SigmaMax[badMax])))
                return T
            # Store interpolator as an instance method
            self._bellLinT = func
            # Save the temperature as an operator variable
            self.T = self.Sigma._UnaryOperatorVariable(lambda x: self._bellLinT(x))

        # Initialize T with the interpolation of the various thermodynamic limits
        else:
            self.T = self._interpT()

    def _genVr(self):
        """Generate the face variable that stores the velocity values"""
        r = self.r #In dimensionless units (cgs)
        # viscosity at cell centers in cgs
        self.nu = alpha*k/mu/self.Omega/self.nu0*self.T
        self.visc = r**0.5*self.nu*self.Sigma
        #self.visc.grad.constrain([self.visc/2/self.r[0]], self.mesh.facesLeft)
        #self.Sigma.constrain(self.visc.grad/self.nu*2*self.r**0.5, where=self.mesh.facesLeft)
        # I add the delta to avoid divisions by zero
        self.vrVisc = -3/self.rF**(0.5)/(self.Sigma.faceValue + self.delta)*self.visc.faceGrad
        if self.q > 0.0:
            self.vrTid = self.Lambda*np.sqrt(self.rF)

    def _buildEq(self):
        """
        Build the equation to solve, we can change this method to impelement other
        schemes, e.g. Crank-Nicholson.
        """
        # The current scheme is an implicit-upwind
        if self.q > 0.0:
            self.vr = self.vrVisc + self.vrTid
            self.eq = TransientTerm(var=self.Sigma) == - ExplicitUpwindConvectionTerm(coeff=self.vr, var=self.Sigma)
        else:
            self.vr = self.vrVisc
            mask_coeff = (self.mesh.facesLeft * self.mesh.faceNormals).getDivergence()
            self.eq = TransientTerm(var=self.Sigma) == - ExplicitUpwindConvectionTerm(coeff=self.vr, var=self.Sigma)\
                                                       - mask_coeff*3.0/2*self.nu/self.mesh.x*self.Sigma.old

    def dimensionalSigma(self):
        """
        Return Sigma in dimensional form (cgs)
        """
        return self.Sigma.value*self.mDisk*M/(self.gamma*a)**2

    def dimensionalFJ(self):
        """
        Return the viscous torque in dimensional units (cgs)
        """
        return 3*np.pi*self.nu.value*self.nu0*self.dimensionalSigma()*np.sqrt(G*M*self.r*a*self.gamma)

    def dimensionalTime(self, t=None, mode='yr'):
        """
        Return current time in dimensional units (years or seconds)
        """
        if t == None:
            t = self.t
        if mode == 'yr' or mode == 'years' or mode == 'year':
            return t*(a*self.gamma)**2/self.nu0/(365*24*60*60)
        else:
            return t*(a*self.gamma)**2/self.nu0

    def dimensionlessTime(self, t, mode='yr'):
        """
        Returns the dimensionless value of the time given as an argument
        """
        if mode == 'yr' or mode == 'years' or mode == 'year':
            return t/(a*self.gamma)**2*self.nu0*(365*24*60*60)
        else:
            return t/(a*self.gamma)**2*self.nu0

    def singleTimestep(self, dtMax=0.001, dt=None, update=True, emptyDt=False):
        """
        Evolve the system for a single timestep of size `dt`
        """
        if dt:
            self.dt = dt
        if emptyDt:
            vr = self.vr.value[0]
            if self.q == 0.0:
                vr[0] = -3.0/2*self.nu.faceValue.value[0]/self.rF[0]
            #vr[np.where(self.Sigma.value)] = self.delta
            self.flux = self.rF[1:]*vr[1:]-self.rF[:-1]*vr[:-1]
            self.flux = np.maximum(self.flux, self.delta)
            self.dts = self.mesh.cellVolumes/(self.flux)
            self.dts[np.where(self.Sigma.value == 0.0)] = np.inf
            self.dts[self.gap] = np.inf
            self.dt = self.emptydt*np.amin(self.dts)
        self.dt = min(dtMax, self.dt)
        try:
            self.eq.sweep(dt=self.dt)
            if np.any(self.Sigma.value < 0.0):
                self.singleTimestep(dt=self.dt/2)
            if update:
                self.Sigma.updateOld()
            self.t += self.dt
        except FloatingPointError:
            import ipdb; ipdb.set_trace()

    def evolve(self, deltaTime, **kargs):
        """
        Evolve the system using the singleTimestep method
        """
        tEv = self.t + deltaTime
        while self.t < tEv:
            dtMax = tEv - self.t
            self.singleTimestep(dtMax=dtMax, **kargs)

    def revert(self):
        """
        Revert evolve method if update=False was used, otherwise
        it has no effect.
        """
        self.Sigma.setValue(self.Sigma.old.value)

    def writeToFile(self):
        fName = self.odir + '/t{0}.pkl'.format(self.t)
        with open(fName, 'wb') as f:
            pickle.dump((self.t, self.Sigma.getValue()), f)

    def readFromFile(self, fName):
        with open(fName, 'rb') as f:
            t, Sigma = pickle.load(f)
        self.t = t
        self.Sigma.setValue(Sigma)

    def loadTimesList(self):
        path = self.odir
        files = os.listdir(path)
        if '.DS_Store' in files:
            files.remove('.DS_Store')
        if 'interpolator.pkl' in files:
            files.remove('interpolator.pkl')
        if 'init.pkl' in files:
            files.remove('init.pkl')
        self.times = np.zeros((len(files),))
        for i, f in enumerate(files):
            match = re.match(r"^t((\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)\.pkl", f)
            if match == None:
                print "WARNING: File {0} has an unexepected name".format(f)
                files.remove(f)
                continue
            self.times[i] = float(match.group(1))
        self.times.sort()
        self.files = files

    def loadTime(self, t):
        """
        Load the file with the time closest to `t`
        """
        idx = (np.abs(self.times-t)).argmin()
        fName = self.odir + '/t'+str(self.times[idx]) + '.pkl'
        self.readFromFile(fName)
Exemple #43
0
def y02(x):
    """"Initial negative ion charge density"""
    return nini * ((special.gamma(k2 + p2)) /
                   (special.gamma(k2) * special.gamma(p2)) *
                   ((x / l)**(k2 - 1)) * (1 - (x / l))**(p2 - 1)) / 7.3572


def y03(x):
    """Initial potential"""
    return a1 * np.sin(b1 * x + c1) + a2 * np.sin(b2 * x + c2)


mesh = Grid1D(dx=dx, nx=nx)

Pion = CellVariable(mesh=mesh,
                    name='Positive ion Charge Density',
                    value=y01(mesh.x))
Nion = CellVariable(mesh=mesh,
                    name='Negative ion Charge Density',
                    value=y02(mesh.x))
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(
#!/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()
Exemple #45
0
steps = 100
timeStepDuration = 0.02
L = 1.5
nx = 100
temperature = 1.
phaseTransientCoeff = 0.1
epsilon = 0.008
s = 0.01
alpha = 0.015
temperature = 1.

dx = L / nx

mesh = Grid1D(dx=dx, nx=nx)

phase = CellVariable(name='PhaseField', mesh=mesh, value=1.)

theta = ModularVariable(name='Theta', mesh=mesh, value=1.)
theta.setValue(0., where=mesh.cellCenters[0] > L / 2.)

mPhiVar = phase - 0.5 + temperature * phase * (1 - phase)
thetaMag = theta.old.grad.mag
implicitSource = mPhiVar * (phase - (mPhiVar < 0))
implicitSource += (2 * s + epsilon**2 * thetaMag) * thetaMag

phaseEq = TransientTerm(phaseTransientCoeff) == \
          ExplicitDiffusionTerm(alpha**2) \
          - ImplicitSourceTerm(implicitSource) \
          + (mPhiVar > 0) * mPhiVar * phase

if __name__ == '__main__':
Exemple #46
0
nx = 8 # FIXME: downsized temporarily from 10 due to https://github.com/usnistgov/fipy/issues/622
ny = 5
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.
Exemple #47
0
nx = 40
dx = L / nx
cfl = 0.5
velocity = 1.0
dt = cfl * dx / velocity

steps = int(L / 4. / dt / velocity)

mesh = Grid1D(dx=dx, nx=nx)

periodicMesh = PeriodicGrid1D(dx=dx, nx=nx // 2)

startingArray = numerix.zeros(nx, 'd')
startingArray[2 * nx // 10:3 * nx // 10] = 1.

var1 = CellVariable(name="non-periodic", mesh=mesh, value=startingArray)

var2 = CellVariable(name="periodic",
                    mesh=periodicMesh,
                    value=startingArray[:nx // 2])

eq1 = TransientTerm() - VanLeerConvectionTerm(coeff=(-velocity, ))
eq2 = TransientTerm() - VanLeerConvectionTerm(coeff=(-velocity, ))

if __name__ == '__main__':

    viewer1 = Viewer(vars=var1)
    viewer2 = Viewer(vars=var2)
    viewer1.plot()
    viewer2.plot()
Exemple #48
0
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