def assert_solves( mesh: Mesh, diffusion: Coefficient, convection: Optional[Coefficient], reaction: Optional[Coefficient], source: Coefficient, exact: Coefficient, l2_tol: Optional[float] = 1.0e-8, h1_tol: Optional[float] = 1.0e-6, ): eafe_matrix = eafe_assemble(mesh, diffusion, convection, reaction) pw_linears = FunctionSpace(mesh, "Lagrange", 1) test_function = TestFunction(pw_linears) rhs_vector = assemble(source * test_function * dx) bc = DirichletBC(pw_linears, exact, lambda _, on_bndry: on_bndry) bc.apply(eafe_matrix, rhs_vector) solution = Function(pw_linears) solver = LUSolver(eafe_matrix, "default") solver.parameters["symmetric"] = False solver.solve(solution.vector(), rhs_vector) l2_err: float = errornorm(exact, solution, "l2", 3) assert l2_err <= l2_tol, f"L2 error too large: {l2_err} > {l2_tol}" h1_err: float = errornorm(exact, solution, "H1", 3) assert h1_err <= h1_tol, f"H1 error too large: {h1_err} > {h1_tol}"
def app_pverr(tcur): cdatstr = get_dtstr(t=tcur, **dtstrdct) vp = np.load(cdatstr + '.npy') v, p = expand_vp_dolfunc(PrP, vp=vp) # vpref = np.load(cdatstrref + '.npy') # vref, pref = expand_vp_dolfunc(PrP, vp=vpref) vref = np.load(vdref[tcur] + '.npy') pref = np.load(pdref[tcur] + '.npy') # vpref = np.vstack([vref, pref]) vreff, preff = expand_vp_dolfunc(PrP, vc=vref, pc=pref) # vdiff, pdiff = expand_vp_dolfunc(PrP, vc=vp[:Nv]-vref, # pc=vp[Nv:]-pref) # prtrial = snu.get_pfromv(v=vref, **snsedict) # vrtrial, prtrial = expand_vp_dolfunc(PrP, vc=vref, pc=prtrial) # print 'pref', dolfin.norm(preff) # print 'p', dolfin.norm(p) # print 'p(v)', dolfin.norm(ptrial) # print 'p(vref){0}\n'.format(dolfin.norm(prtrial)) elv.append(dolfin.errornorm(v, vreff)) elp.append(dolfin.errornorm(p, preff)) # elv.append(dolfin.norm(vdiff)) # elp.append(dolfin.norm(pdiff)) cres = J*vp[:Nv]-fpbc mpires = (Mpfac.solve(cres.flatten())).reshape((cres.size, 1)) ncres = np.sqrt(np.dot(cres.T, mpires))[0][0] # ncres = np.sqrt(np.dot(cres.T, MP*cres))[0][0] # routine from time_int_schemes seems buggy for CR or 'g not 0' # ncres = comp_cont_error(v, fpbc, PrP.Q) elc.append(ncres)
def compute_error(problem, mesh_size): mesh = problem.mesh_generator(mesh_size) u = problem.solution['u'] u_sol = Expression((ccode(u['value'][0]), ccode(u['value'][1])), degree=u['degree']) p = problem.solution['p'] p_sol = Expression(ccode(p['value']), degree=p['degree']) f = Expression( (ccode(problem.f['value'][0]), ccode(problem.f['value'][1])), degree=problem.f['degree']) W = VectorElement('Lagrange', mesh.ufl_cell(), 2) P = FiniteElement('Lagrange', mesh.ufl_cell(), 1) WP = FunctionSpace(mesh, W * P) # Get Dirichlet boundary conditions u_bcs = DirichletBC(WP.sub(0), u_sol, 'on_boundary') p_bcs = DirichletBC(WP.sub(1), p_sol, 'on_boundary') u_approx, p_approx = flow.stokes.solve(WP, bcs=[u_bcs, p_bcs], mu=problem.mu, f=f, verbose=True, tol=1.0e-12) # compute errors u_error = errornorm(u_sol, u_approx) p_error = errornorm(p_sol, p_approx) return mesh.hmax(), u_error, p_error
def compute_err(self, is_tent, velocity, t): if self.doErrControl: er_list_L2 = self.listDict['u2L2' if is_tent else 'u_L2']['list'] er_list_H1 = self.listDict['u2H1' if is_tent else 'u_H1']['list'] self.tc.start('errorV') # assemble is faster than errornorm errorL2_sq = assemble(inner(velocity - self.solution, velocity - self.solution) * dx) errorH1seminorm_sq = assemble(inner(grad(velocity - self.solution), grad(velocity - self.solution)) * dx) info(' H1 seminorm error: %f' % sqrt(errorH1seminorm_sq)) errorL2 = sqrt(errorL2_sq) errorH1 = sqrt(errorL2_sq + errorH1seminorm_sq) info(" Relative L2 error in velocity = %f" % (errorL2 / self.analytic_v_norm_L2)) self.last_error = errorH1 / self.analytic_v_norm_H1 self.last_status_functional = self.last_error info(" Relative H1 error in velocity = %f" % self.last_error) er_list_L2.append(errorL2) er_list_H1.append(errorH1) self.tc.end('errorV') if self.testErrControl: er_list_test_H1 = self.listDict['u2H1test' if is_tent else 'u_H1test']['list'] er_list_test_L2 = self.listDict['u2L2test' if is_tent else 'u_L2test']['list'] self.tc.start('errorVtest') er_list_test_L2.append(errornorm(velocity, self.solution, norm_type='L2', degree_rise=0)) er_list_test_H1.append(errornorm(velocity, self.solution, norm_type='H1', degree_rise=0)) self.tc.end('errorVtest') # stopping criteria for detecting diverging solution if self.last_error > self.divergence_treshold: raise RuntimeError('STOPPED: Failed divergence test!')
def main(N, dt, T, theta=0.5): """Run bidomain MMA.""" # Exact solutions u_exact_str = "-cos(pi*x[0])*cos(pi*x[1])*sin(t)/2.0" v_exact_str = "cos(pi*x[0])*cos(pi*x[1])*sin(t)" s_exact_str = "-cos(pi*x[0])*cos(pi*x[1])*cos(t)" # Source term ac_str = "cos(t)*cos(pi*x[0])*cos(pi*x[1]) + pow(pi, 2)*cos(pi*x[0])*cos(pi*x[1])*sin(t)" ac_str += " - " + s_exact_str # Create data mesh = df.UnitSquareMesh(N, N) time = df.Constant(0.0) # We choose the FHN parameters such that s=1 and I_s=v model = SimpleODEModel() model.set_initial_conditions(V=0, S=df.Expression(s_exact_str, degree=5, t=0)) # Set initial condition ps = SplittingSolver.default_parameters() ps["pde_solver"] = "bidomain" ps["theta"] = theta # ps["CardiacODESolver"]["scheme"] = "RK4" ps["BidomainSolver"]["linear_solver_type"] = "direct" ps["BidomainSolver"]["use_avg_u_constraint"] = True ps["BidomainSolver"]["Chi"] = 1.0 ps["BidomainSolver"]["Cm"] = 1.0 ps["apply_stimulus_current_to_pde"] = True stimulus = df.Expression(ac_str, t=time, dt=dt, degree=5) M_i = 1.0 M_e = 1.0 heart = xalbrain.Model(mesh, time, M_i, M_e, model, stimulus) splittingsolver = SplittingSolver(heart, parameters=ps) # Define exact solution (Note: v is returned at end of time # interval(s), u is computed at somewhere in the time interval # depending on theta) v_exact = df.Expression(v_exact_str, t=T, degree=3) u_exact = df.Expression(u_exact_str, t=T - (1. - theta) * dt, degree=3) pde_vs_, pde_vs, vur = splittingsolver.solution_fields() pde_vs_.assign(model.initial_conditions()) solutions = splittingsolver.solve(0, T, dt) for (t0, t1), (vs_, vs, vur) in solutions: pass # Compute errors v = vs.split(deepcopy=True)[0] u = vur.split(deepcopy=True)[1] v_error = df.errornorm(v_exact, v, "L2", degree_rise=2) u_error = df.errornorm(u_exact, u, "L2", degree_rise=2) return v_error, u_error, mesh.hmin(), dt, T
def test_superposition_dirichlet_boundary_conditions(self): nx, ny = 31, 31 degree = 2 kappa = dla.Constant(3) xl, xr, yb, yt = 0.25, 1.25, 0.25, 1.25 sols = [] mesh = dla.RectangleMesh(dl.Point(xl, yb), dl.Point(xr, yt), nx, ny) function_space = dl.FunctionSpace(mesh, "Lagrange", degree) for ii in range(4): boundary_conditions =\ get_dirichlet_boundary_conditions_from_expression( get_exact_solution(mesh, degree, True), xl, xr, yb, yt) for jj in range(4): if jj != ii: boundary_conditions[jj] = [ 'dirichlet', boundary_conditions[jj][1], 0 ] sol = run_steady_state_model( function_space, kappa, dla.Constant(0.0), boundary_conditions=boundary_conditions) sols.append(sol) sol = run_steady_state_model(function_space, kappa, get_forcing(kappa, mesh, degree, True), boundary_conditions=None) sols.append(sol) superposition_sol = sols[0] for ii in range(1, len(sols)): superposition_sol += sols[ii] # pp=dl.plot(superposition_sol) #plt.colorbar(pp); plt.show() superposition_sol = dla.project(superposition_sol, function_space) boundary_conditions = get_dirichlet_boundary_conditions_from_expression( get_exact_solution(mesh, degree, True), xl, xr, yb, yt) sol = run_steady_state_model(function_space, kappa, get_forcing(kappa, mesh, degree, True), boundary_conditions=boundary_conditions) # plt.figure() # pp=dl.plot(sol-superposition_sol) #plt.colorbar(pp); plt.show() exact_sol = get_exact_solution(mesh, degree, True) error = dl.errornorm(exact_sol, sol, mesh=mesh) print('Error', error) assert error <= 1e-4 error = dl.errornorm(superposition_sol, sol, mesh=mesh) print('error', error) assert error < 1e-14
def compute_errornorms(v, div_v, p, p_ref): deg = v.ufl_element().degree() v_ref = df.Expression(("0.0", "0.0"), degree=deg + 3) v_errL2 = df.errornorm(v_ref, v, norm_type="L2") v_errH10 = df.errornorm(v_ref, v, norm_type="H10") #div_errL2 = df.assemble(div_v * div_v * df.dx) ** 0.5 div_ref = df.Expression("0.0", degree=deg + 3) div_errL2 = df.errornorm(div_ref, div_v, norm_type="L2") p_errL2 = df.errornorm(p_ref, p, norm_type="L2") return v_errL2, v_errH10, div_errL2, p_errL2
def main(N: int, dt: float, T: float, theta: float) -> Tuple[float, float, float, float]: """Set up solver and return errors and mesh size.""" mesh = UnitSquareMesh(N, N) time = Constant(0.0) ac_str = "(8*pi*pi*lam*sin(t) + (lam + 1)*cos(t))*cos(2*pi*x[0])*cos(2*pi*x[1])/(lam + 1)" stimulus = Expression(ac_str, t=time, lam=Constant(1), degree=3) M_i = Constant(1.0) # Set up solver parameters = BasicMonodomainSolver.default_parameters() parameters["theta"] = theta solver = BasicMonodomainSolver(mesh, time, M_i, I_s=stimulus, parameters=parameters) v_exact = Expression("sin(t)*cos(2*pi*x[0])*cos(2*pi*x[1])", t=T, degree=3) # Define initial conditions v_, v = solver.solution_fields() # Solve solutions = solver.solve(0, T, dt) for interval, fields in solutions: continue # Compute errors v_error = errornorm(v_exact, v, "L2", degree_rise=2) return v_error, mesh.hmin(), dt, T
def test_quadratic_solution(self): dt = 0.01 t = 0 final_time = 2 nx, ny = 2, 2 degree = 2 alpha, beta = 3, 1.2 kappa = dla.Constant(1) mesh = dla.RectangleMesh(dl.Point(0, 0), dl.Point(1, 1), nx, ny) function_space = dl.FunctionSpace(mesh, "Lagrange", degree) boundary_conditions = get_dirichlet_boundary_conditions_from_expression( get_quadratic_exact_solution(alpha, beta, mesh, degree), 0, 1, 0, 1) sol = run_model(function_space, kappa, get_quadratic_solution_forcing(alpha, beta, mesh, degree), get_quadratic_exact_solution(alpha, beta, mesh, degree), dt, final_time, boundary_conditions=boundary_conditions) # , # exact_sol=get_quadratic_exact_solution(alpha,beta,mesh,degree)) exact_sol = get_quadratic_exact_solution(alpha, beta, mesh, degree) exact_sol.t = final_time error = dl.errornorm(exact_sol, sol, mesh=mesh) print('Error', error) assert error <= 3e-14
def debug_phi_plot(phi, phia, phih, plotname, compare_historical=False, **plotargs): """ Only used while developing the tests, left here in case more tests are added that need some debug plotting as well """ diff = phia.copy(deepcopy=True) diff.vector().axpy(-1, phih.vector()) diff.vector().apply('insert') na = dolfin.norm(phia) nh = dolfin.norm(phih) nd = dolfin.norm(diff) nd2 = dolfin.errornorm(phi, phih) from matplotlib import pyplot pyplot.figure(figsize=(10, 20)) pyplot.subplot(311) c = dolfin.plot(phia, **plotargs) pyplot.colorbar(c) pyplot.title('Analytical (norm: %g)' % na) pyplot.subplot(312) c = dolfin.plot(phih, **plotargs) pyplot.colorbar(c) pyplot.title('Numerical (norm: %g)' % nh) pyplot.subplot(313) c = dolfin.plot(diff, **plotargs) pyplot.colorbar(c) pyplot.title('Diff (norm: %g, errornorm: %g, rel: %g)' % (nd, nd2, nd2 / na)) pyplot.tight_layout() pyplot.savefig(plotname) pyplot.close() if not compare_historical: return hist_file = plotname + '.npy' comm = phih.function_space().mesh().mpi_comm() mpi_size = dolfin.MPI.size(comm) if mpi_size != 1: return import os arr = phih.vector().get_local() if not os.path.isfile(hist_file): numpy.save(hist_file, arr) return hist = numpy.load(hist_file) print('hist', hist[:5]) print('arr ', arr[:5]) print('diff', (hist - arr)[:5]) print('maxabs', abs(hist - arr).max()) assert abs(hist - arr).max() < 1e-12
def test_cosine_solution_robin_boundary_conditions(self): dt = 0.05 t = 0 final_time = 1 nx, ny = 31, 31 degree = 2 kappa = dla.Constant(3) mesh = dla.RectangleMesh(dl.Point(0, 0), dl.Point(1, 1), nx, ny) function_space = dl.FunctionSpace(mesh, "Lagrange", degree) # bc : kappa * grad u.dot(n)+alpha*u=beta alpha = 1 from functools import partial expression = partial(get_gradu_dot_n, kappa, alpha, mesh, degree) boundary_conditions = get_robin_boundary_conditions_from_expression( expression, dla.Constant(alpha)) sol = run_model(function_space, kappa, get_forcing(kappa, mesh, degree), get_exact_solution(mesh, degree), dt, final_time, boundary_conditions=boundary_conditions, second_order_timestepping=True, exact_sol=None) exact_sol = get_exact_solution(mesh, degree) exact_sol.t = final_time error = dl.errornorm(exact_sol, sol, mesh=mesh) print('Error', error) assert error <= 1e-4
def test_quadratic_diffusion_dirichlet_boundary_conditions(self): """ du/dt = div((1+u**2)*grad(u))+f in the unit square. u = u_D on the boundary. """ nx, ny, degree = 21, 21, 2 mesh = dla.RectangleMesh(dl.Point(0, 0), dl.Point(1, 1), nx, ny) function_space = dl.FunctionSpace(mesh, "Lagrange", degree) bndry_obj = get_2d_unit_square_mesh_boundaries() boundary_conditions = get_dirichlet_boundary_conditions_from_expression( get_quadratic_diffusion_exact_solution(mesh, degree), 0, 1, 0, 1) forcing = get_diffusion_forcing( quadratic_diffusion, get_quadratic_diffusion_exact_solution_sympy, mesh, degree) options = {'time_step': 0.05, 'final_time': 1, 'forcing': forcing, 'boundary_conditions': boundary_conditions, 'second_order_timestepping': True, 'init_condition': get_quadratic_diffusion_exact_solution( mesh, degree), 'nonlinear_diffusion': quadratic_diffusion} sol = run_model(function_space, **options) exact_sol = get_quadratic_diffusion_exact_solution(mesh, degree) exact_sol.t = options['final_time'] error = dl.errornorm(exact_sol, sol, mesh=mesh) print('Abs. Error', error) assert error <= 8e-5
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_constant_diffusion_dirichlet_boundary_conditions(self): kappa = 3 nx, ny, degree = 31, 31, 2 mesh = dla.RectangleMesh(dl.Point(0, 0), dl.Point(1, 1), nx, ny) function_space = dl.FunctionSpace(mesh, "Lagrange", degree) def constant_diffusion(u): return dla.Constant(kappa) boundary_conditions = get_dirichlet_boundary_conditions_from_expression( get_advec_exact_solution(mesh, degree), 0, 1, 0, 1) nlsparam = dict() options = {'time_step': 0.05, 'final_time': 1, 'forcing': get_advec_forcing(kappa, mesh, degree), 'boundary_conditions': boundary_conditions, 'second_order_timestepping': True, 'init_condition': get_advec_exact_solution(mesh, degree), 'nlsparam': nlsparam, 'nonlinear_diffusion': constant_diffusion} sol = run_model(function_space, **options) exact_sol = get_advec_exact_solution(mesh, degree) exact_sol.t = options['final_time'] error = dl.errornorm(exact_sol, sol, mesh=mesh) print('Abs. Error', error) assert error <= 1e-4
def test_dirichlet_boundary(self): frequency=50 omega = 2.*np.pi*frequency c1,c2 = [343.4,6320] gamma=8.4e-4 kappa = omega/c1 Nx, Ny = [21,21] Lx,Ly=[1,1] # create function space mesh = dl.RectangleMesh(dl.Point(0., 0.), dl.Point(Lx, Ly), Nx, Ny) degree=1 P1=dl.FiniteElement('Lagrange',mesh.ufl_cell(),degree) element=dl.MixedElement([P1,P1]) function_space=dl.FunctionSpace(mesh,element) boundary_conditions=None kappa=dl.Constant(kappa) # do not pass element=function_space.ufl_element() # as want forcing to be a scalar pass degree instead forcing=[ Forcing(kappa,'real',degree=function_space.ufl_element().degree()), Forcing(kappa,'imag',degree=function_space.ufl_element().degree())] p=run_model(kappa,forcing,function_space,boundary_conditions) error = dl.errornorm( ExactSolution(kappa,element=function_space.ufl_element()),p) print('Error',error) assert error<=3e-2
def verify_function_slice(func_slice, u, cpp_2d, expected_area): u_2D = func_slice.get_slice(u) # The 2D solution we want to obtain analytical = dolfin.Expression(cpp_2d, degree=2 + 3) comm = dolfin.MPI.comm_world if comm.rank == 0: error = dolfin.errornorm(analytical, u_2D) mesh = func_slice.slice_function_space.mesh() area = dolfin.assemble(1 * dolfin.dx(domain=mesh)) if True: import matplotlib matplotlib.use('Agg') from matplotlib import pyplot fig = pyplot.figure() dolfin.plot(u_2D) pyplot.gca().view_init(90, 270) pyplot.gca().set_proj_type('ortho') pyplot.gca().set_xlabel('x') pyplot.gca().set_ylabel('y') fig.savefig('test_func_slice.png') else: error = 0.0 area = 0.0 assert dolfin.MPI.max(comm, error) < 0.015 area = dolfin.MPI.sum(comm, area) assert abs(area - expected_area) < 1e-8
def test_cosine_solution_dirichlet_boundary_conditions(self): dt = 0.05 t = 0 final_time = 1 nx, ny = 31, 31 degree = 2 kappa = dla.Constant(3) mesh = dla.RectangleMesh(dl.Point(0, 0), dl.Point(1, 1), nx, ny) function_space = dl.FunctionSpace(mesh, "Lagrange", degree) boundary_conditions = get_dirichlet_boundary_conditions_from_expression( get_exact_solution(mesh, degree), 0, 1, 0, 1) sol = run_model(function_space, kappa, get_forcing(kappa, mesh, degree), get_exact_solution(mesh, degree), dt, final_time, boundary_conditions=boundary_conditions, second_order_timestepping=True, exact_sol=None) exact_sol = get_exact_solution(mesh, degree) exact_sol.t = final_time error = dl.errornorm(exact_sol, sol, mesh=mesh) print('Error', error) assert error <= 1e-4
def test_robin_boundary(self): frequency=50 omega = 2.*np.pi*frequency c1,c2 = [343.4,6320] gamma=8.4e-4 kappa = omega/c1 alpha=kappa*gamma Nx, Ny = 21,21; Lx, Ly = 1,1 mesh = dl.RectangleMesh(dl.Point(0., 0.), dl.Point(Lx, Ly), Nx, Ny) degree=1 P1=dl.FiniteElement('Lagrange',mesh.ufl_cell(),degree) element=dl.MixedElement([P1,P1]) function_space=dl.FunctionSpace(mesh,element) boundary_conditions=get_robin_bndry_conditions( kappa,alpha,function_space) kappa=dl.Constant(kappa) forcing=[ Forcing(kappa,'real',degree=function_space.ufl_element().degree()), Forcing(kappa,'imag',degree=function_space.ufl_element().degree())] p=run_model(kappa,forcing,function_space,boundary_conditions) error = dl.errornorm( ExactSolution(kappa,element=function_space.ufl_element()),p,) print('Error',error) assert error<=3e-2
def err_est_fun(mesh_name2, hol_cyl, T_sol1, T_sol2, deg_choice2, hol_cyl2, count_it): ''' Error estimate. ''' #comm1 = MPI.COMM_WORLD #rank1 = comm1.Get_rank() #e1 = sqrt(int_Omega (T - T_ex)**2. dx)/sqrt(int_Omega T**2. dx) #do.assemble yields integration e1 = do.sqrt(do.assemble(pow(T_sol2 - T_sol1, 2.) * do.dx(domain = hol_cyl))) / \ do.sqrt(do.assemble(pow(T_sol1, 2.) * do.dx(domain = hol_cyl))) #sometimes e1 does not work properly (it might be unstable) -> e2 #the degree of piecewise polynomials used to approximate T_th and T... #...will be the degree of T + degree_rise e2 = do.errornorm(T_sol1, T_sol2, norm_type = 'l2', degree_rise = 2, mesh = hol_cyl2) / \ do.sqrt(do.assemble(pow(T_sol1, 2.) * do.dx(domain = hol_cyl))) print 'err: count_t = {}, error_1 = {}, error_2 = {}'.format( count_it, e1, e2) #print 'rank = ', rank1, ', print 'max(T_sol) = ', max(T_sol2.vector().array()) #print 'rank = ', rank1, ', print 'min(T_sol) = ', min(T_sol2.vector().array()), '\n' return e1, e2
def save_pressure(self, is_tent, pressure): super(Problem, self).save_pressure(is_tent, pressure) self.tc.start('computePG') # Report pressure gradient p_in = assemble((1.0/self.area) * pressure * self.dsIn) p_out = assemble((1.0/self.area) * pressure * self.dsOut) computed_gradient = (p_in - p_out)/20.0 # 20.0 is a length of a pipe NT should depend on mesh length (implement through metadata or function of mesh) self.tc.end('computePG') self.tc.start('errorP') error = errornorm(self.sol_p, pressure, norm_type="l2", degree_rise=0) self.listDict['p2' if is_tent else 'p']['list'].append(error) print("Normalized pressure error norm:", error/self.p_normalization_factor[0]) self.listDict['pg2' if is_tent else 'pg']['list'].append(computed_gradient) if not is_tent: self.listDict['apg']['list'].append(self.analytic_gradient) self.listDict['pgE2' if is_tent else 'pgE']['list'].append(computed_gradient-self.analytic_gradient) self.listDict['pgEA2' if is_tent else 'pgEA']['list'].append(abs(computed_gradient-self.analytic_gradient)) self.tc.end('errorP') if self.doSaveDiff: sol_pg_expr = Expression(("0", "0", "pg"), pg=self.analytic_gradient / self.pg_normalization_factor[0]) # sol_pg = interpolate(sol_pg_expr, self.pgSpace) # plot(sol_p, title="sol") # plot(pressure, title="p") # plot(pressure - sol_p, interactive=True, title="diff") # exit() self.pFunction.assign(pressure-self.sol_p) self.fileDict['p2D' if is_tent else 'pD']['file'] << self.pFunction
def save_pressure(self, is_tent, pressure): super(Problem, self).save_pressure(is_tent, pressure) self.tc.start('computePG') # Report pressure gradient p_in = assemble((1.0 / self.area) * pressure * self.dsIn) p_out = assemble((1.0 / self.area) * pressure * self.dsOut) computed_gradient = (p_in - p_out) / 20.0 # 20.0 is a length of a pipe NT should depend on mesh length (implement through metadata or function of mesh) self.tc.end('computePG') self.tc.start('errorP') error = errornorm(self.sol_p, pressure, norm_type="l2", degree_rise=0) self.listDict['p2' if is_tent else 'p']['list'].append(error) print("Normalized pressure error norm:", error / self.p_normalization_factor[0]) self.listDict['pg2' if is_tent else 'pg']['list'].append( computed_gradient) if not is_tent: self.listDict['apg']['list'].append(self.analytic_gradient) self.listDict['pgE2' if is_tent else 'pgE']['list'].append( computed_gradient - self.analytic_gradient) self.listDict['pgEA2' if is_tent else 'pgEA']['list'].append( abs(computed_gradient - self.analytic_gradient)) self.tc.end('errorP') if self.doSaveDiff: sol_pg_expr = Expression( ("0", "0", "pg"), pg=self.analytic_gradient / self.pg_normalization_factor[0]) # sol_pg = interpolate(sol_pg_expr, self.pgSpace) # plot(sol_p, title="sol") # plot(pressure, title="p") # plot(pressure - sol_p, interactive=True, title="diff") # exit() self.pFunction.assign(pressure - self.sol_p) self.fileDict['p2D' if is_tent else 'pD']['file'] << self.pFunction
def main(solver, N: int, dt: float, T: float, theta: float) -> Tuple[float, float, float, float]: """Run monodomain MMS.""" mesh = UnitSquareMesh(N, N) time = Constant(0.0) lam = Constant(1.0) cell_model = NoCellModel() ac_str = "(8*pi*pi*lam*sin(t) + (lam + 1)*cos(t))*cos(2*pi*x[0])*cos(2*pi*x[1])/(lam + 1)" stimulus = Expression(ac_str, t=time, lam=lam, degree=3) parameters = solver.default_parameters() _solver = solver(mesh, time, 1.0, I_s=stimulus, parameters=parameters) vs0 = Function(_solver.V) vs_, vs = _solver.solution_fields() vs_.assign(vs0) for timestep, (v_, v) in _solver.solve(0, T, dt): continue v_exact = Expression( "sin(t)*cos(2*pi*x[0])*cos(2*pi*x[1])", t=T, degree=3 ) # compute errors # v, s = vs.split(deepcopy=True) v_error = errornorm(v_exact, v, "L2", degree_rise=2) return (v_error, mesh.hmin(), dt, T)
def compute_errors(u_e, u): """Compute various measures of the error u - u_e, where u is a finite element Function and u_e is an Expression. Adapted from https://fenicsproject.org/pub/tutorial/html/._ftut1020.html """ print('u_e', u_e.ufl_element().degree()) # Get function space V = u.function_space() # Explicit computation of L2 norm error = (u - u_e)**2 * dl.dx E1 = np.sqrt(abs(dla.assemble(error))) # Explicit interpolation of u_e onto the same space as u u_e_ = dla.interpolate(u_e, V) error = (u - u_e_)**2 * dl.dx E2 = np.sqrt(abs(dla.assemble(error))) # Explicit interpolation of u_e to higher-order elements. # u will also be interpolated to the space Ve before integration Ve = dl.FunctionSpace(V.mesh(), 'P', 5) u_e_ = dla.interpolate(u_e, Ve) error = (u - u_e)**2 * dl.dx E3 = np.sqrt(abs(dla.assemble(error))) # Infinity norm based on nodal values u_e_ = dla.interpolate(u_e, V) E4 = abs(u_e_.vector().get_local() - u.vector().get_local()).max() # L2 norm E5 = dl.errornorm(u_e, u, norm_type='L2', degree_rise=3) # H1 seminorm E6 = dl.errornorm(u_e, u, norm_type='H10', degree_rise=3) # Collect error measures in a dictionary with self-explanatory keys errors = { 'u - u_e': E1, 'u - interpolate(u_e, V)': E2, 'interpolate(u, Ve) - interpolate(u_e, Ve)': E3, 'infinity norm (of dofs)': E4, 'L2 norm': E5, 'H10 seminorm': E6 } return errors
def compvperror(reffemp=None, vref=None, pref=None, curfemp=None, vcur=None, pcur=None): try: verf, perf = dts.expand_vp_dolfunc(vc=vref-vcur, pc=pref-pcur, zerodiribcs=True, **reffemp) verr = dolfin.norm(verf) perr = dolfin.norm(perf) # vreff, preff = dts.expand_vp_dolfunc(vc=vref, pc=pref, **reffemp) # vcurf, pcurf = dts.expand_vp_dolfunc(vc=vcur, pc=pcur, **curfemp) # verr = dolfin.norm(vreff - vcurf) # perr = dolfin.norm(preff - pcurf) except ValueError: # obviously not the same FEM spaces vreff, preff = dts.expand_vp_dolfunc(vc=vref, pc=pref, **reffemp) vcurf, pcurf = dts.expand_vp_dolfunc(vc=vcur, pc=pcur, **curfemp) verr = dolfin.errornorm(vreff, vcurf) perr = dolfin.errornorm(preff, pcurf) return verr, perr
def main(N: int, dt: float, T: float, theta: float) -> Tuple[float, float, float, float, float]: """Run bidomain MMA.""" # Create data mesh = UnitSquareMesh(N, N) time = Constant(0.0) ac_str = "cos(t)*cos(2*pi*x[0])*cos(2*pi*x[1]) + 4*pi*pi*cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)" stimulus = Expression(ac_str, t=time, degree=5) M_i = 1. M_e = 1.0 # Set-up solver parameters = BidomainSolver.default_parameters() parameters["theta"] = theta parameters["linear_solver_type"] = "direct" parameters["use_avg_u_constraint"] = True parameters["Chi"] = 1.0 parameters["Cm"] = 1.0 solver = BidomainSolver(mesh, time, M_i, M_e, I_s=stimulus, parameters=parameters) # Define exact solution (Note: v is returned at end of time # interval(s), u is computed at somewhere in the time interval # depending on theta) v_exact = Expression("cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)", t=T, degree=3) u_exact = Expression("-cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)/2.0", t=T - (1. - theta) * dt, degree=3) # Define initial condition(s) v_, vu = solver.solution_fields() # Solve solutions = solver.solve(0, T, dt) for interval, fields in solutions: continue # Compute errors v, u = vu.split(deepcopy=True)[:2] v_error = errornorm(v_exact, v, "L2", degree_rise=2) u_error = errornorm(u_exact, u, "L2", degree_rise=2) return v_error, u_error, mesh.hmin(), dt, T
def _check_space_order(problem, method): mesh_generator, solution, weak_F = problem() # Translate data into FEniCS expressions. fenics_sol = Expression(smp.prining.ccode(solution['value']), degree=solution['degree'], t=0.0 ) # Create initial solution. theta0 = Expression(fenics_sol.cppcode, degree=solution['degree'], t=0.0, cell=triangle ) # Estimate the error component in space. # Leave out too rough discretizations to avoid showing spurious errors. N = [2 ** k for k in range(2, 8)] dt = 1.0e-8 Err = [] H = [] for n in N: mesh = mesh_generator(n) H.append(MPI.max(mesh.hmax())) V = FunctionSpace(mesh, 'CG', 3) # Create boundary conditions. fenics_sol.t = dt #bcs = DirichletBC(V, fenics_sol, 'on_boundary') # Create initial state. theta_approx = method(V, weak_F, theta0, 0.0, dt, bcs=[solution], tol=1.0e-12, verbose=True ) # Compute the error. fenics_sol.t = dt Err.append(errornorm(fenics_sol, theta_approx) / norm(fenics_sol, mesh=mesh) ) print('n: %d error: %e' % (n, Err[-1])) from matplotlib import pyplot as pp # Compare with order 1, 2, 3 curves. for o in [2, 3, 4]: pp.loglog([H[0], H[-1]], [Err[0], Err[0] * (H[-1] / H[0]) ** o], color='0.5' ) # Finally, the actual data. pp.loglog(H, Err, '-o') pp.xlabel('h_max') pp.ylabel('||u-u_h|| / ||u||') pp.show() return
def error_calc(v, v_e, mesh, mesh_name, save_dir='errors.json'): try: with open(save_dir, 'r') as f: errors = json.load(f) except FileNotFoundError: errors = {} new_errors = {} v_e.t = 0.0 v_int = interpolate(v_e, FunctionSpace(mesh, 'CG', 1)) new_errors['Linf'] = norm(v.vector() - v_int.vector(), 'linf') new_errors['L2'] = errornorm(v_e, v, mesh=mesh, degree_rise=3) new_errors['H1'] = errornorm(v_e, v, norm_type='H1', mesh=mesh, degree_rise=3) errors[mesh_name] = new_errors with open(save_dir, 'w') as f: json.dump(errors, f)
def _compute_errors(problem, mesh_sizes): mesh_generator, solution, f, cell_type = problem() max_degree = 20 if solution['degree'] > max_degree: warnings.warn(('Expression degree (%r) > maximum degree (%d). ' 'Truncating.') % (solution['degree'], max_degree) ) degree = 20 else: degree = solution['degree'] sol = Expression((smp.printing.ccode(solution['value'][0]), smp.printing.ccode(solution['value'][1])), t=0.0, degree=degree, cell=cell_type ) errors = numpy.empty(len(mesh_sizes)) hmax = numpy.empty(len(mesh_sizes)) for k, mesh_size in enumerate(mesh_sizes): mesh, dx, ds = mesh_generator(mesh_size) hmax[k] = MPI.max(mpi_comm_world(), mesh.hmax()) V = FunctionSpace(mesh, 'CG', 1) # TODO don't hardcode Mu, Sigma, ... phi_approx = mcyl.solve_maxwell(V, dx, Mu={0: 1.0}, Sigma={0: 1.0}, omega=1.0, f_list=[{0: f['value']}], convections={}, tol=1.0e-12, bcs=None, compute_residuals=False, verbose=False ) #plot(sol0, mesh=mesh, title='sol') #plot(phi_approx[0][0], title='approx') ##plot(fenics_sol - theta_approx, title='diff') #interactive() #exit() # errors[k] = errornorm(sol, phi_approx[0]) # Compute the numerical order of convergence. order = numpy.empty(len(errors) - 1) for i in range(len(errors) - 1): order[i] = numpy.log(errors[i + 1] / errors[i]) \ / numpy.log(hmax[i + 1] / hmax[i]) return errors, order, hmax
def _check_spatial_order(problem, method): mesh_generator, solution, weak_F = problem() # Translate data into FEniCS expressions. fenics_sol = Expression(sympy.printing.ccode(solution['value']), degree=solution['degree'], t=0.0) # Create initial solution. theta0 = Expression(fenics_sol.cppcode, degree=solution['degree'], t=0.0, cell=triangle) # Estimate the error component in space. # Leave out too rough discretizations to avoid showing spurious errors. N = [2**k for k in range(2, 8)] dt = 1.0e-8 Err = [] H = [] for n in N: mesh = mesh_generator(n) H.append(MPI.max(mesh.hmax())) V = FunctionSpace(mesh, 'CG', 5) # Create boundary conditions. fenics_sol.t = dt # bcs = DirichletBC(V, fenics_sol, 'on_boundary') # Create initial state. theta_approx = method(V, weak_F, theta0, 0.0, dt, bcs=[solution], tol=1.0e-12, verbose=True) # Compute the error. fenics_sol.t = dt Err.append( errornorm(fenics_sol, theta_approx) / norm(fenics_sol, mesh=mesh)) print('n: %d error: %e' % (n, Err[-1])) # Plot order curves for comparison. for order in [2, 3, 4]: plt.loglog([H[0], H[-1]], [Err[0], Err[0] * (H[-1] / H[0])**order], color='0.5') # Finally, the actual data. plt.loglog(H, Err, '-o') plt.xlabel('h_max') plt.ylabel('||u-u_h|| / ||u||') plt.show() return
def _compute_time_errors(problem, method, mesh_sizes, Dt, plot_error=False): mesh_generator, solution, ProblemClass, cell_type = problem() # Translate data into FEniCS expressions. fenics_sol = Expression(smp.printing.ccode(solution['value']), degree=solution['degree'], t=0.0, cell=cell_type ) # Compute the problem errors = {'theta': numpy.empty((len(mesh_sizes), len(Dt)))} # Create initial state. # Deepcopy the expression into theta0. Specify the cell to allow for # more involved operations with it (e.g., grad()). theta0 = Expression(fenics_sol.cppcode, degree=solution['degree'], t=0.0, cell=cell_type ) for k, mesh_size in enumerate(mesh_sizes): mesh = mesh_generator(mesh_size) V = FunctionSpace(mesh, 'CG', 1) theta_approx = Function(V) theta0p = project(theta0, V) stepper = method(ProblemClass(V)) if plot_error: error = Function(V) for j, dt in enumerate(Dt): # TODO We are facing a little bit of a problem here, being the # fact that the time stepper only accept elements from V as u0. # In principle, though, this isn't necessary or required. We # could allow for arbitrary expressions here, but then the API # would need changing for problem.lhs(t, u). # Think about this. stepper.step(theta_approx, theta0p, 0.0, dt, tol=1.0e-12, verbose=False ) fenics_sol.t = dt # # NOTE # When using errornorm(), it is quite likely to see a good part # of the error being due to the spatial discretization. Some # analyses "get rid" of this effect by (sometimes implicitly) # projecting the exact solution onto the discrete function # space. errors['theta'][k][j] = errornorm(fenics_sol, theta_approx) if plot_error: error.assign(project(fenics_sol - theta_approx, V)) plot(error, title='error (dt=%e)' % dt) interactive() return errors, stepper.name, stepper.order
def end_hook(x_, t, field_to_subspace, concentration_init, concentration_init_dev, surface_tension, interface_thickness, pf_init, pf_mobility_coeff, solutes, density, permittivity, viscosity, enable_NS, enable_PF, enable_EC, testing, **namespace): if testing: exprs = reference(**vars()) output = "Final error norms:" for field in ["u", "phi", "c_p", "c_m", "V"]: f = df.project(x_[field], field_to_subspace[field].collapse()) f_ref = exprs[field] output += " {} = {:e}".format(field, df.errornorm(f_ref, f, "L2")) info(output)
def ErrorCalculation(exact_sol,numerical_sol): #interpolate on the mesh es = df.interpolate(exact_sol,my_function_space_cls.V.sub(0).collapse()) ns = df.interpolate(numerical_sol,my_function_space_cls.V.sub(0).collapse()) #compute values at the vertex err_linf = np.max(np.abs(es.compute_vertex_values()- ns.compute_vertex_values())) #err_l2 = np.linalg.norm(es.compute_vertex_values()-ns.compute_vertex_values()) err_l2 = df.errornorm(es,ns,"L2")#fenics inbuilt norm calculator max_l2= np.linalg.norm(es.compute_vertex_values()) max_linf = np.max(np.abs(es.compute_vertex_values())) or 1 normalised_err_l2= err_l2/max_linf normalised_err_linf = err_linf/max_linf return normalised_err_l2, normalised_err_linf
def main(solver, N: int, dt: float, T: float, theta: float) -> Tuple[float, float, float, float, float]: # Create cardiac model mesh = UnitSquareMesh(N, N) time = Constant(0.0) cell_model = NoCellModel() ac_str = "cos(t)*cos(2*pi*x[0])*cos(2*pi*x[1]) + 4*pow(pi, 2)*cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)" stimulus = Expression(ac_str, t=time, degree=5) ps = solver.default_parameters() ps["Chi"] = 1.0 ps["Cm"] = 1.0 _solver = solver(mesh, time, 1.0, 1.0, stimulus, parameters=ps) # Define exact solution (Note: v is returned at end of time # interval(s), u is computed at somewhere in the time interval # depending on theta) v_exact = Expression("cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)", t=T, degree=5) u_exact = Expression("-cos(2*pi*x[0])*cos(2*pi*x[1])*sin(t)/2.0", t=T - (1 - theta) * dt, degree=5) # Define initial condition(s) vs0 = Function(_solver.V) vs_, *_ = _solver.solution_fields() vs_.assign(vs0) # Solve for _, (vs_, vur) in _solver.solve(0, T, dt): continue # Compute errors v, u, *_ = vur.split(deepcopy=True) v_error = errornorm(v_exact, v, "L2", degree_rise=5) u_error = errornorm(u_exact, u, "L2", degree_rise=5) return v_error, u_error, mesh.hmin(), dt, T
def _compute_errors(problem, mesh_sizes): mesh_generator, solution, f, cell_type = problem() if solution["degree"] > MAX_DEGREE: warnings.warn( "Expression degree ({}) > maximum degree ({}). Truncating.".format( solution["degree"], MAX_DEGREE)) degree = MAX_DEGREE else: degree = solution["degree"] sol = Expression( (helpers.ccode( solution["value"][0]), helpers.ccode(solution["value"][1])), t=0.0, degree=degree, cell=cell_type, ) errors = numpy.empty(len(mesh_sizes)) hmax = numpy.empty(len(mesh_sizes)) for k, mesh_size in enumerate(mesh_sizes): mesh, dx, _ = mesh_generator(mesh_size) hmax[k] = MPI.max(mpi_comm_world(), mesh.hmax()) V = FunctionSpace(mesh, "CG", 1) # TODO don't hardcode Mu, Sigma, ... phi_approx = maxwell.solve( V, dx, Mu={0: 1.0}, Sigma={0: 1.0}, omega=1.0, f_list=[{ 0: f["value"] }], f_degree=f["degree"], convections={}, tol=1.0e-12, bcs=None, verbose=False, ) # plot(sol0, mesh=mesh, title='sol') # plot(phi_approx[0][0], title='approx') # #plot(fenics_sol - theta_approx, title='diff') # interactive() # exit() # errors[k] = errornorm(sol, phi_approx[0]) return errors, hmax
def test_unconstrained_newton_solver(self): L, nelem = 1, 201 mesh = dl.IntervalMesh(nelem, -L, L) Vh = dl.FunctionSpace(mesh, "CG", 2) forcing = dl.Constant(1) dirichlet_bcs = [dl.DirichletBC(Vh, dl.Constant(0.0), on_any_boundary)] bc0 = dl.DirichletBC(Vh, dl.Constant(0.0), on_any_boundary) uh = dl.TrialFunction(Vh) vh = dl.TestFunction(Vh) F = dl.inner((1 + uh**2) * dl.grad(uh), dl.grad(vh)) * dl.dx - forcing * vh * dl.dx u = dl.Function(Vh) F = dl.action(F, u) parameters = { "symmetric": True, "newton_solver": { # "relative_tolerance": 1e-8, "report": True, "linear_solver": "cg", "preconditioner": "petsc_amg" } } dl.solve(F == 0, u, dirichlet_bcs, solver_parameters=parameters) # dl.plot(uh) # plt.show() u_newton = dl.Function(Vh) F = dl.inner((1 + uh**2) * dl.grad(uh), dl.grad(vh)) * dl.dx - forcing * vh * dl.dx F = dl.action(F, u_newton) # Compute Jacobian J = dl.derivative(F, u_newton, uh) unconstrained_newton_solve( F, J, u_newton, dirichlet_bcs=dirichlet_bcs, bc0=bc0, # linear_solver='PETScLU',opts=dict()) linear_solver=None, opts=dict()) error = dl.errornorm(u, u_newton, mesh=mesh) assert error < 1e-15
def save_pressure(self, is_tent, pressure): super(Problem, self).save_pressure(is_tent, pressure) self.tc.start('computePG') # Report pressure gradient p_in = assemble((1.0/self.area) * pressure * self.dsIn) p_out = assemble((1.0/self.area) * pressure * self.dsOut) computed_gradient = (p_out - p_in)/20.0 # 20.0 is a length of a pipe NT should depend on mesh length (implement throuhg metadata or function of mesh) self.tc.end('computePG') self.tc.start('analyticP') analytic_gradient = womersleyBC.analytic_pressure_grad(self.factor, self.actual_time) analytic_pressure = womersleyBC.analytic_pressure(self.factor, self.actual_time) self.sol_p = interpolate(analytic_pressure, self.pSpace) # NT move to update_time if not is_tent: self.last_analytic_pressure_norm = norm(self.sol_p, norm_type='L2') self.listDict['ap_norm']['list'].append(self.last_analytic_pressure_norm) self.tc.end('analyticP') self.tc.start('errorP') error = errornorm(self.sol_p, pressure, norm_type="l2", degree_rise=0) self.listDict['p2' if is_tent else 'p']['list'].append(error) print("Normalized pressure error norm:", error/self.p_normalization_factor[0]) self.listDict['pg2' if is_tent else 'pg']['list'].append(computed_gradient) if not is_tent: self.listDict['apg']['list'].append(analytic_gradient) self.listDict['pgE2' if is_tent else 'pgE']['list'].append(computed_gradient-analytic_gradient) self.listDict['pgEA2' if is_tent else 'pgEA']['list'].append(abs(computed_gradient-analytic_gradient)) if self.isWholeSecond: for key in (['pgE2', 'p2'] if is_tent else ['pgE', 'p']): self.listDict[key]['slist'].append( sqrt(sum([i*i for i in self.listDict[key]['list'][self.N0:self.N1]])/self.stepsInSecond)) self.tc.end('errorP') if self.doSaveDiff: sol_pg_expr = Expression(("0", "0", "pg"), pg=analytic_gradient / self.pg_normalization_factor[0]) # sol_pg = interpolate(sol_pg_expr, self.pgSpace) # plot(sol_p, title="sol") # plot(pressure, title="p") # plot(pressure - sol_p, interactive=True, title="diff") # exit() self.pFunction.assign(pressure-self.sol_p) self.fileDict['p2D' if is_tent else 'pD']['file'] << self.pFunction
def test_outopa_workingconfig(self): """ The innerproducts that assemble the output operator are accurately sampled for this parameter set (NV=25, NY=5)""" NV = 25 NY = 5 mesh = dolfin.UnitSquareMesh(NV, NV) V = dolfin.VectorFunctionSpace(mesh, "CG", 2) exv = dolfin.Expression(('1', '1')) testv = dolfin.interpolate(exv, V) odcoo = dict(xmin=0.45, xmax=0.55, ymin=0.6, ymax=0.8) # check the C MyC, My = cou.get_mout_opa(odcoo=odcoo, V=V, NY=NY, NV=NV) # signal space ymesh = dolfin.IntervalMesh(NY - 1, odcoo['ymin'], odcoo['ymax']) Y = dolfin.FunctionSpace(ymesh, 'CG', 1) y1 = dolfin.Function(Y) y2 = dolfin.Function(Y) testvi = testv.vector().array() testy = spsla.spsolve(My, MyC * testvi) y1 = dolfin.Expression('1') y1 = dolfin.interpolate(y1, Y) y2 = dolfin.Function(Y) y2.vector().set_local(testy[NY:]) self.assertTrue(dolfin.errornorm(y2, y1) < 1e-14)
def _compute_errors(problem, mesh_sizes, stabilization): mesh_generator, solution, f, cell_type, kappa, rho, cp, conv = problem() if solution["degree"] > MAX_DEGREE: warnings.warn( "Expression degree ({}) > maximum degree ({}). Truncating.".format( solution["degree"], MAX_DEGREE ) ) degree = MAX_DEGREE else: degree = solution["degree"] sol = Expression( helpers.ccode(solution["value"]), t=0.0, degree=degree, cell=cell_type ) errors = numpy.empty(len(mesh_sizes)) hmax = numpy.empty(len(mesh_sizes)) for k, mesh_size in enumerate(mesh_sizes): mesh = mesh_generator(mesh_size) hmax[k] = MPI.max(mpi_comm_world(), mesh.hmax()) Q = FunctionSpace(mesh, "CG", 1) prob = heat.Heat( Q, kappa=kappa, rho=rho, cp=cp, convection=conv, source=f["value"], dirichlet_bcs=[DirichletBC(Q, 0.0, "on_boundary")], stabilization=stabilization, ) phi_approx = prob.solve_stationary() errors[k] = errornorm(sol, phi_approx) return errors, hmax
description['transfer_params'] = tparams # quickly generate block of steps MS = mp.generate_steps(num_procs,sparams,description) # setup parameters "in time" t0 = MS[0].levels[0].prob.t0 dt = 0.5 Tend = 8*dt # get initial values on finest level P = MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend,stats = mp.run_pfasst(MS,u0=uinit,t0=t0,dt=dt,Tend=Tend) # df.plot(uend.values,interactive=True) # compute exact solution and compare uex = P.u_exact(Tend) print('(classical) error at time %s: %s' %(Tend,abs(uex-uend)/abs(uex))) uex = df.Expression('sin(a*x[0]) * cos(t)',a=np.pi,t=Tend) print('(fenics-style) error at time %s: %s' %(Tend,df.errornorm(uex,uend.values))) extract_stats = grep_stats(stats,iter=-1,type='residual') sortedlist_stats = sort_stats(extract_stats,sortby='step') print(extract_stats,sortedlist_stats)
def halfexp_euler_nseind2(Mc, MP, Ac, BTc, Bc, fvbc, fpbc, PrP, TsP, vp_init=None): """halfexplicit euler for the NSE in index 2 formulation """ # # # Basic Eqn: # # 1/dt*M -B.T q+ 1/dt*M*qc - K(qc) + fc # B * pc = g # # Nts, t0, tE, dt, Nv = init_time_stepping(PrP, TsP) tcur = t0 MFac = dt CFac = 1 # /dt # PFac = -1 # -1 for symmetry (if CFac==1) PFacI = -1./dt dtstrdct = dict(prefix=TsP.svdatapath, method=2, N=PrP.N, tolcor=TsP.TolCorB, nu=PrP.nu, Nts=TsP.Nts, tol=TsP.linatol, te=TsP.tE) cdatstr = get_dtstr(t=t0, **dtstrdct) try: np.load(cdatstr + '.npy') print 'loaded data from ', cdatstr, ' ...' except IOError: np.save(cdatstr, vp_init) print 'saving to ', cdatstr, ' ...' v, p = expand_vp_dolfunc(PrP, vp=vp_init, vc=None, pc=None) TsP.UpFiles.u_file << v, tcur TsP.UpFiles.p_file << p, tcur Bcc, BTcc, MPc, fpbcc, vp_init, Npc = pinthep(Bc, BTc, MP, fpbc, vp_init, PrP.Pdof) IterAv = MFac*sps.hstack([1.0/dt*Mc + Ac, PFacI*(-1)*BTcc]) IterAp = CFac*sps.hstack([Bcc, sps.csr_matrix((Npc, Npc))]) IterA = sps.vstack([IterAv, IterAp]) if TsP.linatol == 0: IterAfac = spsla.factorized(IterA) vp_old = vp_init vp_old = np.vstack([vp_init[:Nv], 1./PFacI*vp_init[Nv:]]) vp_oldold = vp_old ContiRes, VelEr, PEr, TolCorL = [], [], [], [] # Mvp = sps.csr_matrix(sps.block_diag((Mc, MPc))) # Mvp = sps.eye(Mc.shape[0] + MPc.shape[0]) # Mvp = None # M matrix for the minres routine # M accounts for the FEM discretization Mcfac = spsla.splu(Mc) MPcfac = spsla.splu(MPc) def _MInv(vp): # v, p = vp[:Nv, ], vp[Nv:, ] # lsv = krypy.linsys.LinearSystem(Mc, v, self_adjoint=True) # lsp = krypy.linsys.LinearSystem(MPc, p, self_adjoint=True) # Mv = (krypy.linsys.Cg(lsv, tol=1e-14)).xk # Mp = (krypy.linsys.Cg(lsp, tol=1e-14)).xk v, p = vp[:Nv, ], vp[Nv:, ] Mv = np.atleast_2d(Mcfac.solve(v.flatten())).T Mp = np.atleast_2d(MPcfac.solve(p.flatten())).T return np.vstack([Mv, Mp]) MInv = spsla.LinearOperator( (Nv + Npc, Nv + Npc), matvec=_MInv, dtype=np.float32) def ind2_ip(vp1, vp2): """ for applying the fem inner product """ v1, v2 = vp1[:Nv, ], vp2[:Nv, ] p1, p2 = vp1[Nv:, ], vp2[Nv:, ] return mass_fem_ip(v1, v2, Mcfac) + mass_fem_ip(p1, p2, MPcfac) inikryupd = TsP.inikryupd iniiterfac = TsP.iniiterfac # the first krylov step needs more maxiter for etap in range(1, TsP.NOutPutPts + 1): for i in range(Nts / TsP.NOutPutPts): cdatstr = get_dtstr(t=tcur+dt, **dtstrdct) try: vp_next = np.load(cdatstr + '.npy') print 'loaded data from ', cdatstr, ' ...' vp_next = np.vstack([vp_next[:Nv], 1./PFacI*vp_next[Nv:]]) vp_oldold = vp_old vp_old = vp_next if tcur == dt+dt: iniiterfac = 1 # fac only in the first Krylov Call except IOError: print 'computing data for ', cdatstr, ' ...' ConV = dts.get_convvec(u0_dolfun=v, V=PrP.V) CurFv = dts.get_curfv(PrP.V, PrP.fv, PrP.invinds, tcur) Iterrhs = np.vstack([MFac*1.0/dt*Mc*vp_old[:Nv, ], np.zeros((Npc, 1))]) +\ np.vstack([MFac*(fvbc + CurFv - ConV[PrP.invinds, ]), CFac*fpbcc]) if TsP.linatol == 0: # ,vp_old,tol=TsP.linatol) vp_new = IterAfac(Iterrhs.flatten()) # vp_new = spsla.spsolve(IterA, Iterrhs) vp_old = np.atleast_2d(vp_new).T TolCor = 0 else: if inikryupd and tcur == t0: print '\n1st step direct solve to initialize krylov\n' vp_new = spsla.spsolve(IterA, Iterrhs) vp_old = np.atleast_2d(vp_new).T TolCor = 0 inikryupd = False # only once !! else: if TsP.TolCorB: NormRhsInd2 = \ np.sqrt(ind2_ip(Iterrhs, Iterrhs))[0][0] TolCor = 1.0 / np.max([NormRhsInd2, 1]) else: TolCor = 1.0 curls = krypy.linsys.LinearSystem(IterA, Iterrhs, M=MInv) tstart = time.time() # extrapolating the initial value upv = (vp_old - vp_oldold) ret = krypy.linsys.\ RestartedGmres(curls, x0=vp_old + upv, tol=TolCor*TsP.linatol, maxiter=iniiterfac*TsP.MaxIter, max_restarts=100) # ret = krypy.linsys.\ # Minres(curls, maxiter=20*TsP.MaxIter, # x0=vp_old + upv, tol=TolCor*TsP.linatol) tend = time.time() vp_oldold = vp_old vp_old = ret.xk print ('Needed {0} of max {4}*{1} iterations: ' + 'final relres = {2}\n TolCor was {3}').\ format(len(ret.resnorms), TsP.MaxIter, ret.resnorms[-1], TolCor, iniiterfac) print 'Elapsed time {0}'.format(tend - tstart) iniiterfac = 1 # fac only in the first Krylov Call np.save(cdatstr, np.vstack([vp_old[:Nv], PFacI*vp_old[Nv:]])) vc = vp_old[:Nv, ] print 'Norm of current v: ', np.linalg.norm(vc) pc = PFacI*vp_old[Nv:, ] v, p = expand_vp_dolfunc(PrP, vp=None, vc=vc, pc=pc) tcur += dt # the errors vCur, pCur = PrP.v, PrP.p try: vCur.t = tcur pCur.t = tcur - dt ContiRes.append(comp_cont_error(v, fpbc, PrP.Q)) VelEr.append(errornorm(vCur, v)) PEr.append(errornorm(pCur, p)) TolCorL.append(TolCor) except AttributeError: ContiRes.append(0) VelEr.append(0) PEr.append(0) TolCorL.append(0) print '%d of %d time steps completed ' % (etap*Nts/TsP.NOutPutPts, Nts) if TsP.ParaviewOutput: TsP.UpFiles.u_file << v, tcur TsP.UpFiles.p_file << p, tcur TsP.Residuals.ContiRes.append(ContiRes) TsP.Residuals.VelEr.append(VelEr) TsP.Residuals.PEr.append(PEr) TsP.TolCor.append(TolCorL) return
def __init__(self): import os from dolfin import Mesh, MeshFunction, SubMesh, SubDomain, \ FacetFunction, DirichletBC, dot, grad, FunctionSpace, \ MixedFunctionSpace, Expression, FacetNormal, pi, Function, \ Constant, TestFunction, MPI, mpi_comm_world, File import numpy import warnings from maelstrom import heat_cylindrical as cyl_heat from maelstrom import materials_database as md GMSH_EPS = 1.0e-15 current_path = os.path.dirname(os.path.realpath(__file__)) base = os.path.join( current_path, '../../meshes/2d/crucible-with-coils' ) self.mesh = Mesh(base + '.xml') self.subdomains = MeshFunction('size_t', self.mesh, base + '_physical_region.xml' ) self.subdomain_materials = { 1: md.get_material('porcelain'), 2: md.get_material('argon'), 3: md.get_material('GaAs (solid)'), 4: md.get_material('GaAs (liquid)'), 27: md.get_material('air') } # coils for k in range(5, 27): self.subdomain_materials[k] = md.get_material('graphite EK90') # Define the subdomains which together form a single coil. self.coil_domains = [ [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [20, 21, 22, 23], [24, 25, 26] ] self.wpi = 4 # http://fenicsproject.org/qa/2026/submesh-workaround-for-parallel-computation submesh_parallel_bug_fixed = False if submesh_parallel_bug_fixed: submesh_workpiece = SubMesh(self.mesh, self.subdomains, self.wpi) else: # To get the mesh in parallel, we need to read it in from a file. # Writing out can only happen in serial mode, though. :/ base = os.path.join(current_path, '../../meshes/2d/crucible-with-coils-submesh' ) filename = base + '.xml' if not os.path.isfile(filename): warnings.warn( 'Submesh file \'%s\' does not exist. Creating... ' % filename ) if MPI.size(mpi_comm_world()) > 1: raise RuntimeError( 'Can only write submesh in serial mode.' ) submesh_workpiece = \ SubMesh(self.mesh, self.subdomains, self.wpi) output_stream = File(filename) output_stream << submesh_workpiece # Read the mesh submesh_workpiece = Mesh(base + '.xml') coords = submesh_workpiece.coordinates() ymin = min(coords[:, 1]) ymax = max(coords[:, 1]) # Find the top right point. k = numpy.argmax(numpy.sum(coords, 1)) topright = coords[k, :] # Initialize mesh function for boundary domains class Left(SubDomain): def inside(self, x, on_boundary): # Explicitly exclude the lowest and the highest point of the # symmetry axis. # It is necessary for the consistency of the pressure-Poisson # system in the Navier-Stokes solver that the velocity is # exactly 0 at the boundary r>0. Hence, at the corner points # (r=0, melt-crucible, melt-crystal) we must enforce u=0 # already and cannot have a component in z-direction. return on_boundary \ and x[0] < GMSH_EPS \ and x[1] < ymax - GMSH_EPS \ and x[1] > ymin + GMSH_EPS class Crucible(SubDomain): def inside(self, x, on_boundary): return on_boundary \ and ((x[0] > GMSH_EPS and x[1] < ymax - GMSH_EPS) or (x[0] > topright[0] - GMSH_EPS and x[1] > topright[1] - GMSH_EPS) or (x[0] < GMSH_EPS and x[1] < ymin + GMSH_EPS) ) # At the top right part (boundary melt--gas), slip is allowed, so only # n.u=0 is enforced. Very weirdly, the PPE is consistent if and only if # the end points of UpperRight are in UpperRight. This contrasts # Left(), where the end points must NOT belong to Left(). Judging from # the experiments, these settings do the right thing. # TODO try to better understand the PPE system/dolfin's boundary # settings class Upper(SubDomain): def inside(self, x, on_boundary): return on_boundary \ and x[1] > ymax - GMSH_EPS class UpperRight(SubDomain): def inside(self, x, on_boundary): return on_boundary \ and x[1] > ymax - GMSH_EPS \ and x[0] > 0.038 - GMSH_EPS # The crystal boundary is taken to reach up to 0.038 where the # Dirichlet boundary data is about the melting point of the crystal, # 1511K. This setting gives pretty acceptable results when there is no # convection except the one induced by buoyancy. Is there is any more # stirring going on, though, the end point of the crystal with its # fixed temperature of 1511K might be the hottest point globally. This # looks rather unphysical. # TODO check out alternatives class UpperLeft(SubDomain): def inside(self, x, on_boundary): return on_boundary \ and x[1] > ymax - GMSH_EPS \ and x[0] < 0.038 + GMSH_EPS left = Left() crucible = Crucible() upper_left = UpperLeft() upper_right = UpperRight() self.wp_boundaries = FacetFunction('size_t', submesh_workpiece) self.wp_boundaries.set_all(0) left.mark(self.wp_boundaries, 1) crucible.mark(self.wp_boundaries, 2) upper_right.mark(self.wp_boundaries, 3) upper_left.mark(self.wp_boundaries, 4) if DEBUG: from dolfin import plot, interactive plot(self.wp_boundaries, title='Boundaries') interactive() submesh_boundary_indices = { 'left': 1, 'crucible': 2, 'upper right': 3, 'upper left': 4 } # Boundary conditions for the velocity. # # [1] Incompressible flow and the finite element method; volume two; # Isothermal Laminar Flow; # P.M. Gresho, R.L. Sani; # # For the choice of function space, [1] says: # "In 2D, the triangular elements P_2^+P_1 and P_2^+P_{-1} are very # good [...]. [...] If you wish to avoid bubble functions on # triangular elements, P_2P_1 is not bad, and P_2(P_1+P_0) is even # better [...]." # # It turns out that adding the bubble space significantly hampers the # convergence of the Stokes solver and also considerably increases the # time it takes to construct the Jacobian matrix of the Navier--Stokes # problem if no optimization is applied. V = FunctionSpace(submesh_workpiece, 'CG', 2) with_bubbles = False if with_bubbles: V += FunctionSpace(submesh_workpiece, 'B', 3) self.W = MixedFunctionSpace([V, V, V]) self.u_bcs = [ DirichletBC(self.W, Expression( ('0.0', '0.0', '-2*pi*x[0] * 5.0/60.0'), degree=1 ), #(0.0, 0.0, 0.0), crucible), DirichletBC(self.W.sub(0), 0.0, left), DirichletBC(self.W.sub(2), 0.0, left), # Make sure that u[2] is 0 at r=0. DirichletBC(self.W, Expression( ('0.0', '0.0', '2*pi*x[0] * 5.0/60.0'), degree=1 ), upper_left), DirichletBC(self.W.sub(1), 0.0, upper_right), ] self.p_bcs = [] self.P = FunctionSpace(submesh_workpiece, 'CG', 1) # Boundary conditions for heat equation. self.Q = FunctionSpace(submesh_workpiece, 'CG', 2) # Dirichlet. # This is a bit of a tough call since the boundary conditions need to # be read from a Tecplot file here. import tecplot_reader filename = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'data/crucible-boundary.dat' ) data = tecplot_reader.read(filename) RZ = numpy.c_[data['ZONE T']['node data']['r'], data['ZONE T']['node data']['z'] ] T_vals = data['ZONE T']['node data']['temp. [K]'] class TecplotDirichletBC(Expression): # TODO specify degree def eval(self, value, x): # Find on which edge x sits, and raise exception if it doesn't. edge_found = False for edge in data['ZONE T']['element data']: # Given a point X and an edge X0--X1, # # (1 - theta) X0 + theta X1, # # the minimum distance is assumed for # # argmin_theta ||(1-theta) X0 + theta X1 - X||^2 # = <X1 - X0, X - X0> / ||X1 - X0||^2. # # If the distance is 0 and 0<=theta<=1, we found the edge. # # Note that edges are 1-based in Tecplot. X0 = RZ[edge[0] - 1] X1 = RZ[edge[1] - 1] theta = numpy.dot(X1-X0, x-X0) / numpy.dot(X1-X0, X1-X0) diff = (1.0-theta)*X0 + theta*X1 - x if numpy.dot(diff, diff) < 1.0e-10 and \ 0.0 <= theta and theta <= 1.0: # Linear interpolation of the temperature value. value[0] = (1.0-theta) * T_vals[edge[0]-1] \ + theta * T_vals[edge[1]-1] edge_found = True break # This class is supposed to be used for Dirichlet boundary # conditions. For some reason, FEniCS also evaluates # DirichletBC objects at coordinates which do not sit on the # boundary, see # <http://fenicsproject.org/qa/1033/dirichletbc-expressions-evaluated-away-from-the-boundary>. # The assigned values have no meaning though, so not assigning # values[0] here is okay. # #from matplotlib import pyplot as pp #pp.plot(x[0], x[1], 'xg') if not edge_found: value[0] = 0.0 warnings.warn('Coordinate (%e, %e) doesn\'t sit on edge.' % (x[0], x[1])) #pp.plot(RZ[:, 0], RZ[:, 1], '.k') #pp.plot(x[0], x[1], 'xr') #pp.show() #raise RuntimeError('Input coordinate ' # '%r is not on boundary.' % x) return tecplot_dbc = TecplotDirichletBC() self.theta_bcs_d = [ DirichletBC(self.Q, tecplot_dbc, upper_left) ] theta_bcs_d_strict = [ DirichletBC(self.Q, tecplot_dbc, upper_right), DirichletBC(self.Q, tecplot_dbc, crucible), DirichletBC(self.Q, tecplot_dbc, upper_left) ] # Neumann dTdr_vals = data['ZONE T']['node data']['dTempdx [K/m]'] dTdz_vals = data['ZONE T']['node data']['dTempdz [K/m]'] class TecplotNeumannBC(Expression): # TODO specify degree def eval(self, value, x): # Same problem as above: This expression is not only evaluated # at boundaries. for edge in data['ZONE T']['element data']: X0 = RZ[edge[0] - 1] X1 = RZ[edge[1] - 1] theta = numpy.dot(X1-X0, x-X0) / numpy.dot(X1-X0, X1-X0) dist = numpy.linalg.norm((1-theta)*X0 + theta*X1 - x) if dist < 1.0e-5 and 0.0 <= theta and theta <= 1.0: value[0] = (1-theta) * dTdr_vals[edge[0]-1] \ + theta * dTdr_vals[edge[1]-1] value[1] = (1-theta) * dTdz_vals[edge[0]-1] \ + theta * dTdz_vals[edge[1]-1] break return def value_shape(self): return (2,) tecplot_nbc = TecplotNeumannBC() n = FacetNormal(self.Q.mesh()) self.theta_bcs_n = { submesh_boundary_indices['upper right']: dot(n, tecplot_nbc), submesh_boundary_indices['crucible']: dot(n, tecplot_nbc) } self.theta_bcs_r = {} # It seems that the boundary conditions from above are inconsistent in # that solving with Dirichlet overall and mixed Dirichlet-Neumann give # different results; the value *cannot* correspond to one solution. # From looking at the solutions, the pure Dirichlet setting appears # correct, so extract the Neumann values directly from that solution. zeta = TestFunction(self.Q) theta_reference = Function(self.Q, name='temperature (Dirichlet)') theta_reference.vector()[:] = 0.0 # Solve the *quasilinear* PDE (coefficients may depend on theta). # This is to avoid setting a fixed temperature for the coefficients. # Get material parameters wp_material = self.subdomain_materials[self.wpi] if isinstance(wp_material.specific_heat_capacity, float): cp = wp_material.specific_heat_capacity else: cp = wp_material.specific_heat_capacity(theta_reference) if isinstance(wp_material.density, float): rho = wp_material.density else: rho = wp_material.density(theta_reference) if isinstance(wp_material.thermal_conductivity, float): k = wp_material.thermal_conductivity else: k = wp_material.thermal_conductivity(theta_reference) reference_problem = cyl_heat.HeatCylindrical( self.Q, theta_reference, zeta, b=Constant((0.0, 0.0, 0.0)), kappa=k, rho=rho, cp=cp, source=Constant(0.0), dirichlet_bcs=theta_bcs_d_strict ) from dolfin import solve solve(reference_problem.F0 == 0, theta_reference, bcs=theta_bcs_d_strict ) # Create equivalent boundary conditions from theta_reference. This # makes sure that the potentially expensive Expression evaluation in # theta_bcs_* is replaced by something reasonably cheap. for k, bc in enumerate(self.theta_bcs_d): self.theta_bcs_d[k] = DirichletBC(bc.function_space(), theta_reference, bc.domain_args[0] ) # Adapt Neumann conditions. n = FacetNormal(self.Q.mesh()) for k in self.theta_bcs_n: self.theta_bcs_n[k] = dot(n, grad(theta_reference)) if DEBUG: # Solve the heat equation with the mixed Dirichlet-Neumann # boundary conditions and compare it to the Dirichlet-only # solution. theta_new = Function( self.Q, name='temperature (Neumann + Dirichlet)' ) from dolfin import Measure ds_workpiece = Measure('ds')[self.wp_boundaries] problem_new = cyl_heat.HeatCylindrical( self.Q, theta_new, zeta, b=Constant((0.0, 0.0, 0.0)), kappa=k, rho=rho, cp=cp, source=Constant(0.0), dirichlet_bcs=self.theta_bcs_d, neumann_bcs=self.theta_bcs_n, ds=ds_workpiece ) from dolfin import solve solve(problem_new.F0 == 0, theta_new, bcs=problem_new.dirichlet_bcs ) from dolfin import plot, interactive, errornorm print('||theta_new - theta_ref|| = %e' % errornorm(theta_new, theta_reference) ) plot(theta_reference) plot(theta_new) plot( theta_reference - theta_new, title='theta_ref - theta_new' ) interactive() #omega = 2 * pi * 10.0e3 self.omega = 2 * pi * 300.0 return
def teXXXst_fenics_vector(): # quad_degree = 13 # dolfin.parameters["form_compiler"]["quadrature_degree"] = quad_degree pi = 3.14159265358979323 k1, k2 = 2, 3 EV = pi * pi * (k1 * k1 + k2 * k2) N = 11 degree = 1 mesh = UnitSquare(N, N) fs = FunctionSpace(mesh, "CG", degree) ex = Expression("A*sin(k1*pi*x[0])*sin(k2*pi*x[1])", k1=k1, k2=k2, A=1.0) x = FEniCSVector(interpolate(ex, fs)) # print "x.coeff", x.coeffs.array() ex.A = EV b_ex = assemble_rhs(ex, fs) bexg = interpolate(ex, fs) # print b_ex.array() # print b_ex.array() / (2 * pi * pi * x.coeffs.array()) Afe = assemble_lhs(Expression('1'), fs) # apply discrete operator on (interpolated) x A = FEniCSOperator(Afe, x.basis) b = A * x # evaluate solution for eigenfunction rhs if False: b_num = Function(fs) solve(A, b_num.vector(), b_ex) bnv = A * b_num.vector() b3 = Function(fs, bnv / EV) np.set_printoptions(threshold='nan', suppress=True) print b.coeffs.array() print np.abs((b_ex.array() - b.coeffs.array()) / np.max(b_ex.array())) print np.max(np.abs((b_ex.array() - b.coeffs.array()) / np.max(b_ex.array()))) #print b_ex.array() / (M * interpolate(ex1, fs).vector()).array() # #assert_array_almost_equal(b.coeffs, b_ex.coeffs) b2 = Function(fs, b_ex.copy()) bg = Function(fs, b_ex.copy()) b2g = Function(fs, b_ex.copy()) G = assemble_gramian(x.basis) dolfin.solve(G, bg.vector(), b.coeffs) dolfin.solve(G, b2g.vector(), b2.vector()) # # compute eigenpairs numerically # eigensolver = evaluate_evp(FEniCSBasis(fs)) # # Extract largest (first) eigenpair # r, c, rx, cx = eigensolver.get_eigenpair(0) # print "Largest eigenvalue: ", r # # Initialize function and assign eigenvector # ef0 = Function(fs) # ef0.vector()[:] = rx if False: # export out_b = dolfin.File(__name__ + "_b.pvd", "compressed") out_b << b._fefunc out_b_ex = dolfin.File(__name__ + "_b_ex.pvd", "compressed") out_b_ex << b2 out_b_num = dolfin.File(__name__ + "_b_num.pvd", "compressed") out_b_num << b_num #dolfin.plot(x._fefunc, title="interpolant x", rescale=False, axes=True, legend=True) dolfin.plot(bg, title="b", rescale=False, axes=True, legend=True) dolfin.plot(b2g, title="b_ex (ass/G)", rescale=False, axes=True, legend=True) dolfin.plot(bexg, title="b_ex (dir)", rescale=False, axes=True, legend=True) #dolfin.plot(b_num, title="b_num", rescale=False, axes=True, legend=True) # dolfin.plot(b3, title="M*b_num", rescale=False, axes=True, legend=True) #dolfin.plot(ef0, title="ef0", rescale=False, axes=True, legend=True) print dolfin.errornorm(u=b._fefunc, uh=b2) #, norm_type, degree, mesh) dolfin.interactive()
def compute_time_errors(problem, MethodClass, mesh_sizes, Dt): mesh_generator, solution, f, mu, rho, cell_type = problem() # Compute the problem errors = { "u": numpy.empty((len(mesh_sizes), len(Dt))), "p": numpy.empty((len(mesh_sizes), len(Dt))), } for k, mesh_size in enumerate(mesh_sizes): info("") info("") with Message("Computing for mesh size {}...".format(mesh_size)): mesh = mesh_generator(mesh_size) # Define all expression with `domain`, see # <https://bitbucket.org/fenics-project/ufl/issues/96>. # # Translate data into FEniCS expressions. sol_u = Expression( (ccode(solution["u"]["value"][0]), ccode(solution["u"]["value"][1])), degree=_truncate_degree(solution["u"]["degree"]), t=0.0, domain=mesh, ) sol_p = Expression( ccode(solution["p"]["value"]), degree=_truncate_degree(solution["p"]["degree"]), t=0.0, domain=mesh, ) fenics_rhs0 = Expression( (ccode(f["value"][0]), ccode(f["value"][1])), degree=_truncate_degree(f["degree"]), t=0.0, mu=mu, rho=rho, domain=mesh, ) # Deep-copy expression to be able to provide f0, f1 for the # Dirichlet boundary conditions later on. fenics_rhs1 = Expression( fenics_rhs0.cppcode, degree=_truncate_degree(f["degree"]), t=0.0, mu=mu, rho=rho, domain=mesh, ) # Create initial states. W = VectorFunctionSpace(mesh, "CG", 2) P = FunctionSpace(mesh, "CG", 1) p0 = Expression( sol_p.cppcode, degree=_truncate_degree(solution["p"]["degree"]), t=0.0, domain=mesh, ) mesh_area = assemble(1.0 * dx(mesh)) method = MethodClass( time_step_method="backward euler", # time_step_method='crank-nicolson', # stabilization=None # stabilization='SUPG' ) u1 = Function(W) p1 = Function(P) err_p = Function(P) divu1 = Function(P) for j, dt in enumerate(Dt): # Prepare previous states for multistepping. u = { 0: Expression( sol_u.cppcode, degree=_truncate_degree(solution["u"]["degree"]), t=0.0, cell=cell_type, ) } sol_u.t = dt u_bcs = [DirichletBC(W, sol_u, "on_boundary")] sol_p.t = dt # p_bcs = [DirichletBC(P, sol_p, 'on_boundary')] p_bcs = [] fenics_rhs0.t = 0.0 fenics_rhs1.t = dt u1, p1 = method.step( Constant(dt), u, p0, W, P, u_bcs, p_bcs, Constant(rho), Constant(mu), f={0: fenics_rhs0, 1: fenics_rhs1}, verbose=False, tol=1.0e-10, ) sol_u.t = dt sol_p.t = dt errors["u"][k][j] = errornorm(sol_u, u1) # The pressure is only determined up to a constant which makes # it a bit harder to define what the error is. For our # purposes, choose an alpha_0\in\R such that # # alpha0 = argmin ||e - alpha||^2 # # with e := sol_p - p. # This alpha0 is unique and explicitly given by # # alpha0 = 1/(2|Omega|) \int (e + e*) # = 1/|Omega| \int Re(e), # # i.e., the mean error in \Omega. alpha = +assemble(sol_p * dx(mesh)) - assemble(p1 * dx(mesh)) alpha /= mesh_area # We would like to perform # p1 += alpha. # To avoid creating a temporary function every time, assume # that p1 lives in a function space where the coefficients # represent actual function values. This is true for CG # elements, for example. In that case, we can just add any # number to the vector of p1. p1.vector()[:] += alpha errors["p"][k][j] = errornorm(sol_p, p1) show_plots = False if show_plots: plot(p1, title="p1", mesh=mesh) plot(sol_p, title="sol_p", mesh=mesh) err_p.vector()[:] = p1.vector() sol_interp = interpolate(sol_p, P) err_p.vector()[:] -= sol_interp.vector() # plot(sol_p - p1, title='p1 - sol_p', mesh=mesh) plot(err_p, title="p1 - sol_p", mesh=mesh) # r = SpatialCoordinate(mesh)[0] # divu1 = 1 / r * (r * u1[0]).dx(0) + u1[1].dx(1) divu1.assign(project(u1[0].dx(0) + u1[1].dx(1), P)) plot(divu1, title="div(u1)") return errors
def compute_time_errors(problem, MethodClass, mesh_sizes, Dt): mesh_generator, solution, f, mu, rho, cell_type = problem() # Translate data into FEniCS expressions. sol_u = Expression((smp.printing.ccode(solution['u']['value'][0]), smp.printing.ccode(solution['u']['value'][1]) ), degree=_truncate_degree(solution['u']['degree']), t=0.0, cell=cell_type ) sol_p = Expression(smp.printing.ccode(solution['p']['value']), degree=_truncate_degree(solution['p']['degree']), t=0.0, cell=cell_type ) fenics_rhs0 = Expression((smp.printing.ccode(f['value'][0]), smp.printing.ccode(f['value'][1]) ), degree=_truncate_degree(f['degree']), t=0.0, mu=mu, rho=rho, cell=cell_type ) # Deep-copy expression to be able to provide f0, f1 for the Dirichlet- # boundary conditions later on. fenics_rhs1 = Expression(fenics_rhs0.cppcode, degree=_truncate_degree(f['degree']), t=0.0, mu=mu, rho=rho, cell=cell_type ) # Create initial states. p0 = Expression( sol_p.cppcode, degree=_truncate_degree(solution['p']['degree']), t=0.0, cell=cell_type ) # Compute the problem errors = {'u': numpy.empty((len(mesh_sizes), len(Dt))), 'p': numpy.empty((len(mesh_sizes), len(Dt))) } for k, mesh_size in enumerate(mesh_sizes): info('') info('') with Message('Computing for mesh size %r...' % mesh_size): mesh = mesh_generator(mesh_size) mesh_area = assemble(1.0 * dx(mesh)) W = VectorFunctionSpace(mesh, 'CG', 2) P = FunctionSpace(mesh, 'CG', 1) method = MethodClass(W, P, rho, mu, theta=1.0, #theta=0.5, stabilization=None #stabilization='SUPG' ) u1 = Function(W) p1 = Function(P) err_p = Function(P) divu1 = Function(P) for j, dt in enumerate(Dt): # Prepare previous states for multistepping. u = [Expression( sol_u.cppcode, degree=_truncate_degree(solution['u']['degree']), t=0.0, cell=cell_type ), # Expression( #sol_u.cppcode, #degree=_truncate_degree(solution['u']['degree']), #t=0.5*dt, #cell=cell_type #) ] sol_u.t = dt u_bcs = [DirichletBC(W, sol_u, 'on_boundary')] sol_p.t = dt #p_bcs = [DirichletBC(P, sol_p, 'on_boundary')] p_bcs = [] fenics_rhs0.t = 0.0 fenics_rhs1.t = dt method.step(dt, u1, p1, u, p0, u_bcs=u_bcs, p_bcs=p_bcs, f0=fenics_rhs0, f1=fenics_rhs1, verbose=False, tol=1.0e-10 ) sol_u.t = dt sol_p.t = dt errors['u'][k][j] = errornorm(sol_u, u1) # The pressure is only determined up to a constant which makes # it a bit harder to define what the error is. For our # purposes, choose an alpha_0\in\R such that # # alpha0 = argmin ||e - alpha||^2 # # with e := sol_p - p. # This alpha0 is unique and explicitly given by # # alpha0 = 1/(2|Omega|) \int (e + e*) # = 1/|Omega| \int Re(e), # # i.e., the mean error in \Omega. alpha = assemble(sol_p * dx(mesh)) \ - assemble(p1 * dx(mesh)) alpha /= mesh_area # We would like to perform # p1 += alpha. # To avoid creating a temporary function every time, assume # that p1 lives in a function space where the coefficients # represent actual function values. This is true for CG # elements, for example. In that case, we can just add any # number to the vector of p1. p1.vector()[:] += alpha errors['p'][k][j] = errornorm(sol_p, p1) show_plots = False if show_plots: plot(p1, title='p1', mesh=mesh) plot(sol_p, title='sol_p', mesh=mesh) err_p.vector()[:] = p1.vector() sol_interp = interpolate(sol_p, P) err_p.vector()[:] -= sol_interp.vector() #plot(sol_p - p1, title='p1 - sol_p', mesh=mesh) plot(err_p, title='p1 - sol_p', mesh=mesh) #r = Expression('x[0]', degree=1, cell=triangle) #divu1 = 1 / r * (r * u1[0]).dx(0) + u1[1].dx(1) divu1.assign(project(u1[0].dx(0) + u1[1].dx(1), P)) plot(divu1, title='div(u1)') interactive() return errors
# Error ['e_(u%d)=%.2E[%.2f]' % (i, e, r) for i, (e, r) in enumerate(zip(error, rate))] + # Unknowns ['#(%d)=%d' % p for p in enumerate(ndofs)] + # Total ['#(all)=%d' % sum(ndofs)] + # Rnorm ['|r|_l2=%g' % r_norm] + ['niters=%d' % niters]) # Screen print GREEN % msg # Log if path: with open(path, 'a') as f: f.write(msg + '\n') error0, mesh_size0 = error, mesh_size memory.append(np.r_[mesh_size, error]) # Two arg norms H1_norm = lambda u, uh, m=None: errornorm(u, uh, 'H1', degree_rise=2, mesh=m) H10_norm = lambda u, uh, m=None: errornorm(u, uh, 'H10', degree_rise=2, mesh=m) L2_norm = lambda u, uh, m=None: errornorm(u, uh, 'L2', degree_rise=2, mesh=m) Hdiv_norm = lambda u, uh, m=None: errornorm(u, uh, 'Hdiv', degree_rise=2, mesh=m) Hdiv0_norm = lambda u, uh, m=None: errornorm(u, uh, 'Hdiv0', degree_rise=2, mesh=m) Hcurl_norm = lambda u, uh, m=None: errornorm(u, uh, 'Hcurl', degree_rise=2, mesh=m) Hcurl0_norm = lambda u, uh, m=None: errornorm(u, uh, 'Hcurl0', degree_rise=2, mesh=m) linf_norm = lambda u, uh: np.linalg.norm(u - uh.vector().get_local())
def halfexp_euler_smarminex(MSme, ASme, BSme, MP, FvbcSme, FpbcSme, B2BoolInv, PrP, TsP, vp_init=None, qqpq_init=None, saveallres=True): """ halfexplicit euler for the NSE in index 1 formulation """ Nts, t0, tE, trange, Nv = init_time_stepping(PrP, TsP) tcur = t0 # remove the p - freedom BSme, BTSme, MPc, FpbcSmeC, vp_init, Npc\ = pinthep(BSme, BSme.T, MP, FpbcSme, vp_init, PrP.Pdof) # split the coeffs B1Sme = BSme[:, :-Npc] B2Sme = BSme[:, -Npc:] M1Sme = MSme[:, :-Npc] M2Sme = MSme[:, -Npc:] A1Sme = ASme[:, :-Npc] A2Sme = ASme[:, -Npc:] # The matrix to be solved in every time step # # 1/dt*M11 M12 -B2' 0 q1 # 1/dt*M21 M22 -B1' 0 tq2 # 1/dt*B1 B2 0 0 * p = rhs # B1 0 0 B2 q2 # # cf. preprint # if A is there - we need to treat it implicitly # # 1/dt*M11+A11 M12 -B2' A12 q1 # 1/dt*M21+A21 M22 -B1' A22 tq2 # 1/dt*B1 B2 0 0 * p = rhs # B1 0 0 B2 q2 # MFac = 1 # Weights for the 'conti' eqns to balance the residuals WC = 0.5 WCD = 0.5 PFac = 1 # dt/WCD PFacI = 1 # WCD/dt # rescale q1 q1facI = 1. DT = (tE-t0)/(trange.size-1) # TODO: non uniform meshes !!! IterA1 = MFac*sps.hstack([q1facI*(1.0/DT*M1Sme + A1Sme), M2Sme, -PFacI*BSme.T, A2Sme]) IterA2 = WCD*sps.hstack([q1facI*(1.0/DT*B1Sme), B2Sme, sps.csr_matrix((Npc, 2*Npc))]) IterA3 = WC*sps.hstack([q1facI*B1Sme, sps.csr_matrix((Npc, 2*Npc)), B2Sme]) IterA = sps.vstack([IterA1, IterA2, IterA3]) if TsP.linatol == 0: IterAfac = spsla.factorized(IterA) # Preconditioning ... # if TsP.SadPtPrec: MLump = np.atleast_2d(MSme.diagonal()).T MLump2 = MLump[-Npc:, ] MLumpI = 1. / MLump # MLumpI1 = MLumpI[:-(Np - 1), ] # MLumpI2 = MLumpI[-(Np - 1):, ] B2SmeTfac = spsla.splu(B2Sme.T) B2Smefac = spsla.splu(B2Sme) def PrecByB2(qqpq): qq = MLumpI*qqpq[:Nv, ] p = qqpq[Nv:-Npc, ] p = B2Smefac.solve(p.flatten()) p = MLump2*np.atleast_2d(p).T # p = spsla.spsolve(B2Sme.T, p) p = B2SmeTfac.solve(p.flatten()) p = np.atleast_2d(p).T q2 = qqpq[-Npc:, ] # q2 = spsla.spsolve(B2Sme, q2) q2 = B2Smefac.solve(q2.flatten()) q2 = np.atleast_2d(q2).T return np.vstack([np.vstack([qq, -p]), q2]) MGmr = spsla.LinearOperator( (Nv + 2*Npc, Nv + 2*Npc), matvec=PrecByB2, dtype=np.float32) TsP.Ml = MGmr Mcfac = spsla.splu(MSme) MPcfac = spsla.splu(MPc) def _MInvInd1(qqpq): qq = qqpq[:Nv, ] p = qqpq[Nv:-Npc, ] q2 = qqpq[-Npc:, ] miqq = np.atleast_2d(Mcfac.solve(qq.flatten())).T mip = np.atleast_2d(MPcfac.solve(p.flatten())).T miq2 = np.atleast_2d(MPcfac.solve(q2.flatten())).T return np.vstack([miqq, mip, miq2]) # MInvInd1 = spsla.LinearOperator((Nv + 2*Npc, Nv + 2*Npc), # matvec=_MInvInd1, dtype=np.float32) def smamin_prec_fem_ip(qqpq1, qqpq2, retparts=False): """ M ip for the preconditioned residuals """ if retparts: return (np.dot(qqpq1[:Nv, ].T.conj(), MSme*qqpq2[:Nv, ]), np.dot(qqpq1[Nv:-Npc, ].T.conj(), MPc*qqpq2[Nv:-Npc, ]), np.dot(qqpq1[-Npc:, ].T.conj(), MPc*qqpq2[-Npc:, ])) else: return np.dot(qqpq1[:Nv, ].T.conj(), MSme*qqpq2[:Nv, ]) + \ np.dot(qqpq1[Nv:-Npc, ].T.conj(), MPc*qqpq2[Nv:-Npc, ]) + \ np.dot(qqpq1[-Npc:, ].T.conj(), MPc*qqpq2[-Npc:, ]) def smamin_fem_ip(qqpq1, qqpq2, Mv, Mp, Nv, Npc, dt=1.): """ M^-1 ip for the extended system """ return mass_fem_ip(qqpq1[:Nv, ], qqpq2[:Nv, ], Mv) + \ dt*mass_fem_ip(qqpq1[Nv:-Npc, ], qqpq2[Nv:-Npc, ], Mp) + \ mass_fem_ip(qqpq1[-Npc:, ], qqpq2[-Npc:, ], Mp) v, p = expand_vp_dolfunc(PrP, vp=vp_init, vc=None, pc=None, pdof=PrP.Pdof) TsP.UpFiles.u_file << v, tcur TsP.UpFiles.p_file << p, tcur dtstrdct = dict(prefix=TsP.svdatapath, method=1, N=PrP.N, tolcor=TsP.TolCorB, nu=PrP.nu, Nts=TsP.Nts, tol=TsP.linatol, te=TsP.tE) cdatstr = get_dtstr(t=t0, **dtstrdct) try: np.load(cdatstr + '.npy') print 'loaded data from ', cdatstr, ' ...' except IOError: np.save(cdatstr, vp_init) print 'saving to ', cdatstr, ' ...' vp_old = np.copy(vp_init) q1_old = 1./q1facI*vp_init[~B2BoolInv, ] q2_old = vp_init[B2BoolInv, ] if qqpq_init is None and TsP.linatol > 0: # initial value for tq2 ConV, CurFv = get_conv_curfv_rearr(v, PrP, tcur, B2BoolInv) tq2_old = spsla.spsolve(M2Sme[-Npc:, :], CurFv[-Npc:, ]) # tq2_old = MLumpI2*CurFv[-(Np-1):,] tq2_old = np.atleast_2d(tq2_old).T # state vector of the smaminex system : [ q1^+, tq2^c, p^c, q2^+] qqpq_old = np.zeros((Nv + 2*Npc, 1)) qqpq_old[:Nv - Npc, ] = q1_old qqpq_old[Nv - Npc:Nv, ] = tq2_old qqpq_old[Nv:Nv + Npc, ] = PFac*vp_old[Nv:, ] qqpq_old[Nv + Npc:, ] = q2_old else: qqpq_old = qqpq_init qqpq_oldold = qqpq_old ContiRes, VelEr, PEr, TolCorL = [], [], [], [] MomRes, DContiRes = [], [] # compute 1st time step by direct solve to initialize the krylov upd scheme inikryupd = TsP.inikryupd iniiterfac = TsP.iniiterfac # the first krylov step needs more maxiter for etap in range(1, TsP.NOutPutPts + 1): for i in range(Nts / TsP.NOutPutPts): idx = (etap-1)*(Nts/TsP.NOutPutPts) + i tnext = trange[idx+1] cdatstr = get_dtstr(t=tnext, **dtstrdct) DT = tnext - tcur try: qqpq_next = np.load(cdatstr + '_qqpq' + '.npy') print 'loaded data from ', cdatstr, ' ...' qqpq_oldold = qqpq_old qqpq_old = qqpq_next TolCor = 'n.a.' if i == 2: iniiterfac = 1 # fac only in the first Krylov Call # Reconstruct data of the iterative solution if TsP.linatol > 0 and (TsP.TolCorB or saveallres): ConV, CurFv = get_conv_curfv_rearr(v, PrP, tcur, B2BoolInv) gdot = np.zeros((Npc, 1)) # TODO: implement \dot g Iterrhs = 1.0 / DT*np.vstack([MFac*M1Sme*q1_old, WCD*B1Sme*q1_old]) +\ np.vstack([MFac*(FvbcSme + CurFv - ConV), WCD*gdot]) Iterrhs = np.vstack([Iterrhs, WC*FpbcSmeC]) if TsP.TolCorB: NormRhsInd1 = np.sqrt( smamin_fem_ip(Iterrhs, Iterrhs, Mcfac, MPcfac, Nv, Npc, dt=np.sqrt(DT)))[0][0] TolCor = 1.0 / np.max([NormRhsInd1, 1]) else: TolCor = 1.0 except IOError: print 'computing data for ', cdatstr, ' ...' # set up right hand side ConV, CurFv = get_conv_curfv_rearr(v, PrP, tcur, B2BoolInv) gdot = np.zeros((Npc, 1)) # TODO: implement \dot g Iterrhs = 1.0 / DT*np.vstack([MFac*M1Sme*q1_old, WCD*B1Sme*q1_old]) +\ np.vstack([MFac*(FvbcSme + CurFv - ConV), WCD*gdot]) Iterrhs = np.vstack([Iterrhs, WC*FpbcSmeC]) if TsP.linatol == 0: # q1_tq2_p_q2_new = spsla.spsolve(IterA, Iterrhs) q1_tq2_p_q2_new = IterAfac(Iterrhs.flatten()) qqpq_old = np.atleast_2d(q1_tq2_p_q2_new).T TolCor = 0 else: # Norm of rhs of index-1 formulation # used to correct the relative residual # such that the absolute residual stays constant if TsP.TolCorB: NormRhsInd1 = np.sqrt( smamin_fem_ip(Iterrhs, Iterrhs, MSme, MPc, Nv, Npc, dt=np.sqrt(DT)))[0][0] TolCor = 1.0 / np.max([NormRhsInd1, 1]) else: TolCor = 1.0 if inikryupd and tcur == t0: print '\n1st step direct solve to initialize krylov\n' q1_tq2_p_q2_new = spsla.spsolve(IterA, Iterrhs) qqpq_oldold = qqpq_old qqpq_old = np.atleast_2d(q1_tq2_p_q2_new).T TolCor = 0 inikryupd = False # only once !! else: cls = krypy.linsys.\ LinearSystem(IterA, Iterrhs, Ml=MGmr, ip_B=smamin_prec_fem_ip) tstart = time.time() # extrapolating the initial value qqqp_pv = (qqpq_old - qqpq_oldold) q1_tq2_p_q2_new = krypy.linsys.\ RestartedGmres(cls, x0=qqpq_old+qqqp_pv, tol=TolCor*TsP.linatol, maxiter=iniiterfac*TsP.MaxIter, max_restarts=100) qqpq_oldold = qqpq_old qqpq_old = np.atleast_2d(q1_tq2_p_q2_new.xk) tend = time.time() print ('Needed {0} of max {4}*{1} iterations: ' + 'final relres = {2}\n TolCor was {3}').\ format(len(q1_tq2_p_q2_new.resnorms), TsP.MaxIter, q1_tq2_p_q2_new.resnorms[-1], TolCor, iniiterfac) print 'Elapsed time {0}'.format(tend - tstart) iniiterfac = 1 # fac only in the first Krylov Call np.save(cdatstr + '_qqpq', qqpq_old) q1_old = q1facI*qqpq_old[:Nv - Npc, ] q2_old = qqpq_old[-Npc:, ] # Extract the 'actual' velocity and pressure vc = np.zeros((Nv, 1)) vc[~B2BoolInv, ] = q1_old vc[B2BoolInv, ] = q2_old # print np.linalg.norm(vc) pc = PFacI*qqpq_old[Nv:Nv + Npc, ] v, p = expand_vp_dolfunc(PrP, vp=None, vc=vc, pc=pc, pdof=PrP.Pdof) cdatstr = get_dtstr(t=tnext, **dtstrdct) np.save(cdatstr, np.vstack([vc, pc])) # the errors and residuals # ContiRes.append(comp_cont_error(v, FpbcSme, PrP.Q)) TolCorL.append(TolCor) ContiRes.append(0) # troubles with fenics 1.5 try: vCur, pCur = PrP.v, PrP.p vCur.t = tnext pCur.t = tcur VelEr.append(errornorm(vCur, v)) PEr.append(errornorm(pCur, p)) except AttributeError: VelEr.append(0) PEr.append(0) if saveallres: res = IterA*qqpq_old - Iterrhs (mr, mcd, mc) = smamin_prec_fem_ip(res, res, retparts=True) MomRes.append(np.sqrt(mr)[0][0]) DContiRes.append(np.sqrt(mcd)[0][0]) ContiRes[-1] = np.sqrt(mc)[0][0] # print 'Res is dconti: ', np.sqrt(mcd)[0][0] # print 'Res is conti: ', np.sqrt(mc)[0][0] # print 'Res is moment: ', np.sqrt(mr+mc+mcd)[0][0] if i + etap == 1 and TsP.SaveIniVal: from scipy.io import savemat dname = 'IniValSmaMinN%s' % Nv savemat(dname, {'qqpq_old': qqpq_old}) tcur = tnext print '%d of %d time steps completed ' % (etap*Nts/TsP.NOutPutPts, Nts) print 'DEBUG: idx={0}'.format(idx) if TsP.ParaviewOutput: TsP.UpFiles.u_file << v, tcur TsP.UpFiles.p_file << p, tcur TsP.Residuals.VelEr.append(VelEr) TsP.Residuals.PEr.append(PEr) TsP.TolCor.append(TolCorL) TsP.Residuals.ContiRes.append(ContiRes) if saveallres: TsP.Residuals.MomRes.append(MomRes) TsP.Residuals.DContiRes.append(DContiRes) return
def run_mc(w, err, pde): import time from dolfin import norm # create reference mesh and function space projection_basis = get_projection_basis(mesh0, maxh=min(w[Multiindex()].basis.minh / 4, MC_HMAX)) logger.debug("hmin of mi[0] = %s, reference mesh = (%s, %s)", w[Multiindex()].basis.minh, projection_basis.minh, projection_basis.maxh) # get realization of coefficient field err_L2, err_H1 = 0, 0 for i in range(MC_N): logger.info("---- MC Iteration %i/%i ----", i + 1 , MC_N) RV_samples = coeff_field.sample_rvs() logger.debug("-- RV_samples: %s", [RV_samples[j] for j in range(w.max_order)]) t1 = time.time() sample_sol_param = compute_parametric_sample_solution(RV_samples, coeff_field, w, projection_basis) t2 = time.time() sample_sol_direct = compute_direct_sample_solution(pde, RV_samples, coeff_field, A, 2 * w.max_order, projection_basis) t3 = time.time() cerr_L2 = errornorm(sample_sol_param._fefunc, sample_sol_direct._fefunc, "L2") cerr_H1 = errornorm(sample_sol_param._fefunc, sample_sol_direct._fefunc, "H1") logger.debug("-- current error L2 = %s H1 = %s", cerr_L2, cerr_H1) err_L2 += 1.0 / MC_N * cerr_L2 err_H1 += 1.0 / MC_N * cerr_H1 if i + 1 == MC_N: # error function errf = sample_sol_param - sample_sol_direct # deterministic part sample_sol_direct_a0 = compute_direct_sample_solution(pde, RV_samples, coeff_field, A, 0, projection_basis) L2_a0 = errornorm(sample_sol_param._fefunc, sample_sol_direct_a0._fefunc, "L2") H1_a0 = errornorm(sample_sol_param._fefunc, sample_sol_direct_a0._fefunc, "H1") logger.info("-- DETERMINISTIC error L2 = %s H1 = %s", L2_a0, H1_a0) # stochastic part sample_sol_direct_am = sample_sol_direct - sample_sol_direct_a0 # L2_am = errornorm(sample_sol_param._fefunc, sample_sol_direct_am._fefunc, "L2") # H1_am = errornorm(sample_sol_param._fefunc, sample_sol_direct_am._fefunc, "H1") logger.info("-- STOCHASTIC norm L2 = %s H1 = %s", sample_sol_direct_am.norm("L2"), sample_sol_direct_am.norm("H1")) if MC_PLOT: sample_sol_param.plot(title="param") sample_sol_direct.plot(title="direct") errf.plot(title="|param-direct| error") sample_sol_direct_am.plot(title="direct stochastic part") fc = get_coeff_realisation(RV_samples, coeff_field, w.max_order, projection_basis) fc.plot(title="coeff") sol_variance = compute_solution_variance(coeff_field, w, projection_basis) sol_variance.plot(title="sol variance") interactive() #coeff_variance = compute_solution_variance(coeff_field, w0, proj_basis) #sol_variance.plot(title="variance") t4 = time.time() logger.info("TIMING: param: %s, direct %s, error %s", t2 - t1, t3 - t2, t4 - t3) logger.info("MC Error: L2: %s, H1: %s", err_L2, err_H1) err.append((err_L2, err_H1))
def solve_fixed_point( mesh, W_element, P_element, Q_element, u0, p0, theta0, kappa, rho, mu, cp, g, extra_force, heat_source, u_bcs, p_bcs, theta_dirichlet_bcs, theta_neumann_bcs, my_dx, my_ds, max_iter, tol ): # Solve the coupled heat-Stokes equation approximately. Do this # iteratively by solving the heat equation, then solving Stokes with the # updated heat, the heat equation with the updated velocity and so forth # until the change is 'small'. WP = FunctionSpace(mesh, MixedElement([W_element, P_element])) Q = FunctionSpace(mesh, Q_element) # Initialize functions. up0 = Function(WP) u0, p0 = up0.split() theta1 = Function(Q) for _ in range(max_iter): heat_problem = heat.Heat( Q, kappa=kappa, rho=rho(theta0), cp=cp, convection=u0, source=heat_source, dirichlet_bcs=theta_dirichlet_bcs, neumann_bcs=theta_neumann_bcs, my_dx=my_dx, my_ds=my_ds ) theta1.assign(heat_problem.solve_stationary()) # Solve problem for velocity, pressure. f = rho(theta0) * g # coupling if extra_force: f += as_vector((extra_force[0], extra_force[1], 0.0)) # up1 = up0.copy() stokes.stokes_solve( up0, mu, u_bcs, p_bcs, f, my_dx=my_dx, tol=1.0e-10, verbose=False, maxiter=1000 ) # from dolfin import plot # plot(u0) # plot(theta0) theta_diff = errornorm(theta0, theta1) info('||theta - theta0|| = {:e}'.format(theta_diff)) # info('||u - u0|| = {:e}'.format(u_diff)) # info('||p - p0|| = {:e}'.format(p_diff)) # diff = theta_diff + u_diff + p_diff diff = theta_diff info('sum = {:e}'.format(diff)) # # Show the iterates. # plot(theta0, title='theta0') # plot(u0, title='u0') # interactive() # #exit() if diff < tol: break theta0.assign(theta1) # Create a *deep* copy of u0, p0, to be able to deal with them as # actually separate entities. u0, p0 = up0.split(deepcopy=True) return u0, p0, theta0