def create(self, pc): self.diag = None kspNS = PETSc.KSP() kspNS.create(comm=PETSc.COMM_WORLD) pcNS = kspNS.getPC() kspNS.setType('gmres') pcNS.setType('python') pcNS.setPythonContext( NSprecond.PCDdirect( MixedFunctionSpace([self.Fspace[0], self.Fspace[1]]), self.Q, self.F, self.L)) kspNS.setTolerances(1e-3) kspNS.setFromOptions() self.kspNS = kspNS kspM = PETSc.KSP() kspM.create(comm=PETSc.COMM_WORLD) pcM = kspM.getPC() kspM.setType('gmres') pcM.setType('python') kspM.setTolerances(1e-3) pcM.setPythonContext( MP.Direct(MixedFunctionSpace([self.Fspace[2], self.Fspace[3]]))) kspM.setFromOptions() self.kspM = kspM
def increase_order(V): """ For a given function space, return the same space, but with a higher polynomial degree """ n = V.num_sub_spaces() if n > 0: spaces = [] for i in range(n): V_i = V.sub(i) element = V_i.ufl_element() # Handle VectorFunctionSpaces specially if isinstance(element, ufl.VectorElement): spaces += [ VectorFunctionSpace(V_i.mesh(), element.family(), element.degree() + 1, dim=element.num_sub_elements()) ] # Handle all else as MixedFunctionSpaces else: spaces += [increase_order(V_i)] return MixedFunctionSpace(spaces) if V.ufl_element().family() == "Real": return FunctionSpace(V.mesh(), "Real", 0) return FunctionSpace(V.mesh(), V.ufl_element().family(), V.ufl_element().degree() + 1)
def derivative(form, u, du=None, coefficient_derivatives=None): if du is None: # Get existing arguments from form and position the new one with the next argument number from ufl.algorithms import extract_arguments form_arguments = extract_arguments(form) number = max([-1] + [arg.number() for arg in form_arguments]) + 1 if any(arg.part() is not None for arg in form_arguments): cpp.dolfin_error( "formmanipulation.py", "compute derivative of form", "Cannot automatically create third argument using parts, please supply one" ) part = None if isinstance(u, Function): V = u.function_space() du = Argument(V, number, part) elif isinstance(u, (list, tuple)) and all( isinstance(w, Function) for w in u): V = MixedFunctionSpace([w.function_space() for w in u]) du = ufl.split(Argument(V, number, part)) else: cpp.dolfin_error( "formmanipulation.py", "compute derivative of form", "Cannot automatically create third argument, please supply one" ) return ufl.derivative(form, u, du, coefficient_derivatives)
def change_regularity(V, family): """ For a given function space, return the corresponding space with the finite elements specified by 'family'. Possible families are the families supported by the form compiler """ n = V.num_sub_spaces() if n > 0: return MixedFunctionSpace([change_regularity(V.sub(i), family) for i in range(n)]) element = V.ufl_element() shape = element.value_shape() if not shape: return FunctionSpace(V.mesh(), family, element.degree()) return MixedFunctionSpace([FunctionSpace(V.mesh(), family, element.degree()) for i in range(shape[0])])
def ball_in_tube(): mesh = Mesh("../meshes/2d/ball-in-tube-cylindrical-coarse4.xml") V0 = FunctionSpace(mesh, "CG", 2) V1 = FunctionSpace(mesh, "B", 3) V = V0 + V1 W = MixedFunctionSpace([V, V]) P = FunctionSpace(mesh, "CG", 1) # Define mesh and boundaries. class LeftBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] < GMSH_EPS left_boundary = LeftBoundary() class RightBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] > 1.0 - GMSH_EPS right_boundary = RightBoundary() class LowerBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] < GMSH_EPS lower_boundary = LowerBoundary() class UpperBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] > 5.0 - GMSH_EPS class CoilBoundary(SubDomain): def inside(self, x, on_boundary): # One has to pay a little bit of attention when defining the # coil boundary; it's easy to miss the edges closest to x[0]=0. return ( on_boundary and x[1] > 1.0 - GMSH_EPS and x[1] < 2.0 + GMSH_EPS and x[0] < 1.0 - GMSH_EPS ) coil_boundary = CoilBoundary() u_bcs = [ DirichletBC(W, (0.0, 0.0), right_boundary), DirichletBC(W.sub(0), 0.0, left_boundary), DirichletBC(W, (0.0, 0.0), lower_boundary), DirichletBC(W, (0.0, 0.0), coil_boundary), ] p_bcs = [] # p_bcs = [DirichletBC(Q, 0.0, upper_boundary)] return mesh, W, P, u_bcs, p_bcs
def rotating_lid(): mesh = UnitSquareMesh(20, 20, "left/right") # Define mesh and boundaries. class LeftBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] < GMSH_EPS class RightBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] > 1.0 - GMSH_EPS class LowerBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] < GMSH_EPS class UpperBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] > 1.0 - DOLFIN_EPS class RestrictedUpperBoundary(SubDomain): def inside(self, x, on_boundary): return ( on_boundary and x[1] > 1.0 - DOLFIN_EPS and DOLFIN_EPS < x[0] and x[0] < 0.5 - DOLFIN_EPS ) left = LeftBoundary() right = RightBoundary() lower = LowerBoundary() upper = UpperBoundary() restricted_upper = RestrictedUpperBoundary() V = FunctionSpace(mesh, "CG", 2) W = MixedFunctionSpace([V, V, V]) u_bcs = [ DirichletBC(W.sub(0), 0.0, left), DirichletBC(W.sub(2), 0.0, left), DirichletBC(W, Constant((0.0, 0.0, 0.0)), right), DirichletBC(W.sub(0), 0.0, upper), DirichletBC(W.sub(1), 0.0, upper), DirichletBC(W.sub(2), Expression("x[0]", degree=1), restricted_upper), DirichletBC(W, Constant((0.0, 0.0, 0.0)), lower), ] P = FunctionSpace(mesh, "CG", 1) p_bcs = [] return mesh, W, P, u_bcs, p_bcs
def derivative(form, u, du=None): if du is None: if isinstance(u, Function): V = u.function_space() du = Argument(V) elif isinstance(u, (list, tuple)) and all( isinstance(w, Function) for w in u): V = MixedFunctionSpace([w.function_space() for w in u]) du = ufl.split(Argument(V)) else: cpp.dolfin_error( "formmanipulation.py", "compute derivative of form", "Cannot automatically create third argument, please supply one" ) return ufl.derivative(form, u, du)
def make_function_spaces(mesh, element): 'Create mixed function space on the mesh.' assert hasattr(element, 'V') and hasattr(element, 'Q') # Create velocity space n = len(element.V) assert n > 0 V = VectorFunctionSpace(mesh, *element.V[0]) for i in range(1, n): V += VectorFunctionSpace(mesh, *element.V[i]) # Create pressure space assert len(element.Q) == 1 Q = FunctionSpace(mesh, *element.Q[0]) M = MixedFunctionSpace([V, Q]) return V, Q, M
def createMixedFSi(Vs): """ Create MixedFunctionSpace from V1 and V2 """ Vdim = Vs[0].dim() Vms = Vs[0].mesh().size(0) for V in Vs: assert Vdim == V.dim() assert Vms == V.mesh().size(0) try: V1V2 = MixedFunctionSpace(Vs) except: Vsfem = [] for V in Vs: Vsfem.append(V.ufl_element()) V1V2 = FunctionSpace(Vs[0].mesh(), MixedElement(Vsfem)) return V1V2
v1 = Constant((1.0, 0.0)) v2 = Constant((-1.0, 0.0)) def left(x, on_boundary): return on_boundary and near(x[0], 0.0) def right(x, on_boundary): return on_boundary and near(x[0], 1.0) mesh = RectangleMesh(Point(0.0, 0.0), Point(1.0, 1.0), 50, 50) dt = 0.01 S = FunctionSpace(mesh, 'CG', 1) W = MixedFunctionSpace([S, S]) u = Function(W) T, Tf = split(u) # T, Tf = TrialFunctions(W) T_t, Tf_t = TestFunctions(W) T0 = interpolate(Expression('1.0 / (10.0 * x[0] + 1.0)'), S) Tf0 = interpolate(Expression('1.0 / (10.0 * (1.0 - x[0]) + 1.0)'), S) heat_transfer = 10.0 * (Tf - T) * dt r_1 = T_t * ( (T - T0) + dt * dot(v1, grad(T)) - heat_transfer) * dx
def solve(A,b,u,IS,Fspace,IterType,OuterTol,InnerTol,HiptmairMatrices,KSPlinearfluids,kspF,Fp,MatrixLinearFluids,kspFp): if IterType == "Full": kspOuter = PETSc.KSP().create() kspOuter.setTolerances(OuterTol) kspOuter.setType('fgmres') u_is = PETSc.IS().createGeneral(range(Fspace[0].dim())) p_is = PETSc.IS().createGeneral(range(Fspace[0].dim(),Fspace[0].dim()+Fspace[1].dim())) Bt = A.getSubMatrix(u_is,p_is) reshist = {} def monitor(ksp, its, fgnorm): reshist[its] = fgnorm print "OUTER:", fgnorm kspOuter.setMonitor(monitor) pcOutter = kspOuter.getPC() pcOutter.setType(PETSc.PC.Type.KSP) kspOuter.setOperators(A,A) kspOuter.max_it = 500 kspInner = pcOutter.getKSP() kspInner.max_it = 100 kspInner.max_it = 100 reshist1 = {} def monitor(ksp, its, fgnorm): reshist1[its] = fgnorm print "INNER:", fgnorm # kspInner.setMonitor(monitor) kspInner.setType('gmres') kspInner.setTolerances(InnerTol) pcInner = kspInner.getPC() pcInner.setType(PETSc.PC.Type.PYTHON) pcInner.setPythonContext(MHDstabPrecond.InnerOuterWITHOUT(Fspace,kspF, KSPlinearfluids[0], KSPlinearfluids[1],Fp, HiptmairMatrices[3], HiptmairMatrices[4], HiptmairMatrices[2], HiptmairMatrices[0], HiptmairMatrices[1], HiptmairMatrices[6],1e-6,A)) PP = PETSc.Mat().createPython([A.size[0], A.size[0]]) PP.setType('python') p = PrecondMulti.MultiApply(Fspace,A,HiptmairMatrices[6],MatrixLinearFluids[1],MatrixLinearFluids[0],kspFp, HiptmairMatrices[3]) PP.setPythonContext(p) kspInner.setOperators(PP) tic() scale = b.norm() b = b/scale print b.norm() kspOuter.solve(b, u) u = u*scale print toc() # print s.getvalue() NSits = kspOuter.its del kspOuter Mits = kspInner.its del kspInner # print u.array return u,NSits,Mits NS_is = IS[0] M_is = IS[1] kspNS = PETSc.KSP().create() kspM = PETSc.KSP().create() kspNS.setTolerances(OuterTol) kspNS.setOperators(A.getSubMatrix(NS_is,NS_is)) kspM.setOperators(A.getSubMatrix(M_is,M_is)) del A uNS = u.getSubVector(NS_is) bNS = b.getSubVector(NS_is) kspNS.setType('gmres') pcNS = kspNS.getPC() kspNS.setTolerances(OuterTol) pcNS.setType(PETSc.PC.Type.PYTHON) if IterType == "MD": pcNS.setPythonContext(NSpreconditioner.NSPCD(MixedFunctionSpace([Fspace[0],Fspace[1]]), kspF, KSPlinearfluids[0], KSPlinearfluids[1],Fp)) else: pcNS.setPythonContext(StokesPrecond.MHDApprox(MixedFunctionSpace([Fspace[0],Fspace[1]]), kspF, KSPlinearfluids[1])) scale = bNS.norm() bNS = bNS/scale start_time = time.time() kspNS.solve(bNS, uNS) print ("{:25}").format("NS, time: "), " ==> ",("{:4f}").format(time.time() - start_time),("{:9}").format(" Its: "), ("{:4}").format(kspNS.its), ("{:9}").format(" time: "), ("{:4}").format(time.strftime('%X %x %Z')[0:5]) uNS = scale*uNS NSits = kspNS.its # kspNS.destroy() # for line in reshist.values(): # print line kspM.setFromOptions() kspM.setType(kspM.Type.MINRES) kspM.setTolerances(InnerTol) pcM = kspM.getPC() pcM.setType(PETSc.PC.Type.PYTHON) pcM.setPythonContext(MP.Hiptmair(MixedFunctionSpace([Fspace[2],Fspace[3]]), HiptmairMatrices[3], HiptmairMatrices[4], HiptmairMatrices[2], HiptmairMatrices[0], HiptmairMatrices[1], HiptmairMatrices[6],1e-6)) # x = x*scale uM = u.getSubVector(M_is) bM = b.getSubVector(M_is) scale = bM.norm() bM = bM/scale start_time = time.time() kspM.solve(bM, uM) print ("{:25}").format("Maxwell solve, time: "), " ==> ",("{:4f}").format(time.time() - start_time),("{:9}").format(" Its: "), ("{:4}").format(kspM.its), ("{:9}").format(" time: "), ("{:4}").format(time.strftime('%X %x %Z')[0:5]) uM = uM*scale Mits = kspM.its kspM.destroy() u = IO.arrayToVec(np.concatenate([uNS.array, uM.array])) return u,NSits,Mits
def solve(A, b, u, P, IS, Fspace, IterType, OuterTol, InnerTol, Mass=0, L=0, F=0): # u = b.duplicate() if IterType == "Full": kspOuter = PETSc.KSP().create() kspOuter.setTolerances(OuterTol) kspOuter.setType('fgmres') reshist = {} def monitor(ksp, its, fgnorm): reshist[its] = fgnorm print "OUTER:", fgnorm kspOuter.setMonitor(monitor) pcOutter = kspOuter.getPC() pcOutter.setType(PETSc.PC.Type.KSP) kspOuter.setOperators(A) kspOuter.max_it = 500 kspInner = pcOutter.getKSP() kspInner.max_it = 100 reshist1 = {} def monitor(ksp, its, fgnorm): reshist1[its] = fgnorm print "INNER:", fgnorm # kspInner.setMonitor(monitor) kspInner.setType('gmres') kspInner.setTolerances(InnerTol) pcInner = kspInner.getPC() pcInner.setType(PETSc.PC.Type.PYTHON) pcInner.setPythonContext(MHDprecond.D(Fspace, P, Mass, F, L)) PP = PETSc.Mat().createPython([A.size[0], A.size[0]]) PP.setType('python') p = PrecondMulti.P(Fspace, P, Mass, L, F) PP.setPythonContext(p) kspInner.setOperators(PP) tic() scale = b.norm() b = b / scale print b.norm() kspOuter.solve(b, u) u = u * scale print toc() # print s.getvalue() NSits = kspOuter.its del kspOuter Mits = kspInner.its del kspInner # print u.array return u, NSits, Mits NS_is = IS[0] M_is = IS[1] kspNS = PETSc.KSP().create() kspM = PETSc.KSP().create() kspNS.setTolerances(OuterTol) kspNS.setOperators(A.getSubMatrix(NS_is, NS_is), P.getSubMatrix(NS_is, NS_is)) kspM.setOperators(A.getSubMatrix(M_is, M_is), P.getSubMatrix(M_is, M_is)) # print P.symmetric A.destroy() P.destroy() if IterType == "MD": kspNS.setType('gmres') kspNS.max_it = 500 pcNS = kspNS.getPC() pcNS.setType(PETSc.PC.Type.PYTHON) pcNS.setPythonContext( NSprecond.PCDdirect(MixedFunctionSpace([Fspace[0], Fspace[1]]), Mass, F, L)) elif IterType == "CD": kspNS.setType('minres') pcNS = kspNS.getPC() pcNS.setType(PETSc.PC.Type.PYTHON) pcNS.setPythonContext( StokesPrecond.Approx(MixedFunctionSpace([Fspace[0], Fspace[1]]))) reshist = {} def monitor(ksp, its, fgnorm): reshist[its] = fgnorm print fgnorm # kspNS.setMonitor(monitor) uNS = u.getSubVector(NS_is) bNS = b.getSubVector(NS_is) # print kspNS.view() scale = bNS.norm() bNS = bNS / scale print bNS.norm() kspNS.solve(bNS, uNS) uNS = uNS * scale NSits = kspNS.its kspNS.destroy() # for line in reshist.values(): # print line kspM.setFromOptions() kspM.setType(kspM.Type.MINRES) kspM.setTolerances(InnerTol) pcM = kspM.getPC() pcM.setType(PETSc.PC.Type.PYTHON) pcM.setPythonContext(MP.Direct(MixedFunctionSpace([Fspace[2], Fspace[3]]))) uM = u.getSubVector(M_is) bM = b.getSubVector(M_is) scale = bM.norm() bM = bM / scale print bM.norm() kspM.solve(bM, uM) uM = uM * scale Mits = kspM.its kspM.destroy() u = IO.arrayToVec(np.concatenate([uNS.array, uM.array])) return u, NSits, Mits
def solve(self, problem): self.problem = problem doSave = problem.doSave save_this_step = False onlyVel = problem.saveOnlyVel dt = self.metadata['dt'] nu = Constant(self.problem.nu) self.tc.init_watch('init', 'Initialization', True, count_to_percent=False) self.tc.init_watch('solve', 'Running nonlinear solver', True, count_to_percent=True) self.tc.init_watch('next', 'Next step assignments', True, count_to_percent=True) self.tc.init_watch('saveVel', 'Saved velocity', True) self.tc.start('init') mesh = self.problem.mesh # Define function spaces (P2-P1) self.V = VectorFunctionSpace(mesh, "Lagrange", 2) # velocity self.Q = FunctionSpace(mesh, "Lagrange", 1) # pressure self.W = MixedFunctionSpace([self.V, self.Q]) self.PS = FunctionSpace( mesh, "Lagrange", 2) # partial solution (must be same order as V) self.D = FunctionSpace(mesh, "Lagrange", 1) # velocity divergence space # to assign solution in space W.sub(0) to Function(V) we need FunctionAssigner (cannot be assigned directly) fa = FunctionAssigner(self.V, self.W.sub(0)) velSp = Function(self.V) problem.initialize(self.V, self.Q, self.PS, self.D) # Define unknown and test function(s) NS v, q = TestFunctions(self.W) w = Function(self.W) dw = TrialFunction(self.W) u, p = split(w) # Define fields n = FacetNormal(mesh) I = Identity(u.geometric_dimension()) theta = 0.5 # Crank-Nicholson k = Constant(self.metadata['dt']) # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure [u0, p0] = self.problem.get_initial_conditions([{ 'type': 'v', 'time': 0.0 }, { 'type': 'p', 'time': 0.0 }]) if doSave: problem.save_vel(False, u0) # boundary conditions bcu, bcp = problem.get_boundary_conditions(False, self.W.sub(0), self.W.sub(1)) # Define steady part of the equation def T(u): return -p * I + 2.0 * nu * sym(grad(u)) def F(u, v, q): return (inner(T(u), grad(v)) - q * div(u)) * dx + inner( grad(u) * u, v) * dx # Define variational forms F_ns = (inner( (u - u0), v) / k) * dx + (1.0 - theta) * F(u0, v, q) + theta * F( u, v, q) J_ns = derivative(F_ns, w, dw) # J_ns = derivative(F_ns, w) # did not work # NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns, form_compiler_parameters=ffc_options) NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns) # (var. formulation, unknown, Dir. BC, jacobian, optional) NS_solver = NonlinearVariationalSolver(NS_problem) prm = NS_solver.parameters prm['newton_solver']['absolute_tolerance'] = 1E-08 prm['newton_solver']['relative_tolerance'] = 1E-08 # prm['newton_solver']['maximum_iterations'] = 45 # prm['newton_solver']['relaxation_parameter'] = 1.0 prm['newton_solver']['linear_solver'] = 'mumps' # prm['newton_solver']['lu_solver']['same_nonzero_pattern'] = True info(NS_solver.parameters, True) self.tc.end('init') # Time-stepping info("Running of direct method") ttime = self.metadata['time'] t = dt step = 1 while t < (ttime + dt / 2.0): self.problem.update_time(t, step) if self.MPI_rank == 0: problem.write_status_file(t) if doSave: save_this_step = problem.save_this_step # Compute begin("Solving NS ....") try: self.tc.start('solve') NS_solver.solve() self.tc.end('solve') except RuntimeError as inst: problem.report_fail(t) return 1 end() # Extract solutions: (u, p) = w.split() fa.assign(velSp, u) # we are assigning twice (now and inside save_vel), but it works with one method save_vel for direct and # projection (we could split save_vel to save one assign) if save_this_step: self.tc.start('saveVel') problem.save_vel(False, velSp) self.tc.end('saveVel') if save_this_step and not onlyVel: problem.save_div(False, u) problem.compute_err(False, u, t) problem.compute_div(False, u) # foo = Function(self.Q) # foo.assign(p) # problem.averaging_pressure(foo) # if save_this_step and not onlyVel: # problem.save_pressure(False, foo) if save_this_step and not onlyVel: problem.save_pressure(False, p) # compute functionals (e. g. forces) problem.compute_functionals(u, p, t, step) # Move to next time step self.tc.start('next') u0.assign(velSp) t = round(t + dt, 6) # round time step to 0.000001 step += 1 self.tc.end('next') info("Finished: direct method") problem.report() return 0
def lid_driven_cavity(): n = 40 mesh = RectangleMesh(0.0, 0.0, 1.0, 1.0, n, n, "crossed") # Define mesh and boundaries. class LeftBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] < DOLFIN_EPS class RightBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] > 1.0 - DOLFIN_EPS class LowerBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] < DOLFIN_EPS class UpperBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] > 1.0 - DOLFIN_EPS class RestrictedUpperBoundary(SubDomain): def inside(self, x, on_boundary): return ( on_boundary and x[1] > 1.0 - DOLFIN_EPS and DOLFIN_EPS < x[0] and x[0] < 0.5 - DOLFIN_EPS ) left = LeftBoundary() right = RightBoundary() lower = LowerBoundary() upper = UpperBoundary() # restricted_upper = RestrictedUpperBoundary() V = FunctionSpace(mesh, "CG", 2) # Be particularly careful with the boundary conditions. # The main problem here is that the PPE system is consistent if and only # if # # \int_\Omega div(u) = \int_\Gamma n.u = 0. # # This is exactly and even pointwise fulfilled for the continuous problem. # In the discrete case, we can have to make sure that n.u is 0 all along # the boundary. # In the lid-driven cavity problem, of particular interest are the corner # points at the lid. One has to assert that the z-component of u is 0 all # across the lid, and the x-component of u is 0 everywhere but the lid. # Since u is L2-"continuous", the lid condition on u_x must not be enforced # in the corner points. The u_y component must be enforced all over the # lid, including the end points. W = MixedFunctionSpace([V, V]) u_bcs = [ DirichletBC(W, (0.0, 0.0), left), DirichletBC(W, (0.0, 0.0), right), # DirichletBC(W.sub(0), Expression('x[0]'), restricted_upper), DirichletBC(W, (0.0, 0.0), lower), DirichletBC(W.sub(0), Constant("1.0"), upper), DirichletBC(W.sub(1), 0.0, upper), # DirichletBC(W.sub(0), Constant('-1.0'), lower), # DirichletBC(W.sub(1), 0.0, lower), # DirichletBC(W.sub(1), Constant('1.0'), left), # DirichletBC(W.sub(0), 0.0, left), # DirichletBC(W.sub(1), Constant('-1.0'), right), # DirichletBC(W.sub(0), 0.0, right), ] P = FunctionSpace(mesh, "CG", 1) p_bcs = [] return mesh, W, P, u_bcs, p_bcs
def RunJob(Tb, mu_value, path): runtimeInit = clock() tfile = File(path + '/t6t.pvd') mufile = File(path + "/mu.pvd") ufile = File(path + '/velocity.pvd') gradpfile = File(path + '/gradp.pvd') pfile = File(path + '/pstar.pvd') parameters = open(path + '/parameters', 'w', 0) vmeltfile = File(path + '/vmelt.pvd') rhofile = File(path + '/rhosolid.pvd') for name in dir(): ev = str(eval(name)) if name[0] != '_' and ev[0] != '<': parameters.write(name + ' = ' + ev + '\n') temp_values = [27. + 273, Tb + 273, 1300. + 273, 1305. + 273] dTemp = temp_values[3] - temp_values[0] temp_values = [x / dTemp for x in temp_values] # non dimensionalising temp mu_a = mu_value # this was taken from the blankenbach paper, can change.. Ep = b / dTemp mu_bot = exp(-Ep * (temp_values[3] * dTemp - 1573) + cc) * mu_a Ra = rho_0 * alpha * g * dTemp * h**3 / (kappa_0 * mu_a) w0 = rho_0 * alpha * g * dTemp * h**2 / mu_a tau = h / w0 p0 = mu_a * w0 / h print(mu_a, mu_bot, Ra, w0, p0) vslipx = 1.6e-09 / w0 vslip = Constant((vslipx, 0.0)) # nondimensional noslip = Constant((0.0, 0.0)) dt = 3.E11 / tau tEnd = 3.E13 / tau # non-dimensionalising times class PeriodicBoundary(SubDomain): def inside(self, x, on_boundary): return left(x, on_boundary) def map(self, x, y): y[0] = x[0] - MeshWidth y[1] = x[1] pbc = PeriodicBoundary() class TempExp(Expression): def eval(self, value, x): if x[1] >= LAB(x): value[0] = temp_values[0] + (temp_values[1] - temp_values[0] ) * (MeshHeight - x[1]) / (MeshHeight - LAB(x)) else: value[0] = temp_values[3] - ( temp_values[3] - temp_values[2]) * (x[1]) / (LAB(x)) class FluidTemp(Expression): def eval(self, value, x): if value[0] < 1295: value[0] = 1295 mesh = RectangleMesh(Point(0.0, 0.0), Point(MeshWidth, MeshHeight), nx, ny) Svel = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc) Spre = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) Stemp = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) Smu = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) Sgradp = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc) Srho = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) S0 = MixedFunctionSpace([Svel, Spre, Stemp]) u = Function(S0) v, p, T = split(u) v_t, p_t, T_t = TestFunctions(S0) T0 = interpolate(TempExp(), Stemp) muExp = Expression( 'exp(-Ep * (T_val * dTemp - 1573) + cc * x[2] / meshHeight)', Smu.ufl_element(), Ep=Ep, dTemp=dTemp, cc=cc, meshHeight=MeshHeight, T_val=T0) mu = interpolate(muExp, Smu) rhosolid = Function(Srho) deltarho = Function(Srho) v0 = Function(Svel) vmelt = Function(Svel) v_theta = (1. - theta) * v0 + theta * v T_theta = (1. - theta) * T + theta * T0 r_v = (inner(sym(grad(v_t)), 2.*mu*sym(grad(v))) \ - div(v_t)*p \ - T*v_t[1] )*dx r_p = p_t * div(v) * dx r_T = (T_t*((T - T0) \ + dt*inner(v_theta, grad(T_theta))) \ + (dt/Ra)*inner(grad(T_t), grad(T_theta)) )*dx # + k_s*(Tf-T_theta)*dt Tf = T0.interpolate(FluidTemp()) # Tf = T0.interpolate(Expression('value[0] >= 1295.0 ? value[0] : 1295.0')) # Tf.interpolate(Expression('value[0] >= 1295 ? value[0] : 1295')) # project(Expression('value[0] >= 1295 ? value[0] : 1295'), Tf) # Alex, a question for you: # can you see if there is a way to set Tf = T in regions where T >=1295 celsius # # 1295 celsius is my arbitrary choice for the LAB isotherm. In regions # where T < 1295 C, set Tf to be some constant for now, such as 1295 C. # Once we do this, then we can add in a term like that last line above where # it will only be non-zero when the solid temperature, T, is cooler than 1295 # can you do this? After this is done, we will then worry about a calculation # where we solve for Tf as a function of time in the regions cooler than 1295 C # Makes sense? If not, we can skype soon -- email me with questions # 3/19/16 r = r_v + r_p + r_T bcv0 = DirichletBC(S0.sub(0), noslip, top) bcv1 = DirichletBC(S0.sub(0), vslip, bottom) bcp0 = DirichletBC(S0.sub(1), Constant(0.0), bottom) bct0 = DirichletBC(S0.sub(2), Constant(temp_values[0]), top) bct1 = DirichletBC(S0.sub(2), Constant(temp_values[3]), bottom) bcs = [bcv0, bcv1, bcp0, bct0, bct1] t = 0 count = 0 while (t < tEnd): solve(r == 0, u, bcs) t += dt nV, nP, nT = u.split() gp = grad(nP) rhosolid = rho_0 * (1 - alpha * (nT * dTemp - 1573)) deltarho = rhosolid - rhomelt yvec = Constant((0.0, 1.0)) vmelt = nV * w0 - darcy * (gp * p0 / h - deltarho * yvec * g) if (count % 100 == 0): pfile << nP ufile << nV tfile << nT mufile << mu gradpfile << project(grad(nP), Sgradp) mufile << project(mu * mu_a, Smu) rhofile << project(rhosolid, Srho) vmeltfile << project(vmelt, Svel) count += 1 assign(T0, nT) assign(v0, nV) mu.interpolate(muExp) print('Case mu=%g, Tb=%g complete.' % (mu_a, Tb), ' Run time =', clock() - runtimeInit, 's')
def solve(A, b, u, params, Fspace, SolveType, IterType, OuterTol, InnerTol, HiptmairMatrices, Hiptmairtol, KSPlinearfluids, Fp, kspF): if SolveType == "Direct": ksp = PETSc.KSP() ksp.create(comm=PETSc.COMM_WORLD) pc = ksp.getPC() ksp.setType('preonly') pc.setType('lu') OptDB = PETSc.Options() OptDB['pc_factor_mat_solver_package'] = "mumps" OptDB['pc_factor_mat_ordering_type'] = "rcm" ksp.setFromOptions() scale = b.norm() b = b / scale ksp.setOperators(A, A) del A ksp.solve(b, u) # Mits +=dodim u = u * scale MO.PrintStr("Number iterations = " + str(ksp.its), 60, "+", "\n\n", "\n\n") return u, ksp.its, 0 elif SolveType == "Direct-class": ksp = PETSc.KSP() ksp.create(comm=PETSc.COMM_WORLD) pc = ksp.getPC() ksp.setType('gmres') pc.setType('none') ksp.setFromOptions() scale = b.norm() b = b / scale ksp.setOperators(A, A) del A ksp.solve(b, u) # Mits +=dodim u = u * scale MO.PrintStr("Number iterations = " + str(ksp.its), 60, "+", "\n\n", "\n\n") return u, ksp.its, 0 else: # u = b.duplicate() if IterType == "Full": ksp = PETSc.KSP() ksp.create(comm=PETSc.COMM_WORLD) pc = ksp.getPC() ksp.setType('fgmres') pc.setType('python') OptDB = PETSc.Options() OptDB['ksp_gmres_restart'] = 200 # FSpace = [Velocity,Magnetic,Pressure,Lagrange] reshist = {} def monitor(ksp, its, fgnorm): reshist[its] = fgnorm print its, " OUTER:", fgnorm # ksp.setMonitor(monitor) ksp.max_it = 1000 W = Fspace FFSS = [W.sub(0), W.sub(1), W.sub(2), W.sub(3)] pc.setPythonContext( MHDprec.InnerOuterMAGNETICapprox( FFSS, kspF, KSPlinearfluids[0], KSPlinearfluids[1], Fp, HiptmairMatrices[3], HiptmairMatrices[4], HiptmairMatrices[2], HiptmairMatrices[0], HiptmairMatrices[1], HiptmairMatrices[6], Hiptmairtol)) #OptDB = PETSc.Options() # OptDB['pc_factor_mat_solver_package'] = "mumps" # OptDB['pc_factor_mat_ordering_type'] = "rcm" # ksp.setFromOptions() scale = b.norm() b = b / scale ksp.setOperators(A, A) del A ksp.solve(b, u) # Mits +=dodim u = u * scale MO.PrintStr("Number iterations = " + str(ksp.its), 60, "+", "\n\n", "\n\n") return u, ksp.its, 0 IS = MO.IndexSet(Fspace, '2by2') M_is = IS[1] NS_is = IS[0] kspNS = PETSc.KSP().create() kspM = PETSc.KSP().create() kspNS.setTolerances(OuterTol) kspNS.setOperators(A[0]) kspM.setOperators(A[1]) # print P.symmetric if IterType == "MD": kspNS.setType('gmres') kspNS.max_it = 500 pcNS = kspNS.getPC() pcNS.setType(PETSc.PC.Type.PYTHON) pcNS.setPythonContext( NSpreconditioner.NSPCD( MixedFunctionSpace([Fspace.sub(0), Fspace.sub(1)]), kspF, KSPlinearfluids[0], KSPlinearfluids[1], Fp)) elif IterType == "CD": kspNS.setType('minres') pcNS = kspNS.getPC() pcNS.setType(PETSc.PC.Type.PYTHON) Q = KSPlinearfluids[1].getOperators()[0] Q = 1. / params[2] * Q KSPlinearfluids[1].setOperators(Q, Q) pcNS.setPythonContext( StokesPrecond.MHDApprox( MixedFunctionSpace([Fspace.sub(0), Fspace.sub(1)]), kspF, KSPlinearfluids[1])) reshist = {} def monitor(ksp, its, fgnorm): reshist[its] = fgnorm print fgnorm # kspNS.setMonitor(monitor) uNS = u.getSubVector(NS_is) bNS = b.getSubVector(NS_is) # print kspNS.view() scale = bNS.norm() bNS = bNS / scale print bNS.norm() kspNS.solve(bNS, uNS) uNS = uNS * scale NSits = kspNS.its kspNS.destroy() # for line in reshist.values(): # print line kspM.setFromOptions() kspM.setType(kspM.Type.MINRES) kspM.setTolerances(InnerTol) pcM = kspM.getPC() pcM.setType(PETSc.PC.Type.PYTHON) pcM.setPythonContext( MP.Hiptmair(MixedFunctionSpace([Fspace.sub(2), Fspace.sub(3)]), HiptmairMatrices[3], HiptmairMatrices[4], HiptmairMatrices[2], HiptmairMatrices[0], HiptmairMatrices[1], HiptmairMatrices[6], Hiptmairtol)) uM = u.getSubVector(M_is) bM = b.getSubVector(M_is) scale = bM.norm() bM = bM / scale print bM.norm() kspM.solve(bM, uM) uM = uM * scale Mits = kspM.its kspM.destroy() u = IO.arrayToVec(np.concatenate([uNS.array, uM.array])) MO.PrintStr("Number of M iterations = " + str(Mits), 60, "+", "\n\n", "\n\n") MO.PrintStr("Number of NS/S iterations = " + str(NSits), 60, "+", "\n\n", "\n\n") return u, NSits, Mits
def run_with_params(Tb, mu_value, k_s, path): run_time_init = clock() temperature_vals = [27.0 + 273, Tb + 273, 1300.0 + 273, 1305.0 + 273] temp_prof = TemperatureProfile(temperature_vals) mu_a = mu_value # this was taken from the Blankenbach paper, can change Ep = b / temp_prof.delta mu_bot = exp(-Ep * (temp_prof.bottom * temp_prof.delta - 1573.0) + cc) * mu_a Ra = rho_0 * alpha * g * temp_prof.delta * h**3 / (kappa_0 * mu_a) w0 = rho_0 * alpha * g * temp_prof.delta * h**2 / mu_a tau = h / w0 p0 = mu_a * w0 / h log(mu_a, mu_bot, Ra, w0, p0) vslipx = 1.6e-09 / w0 vslip = Constant((vslipx, 0.0)) # Non-dimensional noslip = Constant((0.0, 0.0)) time_step = 3.0E11 / tau / 10.0 dt = Constant(time_step) tEnd = 3.0E15 / tau / 5.0 # Non-dimensionalising times mesh = RectangleMesh(Point(0.0, 0.0), Point(mesh_width, mesh_height), nx, ny) pbc = PeriodicBoundary() W = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc) S = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) WSSS = MixedFunctionSpace([W, S, S, S]) # WSSS -> W u = Function(WSSS) # Instead of TrialFunctions, we use split(u) for our non-linear problem v, p, T, Tf = split(u) v_t, p_t, T_t, Tf_t = TestFunctions(WSSS) T0 = interpolate(temp_prof, S) FluidTemp = Expression('max(T0, 1.031)', T0=T0) muExp = Expression( 'exp(-Ep * (T_val * dTemp - 1573.0) + cc * x[1] / mesh_height)', Ep=Ep, dTemp=temp_prof.delta, cc=cc, mesh_height=mesh_height, T_val=T0) Tf0 = interpolate(temp_prof, S) mu = Function(S) v0 = Function(W) v_theta = (1.0 - theta) * v0 + theta * v T_theta = (1.0 - theta) * T0 + theta * T Tf_theta = (1.0 - theta) * Tf0 + theta * Tf r_v = (inner(sym(grad(v_t)), 2.0 * mu * sym(grad(v))) - div(v_t) * p - T * v_t[1]) * dx r_p = p_t * div(v) * dx heat_transfer = k_s * (Tf_theta - T_theta) * dt r_T = (T_t * ((T - T0) + dt * inner(v_theta, grad(T_theta))) + (dt / Ra) * inner(grad(T_t), grad(T_theta)) - T_t * heat_transfer) * dx # yvec = Constant((0.0, 1.0)) # rhosolid = rho_0 * (1.0 - alpha * (T_theta * temp_prof.delta - 1573.0)) # deltarho = rhosolid - rhomelt # v_f = v_theta - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0 v_melt = Function(W) yvec = Constant((0.0, 1.0)) # TODO: inner -> dot, take out Tf_t r_Tf = (Tf_t * ((Tf - Tf0) + dt * dot(v_melt, grad(Tf_theta))) + Tf_t * heat_transfer) * dx r = r_v + r_p + r_T + r_Tf bcv0 = DirichletBC(WSSS.sub(0), noslip, top) bcv1 = DirichletBC(WSSS.sub(0), vslip, bottom) bcp0 = DirichletBC(WSSS.sub(1), Constant(0.0), bottom) bct0 = DirichletBC(WSSS.sub(2), Constant(temp_prof.surface), top) bct1 = DirichletBC(WSSS.sub(2), Constant(temp_prof.bottom), bottom) bctf1 = DirichletBC(WSSS.sub(3), Constant(temp_prof.bottom), bottom) bcs = [bcv0, bcv1, bcp0, bct0, bct1, bctf1] t = 0 count = 0 files = DefaultDictByKey(partial(create_xdmf, path)) while t < tEnd: mu.interpolate(muExp) rhosolid = rho_0 * (1.0 - alpha * (T0 * temp_prof.delta - 1573.0)) deltarho = rhosolid - rhomelt assign( v_melt, project(v0 - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0, W)) # use nP after to avoid projection? # pdb.set_trace() solve(r == 0, u, bcs) nV, nP, nT, nTf = u.split() if count % output_every == 0: time_left(count, tEnd / time_step, run_time_init) # TODO: Make sure all writes are to the same function for each time step files['T_fluid'].write(nTf) files['p'].write(nP) files['v_solid'].write(nV) files['T_solid'].write(nT) files['mu'].write(mu) files['v_melt'].write(v_melt) files['gradp'].write(project(grad(nP), W)) files['rho'].write(project(rhosolid, S)) files['Tf_grad'].write(project(grad(Tf), W)) files['advect'].write(project(dt * dot(v_melt, grad(nTf)))) files['ht'].write(project(heat_transfer, S)) assign(T0, nT) assign(v0, nV) assign(Tf0, nTf) t += time_step count += 1 log('Case mu=%g, Tb=%g complete. Run time = %g s' % (mu_a, Tb, clock() - run_time_init))