예제 #1
0
def run_and_calculate_error(N, dt, tmax, polydeg_rho, last=False):
    """
    Run Ocellaris and return L2 & H1 errors in the last time step
    """
    say(N, dt, tmax, polydeg_rho)

    # Setup and run simulation
    sim = Simulation()
    sim.input.read_yaml('transport.inp')

    mesh_type = sim.input.get_value('mesh/type')
    if mesh_type == 'XML':
        # Create unstructured mesh with gmsh
        cmd1 = [
            'gmsh', '-string',
            'lc = %f;' % (3.14 / N), '-o',
            'disc_%d.msh' % N, '-2',
            '../convergence-variable-density-disk/disc.geo'
        ]
        cmd2 = ['dolfin-convert', 'disc_%d.msh' % N, 'disc.xml']
        with open('/dev/null', 'w') as devnull:
            for cmd in (cmd1, cmd2):
                say(' '.join(cmd))
                if ISROOT:
                    subprocess.call(cmd, stdout=devnull, stderr=devnull)
    elif mesh_type == 'UnitDisc':
        sim.input.set_value('mesh/N', N // 2)
    else:
        sim.input.set_value('mesh/Nx', N)
        sim.input.set_value('mesh/Ny', N)

    sim.input.set_value('time/dt', dt)
    sim.input.set_value('time/tmax', tmax)
    sim.input.set_value('multiphase_solver/polynomial_degree_rho', polydeg_rho)
    sim.input.set_value('output/stdout_enabled', False)

    say('Running with multiphase solver %s ...' %
        (sim.input.get_value('multiphase_solver/type')))
    t1 = time.time()
    setup_simulation(sim)
    run_simulation(sim)
    duration = time.time() - t1
    say('DONE')

    # Interpolate the analytical solution to the same function space
    Vu = sim.data['Vu']
    Vp = sim.data['Vp']
    Vr = sim.data['Vrho']
    polydeg_r = Vr.ufl_element().degree()
    vals = dict(t=sim.time, dt=sim.dt)
    rho_e = dolfin.Expression(
        sim.input.get_value('initial_conditions/rho_p/cpp_code'),
        degree=polydeg_r,
        **vals)
    rho_a = dolfin.project(rho_e, Vr)

    rho_e.t = 0
    rho_0 = dolfin.project(rho_e, Vr)

    # Calculate L2 errors
    err_rho = calc_err(sim.data['rho'], rho_a)

    # Calculate H1 errors
    err_rho_H1 = calc_err(sim.data['rho'], rho_a, 'H1')

    mesh = sim.data['mesh']
    n = dolfin.FacetNormal(mesh)

    reports = sim.reporting.timestep_xy_reports
    say('Num time steps:', sim.timestep)
    say('Num cells:', mesh.num_cells())
    say('Co_max:', numpy.max(reports['Co']))
    say('rho_min went from %r to %r' %
        (reports['min(rho)'][0], reports['min(rho)'][-1]))
    say('rho_max went from %r to %r' %
        (reports['max(rho)'][0], reports['max(rho)'][-1]))
    m0, m1 = reports['mass'][0], reports['mass'][-1]
    say('mass error %.3e (%.3e)' % (m1 - m0, (m1 - m0) / m0))
    say('vel compat error %.3e' %
        dolfin.assemble(dolfin.dot(sim.data['u'], n) * dolfin.ds))
    int_p = dolfin.assemble(sim.data['p'] * dolfin.dx)
    say('p*dx', int_p)
    div_u_Vp = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vp).vector().get_local()).max()
    say('div(u)|Vp', div_u_Vp)
    div_u_Vu = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vu).vector().get_local()).max()
    say('div(u)|Vu', div_u_Vu)
    Vdg0 = dolfin.FunctionSpace(mesh, "DG", 0)
    div_u_DG0 = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vdg0).vector().get_local()).max()
    say('div(u)|DG0', div_u_DG0)
    Vdg1 = dolfin.FunctionSpace(mesh, "DG", 1)
    div_u_DG1 = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vdg1).vector().get_local()).max()
    say('div(u)|DG1', div_u_DG1)

    isoparam = mesh.ufl_coordinate_element().degree() > 1
    if last and (not isoparam
                 or sim.input.get_value('mesh/type') == 'UnitDisc'):
        # Plot the results
        for fa, name in ((rho_a, 'rho'), ):
            fh = sim.data[name]
            if isoparam:
                # Bug in matplotlib plotting for isoparametric elements
                mesh2 = dolfin.UnitDiscMesh(dolfin.MPI.comm_world, N // 2, 1,
                                            2)
                ue = fa.function_space().ufl_element()
                V2 = dolfin.FunctionSpace(mesh2, ue.family(), ue.degree())
                fa2, fh2 = dolfin.Function(V2), dolfin.Function(V2)
                fa2.vector().set_local(fa.vector().get_local())
                fh2.vector().set_local(fh.vector().get_local())
                fa, fh = fa2, fh2
            plot(fh - fa, name + ' diff', '%g_%g_%s_diff' % (N, dt, name))
            plot(fa, name + ' analytical',
                 '%g_%g_%s_analytical' % (N, dt, name))
            plot(fh, name + ' numerical', '%g_%g_%s_numerical' % (N, dt, name))
            plot(rho_0, name + ' initial', '%g_%g_%s_initial' % (N, dt, name))

    hmin = mesh.hmin()
    return err_rho, err_rho_H1, hmin, dt, duration
예제 #2
0
def load_mesh(simulation):
    """
    Get the mesh from the simulation input

    Returns the facet regions contained in the mesh data
    or None if these do not exist
    """
    inp = simulation.input
    mesh_type = inp.get_value('mesh/type', required_type='string')
    mesh_facet_regions = None

    # For testing COMM_SELF may be specified
    comm_type = inp.get_value('mesh/mpi_comm', 'WORLD', required_type='string')
    verify_key('mesh/mpi_comm', comm_type, ('SELF', 'WORLD'))
    if comm_type == 'WORLD':
        comm = dolfin.MPI.comm_world
    else:
        comm = dolfin.MPI.comm_self

    if mesh_type == 'Rectangle':
        simulation.log.info('Creating rectangular mesh')

        startx = inp.get_value('mesh/startx', 0, 'float')
        starty = inp.get_value('mesh/starty', 0, 'float')
        start = dolfin.Point(startx, starty)
        endx = inp.get_value('mesh/endx', 1, 'float')
        endy = inp.get_value('mesh/endy', 1, 'float')
        end = dolfin.Point(endx, endy)
        Nx = inp.get_value('mesh/Nx', required_type='int')
        Ny = inp.get_value('mesh/Ny', required_type='int')
        diagonal = inp.get_value('mesh/diagonal',
                                 'right',
                                 required_type='string')

        mesh = dolfin.RectangleMesh(comm, start, end, Nx, Ny, diagonal)

    elif mesh_type == 'Box':
        simulation.log.info('Creating box mesh')

        startx = inp.get_value('mesh/startx', 0, 'float')
        starty = inp.get_value('mesh/starty', 0, 'float')
        startz = inp.get_value('mesh/startz', 0, 'float')
        start = dolfin.Point(startx, starty, startz)
        endx = inp.get_value('mesh/endx', 1, 'float')
        endy = inp.get_value('mesh/endy', 1, 'float')
        endz = inp.get_value('mesh/endz', 1, 'float')
        end = dolfin.Point(endx, endy, endz)
        Nx = inp.get_value('mesh/Nx', required_type='int')
        Ny = inp.get_value('mesh/Ny', required_type='int')
        Nz = inp.get_value('mesh/Nz', required_type='int')

        mesh = dolfin.BoxMesh(comm, start, end, Nx, Ny, Nz)

    elif mesh_type == 'UnitDisc':
        simulation.log.info('Creating circular mesh')

        N = inp.get_value('mesh/N', required_type='int')
        degree = inp.get_value('mesh/degree', 1, required_type='int')
        gdim = inp.get_value('mesh/gdim', 2, required_type='int')

        mesh = dolfin.UnitDiscMesh(comm, N, degree, gdim)

        if degree > 1 and dolfin.parameters['form_compiler'][
                'representation'] != 'uflacs':
            simulation.log.warning(
                'Using isoparametric elements without uflacs!')

    elif mesh_type == 'XML':
        simulation.log.info('Creating mesh from XML file')
        simulation.log.warning('(deprecated, please use meshio reader)')

        mesh_file = inp.get_value('mesh/mesh_file', required_type='string')
        facet_region_file = inp.get_value('mesh/facet_region_file',
                                          None,
                                          required_type='string')

        # Load the mesh from file
        pth = inp.get_input_file_path(mesh_file)
        mesh = dolfin.Mesh(comm, pth)

        # Load the facet regions if available
        if facet_region_file is not None:
            pth = inp.get_input_file_path(facet_region_file)
            mesh_facet_regions = dolfin.MeshFunction('size_t', mesh, pth)
        else:
            mesh_facet_regions = None

    elif mesh_type == 'XDMF':
        simulation.log.info('Creating mesh from XDMF file')
        simulation.log.warning('(deprecated, please use meshio reader)')

        mesh_file = inp.get_value('mesh/mesh_file', required_type='string')

        # Load the mesh from file
        pth = inp.get_input_file_path(mesh_file)
        mesh = dolfin.Mesh(comm)
        with dolfin.XDMFFile(comm, pth) as xdmf:
            xdmf.read(mesh, False)

    elif mesh_type == 'HDF5':
        simulation.log.info('Creating mesh from DOLFIN HDF5 file')
        h5_file_name = inp.get_value('mesh/mesh_file', required_type='string')

        with dolfin.HDF5File(comm, h5_file_name, 'r') as h5:
            # Read mesh
            mesh = dolfin.Mesh(comm)
            h5.read(mesh, '/mesh', False)

            # Read facet regions
            if h5.has_dataset('/mesh_facet_regions'):
                mesh_facet_regions = dolfin.FacetFunction('size_t', mesh)
                h5.read(mesh_facet_regions, '/mesh_facet_regions')
            else:
                mesh_facet_regions = None

    elif mesh_type == 'meshio':
        simulation.log.info('Creating mesh with meshio reader')
        file_name = inp.get_value('mesh/mesh_file', required_type='string')
        file_type = inp.get_value('mesh/meshio_type',
                                  None,
                                  required_type='string')
        sort_order = inp.get_value('mesh/sort_order',
                                   None,
                                   required_type='list(int)')

        if sort_order:
            simulation.log.info('    Ordering mesh elements by ' +
                                ', then '.join('xyz'[i] for i in sort_order))

        # Read mesh on rank 0
        t1 = time.time()
        mesh = dolfin.Mesh(comm)
        if comm.rank == 0:
            # Read a mesh file by use of meshio
            physical_regions = load_meshio_mesh(mesh, file_name, file_type,
                                                sort_order)
            simulation.log.info('    Read mesh with %d cells in %.2f seconds' %
                                (mesh.num_cells(), time.time() - t1))
        else:
            physical_regions = None

        # Distribute the mesh
        if comm.size > 1:
            physical_regions = comm.bcast(physical_regions)
            t1 = time.time()
            simulation.log.info('    Distributing mesh to %d processors' %
                                comm.size)
            build_distributed_mesh(mesh)
            simulation.log.info('    Distributed mesh in %.2f seconds' %
                                (time.time() - t1))
    else:
        ocellaris_error('Unknown mesh type',
                        'Mesh type %r is not supported' % mesh_type)

    # Optionally move the mesh (for simple grading etc)
    move = inp.get_value('mesh/move', None, required_type='list(string)')
    if move is not None:
        simulation.log.info('    Moving mesh')
        if len(move) != mesh.geometry().dim():
            ocellaris_error(
                'Mesh move not correct',
                'Length of move field is %d while geometric dimension is %r' %
                (len(move), mesh.geometry().dim()),
            )
        e_move = dolfin.Expression(move, degree=1)
        V_move = dolfin.VectorFunctionSpace(mesh, 'CG', 1)
        f_move = dolfin.interpolate(e_move, V_move)
        dolfin.ALE.move(mesh, f_move)
        mesh.bounding_box_tree().build(mesh)

    # Update the simulation
    simulation.set_mesh(mesh, mesh_facet_regions)

    # Load meshio facet regions
    if mesh_type == 'meshio' and physical_regions:
        mfr = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
        conn_FV = simulation.data['connectivity_FV']
        vcoords = mesh.coordinates()
        for ifacet in range(mfr.size()):
            facet_vertices = conn_FV(ifacet)
            key = sorted([tuple(vcoords[vidx]) for vidx in facet_vertices])
            number = physical_regions.get(tuple(key), 0)
            mfr[ifacet] = number
        # Store the loaded regions
        simulation.data['mesh_facet_regions'] = mfr
        mesh_facet_regions = mfr

    # Optionally plot mesh right after loading (for debugging)
    if simulation.input.get_value('output/plot_mesh', False, 'bool'):
        prefix = simulation.input.get_value('output/prefix', '', 'string')
        pfile = prefix + '_mesh.xdmf'
        simulation.log.info(
            '    Plotting mesh with current MPI ranks to XDMF file %r' % pfile)
        V0 = dolfin.FunctionSpace(mesh, 'DG', 0)
        ranks = dolfin.Function(V0)
        ranks.vector().set_local(ranks.vector().get_local() * 0 + comm.rank)
        ranks.vector().apply('insert')
        ranks.rename('MPI_rank', 'MPI_rank')
        with dolfin.XDMFFile(comm, pfile) as xdmf:
            xdmf.write(ranks)

    # Optionally plot facet regions to file
    if simulation.input.get_value('output/plot_facet_regions', False, 'bool'):
        prefix = simulation.input.get_value('output/prefix', '', 'string')
        pfile = prefix + '_input_facet_regions.xdmf'
        simulation.log.info(
            '    Plotting input mesh facet regions to XDMF file %r' % pfile)
        if mesh_facet_regions is None:
            simulation.log.warning(
                'Cannot plot mesh facet regions, no regions found!')
        else:
            with dolfin.XDMFFile(comm, pfile) as xdmf:
                xdmf.write(mesh_facet_regions)
예제 #3
0
def run_and_calculate_error(N, dt, tmax, polydeg_u, polydeg_p, nu, last=False):
    """
    Run Ocellaris and return L2 & H1 errors in the last time step
    """
    say(N, dt, tmax, polydeg_u, polydeg_p)

    # Setup and run simulation
    timingtypes = [
        dolfin.TimingType.user, dolfin.TimingType.system,
        dolfin.TimingType.wall
    ]
    dolfin.timings(dolfin.TimingClear_clear, timingtypes)
    sim = Simulation()
    sim.input.read_yaml('disc.inp')

    mesh_type = sim.input.get_value('mesh/type')
    if mesh_type == 'XML':
        # Create unstructured mesh with gmsh
        cmd1 = [
            'gmsh', '-string',
            'lc = %f;' % (3.14 / N), '-o',
            'disc_%d.msh' % N, '-2', 'disc.geo'
        ]
        cmd2 = ['dolfin-convert', 'disc_%d.msh' % N, 'disc.xml']
        with open('/dev/null', 'w') as devnull:
            for cmd in (cmd1, cmd2):
                say(' '.join(cmd))
                subprocess.call(cmd, stdout=devnull, stderr=devnull)
    elif mesh_type == 'UnitDisc':
        sim.input.set_value('mesh/N', N // 2)
    else:
        sim.input.set_value('mesh/Nx', N)
        sim.input.set_value('mesh/Ny', N)

    sim.input.set_value('time/dt', dt)
    sim.input.set_value('time/tmax', tmax)
    sim.input.set_value('solver/polynomial_degree_velocity', polydeg_u)
    sim.input.set_value('solver/polynomial_degree_pressure', polydeg_p)
    sim.input.set_value('physical_properties/nu', nu)
    sim.input.set_value('output/stdout_enabled', False)

    say('Running with %s %s solver ...' %
        (sim.input.get_value('solver/type'),
         sim.input.get_value('solver/function_space_velocity')))
    t1 = time.time()
    setup_simulation(sim)
    run_simulation(sim)
    duration = time.time() - t1
    say('DONE')

    # Interpolate the analytical solution to the same function space
    Vu = sim.data['Vu']
    Vp = sim.data['Vp']
    Vr = sim.data['Vrho']
    polydeg_r = Vr.ufl_element().degree()
    vals = dict(t=sim.time,
                dt=sim.dt,
                Q=sim.input.get_value('user_code/constants/Q'))
    rho_e = dolfin.Expression(
        sim.input.get_value('initial_conditions/rho_p/cpp_code'),
        degree=polydeg_r,
        **vals)
    u0e = dolfin.Expression(
        sim.input.get_value('initial_conditions/up0/cpp_code'),
        degree=polydeg_u,
        **vals)
    u1e = dolfin.Expression(
        sim.input.get_value('initial_conditions/up1/cpp_code'),
        degree=polydeg_u,
        **vals)
    pe = dolfin.Expression(
        sim.input.get_value('initial_conditions/p/cpp_code'),
        degree=polydeg_p,
        **vals)

    rho_a = dolfin.project(rho_e, Vr)
    u0a = dolfin.project(u0e, Vu)
    u1a = dolfin.project(u1e, Vu)
    pa = dolfin.project(pe, Vp)

    mesh = sim.data['mesh']
    n = dolfin.FacetNormal(mesh)

    # Correct for possible non-zero average p
    int_p = dolfin.assemble(sim.data['p'] * dolfin.dx)
    int_pa = dolfin.assemble(pa * dolfin.dx)
    vol = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=mesh))
    pa_avg = int_pa / vol
    sim.data['p'].vector()[:] += pa_avg

    # Calculate L2 errors
    err_rho = calc_err(sim.data['rho'], rho_a)
    err_u0 = calc_err(sim.data['u0'], u0a)
    err_u1 = calc_err(sim.data['u1'], u1a)
    err_p = calc_err(sim.data['p'], pa)

    # Calculate H1 errors
    err_rho_H1 = calc_err(sim.data['rho'], rho_a, 'H1')
    err_u0_H1 = calc_err(sim.data['u0'], u0a, 'H1')
    err_u1_H1 = calc_err(sim.data['u1'], u1a, 'H1')
    err_p_H1 = calc_err(sim.data['p'], pa, 'H1')

    reports = sim.reporting.timestep_xy_reports
    say('Num time steps:', sim.timestep)
    say('Num cells:', mesh.num_cells())
    Co_max, Pe_max = numpy.max(reports['Co']), numpy.max(reports['Pe'])
    say('Co_max:', Co_max)
    say('Pe_max:', Pe_max)
    say('rho_min went from %r to %r' %
        (reports['min(rho)'][0], reports['min(rho)'][-1]))
    say('rho_max went from %r to %r' %
        (reports['max(rho)'][0], reports['max(rho)'][-1]))
    m0, m1 = reports['mass'][0], reports['mass'][-1]
    say('mass error %.3e (%.3e)' % (m1 - m0, (m1 - m0) / m0))
    say('vel repr error %.3e' %
        dolfin.assemble(dolfin.dot(sim.data['u'], n) * dolfin.ds))
    say('p*dx', int_p)
    div_u_Vp = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vp).vector().get_local()).max()
    say('div(u)|Vp', div_u_Vp)
    div_u_Vu = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vu).vector().get_local()).max()
    say('div(u)|Vu', div_u_Vu)
    Vdg0 = dolfin.FunctionSpace(mesh, "DG", 0)
    div_u_DG0 = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vdg0).vector().get_local()).max()
    say('div(u)|DG0', div_u_DG0)
    Vdg1 = dolfin.FunctionSpace(mesh, "DG", 1)
    div_u_DG1 = abs(
        dolfin.project(dolfin.div(sim.data['u']),
                       Vdg1).vector().get_local()).max()
    say('div(u)|DG1', div_u_DG1)

    isoparam = mesh.ufl_coordinate_element().degree() > 1
    allways_plot = True
    if (last or allways_plot) and (
            not isoparam or sim.input.get_value('mesh/type') == 'UnitDisc'):
        # Plot the results
        for fa, name in ((u0a, 'u0'), (u1a, 'u1'), (pa, 'p'), (rho_a, 'rho')):
            fh = sim.data[name]
            if isoparam:
                # Bug in matplotlib plotting for isoparametric elements
                mesh2 = dolfin.UnitDiscMesh(dolfin.MPI.comm_world, N // 2, 1,
                                            2)
                ue = fa.function_space().ufl_element()
                V2 = dolfin.FunctionSpace(mesh2, ue.family(), ue.degree())
                fa2, fh2 = dolfin.Function(V2), dolfin.Function(V2)
                fa2.vector().set_local(fa.vector().get_local())
                fh2.vector().set_local(fh.vector().get_local())
                fa, fh = fa2, fh2
            discr = ''  # '%g_%g_' % (N, dt)
            plot(fa, name + ' analytical', '%s%s_1analytical' % (discr, name))
            plot(fh, name + ' numerical', '%s%s_2numerical' % (discr, name))
            plot(fh - fa, name + ' diff', '%s%s_3diff' % (discr, name))

    hmin = mesh.hmin()
    return err_rho, err_u0, err_u1, err_p, err_rho_H1, err_u0_H1, err_u1_H1, err_p_H1, hmin, dt, Co_max, Pe_max, duration