def setup(): vertices = numpy.zeros((8, 2)) vertices[0] = [0, 0] for i in range(0, 7): vertices[i + 1] = [ math.cos(cornerAngle / 6 * math.pi / 180 * i), math.sin(cornerAngle / 6 * math.pi / 180 * i) ] triangles = numpy.array([[2, 1, 0], [0, 3, 2], [4, 3, 0], [0, 5, 4], [6, 5, 0], [0, 7, 6]]) domain = {"vertices": vertices, "simplices": triangles} gridView = adaptiveGridView(leafGridView(domain)) gridView.hierarchicalGrid.globalRefine(2) space = solutionSpace(gridView, order=order) from dune.fem.scheme import galerkin as solutionScheme u = TrialFunction(space) v = TestFunction(space) x = SpatialCoordinate(space.cell()) # exact solution for this angle Phi = cornerAngle / 180 * pi phi = atan_2(x[1], x[0]) + conditional(x[1] < 0, 2 * pi, 0) exact = dot(x, x)**(pi / 2 / Phi) * sin(pi / Phi * phi) a = dot(grad(u), grad(v)) * dx # set up the scheme laplace = solutionScheme( [a == 0, DirichletBC(space, exact, 1)], solver="cg", parameters={"newton.linear.preconditioning.method": "jacobi"}) uh = space.interpolate(0, name="solution") return uh, exact, laplace
# space form xForm = inner(grad(u), grad(phi)) * dx # add time discretization form = dot(u - uh_old, phi) * dx + dt * xForm # setup scheme dune.fem.parameter.append({"fem.verboserank": 0}) solverParameters =\ {"newton.tolerance": 1e-9, "newton.linear.tolerance": 1e-11, "newton.linear.preconditioning.method": "ilu", "newton.verbose": False, "newton.linear.verbose": False} scheme = solutionScheme([form == 0], space, solver="cg", parameters=solverParameters) endTime = 0.3 saveInterval = 0.01 nextSaveTime = saveInterval vtk = gridView.sequencedVTK("mcfPaper", pointdata=[uh], subsampling=2) vtk() while t.value < endTime: uh_old.assign(uh) info = scheme.solve(target=uh) t.value += dt.value positions.dofVector.assign(uh.dofVector)
inner(grad(u[1]), grad(v[1])) + inner(u, v) - inner(s, v)) * dx # <markdowncell> # We set up the scheme with some parameters. # <codecell> from dune.fem.scheme import galerkin as solutionScheme solverParameters = { "newton.tolerance": 1e-8, "newton.linear.tolerance": 1e-10, "newton.linear.preconditioning.method": "sor", "newton.verbose": True, "newton.linear.verbose": True } scheme = solutionScheme(a_im == a_ex, space, solver="gmres", parameters=solverParameters) # <markdowncell> # We set up the adaptive method. We start with a marking strategy based on the value of the gradient of the phase field variable. # <codecell> from dune.ufl import expression2GF indicator = expression2GF(gridView, dot(grad(u_h[0]), grad(u_h[0])), 0, name="indicator") # <markdowncell> # We do the initial refinement of the grid. # <codecell>
def compute(space, epsilon, weakBnd, skeleton, mol=None): u = TrialFunction(space) v = TestFunction(space) n = FacetNormal(space) he = avg(CellVolume(space)) / FacetArea(space) hbnd = CellVolume(space) / FacetArea(space) x = SpatialCoordinate(space) exact = uflFunction(space.gridView, name="exact", order=3, ufl=sin(x[0] * x[1])) uh = space.interpolate(exact, name="solution") # diffusion factor eps = Constant(epsilon, "eps") # transport direction and upwind flux b = as_vector([1, 0]) hatb = (dot(b, n) + abs(dot(b, n))) / 2.0 # characteristic function for left/right boundary dD = conditional((1 + x[0]) * (1 - x[0]) < 1e-10, 1, 0) # penalty parameter beta = Constant(20 * space.order**2, "beta") rhs = -(div(eps * grad(exact) - b * exact)) * v * dx aInternal = dot(eps * grad(u) - b * u, grad(v)) * dx aInternal -= eps * dot(grad(exact), n) * v * (1 - dD) * ds diffSkeleton = eps*beta/he*jump(u)*jump(v)*dS -\ eps*dot(avg(grad(u)),n('+'))*jump(v)*dS -\ eps*jump(u)*dot(avg(grad(v)),n('+'))*dS if weakBnd: diffSkeleton += eps*beta/hbnd*(u-exact)*v*dD*ds -\ eps*dot(grad(exact),n)*v*dD*ds advSkeleton = jump(hatb * u) * jump(v) * dS if weakBnd: advSkeleton += (hatb * u + (dot(b, n) - hatb) * exact) * v * dD * ds if skeleton: form = aInternal + diffSkeleton + advSkeleton else: form = aInternal if weakBnd and skeleton: strongBC = None else: strongBC = DirichletBC(space, exact, dD) if space.storage[0] == "numpy": solver = { "solver": ("suitesparse", "umfpack"), "parameters": { "newton.verbose": True, "newton.linear.verbose": False, "newton.linear.tolerance": 1e-5, } } else: solver = { "solver": "bicgstab", "parameters": { "newton.linear.preconditioning.method": "ilu", "newton.linear.tolerance": 1e-13, "newton.verbose": True, "newton.linear.verbose": False } } if mol == 'mol': scheme = molSolutionScheme([form == rhs, strongBC], **solver) else: scheme = solutionScheme([form == rhs, strongBC], **solver) eoc = [] info = scheme.solve(target=uh) error = dot(uh - exact, uh - exact) error0 = math.sqrt(integrate(gridView, error, order=5)) print(error0, " # output", flush=True) for i in range(3): gridView.hierarchicalGrid.globalRefine(1) uh.interpolate(exact) scheme.solve(target=uh) error = dot(uh - exact, uh - exact) error1 = math.sqrt(integrate(gridView, error, order=5)) eoc += [math.log(error1 / error0) / math.log(0.5)] print(i, error0, error1, eoc, " # output", flush=True) error0 = error1 # print(space.order,epsilon,eoc) if (eoc[-1] - (space.order + 1)) < -0.1: print("ERROR:", space.order, epsilon, eoc) return eoc
# <markdowncell> # Finally we define the variational problem # \begin{align*} # \int_\Omega \sigma(u)\colon\epsilon(v) = (0,-\rho g)\cdot v # \end{align*} # and solve the system # <codecell> u = TrialFunction(space) v = TestFunction(space) equation = inner(sigma(u), epsilon(v)) * dx == dot(as_vector([0, -rho * g]), v) * dx scheme = solutionScheme( [equation, dbc], solver='cg', parameters={"newton.linear.preconditioning.method": "ilu"}) info = scheme.solve(target=displacement) # <markdowncell> # We can directly plot the magnitude of the displacement field and the stress # <codecell> fig = pyplot.figure(figsize=(20, 10)) displacement.plot(gridLines=None, figure=(fig, 121), colorbar="horizontal") s = sigma(displacement) - (1. / 3) * tr(sigma(displacement)) * Identity(2) von_Mises = sqrt(3. / 2 * inner(s, s)) plot(von_Mises, grid=gridView, gridLines=None, figure=(fig, 122),
uh = space.interpolate(x, name="uh") uh_old = uh.copy() # problem definition # space form xForm = inner(grad(u), grad(phi)) * dx # add time discretization form = dot(u - uh_old, phi) * dx + dt * xForm # define dirichlet boundary conditions bc = dune.ufl.DirichletBC(space,x) # setup scheme scheme = solutionScheme([form == 0,bc], space, solver="cg") endTime = 0.1 saveInterval = 0.05 nextSaveTime = saveInterval vtk = gridView.sequencedVTK("mcfSoap", pointdata=[uh]) vtk() while t.value < endTime: uh_old.assign(uh) info = scheme.solve(target=uh) t.value += dt.value positions.dofVector.assign(uh.dofVector)
from dune.alugrid import aluSimplexGrid as leafGridView3d gridView3d = leafGridView3d(domain3d) # <markdowncell> # As before we solve a simple Laplace problem # <codecell> from dune.fem.space import lagrange as solutionSpace from dune.fem.scheme import galerkin as solutionScheme from ufl import TrialFunction, TestFunction, SpatialCoordinate, dot, grad, dx, conditional, sqrt space3d = solutionSpace(gridView3d, order=1) u = TrialFunction(space3d) v = TestFunction(space3d) x = SpatialCoordinate(space3d) scheme3d = solutionScheme((dot(grad(u), grad(v)) + u * v) * dx == conditional(dot(x, x) < .01, 100, 0) * v * dx, solver='cg') uh3d = space3d.interpolate([0], name="solution") info = scheme3d.solve(target=uh3d) # <markdowncell> # Instead of plotting this using paraview we want to only study the # solution along a single line. This requires findings points # $x_i = x_0+\frac{i}{N}(x1-x0)$ for $i=0,\dots,N$ within the unstructured # grid. This would be expensive to compute on the Python so we implement # this algorithm in C++ using the `LineSegmentSampler` class available in # `Dune-Fem`. The resulting `algorithm` returns a pair of two lists with # coordinates $x_i$ and the values of the grid function at these points: # # .. literalinclude:: utility.hh #
# to the dual problem with right hand side $J(\varphi_i)$ for all basis # functions $\varphi_i$. This is not directly expressible in UFL and we # therefore implement this using a small C++ function which we then export # to Python: # # .. literalinclude:: laplace-dwr.hh # # <codecell> from dune.fem.scheme import galerkin as solutionScheme spaceZ = solutionSpace(uh.space.grid, order=order + 1) u = TrialFunction(spaceZ) v = TestFunction(spaceZ) x = SpatialCoordinate(spaceZ) a = dot(grad(u), grad(v)) * dx dual = solutionScheme([a == 0, DirichletBC(spaceZ, 0)], solver="cg") z = spaceZ.interpolate(0, name="dual") zh = uh.copy(name="dual_h") point = common.FieldVector([0.4, 0.4]) pointFunctional = z.copy("dual_rhs") eh = expression2GF(uh.space.grid, abs(exact - uh), order=order + 1) computeFunctional = algorithm.load("pointFunctional", "laplace-dwr.hh", point, pointFunctional, eh) # <markdowncell> # <codecell> from dune.fem.space import finiteVolume as estimatorSpace from dune.fem.operator import galerkin as estimatorOp fvspace = estimatorSpace(uh.space.grid)
f = -div( grad(exact) ) g_N = grad(exact) n = FacetNormal(space) b = f*v*dx + dot(g_N,n)*conditional(x[0]>=1e-8,1,0)*v*ds dbc = DirichletBC(space,exact,x[0]<=1e-8) # <markdowncell> # With the model described as a ufl form, we can construct a scheme class # that provides the solve method which we can use to compute the solution: # <codecell> from dune.fem import parameter parameter.append({"fem.verboserank": -1}) from dune.fem.scheme import galerkin as solutionScheme scheme = solutionScheme([a == b, dbc], solver='cg') scheme.solve(target = u_h) # <markdowncell> # We can compute the error between the exact and the discrete solution by # using the `integrate` function described above: # <codecell> h1error = dot(grad(u_h - exact), grad(u_h - exact)) error = sqrt(integrate(gridView, h1error, order=5)) print("Number of elements:",gridView.size(0), "number of dofs:",space.size,"H^1 error:", error) # <markdowncell> # To verify that the discrete scheme is converging to the exact solution # we can compute the experimental order of convergence (EOC):
def calculate(use_cpp, gridView): # space on Gamma_0 to describe position of Gamma(t) space = solutionSpace(gridView, dimRange=gridView.dimWorld, order=order) u = TrialFunction(space) v = TestFunction(space) x = SpatialCoordinate(space.cell()) positions = space.interpolate(x, name="position") # space for discrete solution on Gamma(t) surface = geoGridView(positions) space = solutionSpace(surface, dimRange=surface.dimWorld, order=order) solution = space.interpolate(x, name="solution") # set up model using theta scheme theta = 0.5 # Crank-Nicholson I = Identity(3) dt = dune.ufl.Constant(0, "dt") a = (inner(u - x, v) + dt * inner(theta * grad(u) + (1 - theta) * I, grad(v))) * dx scheme = solutionScheme(a == 0, space, solver="cg") Rexact = lambda t: math.sqrt(R0 * R0 - 4. * t) radius = switchCalcRadius(use_cpp, surface) scheme.model.dt = 0.02 numberOfLoops = 3 times = np.zeros(numberOfLoops) errors = np.zeros(numberOfLoops) totalIterations = np.zeros(numberOfLoops, np.dtype(np.uint32)) gridSizes = np.zeros(numberOfLoops, np.dtype(np.uint32)) for i in range(numberOfLoops): positions.interpolate(x * (R0 / sqrt(dot(x, x)))) solution.interpolate(x) t = 0. error = abs(radius(surface) - Rexact(t)) iterations = 0 start = time.time() while t < endTime: info = scheme.solve(target=solution) # move the surface positions.dofVector.assign(solution.dofVector) # store some information about the solution process iterations += int(info["linear_iterations"]) t += scheme.model.dt error = max(error, abs(radius(surface) - Rexact(t))) print("time used:", time.time() - start) times[i] = time.time() - start errors[i] = error totalIterations[i] = iterations gridSizes[i] = gridView.size(2) if i < numberOfLoops - 1: gridView.hierarchicalGrid.globalRefine(1) scheme.model.dt /= 2 eocs = np.log(errors[0:][:numberOfLoops - 1] / errors[1:]) / math.log( math.sqrt(2)) try: import pandas as pd keys = { 'size': gridSizes, 'error': errors, "eoc": np.insert(eocs, 0, None), 'iterations': totalIterations } table = pd.DataFrame(keys, index=range(numberOfLoops), columns=['size', 'error', 'eoc', 'iterations']) print(table) except ImportError: print("pandas could not be used to show table with results") pass return gridSizes, times
dt = dune.ufl.Constant(0.001, "timeStep") t = dune.ufl.Constant(0.0, "time") # define storage for discrete solutions uh = space.interpolate(x, name="uh") uh_old = uh.copy() # problem definition # space form xForm = inner(grad(u), grad(phi)) * dx # add time discretization form = dot(u - uh_old, phi) * dx + dt * xForm # setup scheme scheme = solutionScheme(form == 0, space, solver="cg") nextSaveTime = saveInterval vtk = gridView.sequencedVTK("mcfSphere", pointdata=[uh]) vtk() while t.value < endTime: uh_old.assign(uh) info = scheme.solve(target=uh) t.value += dt.value positions.dofVector.assign(uh.dofVector) [radius, area] = dune.fem.function.integrate(gridView, [sqrt(dot(x, x)), 1],
def model(space, epsilon, weakBnd, skeleton, useMol): u = TrialFunction(space) v = TestFunction(space) n = FacetNormal(space) he = avg(CellVolume(space)) / FacetArea(space) hbnd = CellVolume(space) / FacetArea(space) x = SpatialCoordinate(space) #exact = sin(x[0]*x[1]) # atan(1*x[1]) exact = uflFunction(space.gridView, name="exact", order=3, ufl=sin(x[0] * x[1])) # diffusion factor eps = 1 # Constant(epsilon,"eps") # transport direction and upwind flux b = as_vector([1, 0]) hatb = (dot(b, n) + abs(dot(b, n))) / 2.0 # characteristic function for left/right boundary dD = conditional((1 + x[0]) * (1 - x[0]) < 1e-10, 1, 0) # penalty parameter beta = Constant(10 * space.order**2 if space.order > 0 else 1, "beta") rhs = (-div(eps * grad(exact) - b * exact) + exact) * v * dx aInternal = (dot(eps * grad(u) - b * u, grad(v)) + dot(u, v)) * dx diffSkeleton = eps*beta/he*jump(u)*jump(v)*dS -\ eps*dot(avg(grad(u)),n('+'))*jump(v)*dS -\ eps*jump(u)*dot(avg(grad(v)),n('+'))*dS diffSkeleton -= eps * dot(grad(exact), n) * v * (1 - dD) * ds if weakBnd: diffSkeleton += eps*beta/hbnd*(u-exact)*v*dD*ds -\ eps*dot(grad(exact),n)*v*dD*ds advSkeleton = jump(hatb * u) * jump(v) * dS if weakBnd: advSkeleton += (hatb * u + (dot(b, n) - hatb) * exact) * v * dD * ds if skeleton: form = aInternal + diffSkeleton + advSkeleton else: form = aInternal if weakBnd and skeleton: strongBC = None else: strongBC = None # DirichletBC(space,exact,dD) if space.storage[0] == "fem": solver = {"solver": ("suitesparse", "umfpack")} else: solver = { "solver": "bicgstab", "parameters": { "newton.linear.preconditioning.method": "jacobi", "newton.linear.tolerance": 1e-13 } } if useMol: scheme = solutionMolScheme([form == rhs, strongBC], **solver) else: scheme = solutionScheme([form == rhs, strongBC], **solver) uh = space.interpolate(exact, name="solution") A = linear(scheme) return scheme, uh, A, exact
inner(grad(u[1]), grad(v[1])) + inner(u, v) - inner(s, v)) * dx # <markdowncell> # We set up the scheme with some parameters. # <codecell> from dune.fem.scheme import galerkin as solutionScheme solverParameters = { "newton.tolerance": 1e-8, "newton.linear.tolerance": 1e-10, "newton.linear.preconditioning.method": "jacobi", "newton.verbose": False, "newton.linear.verbose": False } scheme = solutionScheme(a_im == a_ex, space, solver="bicgstab", parameters=solverParameters) scheme.model.dt = 0.0002 # <markdowncell> # We set up the adaptive method. We start with a marking strategy based on the value of the gradient of the phase field variable. # <codecell> from dune.ufl import expression2GF indicator = expression2GF(gridView, dot(grad(u_h[0]), grad(u_h[0])), 0, name="indicator") # <markdowncell> # We do the initial refinement of the grid.