C_ani.remove() mesh = self.phase.mesh shape = mesh.shape x, y = mesh.cellCenters z = self.phase.value x, y, z = [a.reshape(shape, order='F') for a in (x, y, z)] # self.contour = self.axes.contour(X, Y, Z, (0.5,)) viewer = DendriteViewer(phase=phase, D_temp=D_temp, title=r'%s & %s' % (phase.name, D_temp.name), datamin=-0.1, datamax=0.05) except ImportError: viewer = DendriteViewer(viewers=(Viewer( vars=phase), Viewer(vars=D_temp, datamin=-0.5, datamax=0.5))) if __name__ == "__main__": steps = 500 else: steps = 10 from builtins import range for i in range(steps): phase.updateOld() D_temp.updateOld() phase_EQ.solve(phase, dt=D_time) heatEQ.solve(D_temp, dt=D_time) if __name__ == "__main__" and (i % 10 == 0): viewer.plot()
duration = TIME_MAX time_stride = TIME_STRIDE timestep = 0 # Defining the solver to improve numerical stabilty solver = LinearLUSolver(tolerance=1e-9, iterations=50, precon="lu") # solver = PETSc.KSP().create() start = time.time() while elapsed < duration: if (timestep == 0): vw = VTKCellViewer(vars=(x_a, mu_AB)) vw.plot(filename="0_output.%d.vtk" % (parallelComm.procID)) elapsed += dt timestep += 1 x_a.updateOld() mu_AB.updateOld() res = 1e+10 while res > 1e-10: res = eq.sweep(dt=dt, solver=solver) x_a.setValue(0.0, where=x_a < 0.0) x_a.setValue(1.0, where=x_a > 1.0) print("sweep!") print(elapsed) end = time.time() print(end - start) if (timestep % time_stride == 0): vw = VTKCellViewer(vars=(x_a, mu_AB)) vw.plot(filename="%s_output.%d.vtk" % (elapsed, parallelComm.procID))
logging.info('sweeping is used') for step in range(steps): #sweep res = 1e10 sweepCount = 0 while res > resTol and (sweepCount <= maxSweeps): sweepCount = sweepCount + 1 res = eq.sweep(var=var, dt=dt) if res > resTol: logging.error('unable to sweep to tolerance at step %d; quitting' % step) sys.exit() var.updateOld() if (step > 0) and (step % plotEvery == 0): if showViewer: viewer.plot() print 'step is %d' % step #time.sleep(1.5) raw_input('hit enter to continue') else: s_ray, var_ray = get_solution_along_ray( soln=var, R_inner=R_inner, R_outer=R_outer, cellSize=cellSize, rayAngle=rayAngle,
time_stride = 100 timestep = 0 elapsed = 0 # Initialising the viewer if __name__ == "__main__": viewer = Viewer(vars=(a), datamin=0., datamax=1.) # start the time start = time.time() # Time stepping while elapsed < duration: elapsed += dt timestep += 1 a.updateOld() mu_AB.updateOld() res = 1e4 while res > 1e-10: res = eq.sweep(dt=dt, solver=solver) print("sweep") print(res) print(elapsed) end = time.time() print(end - start) if (timestep % time_stride == 0): print("Beep") if __name__ == '__main__': viewer.plot() if __name__ == '__main__': input("Press <return> to proceed...")
#!/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()
dt = DT if __name__ == "__main__": duration = TIME_MAX time_stride = TIME_STRIDE timestep = 0 # Defining the solver solver = LinearLUSolver(tolerance=1e-10, iterations=50) start = time.time() while elapsed < duration: if (timestep == 0): vw = VTKCellViewer(vars=(x_a, xi)) vw.plot(filename="0_output.%d.vtk" %(parallelComm.procID)) elapsed += dt timestep += 1 x_a.updateOld() xi.updateOld() res = 1e+10 while res > 1e-10: res = eq.sweep(dt=dt, solver=solver) print ("sweep!") print (elapsed) end = time.time() print(end-start) if (timestep % time_stride ==0): vw = VTKCellViewer(vars=(x_a, xi)) vw.plot(filename="%s_output.%d.vtk" %(elapsed, parallelComm.procID))
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)
v0 = CellVariable(mesh=m, hasOld=True, value=0.5) v1 = CellVariable(mesh=m, hasOld=True, value=0.5) v0.constrain(0, m.facesLeft) v0.constrain(1, m.facesRight) v1.constrain(1, m.facesLeft) v1.constrain(0, m.facesRight) eq0 = TransientTerm() == DiffusionTerm(coeff=0.01) - v1.faceGrad.divergence eq1 = TransientTerm() == v0.faceGrad.divergence + DiffusionTerm(coeff=0.01) vi = Viewer((v0, v1)) for t in range(100): v0.updateOld() v1.updateOld() res0 = res1 = 1e100 while max(res0, res1) > 0.1: res0 = eq0.sweep(var=v0, dt=1e-5) res1 = eq1.sweep(var=v1, dt=1e-5) if t % 10 == 0: vi.plot() # eqn0 = TransientTerm(var=v0) == DiffusionTerm(0.01, var=v0) - DiffusionTerm(1, var=v1) # eqn1 = TransientTerm(var=v1) == DiffusionTerm(1, var=v0) + DiffusionTerm(0.01, var=v1) # eqn = eqn0 & eqn1 # for t in range(1): # v0.updateOld()
# Serial: #from fipy.solvers.pysparse import LinearLUSolver as Solver #solver_heat = Solver() #solver_phase = Solver() # Parallel: mpirun with --trilinos for proper meshing, etc. from fipy.solvers.trilinos import LinearGMRESSolver as Solver solver_heat = Solver(precon=None) solver_phase = Solver(precon=None) elapsed_time = 0.0 current_step = 0 while current_step < total_steps: uu.updateOld() phase.updateOld() res_heat0 = heat_eqn.sweep(uu, dt=dt.value, solver=solver_heat) res_phase0 = phase_eqn.sweep(phase, dt=dt.value, solver=solver_phase) for sweep in range(sweeps): res_heat = heat_eqn.sweep(uu, dt=dt.value, solver=solver_heat) res_phase = phase_eqn.sweep(phase, dt=dt.value, solver=solver_phase) if sweep == 0: res_heat1 = res_heat res_phase1 = res_phase print print 'sweep',sweep print res_heat print res_phase