def test_sharp_field_dg0(): sim = Simulation() sim.input.read_yaml(yaml_string=INP) mesh = dolfin.UnitCubeMesh(2, 2, 2) sim.set_mesh(mesh) # Sharp jump at the cell boundaries field_inp = sim.input.get_value('fields/0', required_type='Input') f = SharpField(sim, field_inp).get_variable('rho') check_vector_value_histogram(f.vector(), {1: 24, 1000: 24}, round_digits=6) # Sharp jump in the middle of the cells field_inp['z'] = 0.25 f = SharpField(sim, field_inp).get_variable('rho') hist = get_vector_value_histogram(f.vector()) assert len(hist) == 4 for k, v in hist.items(): if round(k, 6) != 1: assert v == 8 else: assert v == 24 # Non-projected sharp jump between cells field_inp['local_projection'] = False field_inp['z'] = 0.50 f = SharpField(sim, field_inp).get_variable('rho') check_vector_value_histogram(f.vector(), {1: 24, 1000: 24}, round_digits=6) # Non-projected sharp jump the middle of the cells field_inp['z'] = 0.25 f = SharpField(sim, field_inp).get_variable('rho') hist = get_vector_value_histogram(f.vector()) check_vector_value_histogram(f.vector(), {1: 40, 1000: 8}, round_digits=6)
def test_get_dof_region_marks(): sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) setup_simulation(sim) Vp = sim.data['Vp'] dofs_x = Vp.tabulate_dof_coordinates().reshape((-1, 2)) drm = get_dof_region_marks(sim, Vp) num_in_region = [0, 0] ok = True for dof, marks in drm.items(): x, y = dofs_x[dof] if not (x == 0 or x == 1 or y == 0 or y == 1): mpi_print('Got unexpected dof coords', x, y) ok = False if (0 in marks) != (x == 1 or y == 0 or y == 1): mpi_print('Got unexpected dof coords in region 0', x, y) ok = False if (1 in marks) != (x == 0): mpi_print('Got unexpected dof coords in region 0', x, y) ok = False for mark in marks: num_in_region[mark] += 1 assert all_ok(ok) assert mpi_int_sum(num_in_region[0]) == 30 + 29 * 2 assert mpi_int_sum(num_in_region[1]) == 30
def test_user_constants(): sim = Simulation() sim.input.read_yaml(yaml_string=INPUT_USER_CONSTANTS) success = setup_simulation(sim) assert success assert sim.input.get_value('ref') == 42.0
def test_bdm_identity_transform(gdim): N = 5 k = 2 # Create mesh and define a divergence free field if gdim == 2: mesh = dolfin.UnitSquareMesh(N, N) field = ['-sin(pi*x[1])*cos(pi*x[0])', 'sin(pi*x[0])*cos(pi*x[1])'] elif gdim == 3: mesh = dolfin.UnitCubeMesh(N, N, N) field = [ '-sin(pi*x[0])*cos(pi*x[1])*sin(pi*x[2])', 'sin(pi*x[0])*cos(pi*x[1])*sin(pi*x[2])', '-cos(pi*x[2])*cos(pi*(x[0]-x[1]))', ] V = dolfin.FunctionSpace(mesh, 'DG', k) u = dolfin.as_vector([dolfin.Function(V) for _ in range(gdim)]) a = dolfin.as_vector([dolfin.Function(V) for _ in range(gdim)]) # Make a divergence free field for i, cpp in enumerate(field): ei = dolfin.Expression(cpp, degree=k) u[i].interpolate(ei) a[i].assign(u[i]) # Run the projection into BDM and then assign this to u bdm = VelocityBDMProjection(simulation=Simulation(), w=u, use_bcs=False) bdm.run() # Check the changes made for ui, ai in zip(u, a): error = dolfin.errornorm(ai, ui, degree_rise=0) assert error < 1e-15
def test_dirichlet_bcs_scalar_constant_value(method): "Test inhomogenous Dirichlet BCs using a Poisson solver" sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) sim.input.set_value('boundary_conditions', [{}]) sim.input.set_value('boundary_conditions/0/name', 'all walls') sim.input.set_value('boundary_conditions/0/selector', 'code') sim.input.set_value('boundary_conditions/0/inside_code', 'on_boundary') if method == 'const': sim.input.set_value('boundary_conditions/0/phi/type', 'ConstantValue') sim.input.set_value('boundary_conditions/0/phi/value', 1.0) elif method == 'py_eval': sim.input.set_value('boundary_conditions/0/phi/type', 'CodedValue') sim.input.set_value('boundary_conditions/0/phi/code', '1.0') elif method == 'py_exec': sim.input.set_value('boundary_conditions/0/phi/type', 'CodedValue') sim.input.set_value('boundary_conditions/0/phi/code', 'value[0] = 1.0') elif method == 'cpp': sim.input.set_value('boundary_conditions/0/phi/type', 'CppCodedValue') sim.input.set_value('boundary_conditions/0/phi/cpp_code', '1.0') setup_simulation(sim) run_simulation(sim) p = sim.data['phi'].vector().get_local() assert numpy.linalg.norm(p - 1.0) < 1e-8
def test_has_path(): fn = get_test_file_name('base.inp') sim = Simulation() sim.input.read_yaml(fn) assert sim.input.has_path('ocellaris') is True assert sim.input.has_path('ocellaris/type') is True assert sim.input.has_path('ocellaris222') is False assert sim.input.has_path('ocellaris222/type') is False assert sim.input.has_path('ocellaris/type222') is False
def test_use_code(): dummy_mod = '__DUMMY__' assert dummy_mod not in sys.modules sim = Simulation() sim.input.read_yaml(yaml_string=INPUT_USER_CODE) success = setup_simulation(sim) assert success assert dummy_mod in sys.modules sys.modules.pop(dummy_mod)
def test_child_input(): fn = get_test_file_name('child.inp') sim = Simulation() sim.input.read_yaml(fn) gv = lambda k, t: sim.input.get_value(k, required_type=t) assert gv('metadata/author', 'string') == 'Tormod Landet' # assert gv('metadata/date', 'date') == '2018-04-03' assert gv('metadata/description', 'string') == 'ThisIsTheDescription' assert gv('some_vals/computed', 'float') == 2.0 assert gv('test_py_val/C', 'float') == 8.0
def test_base_input(): fn = get_test_file_name('base.inp') sim = Simulation() sim.input.read_yaml(fn) gv = lambda k, t: sim.input.get_value(k, required_type=t) assert gv('metadata/author', 'string') == 'Tormod Landet' assert gv('metadata/description', 'string') == 'NoDescription' assert tuple(gv('some_vals/bools', 'list(int)')) == (1, 1, 0, 0) assert tuple(gv('some_vals/floats', 'list(float)')) == (1.1, 2, 3.0e3) assert gv('some_vals/computed', 'float') == 2.0
def mk_scheme(N, Vname, Vorder, cpp_expr, expr_args, convection_inp, dim=2, comm=None): if comm is None: comm = MPI.comm_world parameters['ghost_mode'] = 'shared_vertex' if dim == 2: mesh = UnitSquareMesh(comm, N, N) else: mesh = UnitCubeMesh(comm, N, N, N) V = FunctionSpace(mesh, Vname, Vorder) C = Function(V) e = Expression(cpp_expr, element=V.ufl_element(), **expr_args) C.interpolate(e) D = Function(V) D.assign(C) sim = Simulation() sim.set_mesh(mesh) sim.data['constrained_domain'] = None sim.data['C'] = C for key, value in convection_inp.items(): sim.input.set_value('convection/C/%s' % key, value) scheme_name = convection_inp['convection_scheme'] return get_convection_scheme(scheme_name)(sim, 'C')
def test_vector_field(): sim = Simulation() sim.input.read_yaml(yaml_string=INP) mesh = dolfin.UnitCubeMesh(2, 2, 2) sim.set_mesh(mesh) field_inp = sim.input.get_value('fields/0', required_type='Input') field = VectorField(sim, field_inp) def verify(f, t, A): print(t, A) check_vector_value_histogram(f[0].vector(), {t + A: 125}) check_vector_value_histogram(f[1].vector(), {t * A: 125}) check_vector_value_histogram(f[2].vector(), {t * A + A: 125}) # t = 0 t, A = 0, 1 f = field.get_variable('u') verify(f, t, A) # t = 1 t, A = 1, 1 sim.time = t sim.input.set_value('user_code/constants/A', A) field.update(1, t, 1.0) verify(f, t, A) # t = 2 t, A = 2, 10 sim.time = t sim.input.set_value('user_code/constants/A', A) field.update(2, t, 1.0) verify(f, t, A)
def test_scalar_field(): sim = Simulation() sim.input.read_yaml(yaml_string=INP) mesh = dolfin.UnitCubeMesh(2, 2, 2) sim.set_mesh(mesh) field_inp = sim.input.get_value('fields/1', required_type='Input') field = ScalarField(sim, field_inp) # t = 0 t, A = 0, 1 f = field.get_variable('rho') check_vector_value_histogram(f.vector(), {t * A + A: 125}) # t = 1 t, A = 1, 1 sim.time = t field.update(1, t, 1.0) check_vector_value_histogram(f.vector(), {t * A + A: 125}) # t = 2 t, A = 2, 10 sim.time = t sim.input.set_value('user_code/constants/A', A) field.update(2, t, 1.0) check_vector_value_histogram(f.vector(), {t * A + A: 125})
def test_restart_file_io(tmpdir_factory): dir_name = mpi_tmpdir(tmpdir_factory, 'test_restart_file_io') prefix = os.path.join(dir_name, 'ocellaris') sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT_PHI) sim.input.set_value('output/prefix', prefix) sim.input.set_value('time/tstart', 42.0) sim.input.set_value('time/dt', 1.0) setup_simulation(sim) # Fill in the phi function phi = sim.data['phi'] phi_arr = phi.vector().get_local() phi_arr[:] = numpy.random.rand(*phi_arr.shape) phi.vector().set_local(phi_arr) phi.vector().apply('insert') # Save restart file file_name = sim.io.write_restart_file() assert file_name.startswith(prefix) # Load input from restart file sim2 = Simulation() sim2.io.load_restart_file_input(file_name) assert sim2.input.get_value('time/tstart') == 42.0 assert str(sim.input) == str(sim2.input) # Load phi from restart file setup_simulation(sim2) sim2.io.load_restart_file_results(file_name) phi2 = sim2.data['phi'] phi2_arr = phi2.vector().get_local() # FIXME: make tests work in parallel if sim2.data['mesh'].mpi_comm().size == 1: assert all(phi_arr == phi2_arr) assert sim.data['mesh'].hash() == sim2.data['mesh'].hash()
def mk_limiter(degree, dim, use_cpp, comm_self=False): dolfin.parameters['ghost_mode'] = 'shared_vertex' sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) if dim == 2: sim.input.set_value('mesh/type', 'Rectangle') sim.input.set_value('mesh/Nx', 10) sim.input.set_value('mesh/Ny', 10) cpp = 'A + A*sin(B*pi*x[0])*sin(B*pi*x[1])' else: sim.input.set_value('mesh/type', 'Box') sim.input.set_value('mesh/Nx', 5) sim.input.set_value('mesh/Ny', 5) sim.input.set_value('mesh/Nz', 5) cpp = 'A + A*sin(B*pi*x[0])*sin(B*pi*x[1])*sin(B*pi*x[2])' # Create simulation with mesh and the phi function sim.input.set_value('mesh/mpi_comm', 'SELF' if comm_self else 'WORLD') sim.input.set_value('solver/polynomial_degree', degree) sim.input.set_value('output/stdout_enabled', False) setup_simulation(sim) phi = sim.data['phi'] V = phi.function_space() # Create a phi field with some jumps e = dolfin.Expression(cpp, element=V.ufl_element(), A=0.5, B=2.0) phi.interpolate(e) arr = phi.vector().get_local() arr[arr > 0.8] = 2 * 0.8 - arr[arr > 0.8] arr[arr < 0.2] = 0.5 phi.vector().set_local(arr) phi.vector().apply('insert') # Create slope limiter sim.input.set_value('slope_limiter/phi/method', 'HierarchicalTaylor') sim.input.set_value('slope_limiter/phi/use_cpp', use_cpp) sim.input.set_value('slope_limiter/phi/skip_boundaries', []) lim = SlopeLimiter(sim, 'phi', phi) if True: from matplotlib import pyplot pyplot.figure() patches = dolfin.plot(phi) pyplot.colorbar(patches) pyplot.savefig('ht_lim_phi.png') return phi, lim
def test_ensure_path(): fn = get_test_file_name('base.inp') sim = Simulation() sim.input.read_yaml(fn) a = sim.input.ensure_path('user_code/constants') assert 'A' in a b = sim.input.ensure_path('does_not_exist') assert len(b) == 0 assert 'does_not_exist' in sim.input c = sim.input.ensure_path('does_not_exist/c') assert len(c) == 0 assert len(sim.input.get_value('does_not_exist')) == 1
def test_import_module(): # A randomly selected script that does nothing at import time dummy_mod = 'plot_reports' assert dummy_mod not in sys.modules # Account for current working directory inp = INPUT_MODULE_IMPORT % os.path.join(TEST_DIR, '..') sim = Simulation() sim.input.read_yaml(yaml_string=inp) success = setup_simulation(sim) assert success assert dummy_mod in sys.modules sys.modules.pop(dummy_mod)
def test_isoline_circle(degree): sim = Simulation() sim.input.read_yaml(yaml_string=ISO_INPUT) sim.input.set_value('multiphase_solver/polynomial_degree_colour', degree) sim.input.set_value('mesh/Nx', 10) sim.input.set_value('mesh/Ny', 10) sim.input.set_value( 'initial_conditions/cp/cpp_code', '1.1*pow(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2), 0.5)' ) setup_simulation(sim) sim.data['c'].assign(sim.data['cp']) probe = sim.probes['free_surface'] lines = probe.run(force_active=True) if False: from matplotlib import pyplot c = dolfin.plot(sim.data['c']) pyplot.colorbar(c) for x, y in lines: pyplot.plot(x, y) pyplot.savefig('test_isoline_circle_%d.png' % degree) pyplot.close() print(probe.name, probe.field_name, probe.value) print(len(lines)) for x, y in lines: # Check that the radius is constant r = ((x - 0.5) ** 2 + (y - 0.5) ** 2) ** 0.5 print('x', x) print('y', y) print('dr', r - 0.5 / 1.1) assert all(abs(r - 0.5 / 1.1) < 5e-3) # Check that the line is clockwise or counter clockwise # for all segments, no going back and forth theta = numpy.arctan2(y - 0.5, x - 0.5) * 180 / numpy.pi theta[theta < 0] += 360 tdt = numpy.diff(theta) tdt2 = tdt[abs(tdt) < 340] print('dt', tdt) assert all(tdt2 > 0) or all(tdt2 < 0) if sim.ncpu == 1: # The iso surface code is not written for full parallel support assert len(lines) == 1 assert x[0] == x[-1] and y[0] == y[-1], "The loop should be closed"
def test_plot_io_3D(iotype, tmpdir_factory): dir_name = mpi_tmpdir(tmpdir_factory, 'test_plot_io_3D') prefix = os.path.join(dir_name, 'ocellaris') N = 4 sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT_VELPRES) sim.input.set_value('output/prefix', prefix) sim.input.set_value('user_code/constants/N', N) setup_simulation(sim) sim.io.setup() # Normally called in sim._at_start_of_simulation() for d in range(3): sim.data['u%d' % d].assign(sim.data['up%d' % d]) ncell = N**3 * 6 npoint = ncell * 10 if iotype == 'vtk': file_name = sim.io.lvtk.write() assert file_name.startswith(prefix) assert file_name.endswith('.vtk') assert os.path.isfile(file_name) with open(file_name, 'rt') as f: for line in f: if line.startswith('POINTS'): pline = line elif line.startswith('CELLS'): cline = line elif line.startswith('CELL_TYPES'): tline = line elif line.startswith('POINT_DATA'): dline = line assert pline.strip() == 'POINTS %d float' % npoint assert cline.strip() == 'CELLS %d %d' % (ncell, ncell * 11) assert tline.strip() == 'CELL_TYPES %d' % ncell assert dline.strip() == 'POINT_DATA %d' % (ncell * 10) elif iotype == 'xdmf': file_name = sim.io.xdmf.write() assert file_name.startswith(prefix) assert file_name.endswith('.xdmf') assert os.path.isfile(file_name)
def test_mark_cell_layers(): sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) setup_simulation(sim) mesh = sim.data['mesh'] Vp = sim.data['Vp'] # No named == all cells = mark_cell_layers(sim, Vp) for cid in cells: cell = dolfin.Cell(mesh, cid) mp = cell.midpoint()[:] assert mp[0] < 0.1 or mp[0] > 0.9 or mp[1] < 0.1 or mp[1] > 0.9 assert mpi_int_sum(len(cells)) == 20 * 2 + 16 * 2 # Test all cells = mark_cell_layers(sim, Vp, named_boundaries=['all']) for cid in cells: cell = dolfin.Cell(mesh, cid) mp = cell.midpoint()[:] assert mp[0] < 0.1 or mp[0] > 0.9 or mp[1] < 0.1 or mp[1] > 0.9 assert mpi_int_sum(len(cells)) * 2 + 16 * 2 # Test only left side cells = mark_cell_layers(sim, Vp, named_boundaries=['left']) for cid in cells: cell = dolfin.Cell(mesh, cid) mp = cell.midpoint()[:] assert mp[0] < 0.1 assert mpi_int_sum(len(cells)) == 20 cells = mark_cell_layers(sim, Vp, named_boundaries=['not left']) for cid in cells: cell = dolfin.Cell(mesh, cid) mp = cell.midpoint()[:] assert mp[0] > 0.9 or mp[1] < 0.1 or mp[1] > 0.9 assert mpi_int_sum(len(cells)) == 20 * 1 + 18 * 2 cells = mark_cell_layers(sim, Vp, named_boundaries=['left', 'not left']) assert mpi_int_sum(len(cells)) == 20 * 2 + 16 * 2
def test_dirichlet_bcs_scalar_mms(method): "Test inhomogenous coded Dirichlet BCs using a Poisson solver" sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) sim.input.set_value('boundary_conditions', [{}]) sim.input.set_value('boundary_conditions/0/name', 'all walls') sim.input.set_value('boundary_conditions/0/selector', 'code') sim.input.set_value('boundary_conditions/0/inside_code', 'on_boundary') # Get analytical expressions cphi, _, _, cf = mms_case() sim.input.set_value('solver/source', cf) # Setup the boundary conditions to test if method == 'py_eval': sim.input.set_value('boundary_conditions/0/phi/type', 'CodedValue') sim.input.set_value('boundary_conditions/0/phi/code', cphi) elif method == 'py_exec': sim.input.set_value('boundary_conditions/0/phi/type', 'CodedValue') sim.input.set_value('boundary_conditions/0/phi/code', 'value[0] = ' + cphi) elif method == 'cpp': sim.input.set_value('boundary_conditions/0/phi/type', 'CppCodedValue') sim.input.set_value('boundary_conditions/0/phi/cpp_code', cphi) # Run Ocellaris setup_simulation(sim) run_simulation(sim) # The numeric (phih) and analytic (phia) solution functions Vphi = sim.data['Vphi'] phi = dolfin.Expression(cphi, degree=5) phih = sim.data['phi'] phia = dolfin.interpolate(phi, Vphi) # Compute relative error and check that it is reasonable phidiff = dolfin.errornorm(phi, phih) analytical = dolfin.norm(phia) relative_error = phidiff / analytical print('RELATIVE ERROR IS %.3f' % relative_error) assert relative_error < 0.074
def test_isoline_horizontal(degree): sim = Simulation() sim.input.read_yaml(yaml_string=ISO_INPUT) sim.input.set_value('multiphase_solver/polynomial_degree_colour', degree) setup_simulation(sim) probe = sim.probes['free_surface'] # Initial value with sharp interface at x[1] == 0.5 Vc = sim.data['Vc'] c = sim.data['c'] dm = Vc.dofmap() arr = c.vector().get_local() for cell in dolfin.cells(sim.data['mesh']): cell_value = 1 if cell.midpoint().y() < 0.5 else 0 for dof in dm.cell_dofs(cell.index()): arr[dof] = cell_value c.vector().set_local(arr) c.vector().apply('insert') lines = probe.run(force_active=True) print('\nDegree:', degree, 'Vcdim:', Vc.dim()) print(probe.name, probe.field_name, probe.value) print(len(lines)) if sim.ncpu > 1: raise pytest.skip() for x, y in lines: print('x', x, '\ny', y) assert all(abs(y - 0.5) < 1e-12) # Results should be in sorted order xdx = numpy.diff(x) assert all(xdx > 0) or all(xdx < 0) assert len(lines) == 1
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
def plot_backward_facing_step(res): u = df.as_vector([res['u0'], res['u1']]) V = u[0].function_space() mesh = V.mesh() ############################################################################ # Get some meta data sim = Simulation() sim.input.read_yaml(yaml_string=res['input']) Re = sim.input.get_value('user_code/constants/Re', required_type='float') time = res['time'] ############################################################################ # Find the length X1 of primary recirculating bubble x1_ypos = -0.99 * H2 xf, _, _, f = get_probe_values(u[0], [0, x1_ypos, 0], [L2, x1_ypos, 0], 200) x1_c0 = get_zero_crossings(xf, f) print(x1_c0) ############################################################################ # Find the inflow profile x_inflow = -1.5 * H1 _, y_inflow, _, u0_inflow = get_probe_values( u[0], [x_inflow, 0, 0], [x_inflow, H1, 0], 20 ) ############################################################################ # Refine the mesh and get a triangluated stream function for _ in range(2): old = mesh, V mesh = df.refine(mesh) V = df.FunctionSpace(mesh, V.ufl_element()) df.parameters['allow_extrapolation'] = True try: u0 = df.interpolate(u[0], V) u1 = df.interpolate(u[1], V) u = df.as_vector([u0, u1]) except Exception: mesh, V = old u0, u1 = u[0], u[1] print('Refining failed ------------------------------') break df.parameters['allow_extrapolation'] = False sf = StreamFunction(u, degree=V.ufl_element().degree()) sf.compute() levels = get_probe_values( sf.psi, [1.5 * H2, -0.5 * H2, 0], [H2, H1 * 0.99, 0], N_levels )[-1] levels2 = [] for xi, _idx, _upcrossing in x1_c0: # Add stream function values at upcrossing locations if xi - 0.3 > 0: levels2.append(get_probe_value(sf.psi, (xi - 0.3, x1_ypos, 0))) if xi + 0.1 < L2: levels2.append(get_probe_value(sf.psi, (xi + 0.1, x1_ypos, 0))) if levels2: levels = numpy.concatenate((levels, levels2)) levels.sort() coords = mesh.coordinates() triangles = [] for cell in df.cells(mesh): cell_vertices = cell.entities(0) triangles.append(cell_vertices) triangulation = Triangulation(coords[:, 0], coords[:, 1], triangles) Z = sf.psi.compute_vertex_values() ############################################################################ # Plot streamlines and velocity distributions fig = pyplot.figure(figsize=(15, 2.5)) ax = fig.add_subplot(111) ax.plot([-L1, -L1, 0, 0, L2, L2, -L1], [H1, 0, 0, -H2, -H2, H1, H1], 'k') # ax.triplot(triangulation, color='#000000', alpha=0.5, lw=0.25) ax.tricontour( triangulation, Z, levels, linestyles='solid', colors='#0000AA', linewidths=0.5 ) ax.plot(x_inflow + u0_inflow, y_inflow, 'm') ax.plot(x_inflow - 6 * (y_inflow - 1) * y_inflow, y_inflow, 'k.', ms=4) # ax2 = fig.add_subplot(212) # ax2.plot(xf, f) # ax2.set_xlim(-L1, L2) for xi, _idx, _upcrossing in x1_c0: ax.plot(xi, x1_ypos, 'rx') # ax.text(xi, x1_ypos+0.1, 'X1=%.3f' % x1, backgroundcolor='white') ax.set_title( 'Re = %g, t = %g, xi = %s' % (Re, time, ', '.join('%.3f' % e[0] for e in x1_c0)) ) fig.tight_layout()
def test_robin_bcs_scalar_mms(bcs, b): """ Test Robin BCs using a Poisson solver to solve -∇⋅∇φ = f where φ = 1 + x and hence f = 0. We use Neumann BCs n⋅∇φ = 0 on the horizontal walls and Robin BCs on the vertical walls """ sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) # Create boundary regions sim.input.set_value('boundary_conditions', [{}, {}, {}]) sim.input.set_value('boundary_conditions/0/name', 'vertical wall x=0') sim.input.set_value('boundary_conditions/0/selector', 'code') sim.input.set_value( 'boundary_conditions/0/inside_code', 'on_boundary and (x[0] < 1e-6 or x[0] > 1 - 1e-6)' ) sim.input.set_value('boundary_conditions/1/name', 'vertical walls x=1') sim.input.set_value('boundary_conditions/1/selector', 'code') sim.input.set_value('boundary_conditions/1/inside_code', 'on_boundary and x[0] > 1 - 1e-6') sim.input.set_value('boundary_conditions/2/name', 'horizontal walls') sim.input.set_value('boundary_conditions/2/selector', 'code') sim.input.set_value( 'boundary_conditions/2/inside_code', 'on_boundary and (x[1] < 1e-6 or x[1] > 1 - 1e-6)' ) # Setup the boundary conditions to test if bcs == 'robin': sim.input.set_value('boundary_conditions/0/phi/type', 'ConstantRobin') sim.input.set_value('boundary_conditions/0/phi/blend', b) sim.input.set_value('boundary_conditions/0/phi/dval', 1.0) sim.input.set_value('boundary_conditions/0/phi/nval', -1.0) sim.input.set_value('boundary_conditions/1/phi/type', 'ConstantRobin') sim.input.set_value('boundary_conditions/1/phi/blend', b) sim.input.set_value('boundary_conditions/1/phi/dval', 2.0) sim.input.set_value('boundary_conditions/1/phi/nval', 1.0) sim.input.set_value('boundary_conditions/2/phi/type', 'ConstantGradient') sim.input.set_value('boundary_conditions/2/phi/value', 0.0) elif bcs == 'neumann': sim.input.set_value('boundary_conditions/0/phi/type', 'ConstantGradient') sim.input.set_value('boundary_conditions/0/phi/value', -1.0) sim.input.set_value('boundary_conditions/1/phi/type', 'ConstantGradient') sim.input.set_value('boundary_conditions/1/phi/value', 1.0) # RHS sim.input.set_value('solver/source', '2*pi*pi*(pow(sin(x[0]*pi), 2) - pow(cos(x[0]*pi), 2))') # Run Ocellaris setup_simulation(sim) run_simulation(sim) # The numeric (phih) and analytic (phia) solution functions cphi = '1.0 + x[0] + pow(sin(x[0]*pi), 2)' Vphi = sim.data['Vphi'] phi = dolfin.Expression(cphi, degree=5) phih = sim.data['phi'] phia = dolfin.interpolate(phi, Vphi) # Correct the constant offset due to how the null space is handledFalse if bcs == 'neumann': correct_constant_offset(sim, phih, phia) # Plot to file for debugging # debug_phi_plot(phia, phih, 'test_robin_bcs_scalar_mms_%s.png' % bcs) # Compute relative error and check that it is reasonable phidiff = dolfin.errornorm(phi, phih) analytical = dolfin.norm(phia) relative_error = phidiff / analytical print('RELATIVE ERROR IS %.3f' % relative_error) assert relative_error < 0.015 # Expect 0.0139 with Robin
def run_and_calculate_error(N, dt, tmax, polydeg_u, polydeg_p, modifier=None): """ Run Ocellaris and return L2 & H1 errors in the last time step """ say(N, dt, tmax, polydeg_u, polydeg_p) # Setup and run simulation sim = Simulation() sim.input.read_yaml('kovasznay.inp') 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('output/stdout_enabled', False) if modifier: modifier(sim) # Running regression tests, modify some input params say('Running ...') try: t1 = time.time() setup_simulation(sim) run_simulation(sim) duration = time.time() - t1 except KeyboardInterrupt: raise except BaseException as e: raise import traceback traceback.print_exc() return [1e10] * 6 + [1, dt, time.time() - t1] say('DONE') tmax_warning = ' <------ NON CONVERGENCE!!' if sim.time > tmax - dt / 2 else '' # Interpolate the analytical solution to the same function space Vu = sim.data['Vu'] Vp = sim.data['Vp'] lambda_ = sim.input.get_value('user_code/constants/LAMBDA', required_type='float') u0e = dolfin.Expression( sim.input.get_value('boundary_conditions/0/u/cpp_code/0'), LAMBDA=lambda_, degree=polydeg_u) u1e = dolfin.Expression( sim.input.get_value('boundary_conditions/0/u/cpp_code/1'), LAMBDA=lambda_, degree=polydeg_u) pe = dolfin.Expression( '-0.5*exp(LAMBDA*2*x[0]) + 1/(4*LAMBDA)*(exp(2*LAMBDA) - 1.0)', LAMBDA=lambda_, degree=polydeg_p, ) u0a = dolfin.project(u0e, Vu) u1a = dolfin.project(u1e, Vu) pa = dolfin.project(pe, Vp) # Correct pa (we want to be spot on, not close) int_pa = dolfin.assemble(pa * dolfin.dx) vol = dolfin.assemble(dolfin.Constant(1.0) * dolfin.dx(domain=Vp.mesh())) pa.vector()[:] -= int_pa / vol # Calculate L2 errors 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_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') say('Number of time steps:', sim.timestep, tmax_warning) loglines = sim.log.get_full_log().split('\n') say('Num inner iterations:', sum(1 if 'Inner iteration' in line else 0 for line in loglines)) say('max(ui_new-ui_prev)', sim.reporting.get_report('max(ui_new-ui_prev)')[1][-1]) int_p = dolfin.assemble(sim.data['p'] * dolfin.dx) say('p*dx', int_p) say('pa*dx', dolfin.assemble(pa * dolfin.dx(domain=Vp.mesh()))) 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(sim.data['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(sim.data['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) if False: # Plot the results for fa, name in ((u0a, 'u0'), (u1a, 'u1'), (pa, 'p')): p1 = dolfin.plot(sim.data[name] - fa, title='%s_diff' % name, key='%s_diff' % name) p2 = dolfin.plot(fa, title=name + ' analytical', key=name) p1.write_png('%g_%g_%s_diff' % (N, dt, name)) p2.write_png('%g_%g_%s' % (N, dt, name)) dolfin.interactive() from numpy import argmax for d in range(2): up = sim.data['up%d' % d] upp = sim.data['upp%d' % d] V = up.function_space() coords = V.tabulate_dof_coordinates().reshape((-1, 2)) up.vector()[:] -= upp.vector() diff = abs(up.vector().get_local()) i = argmax(diff) say('Max difference in %d direction is %.4e at %r' % (d, diff[i], coords[i])) if 'uppp%d' % d in sim.data: uppp = sim.data['uppp%d' % d] upp.vector()[:] -= uppp.vector() diffp = abs(upp.vector().get_local()) ip = argmax(diffp) say('Prev max diff. in %d direction is %.4e at %r' % (d, diffp[ip], coords[ip])) if False and N == 24: # dolfin.plot(sim.data['u0'], title='u0') # dolfin.plot(sim.data['u1'], title='u1') # dolfin.plot(sim.data['p'], title='p') # dolfin.plot(u0a, title='u0a') # dolfin.plot(u1a, title='u1a') # dolfin.plot(pa, title='pa') plot_err(sim.data['u0'], u0a, title='u0a - u0') plot_err(sim.data['u1'], u1a, title='u1a - u1') plot_err(sim.data['p'], pa, 'pa - p') # plot_err(sim.data['u0'], u0a, title='u0a - u0') dolfin.plot(sim.data['up0'], title='up0 - upp0') dolfin.plot(sim.data['upp0'], title='upp0 - uppp0') # plot_err(sim.data['u1'], u1a, title='u1a - u1') dolfin.plot(sim.data['up1'], title='up1 - upp1') # dolfin.plot(sim.data['upp1'], title='upp1 - uppp1') hmin = sim.data['mesh'].hmin() return err_u0, err_u1, err_p, err_u0_H1, err_u1_H1, err_p_H1, hmin, dt, duration
def test_slip_length_robin_bcs_scalar_mms(slip_length, method): """ Test slip length Robin BCs using a Poisson solver to solve -∇⋅∇φ = f where φ = (-6x² + 6x + 6𝛿)/(6𝛿 - 1) and hence f = 12/(6𝛿 - 1). We use Neumann BCs n⋅∇φ = 0 on the horizontal walls and Navier's slip length boundary condition on the vertical walls. The selected analytical solution is such that for any slip length 𝛿 the average value of φ is 1.0 This mimics a flow profile going vertically in a 1.0 wide channel """ sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) # Create boundary regions sim.input.set_value('boundary_conditions', [{}, {}]) sim.input.set_value('boundary_conditions/0/name', 'vertical walls') sim.input.set_value('boundary_conditions/0/selector', 'code') sim.input.set_value( 'boundary_conditions/0/inside_code', 'on_boundary and (x[0] < 1e-6 or x[0] > 1 - 1e-6)' ) sim.input.set_value('boundary_conditions/1/name', 'horizontal walls') sim.input.set_value('boundary_conditions/1/selector', 'code') sim.input.set_value( 'boundary_conditions/1/inside_code', 'on_boundary and (x[1] < 1e-6 or x[1] > 1 - 1e-6)' ) # Vertical wall BCs if method == 'Constant': sim.input.set_value('boundary_conditions/0/phi/type', 'SlipLength') sim.input.set_value('boundary_conditions/0/phi/slip_length', slip_length) elif method == 'C++': sim.input.set_value('boundary_conditions/0/phi/type', 'SlipLength') sim.input.set_value('boundary_conditions/0/phi/slip_length', repr(slip_length)) else: sim.input.set_value('boundary_conditions/0/phi/type', 'InterfaceSlipLength') sim.input.set_value('boundary_conditions/0/phi/slip_length', slip_length) sim.input.set_value('boundary_conditions/0/phi/slip_factor_function', 'fs_zone/phi') sim.input.set_value('fields', [{}]) sim.input.set_value('fields/0/name', 'fs_zone') sim.input.set_value('fields/0/type', 'FreeSurfaceZone') sim.input.set_value('fields/0/radius', 0.5) # Create dummy scalar field sim.input.set_value('multiphase_solver/type', 'BlendedAlgebraicVOF') sim.input.set_value('multiphase_solver/function_space_colour', 'DG') sim.input.set_value('multiphase_solver/polynomial_degree_colour', 0) sim.input.set_value('initial_conditions/cp/cpp_code', 'x[1] < 0.5 ? 1.0 : 0.0') sim.input.set_value('physical_properties/rho0', 1.0) sim.input.set_value('physical_properties/rho1', 1.0) sim.input.set_value('physical_properties/nu0', 1.0) sim.input.set_value('physical_properties/nu1', 1.0) sim.input.set_value('multiphase_solver/project_uconv_dgt0', False) sim.data['u_conv'] = dolfin.as_vector([0, 0]) sim.data['dt'] = dolfin.Constant(1.0) # Horizontal wall BCs sim.input.set_value('boundary_conditions/1/phi/type', 'ConstantGradient') sim.input.set_value('boundary_conditions/1/phi/value', 0.0) # RHS sim.input.set_value('solver/source', '12/(6*𝛿 - 1.0)'.replace('𝛿', repr(slip_length))) # Run Ocellaris setup_simulation(sim) run_simulation(sim) # The numeric (phih) and analytic (phia) solution functions cphi = '(-6*x[0]*x[0] + 6*x[0] + 6*𝛿)/(6*𝛿 - 1.0)'.replace('𝛿', repr(slip_length)) Vphi = sim.data['Vphi'] phi = dolfin.Expression(cphi, degree=5) phih = sim.data['phi'] phia = dolfin.interpolate(phi, Vphi) # Plot to file for debugging # debug_phi_plot(phi, phia, phih, 'test_slip_length_bcs_scalar_mms_%g.png' % slip_length) # Compute relative error and check that it is reasonable phidiff = dolfin.errornorm(phi, phih) analytical = dolfin.norm(phia) relative_error = phidiff / analytical print('RELATIVE ERROR IS %.4f for 𝛿=%r' % (relative_error, slip_length)) if method == 'Interface' and False: from matplotlib import pyplot fig = pyplot.figure(figsize=(8, 15)) fig.add_subplot(311) c = dolfin.plot(sim.data['c']) pyplot.colorbar(c) fig.add_subplot(312) c = dolfin.plot(sim.data['ls_c_0_5']) pyplot.colorbar(c) fig.add_subplot(313) c = dolfin.plot(sim.fields['fs_zone'].get_variable('phi')) pyplot.colorbar(c) fig.tight_layout() fig.savefig('AAAAAAAAAAAaaaa.png') assert relative_error < 0.0099 # Expect 0.0097 for 𝛿=0.001
def main(inputfile, input_override): """ Run Ocellaris """ if os.environ.get('OCELLARIS_SUPER_DEBUG', False): print('FOUND OCELLARIS_SUPER_DEBUG in environment') from ocellaris.utils.debug import enable_super_debug enable_super_debug() sim = Simulation() # Read input if sim.io.is_restart_file(inputfile): sim.io.load_restart_file_input(inputfile) else: sim.input.read_yaml(inputfile) # Alter input by values given on the command line override_input_variables(sim, input_override) # Setup logging before we start printing anything sim.log.setup() # Print banner with Ocellaris version number version = get_detailed_version() location = os.path.split(os.path.abspath(__file__))[0] sim.log.info('=' * 80) sim.log.info(' Ocellaris %s' % version) sim.log.info('=' * 80) sim.log.info('Installed at:') sim.log.info(' %s' % location) sim.log.info(' host: %s' % platform.node()) sim.log.info() # Print some version information sim.log.info('Running on Python %s' % sys.version) sim.log.info(' Using dolfin %s' % dolfin.__version__) sim.log.info(' Using mpi4py %s' % mpi4py.__version__) sim.log.info(' Using h5py %s' % h5py.__version__) sim.log.info(' Using meshio %s' % meshio.__version__) sim.log.info(' Using PyYAML %s' % yaml.__version__) sim.log.info(' Using petsc4py %s' % petsc4py_version) sim.log.info(' Using PETSc %d.%d.%d\n' % PETSc.Sys.getVersion()) # Setup the Ocellaris simulation ok = setup_simulation(sim, setup_logging=False, catch_exceptions=True) if not ok: sim.log.error('Setup did not suceed, exiting') sys.exit(1) if sim.restarted: # Load previous results sim.io.load_restart_file_results(inputfile) # Run the Ocellaris simulation time loop run_simulation(sim, catch_exceptions=True) sim.log.info('=' * 80) if sim.success: sim.log.info('Ocellaris finished successfully') else: sim.log.info('Ocellaris finished with errors')
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
def mk_vof_sim(case_name, modifier=None): sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) cases = { 'DG0_2D_y': (2, 0, 'y'), 'DG0_3D_z': (3, 0, 'z'), 'DG0_2D_x': (2, 0, 'x') } dim, vof_deg, surf_normal = cases[case_name] if dim == 3: sim.input.set_value('mesh/type', 'Box') sim.input.set_value('mesh/Nz', 2) sim.test_name = case_name if surf_normal == 'x': sim.input.set_value('initial_conditions/cp/cpp_code', 'x[0] < 0.5 ? 0.0 : 1.0') sim.test_surf_normal = [1, 0, 0] sim.test_coord_index = 0 elif surf_normal == 'y': sim.input.set_value('initial_conditions/cp/cpp_code', 'x[1] < 0.5 ? 1.0 : 0.0') sim.test_surf_normal = [0, -1, 0] sim.test_coord_index = 1 elif surf_normal == 'z': sim.input.set_value('initial_conditions/cp/cpp_code', 'x[2] < 0.5 ? 1.0 : 0.0') sim.test_surf_normal = [0, 0, -1] sim.test_coord_index = 2 sim.input.set_value('multiphase_solver/polynomial_degree_colour', vof_deg) # Run any custom code if modifier is not None: modifier(sim) sim.log.setup() sim.setup() sim.data['c'].assign(sim.data['cp']) return sim
def run_and_calculate_error(N, dt, tmax, polydeg_u, polydeg_p, modifier=None): """ Run Ocellaris and return L2 & H1 errors in the last time step """ say(N, dt, tmax, polydeg_u, polydeg_p) # Setup and run simulation sim = Simulation() sim.input.read_yaml('taylor-green.inp') if sim.input.get_value('mesh/type') == 'Rectangle': # Use structured mesh sim.input.set_value('mesh/Nx', N) sim.input.set_value('mesh/Ny', N) else: # Create unstructured mesh with gmsh cmd1 = [ 'gmsh', '-string', 'lc = %f;' % (2.0 / N), '-o', 'taylor-green_%d.msh' % N, '-2', 'taylor-green.geo', ] cmd2 = [ 'dolfin-convert', 'taylor-green_%d.msh' % N, 'taylor-green.xml' ] with open('/dev/null', 'w') as devnull: for cmd in (cmd1, cmd2): say(' '.join(cmd)) subprocess.call(cmd, stdout=devnull, stderr=devnull) 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('output/stdout_enabled', False) if sim.input.get_value('solver/timestepping_method', 'BDF') == 'CN': sim.input.set_value( 'initial_conditions/p/cpp_code', '-(cos(2*pi*x[0]) + cos(2*pi*x[1])) * exp(-4*pi*pi*nu*(t+dt/2))/4', ) # Turn off BDM # sim.input.set_value('solver/velocity_postprocessing', 'None') if modifier: modifier(sim) # Running regression tests, modify some input params say('Running with %s %s solver ...' % ( sim.input.get_value('solver/type'), sim.input.get_value('solver/function_space_velocity', 'DG'), )) t1 = time.time() setup_simulation(sim) if 'Vcoupled' in sim.data: say('Num unknowns', sim.data['Vcoupled'].dim()) 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'] vals = dict( t=sim.time, dt=sim.dt, nu=sim.input['physical_properties']['nu'], rho=sim.input['physical_properties']['rho'], ) u0e = dolfin.Expression( sim.input.get_value('initial_conditions/up0/cpp_code'), degree=polydeg_u + 3, **vals) u1e = dolfin.Expression( sim.input.get_value('initial_conditions/up1/cpp_code'), degree=polydeg_u + 3, **vals) if sim.input.get_value('solver/timestepping_method', 'BDF') == 'CN': vals['t'] = sim.time - sim.dt pe = dolfin.Expression( sim.input.get_value('initial_conditions/p/cpp_code'), degree=polydeg_p + 3, **vals) u0a = dolfin.project(u0e, Vu) u1a = dolfin.project(u1e, Vu) pa = dolfin.project(pe, Vp) # Calculate L2 errors 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_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') say('Number of time steps:', sim.timestep) loglines = sim.log.get_full_log().split('\n') say('Num inner iterations:', sum(1 if 'iteration' in line else 0 for line in loglines)) int_p = dolfin.assemble(sim.data['p'] * dolfin.dx) say('Number of mesh cells:', sim.data['mesh'].num_cells()) 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(sim.data['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(sim.data['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) if 'u_mesh' in sim.data: Vmesh = sim.data['Vmesh'] div_u_mesh_Vmesh = abs( dolfin.project(dolfin.div(sim.data['u_mesh']), Vmesh).vector().get_local()).max() say('div(u_mesh)|V_mesh', div_u_mesh_Vmesh) div_u_mesh_DG0 = abs( dolfin.project(dolfin.div(sim.data['u_mesh']), Vdg0).vector().get_local()).max() say('div(u_mesh)|DG0', div_u_mesh_DG0) div_u_mesh_DG1 = abs( dolfin.project(dolfin.div(sim.data['u_mesh']), Vdg1).vector().get_local()).max() say('div(u_mesh)|DG1', div_u_mesh_DG1) if False: # Plot the results for fa, name in ((u0a, 'u0'), (u1a, 'u1'), (pa, 'p')): p1 = dolfin.plot(sim.data[name] - fa, title='%s_diff' % name, key='%s_diff' % name) p2 = dolfin.plot(fa, title=name + ' analytical', key=name) p1.write_png('%g_%g_%s_diff' % (N, dt, name)) p2.write_png('%g_%g_%s' % (N, dt, name)) dolfin.interactive() if N == 40 and False: dolfin.plot(sim.data['u0'], title='u0') dolfin.plot(sim.data['u1'], title='u1') dolfin.plot(sim.data['p'], title='p') dolfin.plot(u0a, title='u0a') dolfin.plot(u1a, title='u1a') dolfin.plot(pa, title='pa') plot_err(sim.data['u0'], u0a, 'u0a - u0') plot_err(sim.data['u1'], u1a, 'u1a - u1') plot_err(sim.data['p'], pa, 'pa - p') hmin = sim.data['mesh'].hmin() return err_u0, err_u1, err_p, err_u0_H1, err_u1_H1, err_p_H1, hmin, dt, duration