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
t = 0 # <markdowncell> # We use *gmsh* to define the domain and then set up a first order # scalar Lagrange space which we will use both for $\psi$ and $p$. We can # construct general grids by either defining the grids directly in Python # (as demonstrated in the following example) or by reading the grid from # files using readers provided by Dune, e.g., Dune Grid Format (dgf) files # or Gmsh files. # <codecell> domain = (reader.gmsh, "wave_tank.msh") gridView = leafGridView( domain, dimgrid=2 ) gridView.hierarchicalGrid.loadBalance() V = solutionSpace(gridView, order=1, storage="fem") p = V.interpolate(0,name="p") phi = V.interpolate(0,name="phi") pVec = p.as_numpy phiVec = phi.as_numpy # <markdowncell> # Next we define an operator for the stiffness matrix including the # boundary condition which are time dependent so we use a `Constant` for # this. We use the `BoxDirichletBC` class which is derived from the more # general `DirichletBC` class which takes a function space, the boundary # function $g$ as a ufl expression, and finally a description of the part # $\Gamma_D$ of the boundary where this boundary condition is defined. # This can be a ufl expression which evaluates to $0$ for
import ufl from ufl import grad, dot, dx, inner, Identity, sqrt, sin, pi, cos import dune.ufl import dune.grid import dune.fem from dune.alugrid import aluConformGrid as leafGridView from dune.fem.view import geometryGridView from dune.fem.space import lagrange as solutionSpace from dune.fem.scheme import galerkin as solutionScheme order = 3 storage = "istl" # setup reference surface referenceView = leafGridView("sphere.dgf", dimgrid=2, dimworld=3) space = solutionSpace(referenceView, dimRange=referenceView.dimWorld, order=order, storage=storage) # setup deformed surface x = ufl.SpatialCoordinate(space) # positions = space.interpolate(x, name="position") positions = space.interpolate( x * (1 + 0.5 * sin(2 * pi * (x[0] + x[1])) * cos(0.25 * pi * x[2])), name="position") gridView = geometryGridView(positions) space = solutionSpace(gridView, dimRange=gridView.dimWorld, order=order, storage=storage) u = ufl.TrialFunction(space)
import dune.fem as fem from dune.grid import cartesianDomain from dune.alugrid import aluConformGrid as leafGridView from dune.fem.view import adaptiveLeafGridView as adaptiveGridView from dune.fem.space import lagrange as solutionSpace fem.parameter.append({"fem.verboserank": -1}) order = 1 dimDomain = 2 # we are solving this in 2D dimRange = 2 # we have a system with two unknowns domain = cartesianDomain( [4, 4], [8, 8], [40, 40]) # fails with 20x20 in adapt due to petsc error gridView = adaptiveGridView(leafGridView(domain, dimgrid=dimDomain)) space = solutionSpace(gridView, dimRange=dimRange, order=order, storage="petscadapt") # <markdowncell> # We want to solve the following system of equations of variables $\phi$ (phase field) and $T$ (temperature field) # # \begin{gather*} # \tau \frac{\partial \phi}{\partial t} = \nabla \cdot D \nabla \phi + \phi(1-\phi)m(\phi, T), \\ # \frac{\partial T}{\partial t} = D_T \nabla^2 T + \frac{\partial \phi}{\partial t}, # \end{gather*} # # where $D_T$ = 2.25, m is given by # # \begin{equation*} # m(\phi, T) = \phi - \frac{1}{2} - \frac{\kappa_1}{\pi} \arctan(\kappa_2 T), # \end{equation*}
# field: # <codecell> import matplotlib matplotlib.rc('image', cmap='jet') from matplotlib import pyplot from dune.fem.plotting import plotPointData as plot from dune.grid import structuredGrid as leafGridView from dune.fem.space import lagrange as solutionSpace from dune.fem.scheme import galerkin as solutionScheme from ufl import * import dune.ufl gridView = leafGridView([0, 0], [1, 0.15], [100, 15]) space = solutionSpace(gridView, dimRange=2, order=2, storage="istl") displacement = space.interpolate([0, 0], name="displacement") # <markdowncell> # We want clamped boundary conditions on the left, i.e., zero displacement # <codecell> x = SpatialCoordinate(space) dbc = dune.ufl.DirichletBC(space, as_vector([0, 0]), x[0] < 1e-10) # <markdowncell> # Next we define the variational problem starting with a few constants # describing material properties ($\mu,\lambda,\rho$) and the gravitational # force # <codecell>
except ImportError: # pygmsh not installed - use a simple cartesian domain from dune.grid import cartesianDomain domain3d = cartesianDomain([-0.25, -0.25, 0], [0.25, 0.25, 1], [30, 30, 60]) 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
# <markdowncell> # Now we can setup the functional which will be $J(v)=v(P)$ where # $P=(0.4,0.4)$ is some point in the computational domain at which we want # to minimize the error. To compute the dwr estimator we need the solution # 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>
gridView.writeVTK('exact', pointdata={'exact': exact}) from dune.fem.function import uflFunction exact_gf = uflFunction(gridView, name="ufl", order=1, ufl=exact) mass = 0 for element in gridView.elements: mass += exact_gf(element,[0.5,0.5]) * element.geometry.volume print(mass) # <markdowncell> # ## Discrete Spaces # Setting up a discrete function space and some grid function # <codecell> from dune.fem.space import lagrange as solutionSpace space = solutionSpace(gridView, order=2) # <markdowncell> # So far we used grid functions defined globally. An important subclass of # grid functions are discrete functions over a given discrete function space. # The easiest way to construct such functions is to use the interpolate # method on the discrete function space. # <codecell> u_h = space.interpolate(exact, name='u_h') # <markdowncell> # If a discrete function is already available it is possible to call `copy` # to obtain further discrete functions: # <codecell>
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
# <codecell> order = 2 R0 = 2. # <markdowncell> # We begin by setting up reference domain $\Gamma_0$ (```grid```), and the space on $\Gamma_0$ that describes $\Gamma(t)$ (```space```). From this we interpolate the non-spherical initial surface ```positions```, and, then reconstruct ```space``` for the discrete solution on $\Gamma(t)$. # <codecell> from dune.fem.view import geometryGridView from dune.fem.space import lagrange as solutionSpace from dune.alugrid import aluConformGrid as leafGridView gridView = leafGridView("sphere.dgf", dimgrid=2, dimworld=3) space = solutionSpace(gridView, dimRange=gridView.dimWorld, order=order) u = TrialFunction(space) v = TestFunction(space) x = SpatialCoordinate(space) # positions = space.interpolate(x * (1 + 0.5*sin(2*pi*x[0]*x[1])* cos(pi*x[2])), name="position") positions = space.interpolate(x * (1 + 0.5*sin(2*pi*(x[0]+x[1]))*cos(0.25*pi*x[2])), name="position") surface = geometryGridView(positions) space = solutionSpace(surface, dimRange=surface.dimWorld, order=order) solution = space.interpolate(x, name="solution") # <markdowncell> # We set up the theta scheme with $\theta = 0.5$ (Crank-Nicholson). # <codecell>
import matplotlib matplotlib.rc('image', cmap='jet') import dune.fem as fem from dune.grid import cartesianDomain from dune.alugrid import aluConformGrid as leafGridView from dune.fem.view import adaptiveLeafGridView as adaptiveGridView from dune.fem.space import lagrange as solutionSpace order = 1 dimDomain = 2 # we are solving this in 2D dimRange = 2 # we have a system with two unknowns domain = cartesianDomain([4, 4], [8, 8], [3, 3]) gridView = adaptiveGridView(leafGridView(domain)) space = solutionSpace(gridView, dimRange=dimRange, order=order, storage="fem") # <markdowncell> # We want to solve the following system of equations of variables $\phi$ (phase field) and $T$ (temperature field) # # \begin{equation} # \begin{aligned} # \tau \frac{\partial \phi}{\partial t} &= \nabla \cdot D \nabla \phi + \phi(1-\phi)m(\phi, T), \\ # \frac{\partial T}{\partial t} &= D_T \nabla^2 T + \frac{\partial \phi}{\partial t}, # \end{aligned} # \end{equation} # # where $D_T$ = 2.25, m is given by # # \begin{equation*} # m(\phi, T) = \phi - \frac{1}{2} - \frac{\kappa_1}{\pi} \arctan(\kappa_2 T),