Surface integration

using Ferrite, FerriteAssembly

This how-to shows integration of the normal flux on a surface. As usual, we need the basic Ferrite building blocks, in this case a grid, dofhandler, and facetvalues

grid = generate_grid(Hexahedron, (5,5,5))
ip = Lagrange{RefHexahedron,1}()
dh = DofHandler(grid); add!(dh, :u, ip); close!(dh)
qr = FacetQuadratureRule{RefHexahedron}(2);
fv = FacetValues(qr, ip);

We also need a solution vector to integrate, unless we only calculate geometric properties.

a = zeros(ndofs(dh))
apply_analytical!(a, dh, :u, norm); # f(x)=norm(x)

And then we decide which facets to integrate over

domainbuffer = setup_domainbuffer(DomainSpec(dh, nothing, fv; set=getfacetset(grid, "right")));

Using SimpleIntegrator

Using the simple interface, SimpleIntegrator, we simply give it the function, (u,∇u,n)->∇u⋅n, and the initial value

s_integrator = SimpleIntegrator((u,∇u,n)->∇u⋅n, 0.0);

And then let it do its work

work!(s_integrator, domainbuffer; a=a);

println("Flux: ∫qₙ dA = ", s_integrator.val)
Flux: ∫qₙ dA = 2.8636826734618444

Using Integrator

To demonstrate how the full-fledged interface can be used, we perform the same task by using the Integrator. To do that, we have to define an integrand, let's call it NormalFlux, and overload the facet integration function

mutable struct NormalFlux{T}
    qn::T
end
function FerriteAssembly.integrate_facet!(nf::NormalFlux, ae, material, fv, facetbuffer)
    for q_point in 1:getnquadpoints(fv)
        dA = getdetJdV(fv, q_point)
        ∇u = function_gradient(fv, q_point, ae)
        n = getnormal(fv, q_point)
        nf.qn += (∇u⋅n)*dA
    end
end;

To do the actual integration, we define an instance of the integrand, create an Integrator, and do the work.

nf = NormalFlux(0.0)
integrator = Integrator(nf)
work!(integrator, domainbuffer; a=a)

println("Flux: ∫qₙ dA = ", nf.qn)
Flux: ∫qₙ dA = 2.8636826734618444

This page was generated using Literate.jl.