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_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 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, 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 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
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 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 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 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 test_neumann_bcs_scalar_mms(method): "Test pure Neumann BCs using a Poisson solver" sim = Simulation() sim.input.read_yaml(yaml_string=BASE_INPUT) sim.input.set_value('mesh/Nx', 20) sim.input.set_value('mesh/Ny', 20) 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)' ) # Get analytical expressions cphi, cphix, cphiy, cf = mms_case() sim.input.set_value('solver/source', cf) if method.startswith('py'): cphix = '(-1.0 if x[0] < 0.5 else 1.0) * ' + cphix cphiy = '(-1.0 if x[1] < 0.5 else 1.0) * ' + cphiy else: cphix = '(x[0] < 0.5 ? -1.0 : 1.0) * ' + cphix cphiy = '(x[1] < 0.5 ? -1.0 : 1.0) * ' + cphiy # Setup the boundary conditions to test if method == 'py_eval': sim.input.set_value('boundary_conditions/0/phi/type', 'CodedGradient') sim.input.set_value('boundary_conditions/0/phi/code', cphix) sim.input.set_value('boundary_conditions/1/phi/type', 'CodedGradient') sim.input.set_value('boundary_conditions/1/phi/code', cphiy) elif method == 'py_exec': sim.input.set_value('boundary_conditions/0/phi/type', 'CodedGradient') sim.input.set_value('boundary_conditions/0/phi/code', 'value[0] = ' + cphix) sim.input.set_value('boundary_conditions/1/phi/type', 'CodedGradient') sim.input.set_value('boundary_conditions/1/phi/code', 'value[0] = ' + cphiy) elif method == 'cpp': sim.input.set_value('boundary_conditions/0/phi/type', 'CppCodedGradient') sim.input.set_value('boundary_conditions/0/phi/cpp_code', cphix) sim.input.set_value('boundary_conditions/1/phi/type', 'CppCodedGradient') sim.input.set_value('boundary_conditions/1/phi/cpp_code', cphiy) # 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) # Correct the constant offset due to how the null space is handled correct_constant_offset(sim, phih, phia) # 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.055